如何在Fortran 200x中为多态数量实现重载运算符

时间:2015-08-04 09:21:53

标签: oop fortran polymorphism operator-overloading derived-class

我正在尝试在我的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)) 。但是,有没有办法做到这一点?

非常感谢,我们非常感谢任何建议!

0 个答案:

没有答案