在 Fortran 中泛化特定声明类型的操作



我有一个使用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甚至负责自动分配t2elements。 所以我认为没有必要定义复制整个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编程的想法。

相关内容

  • 没有找到相关文章

最新更新