Polymorphic parent derived type

Viewed 464

I am trying to set up a Fortran OOP code where a parent type geom has an allocatable field shape. This field is allocated with one of the extended types of geom which are a circle or a rectangle types. In another module I have a body type that contains a geom field among others.

So basically I want to have a geom type which can actually access different types (then will access different fields depending on the type) and a body type which is initialized with the geometry.

Find the code below. This is the module for the geometry:

module geomMod

  implicit none

  type :: geom
    class(*),allocatable  :: shape
  contains
    procedure,private     :: set_geom
    generic               :: assignment(=) => set_geom
  end type geom

  type,extends(geom) :: circle
    integer :: id=1
    real    :: centre(2)
    real    :: radius
  end type circle

  type,extends(geom) :: rectangle
    integer :: id=2
    real    :: centre(2)
    real    :: length(2)
  end type rectangle

contains

  subroutine set_geom(a,b)
    implicit none
    class(geom),intent(inout) :: a
    class(*),intent(in)    :: b

    allocate(a%shape,source=b)
  end subroutine set_geom

end module geomMod

This is the module for the body:

module bodyMod
  use geomMod
  implicit none

  type :: body
    class(geom),allocatable :: geom1
    real,allocatable        :: x(:,:)           
    integer                 :: M=50            
    real                    :: eps=0.1         
  contains
    procedure :: init
  end type body

contains

  subroutine init(a,geom1,M,eps)
    implicit none

    class(body),intent(inout)   :: a
    class(geom),intent(in)      :: geom1
    integer,intent(in),optional :: M
    real,intent(in),optional    :: eps

    allocate(a%geom1,source=geom1)

    if(present(M)) a%M = M
    if(present(eps)) a%eps = eps
    if(.not.allocated(a%x)) allocate(a%x(a%M,2))
  end subroutine init

end module bodyMod

And this is how I initialize them from the main file:

  use bodyMod
  implicit none

  integer,parameter :: M = 500
  real,parameter    :: eps = 5

  type(body) :: b
  type(geom) :: geom1

  geom1 = circle(centre=(/1,1/),radius=0.5)

  call b%init(geom1=geom1,M=M,eps=eps)

However I am getting this error compiling with gfortran 4.8.4.

  geom1 = circle(centre=(/1,1/),radius=0.5)
          1
Error: No initializer for component 'shape' given in the structure constructor at (1)!
1 Answers
Related