Model control functions¶
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 – a calling application is able to, for instance, update a model one time step at a time, change its state, and then continue updating.
initialize¶
int initialize(config_file in string);
def initialize(self, config_file: str) -> None:
int initialize(void* self, const char* config_file);
void Initialize(std::string config_file);
The initialize
function accepts a string argument that gives the
path to its configuration file.
This function should perform all tasks that are to take place before
entering the model’s time loop. Models should be refactored, if
necessary, to read their inputs (which could include filenames for
other input files) from a configuration file.
BMI does not impose any constraint on how configuration files are
formatted.
Implementation notes
Models should be refactored, if necessary, to use a configuration file.
While no constraints are placed on how configuration files are formatted, YAML is preferred.
In C and Fortran, the config_file argument is passed as a character array, whereas in C++, Java, and Python, it’s passed as a string – a basic type in these languages.
In C and Fortran, an integer status code indicating success (zero) or failure (nonzero) is returned. In C++, Java, and Python, an exception is raised on failure.
update¶
int update();
def update(self) -> None:
int update(void* self);
void Update();
The update
function advances the model by a single time step. This
is the model’s own internal time step (as returned by the BMI
get_time_step function), not the time step
of a controlling application.
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 involves incrementing all of the model’s state
variables. If the model’s state variables don’t change in time,
then they can be computed by the initialize function and this
function can just return without doing anything.
Implementation notes
In C and Fortran, an integer status code indicating success (zero) or failure (nonzero) is returned. In C++, Java, and Python, an exception is raised on failure.
update_until¶
int update_until(time in double);
def update_until(self, time: float) -> None:
int update_until(void* self, const double time);
void UpdateUntil(const double time);
The update_until
function updates the model to a particular time,
as provided by its time argument.
If the model permits,
the time argument can be a non-integral multiple of time steps,
and even negative.
Once called, the value returned
by the BMI get_current_time function must return the provided time
to reflect that the model was updated to the requested time.
Implementation notes
Time is always a double-precision value.
In C and Fortran, an integer status code indicating success (zero) or failure (nonzero) is returned. In C++, Java, and Python, an exception is raised on failure.
finalize¶
int finalize();
def finalize(self) -> None:
int finalize(void* self);
void Finalize();
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.
Implementation notes
In C and Fortran, an integer status code indicating success (zero) or failure (nonzero) is returned. In C++, Java, and Python, an exception is raised on failure.