Warning: file_get_contents(/data/phpspider/zhask/data//catemap/5/fortran/2.json): failed to open stream: No such file or directory in /data/phpspider/zhask/libs/function.php on line 167

Warning: Invalid argument supplied for foreach() in /data/phpspider/zhask/libs/tag.function.php on line 1116

Notice: Undefined index: in /data/phpspider/zhask/libs/function.php on line 180

Warning: array_chunk() expects parameter 1 to be array, null given in /data/phpspider/zhask/libs/function.php on line 181
在Fortran 90中传递参数的智能方法_Fortran_Argument Passing_Subroutine_Fortran90 - Fatal编程技术网

在Fortran 90中传递参数的智能方法

在Fortran 90中传递参数的智能方法,fortran,argument-passing,subroutine,fortran90,Fortran,Argument Passing,Subroutine,Fortran90,我是一个Fortran新手。我试图编写一个子程序,从主程序中获取四个参数,然后向主程序输出一个数组,其中包含最初传入的四个参数。做这件事的好方法/聪明方法是什么 例如,在下面的测试程序中,我在主程序中创建了四个实变量(a,b,c,和d)。然后我将这些实变量传递给一个名为mysub的子例程。我希望mysub能够接收a、b、c和d,使用它们填充一个名为o的2乘2数组,然后将o发送到主程序,以便在那里显示(以及可能的修改)。因此,我尝试了以下方法: SUBROUTINE mysub(w,x,y,z)

我是一个Fortran新手。我试图编写一个子程序,从主程序中获取四个参数,然后向主程序输出一个数组,其中包含最初传入的四个参数。做这件事的好方法/聪明方法是什么

例如,在下面的测试程序中,我在主程序中创建了四个实变量(
a
b
c
,和
d
)。然后我将这些实变量传递给一个名为
mysub
的子例程。我希望
mysub
能够接收
a
b
c
d
,使用它们填充一个名为
o
的2乘2数组,然后将
o
发送到主程序,以便在那里显示(以及可能的修改)。因此,我尝试了以下方法:

SUBROUTINE mysub(w,x,y,z)
  IMPLICIT NONE
  REAL, INTENT(IN) :: w, x, y, z
  REAL, DIMENSION(:,:), ALLOCATABLE, INTENT(OUT) :: o

  ALLOCATE(o(2,2))
  o(1,1)=w
  o(1,2)=x
  o(2,1)=y
  o(2,2)=z
END SUBROUTINE mysub
END MODULE testsubs

PROGRAM test
  USE testsubs
  IMPLICIT NONE
  REAL :: a=1.1, b=2.2, c=3.3, d=4.4

  CALL mysub(a, b, c, d)

  PRINT *, o(1,1), o(1,2)
  PRINT *, o(2,1), o(2,2)
END PROGRAM test
但是,我得到了以下错误:

test.f90:10.53:

  REAL, DIMENSION(:,:), ALLOCATABLE, INTENT(OUT) :: o
                                                     1
Error: Symbol at (1) is not a DUMMY variable
我将其解释为,编译器不知道
o
是什么,因为
o
不在子程序头的参数列表中:
子程序mysub(w,x,y,z)
。所以我可能需要在标题中包含
o
。因此,我下一步尝试以下操作(我使用
!…
表示更改或添加):

这似乎很好,我得到了正确的输出:

   1.1000000       2.2000000
   3.3000000       4.4000001

但是,我的问题是,这是一个好方法吗?在这个工作示例中,我在子程序和主程序中声明数组
o
。这似乎可能令人困惑,因为我认为这意味着我需要注意子程序或主程序分配
o
(但我认为不是两者都分配,以避免错误消息)。有没有更聪明的方法可以做到这一点——从子程序向主程序发送数组?谢谢您的时间。

如果您想返回数组,您可以a)使用
INTENT(OUT)
将其添加到参数中,就像您的示例一样#2在子节点内分配,或者b)创建函数并在外部分配数组:

FUNCTION myfun(w,x,y,z,n,m)
IMPLICIT NONE
INTEGER, INTENT(IN) :: n,m
REAL, DIMENSION(n,m) :: myfun
REAL, INTENT(IN) :: w,x,y,z

  myfun(1,1)=w
  myfun(1,2)=x
  myfun(2,1)=y
  myfun(2,2)=z

END FUNCTION
END MODULE testsubs

PROGRAM test
  USE testsubs
  IMPLICIT NONE
  REAL :: a=1.1, b=2.2, c=3.3, d=4.4
  REAL, DIMENSION(:,:), ALLOCATABLE :: o !...

  ALLOCATE(o(2,2))
  o  = myfun(a,b,c,d,2,2)

  PRINT *, o(1,1), o(1,2)
  PRINT *, o(2,1), o(2,2)
  DEALLOCATE(o) !...
END PROGRAM test
事实上,我认为你的解决方案更干净。

你的解决方案,把“o”作为意图(out)论点就可以了。如果没有“o”作为参数,则子程序中的变量“o”与主程序中的变量“o”之间没有连接,因此主程序中的变量“o”没有声明或分配。还有另一个解决方案(除了@ja72提供的解决方案外)是修改您的方法:将“o”作为子例程的intent(inout)参数,并在主程序中分配它。可能的优势:allocate和deallocate在代码中更接近,而且是成对的。可能的缺点:根据程序逻辑和设计的不同,子例程可能最了解阵列尺寸


另外,如果您在主程序中分配数组,并且在子例程中没有实际使用数组的可分配属性(即,您没有分配或取消分配它),那么您就不必在子例程中用可分配属性声明它——这是一个有用的简化。在这种情况下,“意图(输出)”可能是合适的。但是,如果在主程序中分配数组,并希望将该状态传递给子例程,则参数状态不能为“intent(out)”。“intent(out)”在进入过程时自动解除分配参数。

您的问题不清楚您是否事先知道数组的大小,但如果您知道,通常最好在同一位置分配和解除分配数组,或者更好的方法是让编译器在可能的情况下分配内存

我会怎么做:

  • 如果大小在编译时已知: 在主程序中声明数组,在子例程中使用
    intent(out)

  • 如果仅在运行时才知道大小: 在主程序中分配,在子程序中使用
    intent(out)
    ,在主程序中取消分配


函数最适合于小输出,因为需要复制输出。

子例程中参数的顺序是否必须与伪参数传递的顺序相匹配?示例:真实,意图(IN)::z,y,x,w是否可接受?
FUNCTION myfun(w,x,y,z,n,m)
IMPLICIT NONE
INTEGER, INTENT(IN) :: n,m
REAL, DIMENSION(n,m) :: myfun
REAL, INTENT(IN) :: w,x,y,z

  myfun(1,1)=w
  myfun(1,2)=x
  myfun(2,1)=y
  myfun(2,2)=z

END FUNCTION
END MODULE testsubs

PROGRAM test
  USE testsubs
  IMPLICIT NONE
  REAL :: a=1.1, b=2.2, c=3.3, d=4.4
  REAL, DIMENSION(:,:), ALLOCATABLE :: o !...

  ALLOCATE(o(2,2))
  o  = myfun(a,b,c,d,2,2)

  PRINT *, o(1,1), o(1,2)
  PRINT *, o(2,1), o(2,2)
  DEALLOCATE(o) !...
END PROGRAM test