如何在抽象接口块中为延迟绑定指定函数接口作为类型绑定过程?

How are function interfaces specified in abstract interface blocks for deferred binding as a type bound procedure?

我想声明一个抽象类型 abstract_tensor 并指定每个扩展 abstract_tensor 的类型都必须实现的一些过程(包括它们的接口)。

举个例子,假设我希望扩展 abstract_tensor 的每个类型都有一个类型绑定过程 sph,return 是具体类型的一个实例,并且是一个 函数,不是子程序。

这是该情况的非编译实现:

module tensors

  implicit none

  private
  public :: sym_tensor

  type, abstract :: abstract_tensor
   contains
     procedure(tr_interface), deferred :: tr
     procedure(sph_interface), deferred :: sph
  end type abstract_tensor

  abstract interface
     !! intrinsic return type works
     function tr_interface(self)
       import :: abstract_tensor
       class(abstract_tensor), intent(in) :: self
       real :: tr_interface
     end function tr_interface
     !! abstract return type not - how do I define the return type correctly here?
     function sph_interface(self)
       import :: abstract_tensor
       class(abstract_tensor), intent(in) :: self
       class(abstract_tensor) :: sph_interface
     end function sph_interface
  end interface

  type, extends(abstract_tensor) :: sym_tensor
     real :: xx = 0.0
     real :: yy = 0.0
     real :: zz = 0.0
     real :: xy = 0.0
     real :: yz = 0.0
     real :: xz = 0.0
   contains
     procedure :: tr => trace
     procedure :: sph => spherical_part
  end type sym_tensor

contains

  real function trace(self)
    class(sym_tensor), intent(in) :: self
    trace = self%xx + self%yy + self%zz
  end function trace

  type(sym_tensor) function spherical_part(self)
    class(sym_tensor), intent(in) :: self
    real :: tr
    tr = 1.0/3.0*self%tr()
    spherical_part = sym_tensor(tr, tr, tr, 0.0, 0.0, 0.0)
  end function spherical_part

end module tensors

program main

  use tensors, only: sym_tensor

  implicit none

  type(sym_tensor) :: t

end program main

此处,sym_tensor 扩展了 abstract_tensor 并且类型绑定过程 trsph 计算了它的迹线和流体静力学部分。 tr的return类型应该是realsph的return类型应该是另一个sym_tensor.

如何在 abstract interface 块中定义 sph_interface 的 return 类型,以便编译并强制每个扩展抽象类型的类型实现这样的功能?

在 Fortran 中,所有抽象多态变量 must be 之一:

  • 虚拟变量
  • 指针
  • 可分配

你的抽象函数

function sph_interface(self)
  import :: abstract_tensor
  class(abstract_tensor), intent(in) :: self
  class(abstract_tensor) :: sph_interface
end function sph_interface

return是class(abstract_tensor)的一个变量,是一个抽象的多态变量,不是上面的一个。

最简单的更改是使 return 类型 allocatable:

function sph_interface(self)
  import :: abstract_tensor
  class(abstract_tensor), intent(in) :: self
  class(abstract_tensor), allocatable :: sph_interface
end function sph_interface

然后 sym_tensor 实现需要有匹配的签名:

function spherical_part(self)
  class(sym_tensor), intent(in) :: self
  class(abstract_tensor), allocatable :: spherical_part
  real :: tr
  tr = 1.0/3.0*self%tr()
  spherical_part = sym_tensor(tr, tr, tr, 0.0, 0.0, 0.0)
end function spherical_part

这会编译,但很可能会导致段错误,因为编译器不喜欢多态赋值

spherical_part = sym_tensor(tr, tr, tr, 0.0, 0.0, 0.0)

您可以通过将简单赋值替换为源分配来解决此问题,

allocate(spherical_part, source=sym_tensor(tr, tr, tr, 0.0, 0.0, 0.0))

由于 Fortran 标准的限制或编译器的限制,我不确定是否需要源分配。