\section{A patch-based heat equation solver}

\chapterDescription
  {
    60 minutes.
  }
  {
    Chapter \ref{chapter:quickstart}.
  }

In this section, we sketch how to realise a simple explicit heat equation
solver that is based upon patches.
The idea is that we embed a small regular Cartesian grid into each individual
spacetree leaf.
This patch is surrounded by a halo/ghost cell layer holding copies from
neighbouring patches.

\begin{center}
  \includegraphics[width=0.4\textwidth]{44_patch-based-solver/patches.pdf}
\end{center}

In the sketch, we enbed $4\times 4$ patches into the spacetree cells.
Two cells (blue and green) are illustrated.
Each patch is surrounded by a halo layer of size one.
We will write the code to work within the patches, while the layers around the
patches will hold copies of the neighbouring patches and thus couple them.

For this endeavour, we need the toolbox \texttt{multiscalelinkedcell} that you
can download from the Peano webpage.
We assume that the whole toolbox is unzipped into a directory
\texttt{multiscalelinkedcell} which is held by your source directory.

\subsection{Preparation}

We start with the creation of a file \texttt{PatchDescription.def} in your
project's root directory.
In our example, each patch solely shall hold one array of unknowns $u$ that are
associated to the vertices of the patch.
So each patch will have exactly $(4+2+1)^2$ unknowns (the four is the size,
there's two halo cells along each coordinate axis, and then there's finally one
more vertex than there are cells).
Besides the unknowns called $u$, we also store the position and size as well as
the level with each patch---well-aware that level and size are kind of
redundant.

\begin{code}
#include "peano/utils/Globals.h"

Packed-Type:  int;

Constant: DIMENSIONS;

/**
 * A cell description describes one individual patch of the overall grid, i.e.
 * it holds pointers to the actual data of the patch (arrays) and its meta data
 * such as time stamps. Each unrefined node of the spacetree, i.e. each leaf,
 * holds exactly one instance of this class.
 */
class myprojectname::records::PatchDescription {
  /**
   * Two pointers to float arrays.
   */
  parallelise persistent int     u;
  /**
   * I need level and offset to be able to determine the source and image in
   * the adaptive case.
   */
  parallelise persistent int     level;
  parallelise persistent double  offset[DIMENSIONS];
  parallelise persistent double  size[DIMENSIONS];
};
\end{code}

Please note that $u$ is modelled as integer.
Actually, we do not hold the data directly within the patch description but we
make the patch description hold a pointer to the actual data.
The data will be managed by Peano on the heap.
The heap uses integers as pointers.
They are actually hash map indices.

Our system design is as follows:
\begin{itemize}
  \item Each cell holds a pointer to one \texttt{PatchDescription}.
  \item The \texttt{PatchDescription} holds a pointer to the actual patch data
  and comprises some additional meta data (such as the level).
  \item Each vertex holds $2^d$ pointers to the
  \texttt{PatchDescription} instances belonging to the adjacent cells.
\end{itemize}

Whenever we enter a cell, we can thus take its patch description, and get the
actual data from this description.
Alternatively, we can use the cell's $2^d$ adjacent vertices.
As they know the adjacent patch descriptions, we can also get the data
associated to cell neighbours and thus befil the ghost layers, e.g.

Take the Peano description file of our project ensurte that it contains the
following lines:
\begin{code}
heap-dastgen-file: PatchDescription.def

[...]

vertex:
  dastgen-file: Vertex.def
  read vector2PowD(int): PatchIndex
  write vector2PowD(int): PatchIndex

[...]

event-mapping:
  name: Mapping1

event-mapping:
  name: Mapping2

[...]

adapter:
  name: Adapter1
  merge-with-user-defined-mapping: Mapping1
  merge-with-predefined-mapping: MultiscaleLinkedCell(PatchIndex)

adapter:
  name: Adapter2
  merge-with-user-defined-mapping: Mapping2
  merge-with-predefined-mapping: MultiscaleLinkedCell(PatchIndex)
\end{code}

Managing all the adjaceny data (making each vertex point to the right patch)
obviously is a tedious task.
The \texttt{multiscalelinkedcell} toolbox fortunately does most of the stuff for
us, if we augment each adapter with a predefined mapping, tell this mapping what
the attribute for the patch handling will be (\texttt{PatchIndex}), and augment
the vertex accordingly.
Finally, open \texttt{Vertex.def} and augment it accordingly:

\begin{code}
#include "peano/utils/Globals.h"

Packed-Type:  int;

Constant: TWO_POWER_D;

class myprojectname::records::Vertex {
  /**
   * These guys are pointers to the adjacent cells. Actually, they do not point
   * to the neighbouring cells but to the heap indices associated to these cells.
   * These heap indices reference one or several instances of PatchDescription.
   */
  expose persistent int patchIndex[TWO_POWER_D];

  [...]
};
\end{code}

We run the translation process and add the toolbox directory to the PDT call:
\begin{code}
 java -jar <mypath>/pdt.jar <mypath>/project.peano-specification <mypath> \
 <mypath>/usrtemplates:<mypath>/multiscalelinkedcell
\end{code}

The PDT in collaboration with the toolbox will now create code that makes each
vertex track the \texttt{patchIndex} value of the adjacent cells.
If you change your grid, the indices are updated automatically, as long as you
merge \texttt{MultiscaleLinkedCell} into your adapters.
To make the code compile, you finally have to add a routine
\begin{code}
  int getPatchIndex() const;
\end{code}
to your Cell class.
Make the routine return the value of an attribute \texttt{persistent int
patchIndex} that you add to your \texttt{Cell.def}.
Set this field to -1 in the default constructor.

