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

时间:2015-01-27 01:50:23

标签: fortran operator-overloading gfortran

我想重载一个运算符(*)来执行以下类中的向量标量乘法:

  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 = a dt有效,但a = dt a不起作用(这是我遇到的问题)

这是一个说明性的样本:

  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

1 个答案:

答案 0 :(得分:1)

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

要使操作员标识符公开(以便可以在模块外部使用),请使用public语句,如:

public :: operator(*)