boxmox

boxmox is a python interface for the chemical box model BOXMOX

Installation

pip install boxmox

Set the BOXMOX environmental variable in ~/.bashrc:

export BOXMOX_WORK_PATH=/where/you/want/boxmox/to/write/stuff/to/

Remember to close the shell and log in again for these changes to take effect.

Detailed instructions

using a clean Ubuntu 16.04.3 LTS installation

  1. Install the chemical box model BOXMOX:

    1. ensure gfortran is installed (superuser credentials necessary)

      ubuntu@ubuntu:~$ apt install gfortran
      
    2. ensure flex (including its static library libfl.a) and bison are installed (superuser credentials necessary)

      ubuntu@ubuntu:~$ apt install flex
      ubuntu@ubuntu:~$ apt install bison
      
    3. download and adapt the install_BOXMOX.bash file to match your needs

      Get the install script from https://boxmodeling.meteo.physik.uni-muenchen.de

      Edit its contents:

      FLEX=/usr/bin/flex
      FLEX_LIB_DIR=/usr/lib/x86_64-linux-gnu/
      
    4. run the BOXMOX install script

      ubuntu@ubuntu:~$ bash install_BOXMOX.bash
      
    5. as explained in the output of above command, set environment variables for future use in your ~/.bashrc file

    6. Close the shell and log in again to make sure everything works

      ubuntu@ubuntu:~$ prepare_BOXMOX_mechanism MOZART_4
      All necessary files and programs found.
      Running KPP.
      'Make'ing the model.
      Successfully created MOZART_4.exe
      

    Allright, this seems to work, and we have already prepared the MOZART-4 mechanism.

  2. Install Python and necessary packages (superuser credentials necessary)

    apt install python
    apt install python-pip
    apt install python-numpy
    apt install python-matplotlib
    
  3. Install the boxmox package

    pip install boxmox
    

    Set the BOXMOX environmental variable in ~/.bashrc:

    export BOXMOX_WORK_PATH=/where/you/want/boxmox/to/write/stuff/to/
    

    Remember to close the shell and log in again for these changes to take effect.

Check if it worked:

ubuntu@ubuntu:~$ python
Python 2.7.12 (...
...)
>>> import boxmox
>>> box = boxmox.Experiment('MOZART_4')
>>> box.run()
>>>

Command-line scripts

Plot boxmox result

BOXMOX experiment plotter.

usage: plot_BOXMOX_experiment [-h] [-e EXPERIMENTPATH] [-f OUTPUTFILE]
                              [--timeLimits TIMELIMITS]
                              species

Positional Arguments

species One or several (comma separated) species names to be plotted

Named Arguments

-e, --experimentPath
 

Path to the experiment to be used. Defaults to current directory.

Default: “./”

-f, --outputFile
 

Name (or full path) of the output (png) file

Default: “plot.png”

--timeLimits Time axis limits (as “min,max”) in time units.

Examples

A simple simulation of a chamber experiment based on one of the examples delivered with the BOXMOX installation.

# import the BOXMOX module
import boxmox

# make a new run, based on an example supplied by the BOXMOX installation
exp = boxmox.ExperimentFromExample('chamber_experiment')

# inspect namelist
print(exp.namelist)

# change some values
exp.namelist['tend'] = 3600.0 * 12.0 # 12 hours
exp.namelist['dt']   = 600.0         # 10 minutes

# inspect initial conditions
print(exp.input['InitialConditions'])

# change some values
exp.input['InitialConditions']['NO2'] = 0.020 # 20 ppbv NO2

# make a simulation
exp.run()

# load reference to matplotlib pyplot state machine
import matplotlib.pyplot as plt

# plot some concentrations
exp.plot(['O3', 'NO2', 'HNO3'])
plt.show()

An intermediate example creating an EKMA diagram through multiple runs with varying initial conditions.

# import the BOXMOX module
import boxmox
import numpy as np

# evaluate differences in run with different NO2 initial conditions
no2_ics  = np.linspace(0.01, 0.3,  20)
c2h4_ics = np.linspace(0.1, 2.000, 20)

X,Y      = np.meshgrid(no2_ics, c2h4_ics)
Z        = np.zeros_like(X)

# make a new experiment, set some values, run, and put the resulting O3 concentration in Z
def run_exp(out, x, y, no2_ic, c2h4_ic):
    exp = boxmox.ExperimentFromExample('chamber_experiment')
    exp.namelist['tend']    = 3600.0 * 1.0  # run time (s)
    exp.namelist['dt']      = 240.0         # time step (s)
    for spec, val in [ ('NO2', no2_ic),
                      ('NO'  , 0.1 * no2_ic),
                      ('C2H4', c2h4_ic) ]:
        exp.input['InitialConditions'][spec] = val
    exp.run()
    out[x, y] = exp.output['Concentrations']['O3'][-1]

# run all the experiments
nul = [ run_exp(Z, x, y, no2, c2h6) for x, no2 in enumerate(no2_ics) for y, c2h6 in enumerate(c2h4_ics) ]

import matplotlib.pyplot as plt

plt.contourf(Z, cmap = plt.cm.jet, vmin=abs(Z).min(), vmax=abs(Z).max(), extent=[c2h4_ics[0], c2h4_ics[-1],no2_ics[0], no2_ics[-1]] )
plt.title('BOXMOX EKMA diagram example')
plt.xlabel(r'C$_2$H$_4$ (ppmv)')
plt.ylabel(r'NO$_x$ (ppmv)')
plt.colorbar(label=r'O$_3$ (ppmv)')
plt.tight_layout()
plt.savefig('ekma.png')

API

Experiment

