【问题标题】:How to create array of arrays from all variables in a module如何从模块中的所有变量创建数组数组
【发布时间】:2016-08-12 21:33:27
【问题描述】:

我在一个模块中声明了许多变量,例如

module test

use othermod, only: n

integer, dimension(n) :: var0
real, dimension(n) :: var1
real, dimension(n) :: var2
..... 
real, dimension(n) :: var1000

end module test

然后我有一个用值填充这些变量的子程序。 此时我想创建一个包含在模块测试中声明的所有变量的数组数组,以便我可以轻松地同时复制或打印特定(n)的所有变量,例如维度(n,allvariablesin module test) .例如,我想做一些类似 array(3,:)=array(2,:) 的事情。 因为这段代码是一个非常大的程序的一部分,所以我不能真正修改太多,而是我需要从这个模块中的所有变量创建一个数组数组,而不需要输入所有变量。 如何轻松地将这种更改集成到当前代码中?

【问题讨论】:

  • 创建一个派生类型并将它们存储在那里。或者在那里存储指向这些的指针。 Fortran 中没有数组数组。
  • 我同意@VladimirF。请注意,模块内的每个变量声明都会自动继承save 属性。如果您希望 var0, var1, var2, ..., var1000 数组的不同实例用于 n 的不同值,则必须将变量作为类型组件包含在派生数据类型中。
  • 有数组的结构,但是为什么呢?如果在你的例程和函数中使用 TEST,那么你会让它们都显示在那里。 array(3,:)=array(2,:) 并没有比 var1(:) = var2(:) 节省太多时间。如果 var1 是质量而 var2 是重量,那么它比 massweight(1,:) 是质量和 massweight(2,:) 是重量更容易理解。如果 var1 是 X 轴而 Var2 是 Y 轴,那么 xy(:,:) 作为 2D 数组是有意义的......否则将它们保留为数组可能更有意义?
  • @Holmz 由于模块自动继承save 属性,因此这种方法不是线程安全的,也就是说,您可以在同一代码中创建var0, var1, ..,var1000 的多个实例。
  • @Holmz 我不明白你的意思,根据你的建议,将位置 x 的所有变量复制到位置 y 我必须输入所有变量名称,我可以使用不同的结构分配所有位置 x 到位置 y 的变量。每个数组的长度完全相同。

标签: arrays module fortran fortran90


【解决方案1】:

我敦促您遵循@Vladimir F 的建议,并将您的变量封装在派生数据类型中。您可以使用 associate 构造来调用期望 var0, var1, .., 等的旧代码。最后,我们可以重载类型的名称以在下面的代码中获取 Java 样式构造函数

module type_MyArray

  implicit none
  private

  type, public :: MyArray
     ! type-components
     real, dimension(:), allocatable :: var0, var1, var2
   contains
     ! type-bound procedures
     procedure :: create => create_my_array
     procedure :: destroy => destroy_my_array
  end type MyArray

  interface MyArray
     module procedure my_array_constructor
  end interface MyArray

contains

  pure function my_array_constructor(n) result (return_value)
    ! Dummy arguments
    integer, intent (in) :: n
    type (MyArray)       :: return_value

    call return_value%create(n)

  end function my_array_constructor


  pure subroutine create_my_array(self, n)
    ! Dummy arguments
    class(MyArray), intent(in out) :: self
    integer,        intent(in)     :: n

    allocate( self%var0(n) )
    allocate( self%var1(n) )
    allocate( self%var2(n) )

  end subroutine create_my_array


  pure subroutine destroy_my_array(self)
    ! Dummy arguments
    class(MyArray), intent(in out) :: self

    if (allocated(self%var0)) deallocate( self%var0 )
    if (allocated(self%var1)) deallocate( self%var1 )
    if (allocated(self%var2)) deallocate( self%var2 )

  end subroutine destroy_my_array

end module type_MyArray

program main

  use type_MyArray, only: MyArray
  use old_code,     only: do_something

  implicit none

  type (MyArray) :: foo, bar

  ! Allocate memory
  foo = MyArray(42)
  bar = MyArray(4200)

  associate( var0 => foo%var0, var1 => bar%var1 )

    ! Call old code using var0 and var1
    call do_something(var0, var1)

  end associate

  ! Release memory
  call foo%destroy()
  call bar%destroy()

end program main

【讨论】:

  • 感谢您的解决方案,我对 fortran 不太了解,所以我必须了解这一切是如何工作的。我忘了提到的是我不需要替换旧变量,这些变量将保留在原处,这是否让事情变得更容易。这种新类型只会添加到代码中。那么在数据类型中,我可以同时拥有整数、实数和逻辑?
  • 我建议您复习面向对象的软件设计和良好的 Fortran 实践。您可能会发现以下链接很有用fortran90.org
猜你喜欢
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 2021-12-22
  • 1970-01-01
  • 2023-03-05
  • 2022-07-16
相关资源
最近更新 更多