\subsection{Setting up the patches}

Before we start any coding, we have to specify which heaps we want to use to
administer the patch description objects and the actual $u$ data.
One option is to define this centrally in the \texttt{Cell.h} file that is
generated by the PDT:
\begin{code}
#include "peano/heap/Heap.h"
#include "<mypath>/records/PatchDescription.h"

namespace myprojectsnamespace {
  class Cell;

  typedef peano::heap::PlainHeap< myprojectsnamespace::records::PatchDescription >
    PatchDescriptionHeap;
  typedef peano::heap::PlainDoubleHeap                                    DataHeap;
}
\end{code}

\noindent
In this setup, we use the plain heap from Peano's heap directory to administer
both the data and the patch descriptions.
There are several other, more sophisticated, heap implementations available.
While they allow you to tune your code for special purposes, the plain heap
typically is a good starting point.

To set up the patches, we create plug into the mapping creating our grid.
Alternatively, we can first create the grid and then outsource the patch
initialisation into an additional mapping.
In any case, I strongly encourage you to initialise the heap as a first step.
This is however optional:
\begin{code}
void myprojectsnamespace::mappings::InitPatches::beginIteration(
  ...
) {
  logTraceInWith1Argument( "beginIteration(State)", solverState );

  PatchDescriptionHeap::getInstance().setName( "patch-description-heap" );
  DataHeap::getInstance().setName( "data-heap" );

  logTraceOutWith1Argument( "beginIteration(State)", solverState);
}
\end{code}
So far, each cell points to index -1 as patch description index, and each vertex
knows that all adjacent cells point to -1. We change this now as we plug into
\texttt{enterCell} and introduce a new operation in Cell:

\begin{code}
void myprojectsnamespace::mappings::InitPatches::enterCell(
  ...
) {
  fineGridCell.init( ... ); // please pass through the level, the offset and the size
}

void myprojectsnamespace::Cell::initCellInComputeTree( ... ) {
  const int newPatchIndex = PatchDescriptionHeap::getInstance().createData(1);
  _cellData.setPatchIndex( newPatchIndex );
  assertion( newPatchIndex>=0 );
  ...
}

\end{code}

\noindent
We finally befill the patch data, i.e.~replace the dots in
\texttt{initCellInComputeTree}.
This is a three-fold process.
First, we initialise all the meta data.
Second, we create the real patch.
Finally, we make the meta data record point to this data, while
the cell itself points to the \texttt{PatchDescription} instance.

\begin{center}
  \includegraphics[width=0.5\textwidth]{44_patch-based-solver/data.pdf}
\end{center}

\noindent
It is up to you to specificy the semantics of the data arrays used.
They can represent overlapping or non-overlapping patches.
It just has paid off not to make any overlap exceed any neighbouring cell on the
same level.
The introductory sketch of this chapter illustrates $4\times 4$ patches with a
ghost layer/overlap of one.
A code for this setup might read as follows:

\begin{code}
void myprojectsnamespace::Cell::initCellInComputeTree( ... ) {
  const int numberOfPatchDescriptionsPerCell = 1;
  const int newPatchIndex = PatchDescriptionHeap::getInstance().createData
    (numberOfPatchDescriptionsPerCell);
  _cellData.setPatchIndex( newPatchIndex );
  assertion( newPatchIndex>=0 );

  records::PatchDescription&  patchDescription =
    PatchDescriptionHeap::getInstance().getData(newPatchIndex)[0];

  patchDescription.setU( DataHeap::getInstance().createData(7*7) );
  patchDescription.setLevel(...);
  patchDescription.setOffset(...);
  patchDescription.setSize(...);
}

\end{code}

\begin{remark}
  There is absolutely no reason to restrict a code to use only the finest level
  of the spacetree. Furthermore, it might make sense to use different patch
  sizes in different cells of the same level. Please note that all the patch
  techniques also work if you store higher order DG shape functions in your
  cells, e.g.
\end{remark}

\subsection{Working with patches on regular grids}

As each cell points to patch description through its field \texttt{PatchIndex},
it is a natural choice to work with the associated patch data in
\texttt{enterCell}.
Before we actually do the work, we use the data from the
\texttt{PatchIndex} objects of the neighbouring cells to initialise our ghost
cells.
In our case, a simple copying does the job. In other situations, you might have
to implement more sophisticated projection operators.

\begin{code}
#include "multiscalelinkedcell/HangingVertexBookkeeper.h"
#include "multiscalelinkedcell/SAMRTools.h"
#include "peano/utils/Loop.h"
...
void pesplines::mappings::JacobiUpdate::enterCell( ... ) {
 if (
  !fineGridCell.isRefined()
  &&
  multiscalelinkedcell::HangingVertexBookkeeper::allAdjacencyInformationIsAvailable(
   VertexOperations::readPatchIndex(fineGridVerticesEnumerator,fineGridVertices)
  )
 ) {
  intialiseGhostLayerOfPatch(
    fineGridCell,
    fineGridVertices,
    fineGridVerticesEnumerator
  );

  solve(
    PatchDescriptionHeap::getInstance().getData( fineGridCell.getPatchIndex() )[0],
    fineGridVerticesEnumerator.getCellSize()
  );
 }
}
\end{code}

\noindent
The use of the predicate \texttt{allAdjacencyInformationIsAvailable} is too
careful here: it should always return \texttt{true}.
In dynamically adaptive settings, it can happen that adjacency information in
the vertices (i.e.~which patch descriptions are held by the adjacent cells) it
not up-to-date immediately.
In such a case, the branching would skip a cell with incomplete data and wait
for the next traversal where all information is available.

