UserSetServices.F90 Source File


This file depends on

sourcefile~~usersetservices.f90~~EfferentGraph sourcefile~usersetservices.f90 UserSetServices.F90 sourcefile~dso_utilities.f90 DSO_Utilities.F90 sourcefile~usersetservices.f90->sourcefile~dso_utilities.f90 sourcefile~errorhandling.f90 ErrorHandling.F90 sourcefile~usersetservices.f90->sourcefile~errorhandling.f90 sourcefile~esmf_interfaces.f90 ESMF_Interfaces.F90 sourcefile~usersetservices.f90->sourcefile~esmf_interfaces.f90 sourcefile~filesystemutilities.f90 FileSystemUtilities.F90 sourcefile~dso_utilities.f90->sourcefile~filesystemutilities.f90 sourcefile~mapl_throw.f90 MAPL_Throw.F90 sourcefile~errorhandling.f90->sourcefile~mapl_throw.f90

Files dependent on this one

sourcefile~~usersetservices.f90~~AfferentGraph sourcefile~usersetservices.f90 UserSetServices.F90 sourcefile~childspec.f90 ChildSpec.F90 sourcefile~childspec.f90->sourcefile~usersetservices.f90 sourcefile~componentspecparser.f90 ComponentSpecParser.F90 sourcefile~componentspecparser.f90->sourcefile~usersetservices.f90 sourcefile~generic3g.f90 Generic3g.F90 sourcefile~generic3g.f90->sourcefile~usersetservices.f90 sourcefile~genericgridcomp.f90 GenericGridComp.F90 sourcefile~genericgridcomp.f90->sourcefile~usersetservices.f90 sourcefile~mapl_generic.f90~2 MAPL_Generic.F90 sourcefile~mapl_generic.f90~2->sourcefile~usersetservices.f90 sourcefile~outermetacomponent.f90 OuterMetaComponent.F90 sourcefile~outermetacomponent.f90->sourcefile~usersetservices.f90 sourcefile~protoextdatagc.f90 ProtoExtDataGC.F90 sourcefile~protoextdatagc.f90->sourcefile~usersetservices.f90 sourcefile~simpleparentgridcomp.f90 SimpleParentGridComp.F90 sourcefile~simpleparentgridcomp.f90->sourcefile~usersetservices.f90 sourcefile~test_componentspecparser.pf Test_ComponentSpecParser.pf sourcefile~test_componentspecparser.pf->sourcefile~usersetservices.f90 sourcefile~test_genericgridcomp.pf Test_GenericGridComp.pf sourcefile~test_genericgridcomp.pf->sourcefile~usersetservices.f90 sourcefile~test_runchild.pf Test_RunChild.pf sourcefile~test_runchild.pf->sourcefile~usersetservices.f90 sourcefile~test_scenarios.pf Test_Scenarios.pf sourcefile~test_scenarios.pf->sourcefile~usersetservices.f90 sourcefile~test_simpleleafgridcomp.pf Test_SimpleLeafGridComp.pf sourcefile~test_simpleleafgridcomp.pf->sourcefile~usersetservices.f90 sourcefile~test_simpleparentgridcomp.pf Test_SimpleParentGridComp.pf sourcefile~test_simpleparentgridcomp.pf->sourcefile~usersetservices.f90

Source Code

#include "MAPL_ErrLog.h"

! This module provides a family of classes that encapsulate variant
! methods of specifying/running SetServices on a user gridcomp.

! Note that the subclasses (type extensions) are themselves private to
! the module.  Client code is expected to use the overloaded factory
! procedure user_setservices() and assign the result to an object of
! the base class AbstractUserSetServices:
!
!    class(AbstractUserSetServices), allocatable :: ss
!    ss = user_setservices(...)
!

