stfc / PSyclone

Domain-specific compiler and code transformation system for Finite Difference/Volume/Element Earth-system models in Fortran
BSD 3-Clause "New" or "Revised" License
103 stars 25 forks source link

mixed precision metadata #1946

Open rupertford opened 1 year ago

rupertford commented 1 year ago

At the moment, a lack of type-bound procedure in the metadata implies an interface and the interface information needs to be examined by PSyclone. This does not play nicely with metadata reading and writing as the information is not encapsulated within a single type.

module compute_mod

type :: compute_type
  type(arg_type) :: meta_args(1) = (/arg_type(gh_field, gh_real, gh_read, w3)/)
end type compute_type

interface compute_code
   procedure compute1_code, compute2_code
end interface compute_code

contains

  subroutine compute1_code(a)
    real*4 :: a
  end subroutine compute1_code

  subroutine compute2_code(a)
    real*8 :: a
  end subroutine compute2_code

end module

An alternative would be to capture the interface in the type, although this would result in code replication

module compute_mod

type :: compute_type
  type(arg_type) :: meta_args(1) = (/arg_type(gh_field, gh_real, gh_read, w3)/)
  contains
  generic :: compute_code => compute1_code, compute2_code
  procedure, nopass :: compute1_code, compute2_code
end type compute_type

interface compute_code
   procedure compute1_code, compute2_code
end interface compute_code

contains

  subroutine compute1_code(a)
    real*4 :: a
  end subroutine compute1_code

  subroutine compute2_code(a)
    real*8 :: a
  end subroutine compute2_code

end module

Separately to this, the precision could also be captured in the metadata, e.g. ...

type(arg_type) :: meta_args(1) = (/arg_type(gh_field, gh_real(s,d), gh_read, w3)/)
arporter commented 4 months ago

The problem is, the 'new' metadata-handling classes are written such that they expect to be able to get everything out of the derived-type definition. Since a kernel interface is separate to this, we have no information on it whatsoever:

https://github.com/stfc/PSyclone/blob/afed0a940a9955fb531fb368f5d3da8fbab6fcdd/src/psyclone/domain/lfric/kernel/common_metadata.py#L137-L155 where fparser2_class is just Fortran2003.Derived_Type_Def - i.e. not the whole Specification-part so we have no information on the interface.

arporter commented 4 months ago

Another alternative for the metadata might be to have it capture the name of the interface associated with it, e.g.:

module compute_mod

type :: compute_type
  type(arg_type) :: meta_args(1) = (/arg_type(gh_field, gh_real, gh_read, w3)/)
  character(len=50) :: procedure_interface = "compute_code"
end type compute_type

interface compute_code
   procedure compute1_code, compute2_code
end interface compute_code

contains
  ...

That at least avoids the duplication that Rupert mentioned in his suggestion.

arporter commented 4 months ago

Another alternative is simply to list all of the procedures that provide kernel implementations, e.g.:

module compute_mod

type :: compute_type
  type(arg_type) :: meta_args(1) = (/arg_type(gh_field, gh_real, gh_read, w3)/)
  procedure, nopass :: compute1_code, compute2_code
end type compute_type

interface compute_code
   procedure compute1_code, compute2_code
end interface compute_code

contains
 ...

The name of the interface that wraps these routines would be given implicitly by the LFRic naming convention and thus we don't need to specify it. This is better than my "character" suggestion as the metadata does now have full information about the interface and the routines it contains.

arporter commented 4 months ago

What do @TeranIvy and @christophermaynard think of my last suggestion?

arporter commented 4 months ago

Also,@mo-lottieturner has expressed an interest.

arporter commented 4 months ago

At the meeting today (01/03/24) we agreed to go with:

module compute_mod

type :: compute_type
  type(arg_type) :: meta_args(1) = (/arg_type(gh_field, gh_real, gh_read, w3)/)
  procedure, nopass :: compute1_code, compute2_code
end type compute_type

interface compute_code
   procedure compute1_code, compute2_code
end interface compute_code

contains
 ...

The first step is to write this up in the documentation and check that that doesn't reveal any potential problems.