The initialisation of the ghost layer uses Peano's d-dimensional loops (the
code then should work for $d=3$ as well), it rather technical, but not too
difficult to understand as it realises plain copying at the end of the day.
Again, we use operations provided by the \texttt{multiscalelinkedcell} package:

\begin{code}
void pesplines::mappings::MatVec::intialiseGhostLayerOfCell(
 Cell&                                 fineGridCell,
 Vertex * const                        fineGridVertices,
 const peano::grid::VertexEnumerator&  fineGridVerticesEnumerator
) {
 const tarch::la::Vector<THREE_POWER_D,int> neighbourCellIndices =
  multiscalelinkedcell::getIndicesAroundCell(
   VertexOperations::readPatchIndex(fineGridVerticesEnumerator,fineGridVertices)
 );

 assertion3(
   multiscalelinkedcell::HangingVertexBookkeeper::allAdjacencyInformationIsAvailable(
    VertexOperations::readPatchIndex(fineGridVerticesEnumerator,fineGridVertices)
   ),
   fineGridVerticesEnumerator.toString(),
   VertexOperations::readPatchIndex(fineGridVerticesEnumerator,fineGridVertices),
   neighbourCellIndices
 ); // no enty of neighbourCellIndices points to a patch description on the
    // heap that does not exist

 // we take data from surrounding patches and always write into the
 // patch in the center (destPatchDescription)
 records::PatchDescription& destPatchDescription =
  PatchDescriptionHeap::getInstance().getData( fineGridCell.getPatchIndex())[0];

 dfor3(i)
  // i does not point to the central patch (all entries 1) and is valid
  // i.e. we are not at the domain boundary, e.g.
  if (
   i!=tarch::la::Vector<DIMENSIONS,int>(1) &&
   neighbourCellIndices(iScalar) >
    multiscalelinkedcell::HangingVertexBookkeeper::InvalidAdjacencyIndex
  ) {
   assertion(neighbourCellIndices(iScalar)>=0);
   records::PatchDescription& srcPatchDescription
    = PatchDescriptionHeap::getInstance().getData( neighbourCellIndices(iScalar) )[0];

   // this if is always true as long as we work with a regular grid
   if (srcPatchDescription.getLevel()==destPatchDescription.getLevel()) {
    // so now write your well-suited for loop here that befill all entries
    // of the ghost layer of your patch. If the for loop determines the
    // indices destVertexIndex and srcVertexIndex specifying vertices within
    // the patch, then the loop body copying the data around reads as
    DataHeap::getInstance().getData(destPatchDescription.getU())
      [destVertexIndex]._persistentRecords._u =
     DataHeap::getInstance().getData(srcPatchDescription.getU())
      [srcVertexIndex]._persistentRecords._u;
   }
  }
 enddforx // counterpart of dfor3 (see documentation in source code)
}
\end{code}

\noindent
The texttt{dfor3(i)} runs over a $\{0,1,2\}^d$ domain.
In the loop body (that has to be terminated by a \texttt{enddforx} pragma), it
provides two loop counters: \texttt{i} is a d-dimensional integer vector where
each entry is from $\{0,1,2\}$.
Furthermore, it gives us another loop counter \texttt{iScalar} which runs from 0
through $3^d-1$, i.e.~is a linearisation of \texttt{i}.
All the macros are defined in \texttt{Loop.h}.

\texttt{getIndicesAroundCell} is a helper function that takes the $2^d$ adjacent
vertices of a cell.
It actually requires their \texttt{PatchIndex} entries which are automatically
set by the predefined mapping.
The helper tool returns an array with $3^d$ entries to be read as a $3^d$
integer field.
The first entry holds the patch index of the left bottom neighbour.
The second entry holds the patch index of the bottom neighbour.
The fourth entry holds the patch index of the left neighbour.
The fifth entry hold the patch index of the cell itself.
And so forth.
The operation works for any dimension.
Study its source code documentation for details.

How the actual copying is done depends on the semantics of your data.
It also depends on column-major or row-major storage formats for the patch data.
The implementation of the actual \texttt{solve} operation then finally is
straightforward: take the $u$-array and run through it. Again, a \texttt{dfor}
loop might simplify your code.
If you struggle with the \texttt{solve} operation, it might make sense to study
the plotting in the next section first.
It uses exactly the sketched loop of the patch entries.

\begin{remark}
  It is not clear a priori whether it is better to have overlapping patches or
  non-overlapping data structures. With overlaps, there's an additional memory
  overhead for redundant data and data has to be moved around in the preamble of
  \texttt{enterCell}, e.g. In return, the actual work on the patches can be
  realised on a continuous array; and thus benefit from vectorisation and
  parallel fors. Alternatively, one can not use any redundant data and instead
  access the neighbouring data indirectly. This makes the actual computation
  often more complicated (one has to analyse whether data is held within the
  patch of comes from an adjacent patch), but induces no memory overhead and
  perhaps reduces the stress on the memory subsystem.
\end{remark}

\subsection{Plotting}

We briefly sketch what rapid coding of the plotting of a patch-based solver
might look like.
For this, we rely on a mapping \texttt{Plot} that holds plotter classes from
Peano's plotter component.

\begin{code}
#include "tarch/plotter/griddata/blockstructured/PatchWriterUnstructured.h"

namespace pesplines {
  namespace mappings {
    class Plot;
  }
}

class pesplines::mappings::Plot {
  private:
    ...
    static int                  _snapshotCounter;

