ESMF_StateReconcileEx.F90 Source File


Source Code

! $Id$
!
! Earth System Modeling Framework
! Copyright (c) 2002-2023, University Corporation for Atmospheric Research,
! Massachusetts Institute of Technology, Geophysical Fluid Dynamics
! Laboratory, University of Michigan, National Centers for Environmental
! Prediction, Los Alamos National Laboratory, Argonne National Laboratory,
! NASA Goddard Space Flight Center.
! Licensed under the University of Illinois-NCSA License.
!
!==============================================================================
!

module ESMF_StateReconcileEx_Mod

use ESMF

contains

!BOE
!\subsubsection{{\tt ESMF\_StateReconcile()} usage}
!  
! The set services routines are used to tell ESMF which routine
! hold the user code for the initialize, run, and finalize
! blocks of user level Components.
! These are the separate subroutines called by the code below.
!EOE

!BOC
! Initialize routine which creates "field1" on PETs 0 and 1
subroutine comp1_init(gcomp, istate, ostate, clock, rc)
    type(ESMF_GridComp)  :: gcomp
    type(ESMF_State)     :: istate, ostate
    type(ESMF_Clock)     :: clock
    integer, intent(out) :: rc

    type(ESMF_Field) :: field1
    integer :: localrc

    print *, "i am comp1_init"

    field1 = ESMF_FieldEmptyCreate(name="Comp1 Field", rc=localrc)
  
    call ESMF_StateAdd(istate, (/field1/), rc=localrc)
    
    rc = localrc

end subroutine comp1_init

! Initialize routine which creates "field2" on PETs 2 and 3
subroutine comp2_init(gcomp, istate, ostate, clock, rc)
    type(ESMF_GridComp)  :: gcomp
    type(ESMF_State)     :: istate, ostate
    type(ESMF_Clock)     :: clock
    integer, intent(out) :: rc

    type(ESMF_Field) :: field2
    integer :: localrc

    print *, "i am comp2_init"

    field2 = ESMF_FieldEmptyCreate(name="Comp2 Field", rc=localrc)
    
    call ESMF_StateAdd(istate, (/field2/), rc=localrc)

    rc = localrc

end subroutine comp2_init

subroutine comp_dummy(gcomp, rc)
   type(ESMF_GridComp)  :: gcomp
   integer, intent(out) :: rc

   rc = ESMF_SUCCESS
end subroutine comp_dummy
!EOC
    
end module ESMF_StateReconcileEx_Mod






    program ESMF_StateReconcileEx

!------------------------------------------------------------------------------
!ESMF_EXAMPLE        String used by test script to count examples.
!==============================================================================
!BOC
! !PROGRAM: ESMF_StateReconcileEx - State reconciliation
!
! !DESCRIPTION:
!
! This program shows examples of using the State Reconcile function
!-----------------------------------------------------------------------------
#include "ESMF.h"

    ! ESMF Framework module
    use ESMF
    use ESMF_TestMod
    use ESMF_StateReconcileEx_Mod
    implicit none

    ! Local variables
    integer :: rc, petCount
    type(ESMF_State) :: state1
    type(ESMF_GridComp) :: comp1, comp2
    type(ESMF_VM) :: vm
    character(len=ESMF_MAXSTR) :: comp1name, comp2name, statename

!EOC
    integer :: finalrc, result
    character(ESMF_MAXSTR) :: testname
    character(ESMF_MAXSTR) :: failMsg

!-------------------------------------------------------------------------
!-------------------------------------------------------------------------

    write(failMsg, *) "Example failure"
    write(testname, *) "Example ESMF_StateReconcileEx"


! ------------------------------------------------------------------------------
! ------------------------------------------------------------------------------

    finalrc = ESMF_SUCCESS


    call ESMF_Initialize(vm=vm, defaultlogfilename="StateReconcileEx.Log", &
                     logkindflag=ESMF_LOGKIND_MULTI, rc=rc)
    
    ! verify that this example can run on the given petCount
    call ESMF_VMGet(vm, petCount=petCount, rc=rc)
    if (rc .ne. ESMF_SUCCESS) goto 20

    if (petCount<4) then
      print *, "This test must run on at least 4 PETs."
      goto 20
    endif
    

!-------------------------------------------------------------------------
!BOE
!      
!  A Component can be created which will run only on a subset of the
!  current PET list.
!EOE
 
    print *, "State Reconcile Example 1: Component Creation"

!BOC
    ! Get the global VM for this job.
    call ESMF_VMGetGlobal(vm=vm, rc=rc)

    comp1name = "Atmosphere"
    comp1 = ESMF_GridCompCreate(name=comp1name, petList=(/ 0, 1 /), rc=rc)
    print *, "GridComp Create returned, name = ", trim(comp1name)
!EOC
    if (rc.NE.ESMF_SUCCESS) finalrc = ESMF_FAILURE
!BOC

    comp2name = "Ocean"
    comp2 = ESMF_GridCompCreate(name=comp2name, petList=(/ 2, 3 /), rc=rc)
    print *, "GridComp Create returned, name = ", trim(comp2name)
!EOC
    if (rc.NE.ESMF_SUCCESS) finalrc = ESMF_FAILURE
