我有一个使用Fortran中声明类型的数组结构
例如
type t_data
integer :: N
real, allocatable :: x(:)
real, allocatable :: z(:)
real, allocatable :: y(:)
contains
procedure :: copy
procedure :: SWAP
procedure :: copy_element
end type
! constructor
interface t_data
module procedure constructor
end interface
contains
subroutine copy(this, old)
class(t_data), intent(inout) :: this
type(t_data), intent(in) :: old
do i = 1, old% N
this% x(i) = old% x(i)
etc ..
end do
end subroutine
subroutine copy(this, old)
class(t_data), intent(inout) :: this
type(t_data), intent(in) :: old
do i = 1, old% N
this% x(i) = old% x(i)
etc ..
end do
end subroutine
function constructor(size_)
integer, intent(in) :: size_
type(t_data), :: constructor
allocate(constructor% x(size_))
allocate(constructor% y(size_) )
! etc
end function
subroutine swap(this, from, i1,i2)
class(t_particle_data), intent(inout) :: this
type(t_particle_data), intent(in) :: from
integer, intent(in) :: i1, i2
this% x(i1) = from% x(i2)
! etc
end subroutine
这些是一组过程示例,这些过程需要对声明类型t_data
的所有数组执行相同的操作。我的问题是如何使其更易于维护以解决这种情况,例如,当我们稍后想要向声明的类型添加新组件时。 目前,当我向t_data
添加新数组时,我需要遍历所有这些过程、构造函数、解构函数并添加组件。
我问是否有办法使这更容易。
我的申请
请注意,这些数据类型用于粒子模拟。最初,我分配了大量t_data。但是,在以后的模拟过程中,我可能需要更多粒子。因此,我分配了一个具有更多内存的新t_data,并将旧t_data
复制到其旧大小。
subroutine NEW_ALLOC(new, old)
type(t_data), intent(out) :: new
type(t_data), intent(inout) :: old
nsize = old% N * 2 ! allocate twice the old size
new = T_DATA(nsize)
call new% copy(old)
!DEALLCOte OLD
end subroutine
有没有人/是否有可能以更聪明的方式做到这一点。我不介意将其与C/C++混合?
我的问题是,当我们稍后想要向声明的类型添加新组件时,如何使其更易于维护以解决这种情况。
以下是我将如何处理这种情况,以及有多少Fortran程序员已经解决了这种情况。 我认为没有迫切需要一个包含 3 个坐标数组的派生类型,并且以这种方式解决问题确实需要向问题添加另一个维度需要修改代码,例如添加一个成员数组real, allocatable :: w(:)
t_data
并重新编码对该类型操作的所有类型绑定过程。
因此,放弃这种方法,转而支持
TYPE t_data
REAL, DIMENSION(:,:), ALLOCATABLE :: elements
END TYPE t_data
让我们有几个实例来展示
TYPE(t_data) :: t1 ,t2, t3
我们可以通过这种方式分配其中任何一个elements
成员
ALLOCATE(t1%elements(3,10))
这很容易
ALLOCATE(t1%elements(6,100))
或任何你想要的。 与原始派生类型设计相比,这具有优势,即可以在运行时确定elements
的尺寸。 这也使得每个坐标数组很难有不同的长度。
现在,复制t1
就像
t2 = t1
现代Fortran甚至负责自动分配t2
elements
。 所以我认为没有必要定义复制整个t_data
实例的程序。 至于交换数据,切片和切块,这很简单
t2%elements(1,:) = t1%elements(2,:)
甚至
t2%elements(1,:) = t1%elements(1,6:1:-1)
或
t2%elements(1,:) = t1%elements(1,[1,3,5,2,4,6])
如何将它们包装成swap
例程应该是显而易见的。 但如果没有,请问另一个问题。
接下来,关于需要在执行期间为元素分配更多空间的问题。 首先是一个临时数组
REAL, DIMENSION(:,:), ALLOCATABLE :: temp
然后像这样的小代码,使elements
的大小翻倍。
ALLOCATE(temp(3,2*n))
temp(:,1:n) = t2%elements(:,1:n)
CALL MOVE_ALLOC(to=t2%elements,from=temp)
同样,您可能希望将其包装到一个过程中,如果您需要帮助,请要求它。
最后,这一切的教训不是分享我将如何对问题进行编程,而是分享在Fortran中编程的想法。