    tarch::plotter::griddata::blockstructured::PatchWriter*                      _writer;
    tarch::plotter::griddata::blockstructured::PatchWriter::SinglePatchWriter*   _patchWriter;
    tarch::plotter::griddata::blockstructured::PatchWriter::VertexDataWriter*    _uWriter;
};
\end{code}

\noindent
The implementation plugs into \texttt{beginIteration} and \texttt{endIteration}
to open the plotter or to write its data into a file, respectively.
Depending on the build type, we either plot binary data or we plot a plain text
file that is easier to debug.

\begin{code}
int ...::mappings::Plot::_snapshotCounter(0);

void ...::mappings::Plot::beginIteration(
  ...::State&  solverState
) {
  #if defined(Asserts) || defined(Debug)
  _writer = new tarch::plotter::griddata::blockstructured::PatchWriterUnstructured(
    new tarch::plotter::griddata::unstructured::vtk::VTKTextFileWriter() );
  #else
  _writer = new tarch::plotter::griddata::blockstructured::PatchWriterUnstructured(
    new tarch::plotter::griddata::unstructured::vtk::VTKBinaryFileWriter() );
  #endif
  _patchWriter            = _writer->createSinglePatchWriter();

  _uWriter         = _writer->createVertexDataWriter("u",3);
}

void ...::mappings::Plot::endIteration(
  ...::State&  solverState
) {
  _patchWriter->close();
  _uWriter->close();

  delete _uWriter;
  delete _patchWriter;

  _uWriter = 0;
  _patchWriter = 0;

  std::ostringstream snapshotFileName;
  snapshotFileName << "solution"
                   #ifdef Parallel
                   << "-rank-" << tarch::parallel::Node::getInstance().getRank()
                   #endif
                   << "-" << _snapshotCounter
                   << ".vtk";
  _writer->writeToFile( snapshotFileName.str() );

  _snapshotCounter++;

  delete _writer;
  _writer = 0;
}
\end{code}

\noindent
The heart of the plotting can be found in \texttt{enterCell} where the
actual patch data it piped into the solution plotter:

\begin{code}
void ...::mappings::Plot::leaveCell(...) {
 if ( !fineGridCell.isRefined() ) {
  assertion(PatchDescriptionHeap::getInstance().isValidIndex(fineGridCell.getPatchIndex()));
  const records::PatchDescription& patchDescription
   = PatchDescriptionHeap::getInstance().getData( fineGridCell.getPatchIndex() )[0];

  const std::pair<int,int> indexPair = _patchWriter->plotPatch(
    fineGridVerticesEnumerator.getVertexPosition(),
    fineGridVerticesEnumerator.getCellSize(),
    4+1 // number of inner cells per spacetree leaf
  );

  int unknownVertexIndex = indexPair.first;
  //int unknownCellIndex   = indexPair.second;

  dfor(i,4+1) {
   const tarch::la::Vector<DIMENSIONS,int> currentVertex = i + 1;
   const int linearisedCurrentVertex
    = peano::utils::dLinearisedWithoutLookup(currentVertex,4+1);
   const double u = DataHeap::getInstance().getData(patchDescription.getU())
    [linearisedCurrentVertex]._persistentRecords._u;

    _uWriter->plotVertex( unknownVertexIndex,u );
    unknownVertexIndex++;
  }
 }
}
\end{code}

\subsection{Adaptive grids}

We do not detail the handling of adaptivity with patches here.
However, the basic principle is extremely simple:
The toolbox's reconstruction algorithm is completely equipped to handle
resolution changes, i.e.~if a left neighbour resides of a cell resides on a
coarser level, the correct index is written into the left neighbour.

This implies that
\begin{enumerate}
  \item Several neighbour indices might be equal if neighbours reside on coarser
  levels.
  \item Fine grid cells always can read and write data from coarser adjacent
  cells.
  \item Fine to coarse information however also can be transported within the
  tree as any cell has at some stages access to its parent.
\end{enumerate}

\begin{remark}
Peano does not enforce any 2:1 balancing on the grid. However, such a balancing
might be desireable from an application point of view. You can either program
some balancing on your own, or you can merge the predefined mapping
\texttt{GridBalancer2to1} into your adapters.
\end{remark}

\subsection*{Further reading}

\begin{itemize}
  \item   Unterweger, K., Wittmann, R., Neumann, P., Weinzierl, T. and Bungartz,
  H.-J.
(2015), {\em Integration of FULLSWOF2D and PeanoClaw: Adaptivity and Local
Time-stepping for Complex Overland Flows}, in Mehl, M., Bischoff, M. and Sch\"afer,
M. eds, Lecture notes in computational science and engineering, 105 Part II: 3rd International Workshop on Computational Engineering CE 2014. Stuttgart, Germany, Springer, 181-195.
\item Weinzierl, Tobias, Wittmann, Roland, Unterweger, Kristof, Bader, Michael,
Breuer, Alexander and Rettenberger, Sebastian (2014), {\em Hardware-aware block
size tailoring on adaptive spacetree grids for shallow water waves}, in
Gr\"o\ss linger, Armin and K\"ostler, Harald eds, HiPEAC HiStencils 2014 - 1st
International Workshop on High-Performance Stencil Computations. Vienna, Austria.
\item Weinzierl, Tobias, Bader, Michael, Unterweger, Kristof and Wittmann,
Roland (2014). {\em Block Fusion on Dynamically Adaptive Spacetree Grids for
Shallow Water Waves}. Parallel Processing Letters 24(3): 1441006.
\end{itemize}


\chapter{Objectives and information in data}
\thispagestyle{fancy}
\label{ch:objectives-and-information-in-data}

