! $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. ! !============================================================================== ! program ESMF_StateEx !------------------------------------------------------------------------------ !ESMF_EXAMPLE String used by test script to count examples. !============================================================================== #include "ESMF.h" ! ESMF Framework module use ESMF use ESMF_TestMod implicit none #define ESMF_ENABLESTATENEEDED ! Local variables integer :: rc character(ESMF_MAXSTR) :: statename, bundlename, dataname !type(ESMF_Field) :: field1 type(ESMF_FieldBundle) :: bundle1, bundle2 type(ESMF_State) :: state1, state2, state3 integer :: finalrc logical :: neededFlag integer :: result = 0 ! all pass character(ESMF_MAXSTR) :: testname character(ESMF_MAXSTR) :: failMsg finalrc = ESMF_SUCCESS !------------------------------------------------------------------------- !------------------------------------------------------------------------- write(failMsg, *) "Example failure" write(testname, *) "Example ESMF_StateEx" !------------------------------------------------------------------------- !------------------------------------------------------------------------- call ESMF_Initialize(defaultlogfilename="StateEx.Log", & logkindflag=ESMF_LOGKIND_MULTI, rc=rc) !------------------------------------------------------------------------- print *, "State Example 1: Import State" ! This will probably be called from inside the Component Init code statename = "Atmosphere" state1 = ESMF_StateCreate(name=statename, & stateintent=ESMF_STATEINTENT_IMPORT, rc=rc) print *, "State Create returned, name = ", trim(statename) ! Data would be added here and the State reused inside the run ! routine of a sequential application. print *, "State Example 1 finished" if (rc.NE.ESMF_SUCCESS) finalrc = ESMF_FAILURE !------------------------------------------------------------------------- !BOE !\subsubsection{Add items to a State} ! ! Creation of an empty {\tt ESMF\_State}, and adding an {\tt ESMF\_FieldBundle} ! to it. Note that the {\tt ESMF\_FieldBundle} does not get destroyed when ! the {\tt ESMF\_State} is destroyed; the {\tt ESMF\_State} only contains ! a reference to the objects it contains. It also does not make a copy; ! the original objects can be updated and code accessing them by using ! the {\tt ESMF\_State} will see the updated version. !EOE ! Example 2: ! ! Create, Add Data, Query, then Destroy a State. print *, "State Example 2: Export State" !BOC statename = "Ocean" state2 = ESMF_StateCreate(name=statename, & stateintent=ESMF_STATEINTENT_EXPORT, rc=rc) !EOC print *, "State Create returned, name = ", trim(statename) if (rc.NE.ESMF_SUCCESS) finalrc = ESMF_FAILURE !BOC bundlename = "Temperature" bundle1 = ESMF_FieldBundleCreate(name=bundlename, rc=rc) print *, "FieldBundle Create returned", rc !EOC if (rc.NE.ESMF_SUCCESS) finalrc = ESMF_FAILURE !BOC call ESMF_StateAdd(state2, (/bundle1/), rc=rc) print *, "StateAdd returned", rc !EOC if (rc.NE.ESMF_SUCCESS) finalrc = ESMF_FAILURE ! Loop here, updating FieldBundle contents each time step !BOC call ESMF_StateDestroy(state2, rc=rc) !EOC print *, "State Destroy returned", rc if (rc.NE.ESMF_SUCCESS) finalrc = ESMF_FAILURE !BOC call ESMF_FieldBundleDestroy(bundle1, rc=rc) !EOC print *, "FieldBundle Destroy returned", rc print *, "State Example 2 finished" if (rc.NE.ESMF_SUCCESS) finalrc = ESMF_FAILURE !------------------------------------------------------------------------- !BOE !\subsubsection{Add placeholders to a State} ! ! If a component could potentially produce a large number of optional ! items, one strategy is to add the names only of those objects to the ! {\tt ESMF\_State}. Other components can call framework routines to ! set the {\tt ESMF\_NEEDED} flag to indicate they require that data. ! The original component can query this flag and then produce only the ! data that is required by another component. !EOE print *, "State Example 3: Export State with Placeholder" ! The producing Component creates the menu of data items available. !BOC statename = "Ocean" state3 = ESMF_StateCreate(name=statename, & stateintent=ESMF_STATEINTENT_EXPORT, rc=rc) !EOC print *, "State Create returned", rc, " name = ", trim(statename) if (rc.NE.ESMF_SUCCESS) finalrc = ESMF_FAILURE !BOC dataname = "Downward wind:needed" call ESMF_AttributeSet (state3, dataname, .false., rc=rc) !EOC print *, "AttributeSet returned", rc, " name = ", trim(dataname) if (rc.NE.ESMF_SUCCESS) finalrc = ESMF_FAILURE !BOC dataname = "Humidity:needed" call ESMF_AttributeSet (state3, dataname, .false., rc=rc) !EOC print *, "AttributeSet returned", rc, " name = ", trim(dataname) ! See next example for how this is used. print *, "State Example 3 finished" if (rc.NE.ESMF_SUCCESS) finalrc = ESMF_FAILURE !------------------------------------------------------------------------- #if defined (ESMF_ENABLESTATENEEDED) !BOE !\subsubsection{Mark an item {\tt NEEDED}} ! ! How to set the {\tt NEEDED} state of an item. !EOE print *, "State Example 4: Get/Set Needed flags in Export State" ! Given state3 from the previous example, the Coupler or Application ! is given an opportunity to mark which data items are needed. !BOC dataname = "Downward wind:needed" call ESMF_AttributeSet (state3, name=dataname, value=.true., rc=rc) !EOC print *, "AttributeSet returned", rc if (rc.NE.ESMF_SUCCESS) finalrc = ESMF_FAILURE !------------------------------------------------------------------------- !BOE !\subsubsection{Create a {\tt NEEDED} item} ! ! Query an item for the {\tt NEEDED} status, and creating an item on demand. ! Similar flags exist for "Ready", "Valid", and "Required for Restart", ! to mark each data item as ready, having been validated, or needed if the ! application is to be checkpointed and restarted. The flags are supported ! to help coordinate the data exchange between components. !EOE ! Query Needed flags, and add FieldBundle data print *, "State Example 5: Get/Set Needed flags in Export State, continued" ! Given state3 from the previous examples, the producing Component ! can check the state to see what data items are required. !BOC dataname = "Downward wind:needed" call ESMF_AttributeGet (state3, dataname, value=neededFlag, rc=rc) !EOC if (rc.NE.ESMF_SUCCESS) finalrc = ESMF_FAILURE !BOC if (rc == ESMF_SUCCESS .and. neededFlag) then bundlename = dataname bundle2 = ESMF_FieldBundleCreate(name=bundlename, rc=rc) !EOC print *, "FieldBundle Create returned", rc, "name = ", trim(bundlename) if (rc.NE.ESMF_SUCCESS) finalrc = ESMF_FAILURE !BOC call ESMF_StateAdd(state3, (/bundle2/), rc=rc) !EOC print *, "StateAdd returned", rc if (rc.NE.ESMF_SUCCESS) finalrc = ESMF_FAILURE !BOC else print *, "Data not marked as needed", trim(dataname) endif !EOC print *, "State Example 5 finished" #endif call ESMF_StateDestroy(state3, rc=rc) if (rc.NE.ESMF_SUCCESS) finalrc = ESMF_FAILURE print *, "State Destroy returned", rc !------------------------------------------------------------------------- ! ! Similar flags exist for "Ready" and for "Valid" to mark each data ! ! item as ready or having been validated, to help synchronize data ! ! exchange between Components and Couplers. Also "Required for ! ! Restart". !------------------------------------------------------------------------- ! 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_StateEx.F90" else print *, "FAIL: ESMF_StateEx.F90" end if end program ESMF_StateEx