class boxmox.Experiment(mechanism)

A new BOXMOX experiment using a certain mechanism.

addInput(name, inp, overwrite=False)

Add input from InputFile object

addInputFromFile(name, fname, overwrite=False)

Add input from file

archive(archive_path)

Save BOXMOX experiment to archive path

plot(specs, **kwargs)

Shortcut to plotter.concentrations for quick timeline plotting

run(dumbOutput=False, asynchronous=False)

Run BOXMOX experiment

Parameters:
  • dumbOutput (bool) – Only load references to output files, instead of loading data? (faster, but not usable for analysis)
  • asynchronous (bool) – Run asynchronous?
input = None

Input files

log = None

Log file of the last run

mechanism = None

Chemical mechanism used

name = None

Unique ID

namelist = None

Namelist

output = None

Output files

path = None

Absolute file system path of the experiment

running

Check if simulation is running (if started with asynchronous=True).

class boxmox.ExperimentFromExample(example)

A BOXMOX experiment based on an example from the BOXMOX installation.

class boxmox.ExperimentFromExistingRun(path, filename='*')

A BOXMOX experiment using an existing experiment.

Input/Output

boxmox.InputFile(fpath=None, version=1.7)

Returns an instance of a BOXMOX input file class, either old format if version < 1.7 (class InputFileOrig), or the current file format (class InputFile17).

class boxmox.InputFile17(fpath=None, version=1.7)

A generic BOXMOX input file (>= v 1.7). Getting and setting of values works like a dictionary:

print(inp['O3'])
inp['O3'] = 0.040
read(fpath)

Read input file from path.

write(f=<open file '<stdout>', mode 'w'>, version=1.7)

Write to <f>. <f> can be file handle or other connection. Defaults to sys.stdout.

fpath = None

File path of the underlying file (if it exists (yet))

nanc

Number of ancillary variables.

nvar

Number of variables.

timeFormat = None

Time format (0: constant, 1: seconds since start, 2: hour of diurnal cycle)

class boxmox.InputFileOrig(fpath=None)

A generic BOXMOX input file (< 1.7). Getting and setting of values works like a dictionary:

print(inp['O3'])
inp['O3'] = 0.040
read(fpath)

Read input file from path.

write(f=<open file '<stdout>', mode 'w'>, version=1.0)

Write to <f>. <f> can be file handle or other connection. Defaults to sys.stdout.

fpath = None

File path of the underlying file (if it exists (yet))

nvar

Number of variables.

timeFormat = None

Time format (0: constant, 1: seconds since start, 2: hour of diurnal cycle)

class boxmox.ConcentrationOutput(fpath, vars=None)

Concentration time series

copy(target_path)

Copy output file to target_path

Parameters:target_path (str) – location where to copy the output file to.
rm()

Remove output file

simplified(items=None)

Get simple 2D NumPy array of concentration vs. time for <items>

write(f=<open file '<stdout>', mode 'w'>)

Write contents of Output into file

Parameters:f (File) – file object or stream where to write to, defaults to sysout.
class boxmox.RatesOutput(fpath)

Reaction rate time series

copy(target_path)

Copy output file to target_path

Parameters:target_path (str) – location where to copy the output file to.
rm()

Remove output file

write(f=<open file '<stdout>', mode 'w'>)

Write contents of Output into file

Parameters:f (File) – file object or stream where to write to, defaults to sysout.
class boxmox.AdjointOutput(fpath, state=None)

Adjoint

copy(target_path)

Copy output file to target_path

Parameters:target_path (str) – location where to copy the output file to.
rm()

Remove output file

sensitivity(state, obs)

A BOXMOX adjoint output file is taken and the matrix of the adjoints of the species in the state vector is loaded (<adj_mat>: with the function read_adjoint). With <adj_mat> (= dX(t_final)/dY(t_initial)) the adjoint sensitivities of the species in the state vector to the observed species are calculated by using the chain rule.

Calculation of adjoint sensitivities by using adjoints:

dX(t_final)/dY(t_final) = dX(t_final)/dY(t_initial) * (dY(t_final)/dY(t_initial))^-1

where: X state species
Y observed species
Parameters:
  • fname (str) – BOXMOX adjoint output file
  • state (str/list) – State vector; single species or list of species which exists/exist in the BOXMOX run
  • obs (str/list) – Observed species; single species or list of species which exists/exist in the BOXMOX run
Returns:

adjoint sensitivity of the species in the state vector to the observed species

Return type:

numpy.ndarray (dim_obs, dim_state)

write(f=<open file '<stdout>', mode 'w'>)

Write contents of Output into file

Parameters:f (File) – file object or stream where to write to, defaults to sysout.
class boxmox.JacobianOutput(fpath)

Jacobian time series

copy(target_path)

Copy output file to target_path

Parameters:target_path (str) – location where to copy the output file to.
rm()

Remove output file

write(f=<open file '<stdout>', mode 'w'>)

Write contents of Output into file

Parameters:f (File) – file object or stream where to write to, defaults to sysout.
class boxmox.HessianOutput(fpath)

Hessian time series

copy(target_path)

Copy output file to target_path

Parameters:target_path (str) – location where to copy the output file to.
rm()

Remove output file

write(f=<open file '<stdout>', mode 'w'>)

Write contents of Output into file

Parameters:f (File) – file object or stream where to write to, defaults to sysout.

Namelist

class boxmox.Namelist(path=None)

A BOXMOX (Fortran 90) namelist. Getting and setting of values works like a dictionary:

print(nml['tstart'])
nml['tstart'] = 12.0
read(path)

Read namelist from file.

write(path)

Write namelist to file.