Skip to content

Commit

Permalink
update readmes
Browse files Browse the repository at this point in the history
  • Loading branch information
bena-nasa committed Jul 1, 2022
1 parent 7cbd143 commit fcd270c
Show file tree
Hide file tree
Showing 5 changed files with 59 additions and 15 deletions.
6 changes: 3 additions & 3 deletions tutorial/README.md
Original file line number Diff line number Diff line change
Expand Up @@ -4,13 +4,13 @@ For user education we have provided some simple tutorials. These demonstrate how

Before embarking on these tutorials the new users should review the MAPL/ESMF powerpoint presentation here to get a general sense of what these frameworks are about and become familiar with the terminology.

In addition, to use these tutorials you will have to have either built MAPL as a standalone fixture or as part of another fixture like the GEOSgcm. If you are reading this and have not built either, see the instructions for how to build MAPL here: [How to Build MAPL](https://github.com/GEOS-ESM/MAPL/wiki/Building-and-Testing-MAPL-as-a-standalone). For these exercises we highly recommend building MAPL by itself as your build will be much faster, expecially when you change the code. The build itself takes a short time. We also recommend using the "debug" build rather than the "release" build.
In addition, to use these tutorials you will have to have either built MAPL as a standalone fixture or as part of another fixture like the GEOSgcm. If you are reading this and have not built either, see the instructions for how to build MAPL [here](https://github.com/GEOS-ESM/MAPL/wiki/Building-and-Testing-MAPL-as-a-standalone). For these exercises we highly recommend building MAPL by itself as your build will be much faster, expecially when you change the code. The build itself takes a short time. We also recommend using the "debug" build rather than the "release" build. This will turn off optimzations and add extra error checking. The build will be faster in this case. Details on how to do this is in the aformentioned wiki page.

Once you have installed either MAPL or the full GEOSgcm, you will have an installation directory whose full path I will refer to as INSTALL_DIR.

Once you have this, you will find a script run_tutorial_case.sh that is in INSTALL_DIR/bin we have created for your convinience.

This script takes two arguments, the path to INSTALL_DIR and the directory name of the test case you wish to run. To run this, go to a tempoary directory then run the script with the arguments. It will copy the input files to that directory and run the Example_Driver.x for that set of input files. Note that if you are at NCCS or NAS you will need to be on an interactive slurm job with a single node.
This script takes two arguments, the path to INSTALL_DIR and the directory name of the test case you wish to run. To run this, go to a tempoary directory then run the script with the arguments. It will copy the input files to that directory and run the Example_Driver.x for that set of input files. Note that if you are at NCCS or NAS you will need to be on an interactive job with a single node. If you are at NCCS you will be using slurm and instructions can be found [here](https://www.nccs.nasa.gov/nccs-users/instructional/using-slurm). At NAS you would use PBS and instructions can be found [here](https://www.nas.nasa.gov/hecc/support/kb/portable-batch-system-(pbs)-overview_126.html).

The following tutorials are available in the recommended order and represent the tutorial name you would use in the run script.
- hello_world
Expand All @@ -20,7 +20,7 @@ The following tutorials are available in the recommended order and represent the
- parent_one_child_import_via_extdata


As a concrete example, suppose you have installed MAPL here at /discover/nobackup/auser/MAPL/install and want to run hello_world you run this on the command line:
As a concrete example, suppose you have installed MAPL here at `discover/nobackup/auser/MAPL/install` and want to run the hello_world tutorial you run this on the command line:

```
/discover/nobackup/auser/MAPL/install/bin/run_tutorial_case.sh /discover/nobackup/auser/MAPL/install hello_world
Expand Down
36 changes: 32 additions & 4 deletions tutorial/mapl_tutorials/hello_world/README.md
Original file line number Diff line number Diff line change
Expand Up @@ -11,9 +11,11 @@ The gridded component itself is run from the MAPL "CAP". This is a layer that th

If you look in the gridded component you will see that it is quite simple and is just about the minumum lines needed to create a gridded component, a grid for the component, and a run method that does something.

The first routine is the setServices. This is where the user registers the actual methods to be used during the initialize and run phases of the gridded component and are specifed via the SetEntryPoint calls. In addition the MAPL_GenericSetServices is called and every MAPL component must call this before ending the subroutine.
The first routine is the setServices. This is the ONLY routine in the module that should be public. Everything else should be private. In addition the SetServices interface must match the interface defined by ESMF> The main function of the SetServies is to let the user registers the actual methods to be used during the initialize and run phases of the gridded component. These specifed via the SetEntryPoint calls and methods defined in the same module. They also must be defined with the interface prescribed by ESMF. In addition, the MAPL_GenericSetServices is called in this routine and every MAPL component must call this before ending the subroutine. The MAPL_GenericSetServices handles all the extra services provided by MAPL beyond EMSF.

Next we see that a custom initialization routine "my_initialize" is created. It has two calls, the first tells it how to create the grid that is will be used by the gridded component.
Next we see that a custom initialization routine "my_initialize" is created. Notice the subroutine interface. This is the interface all initialize, run, and finalize methods registered my ESMF SetEntryPoint methods must follow. The import state contains all the fields (as well as possibly other types) that will be needed to run the component. The component should not modify the import state. Likewise the export state is what the gridded component produces for use by other components. Finally the clock is just that, a clock that defines the current temporal situation.

In this exmaple, the initialize routine only has two calls. The first tells it how to create the grid that is will be used by the gridded component.

MAPL_GridCreate actually examines the components RC file which in this case is "hello_world.rc". The user will notice these lines:
```
Expand All @@ -27,9 +29,35 @@ hello_world.DATELINE: 'DC'
```
Generally the user will not have to modify these are the setup scripts when running the model would define this for you. In this case it is saying the grid will be a 90x45 lat-lon grid with LM vertical levels.

After this call MAPL_GenericInitialize is called. Once again every custom initialize routine must call this. If no custom initialize routine is defined this will be call automatically.
After this call MAPL_GenericInitialize is called. This is again a MAPL call that handles all the MAPL specify functionality. It also calls the initialize methods of any child, which will be discussed subsequent tutorials. Once again every custom initialize routine must call this. If no custom initialize routine is defined this will be called automatically.

Finally we get to the run method my_run. Notice it has the same interface the initialize method. This was registered and will be executed each time step. As you can see if does very little in this example. It gets the current time from the ESMF clock (this literally a clock that is advanced by the MAPL "CAP"). The time is stored in a variable of `type(ESMF_Time)` declared in the subroutine. It then prints the obligatory "Hello World" and finally uses an ESMF cal which takes an ESMF time and prints it as a string.

# A Note on Error Handling
You will notice that the setServices, initialize, and run subroutines all have an optional rc return variable. This is represents a return code that the calling routine can check to see if the subroutine executed successfully or produced an error. All ESMF and MAPL subroutines and functions have an optional rc value that can be checked when making a call. To check the return status you would do something like this.
```
integer :: status
call ESMF_Foo(arg1,arg2,rc=status)
if (status/=ESMF_SUCCESS) then
if present(rc)) then
rc =status
write(*,*)"Error ",rc," in ",__FILE," on ",__LINE__
return
end if
end
```

This would get very tedious, not to mention make the code hard to read if the user had to do this after every subroutine or function call. To assist the developer MAPL defines a collection of preprocessor macros for error checking .

You will notice that all subroutine calls in this example end with `_RC`. This is a preprocessor macro that expands to `rc=status); _VERIFY(status`.

`_VERIFY` itself is another macro that essentially implements the lines after the call to `ESMF_Foo` in the previous example. It will check the status and if there is an error report the file and line and return.

At the end of each subroutine you will notice another macro, `_RETURN(_SUCCESS)`. This macro ensures that if the optional rc code is passed, it will be set to the "succes" value if the caller is checking the return code. It general placed at the very end of a subroutine.

Finally we get to the run method my_run. This was registered and will be executed each time step. As you can see if does very little in this example. It gets the current time from the clock (this literally a clock that is advanced by the MAPL "CAP"), then prints the obligatory "Hello World" and finally uses an ESMF call to print the current time.
All new functions and subroutines should have an optional rc code and use these macros. It will make debugging and crash analysis much easier.

# Running the code
When you run the code the first few lines will look like this:
Expand Down
15 changes: 12 additions & 3 deletions tutorial/mapl_tutorials/parent_no_children/README.md
Original file line number Diff line number Diff line change
Expand Up @@ -20,7 +20,7 @@ Past the declarations, we see we first retrieve the MAPL_MetaComp from the gridd
```
my_value: 11.0
```
Finally there are two calls to MAPL_GetPointer which is a shorthand way to obtain a pointer to the data in an ESMF_Field in an ESMF_State. Through the magic of MAPL, the user will find that there are indeed two fields in the state named ouput1 and output2! All this was handled by MAPL and ESMF!. Notice we check if the pointer is associated before using it and if so set all the values of the pointer to the constant my_constat. Why do we check the associated status? Because exports might not have been allocated. Imports always are, so the rule is for any pointer from an Export state, always check the associated status before using it.
Finally there are two calls to MAPL_GetPointer which is a shorthand way to obtain a Fortran pointer to the data in an ESMF_Field, contained in an ESMF_State. Through the magic of MAPL, the user will find that there are indeed two fields in the state named ouput1 and output2! All this was handled by MAPL and ESMF!. Notice that a check is mde to determine if the pointer is associated before using it. Only if the pointer is actually associated can it be used. If it is associated, in this case all the values of the array are set to the constant my_constat. Why do we check the associated status? Because exports might not have been allocated. Imports always are, so the rule is for any pointer from an Export state, always check the associated status before using it.

$ HISTORY.rc

Expand All @@ -38,10 +38,19 @@ my_collection.frequency: 060000
my_collection.fields: 'output1', 'root'
::
```
The HISTORY.rc drives the MAPL_HistoryGridComp which is a special service provided by MAPL to allow users to write fields from any component's export state to a file. Documentation for the input file can be found here: [History Documentation](https://github.com/GEOS-ESM/MAPL/wiki/MAPL-History-Component). In this example we are saying every 6 hours write the field 'output1' from the component root. You should see that in your run directory you have 4 files named starting with my_collection. If you ncdump them you will see that the variable output1 should be identically 11 in each one. Indeed you should see while that the program runs it will write a message when History writes a file.
The HISTORY.rc drives the MAPL_HistoryGridComp which is a special service provided by MAPL to allow users to write fields from any component's export state to a file. Documentation for the input file can be found [here](https://github.com/GEOS-ESM/MAPL/wiki/MAPL-History-Component). In this example we are saying every 6 hours write the field 'output1' from the component root. You should see that in your run directory you have 4 files named starting with my_collection. If you ncdump them you will see that the variable output1 should be identically 11 in each one. If you examine the output from the run, you will see message when History writes a file, for example:
```
AGCM Date: 2007/08/01 Time: 01:00:00 Throughput(days/day)[Avg Tot Run]: 998447.8 1017616.9 22162362.2 TimeRemaining(Est) 000:00:00 2.8% : 13.5% Mem Comm:Used
AGCM Date: 2007/08/01 Time: 02:00:00 Throughput(days/day)[Avg Tot Run]: 24850021.6 12648460.0 51528614.8 TimeRemaining(Est) 000:00:00 2.8% : 13.5% Mem Comm:Used
AGCM Date: 2007/08/01 Time: 03:00:00 Throughput(days/day)[Avg Tot Run]: 16222750.9 14134794.7 55756268.3 TimeRemaining(Est) 000:00:00 2.8% : 13.5% Mem Comm:Used
AGCM Date: 2007/08/01 Time: 04:00:00 Throughput(days/day)[Avg Tot Run]: 13864970.4 13973735.3 49224105.6 TimeRemaining(Est) 000:00:00 2.8% : 13.5% Mem Comm:Used
AGCM Date: 2007/08/01 Time: 05:00:00 Throughput(days/day)[Avg Tot Run]: 12915278.6 14773101.2 58278111.3 TimeRemaining(Est) 000:00:00 2.8% : 13.5% Mem Comm:Used
Writing: 1 Slices to File: my_collection.20070801_0600z.nc4
```


# Exercise for the User

The user may want to print the size of the ptr_2d and ptr_3d array to confirm that they match the size of the grid.
Notice that HISTORY.rc is only outputting output1, add output2.
The user may also notice that in the files only the output1 field was written. Try adding output2 to the HISTORY.rc and see what happens.
Original file line number Diff line number Diff line change
Expand Up @@ -11,15 +11,17 @@ tutorial/grid_comps/parent_with_one_child/ParentOneChild_GridComp.F90
This is the same as the earlier tutorial and the "root" component.

# BBB_GridComp.F90
This is the same as the previous totorial
This is the same as the previous tutorial

# Running
In this example we use the same components you have seen before. But now our child has an import and nobody fills it!. But you see that the print from BBB has a value. How is that possible? The answer is the other special MAPL gridded component, ExtData. During the run you will see lines like this:
In this example we use the same components you have seen before. But now our child has an import but there is no other child to make a connectivity with to fill it!. But you will see that the print from BBB has a value that is changing on each step. How is that possible? The answer is the other special MAPL gridded component, ExtData. During the run you will see lines like this:
```
EXTDATA: Updating L bracket for field1
EXTDATA: ... file processed: extdata_input.200708.nc4
EXTDATA: Updating R bracket for field1
EXTDATA: ... file processed: extdata_input.200708.nc4
```
What is going on is that since there was no connectivity in the "root" component the Import is field filled by a data file on the disk from the "ExtData" component. This is a special component that is used to fill fields from the disk. It is used for time varying quantities like emissions and forcing data. If you look in your input files you will see that ExtData.rc has an entry that starts with "field1". This is a "rule" that tell it how to fill a variable named "field1" from a datafile. For more information about ExtData see here: [ExtData](https://github.com/GEOS-ESM/MAPL/wiki/MAPL-ExtData-Component)
In the tutorial with two childrun under root we discussed how import "bubble up" to their parents. In this case since there is no connectivity here here, the import bubbles up to the MAPL_Cap. At this point any imports that have reached the MAPL_Cap are handed off to a special component named ExtData. This is a special component that is delivered ESMF fields and uses "rules" from an input file to fill these fields with data from NetCDF files on the disk. It is used for time varying quantities like emissions and forcing data. If you look in your input files you will see that ExtData.rc has an entry that starts with "field1". This is a "rule" that tell it how to fill a variable named "field1" from a datafile. More imformation about ExtData [here](https://github.com/GEOS-ESM/MAPL/wiki/MAPL-ExtData-Component).

Also note that ExtData is currently undergoing a transition to use a new input format which will use YAML rather than the `ESMF_Config` format. Information about that format can be found [here](https://github.com/GEOS-ESM/MAPL/wiki/ExtData-Next-Generation---User-Guide).

Loading

0 comments on commit fcd270c

Please sign in to comment.