Difference between revisions of "BMI"

From CSDMS
m (Dimension ordering)
 
(139 intermediate revisions by 5 users not shown)
Line 1: Line 1:
 +
{{PageTitle| Basic Model Interface (BMI) }}
  
=   '''CSDMS Basic Modeling Interface (version 1.0)''' =
+
<div class=AutoScaleImage>[[ File:Bmi-logo-below-lowercase.png | 325 px | right ]]</div>
:
 
* In order to simplify conversion of an existing model to a reusable, plug-and-play model component, CSDMS has developed a simple interface called the '''''Basic Model Interface''''' or '''BMI''' that model developers are asked to implement.  Recall that in this context an '''''interface''''' is a named set of functions with prescribed function names, argument types and return types.
 
:
 
* By design, the BMI functions are straightforward to implement in any of the languages supported by CSDMS, which include C, C++, Fortran (all years), Java and Python.  Even though some of these languages are object-oriented and support user-defined types, the BMI functions use only simple (universal) data types.
 
:
 
* Also by design, the BMI functions are '''''noninvasive'''''.  A BMI-compliant model does not make any calls to CSDMS components or tools and is not modified to use CSDMS data structures. BMI therefore introduces no dependencies into a model and the model can still be used in a "stand-alone" manner.
 
:
 
* Any model that provides the BMI functions can be easily be converted to a CSDMS plug-and-play component that has  a CSDMS '''''Component Model Interface''''' or '''CMI'''.  This conversion/wrapping process is done by CSDMS staff.  The BMI functions are called by the CMI, by the framework and by service components.  It is not necessary for a developer to learn anything about the CMI unless they're just curious.
 
:
 
* Any model that provides the BMI functions should also be straightforward to ingest as a component into other component-based modeling frameworks.  For example, all model coupling frameworks use Model Control Functions very similar to those described below, so providing them helps get a model ready for '''''plug-and-play'''''.
 
:
 
* Once a BMI-compliant model has been wrapped by CSDMS staff to become a CSDMS component, it automatically gains many '''''new capabilities'''''.  This includes the ability to be coupled to other models even if their (1) programming language, (2) variable names, (3) variable units, (4) time-stepping scheme or (5) computational grid is different. It also gains (1) the ability to write output variables to standardized NetCDF files, (2) a "tabbed-dialog" graphical user interface (GUI) (this requires a corresponding XML file) (3) a standardized HTML help page and (4) the ability to run within the CSDMS Modeling Tool (CMT). Examples of (1) a GUI XML file, (2) a standardized HTML help page and (3) a Model Metadata File will be provided soon.
 
:
 
