gfortran 运算符重载派生类型和 real()

gfortran operator overloading derived type and real()

我想重载运算符 (*) 以在以下 class 中执行向量标量乘法:

  module vectorField_mod
    use constants_mod
    implicit none
    private

    public :: vectorField
    public :: allocateVectorField
    public :: delete

    type vectorField
      real(dpn),dimension(:,:,:),allocatable :: x,y,z
    end type

  interface operator (*)
    module procedure scalarMultiply
  end interface

  contains

    function scalarMultiply(f,g) result(q)
      implicit none
      type(vectorField),intent(in) :: f
      real(dpn),intent(in) :: g
      type(vectorField) :: q
      q%x = f%x * g
      q%y = f%y * g
      q%z = f%z * g
      q%sx = f%sx; q%sy = f%sy; q%sz = f%sz
    end function
    ...

  end module

但我收到以下错误:

  Error: Operands of binary numeric operator '*' at (1) are REAL(8)/TYPE(vectorfield)

我正在尝试像这样实现:

 type(vectorField) :: a
 real(8) :: dt = 0.001

 call allocateVectorField(a,..)
 a = a*dt

这不是二元运算吗?还有办法做到这一点吗?非常感谢任何帮助!

总结:

1) @francescalus 的回答是必要的,但不足以产生成功的编译。

2) 另外,事实证明乘法的顺序很重要。即 a = adt 有效,但 a = dta 无效(这是我遇到的问题)

这是一个示例:

  module constants_mod
    integer,parameter :: dpn = selected_real_kind(14)
  end module

  module vectorField_mod
    use constants_mod
    implicit none
    private

    public :: vectorField
    public :: allocateX,allocateY,allocateZ
    public :: delete
    public :: operator(*)

    type vectorField
      integer,dimension(3) :: sx,sy,sz
      real(dpn),dimension(:,:,:),allocatable :: x,y,z
    end type

  interface delete
    module procedure deallocateVectorField
  end interface

  interface operator (*)
    module procedure scalarMultiply
  end interface

  contains

    function scalarMultiply(f,g) result(q)
      implicit none
      type(vectorField),intent(in) :: f
      real(dpn),intent(in) :: g
      type(vectorField) :: q
      q%x = f%x * g; q%y = f%y * g; q%z = f%z * g
      q%sx = f%sx; q%sy = f%sy; q%sz = f%sz
    end function

    subroutine allocateX(field,Nx,Ny,Nz)
      implicit none
      type(vectorField),intent(inout) :: field
      integer,intent(in) :: Nx,Ny,Nz
      if (allocated(field%x)) deallocate(field%x)
      allocate(field%x(Nx,Ny,Nz))
      field%sx = shape(field%x)
    end subroutine

    subroutine allocateY(field,Nx,Ny,Nz)
      implicit none
      type(vectorField),intent(inout) :: field
      integer,intent(in) :: Nx,Ny,Nz
      if (allocated(field%y)) deallocate(field%y)
      allocate(field%y(Nx,Ny,Nz))
      field%sy = shape(field%y)
    end subroutine

    subroutine allocateZ(field,Nx,Ny,Nz)
      implicit none
      type(vectorField),intent(inout) :: field
      integer,intent(in) :: Nx,Ny,Nz
      if (allocated(field%z)) deallocate(field%z)
      allocate(field%z(Nx,Ny,Nz))
      field%sz = shape(field%z)
    end subroutine

    subroutine deallocateVectorField(field)
      implicit none
      type(vectorField),intent(inout) :: field
      deallocate(field%x,field%y,field%z)
      field%sx = 0; field%sy = 0; field%sz = 0
    end subroutine

  end module

  program test
  use constants_mod
  use vectorField_mod
  implicit none
  type(vectorField) :: a,b
  integer :: N = 1
  real(dpn) :: dt = 0.1
  call allocateX(a,N,N,N)
  call allocateY(a,N,N,N)
  call allocateZ(a,N,N,N)

  call allocateX(b,N,N,N)
  call allocateY(b,N,N,N)
  call allocateZ(b,N,N,N)
  a%x = dble(1.0); a%y = dble(1.0); a%z = dble(1.0)
  b%x = dble(1.0); b%y = dble(1.0); b%z = dble(1.0)
  a = b
  a = a*dt ! compiles fine
  a = dt*a ! does not compile

  call delete(a)
  call delete(b)

  end program

模块的默认可访问性是private。此默认值也适用于定义的运算符。

要使运算符标识符 public(以便它可以在模块外使用),请使用 public 语句,例如:

public :: operator(*)