【问题标题】:Fortran: Variables changing on their ownFortran:变量自行更改
【发布时间】:2013-06-12 19:17:14
【问题描述】:

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

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

使用打印语句,我发现问题首先出现在第二个 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

【问题讨论】:

  • 您是否尝试将它们声明为intent(in) 变量?

标签: fortran fortran77


【解决方案1】:

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

【讨论】:

    【解决方案2】:

    我同意 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。这可能是可取的,也可能不是可取的,具体取决于您是想总体改进代码还是快速解决这个问题。

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

    【讨论】:

      猜你喜欢
      • 1970-01-01
      • 2016-05-07
      • 1970-01-01
      • 1970-01-01
      • 2012-07-28
      • 1970-01-01
      • 2019-03-13
      • 1970-01-01
      • 1970-01-01
      相关资源
      最近更新 更多