\hrule
\begin{itemize}
\footnotesize
\item[]{Aims:}
\begin{enumerate}
\item{to be aware of the added value of carefully interpreting the results of
the parameter evolution;}
\item{to understand the effect of noise in the measurements;}
\item{to understand the effect of the distribution of observations in relation
to the model's local sensitivity (or system behavior);}
\item{to experience the added value of data transformations for parameter
identification;}
\item{to understand the consequences of model structural errors for the
parameter optimization process and result;}
\item{to experience the opportunities of multi-objective optimization.}
\end{enumerate}
\end{itemize}
\hrule
\vspace{1em}

Often people perform a model calibration, then they present the final model
result, and then\ldots they are done. But in fact the most interesting part of
inverse modeling is the interpretation of both the results of the evolution of
the parameter search and of the simulation results. In this chapter, we will
investigate the relation between model complexity, measurement error, and the
type of observations.

\section{Case: cubic model}

\smallq{Use the MATLAB editor to open `dreamWithCubicmodel.m' located in
`./exercise/dream-cubicmodel/'. After briefly studying the program, press F5 to
run it as provided with 14 data points (variables \mcode{xObs} and
\mcode{yObsNoisy}). Don't forget to save the results (check the code snippet on
page~\pageref{lst:save-print} or copy and paste in a PowerPoint presentation).}

\smallq{To identify the parameters of a 4-parameter model, 14 data points aren't
very many. How do you think the results will change if you increase the number
of data points? Check your hypothesis by setting \mcode{xObsStep} to 0.2.}

\smallq{Not only the number of the data points is important, but also the
distribution. Argue what would be the result if you wouldn't have had the data
points below x=3 (keep \mcode{xObsStep} at 0.2). Explain which parameters you
expect to be identified most accurately? Then check whether your hypothesis was
correct.}

\smallq{If you could do one more measurement between x=-1 and x=7, where would
you place it? Explain why.}

\smallq{What if you would have only the observations below x=3 (keep
\mcode{xObsStep} at 0.2)? Again, explain which parameters you expect to be
identified most precisely and then check whether your hypothesis was correct.}

\smallqo{If you would increase the magnitude of the error term
(\mcode{gaussTerm}), how will that affect the results? Check your hypothesis by
making the appropriate changes to the script.}

\section{Case: rainfall interception}

In this part, we will interpret the relation between data, model and selected
parameters using a simplified version of an existing rainfall interception model
\citep{bout-scha-aert-verm1996}. This version simulates canopy water storage
using one layer only. As with any model, it is important that you understand
both the concept of the model---including equations, parameters and boundary
conditions---as well as the measurements used in the inverse modeling; if you
don't, it is impossible to interpret the results.

Conceptually, the interception model is a very simple water balance of the
canopy. Water storage in the canopy (S) changes with time $t$, as a result of
precipitation (P), interception (I), drainage (D) and evaporation (E); see
Figure~\ref{fig:interception-model-flows} and
Equation~\ref{eq:interception-model}.
\begin{equation}
\label{eq:interception-model}
\frac{\Delta S}{\Delta t} = I-D-E
\end{equation}
\begin{tabular}{lll}
with:&&\\
$S$&canopy water storage&\textsf{mm}\\
$t$&time&\textsf{day}\\
$I$&interception rate&\textsf{mm$\cdot{}$day$^{-1}$}\\
$D$&canopy drainage rate&\textsf{mm$\cdot{}$day$^{-1}$}\\
$E$&canopy evaporation rate&\textsf{mm$\cdot{}$day$^{-1}$}\\
\end{tabular}

\begin{figure}[htbp]
  \centering
    \includegraphics[width=0.3\textwidth]{./eps/converted/interceptionmodel-flows}
  \caption{Definition of flows for the interception model.}
  \label{fig:interception-model-flows}
\end{figure}

\needspace{5\baselineskip}Precipitation and potential evaporation ($E_0$) are
the measured boundary conditions. The other fluxes are calculated as:
\begin{equation}
I=a\cdot{}P
\end{equation}
\begin{equation}
D =
\begin{cases}
b\cdot{}(S-c), & \text{if }S>c\\
0, & \text{if }S\leq{}c\\
\end{cases}
\end{equation}
\begin{equation}
E = d\cdot{}E_0\cdot{}\frac{S}{c}
\end{equation}
\begin{tabular}{lll}
{\bf parameter}&{\bf description}&{\bf units}\\
$a$&interception efficiency (canopy cover fraction)&\textsf{-}\\
$b$&canopy drainage efficiency&\textsf{day$^{-1}$}\\
$c$&canopy water storage capacity&\textsf{mm}\\
$d$&evaporation efficiency&\textsf{-}\\
\end{tabular}

Before optimizing the model parameters $a$, $b$, $c$ and $d$, you need to get a
better understanding of the meaning of each parameter, and its effect on the
model prediction. With this knowledge you will be able to choose a more
meaningful minimum and maximum parameter space and your optimization will
converge faster.

\smallq{Use the MATLAB editor to open `mancal\_interceptionmodel' located in
`./exercises/manual-calibration-interception-model/'. After pressing F5 to run
the script, a graphical user interface (GUI) will appear. If you run the model
with the input values $a$ = 0.6, $b$ = 200, $c$ = 2.5 and $d$ = 0.83, you will
get a plot similar to those in  Figure~\ref{fig:interceptionmodel-mancal-gui}.
Explain the output of this simulation:

\begin{itemize}
\item{why does the storage increase at $t$ = 0.75?}
\item{why does it reach a constant level?}
\item{why is this level 2.6?}
\item{why does this level change at $t$ = 1.0?}
\item{why does this level become 2.5?}
\item{why does the storage decrease at $t$ = 1.25?}
\item{explain the shape of the storage curve after $t$ = 1.25.}
\item{draw the canopy evaporation rate in
Figure~\ref{fig:interceptionmodel-mancal-gui}.}
\end{itemize}
}% smallq

