Skip to content

Setting Up MAPL Automatic Code Generator

Darian Boggs edited this page May 24, 2024 · 17 revisions

Overview

The MAPL Automatic Code Generator (ACG) is a utility to allow the user specify certain bits of "boilerplate" code common in MAPL gridded components in an external text file. This text file is parsed to generate include files the user can include in their component. The ACG produces subroutine calls to specify the import/export/internal state of a component in the SetServices phase, as well as declarations of pointers associated with these fields and states, and subroutine calls to retrieve the pointers. A component can have hundreds of fields potentially, which requires in very, very long blocks of source code and obfuscates the actual computational code.

Setting up the MAPL Automatic Code Generator (ACG), consists of three steps:

  1. Create a specs file that the ACG will use to generate source code.
  2. Edit source code to include the files that will be generated.
  3. Edit CMakeLists.txt to generate the include files at build time.

Create a specs file.

The ACG allows the user specify the component state and fields in the spec file, rather than in the source code. In particular, a properly configured spec file allows the user to replace the calls below:

  1. Add an import/export/internal spec.
   call MAPL_AddImportSpec(GC,         &
   SHORT_NAME = 'V',                   &
   LONG_NAME  = 'northward_wind',      &
   UNITS      = 'm s-1',               &
   DIMS       =  MAPL_DimsHorzVert,    &
   VLOCATION  =  MAPL_VLocationCenter, &
   RC=STATUS  )

This tells the component to add a field named V to the import state.

  1. Declare a Fortran pointer to the variable: During the run method of the component, the user needs to use this field, which requires declaring a Fortran pointer of the correct dimensionality:
real, pointer :: v(:,:,:)
  1. Retrieving the pointer to the field. When the field is needed, retrieve the field when it is needed with a MAPL_GetPointer call:
