Fortran中数组赋值的不同形状

时间:2016-04-24 00:51:02

标签: fortran gfortran

这是我的代码:

Program Arrays

Implicit none

Integer::i,j
Integer,dimension(2)::V_Max
Complex,dimension(0:7,3)::V_cvo
Complex,dimension(7,3)::V_cvo_temp


Do concurrent(i=0:7,j=1:3)

   V_cvo(i,j)=cmplx(i+j,2*i-j)

End Do

V_cvo_temp=V_cvo(1:,:)
V_Min=minloc(abs((/((V_cvo_temp(i,j),j=1,3),i=2,5)/)))

Stop
End Program Arrays

编译后我收到了这条消息:

Error: Different shape for array assignment  on dimension 1 (2 and 1)|

这里有什么问题?如果我想在该数组的特定扇区中的某个数组中找到最小元素的位置,那么它是如何可能的?

这可能是问题的可能解决方案之一:

Program Arrays

Implicit none

Integer::i,j
Integer,dimension(2)::V_Max
Complex,dimension(0:7,2)::V_cvo
Logical,dimension(0:7,2) :: lmask = .FALSE.

forall(i=2:5,j=1:2)lmask(i,j) = .TRUE.

Do concurrent(i=0:7,j=1:2)

   V_cvo(i,j)=cmplx(i+j,2*i-j)

End Do

V_Max = Maxloc(abs(V_cvo),mask=lmask)-(/1,0/)

Open(1,File='Output.txt',Status='Unknown')

Write(1,'(2x,i0,2x,i0)') V_max
Write(1,*)

Do concurrent(i=2:5,j=1:2)

   Write(1,'(1x,i0,1x,i0,2x,f7.4)')i,j,abs(V_cvo(i,j))

End Do

Close(1)

Stop
End Program Arrays

输出文件是:

 5  1

 2 1   4.2426
 3 1   6.4031
 4 1   8.6023
 5 1  10.8167
 2 2   4.4721
 3 2   6.4031
 4 2   8.4853
 5 2  10.6301

对此的看法?

3 个答案:

答案 0 :(得分:3)

此表达式

minloc(abs((/((V_cvo_temp(i,j),j=1,3),i=2,5)/)))

返回包含1个元素的rank-1数组。赋值的 lhs 是具有2个元素的rank-1数组。 Fortran不会分配不兼容的数组 - 因此编译错误消息。

(@ gdlmx'答案在诊断中是错误的,如果表达式返回标量,Fortran会愉快地将其值广播到数组的每个元素。)

如果表达式确实返回标量,它仍然不会返回V_cvo部分中最小元素的位置。子表达式

(/((V_cvo_temp(i,j),j=1,3),i=2,5)/)

生成一个包含指定元素V_cvo_temp的rank-1数组,它基本上将数组变平为一个向量并沿途丢失它们的位置。这就是为什么第一个表达式返回带有1个元素的rank-1数组的原因 - 它是rank-1数组中元素的位置。

此解决方案的问题

V_Min=minloc(abs(V_cvo(2:5,1:3)))

表达式abs(V_cvo(2:5,1:3))将返回索引的(临时)数组,因为默认情况下Fortran数组在每个等级上为1。当我尝试代码时,它会返回位于所考虑部分之外的位置(1,1)。这是临时数组的最小元素的位置。

'聪明的问题'我尝试过的解决方案是abs(V_cvo(2:5,1:3))总是返回,即使从视图中隐藏,每个等级从1开始索引的临时数组。 minloc或类似函数的任何应用都使用这些索引,而不是v_cvo使用的索引。最好的解决方案可能是制作一个显式的临时数组(适当声明),如下所示:

allocate(abstemp(LBOUND(v_cvo,1):UBOUND(v_cvo,1),LBOUND(v_cvo,2):UBOUND(v_cvo,2)))

然后

v_min = minloc(abstemp(2:5,1:3))

deallocate(abstemp)

答案 1 :(得分:1)

似乎是

的右侧
//component/@id[string()]

返回标量而不是2个组件的向量。您需要的是sphere packing problem//component/@id[normalize-space()]

V_Min=minloc(abs((/((V_cvo_temp(i,j),j=1,3),i=2,5)/)))

或更简单

V_cvo_temp(1:3,2:5)

此外,您最后还不需要V_Min=minloc(abs(V_cvo_temp(2:5,1:3)))

EDIT1:

V_Min=minloc(abs(V_cvo(2:5,1:3))) ! without temp array 返回相对于(1,1)的索引。要了解此行为,请尝试以下示例:

stop

输出:

minloc

因此,如果将子数组传递给minloc,则需要添加基本索引以获得正确的'答案。

答案 2 :(得分:0)

此解决方案也可以正常工作(最好的):

forall(i=1:7,j=1:3) V_cvo_temp(i,j)=abs(V_cvo(i,j))
V_Min = MINLOC(V_cvo_temp(m:n,:))+(/m-1,0/)

对于每个m和n,如果它们在这种情况下的区间1:7或其他某个区间内,则代码是正确的。