Fortran:变量自行变化

Fortran:变量自行变化,fortran,fortran77,Fortran,Fortran77,我不知道是什么原因导致变量被重写。我在下面发布了一段代码,这样您就可以看到事情是如何声明的。变量应变、Qi、Qf、Qd、tel和Gc被传递到子程序中,并用于计算ssgrad、strn0、strss0 我的问题是tel和Gc被传递到子例程OK中,但由于某种原因,它们在这段代码中更改了值 使用print语句,我发现问题首先出现在第二个do循环中。当我将strss0设置为0时,Gc和tel的值都从等于1变为看似随机的数字:tel=11.52822 Gc=-8.789086(仅为示例而显示) 但每次我运

我不知道是什么原因导致变量被重写。我在下面发布了一段代码,这样您就可以看到事情是如何声明的。变量应变、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能够更好地自动发现参数一致性问题。您可以使用调试器监视内存位置,并查看它修改了什么。

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

我同意M.S.B.:启用严格警告和错误检查,并验证子例程调用传递的参数与子例程预期的类型和形状(数组尺寸)相同

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

例如,假设传递到此例程的参数中,
strain
Qi
Qf
Qd
tel
Gc
是只读输入,参数是
ssgrad
strn0
,并且
strsss0
作为输出返回;也就是说,它们拥有的任何值都会被该例程覆盖

参数的变量声明将更改为:

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
。这可能是可取的,也可能是不可取的,这取决于您是希望总体上改进代码,还是希望快速解决这一问题


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

我同意m.S.B.:启用严格警告和错误检查,并验证子例程调用传递的参数与子例程预期的类型和形状(数组维度)相同

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

例如,我们假设传递到此例程的参数中,
strain
Qi
Qf
Qd
tel
Gc
为只读输入,参数为
ssgrad
strn0
,而
strsss0
为只读输入