diff --git a/CHANGELOG.md b/CHANGELOG.md index bfada66bd2c4..f6aa08f82101 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -9,6 +9,8 @@ and this project adheres to [Semantic Versioning](https://semver.org/spec/v2.0.0 ### Added +- New directory (`docs/tutorial/grid_comps/automatic_code_generator`) containing an example showing how to automatically generate the source code using the `MAPL_GridCompSpecs_ACG.py` tool. + ### Changed ### Fixed diff --git a/CMakeLists.txt b/CMakeLists.txt index d14733c3bcaf..01c558963df2 100644 --- a/CMakeLists.txt +++ b/CMakeLists.txt @@ -207,6 +207,11 @@ endif () add_definitions(-Dsys${CMAKE_SYSTEM_NAME}) +# Support for automated code generation +include(mapl_acg) +include(mapl_create_stub_component) +add_subdirectory (Apps) + # Special case - MAPL_cfio is built twice with two different precisions. add_subdirectory (MAPL_cfio MAPL_cfio_r4) add_subdirectory (MAPL_cfio MAPL_cfio_r8) @@ -242,11 +247,6 @@ if (PFUNIT_FOUND) add_subdirectory (pfunit EXCLUDE_FROM_ALL) endif () -# Support for automated code generation -include(mapl_acg) -include(mapl_create_stub_component) -add_subdirectory (Apps) - add_subdirectory (Tests) # @env will exist here if MAPL is built as itself but not as part of, say, GEOSgcm diff --git a/docs/tutorial/grid_comps/CMakeLists.txt b/docs/tutorial/grid_comps/CMakeLists.txt index 2a006d2e4feb..9cdb243357f7 100644 --- a/docs/tutorial/grid_comps/CMakeLists.txt +++ b/docs/tutorial/grid_comps/CMakeLists.txt @@ -4,3 +4,4 @@ add_subdirectory (leaf_comp_a) add_subdirectory (leaf_comp_b) add_subdirectory (parent_with_one_child) add_subdirectory (parent_with_two_children) +add_subdirectory (automatic_code_generator_example) diff --git a/docs/tutorial/grid_comps/automatic_code_generator_example/ACG_GridComp.F90 b/docs/tutorial/grid_comps/automatic_code_generator_example/ACG_GridComp.F90 new file mode 100644 index 000000000000..c3eed7ab9585 --- /dev/null +++ b/docs/tutorial/grid_comps/automatic_code_generator_example/ACG_GridComp.F90 @@ -0,0 +1,113 @@ +#include "MAPL_Generic.h" +#include "MAPL_Exceptions.h" +!------------------------------------------------------------------------------ +!> +!### MODULE: `ACG_GridComp` +! +! This module is created to show how to automatically regenerate code segments +! for the registration and access of ESMF states member variables. +! It is not meant to be executed in an application but only to be compiled. +! +module ACG_GridComp + + use ESMF + use MAPL + + implicit none + private + + public SetServices + +!------------------------------------------------------------------------------ + contains +!------------------------------------------------------------------------------ +!> +! `SetServices` uses MAPL_GenericSetServices, which sets +! the Initialize and Finalize services to generic versions. +! It also allocates our instance of a generic state and puts it in the +! gridded component (GC). Here we only set the run method and +! declare the data services. +! + subroutine SetServices(GC,rc) + + type(ESMF_GridComp), intent(inout) :: GC !! gridded component + integer, optional :: rc !! return code + + integer :: status + + call MAPL_GridCompSetEntryPoint ( gc, ESMF_METHOD_INITIALIZE, initialize, _RC) + call MAPL_GridCompSetEntryPoint ( gc, ESMF_METHOD_RUN, run, _RC) + +#include "ACG_Export___.h" +#include "ACG_Import___.h" + +! Set generic services +! ---------------------------------- + call MAPL_GenericSetServices(GC, _RC) + + _RETURN(_SUCCESS) + + end subroutine SetServices + +!------------------------------------------------------------------------------ +!> +! `initialize` is meant to initialize the `ACG` gridded component. +! It primarily creates its exports. +! + subroutine initialize(GC, import, export, clock, rc) + + type (ESMF_GridComp), intent(inout) :: GC !! Gridded component + type (ESMF_State), intent(inout) :: import !! Import state + type (ESMF_State), intent(inout) :: export !! Export state + type (ESMF_Clock), intent(inout) :: clock !! The clock + integer, optional, intent( out) :: RC !! Error code +! +! Locals + integer :: status + + call MAPL_GridCreate(GC, _RC) + +! Call Generic Initialize +! ---------------------------------------- + call MAPL_GenericInitialize(GC, import, export, clock, _RC) + + _RETURN(_SUCCESS) + + end subroutine initialize + +!------------------------------------------------------------------------------ +!> +! `run` is the Run method for `ACG`. +! + subroutine run(GC, import, export, clock, rc) + + type (ESMF_GridComp), intent(inout) :: GC !! Gridded component + type (ESMF_State), intent(inout) :: import !! Import state + type (ESMF_State), intent(inout) :: export !! Export state + type (ESMF_Clock), intent(inout) :: clock !! The clock + integer, optional, intent( out) :: RC !! Error code +! +! Locals + type (MAPL_MetaComp), pointer :: MAPL + integer :: status + +#include "ACG_DeclarePointer___.h" + +!**************************************************************************** +! Begin... + + ! Get my internal MAPL_Generic state + ! ----------------------------------- + call MAPL_GetObjectFromGC ( GC, MAPL, _RC) + +#include "ACG_GetPointer___.h" + + + _RETURN(_SUCCESS) + + _UNUSED_DUMMY(import) + _UNUSED_DUMMY(clock) + + end subroutine run + +end module ACG_GridComp diff --git a/docs/tutorial/grid_comps/automatic_code_generator_example/ACG_StateSpecs.rc b/docs/tutorial/grid_comps/automatic_code_generator_example/ACG_StateSpecs.rc new file mode 100644 index 000000000000..386d1f122034 --- /dev/null +++ b/docs/tutorial/grid_comps/automatic_code_generator_example/ACG_StateSpecs.rc @@ -0,0 +1,57 @@ +schema_version: 2.0.0 +component: ACG + +category: IMPORT +#---------------------------------------------------------------------------- +# VARIABLE | DIMENSIONS | Additional Metadata +#---------------------------------------------------------------------------- + NAME | UNITS | DIMS | VLOC | RESTART | LONG NAME +#---------------------------------------------------------------------------- + ZLE | m | xyz | E | | geopotential_height + T | K | xyz | C | OPT | air_temperature + PLE | Pa | xyz | E | OPT | air_pressure + +category: EXPORT +#--------------------------------------------------------------------------- +# VARIABLE | DIMENSIONS | Additional Metadata +#--------------------------------------------------------------------------- + NAME | UNITS | DIMS | VLOC | LONG NAME +#--------------------------------------------------------------------------- + ZPBLCN | m | xy | N | boundary_layer_depth + CNV_FRC | 1 | xy | N | convective_fraction + +category: INTERNAL +#--------------------------------------------------------------------------- +# VARIABLE | DIMENSION | Additional Metadata +#--------------------------------------------------------------------------- + NAME | UNITS | DIMS | VLOC | ADD2EXPORT | FRIENDLYTO | LONG NAME +#--------------------------------------------------------------------------- + + +#******************************************************** +# +# Legend +# +#------------------------------------------------------------------ +# Column label | MAPL keyword/interpretation | Default +#--------------|--------------------------------------------------- +# NAME | short_name | +# UNITS | units | +# DIMS | dims | +# VLOC | VLocation | MAPL_VLocationNone +# LONG NAME | long_name | +# COND | if () then | .FALSE. +# NUM_SUBTILES | num_subtiles +# ... +#------------------------------------------------------------------ +# +#-------------------------------------------- +# Entry alias | Column | MAPL keyword/interpretation +#--------------|----------------------------- +# xyz | DIMS | MAPL_HorzVert +# xy | DIMS | MAPL_HorzOnly +# z | DIMS | MAPL_VertOnly (plus ungridded) +# C | VLOC | MAPL_VlocationCenter +# E | VLOC | MAPL_VlocationEdge +# N | VLOC | MAPL_VlocationNone +#-------------------------------------------- diff --git a/docs/tutorial/grid_comps/automatic_code_generator_example/CMakeLists.txt b/docs/tutorial/grid_comps/automatic_code_generator_example/CMakeLists.txt new file mode 100644 index 000000000000..4ae20760f332 --- /dev/null +++ b/docs/tutorial/grid_comps/automatic_code_generator_example/CMakeLists.txt @@ -0,0 +1,21 @@ +esma_set_this (OVERRIDE MAPL.acg) + +set (srcs + ACG_GridComp.F90 + ) + +esma_add_library (${this} SRCS ${srcs} DEPENDENCIES MAPL.shared MAPL TYPE ${MAPL_LIBRARY_TYPE}) + +target_link_libraries(${this} PRIVATE esmf) + +target_include_directories (${this} PUBLIC $) + +set_target_properties (${this} PROPERTIES Fortran_MODULE_DIRECTORY ${include_${this}}) + +mapl_acg (${this} ACG_StateSpecs.rc + IMPORT_SPECS EXPORT_SPECS + GET_POINTERS DECLARE_POINTERS) + +if (NOT CMAKE_Fortran_COMPILER_ID MATCHES "NAG") + target_link_libraries(${this} PRIVATE OpenMP::OpenMP_Fortran) +endif () diff --git a/docs/user_guide/docs/mapl_code_generator.md b/docs/user_guide/docs/mapl_code_generator.md index d832986e37c4..fd3766fb614a 100644 --- a/docs/user_guide/docs/mapl_code_generator.md +++ b/docs/user_guide/docs/mapl_code_generator.md @@ -7,7 +7,7 @@ The number of the those variables can be large and make the declaration process MAPL has a utility tool (named [MAPL_GridCompSpecs_ACG.py ](https://github.com/GEOS-ESM/MAPL/blob/main/Apps/MAPL_GridCompSpecs_ACG.py)) that simplifies and facilitates the registration and access of member variables of the various states (Export, Import, and Internal) of gridded components. -The tool relies on a formatted ASCII file (`spec`` file) to autmatically generate, at compilation time, include files that have the necessary code segments for defining and accessing the expected state member variables. +The tool relies on a formatted ASCII file (`spec` file) to autmatically generate, at compilation time, include files that have the necessary code segments for defining and accessing the expected state member variables. In this document, we describe the [steps](https://github.com/GEOS-ESM/MAPL/wiki/Setting-Up-MAPL-Automatic-Code-Generator) to follow to use the tool. To simplify this documents, we use the words _Imports_, _Exports_ and _Internals_ to refer to member variables of the Import, Export and Internal states, respectively. @@ -138,6 +138,7 @@ Assume that we create such a file (that we name `MyComponent_StateSpecs.rc`) and ``` +schema_version: 2.0.0 component: MyComponent category: IMPORT @@ -196,7 +197,12 @@ category: INTERNAL #-------------------------------------------- ``` -Running `MAPL_GridCompSpecs_ACG.py` on the file `MyComponent_StateSpecs.rc` generates at compilation time four (4) includes files: +#### Remark +It is required to have the settings for the two variable `schema_version` (here `2.0.0`) +and `component` (here `MyComponent`) on top of the `spec` file. + + +Running `MAPL_GridCompSpecs_ACG.py` on the file `MyComponent_StateSpecs.rc` generates at compilation time four (4) include files: 1. `MyComponent_Export___.h` for the `MAPL_AddExportSpec` calls in the `SetServices` routine: @@ -307,6 +313,16 @@ mapl_acg (${this} MyComponent_StateSpecs.rc Note, if in your case, there is no Internal state, `INTERNAL_SPECS` needs not to be added in the above command. But there is no harm including it. +### Sample code +We provide a sample code (gridded component module, `spec` and `CMakeLists.txt` files) that shows +how the automatic code generator is used. The code is available at: + +``` + docs/tutorial/grid_comps/automatic_code_generator_example +``` + +The code is provided for illustration only and compiled with the entire MAPL package. + ### Future Work A future version of the tool will support a YAML specification file.