In order to use the plugins with ICON, the first step involves building the ICON and plugins. The instruction of building and using the plugins is explained here for the Levante_gcc and the DWD_nec platforms:
Clone the ICON repository, which is publicly available under the BSD-3-C license:
After cloning ICON, the example plugins can be found in externals/comin/plugins. In this folder there are different examples written in Fortran, C and Python:
| Plugin | Language | Main Functionality |
|---|---|---|
| simple_fortran_plugin.F90 | Fortran | Minimal ComIn plug‑in written in Fortran. |
| simple_c_plugin.c | C | Minimal ComIn plug‑in written in C. |
| simple_python_plugin.py | Python | Minimal ComIn plug‑in written in Python using the ComIn Python adapter. |
| calc_water_column_plugin.F90 | Fortran | Diagnosics for computing the water content in a column. |
| point_source.py | Python | * Requests a tracer that is coupled to ICON’s turbulence and convection schemes. |
To enable the plugins, one or more entries are added to ICON's namelist comin_nml (which is part of the namelist file "atmo_namelist"). Specify the plugin information in the order you want to use them. The different items of plugin_list are
name: the name of the plugin.plugin_library: the shared library file associated with the plugin.primary_constructor (optional): name of the primary constructor. It must be specified if it is not comin_main.options (optional): offers the possibility to pass a character string (e.g. a python script filename) to the plugin.comm (optional): denotes the name of the MPI communicator that is created for this particular plugin. This is useful when exchanging data with other running processes. The parameter comm can be left as an empty string if the application does not require a communicator for this plugin.
Note: The first two components are mandatory to set.
It is recommended to adjust your run script template before configuring ICON. This modified version of your template will be copied to the build/run subdirectory then.
Modifying your experiment's template involves two parts. First, the &comin_nml namelist needs to be added to the namelist "atmo_namelist" (see above).
In addition, you need to set the path of your plugin's shared library in the LD_LIBRARY_PATH. To accomplish this, there are two options available.
add_comin_setup in the run script which does the same automatically. To use this function your basedir variable must be set to the build directory of your ICON installation. The following commands copy the modified version of your template to the build/run subdirectory and launch the batch job
An alternative option is to run your experiment on interactive nodes. Allocate resources for a suitable (cheap!) cluster queue on Levante and wait for the interactive job to start:
Then run the test interactively (remember to make your $BASEDIR known to the new shell: export BASEDIR= ...):
The initial stage involves choosing the preferred programming language, which can be either Fortran 2003, C/C++ or Python. As an illustration, provided here is a guide on creating a plugin using Fortran.
Each plugin must have three parts:
The plugin allows users to write subroutines that can be called at predefined events (entry points) throughout the model simulation. The primary constructor registers the plugin, and it especially registers additional variables and callback functions. Basically, the primary constructor contains the following steps:
It is the plugin's responsibility to check that the host model's ComIn version is compatible with the one the plugin needs. ComIn follows semantic versioning practices, so this check is simple to implement: major versions have to agree and the minor of the host has to exceed the plugin's minimum. As many components of the development are still in the testing phase, the initial public release is set to version number 0.1.0. At major version 0, semantic versioning allows for breaking changes between minor releases. Hence, the minor version has to be equal between the plugin and the host model.
The host model's version is obtained by a call to comin_setup_get_version. In Fortran, this function returns a derived type with the major, minor, and patch versions. In C, the function takes three unsigned* arguments, which get filled with the version components.
The plugin has access to the preprocessor macros COMIN_VERSION_MAJOR, COMIN_VERSION_MINOR, and COMIN_VERSION_PATCH. Those contain the ComIn version used to build the plugin itself. Thus, a simple compatibility check could be implemented as
This check might be overly restrictive because the plugin could work with an older minor version than is used at time of compilation. If the plugin detects an incompatibility, it should call the finish subroutine to abort the simulation.
Plugins are allowed to register additional model variables for ICON. A list of to-be-created variables made known to the ICON via the function comin_var_request_add.
var_descriptor is required to describe (and uniquely identify) a model variable in ICON. lmodexclusive: Whenever a plugin calls comin_var_request_add, there is a check to determine if the requested variable is already registered. In this case, the existing variable will be used instead of creating a new one. However, if the variable exists and is either exclusively requested in the current call or was exclusively requested before, the model aborts based on the lmodexclusive setting.tracer flag (part of the metadata). Apart from that aspect it is not possible to create additional variable containers via the adapter library. Note that it cannot be assumed (if only because of the "sharing" of variables between multiple ComIn plugins) that the tracers generated by a module are stored consecutively. -1 (meaning all domains) as part of the var_descriptor for variables with tracer = .true.The primary constructor appends subroutines of the 3rd party module to the callback register via the adapter library subroutine comin_callback_register.
entry_point_id: entry points denote events during the ICON model simulation, which can trigger a subroutine call of the plugin. Entry points are denoted by named integer constants. The table of available entry points is available in the technical documentation.fct_ptr: this is the callback function. Callback functions do not have additional arguments or return values. The callback function has to be interoperable with the C processor (for Fortran, this requires the BIND(C) attribute; see the technical documentation).The descriptive data structures contain information on the ICON setup (e.g. Fortran KIND values), the computational grid(s), and the simulation status. All descriptive data structures are treated as read-only (seen from the perspective of the 3rd party plugins). However, this read-only nature is (currently) not enforced. For efficiency reasons, the adapter library directly uses pointers to ICON data structures where possible. This holds mostly for components of p_patch, while non p_patch descriptive data are copied from the host model.
A secondary constructor is called after the allocation of ICON variable lists and fields and before the time loop. It needs to be registered by the primary constructor as one of the plugin's callbacks.
comin_var_get. Basically, comin_var_get(context, var_descriptor, flag, var_handle) returns a variable handle var_handle of type t_comin_var_handle, with which the pointer to the data can be accessed in a second step.context: the name of the entry point.var_descriptor: same as described in primary constructor part.flag: the optional argument flag provides information w.r.t. the data flow. Flags may be combined like flag = IOR(COMIN_FLAG_READ, COMIN_FLAG_WRITE). It is important to highlight that when the comin_var_request_add procedure is executed, a variable is not immediately created. This step only involves the registration of a new variable. To use this variable later, it must be queried, similar to the other variables, using the comin_var_get function with flag=COMIN_FLAG_WRITE.comin_var_get registers the access to a variable and returns a variable handle.Code example:
The 5D pointer is than accessed via thr type-bound procedure get_ptr.
Code example:
Note, it is important here to know in advance, of which data type the delivered pointer will be. The integer metadata datatype provides the data type. COMIN_VAR_DATATYPE_DOUBLE, COMIN_VAR_DATATYPE_FLOAT, and COMIN_VAR_DATATYPE_INT are the currently available data types.
There exists a convenience procedure to_3d for accessing 2D/3D fields: In practice, access to fields can be simplified, under the condition that the sequence of dimensions is (jc,jk,jb). This exact dimension sequence is (currently) fulfilled by the ICON model. In this case, a 3D pointer variable REAL(wp) :: slice(:,:,:) can be generated directly from the handle using the procedure.
Python plugins can be attached to ComIn via the Python adapter which is located in the plugins directory in the ComIn source code. It is compiled with ComIn if COMIN_ENABLE_PYTHON_ADAPTER is enabled in the CMake configuration, see the build instructions above. The Python adapter embeds a Python interpreter, which also has the comin Python module available. This module contains all the functions, variables, constants and data structures of the Python language API. When including the Python adapter in the namelist, the Python plugin script must be specified as the options, which can be modified while the actual ComIn plugin Python adapter (libpython_adapter.so) remains unchanged. This script is executed in the primary constructor of the Python adapter. Further callbacks can then be registered by decorating functions with entrypoints.