c++ - 在 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
。我的问题是如何使它更易于维护以解决例如我们稍后想要将新组件添加到声明的类型时的情况。目前,当我向 my 添加一个新数组时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 个坐标数组的派生类型的迫切需要,并且像 OP 所担心的那样,以这种方式解决问题需要向问题添加另一个维度需要代码修改,例如添加一个成员数组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 甚至负责自动分配elements
. t2
所以我认为不需要定义复制整个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中编程的想法。
推荐阅读
- r - 是否有一个 R 函数可以找到任意模型的参数?
- jenkins - Jenkins Email-Ext 插件不再附加文件
- reactjs - 如何在 ag-grid-react 中禁用或删除输入搜索过滤器?
- facebook-graph-api - 在 Graph Facebook API 中,如何在给定用户电子邮件的情况下获取用户 ID?
- python - 给定转换矩阵,有效地将转换应用于状态矩阵
- ravendb - 如何在 Ravendb 中更新数组中的值?我需要使用查询
- macos - 没有键盘快捷键的 NSMenuItem 替代项
- discord - 当一条消息中说出两个不同的词时,我的不和谐机器人是否会做出响应?
- sql-server - 将 Microsoft Access 数据库迁移到 SQL Server 2014
- xcode - 如何将 2x2x2 的 NDC 的 MVP 矩阵转换为 2x2x1 立方体(金属)的 NDC 的 MVP 矩阵?