\begin{sidewaysfigure}
%\begin{figure}[htbp]
  \centering
    \includegraphics[width=1.0\textheight]{./eps/converted/interceptionmodel-mancal-gui}
  \caption{Graphical user interface showing the model prediction for $a$ = 0.6,
$b$ = 200, $c$ = 2.5 and $d$ = 0.83, based on simplified boundary conditions.}
  \label{fig:interceptionmodel-mancal-gui}
%\end{figure}
\end{sidewaysfigure}

\smallq{Next we will alter the parameter values only one at a time (!) and
predict how the change affects the model result. So, choose a parameter, then
first draw your prediction in one of the subplots of
Figure~\ref{fig:interceptionmodel-mancal-gui}. Only after you've drawn your
prediction, change the parameter value in the GUI. Press the `Go' button to run
the interception model with the changed parameter. Try to explain why your
prediction diverges from the model result. This is a useful procedure to better
understand the behavior of a system.}

\smallq{Summarize the knowledge you gained about each parameter's effect on the
model result.}

\subsection{Distribution of information within the data}

Having done the manual calibration, you are ready to interpret the results of
the interception model with boundary conditions that are more realistic. In the
next few exercises, we will perform several DREAM calibrations of the
interception model using  different data sets.

As a first step, it is always wise to first check your inverse modeling design
with so-called `artificial measurements'. Artificial measurements are generated
by running the model with a known parameter set. Subsequent calibration of the
model to the artificial measurements should yield this same parameter set again.

\smallq{Use the MATLAB editor to open `dreamWithInterc.m' located in
`./exercises/dream-interception-model/'. By default this script uses the
simplified boundary condition that we used in the manual calibration. Run the
main script to check if the true parameters are found.}

\smallq{Now adapt your script to let it use the more realistic boundary
conditions, by uncommenting the appropriate parts in the script. Experiment with
different boundary conditions. Can you explain the differences between the
various data sets? And what is the difference between the realistic boundary
conditions on the one hand and the ideal case on the other?}

It is often interesting to calibrate your model parameters based on a subset of
the data. This way, you can get some idea of the type of information that is
needed to identify each model parameter with precision and accuracy. The generic
way to have DREAM use subsets, is by adding a field to \mcode{Extra} that
contains the observation times that you want to use as part of your objective
function:
\lstinputlisting[numbers=none,nolol,label={lst:subsetting-t-less-than-one}]{./../m/subsetting-t-less-than-one.m}
\needspace{3\baselineskip}Inside \mcode{interceptionmodel}, you can use the time
information to only export simulated storage values at the times specified in
\mcode{tObj}:
\lstinputlisting[numbers=none,nolol,label={lst:subsetting-modelside}]{./../m/subsetting-modelside.m}
\mcode{output} can subsequently be returned as the function's output argument,
after which DREAM will compare it to the contents of
\mcode{Measurement.MeasData}.

\needspace{15\baselineskip}After the optimization finishes, the script probably
throws an error in the visualization part. This is because the simulated time
series of storage now has less elements than \mcode{bounds(:,1)}. You can avoid
this by re-defining \mcode{Extra.tObj} just before re-running the last 1000
parameter sets:
\lstinputlisting[numbers=none,nolol,label={lst:subsetting-redefine-extra}]{./../m/interceptionmodel-subsets-redefine-extra.tobj.m}

\smallq{Adapt your script to let it use only the observations for which $t<1$
(simplified boundary conditions). Make sure that the storage values returned by
\mcode{interceptionmodel} refer to the times at which storage was observed. What
do you expect with regard to the identifiability of the parameters? Store the
results to be able to refer back to them later, for instance by copying and
pasting into a PowerPoint presentation.}

\smallq{\needspace{5\baselineskip}In the previous exercises, we have calibrated
to a time-based subset of the observations. However, you can also make a subset
based on certain characteristics of the data. For instance, make a subset based
on $S>2.2$~\textsf{mm} (use the `211' data), calibrate the interception model
and explain the results. Remember, you can add fields to \mcode{Extra} with
information you need inside your model's workspace. For instance, you could do:
\lstinputlisting[numbers=none,nolol,label={lst:subsetting}]{./../m/subsetting.m} }

\smallq{If you didn't already do this, adapt the script such that the simulated
canopy storage dynamics are visualized starting from t=211.41 through t=212.65.
Let your visualization differentiate between observations that are part of the
objective set and those that aren't. You should get a figure more or less like
Figure~\ref{fig:interception-model-subsets}.
\begin{figure}[htbp]
  \centering
    \includegraphics[width=1.0\textwidth]{./eps/converted/interceptionmodel-subset}
  \caption{Example of the interception model with objective based on high-storage
values only.}
  \label{fig:interception-model-subsets}
\end{figure}
}% smallq

\smallq{Describe the characteristics of a minimal data set with which the
parameters of the interception model can still be identified. Does the
measurement accuracy affect the minimal set?}

\subsection{Data transformations}

In this part, we will experiment with using different kinds of transformations.
For instance, squaring the observed data ($Y^2$) emphasizes the high values,
whereas $\sqrt{Y}$ and Box-Cox transforms ($\frac{Y^\lambda-1}{\lambda},
\lambda=0.3$) give more weight to lower (non-negative) values. Also, Box-Cox
transformations are often used when the error is known to be heteroscedastic
(i.e.~when the magnitude of the error is dependent on measurement value).
$log(Y)$ and $log_{10}(Y)$ should be avoided if Y-values of 0 can occur.

\smallq{Use the MATLAB editor to open `dreamWithHymodBoxCox.m' located in
`./exercises/dream-hymod-box-cox'. Despite its name, the script does not perform
a Box-Cox transform yet, but we'll get to that in a minute. First run the script
as provided and interpret the results.}

\smallq{What change in model performance or identifiability of parameters would
you expect if you apply the Box-Cox transform? Before running the script, we
need to make some small changes first. Of course, you need to transform the
observations as well as the model output. In order to  visualize the
optimization results, we need to adapt the model such that it can output either
the untransformed simulated storage or the transformed simulated storage,
depending on a flag \mcode{Extra.argOutIsTransformed} which can be \mcode{true}
or \mcode{false}. For instance:
\lstinputlisting[numbers=none,nolol,label={lst:argOutIsTransformed-modelside}]{./../m/argOutIsTransformed-modelside.m}
This is an easy way to use transformed data for the optimization, and
untransformed data for the subsequent visualization. Make the appropriate
changes in the program and check the answer you gave earlier.}

Another interesting transform is to use the derivative of the observations. This
can be particularly helpful with determining rates with respect to time.

\smallqo{What result do you expect if you apply the derivative transformation in
case of the cubic model?}

\smallq{Use the MATLAB editor to open `dreamWithIntercDerivative.m' located at
`./exercises/dream-interceptionmodel-derivative/'. As you can see, the objective
function operates on the derivative of storage. How do you think the prediction
will be different from the earlier results? Check your answer by running the
script.}

\section{Case: Easter Island population dynamics}

In the past few exercises we have seen that successful parameter identification
depends on what we call ``the information content of data''. It depends on:
\begin{enumerate}
\item{the signal/noise ratio (the higher the ratio, the faster the convergence
of the search procedure);}
\item{the sensitivity of the model for the parameters;}
\item{the distribution of the measurements in relation to this sensitivity.}
\end{enumerate}

Keep in mind that a model is never perfect and that deviations between model
output and observations is not by definition a Gaussian distribution. If the
model structure causes systematic errors, the inverse modeling procedure as used
until now will lead to a best fit while tuning the parameters. In this case the
optimal parameter values will compensate for the model structure error. In such
a case parameter identification produces the ``wrong'' (but optimal) parameter
values and convergence will also become slower.

To explore this effect in more detail, we will test a model of human population
and resources (trees/biomass) of Easter Island in the period 0-2000 AD. The
model is based on \citeauthor*{bran-tayl1998}~(\citeyear{bran-tayl1998}). The
governing equations and probable parameter values are as follows.

\needspace{15\baselineskip}

Rate of change of population:
\begin{equation}
\label{eq:easter-island-popgrowth}
\frac{dP}{dt} = (b+cr\cdot{}\frac{C}{P})\cdot{}P-(d-cr\cdot{}\frac{C}{P})\cdot{P}
\end{equation}
Rate of change of resources:
\begin{equation}
\frac{dR}{dt} = g\cdot{}(1-\frac{R}{Cc})\cdot{}R-C
\end{equation}
Consumption rate:
\begin{equation}
C = p\cdot{}P\cdot{}R
\end{equation}

\begin{tabular}{llll}
with:&&&\\
&\textbf{variable name as used}&\textbf{description}&\textbf{probable value}\\
&\textbf{in the model}&&\\
$P$&\mcode{Pop}&human population&\\
$R$&\mcode{Res}&resources (biomass)&\\
$b$&\mcode{parPopGrowth}&relative birth rate&0.02\\
$d$&\mcode{parDeathRate}&relative death rate&0.03\\
$Cc$&\mcode{parCarCap}&carrying capacity&160\\
$cr$&\mcode{parConsResponse}&consumption response&150\\
$g$&\mcode{parRelResGrowth}&relative growth rate of resources&0.004\\
$cr\cdot{}\frac{C}{P}$&\mcode{consProfit}&consumption profit&\\
$p$&\mcode{parFit}&labor efficiency constant&0--1e-6\\
\end{tabular}

\smallq{\needspace{15\baselineskip}Use the MATLAB editor to open
`dreamWithEasterModel.m' from `./exercises/dream-easter-island/'.
Figure~\ref{fig:pop-res-figures} shows 5 data sets that we have created using
the model described above. Experiment with calibrating the \mcode{eastermodel}
based on either population or resources data from any of the files listed below.
Assume an initial Population of 20, and an initial Resources value of 160. To
help the interpretation of the results, here are a few pointers on how the data
were created:
\begin{enumerate}
\item{`pop-res-data-ref.mat' is the reference file that contains the artificial
observations generated with the parameters mentioned above, with only very
little noise superimposed;}
\item{`pop-res-data-ref-noise.mat' is the same as (1), but with more noise;}
\item{`pop-res-data-variable-deathrate.mat' is a file that contains the
artificial observations generated with the parameters mentioned above, except
that the death rate parameter was changed to 0.035 for $t>700$. Because the
\mcode{eastermodel} does not incorporate this change, a structural error is
present in the model. Also, there's only very little noise superimposed;}
\item{`pop-res-data-variable-deathrate-noise.mat' is the same as (3), but with
more noise.}
\item{`pop-res-data-high-deathrate.mat' is the same as (1), but with
\mcode{parDeathRate=0.035}.}
\end{enumerate}
}

\smallq{Explain the high correlation between \mcode{parDeathRate} and
\mcode{parPopGrowth} in the results of the calibration.}

\smallq{What is the effect of the higher noise in the observations?}

\smallq{Set the value of \mcode{parPopGrowth} to 0.02 (i.e.~exclude it from the
optimization) to avoid the high correlation between \mcode{parDeathRate} and
\mcode{parPopGrowth}. How do you think this will affect the optimization process
and the accuracy of the optimized parameters (in comparison to the former case)?
Evaluate the result. Is this what you expected? If not, explain the difference.}

\smallqo{If you want to play with this some more, you can make your own
artificial data using `eastermodelArtifMeas.m'.}

\begin{figure}[htbp]
  \centering
    \includegraphics[width=1.0\textwidth]{./eps/converted/pop-res-figures}
  \caption{Resources-Population plots for the various files.}
  \label{fig:pop-res-figures}
\end{figure}

\needspace{15\baselineskip}

So far, we have calibrated the \mcode{eastermodel} based on either Population or
Resources, but you could also use both variables simultaneously. To do this, we
need to make some changes to the model:

\lstinputlisting[numbers=none,nolol,label={lst:weighted-error-series-modelside}]{./../m/weighted-error-series-modelside.m}

With this code, the model returns an error series, rather than the states
themselves, so the objective function should no longer compare model output with
observations; instead, we now want to minimize the model output. A simple way to
accomplish this is by setting \mcode{Measurement.MeasData} to
\mcode{zeros(size(PopMeas))}.

\smallq{Use the MATLAB editor to open `dreamWithEasterModelMO.m' from
`./exercises/dream-easter-island-mo/'. Make the appropriate changes to the
program in order to use both Population and Resources information. Set
\mcode{Extra.popWeight} to 1.0 for now (i.e.~ignoring the misfit on Resources)
and don't forget to initialize \mcode{Extra.argOutIsErr} as well. With this
weighting factor, your result should be similar to that of a single-objective
optimization (when the objective function operates on Population). Run the
script. Store your results.}

\smallq{Now do the same thing, but with all weight on the Resources. Again,
store the result.}

\smallq{Repeat one more time, but with half the weight on the Population and
half the weight on Resources. Store the result. Explain why the last result
looks much more like the result of \mcode{Extra.popWeight=1.0} than that of
\mcode{Extra.popWeight=0.0}.}

\smallq{How would you make sure that Population and Resources are treated as
equally important variables when \mcode{Extra.popWeight=0.5}? Implement your
solution and check if there is any difference with your earlier results.}

\smallq{Adapt the script to let it use the Resources data from
`pop-res-data-ref.mat' and the Population data from
`pop-res-data-high-deathrate.mat' with:
\lstinputlisting[numbers=none,nolol,label={lst:load-selected-variables}]{./../m/load-selected-variables.m}
Run the script for \mcode{Extra.popWeight} equal to 1.0, 0.0, and 0.5. Explain
the results. }%smallq

\smallqo{Looking back at the single-objective exercises that we have done
earlier this week, which one do you think would benefit from a multi-objective
approach? Explain what variables you would use in the calibration and which
objectives you would use (and why) before implementing it.}

\section{Multi-objective optimization of HYMOD}

\smallqo{In the directory `./exercises/hymod-so/' you will find the files to
apply the SCE-UA algorithm \citep{duan-gupt-soro1992} to the HYMOD model. We use
the same data as in previous exercises (Leaf River, Mississippi), and we analyze
the data from a single year (1953). Open `CompOF.m' and verify what objective
function is being used in the current optimization. In a first step, compare the
root mean square error (RMSE) and the mean absolute error (MAE). Run SCE-UA and
save the best parameters and the associated model runs (BestSim and bestSets)
for both objective functions. Note that the objection function values for RMSE
and MAE are given at the end of the SCE-UA run. Are the optimized parameters
different for the two objective functions? Are the model predictions different?
Can you understand why?}

\smallqo{If you like, you can implement alternative objective functions. If you
need inspiration, you might want to take a look at Table~1 in
\citet{gupt-soro-yapo1998}; see the `./papers/' folder. Alternatively, you can
apply a Box-Cox transformation to the data. Again, can you understand why the
model parameters and model predictions are different? Is one of the optimized
parameter sets superior to another one?}

\smallqo{The Pareto front can be approximated by varying the weights $a$ and $b$
in the following objective function: $a*RMSE+b*MAE$. If $a=1$ and $b=0$, you
should get the same result as for the single-objective optimization with RMSE as
the objective function. Implement this weighted objective function in
\mcode{CompOF} and run the SCE-UA algorithm with different selections for the
parameters $a$ and $b$. Were you able to systematically explore the Pareto
front? Is this an efficient approach?}

\smallqo{In order to explore the Pareto front between the RMSE and the MAE more
accurately, we will apply the MOSCEM-UA algorithm to HYMOD. You can find the
code in the directory `./exercises/hymod-mo/'. The two objective functions are
defined at the end of \mcode{hymod}.}

\smallqo{You can start the algorithm by typing \mcode{runMOSCEM} at the command
prompt. Compare the results of MOSCEM-UA with those of the previous exercise.
Does MOSCEM-UA provide a good estimate of the Pareto front? Do the optimized
parameters vary systematically along the Pareto front? Can you draw any
conclusions about the model from this? Explore different objective functions.}

\smallq{Formulate 2 conclusions on the basis of today's activities:
\begin{enumerate}
\item{your most important conclusion;}
\item{a conclusion based on your findings, that you don't expect anyone else has
found.}
\end{enumerate}
}%smallq