* The CMI wrapping does not have a significant impact on performance.  This is due to the use of [https://computation.llnl.gov/casc/components/#page=home '''Babel'''] for language interoperability and the fact that CSDMS components pass values '''''by reference''''' instead of '''''by copy''''' whenever possible.
 
:
 
* Additional information on the design of the CSDMS framework can be found in [http://www.sciencedirect.com/science/article/pii/S0098300412001252 '''Peckham et al. (2012)'''].
 
:
 
* Simple examples of BMI-compliant models are available for [[BMI_C_Example | '''C''']], [[BMI_Cpp_Example | '''C++''']], [[BMI_Fortran_Example | '''Fortran''']], [[BMI_Python_Example | '''Python''']] and [[BMI_Java_Example | '''Java''']].  (coming soon)
 
:
 
  
<br/>
+
'''Version 2.0'''
<!-- ============================================= -->
 
== {{ Bar Heading| text=Model Control Functions}} ==
 
:
 
<syntaxhighlight lang=sidl>
 
void initialize (in string config_file)
 
void update (in double dt) //  Advance model variables by time interval, dt (dt=-1 means use model time step)
 
void finalize ()
 
void run_model (in string config_file) //  Do a complete model run. Not needed for CMI.
 
</syntaxhighlight>
 
:
 
* These BMI functions are critical to plug-and-play modeling because they allow a calling component to bypass a model's own time loop.  They also provide the caller with '''''fine-grained control''''' over the model, similar to a TV remote control.
 
:
 
* The '''''initialize()''''' function accepts a string argument that gives the name (and path) of its "main input file", called a '''''configuration file'''''. This function should perform all tasks that are to take place before entering the model's time loop.
 
:
 
* The '''''update()''''' function accepts a time step argument, "dt".  If (dt == -1), then the model should use its own (internal) timestep;  otherwise it should use the value provided.  This function should perform all tasks that take place during one pass through the model's time loop.  It does not contain the time loop. This typically includes incrementing all of the model's state variables.
 
:
 
* The '''''finalize()''''' function should perform all tasks that take place after exiting the model's time loop.  This typically includes deallocating memory, closing files and printing reports.
 
:
 
* The '''''run_model()''''' function is not needed by CSDMS but provides a simple method to run the model in "stand-alone mode". (It is often used by the developer; basically the model's "main".)  It would simply call "initialize()", start a time loop that only calls "update()" and then calls "finalize()".
 
  
<br/>
+
Automobiles benefit from a standard interface.
<!-- ============================================= -->
+
Regardless of whether you drive a pickup truck or an electric two-seater,
 +
you use an ignition, an accelerator, and steering wheel.
 +
Imagine having to spend weeks of study to switch from one type of automobile to another,
 +
or from one brand to another.
 +
At CSDMS,
 +
we believe that numerical models, and the sub-components that make up these models, should offer a similar kind of standardization.
 +
To this end, we have developed the Basic Model Interface (BMI): a set of standard query and control functions that, when added to a model code, make that model both easier to learn and easier to couple with other software.
  
== {{ Bar Heading| text=Model Information Functions}} ==
+
BMI is an element of the [[Workbench|CSDMS Workbench]], an integrated system of software tools, technologies, and standards for building and coupling models.
:
 
<syntaxhighlight lang=sidl>
 
array<string> get_input_var_names()
 
array<string> get_output_var_names()
 
string get_attribute( in string att_name ) // (for model_name, mesh_type, time_step_type, etc.)
 
</syntaxhighlight>
 
:
 
* These BMI functions are called by the CSDMS framework in order to determine what input variables each model component needs and what output variables it can provide to other components.
 
:
 
* Note that "long variable name" and "long_var_name" refer to standardized variable names from the [[CSDMS_Standard_Names | '''CSDMS Standard Names''']].  The use of these names makes it possible for the framework to '''automatically''' connect "user components" to "provider components" without user intervention.  The framework can also use metadata associated with the "long variable name" (stored in a Model Metadata File) to determine the degree to which the variable from the provider matches the needs of the user.
 
:
 
* The '''''get_input_var_names()''''' function returns a string array of the model's ''input variable'' names as "long variable names".
 
:
 
* The '''''get_output_var_names()''''' function returns a string array of the models ''output variable'' names.
 
:
 
* The '''''get_attribute()''''' function returns '''''static attributes''''' of the model when passed an attribute name from the following list:
 
model_name
 
version
 
author_name
 
mesh_type
 
time_step_type
 
numerical_method  (explicit or implicit)
 
:For the "mesh_type" attribute, the allowed return values are:
 
uniform, rectilinear, s_mesh and u_mesh
 
:as described in the section called Grid Information Functions below.  For the "time_step_type" attribute, the allowed return values are:
 
fixed      (Timestep size is fixed for all time and is used by all grid cells.)
 
adaptive    (Timestep varies in time, but is used by all grid cells.)
 
des        (Timestep size varies in both space and time.  See below.)
 
: Note that DES ([http://en.wikipedia.org/wiki/Discrete_event_simulation Discrete Event Simulation]) models allow each grid cell to have its own, adaptive time step.
 
  
<br/>
+
== Links ==
<!-- ============================================= -->
 
== {{ Bar Heading| text=Variable Information Functions}} ==
 
:
 
<syntaxhighlight lang=sidl>
 
string get_var_type( in string long_var_name ) // ( returns type_string, e.g. ‘double’)
 
string get_var_units( in string long_var_name ) // ( returns unit_string, e.g. ‘meters’ )
 
int get_var_rank( in string long_var_name ) // ( returns array rank or 0 for scalar)
 
string get_var_name( in string long_var_name ) // ( returns model’s internal, short name )
 
 
double get_time_step() // (returns the model’s current timestep;  adaptive or fixed.)
 
string get_time_units() // (returns unit string for model time, e.g. ‘seconds’, ‘years’)
 
double get_start_time()
 
double get_current_time()
 
double get_end_time()
 
</syntaxhighlight>
 
  
:
+
* The latest [http://bmi.readthedocs.io/ BMI documentation]. Check it out! Last updated February 2020 for BMI 2.0.
* These BMI functions are called by the CSDMS framework to obtain information about a particular input or output variable.  Based on this information, the framework can apply type or unit conversion when necessary.
+
* The central BMI repository on [https://github.com/csdms/bmi GitHub]: Go here to contribute to BMI, ask a BMI-related question, or submit an issue.
:
+
* The BMI 2.0 language specifications for [https://github.com/csdms/bmi-c C], [https://github.com/csdms/bmi-cxx C++], [https://github.com/csdms/bmi-fortran Fortran], and [https://github.com/csdms/bmi-python Python]. If you have a model in one of these supported languages, implement the corresponding spec to create a BMI.
* Note that "long variable name" and "long_var_name" refer to standardized variable names from the [[CSDMS_Standard_Names | '''CSDMS Standard Names''']].
+
* Sample implementations in [https://github.com/csdms/bmi-example-c C], [https://github.com/csdms/bmi-example-cxx C++], [https://github.com/csdms/bmi-example-fortran Fortran], and [https://github.com/csdms/bmi-example-python Python]. These examples demonstrate how to implement a BMI for a simple model.
:
+
* The [http://www.sciencedirect.com/science/article/pii/S0098300412001252 Peckham et al. (2013) article] in ''Computers & Geosciences'' where the concept of BMI was proposed.
* For the '''''get_var_units()''''' and '''''get_time_units()''''' functions, standard unit names (in lower case) should be provided, such as "meters" or "feet". Standard abbreviations, like "m" for "meters" and "mi" for "miles" are also supported. For variables with "compound units", each primitive unit name or abbreviation is separated by a single space character and exponents other than 1 are placed immediately after the name, as in "m s-1" for velocity, or "W m-2" for an energy flux. CSDMS uses the [http://www.unidata.ucar.edu/software/udunits/ '''UDUNITS'''] standard from Unidata.
+
* The [https://joss.theoj.org/papers/10.21105/joss.02317 Hutton et al. (2020) article] in ''Journal of Open Source Software'' describing BMI 2.0.
:
+
* The latest materials for the [https://github.com/csdms/bmi-live BMI Live] instructional clinic.
* The '''''get_var_name()''''' function is not used by CSDMS but often makes it easier to implement the other BMI functions.
 
:
 
* For the '''''get_var_type()''''' function, the returned data type should be a string from the first column of the following table.
 
:
 
{|
 
! align=left width=250 | &nbsp; BMI datatype
 
! align=left width=150 | C datatype
 
! align=left width=150 | NumPy datatype
 
|-
 
| &nbsp; BMI_CHAR
 
| <tt>char</tt>
 
| int8
 
|-
 
| &nbsp; BMI_UNSIGNED_CHAR
 
| <tt>unsigned char</tt>
 
| uint8
 
|-
 
| &nbsp; BMI_INT
 
| <tt>signed int</tt>
 
| int16
 
|-
 
| &nbsp; BMI_LONG
 
| <tt>signed long int</tt>
 
| int32
 
|-
 
| &nbsp; BMI_UNSIGNED_INT
 
| <tt>unsigned int</tt>
 
| uint16
 
|-
 
| &nbsp; BMI_UNSIGNED_LONG
 
| <tt>unsigned long int</tt>
 
| uint32
 
|-
 
| &nbsp; BMI_FLOAT
 
| <tt>float</tt>
 
| float32
 
|-
 
| &nbsp; BMI_DOUBLE
 
| <tt>double</tt>
 
| float64
 
|-
 
|}
 
  
<br/>
+
== Citation ==
<!-- ============================================= -->
 
  
== {{ Bar Heading| text=Variable Getter and Setter Functions}} ==
+
If you use BMI in your work, please cite:
:
 
<syntaxhighlight lang=sidl>
 
double get_0d_double( in string long_var_name )
 
array<double> get_1d_double( in string long_var_name  )
 
array<double,2> get_2d_double( in string long_var_name )
 
array<double> get_2d_double_at_indices( in string long_var_name, array<int> indices )
 
  
void set_0d_double( in string long_var_name, in double scalar )
+
* Peckham, S.D., Hutton, E.W., and Norris, B., 2013. A component-based approach to integrated modeling in the geosciences: The design of CSDMS. ''Computers & Geosciences'', '''53''', pp.3-12, http://dx.doi.org/10.1016/j.cageo.2012.04.002.
void set_1d_double( in string long_var_name, in array<double> array)
 
void set_2d_double( in string long_var_name, in array<double,2> array)
 
void set_2d_double_at_indices( in string long_var_name, in array<int> indices, in array<double,2> array)
 
</syntaxhighlight>
 
:
 
* There are different getter and setter functions for scalars (0d), 1D arrays (1d), 2D arrays (2d) and 3D arrays (3d).  This simplifies implementation, since most of the programming languages supported by CSDMS require '''''static''''' vs. '''''dynamic''''' data types. (''However, other approaches are possible and may also be supported later.'')
 
:
 
* Although not listed above, BMI functions to get and set integer data are also supported. They have names like: "get_2d_int()" instead of "get_2d_double()".
 
:
 
* There is no problem if a model uses arrays with a dimension greater than 3. In that case, BMI functions with names like "get_4d_double()" would simply be provided, following the same naming pattern.
 
:
 
* The BMI functions '''''get_2d_double_at_indices()''''' and '''''set_2d_double_at_indices()''''' allow a (possibly much smaller) subset of values to be obtained from an array. This can dramatically reduce the amount of data that is passed, which can be important when components are coupled across a network.
 
:
 
* Note that "long variable name" and "long_var_name" refer to standardized variable names from the [[CSDMS_Standard_Names | '''CSDMS Standard Names''']].
 
  
<br/>
+
* Hutton, E.W.H., Piper, M.D., and Tucker, G.E., 2020. The Basic Model Interface 2.0: A standard interface for coupling numerical models in the geosciences. ''Journal of Open Source Software'', '''5(51)''', 2317, https://doi.org/10.21105/joss.02317.
<!-- ============================================= -->
 
== {{ Bar Heading| text=Grid Information Functions}} ==
 
:
 
* The BMI function call '''''get_attribute( "mesh_type" )''''' should return one of the following strings:
 
 
 
uniform      (for uniform rectilinear)
 
rectilinear  (for rectilinear)
 
s_mesh        (for structured mesh)
 
u_mesh        (for unstructured mesh)
 
 
 
* Each of these strings corresponds to a particular type of model grid or mesh. In order to provide a complete and standardized description of a model's grid, there is a different set of BMI functions that are required for each model "mesh_type" as described in this section.
 
:
 
* The BMI functions below return grid descriptions that are compatible with [http://earthsystemcog.org/projects/esmp/ '''ESMP'''], the new Python interface for the ESMF regridding tool.  CSDMS uses this tool for spatial regridding, when needed.
 
:
 
* The BMI functions below are also closely aligned with the mesh types supported by [http://www.vtk.org/ '''VTK'''], as described in the [http://www.vtk.org/VTK/img/file-formats.pdf '''VTK File Formats'''] document.
 
:
 
* The [https://groups.google.com/group/ugrid-interoperability '''Ugrid Interoperability Group'''] is working on a standard method for describing and storing unstructured grids.  It is expected to be compatible with NetCDF files.
 
:
 
* An '''''orthogonal curvilinear''''' coordinate system is a special case of a "structured mesh".
 
:
 
* Note that "uniform rectilinear", "rectilinear" and "structured mesh" all have the topology of a two-dimensional array.
 
 
 
=== &nbsp; Uniform Rectilinear ===
 
 
 
[[Image:mesh_uniform_rectilinear.png|300px|wrap]]
 
<syntaxhighlight lang=sidl>
 
array<double, 1> get_grid_spacing (in string long_var_name)
 
array<double, 1> get_grid_lower_left_corner (in string long_var_name)
 
array<int, 1> get_grid_shape (in string long_var_name)
 
</syntaxhighlight>
 
 
 
Each of these functions returns information about each dimension of a mesh. The dimensions are ordered with "ij" indexing (as opposed to "xy"). For example, the get_grid_shape function for the above mesh would return the array [4, 5]. If there were a third dimension, the length of the z dimension would be listed first.
 
 
 
=== &nbsp; Rectilinear ===
 
[[Image:mesh_rectilinear.png|300px|wrap]]
 
<syntaxhighlight lang=sidl>
 
array<double, 1> get_grid_x (in string long_var_name)
 
array<double, 1> get_grid_y (in string long_var_name)
 
array<double, 1> get_grid_z (in string long_var_name)
 
array<int, 1> get_grid_shape (in string long_var_name)
 
</syntaxhighlight>
 
 
 
=== &nbsp; Structured Mesh ===
 
[[Image:mesh_structured.png|300px|wrap]]
 
<syntaxhighlight lang=sidl>
 
array<double, 1> get_grid_x (in string long_var_name)
 
array<double, 1> get_grid_y (in string long_var_name)
 
array<int, 1> get_grid_shape (in string long_var_name)
 
</syntaxhighlight>
 
 
 
=== &nbsp; Unstructured Mesh ===
 
[[Image:mesh_unstructured.png|300px|wrap]]
 
<syntaxhighlight lang=sidl>
 
array<double, 1> get_grid_x (in string long_var_name)
 
array<double, 1> get_grid_y (in string long_var_name)
 
array<int, 1> get_grid_connectivity (in string long_var_name)
 
array<int, 1> get_grid_offset (in string long_var_name)
 
</syntaxhighlight>
 
 
 
:
 
:
 
:
 

Latest revision as of 10:55, 5 March 2021

Basic Model Interface (BMI)
Bmi-logo-below-lowercase.png

Version 2.0

Automobiles benefit from a standard interface. Regardless of whether you drive a pickup truck or an electric two-seater, you use an ignition, an accelerator, and steering wheel. Imagine having to spend weeks of study to switch from one type of automobile to another, or from one brand to another. At CSDMS, we believe that numerical models, and the sub-components that make up these models, should offer a similar kind of standardization. To this end, we have developed the Basic Model Interface (BMI): a set of standard query and control functions that, when added to a model code, make that model both easier to learn and easier to couple with other software.

BMI is an element of the CSDMS Workbench, an integrated system of software tools, technologies, and standards for building and coupling models.

Links

  • The latest BMI documentation. Check it out! Last updated February 2020 for BMI 2.0.
  • The central BMI repository on GitHub: Go here to contribute to BMI, ask a BMI-related question, or submit an issue.
  • The BMI 2.0 language specifications for C, C++, Fortran, and Python. If you have a model in one of these supported languages, implement the corresponding spec to create a BMI.
  • Sample implementations in C, C++, Fortran, and Python. These examples demonstrate how to implement a BMI for a simple model.
  • The Peckham et al. (2013) article in Computers & Geosciences where the concept of BMI was proposed.
  • The Hutton et al. (2020) article in Journal of Open Source Software describing BMI 2.0.
  • The latest materials for the BMI Live instructional clinic.

Citation

If you use BMI in your work, please cite:

  • Peckham, S.D., Hutton, E.W., and Norris, B., 2013. A component-based approach to integrated modeling in the geosciences: The design of CSDMS. Computers & Geosciences, 53, pp.3-12, http://dx.doi.org/10.1016/j.cageo.2012.04.002.
  • Hutton, E.W.H., Piper, M.D., and Tucker, G.E., 2020. The Basic Model Interface 2.0: A standard interface for coupling numerical models in the geosciences. Journal of Open Source Software, 5(51), 2317, https://doi.org/10.21105/joss.02317.