我正在尝试在我的Fortran代码中实现一些高级字段处理。我的斗争是执行速度,但与此同时我想利用现代Fortran范例允许的所有最佳功能。
我基本上有一个抽象的基类型,可以扩展为多种类型:
module fields
use domains, only: domain_type => domain
implicit none
private
type, abstract, public :: field
character(12) :: name
character(256) :: description
integer :: tag
type(domain_type), pointer :: domain => null()
contains
! Some deferred type-bound procedures
procedure(init_proc), deferred :: field_init
! ...
! Some deferred overloaded operators
procedure(assign_proc), private, deferred :: field_assign
generic :: assignment(=) => field_assign
! ...
end type field
! ...
end module fields
我的子类型在其他源文件中实现:
module cell_scalar_fields
use fields
implicit none
private
type, public, extends(field) :: cell_scalar_field
! Field variable
real(8), allocatable :: var(:)
! ... other contents ...
contains
! list of procedures
end type cell_scalar_field
contains
! ... procedures
end module cell_scalar_fields
和
module cell_vector_fields
use fields
implicit none
private
type, public, extends(field) :: cell_vector_field
! Field variable
type(vector3d), allocatable :: var(:)
! ... other contents ...
contains
! list of procedures
end type cell_vector_field
contains
! ... procedures
end module cell_vector_fields
我现在正在尝试实现与赋值,乘积,和,除法相对应的重载运算,包括子类型(scalar_field / scalar_field,scalar_field / vector_field,vector_field / vector_field)和带标量常量的运算。
从实现中可以看出,操作几乎不对应于快速数组乘法/求和运算,还有一些需要在字段类型上进行的其他信息。
尝试遵守现代Fortran标准,我为每个操作做了类似的事情:
subroutine cell_scalar_field_assignment(this,that)
class(cell_scalar_field) , intent(inout) :: this
class(field) , intent(in) :: that
! Local variables
class(field) , pointer :: infield
integer :: ncells,domainid
select type (infield => that)
type is (scalar_cell_field)
if (.not.this%allocated()) then
ncells = size(infield%var)
allocate(this%var(ncells))
! ...
this%name = infield%name
this%descr = infield%descr
this%tag = infield%tag
domainid = infield%domain%id
this%domain => domains(domainid)
endif
this%var=infield%var
this%revar=infield%revar
class default
write(*,*) this_module,' Method to assign field <',infield%type_name(),'> to <',this%type_name(),'> not yet implemented.'
stop
end select
end subroutine cell_scalar_field_assignment
然而,这种方法存在问题:
intent(inout)
来避免它了,也许是gfortran允许这个?),我担心的是一切在计算诸如y = a*(x+z) - (B.dot.C)
等表达式时会非常慢:使用普通数组,这将通过类似于y = a*(x+z) - (dot_product(B,C))
的更简单且极快的表达式来解决。
我认为解决方案是,如果我可以克服字段分配问题,并以某种方式直接直接使用每个字段类型中的%var
内容,而无需在%var
中的任何地方指定y%var = a*(x%var+z%var) - (dot_product(B%var,C%var))
。但是,有没有办法做到这一点?非常感谢,我们非常感谢任何建议!