Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

Overloading the equals operator in Fortran

Is there a way to overload the = operator so that you can write an assignment like in this example:

  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 vectorAssign
  ! end interface

  contains

    ! function vectorAssign(f) result(q)
    !   implicit none
    !   real(dpn),intent(in) :: f
    !   type(vectorField) :: q
    !   q%x = f; q%y = f; q%z = f
    ! end function

    ! subroutine vectorAssign(f,g)
    !   implicit none
    !   type(vectorField),intent(inout) :: f
    !   real(dpn),intent(in) :: g
    !   f%x = g; f%y = g; f%z = g
    ! end subroutine

    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
  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)

  a%x = dble(1.0) ! want to avoid this
  a%y = dble(1.0) ! want to avoid this
  a%z = dble(1.0) ! want to avoid this

  a = real(1.0,dpn) ! want this instead (does not compile)

  call delete(a)

  end program

I've tried two different ways (shown in comments) but I get errors saying that there is a syntax error in generic specification (for publicizing the = operator).

like image 640
Charles Avatar asked Dec 02 '22 15:12

Charles


1 Answers

= is not an operator, it is an assignment in Fortran and they are very different beasts.

To the classical possibility found in Fortran 90 and explained well in other answers, Fortran 2003 added a better possibility to bind the overloaded operators and assignments with the derived type.

This way you are sure you will not import the type without the assignment (beware of public and private statement in this case!). It can have very unpleasant consequences and can be hard to debug:

type vectorField
  integer,dimension(3) :: sx,sy,sz
  real(dpn),dimension(:,:,:),allocatable :: x,y,z
contains
  procedure :: assignVector
  generic :: assignment(=) => assignVector
end type

This way you do not have to be that careful to not forget the public :: assignment (=)

like image 89
Vladimir F Героям слава Avatar answered Dec 09 '22 11:12

Vladimir F Героям слава