call MAPL_GetPointer(IMPORT, v, 'V",rc=status)

with #include "FILENAME" statements. If your combined import/export/internal state has several hundred fields, it requires a lot of code. The ACG essentially generates the code above into several files which you can include in your component. In general, the AddVarSpecs will be in one include file, the variable declarations will be in another include file, and the MAPL_GetPointer calls will be a third include file.

Note that the variable declaration for the pointer, is the SAME NAME AS THE SHORT NAME. So anywhere you use the pointer, you will use the short name! In the example above, the pointer will be declared as v, and that's what you will use in your code.

Spec File Format

CSV (Comma Separated Value)

The first way to specify the input spec file for the ACG is via CSV or comma separated value type file. Though the format is referred to as "comma separated value", the ACG uses "|" instead of "," to separate values. The input spec file can specify all 3 component states, import, export, and internal. The file consists of a header and up to three component state sections. The header and the component state sections are separated by blank lines. Lines beginning with # are comments, which are ignored, but the lines are not treated as blank lines.

Header

The header consists of these two lines:

schema_version: 2.0.0
component: <Component Name>

The current schema version is 2.0.0, and <Component-Name> is the component the spec file refers to.

Component State Sections

Each component state section consists of a category line that starts with category: followed by a keyword to denote which of those 3 states it is, a row of entries separated by a | character that name the column represented, and a series of rows that specify the values of the columns for multiple variables. For example, the section below specifies the export state, with each line representing a MAPL_AddExportSpec. The first value row specifies a field named DUMASS.

category: EXPORT
#----------------------------------------------------------------------------------------
#  VARIABLE              | DIMENSIONS  |          Additional Metadata
#----------------------------------------------------------------------------------------
 NAME          | UNITS      | DIMS | VLOC | UNGRIDDED                      | LONG NAME
#----------------------------------------------------------------------------------------
 DUMASS        | kg kg-1    | xyz  | C    |                                | Dust Mass Mixing Ratio
 DUMASS25      | kg kg-1    | xyz  | C    |                                | Dust Mass Mixing Ratio
 DUCONC        | kg m-3     | xyz  | C    |                                | Dust Mass Concentration
 DUEXTCOEF     | m-1        | xyz  | C    | size(self%wavelengths_profile) | Dust Extinction Coefficient
 DUEXTCOEFRH20 | m-1        | xyz  | C    | size(self%wavelengths_profile) | Dust Extinction Coefficient - Fixed RH=20%
 DUEXTCOEFRH80 | m-1        | xyz  | C    | size(self%wavelengths_profile) | Dust Extinction Coefficient - Fixed RH=80%
 DUSCACOEF     | m-1        | xyz  | C    | size(self%wavelengths_profile) | Dust Scattering Coefficient

The full spec file would look like this:

schema_version: 2.0.0
component: DU

category: EXPORT
#----------------------------------------------------------------------------------------
#  VARIABLE              | DIMENSIONS  |          Additional Metadata
#----------------------------------------------------------------------------------------
 NAME          | UNITS      | DIMS | VLOC | UNGRIDDED                      | LONG NAME
#----------------------------------------------------------------------------------------
 DUMASS        | kg kg-1    | xyz  | C    |                                | Dust Mass Mixing Ratio
 DUMASS25      | kg kg-1    | xyz  | C    |                                | Dust Mass Mixing Ratio
 DUCONC        | kg m-3     | xyz  | C    |                                | Dust Mass Concentration
 DUEXTCOEF     | m-1        | xyz  | C    | size(self%wavelengths_profile) | Dust Extinction Coefficient
 DUEXTCOEFRH20 | m-1        | xyz  | C    | size(self%wavelengths_profile) | Dust Extinction Coefficient - Fixed RH=20%
 DUEXTCOEFRH80 | m-1        | xyz  | C    | size(self%wavelengths_profile) | Dust Extinction Coefficient - Fixed RH=80%
 DUSCACOEF     | m-1        | xyz  | C    | size(self%wavelengths_profile) | Dust Scattering Coefficient

Notice one annoyance with this format is that if a particular field does not need to specify a value for a column, you need a blank entry there, nonetheless. For example, for the first item, DUMASS has no UNGRIDDED entry, but you still must have the blank column value there. Likewise, if you decide a field needs a new column, you have to insert a whole column for all the fields in the section. This only applies in a section. Fields in different sections do not require the same columns.

Columns

Below we will enumerate some columns. Some columns are required, since you must specify short_name, long_name, units, and dimensional parameters for each field. Some columns are only applicable to specific state types (import, export, or internal). Some columns have aliases.

Column Name Mandatory Aliases AddVarSpec Name Description
SHORT_NAME Yes NAME short_name short name of the add varspec, the name the field you are adding
LONG_NAME Yes LONG NAME long_name long name attached to the field
UNITS Yes units field units
DIMS Yes dims. dimensions
VLOCATION VLOC vlocation vertical location
RESTART restart
CONDITION1 COND See below.
UNGRIDDED_DIMS UNGRID ungridded_dims
UNGRIDDED
ADD2EXPORT ADDEXP add2export
FRIENDLYTO FRIENDLY2 friendlyto

1 This column specifies a condition for a IF-THEN-END IF block enclosing the AddVarSpec.

"*" in SHORT and LONG NAMES

Both the values in the NAME and LONG NAME columns can be proceeded by a *. This means that when the file is processed, the * is substituted with the component name. In this way the same file can be shared by multiples instances of a component. For example, given this spec:

schema_version: 2.0.0
component: DU

category: EXPORT
#----------------------------------------------------------------------------------------
#  VARIABLE              | DIMENSIONS  |          Additional Metadata
#----------------------------------------------------------------------------------------
 NAME          | UNITS      | DIMS | VLOC | UNGRIDDED                      | LONG NAME
#----------------------------------------------------------------------------------------
 *MASS         | kg kg-1    | xyz  | C    |                                | * Mass Mixing Ratio
#----------------------------------------------------------------------------------------

the generated code would be:

   call MAPL_AddImportSpec(GC,           &
   SHORT_NAME = 'DUMASS',                &
   LONG_NAME  = 'DU Mass Mixing Ratio',  &
   UNITS      = 'kg kg-1',               &
   DIMS       =  MAPL_DimsHorzVert,      &
   VLOCATION  =  MAPL_VLocationCenter,   &
   RC=STATUS  )

...

real, pointer :: dumass(:,:,:)

call MAPL_GetPointer(EXPORT, dumass, 'DUMASS",rc=status)

YAML

This will be implemented in the future.

Edit source code.

Assuming you are converting that does not use the ACG, to code that does you must do the following. For each Spec in the specs file, remove:

  1. the MAPL_Add...Spec call.
  2. the corresponding pointer declaration.
  3. the MAPL_GetPointer call.

Edit CMakeLists.txt.

In addition to creating the Specs file, you need to modify CMakeLists.txt at the GridComp and Repository levels.

Edit GridComp CMakeLists.txt.

For each GridComp, add the following block to CMakeLists.txt in the directory that contains the GridComp source file:

mapl_acg (${this}   SPECS_FILENAME
          IMPORT_SPECS EXPORT_SPECS INTERNAL_SPECS
          GET_POINTERS DECLARE_POINTERS)

replacing SPECS_FILENAME with the name of the specs file you created. If the directory contains multiple GridComp source files, add a separate block for each GridComp source file. Each block runs the ACG and generates include files for the corresponding GridComp source file.

Edit Repository CMakeLists.txt.

At the top level directory of the Repository, add the following line to CMakeLists.txt:

include(mapl_acg)
Clone this wiki locally