Fortran:变量自己改变



我有一个变量被覆盖的问题,我不知道什么原因。我在下面发布了一段代码,以便您可以了解如何声明事物。变量strain,Qi,Qf,Qd,tel, Gc传入子程序,用于计算ssgrad,strn0,strss0。

我的问题是tel和Gc被传递到子例程OK中,但由于某种原因在这段代码中改变了值。

使用print语句,我发现问题首先发生在第二个do循环中。当我将strss0设置为0时,Gc和tel的值从等于1变为看似随机的数字:tel=11.52822 Gc=-8.789086(仅为示例所示)

每次运行代码时,它们都被设置为相同的值。

只是让你知道,这个子程序与一个商业有限元程序包接口。

提前感谢您对我的帮助

subroutine initcalcs(strain,Qi,Qf,Qd,tel,Gc,ssgrad,strn0,strss0)
  implicit none
  integer :: i,j
  real*8:: nstrn0,nstrs0,strn0,strnf,varsq,normvar,lmbda0,lmbdaf,
 # ssgrad,t0,tt,tel,nstrnf,nstrsf,Gc
  real*8, dimension(3) :: strain,stran0,stranf,strss0,strssf,var
  real*8, dimension(3,3) :: Qd,Qi,Qf

  lmbda0=1.0d0                                                                                          

  nstrn0=0.0d0                                                                             
  do i=1,3
        stran0(i)=0.0d0
        stran0(i)=strain(i)*lmbda0                                                         
        nstrn0=nstrn0+stran0(i)**2                                                         
  end do                                                                                    
  nstrn0=dsqrt(nstrn0)                                                                     

  do i=1,3
        strss0(i)=0.0d0 
  end do

在Fortran中,有两个常见的内存值损坏原因。一种是下标错误,即使用不正确的下标值赋值给数组元素。这将写入数组之外的内存位置。另一个是过程(子例程或函数)调用中的参数与过程的虚拟参数之间的不一致。两者都可能导致问题出现在与实际原因不同的源代码位置。建议:检查代码是否存在这些问题。打开编译器的严格警告和错误检查选项。使用Fortran>=90和模块使Fortran能够更好地自动发现参数一致性问题。您可以使用调试器监视内存位置,并查看它是如何修改的。

我同意m.s.b的观点:打开严格的警告和错误检查,并验证子例程调用传递的参数与子例程期望的类型和形状(数组尺寸)相同。

变量声明语法中的冒号暗示这是Fortran90或更高版本。如果是这种情况,我强烈建议使用INTENT修饰符来指定参数是否打算为只读。

例如,我们假设传递给这个例程的参数中,strainQiQfQdtelGc为只读输入,返回的参数为ssgradstrn0strss0;也就是说,无论它们的值是什么,都会被这个例程覆盖。

参数的变量声明将改为:

real*8, dimension(3), intent(in) :: strain
real*8, dimension(3,3), intent(in) :: Qi, Qf, Qd
real*8, intent(in) :: tel, Gc
real*8, intent(out) :: strn0, ssgrad 
real*8, dimension(3), intent(out) :: strss0

INTENT关键字是Fortran 90增加的,它允许用户指定哪些参数是只读的(INTENT(IN)),初始化但可以在例程(INTENT(INOUT))中修改,哪些参数被视为未初始化并将在例程(INTENT(OUT))中设置。

如果未指定INTENT,则默认为INOUT,这与FORTRAN 77一致(注意,未指定INTENT(INOUT)INTENT之间存在细微差异,但在本例中不相关)。

如果一个例程试图给一个声明为INTENT(IN)的变量赋值,一个好的编译器会抛出一个错误,如果一个声明为INTENT(OUT)的变量没有被赋值,它至少会抛出一个警告。

如果可能,在所有应该是只读的变量上设置INTENT(IN)。这可能是不可能的,这取决于如何将这些变量传递给其他例程。如果在这个例程中调用的例程的参数中没有指定INTENT,它将默认为INOUT。如果将INTENT(IN)变量作为INTENT(INOUT)参数传递,编译器将抛出错误。如果这种情况发生在您控制的代码中,则必须在许多例程中指定INTENT。这可能是可取的,也可能是不可取的,这取决于你是想一般地改进你的代码,还是只是快速地修复这个问题。

我假设这些变量中的一些被传递给有限元包中的外部例程,我猜这是链接到你的代码而不是编译;我不确定在这种情况下如何处理编译时意图检查。

相关内容

  • 没有找到相关文章

最新更新