!BOC

    statename = "Ocn2Atm"
    state1 = ESMF_StateCreate(name=statename, rc=rc)  
!EOC
    print *, "State Create returned, name = ", trim(statename)

    print *, "State Example 1 finished"
    if (rc.NE.ESMF_SUCCESS) finalrc = ESMF_FAILURE

!-------------------------------------------------------------------------
!BOE
!   
!  Here we register the subroutines which should be called for initialization.
!  Then we call ESMF\_GridCompInitialize() on all PETs, but the code runs
!  only on the PETs given in the petList when the Component was created.
!
!  Because this example is so short, we call the entry point code
!  directly instead of the normal procedure of nesting it in a separate
!  SetServices() subroutine.  
!
!EOE

!BOC
    ! This is where the VM for each component is initialized.
    ! Normally you would call SetEntryPoint inside set services,
    ! but to make this example very short, they are called inline below.
    ! This is o.k. because the SetServices routine must execute from within
    ! the parent component VM.
    call ESMF_GridCompSetVM(comp1, comp_dummy, rc=rc)
!EOC
    if (rc.NE.ESMF_SUCCESS) finalrc = ESMF_FAILURE
!BOC

    call ESMF_GridCompSetVM(comp2, comp_dummy, rc=rc)
!EOC
    if (rc.NE.ESMF_SUCCESS) finalrc = ESMF_FAILURE
!BOC

    call ESMF_GridCompSetServices(comp1, userRoutine=comp_dummy, rc=rc)
!EOC
    if (rc.NE.ESMF_SUCCESS) finalrc = ESMF_FAILURE
!BOC

    call ESMF_GridCompSetServices(comp2, userRoutine=comp_dummy, rc=rc)
!EOC
    if (rc.NE.ESMF_SUCCESS) finalrc = ESMF_FAILURE
!BOC


    print *, "ready to set entry point 1"
    call ESMF_GridCompSetEntryPoint(comp1, ESMF_METHOD_INITIALIZE, &
         comp1_init, rc=rc)
!EOC
    if (rc.NE.ESMF_SUCCESS) finalrc = ESMF_FAILURE
!BOC


    print *, "ready to set entry point 2"
    call ESMF_GridCompSetEntryPoint(comp2, ESMF_METHOD_INITIALIZE, &
         comp2_init, rc=rc)
!EOC
    if (rc.NE.ESMF_SUCCESS) finalrc = ESMF_FAILURE
!BOC



    print *, "ready to call init for comp 1"
    call ESMF_GridCompInitialize(comp1, exportState=state1, rc=rc)
!EOC
    if (rc.NE.ESMF_SUCCESS) finalrc = ESMF_FAILURE
!BOC

    print *, "ready to call init for comp 2"
    call ESMF_GridCompInitialize(comp2, exportState=state1, rc=rc)
!EOC

    print *, "State Example 2 finished"
    if (rc.NE.ESMF_SUCCESS) finalrc = ESMF_FAILURE

!-------------------------------------------------------------------------
!BOE
!   
! Now we have {\tt state1} containing {\tt field1} on PETs 0 and 1, and
! {\tt state1} containing {\tt field2} on PETs 2 and 3.  For the code
! to have a rational view of the data, we call {\tt ESMF\_StateReconcile}
! which determines which objects are missing from any PET, and communicates
! information about the object. After the call to reconcile, all
! {\tt ESMF\_State} objects now have a consistent view of the data.
!EOE

!BOC
    print *, "State before calling StateReconcile()"
    call ESMF_StatePrint(state1, rc=rc)
!EOC
    if (rc.NE.ESMF_SUCCESS) finalrc = ESMF_FAILURE
!BOC


    call ESMF_StateReconcile(state1, vm=vm, rc=rc)
!EOC
    if (rc.NE.ESMF_SUCCESS) finalrc = ESMF_FAILURE
!BOC


    print *, "State after calling StateReconcile()"
    call ESMF_StatePrint(state1, rc=rc)
!EOC

    print *, "State Example 3 finished"
    if (rc.NE.ESMF_SUCCESS) finalrc = ESMF_FAILURE

!-------------------------------------------------------------------------

    call ESMF_StateDestroy (state1, rc=rc)
    if (rc /= ESMF_SUCCESS) finalrc = ESMF_FAILURE

    call ESMF_GridCompDestroy (comp2, rc=rc)
    if (rc /= ESMF_SUCCESS) finalrc = ESMF_FAILURE

    call ESMF_GridCompDestroy (comp1, rc=rc)
    if (rc /= ESMF_SUCCESS) finalrc = ESMF_FAILURE

20  continue
    ! IMPORTANT: ESMF_STest() prints the PASS string and the # of processors in the log
    ! file that the scripts grep for.
    call ESMF_STest((finalrc.eq.ESMF_SUCCESS), testname, failMsg, result, ESMF_SRCLINE)


    call ESMF_Finalize(rc=rc)

    if (rc.NE.ESMF_SUCCESS) finalrc = ESMF_FAILURE

    if (finalrc.EQ.ESMF_SUCCESS) then
        print *, "PASS: ESMF_StateReconcileEx.F90"
    else
        print *, "FAIL: ESMF_StateReconcileEx.F90"
    end if

!BOC
end program ESMF_StateReconcileEx
!EOC