BMI Live!

Let's use this notebook to test our BMI as we develop it.

Setup

Before we start, make sure you've installed the bmipy package:

$ conda install bmipy -c conda-forge

Also install our bmi-live package in developer mode:

$ python setup.py develop

Last, a pair of imports for later:


In [1]:
import os
import numpy as np

Test the BMI methods

Start by importing the BmiDiffusion class from the bmi-live package:


In [2]:
from bmi_live import BmiDiffusion

Create an instance of the model's BMI.


In [3]:
x = BmiDiffusion()

What's the name of this component?


In [4]:
print(x.get_component_name())


Diffusion model

Show the input and output variables for the component:


In [5]:
print(x.get_input_var_names())
print(x.get_output_var_names())


('plate_surface__temperature',)
('plate_surface__temperature',)

Locate a sample configuration file included with the bmi-live package:


In [6]:
from bmi_live import data_directory
cfg_file = os.path.join(data_directory, 'diffusion.yaml')

Use the sample configuration to initialize the Diffusion model through its BMI:


In [7]:
x.initialize(cfg_file)

Check the time information for the model.


In [8]:
print('Start time:', x.get_start_time())
print('End time:', x.get_end_time())
print('Current time:', x.get_current_time())
print('Time step:', x.get_time_step())
print('Time units:', x.get_time_units())


Start time: 0.0
End time: 1.7976931348623157e+308
Current time: 0.0
Time step: 0.16666666666666666
Time units: s

Next, get attributes of the grid on which the temperature variable is defined:


In [9]:
grid_id = x.get_var_grid('plate_surface__temperature')
print('Grid id:', grid_id)
grid_rank = x.get_grid_rank(grid_id)
print('Grid rank:', grid_rank)
grid_shape = np.ndarray(grid_rank, int)
x.get_grid_shape(grid_id, grid_shape)
print('Grid shape:', grid_shape)
grid_spacing = np.ndarray(grid_rank, float)
x.get_grid_spacing(grid_id, grid_spacing)
print('Grid spacing:', grid_spacing)
print('Grid type:', x.get_grid_type(grid_id))


Grid id: 0
Grid rank: 2
Grid shape: [7 9]
Grid spacing: [1. 1.]
Grid type: uniform_rectilinear_grid

Get the model's initial temperature field through the BMI:


In [10]:
temp = np.ndarray(grid_shape).flatten()  #flattened!
x.get_value('plate_surface__temperature', temp)
print(temp.reshape(grid_shape))  # dimensional


[[0. 0. 0. 0. 0. 0. 0. 0. 0.]
 [0. 0. 0. 0. 0. 0. 0. 0. 0.]
 [0. 0. 0. 0. 0. 0. 0. 0. 0.]
 [0. 0. 0. 0. 0. 0. 0. 0. 0.]
 [0. 0. 0. 0. 0. 0. 0. 0. 0.]
 [0. 0. 0. 0. 0. 0. 0. 0. 0.]
 [0. 0. 0. 0. 0. 0. 0. 0. 0.]]

Add an impulse to the initial temperature field:


In [11]:
temp[20] = 100.0
x.set_value('plate_surface__temperature', temp)

Check that the temperature field has been updated:


In [12]:
x.get_value('plate_surface__temperature', temp)
print(temp.reshape(grid_shape))


[[  0.   0.   0.   0.   0.   0.   0.   0.   0.]
 [  0.   0.   0.   0.   0.   0.   0.   0.   0.]
 [  0.   0. 100.   0.   0.   0.   0.   0.   0.]
 [  0.   0.   0.   0.   0.   0.   0.   0.   0.]
 [  0.   0.   0.   0.   0.   0.   0.   0.   0.]
 [  0.   0.   0.   0.   0.   0.   0.   0.   0.]
 [  0.   0.   0.   0.   0.   0.   0.   0.   0.]]

Now advance the model by a single time step:


In [13]:
x.update()

View the new state of the temperature field:


In [14]:
x.get_value('plate_surface__temperature', temp)
print(temp.reshape(grid_shape))


[[ 0.     0.     0.     0.     0.     0.     0.     0.     0.   ]
 [ 0.     0.     3.125  0.     0.     0.     0.     0.     0.   ]
 [ 0.     3.125 87.5    3.125  0.     0.     0.     0.     0.   ]
 [ 0.     0.     3.125  0.     0.     0.     0.     0.     0.   ]
 [ 0.     0.     0.     0.     0.     0.     0.     0.     0.   ]
 [ 0.     0.     0.     0.     0.     0.     0.     0.     0.   ]
 [ 0.     0.     0.     0.     0.     0.     0.     0.     0.   ]]

There's diffusion!

Advance another step:


In [15]:
x.update()

View the new state of the temperature field (with help from np.set_printoptions):


In [16]:
x.get_value('plate_surface__temperature', temp)
np.set_printoptions(formatter={'float': '{: 6.2f}'.format})
print(temp.reshape(grid_shape))


[[  0.00   0.00   0.00   0.00   0.00   0.00   0.00   0.00   0.00]
 [  0.00   0.20   5.47   0.20   0.00   0.00   0.00   0.00   0.00]
 [  0.00   5.47  76.95   5.47   0.10   0.00   0.00   0.00   0.00]
 [  0.00   0.20   5.47   0.20   0.00   0.00   0.00   0.00   0.00]
 [  0.00   0.00   0.10   0.00   0.00   0.00   0.00   0.00   0.00]
 [  0.00   0.00   0.00   0.00   0.00   0.00   0.00   0.00   0.00]
 [  0.00   0.00   0.00   0.00   0.00   0.00   0.00   0.00   0.00]]

Advance the model to some distant time:


In [17]:
distant_time = 5.0
while x.get_current_time() < distant_time:
    x.update()

View the new state of the temperature field:


In [18]:
x.get_value('plate_surface__temperature', temp)
print(temp.reshape(grid_shape))


[[  0.00   0.00   0.00   0.00   0.00   0.00   0.00   0.00   0.00]
 [  0.00   3.67   5.90   4.17   1.76   0.51   0.11   0.02   0.00]
 [  0.00   5.90   9.46   6.71   2.86   0.84   0.18   0.03   0.00]
 [  0.00   4.17   6.71   4.72   1.98   0.57   0.12   0.02   0.00]
 [  0.00   1.76   2.85   1.98   0.81   0.23   0.05   0.01   0.00]
 [  0.00   0.49   0.81   0.55   0.22   0.06   0.01   0.00   0.00]
 [  0.00   0.00   0.00   0.00   0.00   0.00   0.00   0.00   0.00]]

Finalize the model:


In [19]:
x.finalize()