Intel® Fortran Compiler
Build applications that can scale for the future with optimized code designed for Intel® Xeon® and compatible processors.
28446 Discussions

How overload constructor of a class?

S__MPay
Beginner
1,055 Views

I am very new to FORTRAN, especially the OOP programming using FORTRAN.

I am reading some online notes but I think the resources are a little bit limited on OOP for beginners.

This is how I tried to create a class and overload its constructor:
 

!****************************************************************************
! Grid Class
!****************************************************************************
!
!  CLASS: Geo >> Point >> .:Grid:. >> Vector
!
!  PURPOSE:  Grids are same as points but assignable to a coordinate system
!
!****************************************************************************
      module class_grid
      use class_point
      implicit none
      
      private
      
      public :: grid
      
      !==========================================
      ! Class Properties 
      !==========================================
      type, extends(point) :: grid          !< grid class properties:
          private                           !! nothing private
          Integer, public ::  cd            !! coordinate system for displacements
          Integer, public ::  ps            !! BC (permanent single point)
      contains                              !! 

      end type grid                        !>
      !------------------------------------------
          
      interface grid
          module procedure grid_init01
          module procedure grid_init02
      end interface
      
      
      Contains
      !==========================================
      ! M e t h o d s
      !==========================================
      ! Constructor
      type(grid) function grid_init01(id, cp, x1, x2, x3, cd, ps)
          Integer, intent(in) ::  id            !! ID of geo object
          Integer, intent(in) ::  cp            !! ID of coordinate system
          Real,    intent(in) ::  x1            !! first coordinate
          Real,    intent(in) ::  x2            !! second coordinate
          Real,    intent(in) ::  x3            !! third coordinate
          Integer, intent(in) ::  cd            !! coordinate system for displacements
          Integer, intent(in) ::  ps            !! BC (permanent single point)
          
          grid_init01.id = id
          grid_init01.cp = cp
          grid_init01.x1 = x1
          grid_init01.x2 = x2
          grid_init01.x3 = x3
          grid_init01.cd = cd
          grid_init01.ps = ps
      end function grid_init01

      type(grid) function grid_init02(id, x1, x2, x3)
          Integer, intent(in) ::  id            !! ID of geo object
          Real,    intent(in) ::  x1            !! first coordinate
          Real,    intent(in) ::  x2            !! second coordinate
          Real,    intent(in) ::  x3            !! third coordinate
          Integer             ::  cd            !! coordinate system for displacements
          Integer             ::  ps            !! BC (permanent single point)
          cd = 0
          ps = 0
          grid_init02.id = id
          grid_init02.cp = 0
          grid_init02.x1 = x1
          grid_init02.x2 = x2
          grid_init02.x3 = x3
          grid_init02.cd = cd
          grid_init02.ps = ps
      end function grid_init02


      !------------------------------------------
      end module class_grid

I suppose that the grid_init01 and grid_init02 are constructors that are selected based on given arguments.

But when I use:

    type(grid) :: G1
    type(grid) :: G2
    G1 = grid(1, 1, 1, 1, 1, 1, 1)
    G2 = grid(1, 1, 1, 1)

I will get a compiler error:

error #8212: Omitted field is not initialized. Field initialization missing:   [CD]

So did I get it wrong?

0 Kudos
1 Solution
Mark_Lewy
Valued Contributor I
1,055 Views

Dummy arguments x1, x2, x3 are real, so the 2nd to 4th arguments to the constructor call for G2 should be real too:

G2 = grid(1, 1.0, 1.0, 1.0)

Similarly, the 3rd to 5th arguments for the constructor for G1 should also be 1.0.

I'm assuming your point type is declared something like:

      module class_point

      implicit none
      private

      public :: point
      type point
          private
          Integer, public ::  id
          Integer, public ::  cp
          real, public :: x1, x2, x3
      end type
      end module

 

View solution in original post

0 Kudos
9 Replies
Mark_Lewy
Valued Contributor I
1,056 Views

Dummy arguments x1, x2, x3 are real, so the 2nd to 4th arguments to the constructor call for G2 should be real too:

G2 = grid(1, 1.0, 1.0, 1.0)

