Fortran:变量自行变化
我不知道是什么原因导致变量被重写。我在下面发布了一段代码,这样您就可以看到事情是如何声明的。变量应变、Qi、Qf、Qd、tel和Gc被传递到子程序中,并用于计算ssgrad、strn0、strss0 我的问题是tel和Gc被传递到子例程OK中,但由于某种原因,它们在这段代码中更改了值 使用print语句,我发现问题首先出现在第二个do循环中。当我将strss0设置为0时,Gc和tel的值都从等于1变为看似随机的数字:tel=11.52822 Gc=-8.789086(仅为示例而显示) 但每次我运行代码时,它们都被设置为相同的值 只是想让您知道,这个子程序与一个商业有限元软件包接口 在此,非常感谢您的帮助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(仅为示例而显示) 但每次我运
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
为只读输入