module mapl3g_UserSetServices
   use :: ESMF, only: ESMF_GridComp
   use :: ESMF, only: ESMF_GridCompSetServices
   use :: ESMF, only: ESMF_SUCCESS
   use :: mapl3g_ESMF_Interfaces, only: I_SetServices
   use :: mapl_ErrorHandling
   implicit none
   private

   public :: user_setservices        ! overloaded factory method
   public :: AbstractUserSetServices  ! Base class for variant SS functors
   public :: DSOSetServices
   public :: operator(==)
   public :: operator(/=)
   
   type, abstract :: AbstractUserSetServices
   contains
      procedure(I_RunSetServices), deferred :: run
      procedure(I_write_formatted), deferred :: write_formatted
      generic :: write(formatted) => write_formatted
   end type AbstractUserSetServices

   abstract interface

      subroutine I_RunSetServices(this, gridcomp, rc)
         use esmf, only: ESMF_GridComp
         import AbstractUserSetServices
         class(AbstractUserSetServices), intent(in) :: this
         type(ESMF_GridComp) :: gridcomp
         integer, intent(out) :: rc
      end subroutine I_RunSetServices

      subroutine I_write_formatted(this, unit, iotype, v_list, iostat, iomsg)
         import AbstractUserSetServices
         class(AbstractUserSetServices), intent(in) :: this
         integer, intent(in) :: unit
         character(*), intent(in) :: iotype
         integer, intent(in) :: v_list(:)
         integer, intent(out) :: iostat
         character(*), intent(inout) :: iomsg
      end subroutine I_write_formatted

   end interface

   ! Concrete subclass to encapsulate a traditional user setservices
   ! consisting of a procuder conforming to the I_SetServices
   ! interface.
   type, extends(AbstractUserSetServices) :: ProcSetServices
      procedure(I_SetServices), nopass, pointer :: userRoutine ! ESMF naming convention
   contains
      procedure :: run => run_ProcSetServices
      procedure :: write_formatted => write_formatted_proc
   end type ProcSetServices

   ! Concrete subclass to encapsulate a user setservices procedure
   ! contained in a DSO.
   type, extends(AbstractUserSetServices) :: DSOSetServices
      character(:), allocatable :: sharedObj    ! ESMF naming convention
      character(:), allocatable :: userRoutine  ! ESMF naming convention
   contains
      procedure :: run => run_DSOSetServices
      procedure :: write_formatted => write_formatted_dso
   end type DSOSetServices

   interface user_setservices
      module procedure new_ProcSetServices
      module procedure new_DSOSetservices
   end interface user_setservices

   interface operator(==)
      module procedure equal_setServices
   end interface operator(==)

   interface operator(/=)
      module procedure not_equal_setServices
   end interface operator(/=)

