Skip to content

Commit

Permalink
Add example notebooks (#25)
Browse files Browse the repository at this point in the history
* Expose Heat model through heat package

* Add example notebooks

* List examples directory and update build instructions

* Fix typo

* Run black, isort, and flake8
  • Loading branch information
mdpiper committed Jun 27, 2022
1 parent 1329f47 commit 44c7d4c
Show file tree
Hide file tree
Showing 6 changed files with 578 additions and 10 deletions.
11 changes: 7 additions & 4 deletions README.rst
Original file line number Diff line number Diff line change
Expand Up @@ -30,7 +30,10 @@ Tests of the BMI are provided.
This repository is organized with the following directories:

*heat*
Holds the model and the BMI for the model
Source code for the model and its BMI

*examples*
Jupyter Notebooks that demonstrate how to run the model through its BMI

*tests*
Tests that cover the BMI of the model
Expand All @@ -45,20 +48,20 @@ This example can be built and installed on Linux, macOS, and Windows.
* Python 3
* The Python BMI bindings. Follow the build and install directions
given in the `README`_ in that repository. You can choose to install
them from source, or through pip, or conda.
them from source, or through `pip` or `conda`.

To build/install this example from source,
using the current Python BMI version, run

.. code-block:: bash
$ make install
$ pip install -e .
To run the tests,

.. code-block:: bash
$ pip install -r requirements.txt
$ pip install -r requirements-testing.txt
$ make test
Expand Down
348 changes: 348 additions & 0 deletions examples/run-model-from-bmi.ipynb
Original file line number Diff line number Diff line change
@@ -0,0 +1,348 @@
{
"cells": [
{
"cell_type": "markdown",
"metadata": {},
"source": [
"# Run the `Heat` model through its BMI"
]
},
{
"cell_type": "markdown",
"metadata": {},
"source": [
"`Heat` models the diffusion of temperature on a uniform rectangular plate with Dirichlet boundary conditions. View the source code for the [model](https://github.com/csdms/bmi-example-python/blob/master/heat/heat.py) and its [BMI](https://github.com/csdms/bmi-example-python/blob/master/heat/bmi_heat.py) on GitHub."
]
},
{
"cell_type": "markdown",
"metadata": {},
"source": [
"Start by importing `os`, `numpy` and the `Heat` BMI:"
]
},
{
"cell_type": "code",
"execution_count": null,
"metadata": {},
"outputs": [],
"source": [
"import os\n",
"import numpy as np\n",
"\n",
"from heat import BmiHeat"
]
},
{
"cell_type": "markdown",
"metadata": {},
"source": [
"Create an instance of the model's BMI."
]
},
{
"cell_type": "code",
"execution_count": null,
"metadata": {},
"outputs": [],
"source": [
"x = BmiHeat()"
]
},
{
"cell_type": "markdown",
"metadata": {},
"source": [
"What's the name of this model?"
]
},
{
"cell_type": "code",
"execution_count": null,
"metadata": {},
"outputs": [],
"source": [
"print(x.get_component_name())"
]
},
{
"cell_type": "markdown",
"metadata": {},
"source": [
"Start the `Heat` model through its BMI using a configuration file:"
]
},
{
"cell_type": "code",
"execution_count": null,
"metadata": {},
"outputs": [],
"source": [
"cat heat.yaml"
]
},
{
"cell_type": "code",
"execution_count": null,
"metadata": {},
"outputs": [],
"source": [
"x.initialize(\"heat.yaml\")"
]
},
{
"cell_type": "markdown",
"metadata": {},
"source": [
"Check the time information for the model."
]
},
{
"cell_type": "code",
"execution_count": null,
"metadata": {},
"outputs": [],
"source": [
"print(\"Start time:\", x.get_start_time())\n",
"print(\"End time:\", x.get_end_time())\n",
"print(\"Current time:\", x.get_current_time())\n",
"print(\"Time step:\", x.get_time_step())\n",
"print(\"Time units:\", x.get_time_units())"
]
},
{
"cell_type": "markdown",
"metadata": {},
"source": [
"Show the input and output variables for the component (aside on [Standard Names](https://csdms.colorado.edu/wiki/CSDMS_Standard_Names)):"
]
},
{
"cell_type": "code",
"execution_count": null,
"metadata": {},
"outputs": [],
"source": [
"print(x.get_input_var_names())\n",
"print(x.get_output_var_names())"
]
},
{
"cell_type": "markdown",
"metadata": {},
"source": [
"Next, get the identifier for the grid on which the temperature variable is defined:"
]
},
{
"cell_type": "code",
"execution_count": null,
"metadata": {},
"outputs": [],
"source": [
"grid_id = x.get_var_grid(\"plate_surface__temperature\")\n",
"print(\"Grid id:\", grid_id)"
]
},
{
"cell_type": "markdown",
"metadata": {},
"source": [
"Then get the grid attributes:"
]
},
{
"cell_type": "code",
"execution_count": null,
"metadata": {},
"outputs": [],
"source": [
"print(\"Grid type:\", x.get_grid_type(grid_id))\n",
"\n",
"rank = x.get_grid_rank(grid_id)\n",
"print(\"Grid rank:\", rank)\n",
"\n",
"shape = np.ndarray(rank, dtype=int)\n",
"x.get_grid_shape(grid_id, shape)\n",
"print(\"Grid shape:\", shape)\n",
"\n",
"spacing = np.ndarray(rank, dtype=float)\n",
"x.get_grid_spacing(grid_id, spacing)\n",
"print(\"Grid spacing:\", spacing)"
]
},
{
"cell_type": "markdown",
"metadata": {},
"source": [
"These commands are made somewhat un-Pythonic by the generic design of the BMI."
]
},
{
"cell_type": "markdown",
"metadata": {},
"source": [
"Through the model's BMI, zero out the initial temperature field, except for an impulse near the middle.\n",
"Note that *set_value* expects a one-dimensional array for input."
]
},
{
"cell_type": "code",
"execution_count": null,
"metadata": {},
"outputs": [],
"source": [
"temperature = np.zeros(shape)\n",
"temperature[3, 4] = 100.0\n",
"x.set_value(\"plate_surface__temperature\", temperature)"
]
},
{
"cell_type": "markdown",
"metadata": {},
"source": [
"Check that the temperature field has been updated. Note that *get_value* expects a one-dimensional array to receive output."
]
},
{
"cell_type": "code",
"execution_count": null,
"metadata": {},
"outputs": [],
"source": [
"temperature_flat = np.empty_like(temperature).flatten()\n",
"x.get_value(\"plate_surface__temperature\", temperature_flat)\n",
"print(temperature_flat.reshape(shape))"
]
},
{
"cell_type": "markdown",
"metadata": {},
"source": [
"Now advance the model by a single time step:"
]
},
{
"cell_type": "code",
"execution_count": null,
"metadata": {},
"outputs": [],
"source": [
"x.update()"
]
},
{
"cell_type": "markdown",
"metadata": {},
"source": [
"View the new state of the temperature field:"
]
},
{
"cell_type": "code",
"execution_count": null,
"metadata": {},
"outputs": [],
"source": [
"x.get_value(\"plate_surface__temperature\", temperature_flat)\n",
"print(temperature_flat.reshape(shape))"
]
},
{
"cell_type": "markdown",
"metadata": {},
"source": [
"There's diffusion!"
]
},
{
"cell_type": "markdown",
"metadata": {},
"source": [
"Advance the model to some distant time:"
]
},
{
"cell_type": "code",
"execution_count": null,
"metadata": {},
"outputs": [],
"source": [
"distant_time = 2.0\n",
"while x.get_current_time() < distant_time:\n",
" x.update()"
]
},
{
"cell_type": "markdown",
"metadata": {},
"source": [
"View the final state of the temperature field:"
]
},
{
"cell_type": "code",
"execution_count": null,
"metadata": {},
"outputs": [],
"source": [
"np.set_printoptions(formatter={\"float\": \"{: 5.1f}\".format})\n",
"x.get_value(\"plate_surface__temperature\", temperature_flat)\n",
"print(temperature_flat.reshape(shape))"
]
},
{
"cell_type": "markdown",
"metadata": {},
"source": [
"Note that temperature isn't conserved on the plate:"
]
},
{
"cell_type": "code",
"execution_count": null,
"metadata": {},
"outputs": [],
"source": [
"print(temperature_flat.sum())"
]
},
{
"cell_type": "markdown",
"metadata": {},
"source": [
"End the model:"
]
},
{
"cell_type": "code",
"execution_count": null,
"metadata": {},
"outputs": [],
"source": [
"x.finalize()"
]
}
],
"metadata": {
"kernelspec": {
"display_name": "Python 3 (ipykernel)",
"language": "python",
"name": "python3"
},
"language_info": {
"codemirror_mode": {
"name": "ipython",
"version": 3
},
"file_extension": ".py",
"mimetype": "text/x-python",
"name": "python",
"nbconvert_exporter": "python",
"pygments_lexer": "ipython3",
"version": "3.10.5"
}
},
"nbformat": 4,
"nbformat_minor": 1
}

0 comments on commit 44c7d4c

Please sign in to comment.