Tutorial
=========
This section describes how to use BETR-Research for global scale calculations of semi-volatile organic chemical fate and transport. Here, the reimplementation of `BETR-Global `_ is utilized. This section does not describe how to create new models or change the BETR-Global parametrization. However, after working through this tutorial, it should be obvious how to do that. For questions or if you encounter problems do not hesitate to :doc:`contact ` me.
.. contents::
Download & Installation
-----------------------
Make sure you have the necessary :ref:`software dependencies ` installed.
Do one of the following:
* Download the latest release `here
`_ and unpack it into a
directory of your choice, for example "~/betrs"::
tar zxvf betrs.tar.gz ~/betrs
**Windows users**: You operating system might not have a programm
for unpacking archives. In that case, install `7-Zip
`_.
.. centered:: OR
* Get the latest development tree via `SVN
`_ from the repository:
``svn co https://betrs.svn.sourceforge.net/svnroot/betrs/trunk ~/betrs``
There is no installation procedure necessary. The topmost directory of
the tree contains directories for different model
incarnations. Currently there is only one, *BETR-Global*. All
commands, scripts or interactive sessions should be run from this
root-directory of the current model (here :file:`BETR-Global`). In the
following, pathnames are given relative to this directory.
Input Files
-----------
.. note:: For a standard BETR-Global run, ignore points 4--7 below
1. :file:`Chemicals/chemicals_default.txt` is the database of chemicals. The
file is self-documenting. Look up the ID (first column) of the
chemical you want to model. In this example we will use **PCB-118**
with ID **11**. This database of chemicals can be extended by adding
more lines at the end. It is important that each chemical has a unique
ID. You should not change chemical properties of substances in
chemicals_default.txt. Instead, create a new chemical database with a
different name.
2. :file:`Control/control_default.txt` contains parameters affecting
the model run. Currently there are two options:
**aerosoldeg** indicates whether chemicals sorbed to aerosols
should be shielded from degradation processes (0) or not
(1). Usually, "0" seems to be a good choice [GOETZ2008]_ .
**dumpDmatrices** indicates whether the matrices of D-values should
be written to a file (1) or not (0). If 1, a list of 12 sparse
2016x2016 - matrices is written to
:file:`Output/default/matrixdump.cpk` in `cPickle-format
`_. Each matrix is
the state matrix for one month of the year. Entries have the
units [mol/h]. Rows and columns correspond to region/compartment
combinations (cells) of the model. The matrix entry (*ij*) is the
mass rate constant of transfer from cell *j* to cell *i*. The
functions :func:`~helpers.cell2regcomp` and
:func:`~helpers.tocell` can be used to translate rows and column
indices into regions and compartments and vice versa.
3. :file:`Emissions/emissions_{x}.txt` contain descriptions of
the emissions. The files are
self-descriptive. :file:`emissions_default.txt` is an example for
emissions that only occur in the first month,
:file:`emissions_firstyear.txt` an example for emissions occuring
during the first year. Use these files as templates to create your
own emission files with different (arbitrary) names.
4. :file:`Environment/const_parameters_default.txt` and
:file:`Environment/seasonal_parameters_default.txt` contain
temporally constant and seasonally changing environnmental
parameters, respectively. The files are self-descriptive. They need
not be changed for a standard BETR-Global run.
5. :file:`Flows/default/flow{xy}.txt` contain flow-matrices for
convective transport in transport media like air and water. *x* and
*y* refer to the compartment IDs of the source and the target
compartment, respectively. For example :file:`flow45.txt` describes
the flows from freshwater to ocean water, :file:`flow11.txt`
describes the flow in the upper atmosphere. The files are
self-descriptive. They need not be changed for a standard
BETR-Global run.
6. :file:`Environment/compartments_default.txt` contains the
compartment names and associates them with their ID and with
certain environmental parameters. The file is self-descriptive. It
need not be changed for a standard BETR-Global run.
7. :file:`Processes/processes_default.txt` conatins a list of the
processes to be considered. The file is self-descriptive. It need
not be changed for a standard BETR-Global run.
Example session
----------------
The example session described here is already contained in the file :file:`testrun.py`.
Open an `IPython `_ shell and ``cd`` into
the *BETR-Global* root directory. Alternatively, you might want to use a
different Python environment. For Emacs users we found the combination
of `ipython.el `_ and
`python-mode.el `_ particularly
comfortable and powerful. There is a `large number of Python IDEs
`_
available.
1. **import numpy and the BETRS - module**::
from numpy import *
from BETRS import *
2. **Initialize a model** with chemical ``11``
(PCB-118, see :file:`Chemicals/chemicals_default.txt`)::
m=Model(11)
It will take some seconds until the model has been built. There
are optional parameters that can be passed to the init-routine of
``Model`` to choose a parameterizations different from the default
(see :class:`BETRS.Model`).
3. **read emissions** from :file:`emissions\_default.txt`::
m.update_emissions('emissions_default.txt')
4. **solve for steady-state**::
m.solve_ss()
To achieve a steady-state, the system matrix has to be time
invariant. This is achieved by averaging the 12 monthly matrices of
mass rate constants into one matrix that is representative for the
whole year. The emission file for the steady-state in interpreted
in a special way: Since emissions have to be constant, only the
first column of :file:`emissions\_default.txt` is considered and
interpreted as continuous emission of infinite duration.
5. **Write the output of steady-state results** as concentration and absolute mass::
m.output_ss(units=['mol_per_m3', 'kg'], netcdf=True)
This creates the files:
1. :file:`Output/default/ss_out.cpk` contains a dictionary with
keys 1--7, corresponding to the 7 compartments. Each value is again
a directory with keys corresponding to the chosen units, in this
case *'mol_per_m3'* and *'kg'*. The content of this directory is a
vector of steady-state data with 288 elements, correponding to the
:ref:`288 regions ` of *BETR-Global*. Refer to
:meth:`~BETRS.Model.output_ss` for a complete documentation.
6. **Data anaysis**: If you want for example look at the latitudinal
concentration distibution in lower air, do the following::
result=load('Output/default/ss_out.cpk')
c=result[2]['mol_per_m3']
cgrid=c.reshape(12,24)
clat=mean(cgrid, axis=1)
from pylab import *
plot(clat); show()
to get this graph:
.. figure:: images/latprofile_PCB118.png
:alt: latitudinal profile
There are methods to let you extract the whole averaged system
matrix and the steady-state emission vector::
ssmat=m.get_avgMatrix()
ssem=m.get_ssEmission()
Now the *overall peristence* defined as residence time at steady
is easily calculated::
Pov = sum(m.ss_res)/sum(ssem.toarray())/24
print("Overall persistence of %s:") % (m.chemdict['Name'])
print("%s days") % (Pov)
It is trivial to extract flow data, for example to look at the mass
balance of soil (compartment 6) in region 158 (Africa)::
## get full steady-state mass vector for flows from and to soil
soilflow_to=ssmat[tocell(158,6,m),:]*m.ss_res
soilflow_from=ssmat[:,tocell(158,6,m)]*m.ss_res[tocell(158,6,m)]
## flows from soil
happens=cell2regcomp(where(soilflow_to > 0 )[0],m)
print("Flows happens to soil to compartments %s") %(happens[1])
print("in regions %s:") % (happens[0])
balance_to=soilflow_to[where(soilflow_to > 0 )[0]]
print(balance_to)
## flows to soil
happens=cell2regcomp(where(soilflow_from > 0 )[0],m)
print("Flows happens from soil to compartments %s") %(happens[1])
print("in regions %s:") % (happens[0])
balance_from=soilflow_from[where(soilflow_from > 0 )[0]]
print(balance_from)
## degradation
deg=sum(soilflow_from)
## print the total mass-balance
print(" ***** net balance ****")
balance=(soilflow_to-soilflow_from)[where(soilflow_from > 0 )[0]]
print("compatment: 2 3 4")
print(" "+str(balance))
print("degradation loss: %s") % (deg)
and produce a bar-plot::
import pylab
pos=array([0,1,2,3])
posc=pos+0.4
fig=barh(pos,height=0.8,width=insert(balance,0,deg))
yticks(posc,('degradation','air','vegetation','freshwater'))
show()
.. figure:: images/massbalance.png
:alt: massbalance
7. To **solve the model with transient emissions**, let's first load a
different emission scenario that has emissions during the whole first
year after which emissions are shut off::
m.update_emissions('emissions_firstyear.txt')
Then update (initialize) the solver, solve for 5 years and write
the output::
m.update_solver()
m.solve_dyn(5)
m.output_dyn(units=['mol','mol_per_m3','kg','Pa'],netcdf=True)
Load the result and plot the timeseries of concentrations in
Northern European (region 38) lower air (compartment 2)::
dynresult=load('Output/default/dyn_out.cpk')
plot(dynresult[2]['mol_per_m3'][37,:])
Note that the array index corresponding to region 38 is 37, because
Numpy-array indices start with zero.
.. figure:: images/air2concNE.png
:alt: time-series concentration
Compare that to a plot on the log-scale::
plot(log(dynresult[2]['mol_per_m3'][37,:]))
.. figure:: images/logair2concNE.png
:alt: time-series log-concentration
Refer to the :doc:`source code <./Source>` for more details.