Similarly, the 3rd to 5th arguments for the constructor for G1 should also be 1.0.

I'm assuming your point type is declared something like:

      module class_point

      implicit none
      private

      public :: point
      type point
          private
          Integer, public ::  id
          Integer, public ::  cp
          real, public :: x1, x2, x3
      end type
      end module

 

0 Kudos
FortranFan
Honored Contributor II
1,055 Views

S. PMay wrote:

I am very new to FORTRAN, especially the OOP programming using FORTRAN.

I am reading some online notes but I think the resources are a little bit limited on OOP for beginners...

Take a look at this, especially the reference in the footnote "Scientific Software Design: The Object-Oriented Way" by Rouson et al.

https://software.intel.com/en-us/blogs/2013/12/30/doctor-fortran-in-its-a-modern-fortran-world

By the way, note a related thread on this forum regarding constructors:

https://software.intel.com/pt-br/node/721089

Also, note the standard Fortran delimiter for derived type components is "%" and not period (.); the latter is a non-standard extension supported by Intel Fortran but it may not work with other compilers.

 

0 Kudos
jimdempseyatthecove
Honored Contributor III
1,055 Views

A note on the sample program in #1 aside from the issue related to constructors.

The OOP model as presented above presents the data as Array of Structures (AOS). This format is not favorable to SIMD instructions. Using Structure of Arrays (SOA) is much more friendly to SIMD instructions. Using narrow SSE SIMD instructions (2 doubles/4 floats) may not have experienced a significant difference making the tradeoff between classical particle and high performance computing requirements. AVX/AVX2 with wider SIMD vectors changed this, and now AVX512 (8 or 16 wide vectors) changed this even more. For systems of large numbers of particles, your program design should have performance a higher weight than particle abstractness into a single object.

Use of SOA's is not so difficult if you make your abstraction at the level of "a collection of particles" as opposed to "each particle". Then make your particle-to-particle interactions being described as particle-to-collection or particle-to-collection subset. Programming in this manner will make better use of the CPU (i.e. less time to solution/integration step).

Jim Dempsey

0 Kudos
FortranFan
Honored Contributor II
1,055 Views

S. PMay wrote:

I am very new to FORTRAN ...

Fyi, following  ISO/IEC standard 1539:1991 published more than 25 years ago it has been trying to be referred to as Fortran, not FORTRAN!

0 Kudos
S__MPay
Beginner
1,055 Views

Dear Mark, FortranFan, Jim;

Thank you very much. Every time I ask a question I learn more than just the answer to my question.

Just in case, I was wondering is there the possibility to call constructor of the base class to initialize common fields, so I don't have to rewrite it in the constructor of inherited class?

0 Kudos
Andrew_Smith
New Contributor III
1,055 Views

I believe the compiler is using the default constructor that comes with derived types and not your functions. That explains why it says fields are not initialized when you dont supply enough arguments.

0 Kudos
FortranFan
Honored Contributor II
1,055 Views

S. MPay wrote:

..  I was wondering is there the possibility to call constructor of the base class to initialize common fields, so I don't have to rewrite it in the constructor of inherited class?

Yes, say your 'class' e_t (extended derived type in Fortran) inherits a base class named b_t, you can do <xx>%b_t = b_t(..) where <xx> is the object of type e_t because the base type in 'contained' in the extended type.  Look into the limitations when the base is an abstract type though.

0 Kudos
S__MPay
Beginner
1,055 Views

Andrew Smith wrote:

I believe the compiler is using the default constructor that comes with derived types and not your functions. That explains why it says fields are not initialized when you dont supply enough arguments.

Now I understand why  G1 = grid(1, 1, 1, 1, 1, 1, 1) would work. I need to input appropriate type so the compiler can detect which constructor to use otherwise it will simply try the default constructor.

 

0 Kudos
S__MPay
Beginner
1,055 Views

FortranFan wrote:

Yes, say your 'class' e_t (extended derived type in Fortran) inherits a base class named b_t, you can do <xx>%b_t = b_t(..) where <xx> is the object of type e_t because the base type in 'contained' in the extended type.  Look into the limitations when the base is an abstract type though.

Thanks, that made my life much easier!

0 Kudos
Reply