contains

   !----------------------------------
   ! Direct procedure support

   function new_ProcSetServices(userRoutine) result(proc_setservices)
      type(ProcSetServices) :: proc_setservices
      procedure(I_SetServices) :: userRoutine

      proc_setservices%userRoutine => userRoutine

   end function new_ProcSetServices

   subroutine run_ProcSetServices(this, gridcomp, rc)
      class(ProcSetServices), intent(in) :: this
      type(ESMF_GridComp) :: gridComp
      integer, intent(out) :: rc

      integer :: status, userRC

      call ESMF_GridCompSetServices(gridcomp, this%userRoutine, userRC=userRC, _RC)
      _VERIFY(userRC)

      _RETURN(ESMF_SUCCESS)
   end subroutine run_ProcSetServices

   subroutine write_formatted_proc(this, unit, iotype, v_list, iostat, iomsg)
      class(ProcSetServices), intent(in) :: this
      integer, intent(in) :: unit
      character(*), intent(in) :: iotype
      integer, intent(in) :: v_list(:)
      integer, intent(out) :: iostat
      character(*), intent(inout) :: iomsg

      write(unit,*,iostat=iostat, iomsg=iomsg) "userRoutine: <procedure>"
      _UNUSED_DUMMY(iotype)
      _UNUSED_DUMMY(v_list)
      _UNUSED_DUMMY(this)
   end subroutine write_formatted_proc

   !----------------------------------
   ! DSO support
   
   ! Argument names correspond to ESMF arguments.
   function new_DSOSetServices(sharedObj, userRoutine) result(dso_setservices)
      use mapl_DSO_Utilities
      type(DSOSetServices) :: dso_setservices
      character(len=*), intent(in) :: sharedObj
      character(len=*), optional, intent(in) :: userRoutine

      character(:), allocatable :: userRoutine_

      userRoutine_ = 'setservices_' ! unless
      if (present(userRoutine)) userRoutine_ = userRoutine
         
      dso_setservices%sharedObj   = sharedObj
      dso_setservices%userRoutine = userRoutine_

   end function new_DSOSetServices

   subroutine run_DSOSetServices(this, gridcomp, rc)
      use mapl_DSO_Utilities
      class(DSOSetservices), intent(in) :: this
      type(ESMF_GridComp) :: GridComp
      integer, intent(out) :: rc

      integer :: status, user_status
      logical :: found

      _ASSERT(is_supported_dso_name(this%sharedObj), 'unsupported dso name:: <'//this%sharedObj//'>')
      call ESMF_GridCompSetServices(gridcomp, sharedObj=adjust_dso_name(this%sharedObj), &
           userRoutine=this%userRoutine, userRoutinefound=found, _USERRC)

      _RETURN(ESMF_SUCCESS)
   end subroutine run_DSOSetServices

   subroutine write_formatted_dso(this, unit, iotype, v_list, iostat, iomsg)
      class(DSOSetServices), intent(in) :: this
      integer, intent(in) :: unit
      character(*), intent(in) :: iotype
      integer, intent(in) :: v_list(:)
      integer, intent(out) :: iostat
      character(*), intent(inout) :: iomsg

      write(unit,*,iostat=iostat, iomsg=iomsg) "sharedObj: ", this%sharedObj
      if (iostat /= 0) return
      write(unit,*,iostat=iostat, iomsg=iomsg) "userRoutine: ", this%userRoutine

      _UNUSED_DUMMY(iotype)
      _UNUSED_DUMMY(v_list)
   end subroutine write_formatted_dso

   logical function equal_setServices(a, b) result(equal)
      class(AbstractUserSetServices), intent(in) :: a, b

      select type (a)
      type is (DSOSetServices)
         select type(b)
         type is (DSOSetServices)
            equal = equal_DSOSetServices(a,b)
         class default
            equal = .false.
         end select
      type is (ProcSetServices)
         select type(b)
         type is (ProcSetservices)
            equal = equal_ProcSetServices(a,b)
         class default
            equal = .false.
         end select
      class default
         equal = .false.
      end select

   end function equal_setServices

   logical function not_equal_setServices(a, b) result(not_equal)
      class(AbstractUserSetServices), intent(in) :: a, b
      not_equal = .not. (a == b)
   end function not_equal_setServices

   logical function equal_ProcSetServices(a, b) result(equal)
      type(ProcSetServices), intent(in) :: a, b
      equal = associated(a%userRoutine, b%userRoutine)
   end function equal_ProcSetServices

   logical function equal_DSOSetServices(a, b) result(equal)
      type(DSOSetServices), intent(in) :: a, b
      
      equal = (a%sharedObj == b%sharedObj) .and. (a%userRoutine == b%userRoutine)
   end function equal_DSOSetServices

   logical function not_equal_ProcSetServices(a, b) result(not_equal)
      type(ProcSetServices), intent(in) :: a, b
      not_equal = .not. (a == b)
   end function not_equal_ProcSetServices

   logical function not_equal_DSOSetServices(a, b) result(not_equal)
      type(DSOSetServices), intent(in) :: a, b
      not_equal = .not. (a == b)
   end function not_equal_DSOSetServices
   

   
end module mapl3g_UserSetServices