From 6b292333250ce99ebc761589ed37e29f45a1d1a6 Mon Sep 17 00:00:00 2001
From: Bernd Flemisch <bernd@iws.uni-stuttgart.de>
Date: Tue, 27 Nov 2012 16:39:49 +0000
Subject: [PATCH] implicit branch: change directory structure. Add
 dumux/implicit directory. Copy models from boxmodels/model to implicit/model.
 Copy boxmodels/common to implicit/box. Copy ccmodels/common (from devel) to
 implicit/cellcentered. Copy boxmodels/common/box*.hh to
 implicit/common/implicit*.hh. Move test/boxmodels to test/implicit. Adapt
 configure.ac and Makefile.ams. Everything still builds.

git-svn-id: svn://svn.iws.uni-stuttgart.de/DUMUX/dumux/branches/implicit@9679 2fb0f335-1f38-0410-981e-8018bf24f1b0
---
 configure.ac                                  |  48 +-
 dumux/Makefile.am                             |   2 +-
 dumux/implicit/1p/1pindices.hh                |  45 +
 dumux/implicit/1p/1plocalresidual.hh          | 169 ++++
 dumux/implicit/1p/1pmodel.hh                  | 125 +++
 dumux/implicit/1p/1pproperties.hh             |  65 ++
 dumux/implicit/1p/1ppropertydefaults.hh       | 109 ++
 dumux/implicit/1p/1pvolumevariables.hh        | 203 ++++
 dumux/implicit/1p/Makefile.am                 |   4 +
 dumux/implicit/1p2c/1p2cfluxvariables.hh      | 494 +++++++++
 dumux/implicit/1p2c/1p2cindices.hh            |  63 ++
 dumux/implicit/1p2c/1p2clocalresidual.hh      | 297 ++++++
 dumux/implicit/1p2c/1p2cmodel.hh              | 326 ++++++
 dumux/implicit/1p2c/1p2cproperties.hh         |  68 ++
 dumux/implicit/1p2c/1p2cpropertydefaults.hh   |  96 ++
 dumux/implicit/1p2c/1p2cvolumevariables.hh    | 284 ++++++
 dumux/implicit/1p2c/Makefile.am               |   4 +
 dumux/implicit/2p/2pindices.hh                | 110 ++
 dumux/implicit/2p/2plocalresidual.hh          | 212 ++++
 dumux/implicit/2p/2pmodel.hh                  | 366 +++++++
 dumux/implicit/2p/2pproperties.hh             |  76 ++
 dumux/implicit/2p/2ppropertydefaults.hh       | 148 +++
 dumux/implicit/2p/2pvolumevariables.hh        | 279 +++++
 dumux/implicit/2p/Makefile.am                 |   5 +
 dumux/implicit/2p2c/2p2cfluxvariables.hh      | 246 +++++
 dumux/implicit/2p2c/2p2cindices.hh            | 129 +++
 dumux/implicit/2p2c/2p2clocalresidual.hh      | 383 +++++++
 dumux/implicit/2p2c/2p2cmodel.hh              | 825 +++++++++++++++
 dumux/implicit/2p2c/2p2cnewtoncontroller.hh   | 110 ++
 dumux/implicit/2p2c/2p2cproperties.hh         |  70 ++
 dumux/implicit/2p2c/2p2cpropertydefaults.hh   | 160 +++
 dumux/implicit/2p2c/2p2cvolumevariables.hh    | 455 +++++++++
 dumux/implicit/2p2c/Makefile.am               |   4 +
 dumux/implicit/2p2cni/2p2cnifluxvariables.hh  | 146 +++
 dumux/implicit/2p2cni/2p2cniindices.hh        |  51 +
 dumux/implicit/2p2cni/2p2cnilocalresidual.hh  | 175 ++++
 dumux/implicit/2p2cni/2p2cnimodel.hh          |  98 ++
 dumux/implicit/2p2cni/2p2cniproperties.hh     |  47 +
 .../implicit/2p2cni/2p2cnipropertydefaults.hh |  76 ++
 .../implicit/2p2cni/2p2cnivolumevariables.hh  | 144 +++
 dumux/implicit/2p2cni/Makefile.am             |   4 +
 dumux/implicit/2pdfm/2pdfmfluxvariables.hh    | 234 +++++
 dumux/implicit/2pdfm/2pdfmindices.hh          |  64 ++
 dumux/implicit/2pdfm/2pdfmlocalresidual.hh    | 335 ++++++
 dumux/implicit/2pdfm/2pdfmmodel.hh            | 390 +++++++
 dumux/implicit/2pdfm/2pdfmproblem.hh          |  79 ++
 dumux/implicit/2pdfm/2pdfmproperties.hh       |  69 ++
 dumux/implicit/2pdfm/2pdfmpropertydefaults.hh | 144 +++
 dumux/implicit/2pdfm/2pdfmvolumevariables.hh  | 386 +++++++
 dumux/implicit/2pdfm/Makefile.am              |   4 +
 dumux/implicit/2pni/2pnifluxvariables.hh      | 127 +++
 dumux/implicit/2pni/2pniindices.hh            |  48 +
 dumux/implicit/2pni/2pnilocalresidual.hh      | 182 ++++
 dumux/implicit/2pni/2pnimodel.hh              |  93 ++
 dumux/implicit/2pni/2pniproperties.hh         |  47 +
 dumux/implicit/2pni/2pnipropertydefaults.hh   |  72 ++
 dumux/implicit/2pni/2pnivolumevariables.hh    | 124 +++
 dumux/implicit/2pni/Makefile.am               |   4 +
 dumux/implicit/3p3c/3p3cfluxvariables.hh      | 335 ++++++
 dumux/implicit/3p3c/3p3cindices.hh            |  85 ++
 dumux/implicit/3p3c/3p3clocalresidual.hh      | 264 +++++
 dumux/implicit/3p3c/3p3cmodel.hh              | 952 ++++++++++++++++++
 dumux/implicit/3p3c/3p3cnewtoncontroller.hh   |  85 ++
 dumux/implicit/3p3c/3p3cproperties.hh         |  66 ++
 dumux/implicit/3p3c/3p3cpropertydefaults.hh   | 143 +++
 dumux/implicit/3p3c/3p3cvolumevariables.hh    | 732 ++++++++++++++
 dumux/implicit/3p3c/Makefile.am               |   4 +
 dumux/implicit/3p3cni/3p3cnifluxvariables.hh  | 129 +++
 dumux/implicit/3p3cni/3p3cniindices.hh        |  51 +
 dumux/implicit/3p3cni/3p3cnilocalresidual.hh  | 193 ++++
 dumux/implicit/3p3cni/3p3cnimodel.hh          | 108 ++
 dumux/implicit/3p3cni/3p3cniproperties.hh     |  47 +
 .../implicit/3p3cni/3p3cnipropertydefaults.hh |  71 ++
 .../implicit/3p3cni/3p3cnivolumevariables.hh  | 157 +++
 dumux/implicit/3p3cni/Makefile.am             |   4 +
 dumux/implicit/Makefile.am                    |   5 +
 dumux/implicit/box/Makefile.am                |   4 +
 dumux/implicit/box/boxassembler.hh            | 858 ++++++++++++++++
 dumux/implicit/box/boxdarcyfluxvariables.hh   | 313 ++++++
 dumux/implicit/box/boxelementboundarytypes.hh | 148 +++
 .../implicit/box/boxelementvolumevariables.hh | 138 +++
 .../box/boxforchheimerfluxvariables.hh        | 358 +++++++
 dumux/implicit/box/boxfvelementgeometry.hh    | 933 +++++++++++++++++
 dumux/implicit/box/boxlocaljacobian.hh        | 534 ++++++++++
 dumux/implicit/box/boxlocalresidual.hh        | 742 ++++++++++++++
 dumux/implicit/box/boxmodel.hh                | 927 +++++++++++++++++
 dumux/implicit/box/boxproblem.hh              | 835 +++++++++++++++
 dumux/implicit/box/boxproperties.hh           | 142 +++
 dumux/implicit/box/boxpropertydefaults.hh     | 207 ++++
 dumux/implicit/box/boxvolumevariables.hh      | 190 ++++
 dumux/implicit/box/intersectiontovertexbc.hh  | 112 +++
 dumux/implicit/box/porousmediaboxproblem.hh   | 197 ++++
 dumux/implicit/cellcentered/Makefile.am       |   4 +
 dumux/implicit/cellcentered/ccassembler.hh    | 683 +++++++++++++
 .../cellcentered/ccelementboundarytypes.hh    | 150 +++
 .../cellcentered/ccelementvolumevariables.hh  | 107 ++
 .../cellcentered/ccfvelementgeometry.hh       | 219 ++++
 .../implicit/cellcentered/cclocaljacobian.hh  | 541 ++++++++++
 .../implicit/cellcentered/cclocalresidual.hh  | 710 +++++++++++++
 dumux/implicit/cellcentered/ccmodel.hh        | 755 ++++++++++++++
 dumux/implicit/cellcentered/ccproblem.hh      | 849 ++++++++++++++++
 dumux/implicit/cellcentered/ccproperties.hh   | 142 +++
 .../cellcentered/ccpropertydefaults.hh        | 209 ++++
 .../cellcentered/porousmediaccproblem.hh      | 192 ++++
 dumux/implicit/co2/Makefile.am                |   4 +
 dumux/implicit/co2/co2model.hh                | 283 ++++++
 dumux/implicit/co2/co2volumevariables.hh      | 404 ++++++++
 dumux/implicit/co2ni/Makefile.am              |   4 +
 dumux/implicit/co2ni/co2nimodel.hh            |  56 ++
 dumux/implicit/co2ni/co2nivolumevariables.hh  | 139 +++
 dumux/implicit/common/Makefile.am             |   4 +
 dumux/implicit/common/implicitassembler.hh    | 858 ++++++++++++++++
 .../common/implicitdarcyfluxvariables.hh      | 313 ++++++
 .../common/implicitelementboundarytypes.hh    | 148 +++
 .../common/implicitelementvolumevariables.hh  | 138 +++
 .../implicitforchheimerfluxvariables.hh       | 358 +++++++
 .../common/implicitfvelementgeometry.hh       | 933 +++++++++++++++++
 .../implicit/common/implicitlocaljacobian.hh  | 534 ++++++++++
 .../implicit/common/implicitlocalresidual.hh  | 742 ++++++++++++++
 dumux/implicit/common/implicitmodel.hh        | 927 +++++++++++++++++
 dumux/implicit/common/implicitproblem.hh      | 835 +++++++++++++++
 dumux/implicit/common/implicitproperties.hh   | 142 +++
 .../common/implicitpropertydefaults.hh        | 207 ++++
 .../common/implicitvolumevariables.hh         | 190 ++++
 .../common/porousmediaimplicitproblem.hh      | 197 ++++
 dumux/implicit/mpnc/Makefile.am               |   6 +
 dumux/implicit/mpnc/diffusion/Makefile.am     |   4 +
 dumux/implicit/mpnc/diffusion/diffusion.hh    | 150 +++
 .../implicit/mpnc/diffusion/fluxvariables.hh  | 221 ++++
 .../mpnc/diffusion/volumevariables.hh         | 164 +++
 dumux/implicit/mpnc/energy/Makefile.am        |   4 +
 .../mpnc/energy/mpncfluxvariablesenergy.hh    | 205 ++++
 .../implicit/mpnc/energy/mpncindicesenergy.hh |  75 ++
 .../mpnc/energy/mpnclocalresidualenergy.hh    | 233 +++++
 .../mpnc/energy/mpncvolumevariablesenergy.hh  | 207 ++++
 .../mpnc/energy/mpncvtkwriterenergy.hh        | 218 ++++
 dumux/implicit/mpnc/mass/Makefile.am          |   4 +
 dumux/implicit/mpnc/mass/mpncindicesmass.hh   |  84 ++
 .../mpnc/mass/mpnclocalresidualmass.hh        | 369 +++++++
 .../mpnc/mass/mpncvolumevariablesmass.hh      | 131 +++
 dumux/implicit/mpnc/mass/mpncvtkwritermass.hh | 118 +++
 dumux/implicit/mpnc/mpncfluxvariables.hh      | 174 ++++
 dumux/implicit/mpnc/mpncindices.hh            | 103 ++
 dumux/implicit/mpnc/mpnclocalresidual.hh      | 247 +++++
 dumux/implicit/mpnc/mpncmodel.hh              | 188 ++++
 dumux/implicit/mpnc/mpncnewtoncontroller.hh   | 266 +++++
 dumux/implicit/mpnc/mpncproperties.hh         | 133 +++
 dumux/implicit/mpnc/mpncpropertydefaults.hh   | 279 +++++
 dumux/implicit/mpnc/mpncvolumevariables.hh    | 340 +++++++
 dumux/implicit/mpnc/mpncvolumevariablesia.hh  |  85 ++
 dumux/implicit/mpnc/mpncvtkwriter.hh          | 126 +++
 dumux/implicit/mpnc/mpncvtkwritercommon.hh    | 275 +++++
 dumux/implicit/mpnc/mpncvtkwritermodule.hh    | 256 +++++
 dumux/implicit/richards/Makefile.am           |   4 +
 dumux/implicit/richards/richardsindices.hh    |  67 ++
 .../richards/richardslocalresidual.hh         | 158 +++
 dumux/implicit/richards/richardsmodel.hh      | 208 ++++
 .../richards/richardsnewtoncontroller.hh      | 125 +++
 dumux/implicit/richards/richardsproblem.hh    |  92 ++
 dumux/implicit/richards/richardsproperties.hh |  70 ++
 .../richards/richardspropertydefaults.hh      | 168 ++++
 .../richards/richardsvolumevariables.hh       | 280 ++++++
 .../{artmeshreader.hh => artgridcreator.hh}   | 594 ++++++-----
 test/Makefile.am                              |   2 +-
 test/boxmodels/2pdfm/test_2pdfm.cc            | 136 ---
 .../1p/1ptest-reference.vtu                   |   0
 .../1p/1ptestproblem.hh                       |   0
 .../1p/1ptestspatialparams.hh                 |   0
 .../{boxmodels => implicit}/1p/CMakeLists.txt |   0
 test/{boxmodels => implicit}/1p/Makefile.am   |   0
 .../1p/grids/test_1p_1d.dgf                   |   0
 .../1p/grids/test_1p_2d.dgf                   |   0
 .../1p/grids/test_1p_3d.dgf                   |   0
 test/{boxmodels => implicit}/1p/test_1p.cc    |   0
 test/{boxmodels => implicit}/1p/test_1p.input |   0
 .../1p2c/1p2coutflowproblem.hh                |   0
 .../1p2c/1p2coutflowspatialparams.hh          |   0
 .../1p2c/CMakeLists.txt                       |   0
 test/{boxmodels => implicit}/1p2c/Makefile.am |   0
 .../1p2c/grids/test_1p2c.dgf                  |   0
 .../1p2c/outflow-reference.vtu                |   0
 .../{boxmodels => implicit}/1p2c/test_1p2c.cc |   0
 .../1p2c/test_1p2c.input                      |   0
 .../{boxmodels => implicit}/2p/CMakeLists.txt |   0
 test/{boxmodels => implicit}/2p/Makefile.am   |   0
 .../2p/grids/test_2p.dgf                      |   0
 .../2p/lens-reference.vtu                     |   0
 .../{boxmodels => implicit}/2p/lensproblem.hh |   0
 .../2p/lensspatialparams.hh                   |   0
 test/{boxmodels => implicit}/2p/test_2p.cc    |   0
 test/{boxmodels => implicit}/2p/test_2p.input |   0
 .../2p2c/CMakeLists.txt                       |   0
 test/{boxmodels => implicit}/2p2c/Makefile.am |   0
 .../2p2c/grids/test_2p2c.dgf                  |   0
 .../2p2c/injection-reference.vtu              |   0
 .../2p2c/injectionproblem.hh                  |   0
 .../2p2c/injectionspatialparams.hh            |   0
 .../{boxmodels => implicit}/2p2c/test_2p2c.cc |   0
 .../2p2c/test_2p2c.input                      |   0
 .../2p2cni/CMakeLists.txt                     |   0
 .../2p2cni/Makefile.am                        |   0
 .../2p2cni/grids/test_2p2cni.dgf              |   0
 .../2p2cni/test_2p2cni.cc                     |   0
 .../2p2cni/test_2p2cni.input                  |   0
 .../2p2cni/waterair-reference.vtu             |   0
 .../2p2cni/waterairproblem.hh                 |   0
 .../2p2cni/waterairspatialparams.hh           |   0
 .../2pdfm/2pdfmspatialparams.hh               | 117 +--
 .../2pdfm/2pdfmtestproblem.hh                 |  65 +-
 .../{boxmodels => implicit}/2pdfm/Makefile.am |   0
 .../2pdfm/grids/2pdfmartmesh.net              |   0
 test/implicit/2pdfm/test_2pdfm.cc             |  62 ++
 test/implicit/2pdfm/test_2pdfm.input          |  28 +
 .../2pni/CMakeLists.txt                       |   0
 test/{boxmodels => implicit}/2pni/Makefile.am |   0
 .../2pni/grids/test_2pni.dgf                  |   0
 .../2pni/injection2pni-reference.vtu          |   0
 .../2pni/injectionproblem2pni.hh              |   0
 .../{boxmodels => implicit}/2pni/test_2pni.cc |   0
 .../2pni/test_2pni.input                      |   0
 .../3p3c/CMakeLists.txt                       |   0
 test/{boxmodels => implicit}/3p3c/Makefile.am |   0
 .../3p3c/grids/test_3p3c.dgf                  |   0
 .../3p3c/grids/test_3p3c_coarse.dgf           |   0
 .../3p3c/infiltration-reference.vtu           |   0
 .../3p3c/infiltrationproblem.hh               |   0
 .../3p3c/infiltrationspatialparameters.hh     |   0
 .../{boxmodels => implicit}/3p3c/test_3p3c.cc |   0
 .../3p3c/test_3p3c.input                      |   0
 .../3p3cni/CMakeLists.txt                     |   0
 .../3p3cni/Makefile.am                        |   0
 .../3p3cni/column3p3cni-reference.vtu         |   0
 .../3p3cni/columnxylolproblem.hh              |   0
 .../3p3cni/columnxylolspatialparams.hh        |   0
 .../3p3cni/grids/column.dgf                   |   0
 .../3p3cni/grids/kuev_3p3cni.dgf              |   0
 .../3p3cni/grids/kuev_3p3cni_coarse.dgf       |   0
 .../3p3cni/kuevetteproblem.hh                 |   0
 .../3p3cni/kuevettespatialparams.hh           |   0
 .../3p3cni/test_3p3cni.cc                     |   0
 .../3p3cni/test_3p3cni.input                  |   0
 test/{boxmodels => implicit}/CMakeLists.txt   |   0
 test/{boxmodels => implicit}/Makefile.am      |   0
 .../co2/CMakeLists.txt                        |   0
 test/{boxmodels => implicit}/co2/Makefile.am  |   0
 .../co2/co2-reference.vtu                     |   0
 .../{boxmodels => implicit}/co2/co2values.inc |   0
 .../co2/grids/heterogeneousSmall.dgf          |   0
 .../co2/heterogeneousco2tables.hh             |   0
 .../co2/heterogeneousproblem.hh               |   0
 .../co2/heterogeneousspatialparameters.hh     |   0
 test/{boxmodels => implicit}/co2/test_co2.cc  |   0
 .../co2/test_co2.input                        |   0
 .../co2ni/CMakeLists.txt                      |   0
 .../{boxmodels => implicit}/co2ni/Makefile.am |   0
 .../co2ni/co2ni-reference.vtu                 |   0
 .../co2ni/co2values.inc                       |   0
 .../co2ni/grids/heterogeneousSmall.dgf        |   0
 .../co2ni/heterogeneousco2tables.hh           |   0
 .../co2ni/heterogeneousproblemni.hh           |   0
 .../co2ni/heterogeneousspatialparametersni.hh |   0
 .../co2ni/test_co2ni.cc                       |   0
 .../co2ni/test_co2ni.input                    |   0
 .../mpnc/CMakeLists.txt                       |   0
 test/{boxmodels => implicit}/mpnc/Makefile.am |   0
 .../mpnc/forchheimer1p-reference.vtp          |   0
 .../mpnc/forchheimer1pproblem.hh              |   0
 .../mpnc/forchheimer2p-reference.vtu          |   0
 .../mpnc/forchheimer2pproblem.hh              |   0
 .../mpnc/forchheimerspatialparams.hh          |   0
 .../mpnc/grids/forchheimer1d.dgf              |   0
 .../mpnc/grids/obstacle_24x16.dgf             |   0
 .../mpnc/grids/obstacle_48x32.dgf             |   0
 .../mpnc/obstacle-reference.vtu               |   0
 .../mpnc/obstacleproblem.hh                   |   0
 .../mpnc/obstaclespatialparams.hh             |   0
 .../mpnc/test_forchheimer1p.cc                |   0
 .../mpnc/test_forchheimer1p.input             |   0
 .../mpnc/test_forchheimer2p.cc                |   0
 .../mpnc/test_forchheimer2p.input             |   0
 .../{boxmodels => implicit}/mpnc/test_mpnc.cc |   0
 .../mpnc/test_mpnc.input                      |   0
 .../richards/CMakeLists.txt                   |   0
 .../richards/Makefile.am                      |   0
 .../richards/grids/richardslens-24x16.dgf     |   0
 .../richards/grids/richardslens-48x32.dgf     |   0
 .../richards/grids/richardslens-96x64.dgf     |   0
 .../richardslens-reference-parallel.vtu       |   0
 .../richards/richardslens-reference.vtu       |   0
 .../richards/richardslensproblem.hh           |   0
 .../richards/richardslensspatialparams.hh     |   0
 .../richards/test_richards.cc                 |   0
 .../richards/test_richards.input              |   0
 293 files changed, 37408 insertions(+), 602 deletions(-)
 create mode 100644 dumux/implicit/1p/1pindices.hh
 create mode 100644 dumux/implicit/1p/1plocalresidual.hh
 create mode 100644 dumux/implicit/1p/1pmodel.hh
 create mode 100644 dumux/implicit/1p/1pproperties.hh
 create mode 100644 dumux/implicit/1p/1ppropertydefaults.hh
 create mode 100644 dumux/implicit/1p/1pvolumevariables.hh
 create mode 100644 dumux/implicit/1p/Makefile.am
 create mode 100644 dumux/implicit/1p2c/1p2cfluxvariables.hh
 create mode 100644 dumux/implicit/1p2c/1p2cindices.hh
 create mode 100644 dumux/implicit/1p2c/1p2clocalresidual.hh
 create mode 100644 dumux/implicit/1p2c/1p2cmodel.hh
 create mode 100644 dumux/implicit/1p2c/1p2cproperties.hh
 create mode 100644 dumux/implicit/1p2c/1p2cpropertydefaults.hh
 create mode 100644 dumux/implicit/1p2c/1p2cvolumevariables.hh
 create mode 100644 dumux/implicit/1p2c/Makefile.am
 create mode 100644 dumux/implicit/2p/2pindices.hh
 create mode 100644 dumux/implicit/2p/2plocalresidual.hh
 create mode 100644 dumux/implicit/2p/2pmodel.hh
 create mode 100644 dumux/implicit/2p/2pproperties.hh
 create mode 100644 dumux/implicit/2p/2ppropertydefaults.hh
 create mode 100644 dumux/implicit/2p/2pvolumevariables.hh
 create mode 100644 dumux/implicit/2p/Makefile.am
 create mode 100644 dumux/implicit/2p2c/2p2cfluxvariables.hh
 create mode 100644 dumux/implicit/2p2c/2p2cindices.hh
 create mode 100644 dumux/implicit/2p2c/2p2clocalresidual.hh
 create mode 100644 dumux/implicit/2p2c/2p2cmodel.hh
 create mode 100644 dumux/implicit/2p2c/2p2cnewtoncontroller.hh
 create mode 100644 dumux/implicit/2p2c/2p2cproperties.hh
 create mode 100644 dumux/implicit/2p2c/2p2cpropertydefaults.hh
 create mode 100644 dumux/implicit/2p2c/2p2cvolumevariables.hh
 create mode 100644 dumux/implicit/2p2c/Makefile.am
 create mode 100644 dumux/implicit/2p2cni/2p2cnifluxvariables.hh
 create mode 100644 dumux/implicit/2p2cni/2p2cniindices.hh
 create mode 100644 dumux/implicit/2p2cni/2p2cnilocalresidual.hh
 create mode 100644 dumux/implicit/2p2cni/2p2cnimodel.hh
 create mode 100644 dumux/implicit/2p2cni/2p2cniproperties.hh
 create mode 100644 dumux/implicit/2p2cni/2p2cnipropertydefaults.hh
 create mode 100644 dumux/implicit/2p2cni/2p2cnivolumevariables.hh
 create mode 100644 dumux/implicit/2p2cni/Makefile.am
 create mode 100644 dumux/implicit/2pdfm/2pdfmfluxvariables.hh
 create mode 100644 dumux/implicit/2pdfm/2pdfmindices.hh
 create mode 100644 dumux/implicit/2pdfm/2pdfmlocalresidual.hh
 create mode 100644 dumux/implicit/2pdfm/2pdfmmodel.hh
 create mode 100644 dumux/implicit/2pdfm/2pdfmproblem.hh
 create mode 100644 dumux/implicit/2pdfm/2pdfmproperties.hh
 create mode 100644 dumux/implicit/2pdfm/2pdfmpropertydefaults.hh
 create mode 100644 dumux/implicit/2pdfm/2pdfmvolumevariables.hh
 create mode 100644 dumux/implicit/2pdfm/Makefile.am
 create mode 100644 dumux/implicit/2pni/2pnifluxvariables.hh
 create mode 100644 dumux/implicit/2pni/2pniindices.hh
 create mode 100644 dumux/implicit/2pni/2pnilocalresidual.hh
 create mode 100644 dumux/implicit/2pni/2pnimodel.hh
 create mode 100644 dumux/implicit/2pni/2pniproperties.hh
 create mode 100644 dumux/implicit/2pni/2pnipropertydefaults.hh
 create mode 100644 dumux/implicit/2pni/2pnivolumevariables.hh
 create mode 100644 dumux/implicit/2pni/Makefile.am
 create mode 100644 dumux/implicit/3p3c/3p3cfluxvariables.hh
 create mode 100644 dumux/implicit/3p3c/3p3cindices.hh
 create mode 100644 dumux/implicit/3p3c/3p3clocalresidual.hh
 create mode 100644 dumux/implicit/3p3c/3p3cmodel.hh
 create mode 100644 dumux/implicit/3p3c/3p3cnewtoncontroller.hh
 create mode 100644 dumux/implicit/3p3c/3p3cproperties.hh
 create mode 100644 dumux/implicit/3p3c/3p3cpropertydefaults.hh
 create mode 100644 dumux/implicit/3p3c/3p3cvolumevariables.hh
 create mode 100644 dumux/implicit/3p3c/Makefile.am
 create mode 100644 dumux/implicit/3p3cni/3p3cnifluxvariables.hh
 create mode 100644 dumux/implicit/3p3cni/3p3cniindices.hh
 create mode 100644 dumux/implicit/3p3cni/3p3cnilocalresidual.hh
 create mode 100644 dumux/implicit/3p3cni/3p3cnimodel.hh
 create mode 100644 dumux/implicit/3p3cni/3p3cniproperties.hh
 create mode 100644 dumux/implicit/3p3cni/3p3cnipropertydefaults.hh
 create mode 100644 dumux/implicit/3p3cni/3p3cnivolumevariables.hh
 create mode 100644 dumux/implicit/3p3cni/Makefile.am
 create mode 100644 dumux/implicit/Makefile.am
 create mode 100644 dumux/implicit/box/Makefile.am
 create mode 100644 dumux/implicit/box/boxassembler.hh
 create mode 100644 dumux/implicit/box/boxdarcyfluxvariables.hh
 create mode 100644 dumux/implicit/box/boxelementboundarytypes.hh
 create mode 100644 dumux/implicit/box/boxelementvolumevariables.hh
 create mode 100644 dumux/implicit/box/boxforchheimerfluxvariables.hh
 create mode 100644 dumux/implicit/box/boxfvelementgeometry.hh
 create mode 100644 dumux/implicit/box/boxlocaljacobian.hh
 create mode 100644 dumux/implicit/box/boxlocalresidual.hh
 create mode 100644 dumux/implicit/box/boxmodel.hh
 create mode 100644 dumux/implicit/box/boxproblem.hh
 create mode 100644 dumux/implicit/box/boxproperties.hh
 create mode 100644 dumux/implicit/box/boxpropertydefaults.hh
 create mode 100644 dumux/implicit/box/boxvolumevariables.hh
 create mode 100644 dumux/implicit/box/intersectiontovertexbc.hh
 create mode 100644 dumux/implicit/box/porousmediaboxproblem.hh
 create mode 100644 dumux/implicit/cellcentered/Makefile.am
 create mode 100644 dumux/implicit/cellcentered/ccassembler.hh
 create mode 100644 dumux/implicit/cellcentered/ccelementboundarytypes.hh
 create mode 100644 dumux/implicit/cellcentered/ccelementvolumevariables.hh
 create mode 100644 dumux/implicit/cellcentered/ccfvelementgeometry.hh
 create mode 100644 dumux/implicit/cellcentered/cclocaljacobian.hh
 create mode 100644 dumux/implicit/cellcentered/cclocalresidual.hh
 create mode 100644 dumux/implicit/cellcentered/ccmodel.hh
 create mode 100644 dumux/implicit/cellcentered/ccproblem.hh
 create mode 100644 dumux/implicit/cellcentered/ccproperties.hh
 create mode 100644 dumux/implicit/cellcentered/ccpropertydefaults.hh
 create mode 100644 dumux/implicit/cellcentered/porousmediaccproblem.hh
 create mode 100644 dumux/implicit/co2/Makefile.am
 create mode 100644 dumux/implicit/co2/co2model.hh
 create mode 100644 dumux/implicit/co2/co2volumevariables.hh
 create mode 100644 dumux/implicit/co2ni/Makefile.am
 create mode 100644 dumux/implicit/co2ni/co2nimodel.hh
 create mode 100644 dumux/implicit/co2ni/co2nivolumevariables.hh
 create mode 100644 dumux/implicit/common/Makefile.am
 create mode 100644 dumux/implicit/common/implicitassembler.hh
 create mode 100644 dumux/implicit/common/implicitdarcyfluxvariables.hh
 create mode 100644 dumux/implicit/common/implicitelementboundarytypes.hh
 create mode 100644 dumux/implicit/common/implicitelementvolumevariables.hh
 create mode 100644 dumux/implicit/common/implicitforchheimerfluxvariables.hh
 create mode 100644 dumux/implicit/common/implicitfvelementgeometry.hh
 create mode 100644 dumux/implicit/common/implicitlocaljacobian.hh
 create mode 100644 dumux/implicit/common/implicitlocalresidual.hh
 create mode 100644 dumux/implicit/common/implicitmodel.hh
 create mode 100644 dumux/implicit/common/implicitproblem.hh
 create mode 100644 dumux/implicit/common/implicitproperties.hh
 create mode 100644 dumux/implicit/common/implicitpropertydefaults.hh
 create mode 100644 dumux/implicit/common/implicitvolumevariables.hh
 create mode 100644 dumux/implicit/common/porousmediaimplicitproblem.hh
 create mode 100644 dumux/implicit/mpnc/Makefile.am
 create mode 100644 dumux/implicit/mpnc/diffusion/Makefile.am
 create mode 100644 dumux/implicit/mpnc/diffusion/diffusion.hh
 create mode 100644 dumux/implicit/mpnc/diffusion/fluxvariables.hh
 create mode 100644 dumux/implicit/mpnc/diffusion/volumevariables.hh
 create mode 100644 dumux/implicit/mpnc/energy/Makefile.am
 create mode 100644 dumux/implicit/mpnc/energy/mpncfluxvariablesenergy.hh
 create mode 100644 dumux/implicit/mpnc/energy/mpncindicesenergy.hh
 create mode 100644 dumux/implicit/mpnc/energy/mpnclocalresidualenergy.hh
 create mode 100644 dumux/implicit/mpnc/energy/mpncvolumevariablesenergy.hh
 create mode 100644 dumux/implicit/mpnc/energy/mpncvtkwriterenergy.hh
 create mode 100644 dumux/implicit/mpnc/mass/Makefile.am
 create mode 100644 dumux/implicit/mpnc/mass/mpncindicesmass.hh
 create mode 100644 dumux/implicit/mpnc/mass/mpnclocalresidualmass.hh
 create mode 100644 dumux/implicit/mpnc/mass/mpncvolumevariablesmass.hh
 create mode 100644 dumux/implicit/mpnc/mass/mpncvtkwritermass.hh
 create mode 100644 dumux/implicit/mpnc/mpncfluxvariables.hh
 create mode 100644 dumux/implicit/mpnc/mpncindices.hh
 create mode 100644 dumux/implicit/mpnc/mpnclocalresidual.hh
 create mode 100644 dumux/implicit/mpnc/mpncmodel.hh
 create mode 100644 dumux/implicit/mpnc/mpncnewtoncontroller.hh
 create mode 100644 dumux/implicit/mpnc/mpncproperties.hh
 create mode 100644 dumux/implicit/mpnc/mpncpropertydefaults.hh
 create mode 100644 dumux/implicit/mpnc/mpncvolumevariables.hh
 create mode 100644 dumux/implicit/mpnc/mpncvolumevariablesia.hh
 create mode 100644 dumux/implicit/mpnc/mpncvtkwriter.hh
 create mode 100644 dumux/implicit/mpnc/mpncvtkwritercommon.hh
 create mode 100644 dumux/implicit/mpnc/mpncvtkwritermodule.hh
 create mode 100644 dumux/implicit/richards/Makefile.am
 create mode 100644 dumux/implicit/richards/richardsindices.hh
 create mode 100644 dumux/implicit/richards/richardslocalresidual.hh
 create mode 100644 dumux/implicit/richards/richardsmodel.hh
 create mode 100644 dumux/implicit/richards/richardsnewtoncontroller.hh
 create mode 100644 dumux/implicit/richards/richardsproblem.hh
 create mode 100644 dumux/implicit/richards/richardsproperties.hh
 create mode 100644 dumux/implicit/richards/richardspropertydefaults.hh
 create mode 100644 dumux/implicit/richards/richardsvolumevariables.hh
 rename dumux/io/{artmeshreader.hh => artgridcreator.hh} (51%)
 delete mode 100644 test/boxmodels/2pdfm/test_2pdfm.cc
 rename test/{boxmodels => implicit}/1p/1ptest-reference.vtu (100%)
 rename test/{boxmodels => implicit}/1p/1ptestproblem.hh (100%)
 rename test/{boxmodels => implicit}/1p/1ptestspatialparams.hh (100%)
 rename test/{boxmodels => implicit}/1p/CMakeLists.txt (100%)
 rename test/{boxmodels => implicit}/1p/Makefile.am (100%)
 rename test/{boxmodels => implicit}/1p/grids/test_1p_1d.dgf (100%)
 rename test/{boxmodels => implicit}/1p/grids/test_1p_2d.dgf (100%)
 rename test/{boxmodels => implicit}/1p/grids/test_1p_3d.dgf (100%)
 rename test/{boxmodels => implicit}/1p/test_1p.cc (100%)
 rename test/{boxmodels => implicit}/1p/test_1p.input (100%)
 rename test/{boxmodels => implicit}/1p2c/1p2coutflowproblem.hh (100%)
 rename test/{boxmodels => implicit}/1p2c/1p2coutflowspatialparams.hh (100%)
 rename test/{boxmodels => implicit}/1p2c/CMakeLists.txt (100%)
 rename test/{boxmodels => implicit}/1p2c/Makefile.am (100%)
 rename test/{boxmodels => implicit}/1p2c/grids/test_1p2c.dgf (100%)
 rename test/{boxmodels => implicit}/1p2c/outflow-reference.vtu (100%)
 rename test/{boxmodels => implicit}/1p2c/test_1p2c.cc (100%)
 rename test/{boxmodels => implicit}/1p2c/test_1p2c.input (100%)
 rename test/{boxmodels => implicit}/2p/CMakeLists.txt (100%)
 rename test/{boxmodels => implicit}/2p/Makefile.am (100%)
 rename test/{boxmodels => implicit}/2p/grids/test_2p.dgf (100%)
 rename test/{boxmodels => implicit}/2p/lens-reference.vtu (100%)
 rename test/{boxmodels => implicit}/2p/lensproblem.hh (100%)
 rename test/{boxmodels => implicit}/2p/lensspatialparams.hh (100%)
 rename test/{boxmodels => implicit}/2p/test_2p.cc (100%)
 rename test/{boxmodels => implicit}/2p/test_2p.input (100%)
 rename test/{boxmodels => implicit}/2p2c/CMakeLists.txt (100%)
 rename test/{boxmodels => implicit}/2p2c/Makefile.am (100%)
 rename test/{boxmodels => implicit}/2p2c/grids/test_2p2c.dgf (100%)
 rename test/{boxmodels => implicit}/2p2c/injection-reference.vtu (100%)
 rename test/{boxmodels => implicit}/2p2c/injectionproblem.hh (100%)
 rename test/{boxmodels => implicit}/2p2c/injectionspatialparams.hh (100%)
 rename test/{boxmodels => implicit}/2p2c/test_2p2c.cc (100%)
 rename test/{boxmodels => implicit}/2p2c/test_2p2c.input (100%)
 rename test/{boxmodels => implicit}/2p2cni/CMakeLists.txt (100%)
 rename test/{boxmodels => implicit}/2p2cni/Makefile.am (100%)
 rename test/{boxmodels => implicit}/2p2cni/grids/test_2p2cni.dgf (100%)
 rename test/{boxmodels => implicit}/2p2cni/test_2p2cni.cc (100%)
 rename test/{boxmodels => implicit}/2p2cni/test_2p2cni.input (100%)
 rename test/{boxmodels => implicit}/2p2cni/waterair-reference.vtu (100%)
 rename test/{boxmodels => implicit}/2p2cni/waterairproblem.hh (100%)
 rename test/{boxmodels => implicit}/2p2cni/waterairspatialparams.hh (100%)
 rename test/{boxmodels => implicit}/2pdfm/2pdfmspatialparams.hh (74%)
 rename test/{boxmodels => implicit}/2pdfm/2pdfmtestproblem.hh (83%)
 rename test/{boxmodels => implicit}/2pdfm/Makefile.am (100%)
 rename test/{boxmodels => implicit}/2pdfm/grids/2pdfmartmesh.net (100%)
 create mode 100644 test/implicit/2pdfm/test_2pdfm.cc
 create mode 100644 test/implicit/2pdfm/test_2pdfm.input
 rename test/{boxmodels => implicit}/2pni/CMakeLists.txt (100%)
 rename test/{boxmodels => implicit}/2pni/Makefile.am (100%)
 rename test/{boxmodels => implicit}/2pni/grids/test_2pni.dgf (100%)
 rename test/{boxmodels => implicit}/2pni/injection2pni-reference.vtu (100%)
 rename test/{boxmodels => implicit}/2pni/injectionproblem2pni.hh (100%)
 rename test/{boxmodels => implicit}/2pni/test_2pni.cc (100%)
 rename test/{boxmodels => implicit}/2pni/test_2pni.input (100%)
 rename test/{boxmodels => implicit}/3p3c/CMakeLists.txt (100%)
 rename test/{boxmodels => implicit}/3p3c/Makefile.am (100%)
 rename test/{boxmodels => implicit}/3p3c/grids/test_3p3c.dgf (100%)
 rename test/{boxmodels => implicit}/3p3c/grids/test_3p3c_coarse.dgf (100%)
 rename test/{boxmodels => implicit}/3p3c/infiltration-reference.vtu (100%)
 rename test/{boxmodels => implicit}/3p3c/infiltrationproblem.hh (100%)
 rename test/{boxmodels => implicit}/3p3c/infiltrationspatialparameters.hh (100%)
 rename test/{boxmodels => implicit}/3p3c/test_3p3c.cc (100%)
 rename test/{boxmodels => implicit}/3p3c/test_3p3c.input (100%)
 rename test/{boxmodels => implicit}/3p3cni/CMakeLists.txt (100%)
 rename test/{boxmodels => implicit}/3p3cni/Makefile.am (100%)
 rename test/{boxmodels => implicit}/3p3cni/column3p3cni-reference.vtu (100%)
 rename test/{boxmodels => implicit}/3p3cni/columnxylolproblem.hh (100%)
 rename test/{boxmodels => implicit}/3p3cni/columnxylolspatialparams.hh (100%)
 rename test/{boxmodels => implicit}/3p3cni/grids/column.dgf (100%)
 rename test/{boxmodels => implicit}/3p3cni/grids/kuev_3p3cni.dgf (100%)
 rename test/{boxmodels => implicit}/3p3cni/grids/kuev_3p3cni_coarse.dgf (100%)
 rename test/{boxmodels => implicit}/3p3cni/kuevetteproblem.hh (100%)
 rename test/{boxmodels => implicit}/3p3cni/kuevettespatialparams.hh (100%)
 rename test/{boxmodels => implicit}/3p3cni/test_3p3cni.cc (100%)
 rename test/{boxmodels => implicit}/3p3cni/test_3p3cni.input (100%)
 rename test/{boxmodels => implicit}/CMakeLists.txt (100%)
 rename test/{boxmodels => implicit}/Makefile.am (100%)
 rename test/{boxmodels => implicit}/co2/CMakeLists.txt (100%)
 rename test/{boxmodels => implicit}/co2/Makefile.am (100%)
 rename test/{boxmodels => implicit}/co2/co2-reference.vtu (100%)
 rename test/{boxmodels => implicit}/co2/co2values.inc (100%)
 rename test/{boxmodels => implicit}/co2/grids/heterogeneousSmall.dgf (100%)
 rename test/{boxmodels => implicit}/co2/heterogeneousco2tables.hh (100%)
 rename test/{boxmodels => implicit}/co2/heterogeneousproblem.hh (100%)
 rename test/{boxmodels => implicit}/co2/heterogeneousspatialparameters.hh (100%)
 rename test/{boxmodels => implicit}/co2/test_co2.cc (100%)
 rename test/{boxmodels => implicit}/co2/test_co2.input (100%)
 rename test/{boxmodels => implicit}/co2ni/CMakeLists.txt (100%)
 rename test/{boxmodels => implicit}/co2ni/Makefile.am (100%)
 rename test/{boxmodels => implicit}/co2ni/co2ni-reference.vtu (100%)
 rename test/{boxmodels => implicit}/co2ni/co2values.inc (100%)
 rename test/{boxmodels => implicit}/co2ni/grids/heterogeneousSmall.dgf (100%)
 rename test/{boxmodels => implicit}/co2ni/heterogeneousco2tables.hh (100%)
 rename test/{boxmodels => implicit}/co2ni/heterogeneousproblemni.hh (100%)
 rename test/{boxmodels => implicit}/co2ni/heterogeneousspatialparametersni.hh (100%)
 rename test/{boxmodels => implicit}/co2ni/test_co2ni.cc (100%)
 rename test/{boxmodels => implicit}/co2ni/test_co2ni.input (100%)
 rename test/{boxmodels => implicit}/mpnc/CMakeLists.txt (100%)
 rename test/{boxmodels => implicit}/mpnc/Makefile.am (100%)
 rename test/{boxmodels => implicit}/mpnc/forchheimer1p-reference.vtp (100%)
 rename test/{boxmodels => implicit}/mpnc/forchheimer1pproblem.hh (100%)
 rename test/{boxmodels => implicit}/mpnc/forchheimer2p-reference.vtu (100%)
 rename test/{boxmodels => implicit}/mpnc/forchheimer2pproblem.hh (100%)
 rename test/{boxmodels => implicit}/mpnc/forchheimerspatialparams.hh (100%)
 rename test/{boxmodels => implicit}/mpnc/grids/forchheimer1d.dgf (100%)
 rename test/{boxmodels => implicit}/mpnc/grids/obstacle_24x16.dgf (100%)
 rename test/{boxmodels => implicit}/mpnc/grids/obstacle_48x32.dgf (100%)
 rename test/{boxmodels => implicit}/mpnc/obstacle-reference.vtu (100%)
 rename test/{boxmodels => implicit}/mpnc/obstacleproblem.hh (100%)
 rename test/{boxmodels => implicit}/mpnc/obstaclespatialparams.hh (100%)
 rename test/{boxmodels => implicit}/mpnc/test_forchheimer1p.cc (100%)
 rename test/{boxmodels => implicit}/mpnc/test_forchheimer1p.input (100%)
 rename test/{boxmodels => implicit}/mpnc/test_forchheimer2p.cc (100%)
 rename test/{boxmodels => implicit}/mpnc/test_forchheimer2p.input (100%)
 rename test/{boxmodels => implicit}/mpnc/test_mpnc.cc (100%)
 rename test/{boxmodels => implicit}/mpnc/test_mpnc.input (100%)
 rename test/{boxmodels => implicit}/richards/CMakeLists.txt (100%)
 rename test/{boxmodels => implicit}/richards/Makefile.am (100%)
 rename test/{boxmodels => implicit}/richards/grids/richardslens-24x16.dgf (100%)
 rename test/{boxmodels => implicit}/richards/grids/richardslens-48x32.dgf (100%)
 rename test/{boxmodels => implicit}/richards/grids/richardslens-96x64.dgf (100%)
 rename test/{boxmodels => implicit}/richards/richardslens-reference-parallel.vtu (100%)
 rename test/{boxmodels => implicit}/richards/richardslens-reference.vtu (100%)
 rename test/{boxmodels => implicit}/richards/richardslensproblem.hh (100%)
 rename test/{boxmodels => implicit}/richards/richardslensspatialparams.hh (100%)
 rename test/{boxmodels => implicit}/richards/test_richards.cc (100%)
 rename test/{boxmodels => implicit}/richards/test_richards.input (100%)

diff --git a/configure.ac b/configure.ac
index 2dbe007b34..663287b549 100644
--- a/configure.ac
+++ b/configure.ac
@@ -56,6 +56,26 @@ AC_CONFIG_FILES([dumux.pc
     dumux/freeflow/stokes/Makefile
     dumux/freeflow/stokes2c/Makefile
     dumux/freeflow/stokes2cni/Makefile
+    dumux/implicit/Makefile 
+    dumux/implicit/1p/Makefile 
+    dumux/implicit/1p2c/Makefile 
+    dumux/implicit/2p/Makefile 
+    dumux/implicit/2p2c/Makefile 
+    dumux/implicit/2p2cni/Makefile 
+    dumux/implicit/2pni/Makefile
+    dumux/implicit/2pdfm/Makefile 
+    dumux/implicit/3p3c/Makefile 
+    dumux/implicit/3p3cni/Makefile 
+    dumux/implicit/box/Makefile 
+    dumux/implicit/cellcentered/Makefile 
+    dumux/implicit/common/Makefile 
+    dumux/implicit/co2/Makefile
+    dumux/implicit/co2ni/Makefile
+    dumux/implicit/mpnc/Makefile 
+    dumux/implicit/mpnc/diffusion/Makefile
+    dumux/implicit/mpnc/energy/Makefile
+    dumux/implicit/mpnc/mass/Makefile
+    dumux/implicit/richards/Makefile 
     dumux/io/Makefile
     dumux/linear/Makefile
     dumux/material/Makefile 
@@ -75,20 +95,20 @@ AC_CONFIG_FILES([dumux.pc
     dumux/parallel/Makefile 
     m4/Makefile
     test/Makefile
-    test/boxmodels/Makefile 
-    test/boxmodels/1p/Makefile 
-    test/boxmodels/2p/Makefile 
-    test/boxmodels/2pni/Makefile
-    test/boxmodels/1p2c/Makefile 
-    test/boxmodels/2p2c/Makefile
-    test/boxmodels/2p2cni/Makefile
-    test/boxmodels/2pdfm/Makefile
-    test/boxmodels/3p3c/Makefile
-    test/boxmodels/3p3cni/Makefile
-    test/boxmodels/co2/Makefile
-    test/boxmodels/co2ni/Makefile
-    test/boxmodels/mpnc/Makefile
-    test/boxmodels/richards/Makefile  
+    test/implicit/Makefile 
+    test/implicit/1p/Makefile 
+    test/implicit/2p/Makefile 
+    test/implicit/2pni/Makefile
+    test/implicit/1p2c/Makefile 
+    test/implicit/2p2c/Makefile
+    test/implicit/2p2cni/Makefile
+    test/implicit/2pdfm/Makefile
+    test/implicit/3p3c/Makefile
+    test/implicit/3p3cni/Makefile
+    test/implicit/co2/Makefile
+    test/implicit/co2ni/Makefile
+    test/implicit/mpnc/Makefile
+    test/implicit/richards/Makefile  
     test/common/Makefile
     test/common/generalproblem/Makefile
     test/common/propertysystem/Makefile
diff --git a/dumux/Makefile.am b/dumux/Makefile.am
index d5aa78cec3..f5093738d6 100644
--- a/dumux/Makefile.am
+++ b/dumux/Makefile.am
@@ -1,4 +1,4 @@
-SUBDIRS = boxmodels common decoupled freeflow io linear material nonlinear parallel
+SUBDIRS = boxmodels common decoupled freeflow implicit io linear material nonlinear parallel
 
 dumuxdir = $(includedir)/dumux
 
diff --git a/dumux/implicit/1p/1pindices.hh b/dumux/implicit/1p/1pindices.hh
new file mode 100644
index 0000000000..237d2a79d7
--- /dev/null
+++ b/dumux/implicit/1p/1pindices.hh
@@ -0,0 +1,45 @@
+// -*- mode: C++; tab-width: 4; indent-tabs-mode: nil; c-basic-offset: 4 -*-
+// vi: set et ts=4 sw=4 sts=4:
+/*****************************************************************************
+ *   See the file COPYING for full copying permissions.                      *
+ *                                                                           *
+ *   This program is free software: you can redistribute it and/or modify    *
+ *   it under the terms of the GNU General Public License as published by    *
+ *   the Free Software Foundation, either version 2 of the License, or       *
+ *   (at your option) any later version.                                     *
+ *                                                                           *
+ *   This program is distributed in the hope that it will be useful,         *
+ *   but WITHOUT ANY WARRANTY; without even the implied warranty of          *
+ *   MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the            *
+ *   GNU General Public License for more details.                            *
+ *                                                                           *
+ *   You should have received a copy of the GNU General Public License       *
+ *   along with this program.  If not, see <http://www.gnu.org/licenses/>.   *
+ *****************************************************************************/
+/*!
+ * \file
+ *
+ * \brief  Defines the indices for the one-phase box model.
+ */
+#ifndef DUMUX_1P_INDICES_HH
+#define DUMUX_1P_INDICES_HH
+
+namespace Dumux
+{
+// \{
+
+/*!
+ * \ingroup OnePBoxModel
+ * \ingroup BoxIndices
+ * \brief Indices for the one-phase model.
+ */
+struct OnePIndices
+{
+    static const int conti0EqIdx = 0; //index for the mass balance
+    static const int pressureIdx = 0; //index of the primary variable
+};
+
+// \}
+} // end namepace
+
+#endif
diff --git a/dumux/implicit/1p/1plocalresidual.hh b/dumux/implicit/1p/1plocalresidual.hh
new file mode 100644
index 0000000000..0666c4459a
--- /dev/null
+++ b/dumux/implicit/1p/1plocalresidual.hh
@@ -0,0 +1,169 @@
+// -*- mode: C++; tab-width: 4; indent-tabs-mode: nil; c-basic-offset: 4 -*-
+// vi: set et ts=4 sw=4 sts=4:
+/*****************************************************************************
+ *   See the file COPYING for full copying permissions.                      *
+ *                                                                           *
+ *   This program is free software: you can redistribute it and/or modify    *
+ *   it under the terms of the GNU General Public License as published by    *
+ *   the Free Software Foundation, either version 2 of the License, or       *
+ *   (at your option) any later version.                                     *
+ *                                                                           *
+ *   This program is distributed in the hope that it will be useful,         *
+ *   but WITHOUT ANY WARRANTY; without even the implied warranty of          *
+ *   MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the            *
+ *   GNU General Public License for more details.                            *
+ *                                                                           *
+ *   You should have received a copy of the GNU General Public License       *
+ *   along with this program.  If not, see <http://www.gnu.org/licenses/>.   *
+ *****************************************************************************/
+/*!
+ * \file
+ *
+ * \brief Element-wise calculation of the Jacobian matrix for problems
+ *        using the one-phase box model.
+ */
+#ifndef DUMUX_1P_LOCAL_RESIDUAL_HH
+#define DUMUX_1P_LOCAL_RESIDUAL_HH
+
+#include <dumux/boxmodels/common/boxlocalresidual.hh>
+
+#include "1pvolumevariables.hh"
+#include "1pproperties.hh"
+
+namespace Dumux
+{
+/*!
+ * \ingroup OnePBoxModel
+ * \ingroup BoxLocalResidual
+ * \brief Element-wise calculation of the Jacobian matrix for problems
+ *        using the one-phase box model.
+ */
+template<class TypeTag>
+class OnePLocalResidual : public GET_PROP_TYPE(TypeTag, BaseLocalResidual)
+{
+    typedef OnePLocalResidual<TypeTag> ThisType;
+
+    typedef typename GET_PROP_TYPE(TypeTag, Scalar) Scalar;
+    typedef typename GET_PROP_TYPE(TypeTag, PrimaryVariables) PrimaryVariables;
+    typedef typename GET_PROP_TYPE(TypeTag, VolumeVariables) VolumeVariables;
+    typedef typename GET_PROP_TYPE(TypeTag, FluxVariables) FluxVariables;
+    typedef typename GET_PROP_TYPE(TypeTag, ElementVolumeVariables) ElementVolumeVariables;
+
+    typedef typename GET_PROP_TYPE(TypeTag, GridView) GridView;
+    enum { dim = GridView::dimension };
+    typedef Dune::FieldVector<Scalar, dim> DimVector;
+
+    typedef typename GET_PROP_TYPE(TypeTag, Indices) Indices;
+    //index of the mass balance equation
+    enum {
+        conti0EqIdx = Indices::conti0EqIdx //index for the mass balance
+    };
+    //index of the primary variable
+    enum{
+        pressureIdx = Indices::pressureIdx  //index for the primary variable
+    };
+
+public:
+
+    /*!
+     * \brief Constructor. Sets the upwind weight.
+     */
+    OnePLocalResidual()
+    {
+        // retrieve the upwind weight for the mass conservation equations. Use the value
+        // specified via the property system as default, and overwrite
+        // it by the run-time parameter from the Dune::ParameterTree
+        upwindWeight_ = GET_PARAM_FROM_GROUP(TypeTag, Scalar, Implicit, MassUpwindWeight);
+    };
+
+    /*!
+     * \brief Evaluate the rate of change of all conservation
+     *        quantites (e.g. phase mass) within a sub-control
+     *        volume of a finite volume element for the OneP
+     *        model.
+     *
+     * This function should not include the source and sink terms.
+     *  \param storage The phase mass within the sub-control volume
+     *  \param scvIdx The SCV (sub-control-volume) index
+     *  \param usePrevSol Evaluate function with solution of current or previous time step
+     */
+    void computeStorage(PrimaryVariables &storage, const int scvIdx, const bool usePrevSol) const
+    {
+        // if flag usePrevSol is set, the solution from the previous
+        // time step is used, otherwise the current solution is
+        // used. The secondary variables are used accordingly.  This
+        // is required to compute the derivative of the storage term
+        // using the implicit euler method.
+        const ElementVolumeVariables &elemVolVars = usePrevSol ? this->prevVolVars_() : this->curVolVars_();
+        const VolumeVariables &volVars = elemVolVars[scvIdx];
+
+        // partial time derivative of the wetting phase mass
+        storage[conti0EqIdx] =  volVars.density() * volVars.porosity();
+    }
+
+
+    /*!
+     * \brief Evaluate the mass flux over a face of a sub-control
+     *        volume.
+     *
+     * \param flux The flux over the SCV (sub-control-volume) face
+     * \param faceIdx The index of the SCV face
+     * \param onBoundary A boolean variable to specify whether the flux variables
+     *        are calculated for interior SCV faces or boundary faces, default=false
+     */
+    void computeFlux(PrimaryVariables &flux, const int faceIdx, const bool onBoundary=false) const
+    {
+        FluxVariables fluxVars(this->problem_(),
+                               this->element_(),
+                               this->fvGeometry_(),
+                               faceIdx,
+                               this->curVolVars_(),
+                               onBoundary);
+
+        const VolumeVariables &up = this->curVolVars_(fluxVars.upstreamIdx(/*phaseIdx=*/0));
+        const VolumeVariables &dn = this->curVolVars_(fluxVars.downstreamIdx(/*phaseIdx=*/0));
+        flux[conti0EqIdx] =
+            ((    upwindWeight_)*up.density()
+             +
+             (1 - upwindWeight_)*dn.density())
+            *
+            fluxVars.volumeFlux(/*phaseIdx=*/0);
+    }
+
+    /*!
+     * \brief Calculate the source term of the equation.
+     *
+     * \param source The source/sink in the SCV
+     * \param scvIdx The index of the SCV
+     *
+     */
+    void computeSource(PrimaryVariables &source, const int scvIdx)
+    {
+        this->problem_().boxSDSource(source,
+                                     this->element_(),
+                                     this->fvGeometry_(),
+                                     scvIdx,
+                                     this->curVolVars_());
+    }
+
+    /*!
+     * \brief Return the temperature given the solution vector of a
+     *        finite volume.
+     */
+    template <class PrimaryVariables>
+    Scalar temperature(const PrimaryVariables &priVars)
+    { return this->problem_.temperature(); /* constant temperature */ }
+
+private:
+    ThisType &asImp_()
+    { return *static_cast<ThisType *>(this); }
+
+    const ThisType &asImp_() const
+    { return *static_cast<const ThisType *>(this); }
+
+    Scalar upwindWeight_;
+};
+
+}
+
+#endif
diff --git a/dumux/implicit/1p/1pmodel.hh b/dumux/implicit/1p/1pmodel.hh
new file mode 100644
index 0000000000..40afc03848
--- /dev/null
+++ b/dumux/implicit/1p/1pmodel.hh
@@ -0,0 +1,125 @@
+// -*- mode: C++; tab-width: 4; indent-tabs-mode: nil; c-basic-offset: 4 -*-
+// vi: set et ts=4 sw=4 sts=4:
+/*****************************************************************************
+ *   See the file COPYING for full copying permissions.                      *
+ *                                                                           *
+ *   This program is free software: you can redistribute it and/or modify    *
+ *   it under the terms of the GNU General Public License as published by    *
+ *   the Free Software Foundation, either version 2 of the License, or       *
+ *   (at your option) any later version.                                     *
+ *                                                                           *
+ *   This program is distributed in the hope that it will be useful,         *
+ *   but WITHOUT ANY WARRANTY; without even the implied warranty of          *
+ *   MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the            *
+ *   GNU General Public License for more details.                            *
+ *                                                                           *
+ *   You should have received a copy of the GNU General Public License       *
+ *   along with this program.  If not, see <http://www.gnu.org/licenses/>.   *
+ *****************************************************************************/
+/*!
+ * \file
+ *
+ * \brief Base class for all models which use the one-phase,
+ *        box model.
+ *        Adaption of the BOX scheme to the one-phase flow model.
+ */
+
+#ifndef DUMUX_1P_MODEL_HH
+#define DUMUX_1P_MODEL_HH
+
+#include <dumux/boxmodels/common/boxmodel.hh>
+
+#include "1plocalresidual.hh"
+
+namespace Dumux
+{
+/*!
+ * \ingroup OnePBoxModel
+ * \brief A single-phase, isothermal flow model using the box scheme.
+ *
+ * Single-phase, isothermal flow model, which solves the mass
+ * continuity equation
+ * \f[
+ \phi \frac{\partial \varrho}{\partial t} + \text{div} (- \varrho \frac{\textbf K}{\mu} ( \textbf{grad}\, p -\varrho {\textbf g})) = q,
+ * \f]
+ * discretized using a vertex-centered finite volume (box) scheme as
+ * spatial and the implicit Euler method as time discretization.  The
+ * model supports compressible as well as incompressible fluids.
+ */
+template<class TypeTag >
+class OnePBoxModel : public GET_PROP_TYPE(TypeTag, BaseModel)
+{
+    typedef typename GET_PROP_TYPE(TypeTag, FVElementGeometry) FVElementGeometry;
+    typedef typename GET_PROP_TYPE(TypeTag, VolumeVariables) VolumeVariables;
+    typedef typename GET_PROP_TYPE(TypeTag, SpatialParams) SpatialParams;
+    typedef typename GET_PROP_TYPE(TypeTag, ElementBoundaryTypes) ElementBoundaryTypes;
+    typedef typename GET_PROP_TYPE(TypeTag, SolutionVector) SolutionVector;
+
+    typedef typename GET_PROP_TYPE(TypeTag, GridView) GridView;
+    typedef typename GridView::template Codim<0>::Iterator ElementIterator;
+    enum { dim = GridView::dimension };
+
+public:
+    /*!
+     * \brief \copybrief Dumux::BoxModel::addOutputVtkFields
+     *
+     * Specialization for the OnePBoxModel, adding the pressure and
+     * the process rank to the VTK writer.
+     */
+    template<class MultiWriter>
+    void addOutputVtkFields(const SolutionVector &sol,
+                            MultiWriter &writer)
+    {
+        typedef Dune::BlockVector<Dune::FieldVector<double, 1> > ScalarField;
+
+        // create the required scalar fields
+        unsigned numVertices = this->problem_().gridView().size(dim);
+        ScalarField *p = writer.allocateManagedBuffer(numVertices);
+        ScalarField *K = writer.allocateManagedBuffer(numVertices);
+
+        unsigned numElements = this->gridView_().size(0);
+        ScalarField *rank = writer.allocateManagedBuffer(numElements);
+
+        FVElementGeometry fvGeometry;
+        VolumeVariables volVars;
+        ElementBoundaryTypes elemBcTypes;
+
+        ElementIterator elemIt = this->gridView_().template begin<0>();
+        ElementIterator elemEndIt = this->gridView_().template end<0>();
+        for (; elemIt != elemEndIt; ++elemIt)
+        {
+            int idx = this->problem_().model().elementMapper().map(*elemIt);
+            (*rank)[idx] = this->gridView_().comm().rank();
+
+            fvGeometry.update(this->gridView_(), *elemIt);
+            elemBcTypes.update(this->problem_(), *elemIt, fvGeometry);
+
+            int numVerts = elemIt->template count<dim> ();
+            for (int i = 0; i < numVerts; ++i)
+            {
+                int globalIdx = this->vertexMapper().map(*elemIt, i, dim);
+                volVars.update(sol[globalIdx],
+                               this->problem_(),
+                               *elemIt,
+                               fvGeometry,
+                               i,
+                               false);
+                const SpatialParams &spatialParams = this->problem_().spatialParams();
+
+                (*p)[globalIdx] = volVars.pressure();
+                (*K)[globalIdx]= spatialParams.intrinsicPermeability(*elemIt,
+                                                                     fvGeometry,
+                                                                     i);
+            }
+        }
+
+        writer.attachVertexData(*p, "p");
+        writer.attachVertexData(*K, "K");
+        writer.attachCellData(*rank, "process rank");
+    }
+};
+}
+
+#include "1ppropertydefaults.hh"
+
+#endif
diff --git a/dumux/implicit/1p/1pproperties.hh b/dumux/implicit/1p/1pproperties.hh
new file mode 100644
index 0000000000..87112a4110
--- /dev/null
+++ b/dumux/implicit/1p/1pproperties.hh
@@ -0,0 +1,65 @@
+// -*- mode: C++; tab-width: 4; indent-tabs-mode: nil; c-basic-offset: 4 -*-
+// vi: set et ts=4 sw=4 sts=4:
+/*****************************************************************************
+ *   See the file COPYING for full copying permissions.                      *
+ *                                                                           *
+ *   This program is free software: you can redistribute it and/or modify    *
+ *   it under the terms of the GNU General Public License as published by    *
+ *   the Free Software Foundation, either version 2 of the License, or       *
+ *   (at your option) any later version.                                     *
+ *                                                                           *
+ *   This program is distributed in the hope that it will be useful,         *
+ *   but WITHOUT ANY WARRANTY; without even the implied warranty of          *
+ *   MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the            *
+ *   GNU General Public License for more details.                            *
+ *                                                                           *
+ *   You should have received a copy of the GNU General Public License       *
+ *   along with this program.  If not, see <http://www.gnu.org/licenses/>.   *
+ *****************************************************************************/
+/*!
+ * \ingroup Properties
+ * \ingroup BoxProperties
+ * \ingroup OnePBoxModel
+ * \file
+ *
+ * \brief Defines the properties required for the one-phase BOX model.
+ */
+#ifndef DUMUX_1P_PROPERTIES_DATA_HH
+#define DUMUX_1P_PROPERTIES_DATA_HH
+
+#include <dumux/boxmodels/common/boxproperties.hh>
+
+namespace Dumux
+{
+// \{
+///////////////////////////////////////////////////////////////////////////
+// properties for the isothermal single phase model
+///////////////////////////////////////////////////////////////////////////
+namespace Properties {
+
+//////////////////////////////////////////////////////////////////
+// Type tags
+//////////////////////////////////////////////////////////////////
+
+//! The type tag for the isothermal single phase problems
+NEW_TYPE_TAG(BoxOneP, INHERITS_FROM(BoxModel));
+
+//////////////////////////////////////////////////////////////////
+// Property tags
+//////////////////////////////////////////////////////////////////
+
+NEW_PROP_TAG(NumPhases);   //!< Number of fluid phases in the system
+NEW_PROP_TAG(Indices); //!< Enumerations for the model
+NEW_PROP_TAG(SpatialParams); //!< The type of the spatial parameters object
+NEW_PROP_TAG(FluidSystem); //!< The type of the fluid system to use
+NEW_PROP_TAG(Fluid); //!< The fluid used for the default fluid system
+NEW_PROP_TAG(ProblemEnableGravity); //!< Returns whether gravity is considered in the problem
+NEW_PROP_TAG(ImplicitMassUpwindWeight); //!< Returns weight of the upwind cell when calculating fluxes
+NEW_PROP_TAG(ImplicitMobilityUpwindWeight); //!< Weight for the upwind mobility in the velocity calculation
+NEW_PROP_TAG(SpatialParamsForchCoeff); //!< Property for the forchheimer coefficient
+// \}
+}
+
+} // end namepace
+
+#endif
diff --git a/dumux/implicit/1p/1ppropertydefaults.hh b/dumux/implicit/1p/1ppropertydefaults.hh
new file mode 100644
index 0000000000..27ef59c662
--- /dev/null
+++ b/dumux/implicit/1p/1ppropertydefaults.hh
@@ -0,0 +1,109 @@
+// -*- mode: C++; tab-width: 4; indent-tabs-mode: nil; c-basic-offset: 4 -*-
+// vi: set et ts=4 sw=4 sts=4:
+/*****************************************************************************
+ *   See the file COPYING for full copying permissions.                      *
+ *                                                                           *
+ *   This program is free software: you can redistribute it and/or modify    *
+ *   it under the terms of the GNU General Public License as published by    *
+ *   the Free Software Foundation, either version 2 of the License, or       *
+ *   (at your option) any later version.                                     *
+ *                                                                           *
+ *   This program is distributed in the hope that it will be useful,         *
+ *   but WITHOUT ANY WARRANTY; without even the implied warranty of          *
+ *   MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the            *
+ *   GNU General Public License for more details.                            *
+ *                                                                           *
+ *   You should have received a copy of the GNU General Public License       *
+ *   along with this program.  If not, see <http://www.gnu.org/licenses/>.   *
+ *****************************************************************************/
+/*!
+ * \ingroup Properties
+ * \ingroup BoxProperties
+ * \ingroup OnePBoxModel
+ * \file
+ *
+ * \brief Defines the properties required for the one-phase BOX model.
+ */
+#ifndef DUMUX_1P_PROPERTY_DEFAULTS_HH
+#define DUMUX_1P_PROPERTY_DEFAULTS_HH
+
+#include <dumux/boxmodels/common/boxproperties.hh>
+
+#include "1pmodel.hh"
+#include "1plocalresidual.hh"
+#include "1pvolumevariables.hh"
+#include <dumux/boxmodels/common/boxdarcyfluxvariables.hh>
+#include "1pindices.hh"
+
+#include <dumux/material/fluidsystems/gasphase.hh>
+#include <dumux/material/fluidsystems/liquidphase.hh>
+#include <dumux/material/components/nullcomponent.hh>
+#include <dumux/material/fluidsystems/1pfluidsystem.hh>
+#include <dumux/material/spatialparams/boxspatialparams1p.hh>
+
+namespace Dumux
+{
+// \{
+
+///////////////////////////////////////////////////////////////////////////
+// default property values for the isothermal single phase model
+///////////////////////////////////////////////////////////////////////////
+namespace Properties {
+SET_INT_PROP(BoxOneP, NumEq, 1); //!< set the number of equations to 1
+SET_INT_PROP(BoxOneP, NumPhases, 1); //!< The number of phases in the 1p model is 1
+
+//! The local residual function
+SET_TYPE_PROP(BoxOneP,
+              LocalResidual,
+              OnePLocalResidual<TypeTag>);
+
+//! the Model property
+SET_TYPE_PROP(BoxOneP, Model, OnePBoxModel<TypeTag>);
+
+//! the VolumeVariables property
+SET_TYPE_PROP(BoxOneP, VolumeVariables, OnePVolumeVariables<TypeTag>);
+
+//! the FluxVariables property
+SET_TYPE_PROP(BoxOneP, FluxVariables, BoxDarcyFluxVariables<TypeTag>);
+
+//! The indices required by the isothermal single-phase model
+SET_TYPE_PROP(BoxOneP, Indices, OnePIndices);
+
+//! The spatial parameters to be employed. 
+//! Use BoxSpatialParamsOneP by default.
+SET_TYPE_PROP(BoxOneP, SpatialParams, BoxSpatialParamsOneP<TypeTag>);
+
+//! The weight of the upwind control volume when calculating
+//! fluxes. Use central differences by default.
+SET_SCALAR_PROP(BoxOneP, ImplicitMassUpwindWeight, 0.5);
+
+//! weight for the upwind mobility in the velocity calculation
+//! fluxes. Use central differences by default.
+SET_SCALAR_PROP(BoxOneP, ImplicitMobilityUpwindWeight, 0.5);
+
+//! The fluid system to use by default
+SET_TYPE_PROP(BoxOneP, FluidSystem, Dumux::FluidSystems::OneP<typename GET_PROP_TYPE(TypeTag, Scalar), typename GET_PROP_TYPE(TypeTag, Fluid)>);
+
+SET_PROP(BoxOneP, Fluid)
+{ private:
+    typedef typename GET_PROP_TYPE(TypeTag, Scalar) Scalar;
+public:
+    typedef Dumux::LiquidPhase<Scalar, Dumux::NullComponent<Scalar> > type;
+};
+
+// enable gravity by default
+SET_BOOL_PROP(BoxOneP, ProblemEnableGravity, true);
+
+//! default value for the forchheimer coefficient
+// Source: Ward, J.C. 1964 Turbulent flow in porous media. ASCE J. Hydraul. Div 90.
+//        Actually the Forchheimer coefficient is also a function of the dimensions of the
+//        porous medium. Taking it as a constant is only a first approximation
+//        (Nield, Bejan, Convection in porous media, 2006, p. 10)
+SET_SCALAR_PROP(BoxModel, SpatialParamsForchCoeff, 0.55);
+
+// \}
+} // end namepace Properties
+
+} // end namepace Dumux
+
+#endif
diff --git a/dumux/implicit/1p/1pvolumevariables.hh b/dumux/implicit/1p/1pvolumevariables.hh
new file mode 100644
index 0000000000..b262b85b77
--- /dev/null
+++ b/dumux/implicit/1p/1pvolumevariables.hh
@@ -0,0 +1,203 @@
+// -*- mode: C++; tab-width: 4; indent-tabs-mode: nil; c-basic-offset: 4 -*-
+// vi: set et ts=4 sw=4 sts=4:
+/*****************************************************************************
+ *   See the file COPYING for full copying permissions.                      *
+ *                                                                           *
+ *   This program is free software: you can redistribute it and/or modify    *
+ *   it under the terms of the GNU General Public License as published by    *
+ *   the Free Software Foundation, either version 2 of the License, or       *
+ *   (at your option) any later version.                                     *
+ *                                                                           *
+ *   This program is distributed in the hope that it will be useful,         *
+ *   but WITHOUT ANY WARRANTY; without even the implied warranty of          *
+ *   MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the            *
+ *   GNU General Public License for more details.                            *
+ *                                                                           *
+ *   You should have received a copy of the GNU General Public License       *
+ *   along with this program.  If not, see <http://www.gnu.org/licenses/>.   *
+ *****************************************************************************/
+/*!
+ * \file
+ *
+ * \brief Quantities required by the one-phase box model defined on a vertex.
+ */
+#ifndef DUMUX_1P_VOLUME_VARIABLES_HH
+#define DUMUX_1P_VOLUME_VARIABLES_HH
+
+#include "1pproperties.hh"
+#include <dumux/boxmodels/common/boxvolumevariables.hh>
+
+#include <dumux/material/fluidstates/immisciblefluidstate.hh>
+
+namespace Dumux
+{
+
+/*!
+ * \ingroup OnePBoxModel
+ * \ingroup BoxVolumeVariables
+ * \brief Contains the quantities which are constant within a
+ *        finite volume in the one-phase model.
+ */
+template <class TypeTag>
+class OnePVolumeVariables : public BoxVolumeVariables<TypeTag>
+{
+    typedef BoxVolumeVariables<TypeTag> ParentType;
+
+    typedef typename GET_PROP_TYPE(TypeTag, VolumeVariables) Implementation;
+    typedef typename GET_PROP_TYPE(TypeTag, Scalar) Scalar;
+    typedef typename GET_PROP_TYPE(TypeTag, Problem) Problem;
+    typedef typename GET_PROP_TYPE(TypeTag, FVElementGeometry) FVElementGeometry;
+    typedef typename GET_PROP_TYPE(TypeTag, PrimaryVariables) PrimaryVariables;
+    typedef typename GET_PROP_TYPE(TypeTag, Indices) Indices;
+    typedef typename GET_PROP_TYPE(TypeTag, FluidSystem) FluidSystem;
+
+    typedef typename GET_PROP_TYPE(TypeTag, GridView) GridView;
+    typedef typename GridView::template Codim<0>::Entity Element;
+
+public:
+    //! Type of the fluid state
+    typedef Dumux::ImmiscibleFluidState<Scalar, FluidSystem> FluidState;
+
+    /*!
+     * \copydoc BoxVolumeVariables::update
+     */
+    void update(const PrimaryVariables &priVars,
+                const Problem &problem,
+                const Element &element,
+                const FVElementGeometry &fvGeometry,
+                const int scvIdx,
+                const bool isOldSol)
+    {
+        ParentType::update(priVars, problem, element, fvGeometry, scvIdx, isOldSol);
+
+        completeFluidState(priVars, problem, element, fvGeometry, scvIdx, fluidState_);
+        // porosity
+        porosity_ = problem.spatialParams().porosity(element,
+                                                         fvGeometry,
+                                                         scvIdx);
+
+        // energy related quantities not contained in the fluid state
+        asImp_().updateEnergy_(priVars, problem, element, fvGeometry, scvIdx, isOldSol);
+    };
+
+    /*!
+     * \copydoc BoxModel::completeFluidState
+     */
+    static void completeFluidState(const PrimaryVariables& priVars,
+                                   const Problem& problem,
+                                   const Element& element,
+                                   const FVElementGeometry& fvGeometry,
+                                   const int scvIdx,
+                                   FluidState& fluidState)
+    {
+        Scalar t = Implementation::temperature_(priVars, problem, element,
+                                                fvGeometry, scvIdx);
+        fluidState.setTemperature(t);
+
+        fluidState.setPressure(/*phaseIdx=*/0, priVars[Indices::pressureIdx]);
+
+        // saturation in a single phase is always 1 and thus redundant
+        // to set. But since we use the fluid state shared by the
+        // immiscible multi-phase models, so we have to set it here...
+        fluidState.setSaturation(/*phaseIdx=*/0, 1.0);
+
+        typename FluidSystem::ParameterCache paramCache;
+        paramCache.updatePhase(fluidState, /*phaseIdx=*/0);
+
+        Scalar value = FluidSystem::density(fluidState, paramCache,  /*phaseIdx=*/0);
+        fluidState.setDensity(/*phaseIdx=*/0, value);
+
+        value = FluidSystem::viscosity(fluidState, paramCache,  /*phaseIdx=*/0);
+        fluidState.setViscosity(/*phaseIdx=*/0, value);
+    }
+
+    /*!
+     * \brief Return temperature \f$\mathrm{[K]}\f$ inside the sub-control volume.
+     *
+     * Note that we assume thermodynamic equilibrium, i.e. the
+     * temperatures of the rock matrix and of all fluid phases are
+     * identical.
+     */
+    Scalar temperature() const
+    { return fluidState_.temperature(); }
+
+    /*!
+     * \brief Return the effective pressure \f$\mathrm{[Pa]}\f$ of a given phase within
+     *        the control volume.
+     */
+    Scalar pressure() const
+    { return fluidState_.pressure(/*phaseIdx=*/0); }
+
+    /*!
+     * \brief Return the mass density \f$\mathrm{[kg/m^3]}\f$ of a given phase within the
+     *        control volume.
+     */
+    Scalar density() const
+    { return fluidState_.density(/*phaseIdx=*/0); }
+
+    /*!
+     * \brief Return the dynamic viscosity \f$\mathrm{[Pa s]}\f$ of the fluid within the
+     *        control volume.
+     */
+    Scalar viscosity() const
+    { return fluidState_.viscosity(/*phaseIdx=*/0); }
+
+    /*!
+     * \brief Returns the mobility.
+     * 
+     * This function enables the use of BoxDarcyFluxVariables 
+     * with the 1p box model, ALTHOUGH the term mobility is
+     * usually not employed in the one phase context. 
+     *
+     * \param phaseIdx The phase index
+     */
+    Scalar mobility(int phaseIdx = 0) const
+    { return 1.0/fluidState_.viscosity(phaseIdx); }
+
+    /*!
+     * \brief Return the average porosity \f$\mathrm{[-]}\f$ within the control volume.
+     */
+    Scalar porosity() const
+    { return porosity_; }
+
+    /*!
+     * \brief Return the fluid state of the control volume.
+     */
+    const FluidState &fluidState() const
+    { return fluidState_; }
+
+protected:
+    static Scalar temperature_(const PrimaryVariables &priVars,
+                            const Problem& problem,
+                            const Element &element,
+                            const FVElementGeometry &fvGeometry,
+                            const int scvIdx)
+    {
+        return problem.boxTemperature(element, fvGeometry, scvIdx);
+    }
+
+    /*!
+     * \brief Called by update() to compute the energy related quantities.
+     */
+    void updateEnergy_(const PrimaryVariables &sol,
+                       const Problem &problem,
+                       const Element &element,
+                       const FVElementGeometry &fvGeometry,
+                       const int scvIdx,
+                       const bool isOldSol)
+    { }
+
+    FluidState fluidState_;
+    Scalar porosity_;
+
+private:
+    Implementation &asImp_()
+    { return *static_cast<Implementation*>(this); }
+
+    const Implementation &asImp_() const
+    { return *static_cast<const Implementation*>(this); }
+};
+
+}
+
+#endif
diff --git a/dumux/implicit/1p/Makefile.am b/dumux/implicit/1p/Makefile.am
new file mode 100644
index 0000000000..2dca3ed04d
--- /dev/null
+++ b/dumux/implicit/1p/Makefile.am
@@ -0,0 +1,4 @@
+1pdir = $(includedir)/dumux/boxmodels/1p
+1p_HEADERS = *.hh
+
+include $(top_srcdir)/am/global-rules
diff --git a/dumux/implicit/1p2c/1p2cfluxvariables.hh b/dumux/implicit/1p2c/1p2cfluxvariables.hh
new file mode 100644
index 0000000000..81a09a6098
--- /dev/null
+++ b/dumux/implicit/1p2c/1p2cfluxvariables.hh
@@ -0,0 +1,494 @@
+// -*- mode: C++; tab-width: 4; indent-tabs-mode: nil; c-basic-offset: 4 -*-
+// vi: set et ts=4 sw=4 sts=4:
+/*****************************************************************************
+ *   See the file COPYING for full copying permissions.                      *
+ *                                                                           *
+ *   This program is free software: you can redistribute it and/or modify    *
+ *   it under the terms of the GNU General Public License as published by    *
+ *   the Free Software Foundation, either version 2 of the License, or       *
+ *   (at your option) any later version.                                     *
+ *                                                                           *
+ *   This program is distributed in the hope that it will be useful,         *
+ *   but WITHOUT ANY WARRANTY; without even the implied warranty of          *
+ *   MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the            *
+ *   GNU General Public License for more details.                            *
+ *                                                                           *
+ *   You should have received a copy of the GNU General Public License       *
+ *   along with this program.  If not, see <http://www.gnu.org/licenses/>.   *
+ *****************************************************************************/
+/*!
+ * \file
+ *
+ * \brief This file contains the data which is required to calculate
+ *        all fluxes of fluid phases over a face of a finite volume.
+ *
+ * This means pressure and mole-fraction gradients, phase densities at
+ * the integration point, etc.
+ *
+ */
+#ifndef DUMUX_1P2C_FLUX_VARIABLES_HH
+#define DUMUX_1P2C_FLUX_VARIABLES_HH
+
+#include "1p2cproperties.hh"
+
+#include <dumux/common/math.hh>
+#include <dumux/common/valgrind.hh>
+
+namespace Dumux
+{
+
+/*!
+ * \ingroup OnePTwoCBoxModel
+ * \ingroup BoxFluxVariables
+ * \brief This template class contains the data which is required to
+ *        calculate the fluxes of the fluid phases over a face of a
+ *        finite volume for the one-phase, two-component model.
+ *
+ * This means pressure and mole-fraction gradients, phase densities at
+ * the intergration point, etc.
+ */
+template <class TypeTag>
+class OnePTwoCFluxVariables
+{
+    typedef typename GET_PROP_TYPE(TypeTag, Problem) Problem;
+    typedef typename GET_PROP_TYPE(TypeTag, VolumeVariables) VolumeVariables;
+    typedef typename GET_PROP_TYPE(TypeTag, ElementVolumeVariables) ElementVolumeVariables;
+    typedef typename GET_PROP_TYPE(TypeTag, SpatialParams) SpatialParams;
+
+    typedef typename GET_PROP_TYPE(TypeTag, Indices) Indices;
+    enum {
+        transportCompIdx = Indices::transportCompIdx
+    };
+
+    typedef typename GET_PROP_TYPE(TypeTag, GridView) GridView;
+    typedef typename GridView::template Codim<0>::Entity Element;
+    enum {
+        dim = GridView::dimension,
+        dimWorld = GridView::dimensionworld
+    };
+
+    typedef typename GridView::ctype CoordScalar;
+    typedef Dune::FieldVector<CoordScalar, dimWorld> GlobalPosition;
+    typedef typename GET_PROP_TYPE(TypeTag, Scalar) Scalar;
+    typedef Dune::FieldVector<Scalar, dim> DimVector;
+    typedef Dune::FieldMatrix<Scalar, dim, dim> DimMatrix;
+
+    typedef typename GET_PROP_TYPE(TypeTag, FVElementGeometry) FVElementGeometry;
+    typedef typename FVElementGeometry::SubControlVolumeFace SCVFace;
+
+public:
+    /*
+     * \brief The constructor
+     *
+     * \param problem The problem
+     * \param element The finite element
+     * \param fvGeometry The finite-volume geometry in the box scheme
+     * \param scvfIdx The local index of the SCV (sub-control-volume) face
+     * \param elemVolVars The volume variables of the current element
+     * \param onBoundary A boolean variable to specify whether the flux variables
+     * are calculated for interior SCV faces or boundary faces, default=false
+     */
+    OnePTwoCFluxVariables(const Problem &problem,
+                          const Element &element,
+                          const FVElementGeometry &fvGeometry,
+                          const int faceIdx,
+                          const ElementVolumeVariables &elemVolVars,
+                          const bool onBoundary = false)
+        : fvGeometry_(fvGeometry), faceIdx_(faceIdx), onBoundary_(onBoundary)
+    {
+        viscosity_ = Scalar(0);
+        molarDensity_ = Scalar(0);
+        density_ = Scalar(0);
+        potentialGrad_ = Scalar(0);
+        moleFractionGrad_ = Scalar(0);
+
+        calculateGradients_(problem, element, elemVolVars);
+        calculateK_(problem, element, elemVolVars);
+        calculateVelocities_(problem, element, elemVolVars);
+        calculatePorousDiffCoeff_(problem, element, elemVolVars);
+        calculateDispersionTensor_(problem, element, elemVolVars);
+    };
+
+public:
+    /*!
+    * \brief Return the pressure potential multiplied with the
+    *        intrinsic permeability  and the face normal which
+    *        goes from vertex i to vertex j.
+    *
+    * Note that the length of the face's normal is the area of the
+    * phase, so this is not the actual velocity but the integral of
+    * the velocity over the face's area. Also note that the phase
+    * mobility is not yet included here since this would require a
+    * decision on the upwinding approach (which is done in the
+    * actual model).
+    */
+   Scalar KmvpNormal() const
+   { return KmvpNormal_; }
+
+   /*!
+    * \brief Return the pressure potential multiplied with the
+    *        intrinsic permeability as vector (for velocity output).
+    */
+   DimVector Kmvp() const
+   { return Kmvp_; }
+
+   /*!
+    * \brief The face of the current sub-control volume. This may be either
+    *        an inner sub-control-volume face or a SCV face on the boundary.
+    */
+   const SCVFace &face() const
+   {
+       if (onBoundary_)
+           return fvGeometry_.boundaryFace[faceIdx_];
+       else
+           return fvGeometry_.subContVolFace[faceIdx_];
+   }
+
+    /*!
+     * \brief Return the intrinsic permeability tensor \f$\mathrm{[m^2]}\f$.
+     */
+    const DimMatrix &intrinsicPermeability() const
+    { return K_; }
+
+    /*!
+     * \brief Return the dispersion tensor \f$\mathrm{[m^2/s]}\f$.
+     */
+    const DimMatrix &dispersionTensor() const
+    { return dispersionTensor_; }
+
+    /*!
+     * \brief Return the pressure potential gradient \f$\mathrm{[Pa/m]}\f$.
+     */
+    const DimVector &potentialGrad() const
+    { return potentialGrad_; }
+
+
+    /*!
+     * \brief Return the mole-fraction gradient of a component in a phase \f$\mathrm{[mol/mol/m)]}\f$.
+     *
+     * \param compIdx The index of the considered component
+     */
+    const DimVector &moleFractionGrad(int compIdx) const
+    {
+       if (compIdx != 1)
+       { DUNE_THROW(Dune::InvalidStateException,
+                "The 1p2c model is supposed to need "
+                "only the concentration gradient of "
+                "the second component!"); }
+       return moleFractionGrad_;
+    };
+
+    /*!
+    * \brief The binary diffusion coefficient for each fluid phase in the porous medium \f$\mathrm{[m^2/s]}\f$.
+    */
+    Scalar porousDiffCoeff() const
+    {
+        // TODO: tensorial porousDiffCoeff_usion coefficients
+        return porousDiffCoeff_;
+    };
+
+    /*!
+    * \brief Return viscosity \f$\mathrm{[Pa s]}\f$ of a phase at the integration
+    *        point.
+    */
+    Scalar viscosity() const
+    { return viscosity_;}
+
+    /*!
+     * \brief Return molar density \f$\mathrm{[mol/m^3]}\f$ of a phase at the integration
+     *        point.
+     */
+    Scalar molarDensity() const
+    { return molarDensity_; }
+
+    /*!
+     * \brief Return density \f$\mathrm{[kg/m^3]}\f$ of a phase at the integration
+     *        point.
+     */
+    Scalar density() const
+    { return density_; }
+
+    /*!
+     * \brief Given the intrinsic permeability times the pressure
+     *        potential gradient and SCV face normal for a phase,
+     *        return the local index of the upstream control volume
+     *        for a given phase.
+     *
+     *        \param normalFlux The flux over a face of the sub-control volume
+     */
+    int upstreamIdx(Scalar normalFlux) const
+    { return (normalFlux >= 0)?face().i:face().j; }
+
+    /*!
+     * \brief Given the intrinsic permeability times the pressure
+     *        potential gradient and SCV face normal for a phase,
+     *        return the local index of the downstream control volume
+     *        for a given phase.
+     *
+     *        \param normalFlux The flux over a face of the sub-control volume
+     */
+    int downstreamIdx(Scalar normalFlux) const
+    { return (normalFlux > 0)?face().j:face().i; }
+
+    /*!
+    * \brief Return the local index of the upstream control volume
+    *        for a given phase.
+    */
+   int upstreamIdx() const
+   { return upstreamIdx_; }
+
+   /*!
+    * \brief Return the local index of the downstream control volume
+    *        for a given phase.
+    */
+   int downstreamIdx() const
+   { return downstreamIdx_; }
+
+protected:
+
+    /*!
+     * \brief Calculation of the pressure and mole-/mass-fraction gradients.
+     *
+     *        \param problem The considered problem file
+     *        \param element The considered element of the grid
+     *        \param elemVolVars The parameters stored in the considered element
+     */
+    void calculateGradients_(const Problem &problem,
+                             const Element &element,
+                             const ElementVolumeVariables &elemVolVars)
+    {
+        const VolumeVariables &volVarsI = elemVolVars[face().i];
+        const VolumeVariables &volVarsJ = elemVolVars[face().j];
+
+        DimVector tmp;
+        //The decision of the if-statement depends on the function useTwoPointGradient(const Element &element,
+        //int vertexI,int vertexJ) defined in test/tissue_tumor_spatialparameters.hh
+        if (!problem.spatialParams().useTwoPointGradient(element, face().i, face().j)) {
+            // use finite-element gradients
+            tmp = 0.0;
+            for (int idx = 0;
+                    idx < fvGeometry_.numFAP;
+                    idx++) // loop over adjacent vertices
+            {
+                // FE gradient at vertex idx
+                const DimVector &feGrad = face().grad[idx];
+
+                // index for the element volume variables 
+                int volVarsIdx = face().fapIndices[idx];
+
+                // the pressure gradient
+                tmp = feGrad;
+                tmp *= elemVolVars[volVarsIdx].pressure();
+                potentialGrad_ += tmp;
+
+                // the mole-fraction gradient
+                tmp = feGrad;
+                tmp *= elemVolVars[volVarsIdx].moleFraction(transportCompIdx);
+                moleFractionGrad_ += tmp;
+
+                // phase viscosity
+                viscosity_ += elemVolVars[volVarsIdx].viscosity()*face().shapeValue[idx];
+
+                //phase molar density
+                molarDensity_ += elemVolVars[volVarsIdx].molarDensity()*face().shapeValue[idx];
+
+                //phase density
+                density_ += elemVolVars[volVarsIdx].density()*face().shapeValue[idx];
+            }
+        }
+        else {
+            // use two-point gradients
+            const GlobalPosition &globalPosI = element.geometry().corner(face().i);
+            const GlobalPosition &globalPosJ = element.geometry().corner(face().j);
+            tmp = globalPosI;
+            tmp -= globalPosJ;
+            Scalar dist = tmp.two_norm();
+
+            tmp = face().normal;
+            tmp /= face().normal.two_norm()*dist;
+
+            potentialGrad_ = tmp;
+            potentialGrad_ *= volVarsJ.pressure() - volVarsI.pressure();
+            moleFractionGrad_ = tmp;
+            moleFractionGrad_ *= volVarsJ.moleFraction(transportCompIdx) - volVarsI.moleFraction(transportCompIdx);
+        }
+
+        ///////////////
+        // correct the pressure gradients by the gravitational acceleration
+        ///////////////
+        if (GET_PARAM_FROM_GROUP(TypeTag, bool, Problem, EnableGravity)) {
+            // calculate the phase density at the integration point. we
+            // only do this if the wetting phase is present in both cells
+            Scalar rhoI = elemVolVars[face().i].density();
+            Scalar rhoJ = elemVolVars[face().j].density();
+            Scalar density = (rhoI + rhoJ)/2;
+
+            // estimate the gravitational acceleration at a given SCV face
+            // using the arithmetic mean
+            DimVector f(problem.boxGravity(element, fvGeometry_, face().i));
+            f += problem.boxGravity(element, fvGeometry_, face().j);
+            f /= 2;
+
+            // make it a force
+            f *= density;
+
+            // calculate the final potential gradient
+            potentialGrad_ -= f;
+        }
+    }
+
+    /*!
+    * \brief Calculation of the harmonic mean of the intrinsic permeability
+    *        uses the meanK function in the boxspatialparameters.hh file in the folder
+    *        material/spatialparameters
+    *
+    *        \param problem The considered problem file
+    *        \param element The considered element of the grid
+    *        \param elemVolVars The parameters stored in the considered element
+    */
+    void calculateK_(const Problem &problem,
+                     const Element &element,
+                     const ElementVolumeVariables &elemVolVars)
+    {
+        const SpatialParams &sp = problem.spatialParams();
+        sp.meanK(K_,
+                 sp.intrinsicPermeability(element,
+                                          fvGeometry_,
+                                          face().i),
+                 sp.intrinsicPermeability(element,
+                                          fvGeometry_,
+                                          face().j));
+
+    }
+
+    /*!
+      * \brief Calculation of the velocity normal to face using Darcy's law.
+      *     Tensorial permeability is multiplied with the potential gradient and the face normal.
+      *     Identify upstream node of face.
+      *
+      *        \param problem The considered problem file
+      *        \param element The considered element of the grid
+      *        \param elemVolVars The parameters stored in the considered element
+      */
+    void calculateVelocities_(const Problem &problem,
+                              const Element &element,
+                              const ElementVolumeVariables &elemVolVars)
+    {
+        K_.mv(potentialGrad_, Kmvp_);
+        KmvpNormal_ = -(Kmvp_*face().normal);
+
+        // set the upstream and downstream vertices
+        upstreamIdx_ = face().i;
+        downstreamIdx_ = face().j;
+
+        if (KmvpNormal_ < 0)
+        {
+            std::swap(upstreamIdx_,
+                      downstreamIdx_);
+        }
+    }
+    /*!
+    * \brief Calculation of the effective diffusion coefficient.
+    *
+    *        \param problem The considered problem file
+    *        \param element The considered element of the grid
+    *        \param elemVolVars The parameters stored in the considered element
+    */
+    void calculatePorousDiffCoeff_(const Problem &problem,
+                                   const Element &element,
+                                   const ElementVolumeVariables &elemVolVars)
+    {
+        const VolumeVariables &volVarsI = elemVolVars[face().i];
+        const VolumeVariables &volVarsJ = elemVolVars[face().j];
+
+        // Diffusion coefficient in the porous medium
+        porousDiffCoeff_
+            = harmonicMean(volVarsI.porosity() * volVarsI.tortuosity() * volVarsI.diffCoeff(),
+               volVarsJ.porosity() * volVarsJ.tortuosity() * volVarsJ.diffCoeff());
+//            = 1./2*(volVarsI.porosity() * volVarsI.tortuosity() * volVarsI.diffCoeff() +
+//                    volVarsJ.porosity() * volVarsJ.tortuosity() * volVarsJ.diffCoeff());
+    }
+
+    /*!
+    * \brief Calculation of the dispersion.
+    *
+    *        \param problem The considered problem file
+    *        \param element The considered element of the grid
+    *        \param elemVolVars The parameters stored in the considered element
+    */
+    void calculateDispersionTensor_(const Problem &problem,
+                                    const Element &element,
+                                    const ElementVolumeVariables &elemVolVars)
+    {
+        const VolumeVariables &volVarsI = elemVolVars[face().i];
+        const VolumeVariables &volVarsJ = elemVolVars[face().j];
+
+        //calculate dispersivity at the interface: [0]: alphaL = longitudinal disp. [m], [1] alphaT = transverse disp. [m]
+        Scalar dispersivity[2];
+        dispersivity[0] = 0.5 * (volVarsI.dispersivity()[0] +  volVarsJ.dispersivity()[0]);
+        dispersivity[1] = 0.5 * (volVarsI.dispersivity()[1] +  volVarsJ.dispersivity()[1]);
+
+        //calculate velocity at interface: v = -1/mu * vDarcy = -1/mu * K * grad(p)
+        DimVector velocity;
+        Valgrind::CheckDefined(potentialGrad());
+        Valgrind::CheckDefined(K_);
+        K_.mv(potentialGrad(), velocity);
+        velocity /= - 0.5 * (volVarsI.viscosity() + volVarsJ.viscosity());
+
+        //matrix multiplication of the velocity at the interface: vv^T
+        dispersionTensor_ = 0;
+        for (int i=0; i<dim; i++)
+            for (int j = 0; j<dim; j++)
+                dispersionTensor_[i][j]=velocity[i]*velocity[j];
+
+        //normalize velocity product --> vv^T/||v||, [m/s]
+        Scalar vNorm = velocity.two_norm();
+
+        dispersionTensor_ /= vNorm;
+        if (vNorm < 1e-20)
+            dispersionTensor_ = 0;
+
+        //multiply with dispersivity difference: vv^T/||v||*(alphaL - alphaT), [m^2/s] --> alphaL = longitudinal disp., alphaT = transverse disp.
+        dispersionTensor_ *= (dispersivity[0] - dispersivity[1]);
+
+        //add ||v||*alphaT to the main diagonal:vv^T/||v||*(alphaL - alphaT) + ||v||*alphaT, [m^2/s]
+        for (int i = 0; i<dim; i++)
+            dispersionTensor_[i][i] += vNorm*dispersivity[1];
+    }
+
+    const FVElementGeometry &fvGeometry_;
+    const int faceIdx_;
+    const bool onBoundary_;
+
+    //! pressure potential gradient
+    DimVector potentialGrad_;
+    //! mole-fraction gradient
+    DimVector moleFractionGrad_;
+    //! the effective diffusion coefficent in the porous medium
+    Scalar porousDiffCoeff_;
+
+    //! the dispersion tensor in the porous medium
+    DimMatrix dispersionTensor_;
+
+    //! the intrinsic permeability tensor
+    DimMatrix K_;
+    // intrinsic permeability times pressure potential gradient
+    DimVector Kmvp_;
+    // projected on the face normal
+    Scalar KmvpNormal_;
+
+    // local index of the upwind vertex for each phase
+   int upstreamIdx_;
+   // local index of the downwind vertex for each phase
+   int downstreamIdx_;
+
+    //! viscosity of the fluid at the integration point
+    Scalar viscosity_;
+
+    //! molar densities of the fluid at the integration point
+    Scalar molarDensity_, density_;
+};
+
+} // end namepace
+
+#endif
diff --git a/dumux/implicit/1p2c/1p2cindices.hh b/dumux/implicit/1p2c/1p2cindices.hh
new file mode 100644
index 0000000000..90a3d14f79
--- /dev/null
+++ b/dumux/implicit/1p2c/1p2cindices.hh
@@ -0,0 +1,63 @@
+// -*- mode: C++; tab-width: 4; indent-tabs-mode: nil; c-basic-offset: 4 -*-
+// vi: set et ts=4 sw=4 sts=4:
+/*****************************************************************************
+ *   See the file COPYING for full copying permissions.                      *
+ *                                                                           *
+ *   This program is free software: you can redistribute it and/or modify    *
+ *   it under the terms of the GNU General Public License as published by    *
+ *   the Free Software Foundation, either version 2 of the License, or       *
+ *   (at your option) any later version.                                     *
+ *                                                                           *
+ *   This program is distributed in the hope that it will be useful,         *
+ *   but WITHOUT ANY WARRANTY; without even the implied warranty of          *
+ *   MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the            *
+ *   GNU General Public License for more details.                            *
+ *                                                                           *
+ *   You should have received a copy of the GNU General Public License       *
+ *   along with this program.  If not, see <http://www.gnu.org/licenses/>.   *
+ *****************************************************************************/
+/*!
+ * \file
+ *
+ * \brief Defines the primary variable and equation indices used by
+ *        the 1p2c model
+ */
+
+#ifndef DUMUX_1P2C_INDICES_HH
+#define DUMUX_1P2C_INDICES_HH
+
+#include "1p2cproperties.hh"
+
+namespace Dumux
+{
+// \{
+
+/*!
+ * \ingroup OnePTwoCBoxModel
+ * \ingroup BoxIndices
+ * \brief The indices for the isothermal single-phase, two-component model.
+ */
+template <class TypeTag, int PVOffset = 0>
+struct OnePTwoCIndices
+{
+
+    //! Set the default phase used by the fluid system to the first one
+    static const int phaseIdx = GET_PROP_VALUE(TypeTag, PhaseIdx);
+
+    //! Component indices
+    static const int phaseCompIdx = phaseIdx;//!< The index of the main component of the considered phase
+    static const int transportCompIdx = (unsigned int)(1-phaseIdx); //!< The index of the transported (minor) component; ASSUMES phase indices of 0 and 1
+
+    // Equation indices
+   static const int conti0EqIdx = PVOffset + 0; //!< continuity equation index
+   static const int transportEqIdx = PVOffset + 1; //!< transport equation index
+
+    // primary variable indices
+    static const int pressureIdx = PVOffset + 0; //!< pressure
+    static const int massOrMoleFracIdx = PVOffset + 1; //!< mole fraction of the second component
+};
+
+// \}
+}
+
+#endif
diff --git a/dumux/implicit/1p2c/1p2clocalresidual.hh b/dumux/implicit/1p2c/1p2clocalresidual.hh
new file mode 100644
index 0000000000..6d34e380d7
--- /dev/null
+++ b/dumux/implicit/1p2c/1p2clocalresidual.hh
@@ -0,0 +1,297 @@
+// -*- mode: C++; tab-width: 4; indent-tabs-mode: nil; c-basic-offset: 4 -*-
+// vi: set et ts=4 sw=4 sts=4:
+/*****************************************************************************
+ *   See the file COPYING for full copying permissions.                      *
+ *                                                                           *
+ *   This program is free software: you can redistribute it and/or modify    *
+ *   it under the terms of the GNU General Public License as published by    *
+ *   the Free Software Foundation, either version 2 of the License, or       *
+ *   (at your option) any later version.                                     *
+ *                                                                           *
+ *   This program is distributed in the hope that it will be useful,         *
+ *   but WITHOUT ANY WARRANTY; without even the implied warranty of          *
+ *   MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the            *
+ *   GNU General Public License for more details.                            *
+ *                                                                           *
+ *   You should have received a copy of the GNU General Public License       *
+ *   along with this program.  If not, see <http://www.gnu.org/licenses/>.   *
+ *****************************************************************************/
+/*!
+ * \file
+ *
+ * \brief Element-wise calculation the local Jacobian for the single-phase,
+ *        two-component model in the BOX scheme.
+ */
+
+#ifndef DUMUX_ONEP_TWOC_LOCAL_RESIDUAL_HH
+#define DUMUX_ONEP_TWOC_LOCAL_RESIDUAL_HH
+#define VELOCITY_OUTPUT 1 //1 turns velocity output on, 0 turns it off
+
+#include <dumux/boxmodels/common/boxmodel.hh>
+
+#include <dumux/boxmodels/1p2c/1p2cproperties.hh>
+#include <dumux/boxmodels/1p2c/1p2cvolumevariables.hh>
+#include <dumux/boxmodels/1p2c/1p2cfluxvariables.hh>
+
+#include <dune/common/collectivecommunication.hh>
+#include <vector>
+#include <iostream>
+
+namespace Dumux
+{
+/*!
+ *
+ * \ingroup OnePTwoCBoxModel
+ * \ingroup BoxLocalResidual
+ * \brief Calculate the local Jacobian for the single-phase,
+ *        two-component model in the BOX scheme.
+ *
+ *  This class is used to fill the gaps in BoxLocalResidual for the 1p2c flow and transport.
+ */
+template<class TypeTag>
+class OnePTwoCLocalResidual : public GET_PROP_TYPE(TypeTag, BaseLocalResidual)
+{
+protected:
+    typedef typename GET_PROP_TYPE(TypeTag, LocalResidual) Implementation;
+
+    typedef typename GET_PROP_TYPE(TypeTag, Scalar) Scalar;
+    typedef typename GET_PROP_TYPE(TypeTag, GridView) GridView;
+    typedef typename GridView::IntersectionIterator IntersectionIterator;
+
+    enum { dim = GridView::dimension };
+    typedef Dune::FieldVector<Scalar, dim> DimVector;
+
+    typedef typename GET_PROP_TYPE(TypeTag, VolumeVariables) VolumeVariables;
+    typedef typename GET_PROP_TYPE(TypeTag, FluxVariables) FluxVariables;
+    typedef typename GET_PROP_TYPE(TypeTag, ElementVolumeVariables) ElementVolumeVariables;
+    typedef typename GET_PROP_TYPE(TypeTag, PrimaryVariables) PrimaryVariables;
+    typedef typename GET_PROP_TYPE(TypeTag, BoundaryTypes) BoundaryTypes;
+    typedef typename GET_PROP_TYPE(TypeTag, FluidSystem) FluidSystem;
+    typedef typename GET_PROP_TYPE(TypeTag, Indices) Indices;
+
+    enum {
+        numEq = GET_PROP_VALUE(TypeTag, NumEq),
+
+        //phase index
+        phaseIdx = Indices::phaseIdx,
+        transportCompIdx = Indices::transportCompIdx
+    };
+    // indices of the primary variables
+    enum {
+        pressuerIdx = Indices::pressureIdx,
+        massOrMoleFracIdx = Indices::massOrMoleFracIdx
+    };
+    // indices of the equations
+    enum {
+        conti0EqIdx = Indices::conti0EqIdx,
+        transportEqIdx = Indices::transportEqIdx
+    };
+
+    //! property that defines whether mole or mass fractions are used
+    static const bool useMoles = GET_PROP_VALUE(TypeTag, UseMoles);
+
+
+
+public:
+    /*!
+     * \brief Constructor. Sets the upwind weight.
+     */
+    OnePTwoCLocalResidual()
+    {
+        // retrieve the upwind weight for the mass conservation equations. Use the value
+        // specified via the property system as default, and overwrite
+        // it by the run-time parameter from the Dune::ParameterTree
+        upwindWeight_ = GET_PARAM_FROM_GROUP(TypeTag, Scalar, Implicit, MassUpwindWeight);
+    };
+
+    /*!
+     * \brief Evaluate the amount of all conservation quantities
+     *        (e.g. phase mass) within a finite volume.
+     *
+     *        \param storage The mass of the component within the sub-control volume
+     *        \param scvIdx The index of the considered face of the sub-control volume
+     *        \param usePrevSol Evaluate function with solution of current or previous time step
+     */
+    void computeStorage(PrimaryVariables &storage, const int scvIdx, const bool usePrevSol) const
+    {
+        // if flag usePrevSol is set, the solution from the previous
+        // time step is used, otherwise the current solution is
+        // used. The secondary variables are used accordingly.  This
+        // is required to compute the derivative of the storage term
+        // using the implicit euler method.
+        const ElementVolumeVariables &elemVolVars = usePrevSol ? this->prevVolVars_() : this->curVolVars_();
+        const VolumeVariables &volVars = elemVolVars[scvIdx];
+
+        storage = 0;
+        if(!useMoles)
+        {
+            // storage term of continuity equation - massfractions
+            storage[conti0EqIdx] +=
+                volVars.fluidState().density(phaseIdx)*volVars.porosity();
+            //storage term of the transport equation - massfractions
+            storage[transportEqIdx] +=
+                volVars.fluidState().density(phaseIdx) * volVars.fluidState().massFraction(phaseIdx, transportCompIdx) * volVars.porosity();
+        }
+        else
+        {
+            // storage term of continuity equation- molefractions
+            //careful: molarDensity changes with moleFrac!
+            storage[conti0EqIdx] += volVars.molarDensity()*volVars.porosity();
+            // storage term of the transport equation - molefractions
+            storage[transportEqIdx] +=
+                volVars.fluidState().molarDensity(phaseIdx)*volVars.fluidState().moleFraction(phaseIdx, transportCompIdx) *
+                volVars.porosity();
+        }
+
+    }
+
+    /*!
+     * \brief Evaluate the mass flux over a face of a sub-control
+     *        volume.
+     *
+     *        \param flux The flux over the SCV (sub-control-volume) face for each component
+     *        \param faceIdx The index of the considered face of the sub control volume
+     *        \param onBoundary A boolean variable to specify whether the flux variables
+     *               are calculated for interior SCV faces or boundary faces, default=false
+     */
+    void computeFlux(PrimaryVariables &flux, const int faceIdx, const bool onBoundary=false) const
+    {
+        flux = 0;
+        FluxVariables fluxVars(this->problem_(),
+                               this->element_(),
+                               this->fvGeometry_(),
+                               faceIdx,
+                               this->curVolVars_(),
+                               onBoundary);
+
+        asImp_()->computeAdvectiveFlux(flux, fluxVars);
+        asImp_()->computeDiffusiveFlux(flux, fluxVars);
+    }
+
+    /*!
+     * \brief Evaluate the advective mass flux of all components over
+     *        a face of a sub-control volume.
+     *
+     * \param flux The advective flux over the sub-control-volume face for each component
+     * \param fluxVars The flux variables at the current SCV
+     */
+    void computeAdvectiveFlux(PrimaryVariables &flux, const FluxVariables &fluxVars) const
+    {
+        ////////
+        // advective fluxes of all components in all phases
+        ////////
+
+        // data attached to upstream and the downstream vertices
+        // of the current phase
+        const VolumeVariables &up =
+            this->curVolVars_(fluxVars.upstreamIdx());
+        const VolumeVariables &dn =
+            this->curVolVars_(fluxVars.downstreamIdx());
+
+        if(!useMoles)
+        {
+            // total mass flux - massfraction
+            //KmvpNormal is the Darcy velocity multiplied with the normal vector, calculated in 1p2cfluxvariables.hh
+            flux[conti0EqIdx] +=
+                fluxVars.KmvpNormal() *
+                ((     upwindWeight_)*up.density()/up.viscosity()
+                 +
+                 ((1 - upwindWeight_)*dn.density()/dn.viscosity()));
+
+            // advective flux of the second component - massfraction
+            flux[transportEqIdx] +=
+                fluxVars.KmvpNormal() *
+                ((    upwindWeight_)*up.fluidState().density(phaseIdx) * up.fluidState().massFraction(phaseIdx, transportCompIdx)/up.viscosity()
+                 +
+                 (1 - upwindWeight_)*dn.fluidState().density(phaseIdx)*dn.fluidState().massFraction(phaseIdx, transportCompIdx)/dn.viscosity());
+        }
+        else
+        {
+            // total mass flux - molefraction
+            //KmvpNormal is the Darcy velocity multiplied with the normal vector, calculated in 1p2cfluxvariables.hh
+            flux[conti0EqIdx] +=
+                fluxVars.KmvpNormal() *
+                ((     upwindWeight_)*up.molarDensity()/up.viscosity()
+                 +
+                 ((1 - upwindWeight_)*dn.molarDensity()/dn.viscosity()));
+
+            // advective flux of the second component -molefraction
+            flux[transportEqIdx] +=
+                fluxVars.KmvpNormal() *
+                ((    upwindWeight_)*up.molarDensity() * up.fluidState().moleFraction(phaseIdx, transportCompIdx)/up.viscosity()
+                 +
+                 (1 - upwindWeight_)*dn.molarDensity() * dn.fluidState().moleFraction(phaseIdx, transportCompIdx)/dn.viscosity());
+        }
+
+    }
+
+    /*!
+     * \brief Adds the diffusive mass flux of all components over
+     *        a face of a sub-control volume.
+     *
+     * \param flux The diffusive flux over the sub-control-volume face for each component
+     * \param fluxVars The flux variables at the current SCV
+     */
+    void computeDiffusiveFlux(PrimaryVariables &flux, const FluxVariables &fluxVars) const
+    {
+        Scalar tmp(0);
+
+        // diffusive flux of second component
+        if(!useMoles)
+        {
+            // diffusive flux of the second component - massfraction
+            tmp = -(fluxVars.moleFractionGrad(transportCompIdx)*fluxVars.face().normal);
+            tmp *= fluxVars.porousDiffCoeff() * fluxVars.molarDensity();
+
+            // dispersive flux of second component - massfraction
+                       DimVector normalDisp;
+                       fluxVars.dispersionTensor().mv(fluxVars.face().normal, normalDisp);
+                       tmp -= fluxVars.molarDensity()*
+                       (normalDisp * fluxVars.moleFractionGrad(transportCompIdx));
+
+            // convert it to a mass flux and add it
+            flux[transportEqIdx] += tmp * FluidSystem::molarMass(transportCompIdx);
+        }
+        else
+        {
+            // diffusive flux of the second component - molefraction
+            tmp = -(fluxVars.moleFractionGrad(transportCompIdx)*fluxVars.face().normal);
+            tmp *= fluxVars.porousDiffCoeff() * fluxVars.molarDensity();
+
+            // dispersive flux of second component - molefraction
+                        DimVector normalDisp;
+                        fluxVars.dispersionTensor().mv(fluxVars.face().normal, normalDisp);
+                        tmp -= fluxVars.molarDensity()*
+                            (normalDisp * fluxVars.moleFractionGrad(transportCompIdx));
+
+            flux[transportEqIdx] += tmp;
+        }
+    }
+
+    /*!
+     * \brief Calculate the source term of the equation
+     *        \param source The source/sink in the SCV for each component
+     *        \param scvIdx The index of the vertex of the sub control volume
+     *
+     */
+    void computeSource(PrimaryVariables &source, const int scvIdx)
+    {
+        this->problem_().boxSDSource(source,
+                                     this->element_(),
+                                     this->fvGeometry_(),
+                                     scvIdx,
+                                     this->curVolVars_());
+    }
+
+    Implementation *asImp_()
+    { return static_cast<Implementation *> (this); }
+    const Implementation *asImp_() const
+    { return static_cast<const Implementation *> (this); }
+
+private:
+    Scalar upwindWeight_;
+};
+
+}
+
+#endif
diff --git a/dumux/implicit/1p2c/1p2cmodel.hh b/dumux/implicit/1p2c/1p2cmodel.hh
new file mode 100644
index 0000000000..3b70302f85
--- /dev/null
+++ b/dumux/implicit/1p2c/1p2cmodel.hh
@@ -0,0 +1,326 @@
+// -*- mode: C++; tab-width: 4; indent-tabs-mode: nil; c-basic-offset: 4 -*-
+// vi: set et ts=4 sw=4 sts=4:
+/*****************************************************************************
+ *   See the file COPYING for full copying permissions.                      *
+ *                                                                           *
+ *   This program is free software: you can redistribute it and/or modify    *
+ *   it under the terms of the GNU General Public License as published by    *
+ *   the Free Software Foundation, either version 2 of the License, or       *
+ *   (at your option) any later version.                                     *
+ *                                                                           *
+ *   This program is distributed in the hope that it will be useful,         *
+ *   but WITHOUT ANY WARRANTY; without even the implied warranty of          *
+ *   MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the            *
+ *   GNU General Public License for more details.                            *
+ *                                                                           *
+ *   You should have received a copy of the GNU General Public License       *
+ *   along with this program.  If not, see <http://www.gnu.org/licenses/>.   *
+ *****************************************************************************/
+/*!
+ * \file
+ *
+ * \brief Base class for all models which use the single-phase,
+ *        two-component box model.
+ *        Adaption of the BOX scheme to the one-phase two-component flow model.
+ */
+
+#ifndef DUMUX_ONEP_TWOC_MODEL_HH
+#define DUMUX_ONEP_TWOC_MODEL_HH
+
+#include "1p2cproperties.hh"
+#include "1p2clocalresidual.hh"
+
+#include <dumux/boxmodels/common/boxmodel.hh>
+
+namespace Dumux
+{
+
+/*!
+ * \ingroup OnePTwoCBoxModel
+ * \brief Adaption of the BOX scheme to the one-phase two-component flow model.
+ *
+ * This model implements a one-phase flow of a compressible fluid, that consists of two components,
+ * using a standard Darcy
+ * approach as the equation for the conservation of momentum:
+ \f[
+ v_{D} = - \frac{\textbf K}{\mu}
+ \left(\text{grad} p - \varrho {\textbf g} \right)
+ \f]
+ *
+ * Gravity can be enabled or disabled via the property system.
+ * By inserting this into the continuity equation, one gets
+ \f[
+ \Phi \frac{\partial \varrho}{\partial t} - \text{div} \left\{
+   \varrho \frac{\textbf K}{\mu}  \left(\text{grad}\, p - \varrho {\textbf g} \right)
+ \right\} = q \;,
+ \f]
+ *
+ * The transport of the components is described by the following equation:
+ \f[
+ \Phi \frac{ \partial \varrho x}{\partial t} - \text{div} \left( \varrho \frac{{\textbf K} x}{\mu} \left( \text{grad}\, p -
+ \varrho {\textbf g} \right) + \varrho \tau \Phi D \text{grad} x \right) = q.
+ \f]
+ *
+ * All equations are discretized using a fully-coupled vertex-centered
+ * finite volume (box) scheme as spatial and
+ * the implicit Euler method as time discretization.
+ *
+ * The primary variables are the pressure \f$p\f$ and the mole or mass fraction of dissolved component \f$x\f$.
+ */
+
+template<class TypeTag >
+class OnePTwoCBoxModel : public GET_PROP_TYPE(TypeTag, BaseModel)
+{
+    typedef typename GET_PROP_TYPE(TypeTag, FVElementGeometry) FVElementGeometry;
+    typedef typename GET_PROP_TYPE(TypeTag, VolumeVariables) VolumeVariables;
+    typedef typename GET_PROP_TYPE(TypeTag, FluxVariables) FluxVariables;
+    typedef typename GET_PROP_TYPE(TypeTag, FluidSystem) FluidSystem;
+    typedef typename GET_PROP_TYPE(TypeTag, ElementVolumeVariables) ElementVolumeVariables;
+    typedef typename GET_PROP_TYPE(TypeTag, ElementBoundaryTypes) ElementBoundaryTypes;
+    typedef typename GET_PROP_TYPE(TypeTag, SolutionVector) SolutionVector;
+
+    typedef typename GET_PROP_TYPE(TypeTag, GridView) GridView;
+    enum {
+        dim = GridView::dimension,
+        dimWorld = GridView::dimensionworld
+    };
+    typedef typename GridView::template Codim<0>::Iterator ElementIterator;
+    typedef typename GridView::template Codim<dim>::Iterator VertexIterator;
+
+    typedef typename GET_PROP_TYPE(TypeTag, Scalar) Scalar;
+    typedef Dune::FieldVector<Scalar, dim> DimVector;
+
+public:
+    /*!
+     * \brief Constructor. Sets the upwind weight.
+     */
+    OnePTwoCBoxModel()
+    {
+        // retrieve the upwind weight for the mass conservation equations. Use the value
+        // specified via the property system as default, and overwrite
+        // it by the run-time parameter from the Dune::ParameterTree
+        upwindWeight_ = GET_PARAM_FROM_GROUP(TypeTag, Scalar, Implicit, MassUpwindWeight);
+    }
+
+    /*!
+     * \brief \copybrief Dumux::BoxModel::addOutputVtkFields
+     *
+     * Specialization for the OnePTwoCBoxModel, adding pressure,
+     * mass and mole fractions, and the process rank to the VTK writer.
+     */
+    template<class MultiWriter>
+    void addOutputVtkFields(const SolutionVector &sol,
+                            MultiWriter &writer)
+    {
+        typedef Dune::BlockVector<Dune::FieldVector<double, 1> > ScalarField;
+
+        // create the required scalar fields
+        unsigned numVertices = this->problem_().gridView().size(dim);
+        ScalarField &pressure = *writer.allocateManagedBuffer(numVertices);
+        ScalarField &delp = *writer.allocateManagedBuffer(numVertices);
+        ScalarField &moleFraction0 = *writer.allocateManagedBuffer(numVertices);
+        ScalarField &moleFraction1 = *writer.allocateManagedBuffer(numVertices);
+        ScalarField &massFraction0 = *writer.allocateManagedBuffer(numVertices);
+        ScalarField &massFraction1 = *writer.allocateManagedBuffer(numVertices);
+        ScalarField &rho = *writer.allocateManagedBuffer(numVertices);
+        ScalarField &mu = *writer.allocateManagedBuffer(numVertices);
+#ifdef VELOCITY_OUTPUT // check if velocity output is demanded
+        ScalarField &velocityX = *writer.allocateManagedBuffer(numVertices);
+        ScalarField &velocityY = *writer.allocateManagedBuffer(numVertices);
+        ScalarField &velocityZ = *writer.allocateManagedBuffer(numVertices);
+        //use vertical faces for vx and horizontal faces for vy calculation
+        std::vector<DimVector> boxSurface(numVertices);
+        // initialize velocity fields
+          for (unsigned int i = 0; i < numVertices; ++i)
+          {
+
+              velocityX[i] = 0;
+              if (dim > 1)
+              {
+                  velocityY[i] = 0;
+              }
+              if (dim > 2)
+              {
+                  velocityZ[i] = 0;
+              }
+              boxSurface[i] = Scalar(0.0); // initialize the boundary surface of the fv-boxes
+          }
+#endif
+        unsigned numElements = this->gridView_().size(0);
+        ScalarField &rank =
+                *writer.allocateManagedBuffer(numElements);
+
+        FVElementGeometry fvGeometry;
+        VolumeVariables volVars;
+        ElementBoundaryTypes elemBcTypes;
+
+        ElementIterator elemIt = this->gridView_().template begin<0>();
+        ElementIterator elemEndIt = this->gridView_().template end<0>();
+        for (; elemIt != elemEndIt; ++elemIt)
+        {
+            int idx = this->problem_().model().elementMapper().map(*elemIt);
+            rank[idx] = this->gridView_().comm().rank();
+
+            fvGeometry.update(this->gridView_(), *elemIt);
+            elemBcTypes.update(this->problem_(), *elemIt, fvGeometry);
+
+            int numVerts = elemIt->template count<dim> ();
+            for (int i = 0; i < numVerts; ++i)
+            {
+                int globalIdx = this->vertexMapper().map(*elemIt, i, dim);
+                volVars.update(sol[globalIdx],
+                               this->problem_(),
+                               *elemIt,
+                               fvGeometry,
+                               i,
+                               false);
+
+                pressure[globalIdx] = volVars.pressure();
+                delp[globalIdx] = volVars.pressure() - 1e5;
+                moleFraction0[globalIdx] = volVars.moleFraction(0);
+                moleFraction1[globalIdx] = volVars.moleFraction(1);
+                massFraction0[globalIdx] = volVars.massFraction(0);
+                massFraction1[globalIdx] = volVars.massFraction(1);
+                rho[globalIdx] = volVars.density();
+                mu[globalIdx] = volVars.viscosity();
+            }
+
+#ifdef VELOCITY_OUTPUT // check if velocity output is demanded
+            // In the box method, the velocity is evaluated on the FE-Grid. However, to get an
+            // average apparent velocity at the vertex, all contributing velocities have to be interpolated.
+            DimVector velocity;
+
+            ElementVolumeVariables elemVolVars;
+            elemVolVars.update(this->problem_(),
+                               *elemIt,
+                               fvGeometry,
+                               false /* isOldSol? */);
+            // loop over the phases
+            for (int faceIdx = 0; faceIdx < fvGeometry.numEdges; faceIdx++)
+            {
+                velocity = 0.0;
+                //prepare the flux calculations (set up and prepare geometry, FE gradients)
+                FluxVariables fluxVars(this->problem_(),
+                                       *elemIt,
+                                       fvGeometry,
+                                       faceIdx,
+                                       elemVolVars);
+
+                //use vertical faces for vx and horizontal faces for vy calculation
+                DimVector xVector(0), yVector(0);
+                xVector[0] = 1; yVector[1] = 1;
+
+                Dune::SeqScalarProduct<DimVector> sp;
+
+                Scalar xDir = std::abs(sp.dot(fluxVars.face().normal, xVector));
+                Scalar yDir = std::abs(sp.dot(fluxVars.face().normal, yVector));
+
+                // up+downstream node
+                const VolumeVariables &up =
+                    elemVolVars[fluxVars.upstreamIdx()];
+                const VolumeVariables &dn =
+                    elemVolVars[fluxVars.downstreamIdx()];
+
+                //get surface area to weight velocity at the IP with the surface area
+                Scalar scvfArea = fluxVars.face().normal.two_norm();
+
+                int vertIIdx = this->problem_().vertexMapper().map(
+                    *elemIt, fluxVars.face().i, dim);
+                int vertJIdx = this->problem_().vertexMapper().map(
+                    *elemIt, fluxVars.face().j, dim);
+
+                //use vertical faces (horizontal noraml vector) to calculate vx
+                //in case of heterogeneities it seams to be better to define intrinisc permeability elementwise
+                if(xDir > yDir)//(fluxVars.face().normal[0] > 1e-10 || fluxVars.face().normal[0] < -1e-10)// (xDir > yDir)
+                {
+                    // get darcy velocity
+                    //calculate (v n) n/A
+                    Scalar tmp = fluxVars.KmvpNormal();
+                    velocity = fluxVars.face().normal;
+                    velocity *= tmp;
+                    velocity /= scvfArea;
+                    velocity *= (upwindWeight_ / up.viscosity() +
+                                 (1 - upwindWeight_)/ dn.viscosity());
+
+                    // add surface area for weighting purposes
+                    boxSurface[vertIIdx][0] += scvfArea;
+                    boxSurface[vertJIdx][0] += scvfArea;
+
+                    velocityX[vertJIdx] += velocity[0];
+                    velocityX[vertIIdx] += velocity[0];
+
+                }
+                if (yDir > xDir)//(fluxVars.face().normal[1] > 1e-10 || fluxVars.face().normal[1] < -1e-10)// (yDir > xDir)
+                {
+                    // get darcy velocity
+                    //calculate (v n) n/A
+                    Scalar tmp = fluxVars.KmvpNormal();
+                    velocity = fluxVars.face().normal;
+                    velocity *= tmp;
+                    velocity /= scvfArea;
+                    velocity *= (upwindWeight_ / up.viscosity() +
+                                 (1 - upwindWeight_)/ dn.viscosity());
+
+                    // add surface area for weighting purposes
+                    boxSurface[vertIIdx][1] += scvfArea;
+                    boxSurface[vertJIdx][1] += scvfArea;
+
+                    velocityY[vertJIdx] += velocity[1];
+                    velocityY[vertIIdx] += velocity[1];
+                }
+            }
+#endif
+        }
+#ifdef VELOCITY_OUTPUT
+        // normalize the velocities at the vertices
+        // calculate the bounding box of the grid view
+        VertexIterator vIt = this->gridView_().template begin<dim>();
+        const VertexIterator vEndIt = this->gridView_().template end<dim>();
+        for (; vIt!=vEndIt; ++vIt)
+        {
+            int i = this->problem_().vertexMapper().map(*vIt);
+
+            //use vertical faces for vx and horizontal faces for vy calculation
+            velocityX[i] /= boxSurface[i][0];
+            if (dim >= 2)
+            {
+                velocityY[i] /= boxSurface[i][1];
+            }
+            if (dim == 3)
+            {
+                velocityZ[i] /= boxSurface[i][2];
+            }
+        }
+#endif
+        writer.attachVertexData(pressure, "P");
+        writer.attachVertexData(delp, "delp");
+#ifdef VELOCITY_OUTPUT // check if velocity output is demanded
+        writer.attachVertexData(velocityX, "Vx");
+        writer.attachVertexData(velocityY, "Vy");
+        if (dim > 2)
+            writer.attachVertexData(velocityZ, "Vz");
+#endif
+        char nameMoleFraction0[42], nameMoleFraction1[42];
+        snprintf(nameMoleFraction0, 42, "x_%s", FluidSystem::componentName(0));
+        snprintf(nameMoleFraction1, 42, "x_%s", FluidSystem::componentName(1));
+        writer.attachVertexData(moleFraction0, nameMoleFraction0);
+        writer.attachVertexData(moleFraction1, nameMoleFraction1);
+
+        char nameMassFraction0[42], nameMassFraction1[42];
+        snprintf(nameMassFraction0, 42, "X_%s", FluidSystem::componentName(0));
+        snprintf(nameMassFraction1, 42, "X_%s", FluidSystem::componentName(1));
+        writer.attachVertexData(massFraction0, nameMassFraction0);
+        writer.attachVertexData(massFraction1, nameMassFraction1);
+        writer.attachVertexData(rho, "rho");
+        writer.attachVertexData(mu, "mu");
+        writer.attachCellData(rank, "process rank");
+    }
+
+private:
+    Scalar upwindWeight_;
+};
+}
+
+#include "1p2cpropertydefaults.hh"
+
+#endif
diff --git a/dumux/implicit/1p2c/1p2cproperties.hh b/dumux/implicit/1p2c/1p2cproperties.hh
new file mode 100644
index 0000000000..38d03eba34
--- /dev/null
+++ b/dumux/implicit/1p2c/1p2cproperties.hh
@@ -0,0 +1,68 @@
+// -*- mode: C++; tab-width: 4; indent-tabs-mode: nil; c-basic-offset: 4 -*-
+// vi: set et ts=4 sw=4 sts=4:
+/*****************************************************************************
+ *   See the file COPYING for full copying permissions.                      *
+ *                                                                           *
+ *   This program is free software: you can redistribute it and/or modify    *
+ *   it under the terms of the GNU General Public License as published by    *
+ *   the Free Software Foundation, either version 2 of the License, or       *
+ *   (at your option) any later version.                                     *
+ *                                                                           *
+ *   This program is distributed in the hope that it will be useful,         *
+ *   but WITHOUT ANY WARRANTY; without even the implied warranty of          *
+ *   MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the            *
+ *   GNU General Public License for more details.                            *
+ *                                                                           *
+ *   You should have received a copy of the GNU General Public License       *
+ *   along with this program.  If not, see <http://www.gnu.org/licenses/>.   *
+ *****************************************************************************/
+/*!
+ * \ingroup Properties
+ * \ingroup BoxProperties
+ * \ingroup OnePTwoCBoxModel
+ * \file
+ *
+ * \brief Defines the properties required for the single-phase,
+ *        two-component BOX model.
+ */
+
+#ifndef DUMUX_1P2C_PROPERTIES_HH
+#define DUMUX_1P2C_PROPERTIES_HH
+
+
+#include<dumux/boxmodels/common/boxproperties.hh>
+
+namespace Dumux
+{
+// \{
+namespace Properties
+{
+
+//////////////////////////////////////////////////////////////////
+// Type tags
+//////////////////////////////////////////////////////////////////
+
+//! The type tag for the isothermal single-phase, two-component problems
+NEW_TYPE_TAG(BoxOnePTwoC, INHERITS_FROM(BoxModel));
+
+//////////////////////////////////////////////////////////////////
+// Property tags
+//////////////////////////////////////////////////////////////////
+
+NEW_PROP_TAG(NumPhases);   //!< Number of fluid phases in the system
+NEW_PROP_TAG(PhaseIdx); //!< A phase index in to allow that a two-phase fluidsystem is used
+NEW_PROP_TAG(NumComponents);   //!< Number of fluid components in the system
+NEW_PROP_TAG(Indices); //!< Enumerations for the model
+NEW_PROP_TAG(SpatialParams); //!< The type of the spatial parameters
+NEW_PROP_TAG(FluidSystem); //!< Type of the multi-component relations
+NEW_PROP_TAG(ImplicitMassUpwindWeight);   //!< The default value of the upwind weight
+NEW_PROP_TAG(ProblemEnableGravity); //!< Returns whether gravity is considered in the problem
+NEW_PROP_TAG(UseMoles); //!Defines whether mole (true) or mass (false) fractions are used
+NEW_PROP_TAG(Scaling); //!Defines Scaling of the model
+NEW_PROP_TAG(SpatialParamsForchCoeff); //!< Property for the forchheimer coefficient
+}
+// \}
+}
+
+#endif
+
diff --git a/dumux/implicit/1p2c/1p2cpropertydefaults.hh b/dumux/implicit/1p2c/1p2cpropertydefaults.hh
new file mode 100644
index 0000000000..79cd1e11f3
--- /dev/null
+++ b/dumux/implicit/1p2c/1p2cpropertydefaults.hh
@@ -0,0 +1,96 @@
+// -*- mode: C++; tab-width: 4; indent-tabs-mode: nil; c-basic-offset: 4 -*-
+// vi: set et ts=4 sw=4 sts=4:
+/*****************************************************************************
+ *   See the file COPYING for full copying permissions.                      *
+ *                                                                           *
+ *   This program is free software: you can redistribute it and/or modify    *
+ *   it under the terms of the GNU General Public License as published by    *
+ *   the Free Software Foundation, either version 2 of the License, or       *
+ *   (at your option) any later version.                                     *
+ *                                                                           *
+ *   This program is distributed in the hope that it will be useful,         *
+ *   but WITHOUT ANY WARRANTY; without even the implied warranty of          *
+ *   MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the            *
+ *   GNU General Public License for more details.                            *
+ *                                                                           *
+ *   You should have received a copy of the GNU General Public License       *
+ *   along with this program.  If not, see <http://www.gnu.org/licenses/>.   *
+ *****************************************************************************/
+/*!
+ * \ingroup Properties
+ * \ingroup BoxProperties
+ * \ingroup OnePTwoCBoxModel
+ * \file
+ *
+ * \brief Defines some default values for the properties of the the
+ *        single-phase, two-component BOX model.
+ */
+
+#ifndef DUMUX_1P2C_PROPERTY_DEFAULTS_HH
+#define DUMUX_1P2C_PROPERTY_DEFAULTS_HH
+
+#include "1p2cproperties.hh"
+
+#include "1p2cmodel.hh"
+#include "1p2clocalresidual.hh"
+#include "1p2cvolumevariables.hh"
+#include "1p2cfluxvariables.hh"
+#include "1p2cindices.hh"
+
+#include <dumux/material/spatialparams/boxspatialparams1p.hh>
+
+namespace Dumux
+{
+// \{
+namespace Properties
+{
+//////////////////////////////////////////////////////////////////
+// Property values
+//////////////////////////////////////////////////////////////////
+
+SET_INT_PROP(BoxOnePTwoC, NumEq, 2); //!< set the number of equations to 2
+SET_INT_PROP(BoxOnePTwoC, NumPhases, 1); //!< The number of phases in the 1p2c model is 1
+SET_INT_PROP(BoxOnePTwoC, NumComponents, 2); //!< The number of components in the 1p2c model is 2
+SET_SCALAR_PROP(BoxOnePTwoC, Scaling, 1); //!< Scaling of the model is set to 1 by default
+SET_BOOL_PROP(BoxOnePTwoC, UseMoles, false); //!< Define that mass fractions are used in the balance equations
+
+//! Use the 1p2c local residual function for the 1p2c model
+SET_TYPE_PROP(BoxOnePTwoC, LocalResidual, OnePTwoCLocalResidual<TypeTag>);
+
+//! define the model
+SET_TYPE_PROP(BoxOnePTwoC, Model, OnePTwoCBoxModel<TypeTag>);
+
+//! define the VolumeVariables
+SET_TYPE_PROP(BoxOnePTwoC, VolumeVariables, OnePTwoCVolumeVariables<TypeTag>);
+
+//! define the FluxVariables
+SET_TYPE_PROP(BoxOnePTwoC, FluxVariables, OnePTwoCFluxVariables<TypeTag>);
+
+//! set default upwind weight to 1.0, i.e. fully upwind
+SET_SCALAR_PROP(BoxOnePTwoC, ImplicitMassUpwindWeight, 1.0);
+
+//! Set the indices used by the 1p2c model
+SET_TYPE_PROP(BoxOnePTwoC, Indices, Dumux::OnePTwoCIndices<TypeTag, 0>);
+
+//! The spatial parameters to be employed. 
+//! Use BoxSpatialParamsOneP by default.
+SET_TYPE_PROP(BoxOnePTwoC, SpatialParams, BoxSpatialParamsOneP<TypeTag>);
+
+//! Set the phaseIndex per default to zero (important for two-phase fluidsystems).
+SET_INT_PROP(BoxOnePTwoC, PhaseIdx, 0);
+
+// enable gravity by default
+SET_BOOL_PROP(BoxOnePTwoC, ProblemEnableGravity, true);
+
+//! default value for the forchheimer coefficient
+// Source: Ward, J.C. 1964 Turbulent flow in porous media. ASCE J. Hydraul. Div 90.
+//        Actually the Forchheimer coefficient is also a function of the dimensions of the
+//        porous medium. Taking it as a constant is only a first approximation
+//        (Nield, Bejan, Convection in porous media, 2006, p. 10)
+SET_SCALAR_PROP(BoxModel, SpatialParamsForchCoeff, 0.55);
+}
+// \}
+}
+
+#endif
+
diff --git a/dumux/implicit/1p2c/1p2cvolumevariables.hh b/dumux/implicit/1p2c/1p2cvolumevariables.hh
new file mode 100644
index 0000000000..5e1620dc9b
--- /dev/null
+++ b/dumux/implicit/1p2c/1p2cvolumevariables.hh
@@ -0,0 +1,284 @@
+// -*- mode: C++; tab-width: 4; indent-tabs-mode: nil; c-basic-offset: 4 -*-
+// vi: set et ts=4 sw=4 sts=4:
+/*****************************************************************************
+ *   See the file COPYING for full copying permissions.                      *
+ *                                                                           *
+ *   This program is free software: you can redistribute it and/or modify    *
+ *   it under the terms of the GNU General Public License as published by    *
+ *   the Free Software Foundation, either version 2 of the License, or       *
+ *   (at your option) any later version.                                     *
+ *                                                                           *
+ *   This program is distributed in the hope that it will be useful,         *
+ *   but WITHOUT ANY WARRANTY; without even the implied warranty of          *
+ *   MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the            *
+ *   GNU General Public License for more details.                            *
+ *                                                                           *
+ *   You should have received a copy of the GNU General Public License       *
+ *   along with this program.  If not, see <http://www.gnu.org/licenses/>.   *
+ *****************************************************************************/
+/*!
+ * \file
+ * \brief Quantities required by the single-phase, two-component box
+ *        model defined on a vertex.
+ */
+#ifndef DUMUX_1P2C_VOLUME_VARIABLES_HH
+#define DUMUX_1P2C_VOLUME_VARIABLES_HH
+
+#include <dumux/boxmodels/common/boxvolumevariables.hh>
+#include <dumux/material/fluidstates/compositionalfluidstate.hh>
+
+#include "1p2cproperties.hh"
+
+namespace Dumux
+{
+
+/*!
+ * \ingroup OnePTwoCBoxModel
+ * \ingroup BoxVolumeVariables
+ * \brief Contains the quantities which are constant within a
+ *        finite volume in the single-phase, two-component model.
+ */
+template <class TypeTag>
+class OnePTwoCVolumeVariables : public BoxVolumeVariables<TypeTag>
+{
+    typedef BoxVolumeVariables<TypeTag> ParentType;
+
+    typedef typename GET_PROP_TYPE(TypeTag, Problem) Problem;
+    typedef typename GET_PROP_TYPE(TypeTag, VolumeVariables) Implementation;
+    typedef typename GET_PROP_TYPE(TypeTag, FVElementGeometry) FVElementGeometry;
+    typedef typename GET_PROP_TYPE(TypeTag, PrimaryVariables) PrimaryVariables;
+    typedef typename GET_PROP_TYPE(TypeTag, FluidSystem) FluidSystem;
+    static const bool useMoles = GET_PROP_VALUE(TypeTag, UseMoles);
+
+    typedef typename GET_PROP_TYPE(TypeTag, Indices) Indices;
+    enum {
+        phaseIdx = Indices::phaseIdx,
+        phaseCompIdx = Indices::phaseCompIdx,
+        transportCompIdx = Indices::transportCompIdx
+    };
+    //indices of primary variables
+    enum{
+        pressureIdx = Indices::pressureIdx,
+        massOrMoleFracIdx = Indices::massOrMoleFracIdx
+    };
+
+    typedef typename GET_PROP_TYPE(TypeTag, GridView) GridView;
+    typedef typename GridView::template Codim<0>::Entity Element;
+    enum { dim = GridView::dimension };
+
+    typedef typename GET_PROP_TYPE(TypeTag, Scalar) Scalar;
+    typedef Dune::FieldVector<Scalar,dim> DimVector;
+
+public:
+    //! The type returned by the fluidState() method
+    typedef Dumux::CompositionalFluidState<Scalar, FluidSystem> FluidState;
+
+    /*!
+     * \copydoc BoxVolumeVariables::update
+     */
+    void update(const PrimaryVariables &priVars,
+                const Problem &problem,
+                const Element &element,
+                const FVElementGeometry &fvGeometry,
+                const int scvIdx,
+                const bool isOldSol)
+    {
+        ParentType::update(priVars, problem, element, fvGeometry, scvIdx, isOldSol);
+
+        //calculate all secondary variables from the primary variables and store results in fluidstate
+        completeFluidState(priVars, problem, element, fvGeometry, scvIdx, fluidState_);
+
+        porosity_ = problem.spatialParams().porosity(element, fvGeometry, scvIdx);
+        tortuosity_ = problem.spatialParams().tortuosity(element, fvGeometry, scvIdx);
+        dispersivity_ = problem.spatialParams().dispersivity(element, fvGeometry, scvIdx);
+
+        // Second instance of a parameter cache.
+        // Could be avoided if diffusion coefficients also
+        // became part of the fluid state.
+        typename FluidSystem::ParameterCache paramCache;
+        paramCache.updatePhase(fluidState_, phaseIdx);
+
+        diffCoeff_ = FluidSystem::binaryDiffusionCoefficient(fluidState_,
+                                                             paramCache,
+                                                             phaseIdx,
+                                                             phaseCompIdx,
+                                                             transportCompIdx);
+
+        Valgrind::CheckDefined(porosity_);
+        Valgrind::CheckDefined(tortuosity_);
+        Valgrind::CheckDefined(dispersivity_);
+        Valgrind::CheckDefined(diffCoeff_);
+
+        // energy related quantities not contained in the fluid state
+        asImp_().updateEnergy_(priVars, problem, element, fvGeometry, scvIdx, isOldSol);
+    }
+
+    /*!
+     * \copydoc BoxModel::completeFluidState
+     */
+    static void completeFluidState(const PrimaryVariables& priVars,
+                                   const Problem& problem,
+                                   const Element& element,
+                                   const FVElementGeometry& fvGeometry,
+                                   const int scvIdx,
+                                   FluidState& fluidState)
+    {
+        Scalar T = Implementation::temperature_(priVars, problem, element,
+                                                fvGeometry, scvIdx);
+        fluidState.setTemperature(T);
+
+        fluidState.setPressure(phaseIdx, priVars[pressureIdx]);
+
+        Scalar x1 = priVars[massOrMoleFracIdx]; //mole or mass fraction of component 1
+        if(!useMoles) //mass-fraction formulation
+        {
+            // convert mass to mole fractions
+            Scalar M0 = FluidSystem::molarMass(phaseCompIdx);
+            Scalar M1 = FluidSystem::molarMass(transportCompIdx);
+            //meanMolarMass if x1_ is a massfraction
+            Scalar meanMolarMass = M0*M1/(M1 + x1*(M0 - M1));
+
+            x1 *= meanMolarMass/M1;
+        }
+        fluidState.setMoleFraction(phaseIdx, phaseCompIdx, 1 - x1);
+        fluidState.setMoleFraction(phaseIdx, transportCompIdx, x1);
+
+        typename FluidSystem::ParameterCache paramCache;
+        paramCache.updatePhase(fluidState, phaseIdx);
+
+        Scalar value;
+        value = FluidSystem::density(fluidState, paramCache, phaseIdx);
+        fluidState.setDensity(phaseIdx, value);
+        value = FluidSystem::viscosity(fluidState, paramCache, phaseIdx);
+        fluidState.setViscosity(phaseIdx, value);
+    }
+
+    /*!
+     * \brief Return the fluid configuration at the given primary
+     *        variables
+     */
+    const FluidState &fluidState() const
+    { return fluidState_; }
+
+    /*!
+     * \brief Return density \f$\mathrm{[kg/m^3]}\f$ the of the fluid phase.
+     */
+    Scalar density() const
+    { return fluidState_.density(phaseIdx); }
+
+    /*!
+     * \brief Return molar density \f$\mathrm{[mol/m^3]}\f$ the of the fluid phase.
+     */
+    Scalar molarDensity() const
+    { return fluidState_.molarDensity(phaseIdx);}
+
+    /*!
+     * \brief Return mole fraction \f$\mathrm{[mol/mol]}\f$ of a component in the phase.
+     *
+     * \param compIdx The index of the component
+     */
+    Scalar moleFraction(int compIdx) const
+    { return fluidState_.moleFraction(phaseIdx, (compIdx==0)?phaseCompIdx:transportCompIdx); }
+
+    /*!
+     * \brief Return mass fraction \f$\mathrm{[kg/kg]}\f$ of a component in the phase.
+     *
+     * \param compIdx The index of the component
+     */
+    Scalar massFraction(int compIdx) const
+    { return fluidState_.massFraction(phaseIdx, (compIdx==0)?phaseCompIdx:transportCompIdx); }
+
+    /*!
+     * \brief Return concentration \f$\mathrm{[mol/m^3]}\f$  of a component in the phase.
+     *
+     * \param compIdx The index of the component
+     */
+    Scalar molarity(int compIdx) const
+    { return fluidState_.molarity(phaseIdx, (compIdx==0)?phaseCompIdx:transportCompIdx); }
+
+    /*!
+     * \brief Return the effective pressure \f$\mathrm{[Pa]}\f$ of a given phase within
+     *        the control volume.
+     */
+    Scalar pressure() const
+    { return fluidState_.pressure(phaseIdx); }
+
+    /*!
+     * \brief Return the binary diffusion coefficient \f$\mathrm{[m^2/s]}\f$ in the fluid.
+     */
+    Scalar diffCoeff() const
+    { return diffCoeff_; }
+
+    /*!
+     * \brief Return the tortuosity  \f$\mathrm{[-]}\f$ of the streamlines of the fluid.
+     */
+    Scalar tortuosity() const
+    { return tortuosity_; }
+
+    /*!
+     * \brief Returns the dispersivity of the fluid's streamlines.
+     */
+    const DimVector &dispersivity() const
+    { return dispersivity_; }
+
+    /*!
+     * \brief Return temperature \f$\mathrm{[K]}\f$ inside the sub-control volume.
+     *
+     * Note that we assume thermodynamic equilibrium, i.e. the
+     * temperature of the rock matrix and of all fluid phases are
+     * identical.
+     */
+    Scalar temperature() const
+    { return fluidState_.temperature(phaseIdx); }
+
+    /*!
+     * \brief Return the dynamic viscosity \f$\mathrm{[Pa*s]}\f$ of a given phase
+     *        within the control volume.
+     */
+    Scalar viscosity() const
+    { return fluidState_.viscosity(phaseIdx); }
+
+    /*!
+     * \brief Return the average porosity \f$\mathrm{[-]}\f$ within the control volume.
+     */
+    Scalar porosity() const
+    { return porosity_; }
+
+protected:
+    static Scalar temperature_(const PrimaryVariables &priVars,
+                               const Problem& problem,
+                               const Element &element,
+                               const FVElementGeometry &fvGeometry,
+                               const int scvIdx)
+    {
+        return problem.boxTemperature(element, fvGeometry, scvIdx);
+    }
+
+    /*!
+     * \brief Called by update() to compute the energy related quantities.
+     */
+    void updateEnergy_(const PrimaryVariables &priVars,
+                       const Problem &problem,
+                       const Element &element,
+                       const FVElementGeometry &fvGeometry,
+                       const int scvIdx,
+                       const bool isOldSol)
+    { }
+
+    Scalar porosity_;    //!< Effective porosity within the control volume
+    Scalar tortuosity_;
+    DimVector dispersivity_;
+    Scalar diffCoeff_;
+    FluidState fluidState_;
+
+private:
+    Implementation &asImp_()
+    { return *static_cast<Implementation*>(this); }
+
+    const Implementation &asImp_() const
+    { return *static_cast<const Implementation*>(this); }
+};
+
+}// end namepace
+
+#endif
diff --git a/dumux/implicit/1p2c/Makefile.am b/dumux/implicit/1p2c/Makefile.am
new file mode 100644
index 0000000000..8a96579124
--- /dev/null
+++ b/dumux/implicit/1p2c/Makefile.am
@@ -0,0 +1,4 @@
+1p2cdir = $(includedir)/dumux/boxmodels/1p2c
+1p2c_HEADERS = *.hh
+
+include $(top_srcdir)/am/global-rules
diff --git a/dumux/implicit/2p/2pindices.hh b/dumux/implicit/2p/2pindices.hh
new file mode 100644
index 0000000000..a36d15fdd2
--- /dev/null
+++ b/dumux/implicit/2p/2pindices.hh
@@ -0,0 +1,110 @@
+// -*- mode: C++; tab-width: 4; indent-tabs-mode: nil; c-basic-offset: 4 -*-
+// vi: set et ts=4 sw=4 sts=4:
+/*****************************************************************************
+ *   See the file COPYING for full copying permissions.                      *
+ *                                                                           *
+ *   This program is free software: you can redistribute it and/or modify    *
+ *   it under the terms of the GNU General Public License as published by    *
+ *   the Free Software Foundation, either version 2 of the License, or       *
+ *   (at your option) any later version.                                     *
+ *                                                                           *
+ *   This program is distributed in the hope that it will be useful,         *
+ *   but WITHOUT ANY WARRANTY; without even the implied warranty of          *
+ *   MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the            *
+ *   GNU General Public License for more details.                            *
+ *                                                                           *
+ *   You should have received a copy of the GNU General Public License       *
+ *   along with this program.  If not, see <http://www.gnu.org/licenses/>.   *
+ *****************************************************************************/
+
+/*!
+ * \file
+ *
+ * \brief Defines the indices required for the two-phase box model.
+ */
+#ifndef DUMUX_BOX_2P_INDICES_HH
+#define DUMUX_BOX_2P_INDICES_HH
+
+#include "2pproperties.hh"
+
+namespace Dumux
+{
+// \{
+
+/*!
+ * \ingroup TwoPBoxModel
+ * \ingroup BoxIndices
+ * \brief The common indices for the isothermal two-phase model.
+ */
+
+struct TwoPFormulation
+{
+    static const int pwSn = 0; //!< Pw and Sn as primary variables
+    static const int pnSw = 1; //!< Pn and Sw as primary variables
+};
+
+template <class TypeTag>
+struct TwoPCommonIndices
+{
+    typedef typename GET_PROP_TYPE(TypeTag, FluidSystem) FluidSystem;
+
+    // Phase indices
+    static const int wPhaseIdx = FluidSystem::wPhaseIdx; //!< Index of the wetting phase
+    static const int nPhaseIdx = FluidSystem::nPhaseIdx; //!< Index of the non-wetting phase
+};
+
+/*!
+ * \brief The indices for the \f$p_w-S_n\f$ formulation of the
+ *        isothermal two-phase model.
+ *
+ * \tparam TypeTag The problem type tag
+ * \tparam formulation The formulation, either pwSn or pnSw
+ * \tparam PVOffset The first index in a primary variable vector.
+ */
+template <class TypeTag, 
+          int formulation = TwoPFormulation::pwSn, 
+          int PVOffset = 0>
+struct TwoPIndices 
+: public TwoPCommonIndices<TypeTag>, TwoPFormulation
+{
+    // Primary variable indices
+    static const int pressureIdx = PVOffset + 0; //!< Index for wetting/non-wetting phase pressure (depending on formulation) in a solution vector
+    static const int saturationIdx = PVOffset + 1; //!< Index of the saturation of the non-wetting/wetting phase
+
+    // indices of the primary variables
+    static const int pwIdx = PVOffset + 0; //!< Pressure index of the wetting phase
+    static const int SnIdx = PVOffset + 1; //!< Saturation index of the wetting phase
+
+    // indices of the equations
+    static const int contiWEqIdx = PVOffset + 0; //!< Index of the continuity equation of the wetting phase
+    static const int contiNEqIdx = PVOffset + 1; //!< Index of the continuity equation of the non-wetting phase
+};
+
+/*!
+ * \brief The indices for the \f$p_w-S_n\f$ formulation of the
+ *        isothermal two-phase model.
+ *
+ * \tparam PVOffset The first index in a primary variable vector.
+ */
+template <class TypeTag, int PVOffset>
+struct TwoPIndices<TypeTag, TwoPFormulation::pnSw, PVOffset>
+: public TwoPCommonIndices<TypeTag>, TwoPFormulation
+{
+    // Primary variable indices
+    static const int pressureIdx = PVOffset + 0; //!< Index for wetting/non-wetting phase pressure (depending on formulation) in a solution vector
+    static const int saturationIdx = PVOffset + 1; //!< Index of the saturation of the non-wetting/wetting phase
+
+    // indices of the primary variables
+    static const int pnIdx = PVOffset + 0; //!< Pressure index of the wetting phase
+    static const int SwIdx = PVOffset + 1; //!< Saturation index of the wetting phase
+
+    // indices of the equations
+    static const int contiNEqIdx = PVOffset + 0; //!< Index of the continuity equation of the non-wetting phase
+    static const int contiWEqIdx = PVOffset + 1; //!< Index of the continuity equation of the wetting phase
+};
+
+// \}
+} // namespace Dumux
+
+
+#endif
diff --git a/dumux/implicit/2p/2plocalresidual.hh b/dumux/implicit/2p/2plocalresidual.hh
new file mode 100644
index 0000000000..c72e5046c8
--- /dev/null
+++ b/dumux/implicit/2p/2plocalresidual.hh
@@ -0,0 +1,212 @@
+// -*- mode: C++; tab-width: 4; indent-tabs-mode: nil; c-basic-offset: 4 -*-
+// vi: set et ts=4 sw=4 sts=4:
+/*****************************************************************************
+ *   See the file COPYING for full copying permissions.                      *
+ *                                                                           *
+ *   This program is free software: you can redistribute it and/or modify    *
+ *   it under the terms of the GNU General Public License as published by    *
+ *   the Free Software Foundation, either version 2 of the License, or       *
+ *   (at your option) any later version.                                     *
+ *                                                                           *
+ *   This program is distributed in the hope that it will be useful,         *
+ *   but WITHOUT ANY WARRANTY; without even the implied warranty of          *
+ *   MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the            *
+ *   GNU General Public License for more details.                            *
+ *                                                                           *
+ *   You should have received a copy of the GNU General Public License       *
+ *   along with this program.  If not, see <http://www.gnu.org/licenses/>.   *
+ *****************************************************************************/
+/*!
+ * \file
+ *
+ * \brief Element-wise calculation of the residual for the two-phase box model.
+ */
+#ifndef DUMUX_TWOP_LOCAL_RESIDUAL_BASE_HH
+#define DUMUX_TWOP_LOCAL_RESIDUAL_BASE_HH
+
+#include <dumux/boxmodels/common/boxmodel.hh>
+
+#include "2pproperties.hh"
+
+namespace Dumux
+{
+/*!
+ * \ingroup TwoPBoxModel
+ * \ingroup BoxLocalResidual
+ * \brief Element-wise calculation of the Jacobian matrix for problems
+ *        using the two-phase box model.
+ *
+ * This class is also used for the non-isothermal model, which means
+ * that it uses static polymorphism.
+ */
+template<class TypeTag>
+class TwoPLocalResidual : public GET_PROP_TYPE(TypeTag, BaseLocalResidual)
+{
+protected:
+    typedef typename GET_PROP_TYPE(TypeTag, LocalResidual) Implementation;
+    typedef typename GET_PROP_TYPE(TypeTag, PrimaryVariables) PrimaryVariables;
+    typedef typename GET_PROP_TYPE(TypeTag, VolumeVariables) VolumeVariables;
+    typedef typename GET_PROP_TYPE(TypeTag, FluxVariables) FluxVariables;
+    typedef typename GET_PROP_TYPE(TypeTag, ElementVolumeVariables) ElementVolumeVariables;
+
+    typedef typename GET_PROP_TYPE(TypeTag, Indices) Indices;
+    enum
+    {
+        contiWEqIdx = Indices::contiWEqIdx,
+        contiNEqIdx = Indices::contiNEqIdx,
+        wPhaseIdx = Indices::wPhaseIdx,
+        nPhaseIdx = Indices::nPhaseIdx,
+        numPhases = GET_PROP_VALUE(TypeTag, NumPhases)
+    };
+
+    typedef typename GET_PROP_TYPE(TypeTag, GridView) GridView;
+    enum { dimWorld = GridView::dimensionworld };
+
+    typedef typename GET_PROP_TYPE(TypeTag, Scalar) Scalar;
+    typedef Dune::FieldVector<Scalar, dimWorld> Vector;
+
+public:
+    /*!
+     * \brief Constructor. Sets the upwind weight.
+     */
+    TwoPLocalResidual()
+    {
+        // retrieve the upwind weight for the mass conservation equations. Use the value
+        // specified via the property system as default, and overwrite
+        // it by the run-time parameter from the Dune::ParameterTree
+        massUpwindWeight_ = GET_PARAM_FROM_GROUP(TypeTag, Scalar, Implicit, MassUpwindWeight);
+    };
+
+    /*!
+     * \brief Evaluate the amount all conservation quantities
+     *        (e.g. phase mass) within a finite sub-control volume.
+     *
+     *  \param storage The phase mass within the sub-control volume
+     *  \param scvIdx The SCV (sub-control-volume) index
+     *  \param usePrevSol Evaluate function with solution of current or previous time step
+     */
+    void computeStorage(PrimaryVariables &storage, int scvIdx, bool usePrevSol) const
+    {
+        // if flag usePrevSol is set, the solution from the previous
+        // time step is used, otherwise the current solution is
+        // used. The secondary variables are used accordingly.  This
+        // is required to compute the derivative of the storage term
+        // using the implicit Euler method.
+        const ElementVolumeVariables &elemVolVars = usePrevSol ? this->prevVolVars_() : this->curVolVars_();
+        const VolumeVariables &volVars = elemVolVars[scvIdx];
+
+        // wetting phase mass
+        storage[contiWEqIdx] = volVars.density(wPhaseIdx) * volVars.porosity()
+                * volVars.saturation(wPhaseIdx);
+
+        // non-wetting phase mass
+        storage[contiNEqIdx] = volVars.density(nPhaseIdx) * volVars.porosity()
+                * volVars.saturation(nPhaseIdx);
+    }
+
+    /*!
+     * \brief Evaluates the mass flux over a face of a sub-control
+     *        volume.
+     *
+     * \param flux The flux over the SCV (sub-control-volume) face for each phase
+     * \param faceIdx The index of the SCV face
+     * \param onBoundary A boolean variable to specify whether the flux variables
+     *        are calculated for interior SCV faces or boundary faces, default=false
+     */
+    void computeFlux(PrimaryVariables &flux, int faceIdx, const bool onBoundary=false) const
+    {
+        FluxVariables fluxVars(this->problem_(),
+                           this->element_(),
+                           this->fvGeometry_(),
+                           faceIdx,
+                           this->curVolVars_(),
+                           onBoundary);
+        flux = 0;
+        asImp_()->computeAdvectiveFlux(flux, fluxVars);
+        asImp_()->computeDiffusiveFlux(flux, fluxVars);
+    }
+
+    /*!
+     * \brief Evaluates the advective mass flux of all components over
+     *        a face of a sub-control volume.
+     *
+     * \param flux The advective flux over the sub-control-volume face for each phase
+     * \param fluxVars The flux variables at the current SCV
+     *
+     * This method is called by compute flux and is mainly there for
+     * derived models to ease adding equations selectively.
+     */
+    void computeAdvectiveFlux(PrimaryVariables &flux, const FluxVariables &fluxVars) const
+    {
+        // loop over all phases
+        for (int phaseIdx = 0; phaseIdx < numPhases; ++phaseIdx)
+        {
+            // data attached to upstream and the downstream vertices
+            // of the current phase
+            const VolumeVariables &up = this->curVolVars_(fluxVars.upstreamIdx(phaseIdx));
+            const VolumeVariables &dn = this->curVolVars_(fluxVars.downstreamIdx(phaseIdx));
+
+            // add advective flux of current phase
+            int eqIdx = (phaseIdx == wPhaseIdx) ? contiWEqIdx : contiNEqIdx;
+            flux[eqIdx] +=
+                fluxVars.volumeFlux(phaseIdx)
+                *
+                ((    massUpwindWeight_)*up.density(phaseIdx)
+                 +
+                 (1 - massUpwindWeight_)*dn.density(phaseIdx));
+        }
+    }
+
+    /*!
+     * \brief Adds the diffusive flux to the flux vector over
+     *        the face of a sub-control volume.
+     *
+     * \param flux The diffusive flux over the sub-control-volume face for each phase
+     * \param fluxData The flux variables at the current SCV
+     *
+     * It doesn't do anything in two-phase model but is used by the
+     * non-isothermal two-phase models to calculate diffusive heat
+     * fluxes
+     */
+    void computeDiffusiveFlux(PrimaryVariables &flux, const FluxVariables &fluxData) const
+    {
+        // diffusive fluxes
+        flux += 0.0;
+    }
+
+    /*!
+     * \brief Calculate the source term of the equation
+     *
+     * \param q The source/sink in the SCV for each phase
+     * \param scvIdx The index of the SCV
+     *
+     */
+    void computeSource(PrimaryVariables &q, int scvIdx) const
+    {
+        // retrieve the source term intrinsic to the problem
+        this->problem_().boxSDSource(q,
+                                     this->element_(),
+                                     this->fvGeometry_(),
+                                     scvIdx,
+                                     this->curVolVars_());
+    }
+
+
+protected:
+    Implementation *asImp_()
+    {
+        return static_cast<Implementation *> (this);
+    }
+    const Implementation *asImp_() const
+    {
+        return static_cast<const Implementation *> (this);
+    }
+
+private:
+    Scalar massUpwindWeight_;
+
+};
+
+}
+
+#endif
diff --git a/dumux/implicit/2p/2pmodel.hh b/dumux/implicit/2p/2pmodel.hh
new file mode 100644
index 0000000000..5a46820d2c
--- /dev/null
+++ b/dumux/implicit/2p/2pmodel.hh
@@ -0,0 +1,366 @@
+// -*- mode: C++; tab-width: 4; indent-tabs-mode: nil; c-basic-offset: 4 -*-
+// vi: set et ts=4 sw=4 sts=4:
+/*****************************************************************************
+ *   See the file COPYING for full copying permissions.                      *
+ *                                                                           *
+ *   This program is free software: you can redistribute it and/or modify    *
+ *   it under the terms of the GNU General Public License as published by    *
+ *   the Free Software Foundation, either version 2 of the License, or       *
+ *   (at your option) any later version.                                     *
+ *                                                                           *
+ *   This program is distributed in the hope that it will be useful,         *
+ *   but WITHOUT ANY WARRANTY; without even the implied warranty of          *
+ *   MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the            *
+ *   GNU General Public License for more details.                            *
+ *                                                                           *
+ *   You should have received a copy of the GNU General Public License       *
+ *   along with this program.  If not, see <http://www.gnu.org/licenses/>.   *
+ *****************************************************************************/
+
+/*!
+* \file
+*
+* \brief Adaption of the box scheme to the two-phase flow model.
+*/
+
+#ifndef DUMUX_TWOP_MODEL_HH
+#define DUMUX_TWOP_MODEL_HH
+
+#include "2pproperties.hh"
+#include "2plocalresidual.hh"
+
+namespace Dumux
+{
+
+/*!
+ * \ingroup TwoPBoxModel
+ * \brief A two-phase, isothermal flow model using the box scheme.
+ *
+ * This model implements two-phase flow of two immiscible fluids
+ * \f$\alpha \in \{ w, n \}\f$ using a standard multiphase Darcy
+ * approach as the equation for the conservation of momentum, i.e.
+ \f[
+ v_\alpha = - \frac{k_{r\alpha}}{\mu_\alpha} \textbf{K}
+ \left(\textbf{grad}\, p_\alpha - \varrho_{\alpha} {\textbf g} \right)
+ \f]
+ *
+ * By inserting this into the equation for the conservation of the
+ * phase mass, one gets
+ \f[
+ \phi \frac{\partial \varrho_\alpha S_\alpha}{\partial t}
+ -
+ \text{div} \left\{
+ \varrho_\alpha \frac{k_{r\alpha}}{\mu_\alpha} \mbox{\bf K} \left(\textbf{grad}\, p_\alpha - \varrho_{\alpha} \mbox{\bf g} \right)
+ \right\} - q_\alpha = 0 \;,
+ \f]
+ *
+ * These equations are discretized by a fully-coupled vertex centered finite volume
+ * (box) scheme as spatial and the implicit Euler method as time
+ * discretization.
+ *
+ * By using constitutive relations for the capillary pressure \f$p_c =
+ * p_n - p_w\f$ and relative permeability \f$k_{r\alpha}\f$ and taking
+ * advantage of the fact that \f$S_w + S_n = 1\f$, the number of
+ * unknowns can be reduced to two. Currently the model supports
+ * choosing either \f$p_w\f$ and \f$S_n\f$ or \f$p_n\f$ and \f$S_w\f$
+ * as primary variables. The formulation which ought to be used can be
+ * specified by setting the <tt>Formulation</tt> property to either
+ * <tt>TwoPCommonIndices::pWsN</tt> or <tt>TwoPCommonIndices::pNsW</tt>. By
+ * default, the model uses \f$p_w\f$ and \f$S_n\f$.
+ */
+template<class TypeTag >
+class TwoPModel : public GET_PROP_TYPE(TypeTag, BaseModel)
+{
+    typedef typename GET_PROP_TYPE(TypeTag, FVElementGeometry) FVElementGeometry;
+    typedef typename GET_PROP_TYPE(TypeTag, VolumeVariables) VolumeVariables;
+    typedef typename GET_PROP_TYPE(TypeTag, SolutionVector) SolutionVector;
+    typedef typename GET_PROP_TYPE(TypeTag, FluxVariables) FluxVariables;
+    typedef typename GET_PROP_TYPE(TypeTag, ElementVolumeVariables) ElementVolumeVariables;
+
+    typedef typename GET_PROP_TYPE(TypeTag, Indices) Indices;
+    enum {
+        nPhaseIdx = Indices::nPhaseIdx,
+        wPhaseIdx = Indices::wPhaseIdx,
+        pressureIdx = Indices::pressureIdx,
+        numPhases = GET_PROP_VALUE(TypeTag, NumPhases)
+    };
+
+    typedef typename GET_PROP_TYPE(TypeTag, GridView) GridView;
+    typedef typename GridView::template Codim<0>::Entity Element;
+    typedef typename GridView::template Codim<0>::Iterator ElementIterator;
+    typedef typename GridView::ctype CoordScalar;
+    enum {
+        dim = GridView::dimension,
+        dimWorld = GridView::dimensionworld
+    };
+
+    typedef typename GET_PROP_TYPE(TypeTag, Scalar) Scalar;
+    typedef Dune::FieldVector<Scalar, numPhases> PhasesVector;
+    typedef Dune::FieldVector<Scalar, dimWorld> GlobalPosition;
+
+public:
+    /*!
+     * \brief Append all quantities of interest which can be derived
+     *        from the solution of the current time step to the VTK
+     *        writer.
+     *
+     *        \param sol The global solution vector
+     *        \param writer The writer for multi-file VTK datasets
+     */
+    template<class MultiWriter>
+    void addOutputVtkFields(const SolutionVector &sol,
+                            MultiWriter &writer)
+    {
+        bool velocityOutput = GET_PARAM_FROM_GROUP(TypeTag, bool, Vtk, AddVelocity);
+        typedef Dune::BlockVector<Dune::FieldVector<double, 1> > ScalarField;
+        typedef Dune::BlockVector<Dune::FieldVector<double, dim> > VectorField;
+
+	// get the number of degrees of freedom and the number of vertices
+        unsigned numDofs = this->numDofs();
+        unsigned numVertices = this->problem_().gridView().size(dim);
+	
+	// velocity output currently only works for vertex data
+	if (numDofs != numVertices)
+	  velocityOutput = false;
+	
+        // create the required scalar fields
+        ScalarField *pW = writer.allocateManagedBuffer(numDofs);
+        ScalarField *pN = writer.allocateManagedBuffer(numDofs);
+        ScalarField *pC = writer.allocateManagedBuffer(numDofs);
+        ScalarField *Sw = writer.allocateManagedBuffer(numDofs);
+        ScalarField *Sn = writer.allocateManagedBuffer(numDofs);
+        ScalarField *rhoW = writer.allocateManagedBuffer(numDofs);
+        ScalarField *rhoN = writer.allocateManagedBuffer(numDofs);
+        ScalarField *mobW = writer.allocateManagedBuffer(numDofs);
+        ScalarField *mobN = writer.allocateManagedBuffer(numDofs);
+        ScalarField *poro = writer.allocateManagedBuffer(numDofs);
+        ScalarField *Te = writer.allocateManagedBuffer(numDofs);
+        ScalarField *cellNum =writer.allocateManagedBuffer (numDofs);
+        VectorField *velocityN = writer.template allocateManagedBuffer<double, dim>(numDofs);
+        VectorField *velocityW = writer.template allocateManagedBuffer<double, dim>(numDofs);
+
+        if(velocityOutput) // check if velocity output is demanded
+        {
+            // initialize velocity fields
+            for (unsigned int i = 0; i < numVertices; ++i)
+            {
+                (*velocityN)[i] = Scalar(0);
+                (*velocityW)[i] = Scalar(0);
+                (*cellNum)[i] = Scalar(0.0);
+            }
+        }
+        unsigned numElements = this->gridView_().size(0);
+        ScalarField *rank = writer.allocateManagedBuffer(numElements);
+
+        FVElementGeometry fvGeometry;
+        VolumeVariables volVars;
+        ElementVolumeVariables elemVolVars;
+
+        ElementIterator elemIt = this->gridView_().template begin<0>();
+        ElementIterator elemEndIt = this->gridView_().template end<0>();
+        for (; elemIt != elemEndIt; ++elemIt)
+        {
+            if(velocityOutput && !elemIt->geometry().type().isCube()){
+                DUNE_THROW(Dune::InvalidStateException,
+                           "Currently, velocity output only works for cubes. "
+                           "Please set the EnableVelocityOutput property to false!");
+            }
+            int idx = this->elementMapper().map(*elemIt);
+            (*rank)[idx] = this->gridView_().comm().rank();
+
+            fvGeometry.update(this->gridView_(), *elemIt);
+
+            if (numDofs == numElements) // element data
+            {
+                volVars.update(sol[idx],
+                               this->problem_(),
+                               *elemIt,
+                               fvGeometry,
+                               /*scvIdx=*/0,
+                               false);
+
+                (*pW)[idx] = volVars.pressure(wPhaseIdx);
+                (*pN)[idx] = volVars.pressure(nPhaseIdx);
+                (*pC)[idx] = volVars.capillaryPressure();
+                (*Sw)[idx] = volVars.saturation(wPhaseIdx);
+                (*Sn)[idx] = volVars.saturation(nPhaseIdx);
+                (*rhoW)[idx] = volVars.density(wPhaseIdx);
+                (*rhoN)[idx] = volVars.density(nPhaseIdx);
+                (*mobW)[idx] = volVars.mobility(wPhaseIdx);
+                (*mobN)[idx] = volVars.mobility(nPhaseIdx);
+                (*poro)[idx] = volVars.porosity();
+                (*Te)[idx] = volVars.temperature();
+            }
+            else // vertex data
+            {
+                int numVerts = elemIt->template count<dim> ();
+                for (int scvIdx = 0; scvIdx < numVerts; ++scvIdx)
+                {
+                    int globalIdx = this->vertexMapper().map(*elemIt, scvIdx, dim);
+                    volVars.update(sol[globalIdx],
+                                   this->problem_(),
+                                   *elemIt,
+                                   fvGeometry,
+                                   scvIdx,
+                                   false);
+
+                    (*pW)[globalIdx] = volVars.pressure(wPhaseIdx);
+                    (*pN)[globalIdx] = volVars.pressure(nPhaseIdx);
+                    (*pC)[globalIdx] = volVars.capillaryPressure();
+                    (*Sw)[globalIdx] = volVars.saturation(wPhaseIdx);
+                    (*Sn)[globalIdx] = volVars.saturation(nPhaseIdx);
+                    (*rhoW)[globalIdx] = volVars.density(wPhaseIdx);
+                    (*rhoN)[globalIdx] = volVars.density(nPhaseIdx);
+                    (*mobW)[globalIdx] = volVars.mobility(wPhaseIdx);
+                    (*mobN)[globalIdx] = volVars.mobility(nPhaseIdx);
+                    (*poro)[globalIdx] = volVars.porosity();
+                    (*Te)[globalIdx] = volVars.temperature();
+                    if(velocityOutput)
+                    {
+                        (*cellNum)[globalIdx] += 1;
+                    }
+                }
+
+                if(velocityOutput)
+                {
+                    // calculate vertex velocities
+                    GlobalPosition tmpVelocity[numPhases];
+
+                    for(int phaseIdx = 0; phaseIdx < numPhases; ++phaseIdx)
+                    {
+                        tmpVelocity[phaseIdx]  = Scalar(0.0);
+                    }
+
+                    typedef Dune::BlockVector<Dune::FieldVector<Scalar, dim> > SCVVelocities;
+                    SCVVelocities scvVelocityW(8), scvVelocityN(8);
+
+                    scvVelocityW = 0;
+                    scvVelocityN = 0;
+
+                    ElementVolumeVariables elemVolVars;
+
+                    elemVolVars.update(this->problem_(),
+                                       *elemIt,
+                                       fvGeometry,
+                                       false /* oldSol? */);
+
+                    for (int faceIdx = 0; faceIdx < fvGeometry.numEdges; faceIdx++)
+                    {
+
+                        FluxVariables fluxVars(this->problem_(),
+                                             *elemIt,
+                                             fvGeometry,
+                                             faceIdx,
+                                             elemVolVars);
+
+                        for (int phaseIdx = 0; phaseIdx < numPhases; ++phaseIdx)
+                        {
+                           // local position of integration point
+                           const Dune::FieldVector<Scalar, dim>& localPosIP = fvGeometry.subContVolFace[faceIdx].ipLocal;
+
+                           // Transformation of the global normal vector to normal vector in the reference element
+                           const typename Element::Geometry::JacobianTransposed& jacobianT1 = 
+                               elemIt->geometry().jacobianTransposed(localPosIP);
+
+                           const GlobalPosition globalNormal = fluxVars.face().normal;
+                           GlobalPosition localNormal;
+                           jacobianT1.mv(globalNormal, localNormal);
+                           // note only works for cubes
+                           const Scalar localArea = pow(2,-(dim-1));
+
+                           localNormal /= localNormal.two_norm();
+
+                           // Get the Darcy velocities. The Darcy velocities are divided by the area of the subcontrolvolumeface
+                           // in the reference element.
+                           PhasesVector q;
+                           q[phaseIdx] = fluxVars.volumeFlux(phaseIdx) / localArea;
+
+                           // transform the normal Darcy velocity into a vector
+                           tmpVelocity[phaseIdx] = localNormal;
+                           tmpVelocity[phaseIdx] *= q[phaseIdx];
+
+                           if(phaseIdx == wPhaseIdx){
+                               scvVelocityW[fluxVars.face().i] += tmpVelocity[phaseIdx];
+                               scvVelocityW[fluxVars.face().j] += tmpVelocity[phaseIdx];
+                           }
+                           else if(phaseIdx == nPhaseIdx){
+                               scvVelocityN[fluxVars.face().i] += tmpVelocity[phaseIdx];
+                               scvVelocityN[fluxVars.face().j] += tmpVelocity[phaseIdx];
+                           }
+                        }
+                    }
+                    typedef Dune::GenericReferenceElements<Scalar, dim> ReferenceElements;
+                    const Dune::FieldVector<Scalar, dim> &localPos
+                        = ReferenceElements::general(elemIt->geometry().type()).position(0, 0);
+
+                    // get the transposed Jacobian of the element mapping
+                    const typename Element::Geometry::JacobianTransposed& jacobianT2
+                        = elemIt->geometry().jacobianTransposed(localPos);
+
+                    // transform vertex velocities from local to global coordinates
+                    for (int i = 0; i < numVerts; ++i)
+                    {
+                        int globalIdx = this->vertexMapper().map(*elemIt, i, dim);
+                        // calculate the subcontrolvolume velocity by the Piola transformation
+                        Dune::FieldVector<CoordScalar, dim> scvVelocity(0);
+
+                        jacobianT2.mtv(scvVelocityW[i], scvVelocity);
+                        scvVelocity /= elemIt->geometry().integrationElement(localPos);
+                        // add up the wetting phase subcontrolvolume velocities for each vertex
+                        (*velocityW)[globalIdx] += scvVelocity;
+
+                        jacobianT2.mtv(scvVelocityN[i], scvVelocity);
+                        scvVelocity /= elemIt->geometry().integrationElement(localPos);
+                        // add up the nonwetting phase subcontrolvolume velocities for each vertex
+                        (*velocityN)[globalIdx] += scvVelocity;
+                    }
+                }
+            }
+        }
+
+        if (numDofs == numElements) // element data
+        {
+            writer.attachCellData(*Sn, "Sn");
+            writer.attachCellData(*Sw, "Sw");
+            writer.attachCellData(*pN, "pn");
+            writer.attachCellData(*pW, "pw");
+            writer.attachCellData(*pC, "pc");
+            writer.attachCellData(*rhoW, "rhoW");
+            writer.attachCellData(*rhoN, "rhoN");
+            writer.attachCellData(*mobW, "mobW");
+            writer.attachCellData(*mobN, "mobN");
+            writer.attachCellData(*poro, "porosity");
+            writer.attachCellData(*Te, "temperature");
+        }
+        else // vertex data
+        {
+            writer.attachVertexData(*Sn, "Sn");
+            writer.attachVertexData(*Sw, "Sw");
+            writer.attachVertexData(*pN, "pn");
+            writer.attachVertexData(*pW, "pw");
+            writer.attachVertexData(*pC, "pc");
+            writer.attachVertexData(*rhoW, "rhoW");
+            writer.attachVertexData(*rhoN, "rhoN");
+            writer.attachVertexData(*mobW, "mobW");
+            writer.attachVertexData(*mobN, "mobN");
+            writer.attachVertexData(*poro, "porosity");
+            writer.attachVertexData(*Te, "temperature");
+            if(velocityOutput) // check if velocity output is demanded
+            {
+                // divide the vertex velocities by the number of adjacent scvs i.e. cells
+                for(unsigned int globalIdx = 0; globalIdx < numVertices; ++globalIdx){
+                    (*velocityW)[globalIdx] /= (*cellNum)[globalIdx];
+                    (*velocityN)[globalIdx] /= (*cellNum)[globalIdx];
+                }
+                writer.attachVertexData(*velocityW,  "velocityW", dim);
+                writer.attachVertexData(*velocityN,  "velocityN", dim);
+            }
+        }
+        writer.attachCellData(*rank, "process rank");
+    }
+};
+}
+
+#include "2ppropertydefaults.hh"
+
+#endif
diff --git a/dumux/implicit/2p/2pproperties.hh b/dumux/implicit/2p/2pproperties.hh
new file mode 100644
index 0000000000..c86ab53d93
--- /dev/null
+++ b/dumux/implicit/2p/2pproperties.hh
@@ -0,0 +1,76 @@
+// -*- mode: C++; tab-width: 4; indent-tabs-mode: nil; c-basic-offset: 4 -*-
+// vi: set et ts=4 sw=4 sts=4:
+/*****************************************************************************
+ *   See the file COPYING for full copying permissions.                      *
+ *                                                                           *
+ *   This program is free software: you can redistribute it and/or modify    *
+ *   it under the terms of the GNU General Public License as published by    *
+ *   the Free Software Foundation, either version 2 of the License, or       *
+ *   (at your option) any later version.                                     *
+ *                                                                           *
+ *   This program is distributed in the hope that it will be useful,         *
+ *   but WITHOUT ANY WARRANTY; without even the implied warranty of          *
+ *   MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the            *
+ *   GNU General Public License for more details.                            *
+ *                                                                           *
+ *   You should have received a copy of the GNU General Public License       *
+ *   along with this program.  If not, see <http://www.gnu.org/licenses/>.   *
+ *****************************************************************************/
+/*!
+ * \ingroup Properties
+ * \ingroup BoxProperties
+ * \ingroup TwoPBoxModel
+ */
+/*!
+ * \file
+ *
+ * \brief Defines the properties required for the twophase BOX model.
+ */
+
+#ifndef DUMUX_2P_PROPERTIES_HH
+#define DUMUX_2P_PROPERTIES_HH
+
+#include <dumux/boxmodels/common/boxproperties.hh>
+
+namespace Dumux
+{
+
+
+
+////////////////////////////////
+// properties
+////////////////////////////////
+namespace Properties
+{
+
+//////////////////////////////////////////////////////////////////
+// Type tags
+//////////////////////////////////////////////////////////////////
+
+//! The type tag for the two-phase problems
+NEW_TYPE_TAG(BoxTwoP, INHERITS_FROM(BoxModel));
+
+//////////////////////////////////////////////////////////////////
+// Property tags
+//////////////////////////////////////////////////////////////////
+
+NEW_PROP_TAG(NumPhases);   //!< Number of fluid phases in the system
+NEW_PROP_TAG(ProblemEnableGravity); //!< Returns whether gravity is considered in the problem
+NEW_PROP_TAG(ImplicitMassUpwindWeight); //!< The value of the weight of the upwind direction in the mass conservation equations
+NEW_PROP_TAG(ImplicitMobilityUpwindWeight); //!< Weight for the upwind mobility in the velocity calculation
+NEW_PROP_TAG(Formulation);   //!< The formulation of the model
+NEW_PROP_TAG(Indices); //!< Enumerations for the model
+NEW_PROP_TAG(SpatialParams); //!< The type of the spatial parameters
+NEW_PROP_TAG(MaterialLaw);   //!< The material law which ought to be used (extracted from the spatial parameters)
+NEW_PROP_TAG(MaterialLawParams); //!< The context material law (extracted from the spatial parameters)
+NEW_PROP_TAG(WettingPhase); //!< The wetting phase for two-phase models
+NEW_PROP_TAG(NonwettingPhase); //!< The non-wetting phase for two-phase models
+NEW_PROP_TAG(FluidSystem); //!<The fluid systems including the information about the phases
+NEW_PROP_TAG(FluidState); //!<The phases state
+NEW_PROP_TAG(VtkAddVelocity); //!< Returns whether velocity vectors are written into the vtk output
+NEW_PROP_TAG(SpatialParamsForchCoeff); //!< Property for the forchheimer coefficient
+}
+
+}
+
+#endif
diff --git a/dumux/implicit/2p/2ppropertydefaults.hh b/dumux/implicit/2p/2ppropertydefaults.hh
new file mode 100644
index 0000000000..2cd202b430
--- /dev/null
+++ b/dumux/implicit/2p/2ppropertydefaults.hh
@@ -0,0 +1,148 @@
+// -*- mode: C++; tab-width: 4; indent-tabs-mode: nil; c-basic-offset: 4 -*-
+// vi: set et ts=4 sw=4 sts=4:
+/*****************************************************************************
+ *   See the file COPYING for full copying permissions.                      *
+ *                                                                           *
+ *   This program is free software: you can redistribute it and/or modify    *
+ *   it under the terms of the GNU General Public License as published by    *
+ *   the Free Software Foundation, either version 2 of the License, or       *
+ *   (at your option) any later version.                                     *
+ *                                                                           *
+ *   This program is distributed in the hope that it will be useful,         *
+ *   but WITHOUT ANY WARRANTY; without even the implied warranty of          *
+ *   MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the            *
+ *   GNU General Public License for more details.                            *
+ *                                                                           *
+ *   You should have received a copy of the GNU General Public License       *
+ *   along with this program.  If not, see <http://www.gnu.org/licenses/>.   *
+ *****************************************************************************/
+/*!
+ * \ingroup TwoPBoxModel
+ * \ingroup BoxProperties
+ * \ingroup Properties
+ * \file
+ *
+ * \brief Defines default values for the properties required by the
+ *        twophase box model.
+ */
+#ifndef DUMUX_2P_PROPERTY_DEFAULTS_HH
+#define DUMUX_2P_PROPERTY_DEFAULTS_HH
+
+#include "2pmodel.hh"
+#include "2pindices.hh"
+#include <dumux/boxmodels/common/boxdarcyfluxvariables.hh>
+#include "2pvolumevariables.hh"
+#include "2pproperties.hh"
+
+#include <dumux/material/fluidsystems/gasphase.hh>
+#include <dumux/material/fluidsystems/liquidphase.hh>
+#include <dumux/material/components/nullcomponent.hh>
+#include <dumux/material/fluidsystems/2pimmisciblefluidsystem.hh>
+#include <dumux/material/fluidstates/immisciblefluidstate.hh>
+#include <dumux/material/spatialparams/boxspatialparams.hh>
+
+namespace Dumux
+{
+namespace Properties
+{
+//////////////////////////////////////////////////////////////////
+// Property defaults
+//////////////////////////////////////////////////////////////////
+SET_INT_PROP(BoxTwoP, NumEq, 2); //!< set the number of equations to 2
+SET_INT_PROP(BoxTwoP, NumPhases, 2); //!< The number of phases in the 2p model is 2
+
+//! Set the default formulation to pWsN
+SET_INT_PROP(BoxTwoP,
+             Formulation,
+             TwoPFormulation::pwSn);
+
+//! Use the 2p local jacobian operator for the 2p model
+SET_TYPE_PROP(BoxTwoP,
+              LocalResidual,
+              TwoPLocalResidual<TypeTag>);
+
+//! the Model property
+SET_TYPE_PROP(BoxTwoP, Model, TwoPModel<TypeTag>);
+
+//! the VolumeVariables property
+SET_TYPE_PROP(BoxTwoP, VolumeVariables, TwoPVolumeVariables<TypeTag>);
+
+//! the FluxVariables property
+SET_TYPE_PROP(BoxTwoP, FluxVariables, BoxDarcyFluxVariables<TypeTag>);
+
+//! the upwind weight for the mass conservation equations.
+SET_SCALAR_PROP(BoxTwoP, ImplicitMassUpwindWeight, 1.0);
+
+//! weight for the upwind mobility in the velocity calculation
+SET_SCALAR_PROP(BoxTwoP, ImplicitMobilityUpwindWeight, 1.0);
+
+//! The indices required by the isothermal 2p model
+SET_TYPE_PROP(BoxTwoP, 
+              Indices, 
+              TwoPIndices<TypeTag, GET_PROP_VALUE(TypeTag, Formulation), 0>);
+
+//! The spatial parameters to be employed. 
+//! Use BoxSpatialParams by default.
+SET_TYPE_PROP(BoxTwoP, SpatialParams, BoxSpatialParams<TypeTag>);
+
+/*!
+ * \brief Set the property for the material parameters by extracting
+ *        it from the material law.
+ */
+SET_TYPE_PROP(BoxTwoP,
+              MaterialLawParams,
+              typename GET_PROP_TYPE(TypeTag, MaterialLaw)::Params);
+
+SET_PROP(BoxTwoP, WettingPhase)
+{ private:
+    typedef typename GET_PROP_TYPE(TypeTag, Scalar) Scalar;
+public:
+    typedef Dumux::LiquidPhase<Scalar, Dumux::NullComponent<Scalar> > type;
+};
+
+SET_PROP(BoxTwoP, NonwettingPhase)
+{ private:
+    typedef typename GET_PROP_TYPE(TypeTag, Scalar) Scalar;
+public:
+    typedef Dumux::LiquidPhase<Scalar, Dumux::NullComponent<Scalar> > type;
+};
+
+SET_PROP(BoxTwoP, FluidSystem)
+{ private:
+    typedef typename GET_PROP_TYPE(TypeTag, Scalar) Scalar;
+    typedef typename GET_PROP_TYPE(TypeTag, WettingPhase) WettingPhase;
+    typedef typename GET_PROP_TYPE(TypeTag, NonwettingPhase) NonwettingPhase;
+
+public:
+    typedef Dumux::FluidSystems::TwoPImmiscible<Scalar,
+                                                WettingPhase,
+                                                NonwettingPhase> type;
+};
+
+SET_PROP(BoxTwoP, FluidState)
+{
+private:
+    typedef typename GET_PROP_TYPE(TypeTag, Scalar) Scalar;
+    typedef typename GET_PROP_TYPE(TypeTag, FluidSystem) FluidSystem;
+public:
+    typedef ImmiscibleFluidState<Scalar, FluidSystem> type;
+};
+
+// disable velocity output by default
+SET_BOOL_PROP(BoxTwoP, VtkAddVelocity, false);
+
+// enable gravity by default
+SET_BOOL_PROP(BoxTwoP, ProblemEnableGravity, true);
+
+//! default value for the forchheimer coefficient
+// Source: Ward, J.C. 1964 Turbulent flow in porous media. ASCE J. Hydraul. Div 90.
+//        Actually the Forchheimer coefficient is also a function of the dimensions of the
+//        porous medium. Taking it as a constant is only a first approximation
+//        (Nield, Bejan, Convection in porous media, 2006, p. 10)
+SET_SCALAR_PROP(BoxModel, SpatialParamsForchCoeff, 0.55);
+}
+//
+
+}
+
+#endif
diff --git a/dumux/implicit/2p/2pvolumevariables.hh b/dumux/implicit/2p/2pvolumevariables.hh
new file mode 100644
index 0000000000..24e953f6a7
--- /dev/null
+++ b/dumux/implicit/2p/2pvolumevariables.hh
@@ -0,0 +1,279 @@
+// -*- mode: C++; tab-width: 4; indent-tabs-mode: nil; c-basic-offset: 4 -*-
+// vi: set et ts=4 sw=4 sts=4:
+/*****************************************************************************
+ *   See the file COPYING for full copying permissions.                      *
+ *                                                                           *
+ *   This program is free software: you can redistribute it and/or modify    *
+ *   it under the terms of the GNU General Public License as published by    *
+ *   the Free Software Foundation, either version 2 of the License, or       *
+ *   (at your option) any later version.                                     *
+ *                                                                           *
+ *   This program is distributed in the hope that it will be useful,         *
+ *   but WITHOUT ANY WARRANTY; without even the implied warranty of          *
+ *   MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the            *
+ *   GNU General Public License for more details.                            *
+ *                                                                           *
+ *   You should have received a copy of the GNU General Public License       *
+ *   along with this program.  If not, see <http://www.gnu.org/licenses/>.   *
+ *****************************************************************************/
+/*!
+ * \file
+ *
+ * \brief Contains the quantities which are constant within a
+ *        finite volume in the two-phase model.
+ */
+#ifndef DUMUX_2P_VOLUME_VARIABLES_HH
+#define DUMUX_2P_VOLUME_VARIABLES_HH
+
+#include "2pproperties.hh"
+
+#include <dumux/boxmodels/common/boxvolumevariables.hh>
+
+#include <dune/common/fvector.hh>
+
+namespace Dumux
+{
+/*!
+ * \ingroup TwoPBoxModel
+ * \ingroup BoxVolumeVariables
+ * \brief Contains the quantities which are are constant within a
+ *        finite volume in the two-phase model.
+ */
+template <class TypeTag>
+class TwoPVolumeVariables : public BoxVolumeVariables<TypeTag>
+{
+    typedef BoxVolumeVariables<TypeTag> ParentType;
+
+    typedef typename GET_PROP_TYPE(TypeTag, VolumeVariables) Implementation;
+    typedef typename GET_PROP_TYPE(TypeTag, Scalar) Scalar;
+    typedef typename GET_PROP_TYPE(TypeTag, Problem) Problem;
+    typedef typename GET_PROP_TYPE(TypeTag, FluidSystem) FluidSystem;
+    typedef typename GET_PROP_TYPE(TypeTag, FluidState) FluidState;
+    typedef typename GET_PROP_TYPE(TypeTag, MaterialLaw) MaterialLaw;
+    typedef typename GET_PROP_TYPE(TypeTag, MaterialLawParams) MaterialLawParams;
+    typedef typename GET_PROP_TYPE(TypeTag, FVElementGeometry) FVElementGeometry;
+    typedef typename GET_PROP_TYPE(TypeTag, PrimaryVariables) PrimaryVariables;
+
+    typedef typename GET_PROP_TYPE(TypeTag, Indices) Indices;
+    enum {
+        pwSn = Indices::pwSn,
+        pnSw = Indices::pnSw,
+        pressureIdx = Indices::pressureIdx,
+        saturationIdx = Indices::saturationIdx,
+        wPhaseIdx = Indices::wPhaseIdx,
+        nPhaseIdx = Indices::nPhaseIdx,
+        numPhases = GET_PROP_VALUE(TypeTag, NumPhases),
+        formulation = GET_PROP_VALUE(TypeTag, Formulation)
+    };
+
+    typedef typename GET_PROP_TYPE(TypeTag, GridView) GridView;
+    typedef typename GridView::template Codim<0>::Entity Element;
+
+public:
+    /*!
+     * \copydoc BoxVolumeVariables::update
+     */
+    void update(const PrimaryVariables &priVars,
+                const Problem &problem,
+                const Element &element,
+                const FVElementGeometry &fvGeometry,
+                int scvIdx,
+                bool isOldSol)
+    {
+        ParentType::update(priVars,
+                           problem,
+                           element,
+                           fvGeometry,
+                           scvIdx,
+                           isOldSol);
+
+        completeFluidState(priVars, problem, element, fvGeometry, scvIdx, fluidState_);
+
+        const MaterialLawParams &materialParams =
+            problem.spatialParams().materialLawParams(element, fvGeometry, scvIdx);
+
+        mobility_[wPhaseIdx] =
+            MaterialLaw::krw(materialParams, fluidState_.saturation(wPhaseIdx))
+            / fluidState_.viscosity(wPhaseIdx);
+
+        mobility_[nPhaseIdx] =
+            MaterialLaw::krn(materialParams, fluidState_.saturation(wPhaseIdx))
+            / fluidState_.viscosity(nPhaseIdx);
+
+        // porosity
+        porosity_ = problem.spatialParams().porosity(element,
+                                                     fvGeometry,
+                                                     scvIdx);
+
+        // energy related quantities not belonging to the fluid state
+        asImp_().updateEnergy_(priVars, problem, element, fvGeometry, scvIdx, isOldSol);
+    }
+
+    /*!
+     * \copydoc BoxModel::completeFluidState
+     */
+    static void completeFluidState(const PrimaryVariables& priVars,
+                                   const Problem& problem,
+                                   const Element& element,
+                                   const FVElementGeometry& fvGeometry,
+                                   int scvIdx,
+                                   FluidState& fluidState)
+    {
+        Scalar t = Implementation::temperature_(priVars, problem, element,
+                                                fvGeometry, scvIdx);
+        fluidState.setTemperature(t);
+
+        // material law parameters
+        typedef typename GET_PROP_TYPE(TypeTag, MaterialLaw) MaterialLaw;
+        const typename MaterialLaw::Params &materialParams =
+            problem.spatialParams().materialLawParams(element, fvGeometry, scvIdx);
+
+
+        if (int(formulation) == pwSn) {
+            Scalar Sn = priVars[saturationIdx];
+            fluidState.setSaturation(nPhaseIdx, Sn);
+            fluidState.setSaturation(wPhaseIdx, 1 - Sn);
+
+            Scalar pW = priVars[pressureIdx];
+            fluidState.setPressure(wPhaseIdx, pW);
+            fluidState.setPressure(nPhaseIdx,
+                                   pW + MaterialLaw::pC(materialParams, 1 - Sn));
+        }
+        else if (int(formulation) == pnSw) {
+            Scalar Sw = priVars[saturationIdx];
+            fluidState.setSaturation(wPhaseIdx, Sw);
+            fluidState.setSaturation(nPhaseIdx, 1 - Sw);
+
+            Scalar pN = priVars[pressureIdx];
+            fluidState.setPressure(nPhaseIdx, pN);
+            fluidState.setPressure(wPhaseIdx,
+                                   pN - MaterialLaw::pC(materialParams, Sw));
+        }
+
+        typedef typename GET_PROP_TYPE(TypeTag, FluidSystem) FluidSystem;
+        typename FluidSystem::ParameterCache paramCache;
+        paramCache.updateAll(fluidState);
+
+        for (int phaseIdx = 0; phaseIdx < numPhases; ++phaseIdx) {
+            // compute and set the viscosity
+            Scalar mu = FluidSystem::viscosity(fluidState, paramCache, phaseIdx);
+            fluidState.setViscosity(phaseIdx, mu);
+
+            // compute and set the density
+            Scalar rho = FluidSystem::density(fluidState, paramCache, phaseIdx);
+            fluidState.setDensity(phaseIdx, rho);
+
+            // compute and set the enthalpy
+            Scalar h = Implementation::enthalpy_(fluidState, paramCache, phaseIdx);
+            fluidState.setEnthalpy(phaseIdx, h);
+        }
+    }
+
+    /*!
+     * \brief Returns the phase state for the control-volume.
+     */
+    const FluidState &fluidState() const
+    { return fluidState_; }
+
+    /*!
+     * \brief Returns the effective saturation of a given phase within
+     *        the control volume.
+     *
+     * \param phaseIdx The phase index
+     */
+    Scalar saturation(int phaseIdx) const
+    { return fluidState_.saturation(phaseIdx); }
+
+    /*!
+     * \brief Returns the mass density of a given phase within the
+     *        control volume.
+     *
+     * \param phaseIdx The phase index
+     */
+    Scalar density(int phaseIdx) const
+    { return fluidState_.density(phaseIdx); }
+
+    /*!
+     * \brief Returns the effective pressure of a given phase within
+     *        the control volume.
+     *
+     * \param phaseIdx The phase index
+     */
+    Scalar pressure(int phaseIdx) const
+    { return fluidState_.pressure(phaseIdx); }
+
+    /*!
+     * \brief Returns the capillary pressure within the control volume [Pa].
+     */
+    Scalar capillaryPressure() const
+    { return fluidState_.pressure(nPhaseIdx) - fluidState_.pressure(wPhaseIdx); }
+
+    /*!
+     * \brief Returns temperature inside the sub-control volume.
+     *
+     * Note that we assume thermodynamic equilibrium, i.e. the
+     * temperature of the rock matrix and of all fluid phases are
+     * identical.
+     */
+    Scalar temperature() const
+    { return fluidState_.temperature(/*phaseIdx=*/0); }
+
+    /*!
+     * \brief Returns the effective mobility of a given phase within
+     *        the control volume.
+     *
+     * \param phaseIdx The phase index
+     */
+    Scalar mobility(int phaseIdx) const
+    { return mobility_[phaseIdx]; }
+
+    /*!
+     * \brief Returns the average porosity within the control volume.
+     */
+    Scalar porosity() const
+    { return porosity_; }
+
+protected:
+    static Scalar temperature_(const PrimaryVariables &priVars,
+                               const Problem& problem,
+                               const Element &element,
+                               const FVElementGeometry &fvGeometry,
+                               int scvIdx)
+    {
+        return problem.boxTemperature(element, fvGeometry, scvIdx);
+    }
+
+    template<class ParameterCache>
+    static Scalar enthalpy_(const FluidState& fluidState,
+                            const ParameterCache& paramCache,
+                            int phaseIdx)
+    {
+        return 0;
+    }
+
+    /*!
+     * \brief Called by update() to compute the energy related quantities
+     */
+    void updateEnergy_(const PrimaryVariables &sol,
+                       const Problem &problem,
+                       const Element &element,
+                       const FVElementGeometry &fvGeometry,
+                       int vertIdx,
+                       bool isOldSol)
+    { }
+
+    FluidState fluidState_;
+    Scalar porosity_;
+    Scalar mobility_[numPhases];
+
+private:
+    Implementation &asImp_()
+    { return *static_cast<Implementation*>(this); }
+
+    const Implementation &asImp_() const
+    { return *static_cast<const Implementation*>(this); }
+};
+
+}
+
+#endif
diff --git a/dumux/implicit/2p/Makefile.am b/dumux/implicit/2p/Makefile.am
new file mode 100644
index 0000000000..27994b7a07
--- /dev/null
+++ b/dumux/implicit/2p/Makefile.am
@@ -0,0 +1,5 @@
+2pdir = $(includedir)/dumux/boxmodels/2p
+2p_HEADERS = *.hh
+
+include $(top_srcdir)/am/global-rules
+
diff --git a/dumux/implicit/2p2c/2p2cfluxvariables.hh b/dumux/implicit/2p2c/2p2cfluxvariables.hh
new file mode 100644
index 0000000000..f93b15a39b
--- /dev/null
+++ b/dumux/implicit/2p2c/2p2cfluxvariables.hh
@@ -0,0 +1,246 @@
+// -*- mode: C++; tab-width: 4; indent-tabs-mode: nil; c-basic-offset: 4 -*-
+// vi: set et ts=4 sw=4 sts=4:
+/*****************************************************************************
+ *   See the file COPYING for full copying permissions.                      *
+ *                                                                           *
+ *   This program is free software: you can redistribute it and/or modify    *
+ *   it under the terms of the GNU General Public License as published by    *
+ *   the Free Software Foundation, either version 2 of the License, or       *
+ *   (at your option) any later version.                                     *
+ *                                                                           *
+ *   This program is distributed in the hope that it will be useful,         *
+ *   but WITHOUT ANY WARRANTY; without even the implied warranty of          *
+ *   MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the            *
+ *   GNU General Public License for more details.                            *
+ *                                                                           *
+ *   You should have received a copy of the GNU General Public License       *
+ *   along with this program.  If not, see <http://www.gnu.org/licenses/>.   *
+ *****************************************************************************/
+/*!
+ * \file
+ *
+ * \brief   This file contains the data which is required to calculate
+ *          all fluxes of components over a face of a finite volume for
+ *          the two-phase, two-component model.
+ */
+#ifndef DUMUX_2P2C_FLUX_VARIABLES_HH
+#define DUMUX_2P2C_FLUX_VARIABLES_HH
+
+#include <dumux/common/math.hh>
+#include <dumux/common/spline.hh>
+
+#include "2p2cproperties.hh"
+
+namespace Dumux
+{
+
+/*!
+ * \ingroup TwoPTwoCModel
+ * \ingroup BoxFluxVariables
+ * \brief This template class contains the data which is required to
+ *        calculate all fluxes of components over a face of a finite
+ *        volume for the two-phase, two-component model.
+ *
+ * This means pressure and concentration gradients, phase densities at
+ * the integration point, etc.
+ */
+template <class TypeTag>
+class TwoPTwoCFluxVariables : public GET_PROP_TYPE(TypeTag, BaseFluxVariables)
+{
+    typedef typename GET_PROP_TYPE(TypeTag, BaseFluxVariables) BaseFluxVariables;
+    typedef typename GET_PROP_TYPE(TypeTag, Problem) Problem;
+    typedef typename GET_PROP_TYPE(TypeTag, VolumeVariables) VolumeVariables;
+    typedef typename GET_PROP_TYPE(TypeTag, ElementVolumeVariables) ElementVolumeVariables;
+    typedef typename GET_PROP_TYPE(TypeTag, SpatialParams) SpatialParams;
+    enum { numPhases = GET_PROP_VALUE(TypeTag, NumPhases) };
+
+    typedef typename GET_PROP_TYPE(TypeTag, Indices) Indices;
+    enum {
+        wPhaseIdx = Indices::wPhaseIdx,
+        nPhaseIdx = Indices::nPhaseIdx,
+        wCompIdx = Indices::wCompIdx,
+        nCompIdx = Indices::nCompIdx
+    };
+
+    typedef typename GET_PROP_TYPE(TypeTag, GridView) GridView;
+    typedef typename GridView::template Codim<0>::Entity Element;
+    enum { dim = GridView::dimension };
+
+    typedef typename GET_PROP_TYPE(TypeTag, Scalar) Scalar;
+    typedef Dune::FieldVector<Scalar, dim> DimVector;
+    typedef Dune::FieldMatrix<Scalar, dim, dim> DimMatrix;
+
+    typedef typename GET_PROP_TYPE(TypeTag, FVElementGeometry) FVElementGeometry;
+    typedef typename FVElementGeometry::SubControlVolumeFace SCVFace;
+
+public:
+    /*
+     * \brief The constructor
+     *
+     * \param problem The problem
+     * \param element The finite element
+     * \param fvGeometry The finite-volume geometry in the box scheme
+    * \param faceIdx The local index of the SCV (sub-control-volume) face
+     * \param elemVolVars The volume variables of the current element
+     * \param onBoundary Distinguishes if we are on a SCV face or on a boundary face
+     */
+    TwoPTwoCFluxVariables(const Problem &problem,
+                          const Element &element,
+                          const FVElementGeometry &fvGeometry,
+                          const int faceIdx,
+                          const ElementVolumeVariables &elemVolVars,
+                          const bool onBoundary = false)
+    : BaseFluxVariables(problem, element, fvGeometry, faceIdx, elemVolVars, onBoundary)
+    {
+        for (int phaseIdx = 0; phaseIdx < numPhases; ++phaseIdx) {
+            density_[phaseIdx] = Scalar(0);
+            molarDensity_[phaseIdx] = Scalar(0);
+            moleFractionGrad_[phaseIdx] = Scalar(0);
+        }
+
+        calculateValues_(problem, element, elemVolVars);
+    }
+
+protected:
+    void calculateValues_(const Problem &problem,
+                          const Element &element,
+                          const ElementVolumeVariables &elemVolVars)
+    {
+        // calculate densities at the integration points of the face
+        DimVector tmp(0.0);
+        for (int idx = 0;
+             idx < this->fvGeometry_.numFAP;
+             idx++) // loop over adjacent vertices
+        {
+            // index for the element volume variables 
+            int volVarsIdx = this->face().fapIndices[idx];
+
+            for (int phaseIdx = 0; phaseIdx < numPhases; phaseIdx++)
+            {
+                density_[phaseIdx] += elemVolVars[volVarsIdx].density(phaseIdx)*
+                    this->face().shapeValue[idx];
+                molarDensity_[phaseIdx] += elemVolVars[volVarsIdx].molarDensity(phaseIdx)*
+                    this->face().shapeValue[idx];
+            }
+        }
+
+        calculateGradients_(problem, element, elemVolVars);
+        calculatePorousDiffCoeff_(problem, element, elemVolVars);
+    }
+
+    void calculateGradients_(const Problem &problem,
+                             const Element &element,
+                             const ElementVolumeVariables &elemVolVars)
+    {
+        // calculate gradients
+        DimVector tmp(0.0);
+        for (int idx = 0;
+             idx < this->fvGeometry_.numFAP;
+             idx++) // loop over adjacent vertices
+        {
+            // FE gradient at vertex idx
+            const DimVector &feGrad = this->face().grad[idx];
+
+            // index for the element volume variables 
+            int volVarsIdx = this->face().fapIndices[idx];
+
+            // the mole fraction gradient of the wetting phase
+            tmp = feGrad;
+            tmp *= elemVolVars[volVarsIdx].fluidState().moleFraction(wPhaseIdx, nCompIdx);
+            moleFractionGrad_[wPhaseIdx] += tmp;
+
+            // the mole fraction gradient of the non-wetting phase
+            tmp = feGrad;
+            tmp *= elemVolVars[volVarsIdx].fluidState().moleFraction(nPhaseIdx, wCompIdx);
+            moleFractionGrad_[nPhaseIdx] += tmp;
+        }
+    }
+
+    Scalar rhoFactor_(int phaseIdx, int scvIdx, const ElementVolumeVariables &vDat)
+    {
+        static const Scalar eps = 1e-2;
+        const Scalar sat = vDat[scvIdx].density(phaseIdx);
+        if (sat > eps)
+            return 0.5;
+        if (sat <= 0)
+            return 0;
+
+        static const Dumux::Spline<Scalar> sp(0, eps, // x0, x1
+                                              0, 0.5, // y0, y1
+                                              0, 0); // m0, m1
+        return sp.eval(sat);
+    }
+
+    void calculatePorousDiffCoeff_(const Problem &problem,
+                                   const Element &element,
+                                   const ElementVolumeVariables &elemVolVars)
+    {
+        const VolumeVariables &volVarsI = elemVolVars[this->face().i];
+        const VolumeVariables &volVarsJ = elemVolVars[this->face().j];
+
+        for (int phaseIdx = 0; phaseIdx < numPhases; ++phaseIdx)
+        {
+            // make sure to only calculate diffusion coefficients
+            // for phases which exist in both finite volumes
+            if (volVarsI.saturation(phaseIdx) <= 0 ||
+                volVarsJ.saturation(phaseIdx) <= 0)
+            {
+                porousDiffCoeff_[phaseIdx] = 0.0;
+                continue;
+            }
+
+            // calculate tortuosity at the nodes i and j needed
+            // for porous media diffusion coefficient
+            Scalar tauI =
+                1.0/(volVarsI.porosity() * volVarsI.porosity()) *
+                pow(volVarsI.porosity() * volVarsI.saturation(phaseIdx), 7.0/3);
+            Scalar tauJ =
+                1.0/(volVarsJ.porosity() * volVarsJ.porosity()) *
+                pow(volVarsJ.porosity() * volVarsJ.saturation(phaseIdx), 7.0/3);
+            // Diffusion coefficient in the porous medium
+
+            // -> harmonic mean
+            porousDiffCoeff_[phaseIdx] = harmonicMean(volVarsI.porosity() * volVarsI.saturation(phaseIdx) * tauI * volVarsI.diffCoeff(phaseIdx),
+                                                      volVarsJ.porosity() * volVarsJ.saturation(phaseIdx) * tauJ * volVarsJ.diffCoeff(phaseIdx));
+        }
+    }
+
+public:
+    /*!
+     * \brief The binary diffusion coefficient for each fluid phase.
+     */
+    Scalar porousDiffCoeff(int phaseIdx) const
+    { return porousDiffCoeff_[phaseIdx]; };
+
+    /*!
+     * \brief Return density \f$\mathrm{[kg/m^3]}\f$ of a phase.
+     */
+    Scalar density(int phaseIdx) const
+    { return density_[phaseIdx]; }
+
+    /*!
+     * \brief Return molar density \f$\mathrm{[mol/m^3]}\f$ of a phase.
+     */
+    Scalar molarDensity(int phaseIdx) const
+    { return molarDensity_[phaseIdx]; }
+
+    /*!
+     * \brief The mole fraction gradient of the dissolved component in a phase.
+     */
+    const DimVector &moleFractionGrad(int phaseIdx) const
+    { return moleFractionGrad_[phaseIdx]; };
+
+protected:
+    // mole fraction gradients
+    DimVector moleFractionGrad_[numPhases];
+
+    // density of each face at the integration point
+    Scalar density_[numPhases], molarDensity_[numPhases];
+
+    // the diffusion coefficient for the porous medium
+    Scalar porousDiffCoeff_[numPhases];
+};
+
+} // end namespace
+
+#endif
diff --git a/dumux/implicit/2p2c/2p2cindices.hh b/dumux/implicit/2p2c/2p2cindices.hh
new file mode 100644
index 0000000000..1f00b2540e
--- /dev/null
+++ b/dumux/implicit/2p2c/2p2cindices.hh
@@ -0,0 +1,129 @@
+// -*- mode: C++; tab-width: 4; indent-tabs-mode: nil; c-basic-offset: 4 -*-
+// vi: set et ts=4 sw=4 sts=4:
+/*****************************************************************************
+ *   See the file COPYING for full copying permissions.                      *
+ *                                                                           *
+ *   This program is free software: you can redistribute it and/or modify    *
+ *   it under the terms of the GNU General Public License as published by    *
+ *   the Free Software Foundation, either version 2 of the License, or       *
+ *   (at your option) any later version.                                     *
+ *                                                                           *
+ *   This program is distributed in the hope that it will be useful,         *
+ *   but WITHOUT ANY WARRANTY; without even the implied warranty of          *
+ *   MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the            *
+ *   GNU General Public License for more details.                            *
+ *                                                                           *
+ *   You should have received a copy of the GNU General Public License       *
+ *   along with this program.  If not, see <http://www.gnu.org/licenses/>.   *
+ *****************************************************************************/
+
+/*!
+ * \file
+ *
+ * \brief Defines the indices required for the 2p2c BOX model.
+ */
+#ifndef DUMUX_2P2C_INDICES_HH
+#define DUMUX_2P2C_INDICES_HH
+
+#include "2p2cproperties.hh"
+
+namespace Dumux
+{
+// \{
+
+/*!
+ * \ingroup TwoPTwoCModel
+ * \ingroup BoxIndices
+ * \brief Enumerates the formulations which the 2p2c model accepts.
+ */
+struct TwoPTwoCFormulation
+{
+    enum {
+        pwSn,
+        pnSw
+    };
+};
+
+/*!
+ * \brief The indices for the isothermal TwoPTwoC model.
+ *
+ * \tparam formulation The formulation, either pwSn or pnSw.
+ * \tparam PVOffset The first index in a primary variable vector.
+ */
+template <class TypeTag,
+          int formulation = TwoPTwoCFormulation::pwSn,
+          int PVOffset = 0>
+class TwoPTwoCIndices
+{
+    typedef typename GET_PROP_TYPE(TypeTag, FluidSystem) FluidSystem;
+
+public:
+    // Phase indices
+    static const int wPhaseIdx = FluidSystem::wPhaseIdx; //!< Index of the wetting phase
+    static const int nPhaseIdx = FluidSystem::nPhaseIdx; //!< Index of the non-wetting phase
+
+    // Component indices
+    static const int wCompIdx = FluidSystem::wCompIdx; //!< Index of the primary component of the wetting phase
+    static const int nCompIdx = FluidSystem::nCompIdx; //!< Index of the primary component of the non-wetting phase
+
+    // present phases (-> 'pseudo' primary variable)
+    static const int wPhaseOnly = 1; //!< Only the wetting phase is present
+    static const int nPhaseOnly = 0; //!< Only the non-wetting phase is present
+    static const int bothPhases = 2; //!< Both phases are present
+
+    // Primary variable indices
+    static const int pressureIdx = PVOffset + 0; //!< Index for wetting/non-wetting phase pressure (depending on formulation) in a solution vector
+    static const int switchIdx = PVOffset + 1; //!< Index of the either the saturation or the mass fraction of the non-wetting/wetting phase
+
+    static const int pwIdx = pressureIdx; //!< Index for wetting phase pressure in a solution vector
+    static const int SnOrXIdx = switchIdx; //!< Index of the either the saturation of the non-wetting phase or the mass fraction secondary component in the only phase
+
+    // equation indices
+    static const int conti0EqIdx = PVOffset; //!< Index of the mass conservation equation for the first component
+    static const int contiWEqIdx = conti0EqIdx + wCompIdx; //!< Index of the mass conservation equation for the liquid's primary component
+    static const int contiNEqIdx = conti0EqIdx + nCompIdx; //!< Index of the mass conservation equation for the gas' primary component
+};
+
+/*!
+ * \brief The indices for the isothermal TwoPTwoC model in the pn-Sw
+ *        formulation.
+ *
+ * \tparam PVOffset The first index in a primary variable vector.
+ */
+template <class TypeTag, int PVOffset>
+class TwoPTwoCIndices<TypeTag, TwoPTwoCFormulation::pnSw, PVOffset>
+{
+    typedef typename GET_PROP_TYPE(TypeTag, FluidSystem) FluidSystem;
+
+public:
+    // Phase indices
+    static const int wPhaseIdx = FluidSystem::wPhaseIdx; //!< Index of the wetting phase
+    static const int nPhaseIdx = FluidSystem::nPhaseIdx; //!< Index of the non-wetting phase
+
+    // Component indices
+    static const int wCompIdx = FluidSystem::wCompIdx; //!< Index of the primary component of the wetting phase
+    static const int nCompIdx = FluidSystem::nCompIdx; //!< Index of the primary component of the non-wetting phase
+
+    // present phases (-> 'pseudo' primary variable)
+    static const int wPhaseOnly = 1; //!< Only the wetting phase is present
+    static const int nPhaseOnly = 2; //!< Only the non-wetting phase is present
+    static const int bothPhases = 3; //!< Both phases are present
+
+    // Primary variable indices
+    static const int pressureIdx = PVOffset + 0; //!< Index for wetting/non-wetting phase pressure (depending on formulation) in a solution vector
+    static const int switchIdx = PVOffset + 1; //!< Index of the either the saturation or the mass fraction of the non-wetting/wetting phase
+
+    static const int pnIdx = pressureIdx; //!< Index for non-wetting phase pressure in a solution vector
+    static const int SwOrXIdx = switchIdx; //!< Index of the either the saturation of the liquid phase or the mass fraction of the secondary component in the only phase
+
+    // Equation indices
+    static const int conti0EqIdx = PVOffset; //!< Index of the mass conservation equation for the first component
+    static const int contiWEqIdx = conti0EqIdx + wCompIdx; //!< Index of the mass conservation equation for the liquid's primary component
+    static const int contiNEqIdx = conti0EqIdx + nCompIdx; //!< Index of the mass conservation equation for the gas' primary component
+};
+
+// \}
+
+}
+
+#endif
diff --git a/dumux/implicit/2p2c/2p2clocalresidual.hh b/dumux/implicit/2p2c/2p2clocalresidual.hh
new file mode 100644
index 0000000000..d36494883f
--- /dev/null
+++ b/dumux/implicit/2p2c/2p2clocalresidual.hh
@@ -0,0 +1,383 @@
+// -*- mode: C++; tab-width: 4; indent-tabs-mode: nil; c-basic-offset: 4 -*-
+// vi: set et ts=4 sw=4 sts=4:
+/*****************************************************************************
+ *   See the file COPYING for full copying permissions.                      *
+ *                                                                           *
+ *   This program is free software: you can redistribute it and/or modify    *
+ *   it under the terms of the GNU General Public License as published by    *
+ *   the Free Software Foundation, either version 2 of the License, or       *
+ *   (at your option) any later version.                                     *
+ *                                                                           *
+ *   This program is distributed in the hope that it will be useful,         *
+ *   but WITHOUT ANY WARRANTY; without even the implied warranty of          *
+ *   MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the            *
+ *   GNU General Public License for more details.                            *
+ *                                                                           *
+ *   You should have received a copy of the GNU General Public License       *
+ *   along with this program.  If not, see <http://www.gnu.org/licenses/>.   *
+ *****************************************************************************/
+/*!
+ * \file
+ *
+ * \brief Element-wise calculation of the Jacobian matrix for problems
+ *        using the two-phase two-component box model.
+ */
+
+#ifndef DUMUX_2P2C_LOCAL_RESIDUAL_BASE_HH
+#define DUMUX_2P2C_LOCAL_RESIDUAL_BASE_HH
+
+#include <dumux/boxmodels/common/boxmodel.hh>
+#include <dumux/common/math.hh>
+
+#include "2p2cproperties.hh"
+#include "2p2cvolumevariables.hh"
+#include "2p2cfluxvariables.hh"
+#include "2p2cnewtoncontroller.hh"
+
+#include <iostream>
+#include <vector>
+
+namespace Dumux
+{
+/*!
+ * \ingroup TwoPTwoCModel
+ * \ingroup BoxLocalResidual
+ * \brief Element-wise calculation of the Jacobian matrix for problems
+ *        using the two-phase two-component box model.
+ *
+ * This class is used to fill the gaps in BoxLocalResidual for the 2P-2C flow.
+ */
+template<class TypeTag>
+class TwoPTwoCLocalResidual: public GET_PROP_TYPE(TypeTag, BaseLocalResidual)
+{
+ protected:
+    typedef typename GET_PROP_TYPE(TypeTag, Scalar) Scalar;
+    typedef typename GET_PROP_TYPE(TypeTag, LocalResidual) Implementation;
+    typedef typename GET_PROP_TYPE(TypeTag, FluidSystem) FluidSystem;
+    typedef typename GET_PROP_TYPE(TypeTag, PrimaryVariables) PrimaryVariables;
+    typedef typename GET_PROP_TYPE(TypeTag, FVElementGeometry) FVElementGeometry;
+    typedef typename GET_PROP_TYPE(TypeTag, VolumeVariables) VolumeVariables;
+    typedef typename GET_PROP_TYPE(TypeTag, ElementVolumeVariables) ElementVolumeVariables;
+    typedef typename GET_PROP_TYPE(TypeTag, BoundaryTypes) BoundaryTypes;
+    typedef typename GET_PROP_TYPE(TypeTag, ElementBoundaryTypes) ElementBoundaryTypes;
+    typedef typename GET_PROP_TYPE(TypeTag, FluxVariables) FluxVariables;
+    enum
+    {
+        numEq = GET_PROP_VALUE(TypeTag, NumEq),
+        numPhases = GET_PROP_VALUE(TypeTag, NumPhases),
+        numComponents = GET_PROP_VALUE(TypeTag, NumComponents)
+    };
+
+    typedef typename GET_PROP_TYPE(TypeTag, Indices) Indices;
+    enum
+    {
+        contiWEqIdx = Indices::contiWEqIdx,
+        contiNEqIdx = Indices::contiNEqIdx,
+        wPhaseIdx = Indices::wPhaseIdx,
+        nPhaseIdx = Indices::nPhaseIdx,
+        wCompIdx = Indices::wCompIdx,
+        nCompIdx = Indices::nCompIdx
+    };
+
+    typedef typename GET_PROP_TYPE(TypeTag, GridView) GridView;
+    typedef typename GridView::template Codim<0>::Entity Element;
+    typedef typename GridView::IntersectionIterator IntersectionIterator;
+
+    static constexpr unsigned int replaceCompEqIdx =
+        GET_PROP_VALUE(TypeTag, ReplaceCompEqIdx);
+
+ public:
+    /*!
+     * \brief Constructor. Sets the upwind weight.
+     */
+    TwoPTwoCLocalResidual()
+    {
+        // retrieve the upwind weight for the mass conservation equations. Use the value
+        // specified via the property system as default, and overwrite
+        // it by the run-time parameter from the Dune::ParameterTree
+        massUpwindWeight_ = GET_PARAM_FROM_GROUP(TypeTag, Scalar, Implicit, MassUpwindWeight);
+    };
+
+    /*!
+     * \brief Evaluate the storage term of the current solution in a
+     *        single phase.
+     *
+     * \param element The element
+     * \param phaseIdx The index of the fluid phase
+     */
+    void evalPhaseStorage(const Element &element, const int phaseIdx)
+    {
+        FVElementGeometry fvGeometry;
+        fvGeometry.update(this->gridView_(), element);
+        ElementBoundaryTypes bcTypes;
+        bcTypes.update(this->problem_(), element, fvGeometry);
+        ElementVolumeVariables elemVolVars;
+        elemVolVars.update(this->problem_(), element, fvGeometry, false);
+
+        this->storageTerm_.resize(fvGeometry.numSCV);
+        this->storageTerm_ = 0;
+
+        this->elemPtr_ = &element;
+        this->fvElemGeomPtr_ = &fvGeometry;
+        this->bcTypesPtr_ = &bcTypes;
+        this->prevVolVarsPtr_ = 0;
+        this->curVolVarsPtr_ = &elemVolVars;
+        evalPhaseStorage_(phaseIdx);
+    }
+
+    /*!
+     * \brief Evaluate the amount all conservation quantities
+     *        (e.g. phase mass) within a sub-control volume.
+     *
+     * The result should be averaged over the volume (e.g. phase mass
+     * inside a sub-control volume divided by the volume)
+     *
+     *  \param storage The mass of the component within the sub-control volume
+     *  \param scvIdx The SCV (sub-control-volume) index
+     *  \param usePrevSol Evaluate function with solution of current or previous time step
+     */
+    void computeStorage(PrimaryVariables &storage, const int scvIdx, bool usePrevSol) const
+    {
+        // if flag usePrevSol is set, the solution from the previous
+        // time step is used, otherwise the current solution is
+        // used. The secondary variables are used accordingly.  This
+        // is required to compute the derivative of the storage term
+        // using the implicit euler method.
+        const ElementVolumeVariables &elemVolVars = usePrevSol ? this->prevVolVars_()
+            : this->curVolVars_();
+        const VolumeVariables &volVars = elemVolVars[scvIdx];
+
+        // compute storage term of all components within all phases
+        storage = 0;
+
+        for (unsigned int phaseIdx = 0; phaseIdx < numPhases; ++phaseIdx)
+        {
+            for (unsigned int compIdx = contiCompIdx1_(); compIdx <= contiCompIdx2_(); ++compIdx)
+            {
+                unsigned int eqIdx = (compIdx == wCompIdx) ? contiWEqIdx : contiNEqIdx;
+                storage[eqIdx] += volVars.density(phaseIdx)
+                    * volVars.saturation(phaseIdx)
+                    * volVars.fluidState().massFraction(phaseIdx, compIdx);
+            }
+            // this is only processed, if one component mass balance equation
+            // is replaced by the total mass balance equation
+            if (replaceCompEqIdx < numComponents)
+                storage[replaceCompEqIdx] +=
+                    volVars.density(phaseIdx)
+                    * volVars.saturation(phaseIdx);
+        }
+        storage *= volVars.porosity();
+    }
+
+    /*!
+     * \brief Evaluates the total flux of all conservation quantities
+     *        over a face of a sub-control volume.
+     *
+     * \param flux The flux over the SCV (sub-control-volume) face for each component
+     * \param faceIdx The index of the SCV face
+     * \param onBoundary Evaluate flux at inner SCV face or on a boundary face
+     */
+    void computeFlux(PrimaryVariables &flux, const int faceIdx, bool onBoundary=false) const
+    {
+        FluxVariables fluxVars(this->problem_(),
+                               this->element_(),
+                               this->fvGeometry_(),
+                               faceIdx,
+                               this->curVolVars_(),
+                               onBoundary);
+
+        flux = 0;
+        asImp_()->computeAdvectiveFlux(flux, fluxVars);
+        Valgrind::CheckDefined(flux);
+        asImp_()->computeDiffusiveFlux(flux, fluxVars);
+        Valgrind::CheckDefined(flux);
+    }
+
+    /*!
+     * \brief Evaluates the advective mass flux of all components over
+     *        a face of a sub-control volume.
+     *
+     * \param flux The advective flux over the sub-control-volume face for each component
+     * \param fluxVars The flux variables at the current SCV face
+     */
+    void computeAdvectiveFlux(PrimaryVariables &flux, const FluxVariables &fluxVars) const
+    {
+        ////////
+        // advective fluxes of all components in all phases
+        ////////
+        for (unsigned int phaseIdx = 0; phaseIdx < numPhases; ++phaseIdx)
+        {
+            // data attached to upstream and the downstream vertices
+            // of the current phase
+            const VolumeVariables &up =
+                this->curVolVars_(fluxVars.upstreamIdx(phaseIdx));
+            const VolumeVariables &dn =
+                this->curVolVars_(fluxVars.downstreamIdx(phaseIdx));
+
+            for (unsigned int compIdx = contiCompIdx1_(); compIdx <= contiCompIdx2_(); ++compIdx)
+            {
+                unsigned int eqIdx = (compIdx == wCompIdx) ? contiWEqIdx : contiNEqIdx;
+                // add advective flux of current component in current
+                // phase
+                if (massUpwindWeight_ > 0.0)
+                    // upstream vertex
+                    flux[eqIdx] +=
+                        fluxVars.volumeFlux(phaseIdx)
+                        * massUpwindWeight_
+                        * up.density(phaseIdx)
+                        * up.fluidState().massFraction(phaseIdx, compIdx);
+                if (massUpwindWeight_ < 1.0)
+                    // downstream vertex
+                    flux[eqIdx] +=
+                        fluxVars.volumeFlux(phaseIdx)
+                        * (1 - massUpwindWeight_)
+                        * dn.density(phaseIdx)
+                        * dn.fluidState().massFraction(phaseIdx, compIdx);
+
+                Valgrind::CheckDefined(fluxVars.volumeFlux(phaseIdx));
+                Valgrind::CheckDefined(up.density(phaseIdx));
+                Valgrind::CheckDefined(up.fluidState().massFraction(phaseIdx, compIdx));
+                Valgrind::CheckDefined(dn.density(phaseIdx));
+                Valgrind::CheckDefined(dn.fluidState().massFraction(phaseIdx, compIdx));
+            }
+            // flux of the total mass balance;
+            // this is only processed, if one component mass balance equation
+            // is replaced by a total mass balance equation
+            if (replaceCompEqIdx < numComponents)
+            {
+                // upstream vertex
+                if (massUpwindWeight_ > 0.0)
+                    flux[replaceCompEqIdx] +=
+                        fluxVars.volumeFlux(phaseIdx)
+                        * massUpwindWeight_
+                        * up.density(phaseIdx);
+                // downstream vertex
+                if (massUpwindWeight_ < 1.0)
+                    flux[replaceCompEqIdx] +=
+                        fluxVars.volumeFlux(phaseIdx)
+                        * (1 - massUpwindWeight_)
+                        * dn.density(phaseIdx);
+                Valgrind::CheckDefined(fluxVars.volumeFlux(phaseIdx));
+                Valgrind::CheckDefined(up.density(phaseIdx));
+                Valgrind::CheckDefined(dn.density(phaseIdx));
+
+            }
+
+        }
+    }
+
+    /*!
+     * \brief Adds the diffusive mass flux of all components over
+     *        a face of a sub-control volume.
+     *
+     * \param flux The diffusive flux over the sub-control-volume face for each component
+     * \param fluxVars The flux variables at the current sub control volume face
+     */
+    void computeDiffusiveFlux(PrimaryVariables &flux, const FluxVariables &fluxVars) const
+    {
+        // add diffusive flux of gas component in liquid phase
+        Scalar tmp = fluxVars.moleFractionGrad(wPhaseIdx)*fluxVars.face().normal;
+        tmp *= -1;
+        tmp *=
+            fluxVars.porousDiffCoeff(wPhaseIdx) *
+            fluxVars.molarDensity(wPhaseIdx);
+        // add the diffusive fluxes only to the component mass balance
+        if (replaceCompEqIdx != contiNEqIdx)
+            flux[contiNEqIdx] += tmp * FluidSystem::molarMass(nCompIdx);
+        if (replaceCompEqIdx != contiWEqIdx)
+            flux[contiWEqIdx] -= tmp * FluidSystem::molarMass(wCompIdx);
+
+        // add diffusive flux of liquid component in non-wetting phase
+        tmp = fluxVars.moleFractionGrad(nPhaseIdx)*fluxVars.face().normal;
+        tmp *= -1;
+        tmp *=
+            fluxVars.porousDiffCoeff(nPhaseIdx) *
+            fluxVars.molarDensity(nPhaseIdx);
+        // add the diffusive fluxes only to the component mass balance
+        if (replaceCompEqIdx != contiWEqIdx)
+            flux[contiWEqIdx] += tmp * FluidSystem::molarMass(wCompIdx);
+        if (replaceCompEqIdx != contiNEqIdx)
+            flux[contiNEqIdx] -= tmp * FluidSystem::molarMass(nCompIdx);
+    }
+
+    /*!
+     * \brief Calculate the source term of the equation
+     *
+     * \param source The source/sink in the sub-control volume for each component
+     * \param scvIdx The index of the sub-control volume
+     */
+    void computeSource(PrimaryVariables& source, const int scvIdx)
+    {
+        this->problem_().boxSDSource(source,
+                                     this->element_(),
+                                     this->fvGeometry_(),
+                                     scvIdx,
+                                     this->curVolVars_());
+    }
+
+ protected:
+    void evalPhaseStorage_(const int phaseIdx)
+    {
+        // evaluate the storage terms of a single phase
+        for (int i=0; i < this->fvGeometry_().numSCV; i++) {
+            PrimaryVariables &storage = this->storageTerm_[i];
+            const ElementVolumeVariables &elemVolVars = this->curVolVars_();
+            const VolumeVariables &volVars = elemVolVars[i];
+
+            // compute storage term of all components within all phases
+            storage = 0;
+            for (int compIdx = 0; compIdx < numComponents; ++compIdx)
+            {
+                int eqIdx = (compIdx == wCompIdx) ? contiWEqIdx : contiNEqIdx;
+                storage[eqIdx] += volVars.density(phaseIdx)
+                    * volVars.saturation(phaseIdx)
+                    * volVars.fluidState().massFraction(phaseIdx, compIdx);
+            }
+
+            storage *= volVars.porosity();
+            storage *= this->fvGeometry_().subContVol[i].volume;
+        }
+    }
+
+    /*!
+     * \brief Return the equation index of the first mass-balance equation
+     *        of the component (used for loops); if one component mass balance
+     *        is replaced by the total mass balance, this is the index
+     *        of the remaining component mass-balance equation.
+     */
+    unsigned int contiCompIdx1_() const {
+        switch (replaceCompEqIdx)
+        {
+        case contiWEqIdx: return contiNEqIdx;
+        case contiNEqIdx: return contiWEqIdx;
+        default:          return 0;
+        }
+    }
+
+    /*!
+     * \brief Return the equation index of the second mass balance
+     *        of the component (used for loops);
+     *        if one component mass balance is replaced by the total mass balance
+     *        (replaceCompEqIdx < 2), this index is the same as contiCompIdx1().
+     */
+    unsigned int contiCompIdx2_() const {
+        switch (replaceCompEqIdx)
+        {
+        case contiWEqIdx: return contiNEqIdx;
+        case contiNEqIdx: return contiWEqIdx;
+        default:          return numComponents-1;
+        }
+    }
+
+    Implementation *asImp_()
+    { return static_cast<Implementation *> (this); }
+    const Implementation *asImp_() const
+    { return static_cast<const Implementation *> (this); }
+
+ private:
+    Scalar massUpwindWeight_;
+};
+
+} // end namespace
+
+#endif
diff --git a/dumux/implicit/2p2c/2p2cmodel.hh b/dumux/implicit/2p2c/2p2cmodel.hh
new file mode 100644
index 0000000000..b3b395a54d
--- /dev/null
+++ b/dumux/implicit/2p2c/2p2cmodel.hh
@@ -0,0 +1,825 @@
+// -*- mode: C++; tab-width: 4; indent-tabs-mode: nil; c-basic-offset: 4 -*-
+// vi: set et ts=4 sw=4 sts=4:
+/*****************************************************************************
+ *   See the file COPYING for full copying permissions.                      *
+ *                                                                           *
+ *   This program is free software: you can redistribute it and/or modify    *
+ *   it under the terms of the GNU General Public License as published by    *
+ *   the Free Software Foundation, either version 2 of the License, or       *
+ *   (at your option) any later version.                                     *
+ *                                                                           *
+ *   This program is distributed in the hope that it will be useful,         *
+ *   but WITHOUT ANY WARRANTY; without even the implied warranty of          *
+ *   MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the            *
+ *   GNU General Public License for more details.                            *
+ *                                                                           *
+ *   You should have received a copy of the GNU General Public License       *
+ *   along with this program.  If not, see <http://www.gnu.org/licenses/>.   *
+ *****************************************************************************/
+/*!
+ * \file
+ *
+ * \brief Adaption of the BOX scheme to the two-phase two-component flow model.
+ */
+#ifndef DUMUX_2P2C_MODEL_HH
+#define DUMUX_2P2C_MODEL_HH
+
+#include "2p2cproperties.hh"
+#include "2p2clocalresidual.hh"
+
+namespace Dumux
+{
+/*!
+ * \ingroup TwoPTwoCModel
+ * \brief Adaption of the BOX scheme to the two-phase two-component flow model.
+ *
+ * This model implements two-phase two-component flow of two compressible and
+ * partially miscible fluids \f$\alpha \in \{ w, n \}\f$ composed of the two components
+ * \f$\kappa \in \{ w, a \}\f$. The standard multiphase Darcy
+ * approach is used as the equation for the conservation of momentum:
+ * \f[
+ v_\alpha = - \frac{k_{r\alpha}}{\mu_\alpha} \mbox{\bf K}
+ \left(\text{grad}\, p_\alpha - \varrho_{\alpha} \mbox{\bf g} \right)
+ * \f]
+ *
+ * By inserting this into the equations for the conservation of the
+ * components, one gets one transport equation for each component
+ * \f{eqnarray*}
+ && \phi \frac{\partial (\sum_\alpha \varrho_\alpha X_\alpha^\kappa S_\alpha )}
+ {\partial t}
+ - \sum_\alpha  \text{div} \left\{ \varrho_\alpha X_\alpha^\kappa
+ \frac{k_{r\alpha}}{\mu_\alpha} \mbox{\bf K}
+ (\text{grad}\, p_\alpha - \varrho_{\alpha}  \mbox{\bf g}) \right\}
+ \nonumber \\ \nonumber \\
+ &-& \sum_\alpha \text{div} \left\{{\bf D}_{\alpha, pm}^\kappa \varrho_{\alpha} \text{grad}\, X^\kappa_{\alpha} \right\}
+ - \sum_\alpha q_\alpha^\kappa = 0 \qquad \kappa \in \{w, a\} \, ,
+ \alpha \in \{w, g\}
+ \f}
+ *
+ * This is discretized using a fully-coupled vertex
+ * centered finite volume (box) scheme as spatial and
+ * the implicit Euler method as temporal discretization.
+ *
+ * By using constitutive relations for the capillary pressure \f$p_c =
+ * p_n - p_w\f$ and relative permeability \f$k_{r\alpha}\f$ and taking
+ * advantage of the fact that \f$S_w + S_n = 1\f$ and \f$X^\kappa_w + X^\kappa_n = 1\f$, the number of
+ * unknowns can be reduced to two.
+ * The used primary variables are, like in the two-phase model, either \f$p_w\f$ and \f$S_n\f$
+ * or \f$p_n\f$ and \f$S_w\f$. The formulation which ought to be used can be
+ * specified by setting the <tt>Formulation</tt> property to either
+ * TwoPTwoCIndices::pWsN or TwoPTwoCIndices::pNsW. By
+ * default, the model uses \f$p_w\f$ and \f$S_n\f$.
+ * Moreover, the second primary variable depends on the phase state, since a
+ * primary variable switch is included. The phase state is stored for all nodes
+ * of the system. Following cases can be distinguished:
+ * <ul>
+ *  <li> Both phases are present: The saturation is used (either \f$S_n\f$ or \f$S_w\f$, dependent on the chosen <tt>Formulation</tt>),
+ *      as long as \f$ 0 < S_\alpha < 1\f$</li>.
+ *  <li> Only wetting phase is present: The mass fraction of, e.g., air in the wetting phase \f$X^a_w\f$ is used,
+ *      as long as the maximum mass fraction is not exceeded \f$(X^a_w<X^a_{w,max})\f$</li>
+ *  <li> Only non-wetting phase is present: The mass fraction of, e.g., water in the non-wetting phase, \f$X^w_n\f$, is used,
+ *      as long as the maximum mass fraction is not exceeded \f$(X^w_n<X^w_{n,max})\f$</li>
+ * </ul>
+ */
+
+template<class TypeTag>
+class TwoPTwoCModel: public GET_PROP_TYPE(TypeTag, BaseModel)
+{
+    typedef typename GET_PROP_TYPE(TypeTag, BaseModel) ParentType;
+
+    typedef typename GET_PROP_TYPE(TypeTag, Problem) Problem;
+    typedef typename GET_PROP_TYPE(TypeTag, FluidSystem) FluidSystem;
+    typedef typename GET_PROP_TYPE(TypeTag, FVElementGeometry) FVElementGeometry;
+    typedef typename GET_PROP_TYPE(TypeTag, PrimaryVariables) PrimaryVariables;
+    typedef typename GET_PROP_TYPE(TypeTag, VolumeVariables) VolumeVariables;
+    typedef typename GET_PROP_TYPE(TypeTag, ElementVolumeVariables) ElementVolumeVariables;
+    typedef typename GET_PROP_TYPE(TypeTag, FluxVariables) FluxVariables;
+    typedef typename GET_PROP_TYPE(TypeTag, SolutionVector) SolutionVector;
+    enum {
+        numPhases = GET_PROP_VALUE(TypeTag, NumPhases),
+        numComponents = GET_PROP_VALUE(TypeTag, NumComponents)
+    };
+
+    typedef typename GET_PROP_TYPE(TypeTag, Indices) Indices;
+    enum {
+        pressureIdx = Indices::pressureIdx,
+        switchIdx = Indices::switchIdx,
+
+        wPhaseIdx = Indices::wPhaseIdx,
+        nPhaseIdx = Indices::nPhaseIdx,
+        wCompIdx = Indices::wCompIdx,
+        nCompIdx = Indices::nCompIdx,
+
+        wPhaseOnly = Indices::wPhaseOnly,
+        nPhaseOnly = Indices::nPhaseOnly,
+        bothPhases = Indices::bothPhases,
+
+        pwSn = TwoPTwoCFormulation::pwSn,
+        pnSw = TwoPTwoCFormulation::pnSw,
+        formulation = GET_PROP_VALUE(TypeTag, Formulation)
+    };
+
+    typedef typename GET_PROP_TYPE(TypeTag, GridView) GridView;
+    typedef typename GridView::ctype CoordScalar;
+    typedef typename GridView::template Codim<0>::Entity Element;
+    typedef typename GridView::template Codim<0>::Iterator ElementIterator;
+    enum {
+        dim = GridView::dimension,
+        dimWorld = GridView::dimensionworld
+    };
+    typedef typename GridView::template Codim<dim>::Entity Vertex;
+    typedef typename GridView::template Codim<dim>::Iterator VertexIterator;
+
+    typedef typename GET_PROP_TYPE(TypeTag, Scalar) Scalar;
+    typedef Dune::FieldVector<Scalar, numPhases> PhasesVector;
+    typedef Dune::FieldVector<Scalar, dimWorld> GlobalPosition;
+
+public:
+    /*!
+     * \brief Initialize the static data with the initial solution.
+     *
+     * \param problem The problem to be solved
+     */
+    void init(Problem &problem)
+    {
+        ParentType::init(problem);
+
+        unsigned numDofs = this->numDofs();
+        unsigned numVertices = this->problem_().gridView().size(dim);
+
+        staticVertexDat_.resize(numDofs);
+
+        setSwitched_(false);
+
+        // check, if velocity output can be used (works only for cubes so far)
+        velocityOutput_ = GET_PARAM_FROM_GROUP(TypeTag, bool, Vtk, AddVelocity);
+        ElementIterator eIt = this->gridView_().template begin<0>();
+        ElementIterator eEndIt = this->gridView_().template end<0>();
+        for (; eIt != eEndIt; ++eIt)
+        {
+            if(eIt->geometry().type().isCube() == false){
+                velocityOutput_ = false;
+            }
+
+            if (numDofs != numVertices) // i.e. cell-centered discretization
+            {
+                velocityOutput_ = false;
+
+                int globalIdx = this->dofMapper().map(*eIt);
+                const GlobalPosition &globalPos = eIt->geometry().center();
+
+                // initialize phase presence
+                staticVertexDat_[globalIdx].phasePresence
+                    = this->problem_().initialPhasePresence(*(this->gridView_().template begin<dim>()),
+                                                            globalIdx, globalPos);
+                staticVertexDat_[globalIdx].wasSwitched = false;
+
+                staticVertexDat_[globalIdx].oldPhasePresence
+                    = staticVertexDat_[globalIdx].phasePresence;
+            }
+        }
+
+        if (velocityOutput_ != GET_PARAM_FROM_GROUP(TypeTag, bool, Vtk, AddVelocity))
+            std::cout << "ATTENTION: Velocity output only works for cubes and is set to false for simplices\n";
+
+        if (numDofs == numVertices) // i.e. vertex-centered discretization
+        {
+            VertexIterator vIt = this->gridView_().template begin<dim> ();
+            const VertexIterator &vEndIt = this->gridView_().template end<dim> ();
+            for (; vIt != vEndIt; ++vIt)
+            {
+                int globalIdx = this->dofMapper().map(*vIt);
+                const GlobalPosition &globalPos = vIt->geometry().corner(0);
+
+                // initialize phase presence
+                staticVertexDat_[globalIdx].phasePresence
+                    = this->problem_().initialPhasePresence(*vIt, globalIdx,
+                                                        globalPos);
+                staticVertexDat_[globalIdx].wasSwitched = false;
+
+                staticVertexDat_[globalIdx].oldPhasePresence
+                    = staticVertexDat_[globalIdx].phasePresence;
+            }
+        }
+    }
+
+    /*!
+     * \brief Compute the total storage inside one phase of all
+     *        conservation quantities.
+     *
+     * \param storage Contains the storage of each component for one phase
+     * \param phaseIdx The phase index
+     */
+    void globalPhaseStorage(PrimaryVariables &storage, const int phaseIdx)
+    {
+        storage = 0;
+
+        ElementIterator eIt = this->gridView_().template begin<0>();
+        const ElementIterator eEndIt = this->gridView_().template end<0>();
+        for (; eIt != eEndIt; ++eIt) {
+            this->localResidual().evalPhaseStorage(*eIt, phaseIdx);
+
+            for (unsigned int i = 0; i < this->localResidual().storageTerm().size(); ++i)
+                storage += this->localResidual().storageTerm()[i];
+        }
+
+        if (this->gridView_().comm().size() > 1)
+            storage = this->gridView_().comm().sum(storage);
+    }
+
+    /*!
+     * \brief Called by the update() method if applying the newton
+     *         method was unsuccessful.
+     */
+    void updateFailed()
+    {
+        ParentType::updateFailed();
+
+        setSwitched_(false);
+        resetPhasePresence_();
+    };
+
+    /*!
+     * \brief Called by the problem if a time integration was
+     *        successful, post processing of the solution is done and the
+     *        result has been written to disk.
+     *
+     * This should prepare the model for the next time integration.
+     */
+    void advanceTimeLevel()
+    {
+        ParentType::advanceTimeLevel();
+
+        // update the phase state
+        updateOldPhasePresence_();
+        setSwitched_(false);
+    }
+
+    /*!
+     * \brief Return true if the primary variables were switched for
+     *        at least one vertex after the last timestep.
+     */
+    bool switched() const
+    {
+        return switchFlag_;
+    }
+
+    /*!
+     * \brief Returns the phase presence of the current or the old solution of a vertex.
+     *
+     * \param globalIdx The global vertex index
+     * \param oldSol Evaluate function with solution of current or previous time step
+     */
+    int phasePresence(int globalIdx, bool oldSol) const
+    {
+        return oldSol ? staticVertexDat_[globalIdx].oldPhasePresence
+            : staticVertexDat_[globalIdx].phasePresence;
+    }
+
+    /*!
+     * \brief Append all quantities of interest which can be derived
+     *        from the solution of the current time step to the VTK
+     *        writer.
+     *
+     * \param sol The solution vector
+     * \param writer The writer for multi-file VTK datasets
+     */
+    template<class MultiWriter>
+    void addOutputVtkFields(const SolutionVector &sol,
+                            MultiWriter &writer)
+    {
+        typedef Dune::BlockVector<Dune::FieldVector<double, 1> > ScalarField;
+        typedef Dune::BlockVector<Dune::FieldVector<double, dim> > VectorField;
+
+        // create the required scalar fields
+        unsigned numDofs = this->numDofs();
+        unsigned numVertices = this->problem_().gridView().size(dim);
+
+        // velocity output currently only works for vertex data
+        if (numDofs != numVertices)
+          velocityOutput_ = false;
+
+        ScalarField *sN    = writer.allocateManagedBuffer(numDofs);
+        ScalarField *sW    = writer.allocateManagedBuffer(numDofs);
+        ScalarField *pN    = writer.allocateManagedBuffer(numDofs);
+        ScalarField *pW    = writer.allocateManagedBuffer(numDofs);
+        ScalarField *pC    = writer.allocateManagedBuffer(numDofs);
+        ScalarField *rhoW  = writer.allocateManagedBuffer(numDofs);
+        ScalarField *rhoN  = writer.allocateManagedBuffer(numDofs);
+        ScalarField *mobW  = writer.allocateManagedBuffer(numDofs);
+        ScalarField *mobN = writer.allocateManagedBuffer(numDofs);
+        ScalarField *phasePresence = writer.allocateManagedBuffer(numDofs);
+        ScalarField *massFrac[numPhases][numComponents];
+        for (int phaseIdx = 0; phaseIdx < numPhases; ++phaseIdx)
+            for (int compIdx = 0; compIdx < numComponents; ++compIdx)
+                massFrac[phaseIdx][compIdx] = writer.allocateManagedBuffer(numDofs);
+        ScalarField *temperature = writer.allocateManagedBuffer(numDofs);
+        ScalarField *poro = writer.allocateManagedBuffer(numDofs);
+        ScalarField *cellNum =writer.allocateManagedBuffer (numDofs);
+        VectorField *velocityN = writer.template allocateManagedBuffer<double, dim>(numDofs);
+        VectorField *velocityW = writer.template allocateManagedBuffer<double, dim>(numDofs);
+
+        if(velocityOutput_) // check if velocity output is demanded
+        {
+            // initialize velocity fields
+            for (unsigned int i = 0; i < numDofs; ++i)
+            {
+                (*velocityN)[i] = Scalar(0);
+                (*velocityW)[i] = Scalar(0);
+                (*cellNum)[i] = Scalar(0.0);
+            }
+        }
+
+        unsigned numElements = this->gridView_().size(0);
+        ScalarField *rank = writer.allocateManagedBuffer(numElements);
+
+        FVElementGeometry fvGeometry;
+        VolumeVariables volVars;
+
+        ElementIterator eIt = this->gridView_().template begin<0>();
+        ElementIterator eEndIt = this->gridView_().template end<0>();
+        for (; eIt != eEndIt; ++eIt)
+        {
+            int idx = this->elementMapper().map(*eIt);
+            (*rank)[idx] = this->gridView_().comm().rank();
+            fvGeometry.update(this->gridView_(), *eIt);
+
+            for (int scvIdx = 0; scvIdx < fvGeometry.numSCV; ++scvIdx)
+            {
+                int globalIdx;
+                if (numDofs == numElements) // element data
+                    globalIdx = idx;
+                else
+                    globalIdx = this->vertexMapper().map(*eIt, scvIdx, dim);
+
+                volVars.update(sol[globalIdx],
+                               this->problem_(),
+                               *eIt,
+                               fvGeometry,
+                               scvIdx,
+                               false);
+                (*sN)[globalIdx]    = volVars.saturation(nPhaseIdx);
+                (*sW)[globalIdx]    = volVars.saturation(wPhaseIdx);
+                (*pN)[globalIdx]    = volVars.pressure(nPhaseIdx);
+                (*pW)[globalIdx]    = volVars.pressure(wPhaseIdx);
+                (*pC)[globalIdx]    = volVars.capillaryPressure();
+                (*rhoW)[globalIdx]  = volVars.fluidState().density(wPhaseIdx);
+                (*rhoN)[globalIdx]  = volVars.fluidState().density(nPhaseIdx);
+                (*mobW)[globalIdx]  = volVars.mobility(wPhaseIdx);
+                (*mobN)[globalIdx]  = volVars.mobility(nPhaseIdx);
+                for (int phaseIdx = 0; phaseIdx < numPhases; ++phaseIdx)
+                    for (int compIdx = 0; compIdx < numComponents; ++compIdx)
+                    {
+                        (*massFrac[phaseIdx][compIdx])[globalIdx]
+                            = volVars.fluidState().massFraction(phaseIdx, compIdx);
+
+                        Valgrind::CheckDefined((*massFrac[phaseIdx][compIdx])[globalIdx][0]);
+                    }
+                (*poro)[globalIdx]  = volVars.porosity();
+                (*temperature)[globalIdx] = volVars.temperature();
+                (*phasePresence)[globalIdx]
+                    = staticVertexDat_[globalIdx].phasePresence;
+                if(velocityOutput_)
+                {
+                    (*cellNum)[globalIdx] += 1;
+                }
+            }
+
+            if(velocityOutput_)
+            {
+                // calculate vertex velocities
+                GlobalPosition tmpVelocity[numPhases];
+
+                for(int phaseIdx = 0; phaseIdx < numPhases; ++phaseIdx)
+                {
+                    tmpVelocity[phaseIdx]  = Scalar(0.0);
+                }
+
+                typedef Dune::BlockVector<Dune::FieldVector<Scalar, dim> > SCVVelocities;
+                SCVVelocities scvVelocityW(8), scvVelocityN(8);
+
+                scvVelocityW = 0;
+                scvVelocityN = 0;
+
+                ElementVolumeVariables elemVolVars;
+
+                elemVolVars.update(this->problem_(),
+                                   *eIt,
+                                   fvGeometry,
+                                   false /* oldSol? */);
+
+                for (int faceIdx = 0; faceIdx < fvGeometry.numEdges; faceIdx++)
+                {
+
+                    FluxVariables fluxVars(this->problem_(),
+                                           *eIt,
+                                           fvGeometry,
+                                           faceIdx,
+                                           elemVolVars);
+
+                    for (int phaseIdx = 0; phaseIdx < numPhases; ++phaseIdx)
+                    {
+                        // local position of integration point
+                        const Dune::FieldVector<Scalar, dim>& localPosIP = fvGeometry.subContVolFace[faceIdx].ipLocal;
+
+                        // Transformation of the global normal vector to normal vector in the reference element
+                        const typename Element::Geometry::JacobianTransposed jacobianT1 = 
+                            eIt->geometry().jacobianTransposed(localPosIP);
+                        const GlobalPosition globalNormal = fluxVars.face().normal;
+
+                        GlobalPosition localNormal(0);
+                        jacobianT1.mv(globalNormal, localNormal);
+                        // note only works for cubes
+                        const Scalar localArea = pow(2,-(dim-1));
+
+                        localNormal /= localNormal.two_norm();
+
+                        // Get the Darcy velocities. The Darcy velocities are divided by the area of the subcontrolvolume
+                        // face in the reference element.
+                        PhasesVector flux;
+                        flux[phaseIdx] = fluxVars.volumeFlux(phaseIdx) / localArea;
+
+                        // transform the normal Darcy velocity into a vector
+                        tmpVelocity[phaseIdx] = localNormal;
+                        tmpVelocity[phaseIdx] *= flux[phaseIdx];
+
+                        if(phaseIdx == wPhaseIdx){
+                            scvVelocityW[fluxVars.face().i] += tmpVelocity[phaseIdx];
+                            scvVelocityW[fluxVars.face().j] += tmpVelocity[phaseIdx];
+                        }
+                        else if(phaseIdx == nPhaseIdx){
+                            scvVelocityN[fluxVars.face().i] += tmpVelocity[phaseIdx];
+                            scvVelocityN[fluxVars.face().j] += tmpVelocity[phaseIdx];
+                        }
+                    }
+                }
+
+                typedef Dune::GenericReferenceElements<Scalar, dim> ReferenceElements;
+                const Dune::FieldVector<Scalar, dim>& localPos =
+                    ReferenceElements::general(eIt->geometry().type()).position(0, 0);
+
+                // get the transposed Jacobian of the element mapping
+                const typename Element::Geometry::JacobianTransposed jacobianT2 = 
+                    eIt->geometry().jacobianTransposed(localPos);
+
+                // transform vertex velocities from local to global coordinates
+                for (int scvIdx = 0; scvIdx < fvGeometry.numSCV; ++scvIdx)
+                {
+                    int globalIdx = this->vertexMapper().map(*eIt, scvIdx, dim);
+                    // calculate the subcontrolvolume velocity by the Piola transformation
+                    Dune::FieldVector<CoordScalar, dim> scvVelocity(0);
+
+                    jacobianT2.mtv(scvVelocityW[scvIdx], scvVelocity);
+                    scvVelocity /= eIt->geometry().integrationElement(localPos);
+                    // add up the wetting phase subcontrolvolume velocities for each vertex
+                    (*velocityW)[globalIdx] += scvVelocity;
+
+                    jacobianT2.mtv(scvVelocityN[scvIdx], scvVelocity);
+                    scvVelocity /= eIt->geometry().integrationElement(localPos);
+                    // add up the nonwetting phase subcontrolvolume velocities for each vertex
+                    (*velocityN)[globalIdx] += scvVelocity;
+                }
+            } // velocity output
+        } // loop over elements
+
+        if(velocityOutput_)
+        {
+            // divide the vertex velocities by the number of adjacent scvs i.e. cells
+            for(unsigned int globalIdx = 0; globalIdx < numDofs; ++globalIdx){
+                (*velocityW)[globalIdx] /= (*cellNum)[globalIdx];
+                (*velocityN)[globalIdx] /= (*cellNum)[globalIdx];
+            }
+        }
+
+        if (numDofs == numElements) // element data
+        {
+            writer.attachCellData(*sN,     "Sn");
+            writer.attachCellData(*sW,     "Sw");
+            writer.attachCellData(*pN,     "pN");
+            writer.attachCellData(*pW,     "pW");
+            writer.attachCellData(*pC,     "pC");
+            writer.attachCellData(*rhoW,   "rhoW");
+            writer.attachCellData(*rhoN,   "rhoN");
+            writer.attachCellData(*mobW,   "mobW");
+            writer.attachCellData(*mobN,   "mobN");
+            for (int phaseIdx = 0; phaseIdx < numPhases; ++phaseIdx)
+            {
+                for (int compIdx = 0; compIdx < numComponents; ++compIdx)
+                {
+                    std::ostringstream oss;
+                    oss << "X_" << FluidSystem::phaseName(phaseIdx) << "^" << FluidSystem::componentName(compIdx);
+                    writer.attachCellData(*massFrac[phaseIdx][compIdx], oss.str());
+                }
+            }
+            writer.attachCellData(*poro, "porosity");
+            writer.attachCellData(*temperature,    "temperature");
+            writer.attachCellData(*phasePresence,  "phase presence");
+        }
+        else
+        {
+            writer.attachVertexData(*sN,     "Sn");
+            writer.attachVertexData(*sW,     "Sw");
+            writer.attachVertexData(*pN,     "pN");
+            writer.attachVertexData(*pW,     "pW");
+            writer.attachVertexData(*pC,     "pC");
+            writer.attachVertexData(*rhoW,   "rhoW");
+            writer.attachVertexData(*rhoN,   "rhoN");
+            writer.attachVertexData(*mobW,   "mobW");
+            writer.attachVertexData(*mobN,   "mobN");
+            for (int phaseIdx = 0; phaseIdx < numPhases; ++phaseIdx)
+            {
+                for (int compIdx = 0; compIdx < numComponents; ++compIdx)
+                {
+                    std::ostringstream oss;
+                    oss << "X_" << FluidSystem::phaseName(phaseIdx) << "^" << FluidSystem::componentName(compIdx);
+                    writer.attachVertexData(*massFrac[phaseIdx][compIdx], oss.str());
+                }
+            }
+            writer.attachVertexData(*poro, "porosity");
+            writer.attachVertexData(*temperature,    "temperature");
+            writer.attachVertexData(*phasePresence,  "phase presence");
+
+            if(velocityOutput_) // check if velocity output is demanded
+            {
+                writer.attachVertexData(*velocityW,  "velocityW", dim);
+                writer.attachVertexData(*velocityN,  "velocityN", dim);
+            }
+        }
+
+        writer.attachCellData(*rank, "process rank");
+    }
+
+    /*!
+     * \brief Write the current solution to a restart file.
+     *
+     * \param outStream The output stream of one vertex for the restart file
+     * \param entity The entity, either a vertex or an element
+     */
+    template<class Entity>
+    void serializeEntity(std::ostream &outStream, const Entity &entity)
+    {
+        // write primary variables
+        ParentType::serializeEntity(outStream, entity);
+
+        int globalIdx = this->dofMapper().map(entity);
+        if (!outStream.good())
+            DUNE_THROW(Dune::IOError, "Could not serialize entity " << globalIdx);
+
+        outStream << staticVertexDat_[globalIdx].phasePresence << " ";
+    }
+
+    /*!
+     * \brief Reads the current solution from a restart file.
+     *
+     * \param inStream The input stream of one vertex from the restart file
+     * \param entity The entity, either a vertex or an element
+     */
+    template<class Entity>
+    void deserializeEntity(std::istream &inStream, const Entity &entity)
+    {
+        // read primary variables
+        ParentType::deserializeEntity(inStream, entity);
+
+        // read phase presence
+        int globalIdx = this->dofMapper().map(entity);
+        if (!inStream.good())
+            DUNE_THROW(Dune::IOError,
+                       "Could not deserialize entity " << globalIdx);
+
+        inStream >> staticVertexDat_[globalIdx].phasePresence;
+        staticVertexDat_[globalIdx].oldPhasePresence
+            = staticVertexDat_[globalIdx].phasePresence;
+
+    }
+
+    /*!
+     * \brief Update the static data of all vertices in the grid.
+     *
+     * \param curGlobalSol The current global solution
+     * \param oldGlobalSol The previous global solution
+     */
+    void updateStaticData(SolutionVector &curGlobalSol,
+                          const SolutionVector &oldGlobalSol)
+    {
+        bool wasSwitched = false;
+
+        for (unsigned i = 0; i < staticVertexDat_.size(); ++i)
+            staticVertexDat_[i].visited = false;
+
+        unsigned numDofs = this->numDofs();
+        unsigned numVertices = this->problem_().gridView().size(dim);
+
+        FVElementGeometry fvGeometry;
+        static VolumeVariables volVars;
+        ElementIterator eIt = this->gridView_().template begin<0> ();
+        const ElementIterator &eEndIt = this->gridView_().template end<0> ();
+        for (; eIt != eEndIt; ++eIt)
+        {
+            fvGeometry.update(this->gridView_(), *eIt);
+            for (int scvIdx = 0; scvIdx < fvGeometry.numSCV; ++scvIdx)
+            {
+                int globalIdx;
+
+                if (numDofs != numVertices)
+                    globalIdx = this->elementMapper().map(*eIt);
+                else
+                    globalIdx = this->vertexMapper().map(*eIt, scvIdx, dim);
+
+                if (staticVertexDat_[globalIdx].visited)
+                    continue;
+
+                staticVertexDat_[globalIdx].visited = true;
+                volVars.update(curGlobalSol[globalIdx],
+                               this->problem_(),
+                               *eIt,
+                               fvGeometry,
+                               scvIdx,
+                               false);
+                const GlobalPosition &globalPos = eIt->geometry().corner(scvIdx);
+                if (primaryVarSwitch_(curGlobalSol,
+                                      volVars,
+                                      globalIdx,
+                                      globalPos))
+                {
+                    this->jacobianAssembler().markVertexRed(globalIdx);
+                    wasSwitched = true;
+                }
+            }
+        }
+
+        // make sure that if there was a variable switch in an
+        // other partition we will also set the switch flag
+        // for our partition.
+        if (this->gridView_().comm().size() > 1)
+            wasSwitched = this->gridView_().comm().max(wasSwitched);
+
+        setSwitched_(wasSwitched);
+    }
+
+protected:
+    /*!
+     * \brief Data which is attached to each vertex and is not only
+     *        stored locally.
+     */
+    struct StaticVars
+    {
+        int phasePresence;
+        bool wasSwitched;
+
+        int oldPhasePresence;
+        bool visited;
+    };
+
+    /*!
+     * \brief Reset the current phase presence of all vertices to the old one.
+     *
+     * This is done after an update failed.
+     */
+    void resetPhasePresence_()
+    {
+        for (unsigned int idx = 0; idx < staticVertexDat_.size(); ++idx)
+        {
+            staticVertexDat_[idx].phasePresence
+                = staticVertexDat_[idx].oldPhasePresence;
+            staticVertexDat_[idx].wasSwitched = false;
+        }
+    }
+
+    /*!
+     * \brief Set the old phase of all verts state to the current one.
+     */
+    void updateOldPhasePresence_()
+    {
+        for (unsigned int idx = 0; idx < staticVertexDat_.size(); ++idx)
+        {
+            staticVertexDat_[idx].oldPhasePresence
+                = staticVertexDat_[idx].phasePresence;
+            staticVertexDat_[idx].wasSwitched = false;
+        }
+    }
+
+    /*!
+     * \brief Set whether there was a primary variable switch after in
+     *        the last timestep.
+     */
+    void setSwitched_(bool yesno)
+    {
+        switchFlag_ = yesno;
+    }
+
+    //  perform variable switch at a vertex; Returns true if a
+    //  variable switch was performed.
+    bool primaryVarSwitch_(SolutionVector &globalSol,
+                           const VolumeVariables &volVars, int globalIdx,
+                           const GlobalPosition &globalPos)
+    {
+        // evaluate primary variable switch
+        bool wouldSwitch = false;
+        int phasePresence = staticVertexDat_[globalIdx].phasePresence;
+        int newPhasePresence = phasePresence;
+
+        // check if a primary var switch is necessary
+        if (phasePresence == nPhaseOnly)
+        {
+            // calculate mole fraction in the hypothetic wetting phase
+            Scalar xww = volVars.fluidState().moleFraction(wPhaseIdx, wCompIdx);
+            Scalar xwn = volVars.fluidState().moleFraction(wPhaseIdx, nCompIdx);
+
+            Scalar xwMax = 1.0;
+            if (xww + xwn > xwMax)
+                wouldSwitch = true;
+            if (staticVertexDat_[globalIdx].wasSwitched)
+                xwMax *= 1.02;
+
+            // if the sum of the mole fractions would be larger than
+            // 100%, wetting phase appears
+            if (xww + xwn > xwMax)
+            {
+                // wetting phase appears
+                std::cout << "wetting phase appears at vertex " << globalIdx
+                          << ", coordinates: " << globalPos << ", xww + xwn: "
+                          << xww + xwn << std::endl;
+                newPhasePresence = bothPhases;
+                if (formulation == pnSw)
+                    globalSol[globalIdx][switchIdx] = 0.0;
+                else if (formulation == pwSn)
+                    globalSol[globalIdx][switchIdx] = 1.0;
+            }
+        }
+        else if (phasePresence == wPhaseOnly)
+        {
+            // calculate fractions of the partial pressures in the
+            // hypothetic nonwetting phase
+            Scalar xnw = volVars.fluidState().moleFraction(nPhaseIdx, wCompIdx);
+            Scalar xnn = volVars.fluidState().moleFraction(nPhaseIdx, nCompIdx);
+
+            Scalar xgMax = 1.0;
+            if (xnw + xnn > xgMax)
+                wouldSwitch = true;
+            if (staticVertexDat_[globalIdx].wasSwitched)
+                xgMax *= 1.02;
+
+            // if the sum of the mole fractions would be larger than
+            // 100%, nonwetting phase appears
+            if (xnw + xnn > xgMax)
+            {
+                // nonwetting phase appears
+                std::cout << "nonwetting phase appears at vertex " << globalIdx
+                          << ", coordinates: " << globalPos << ", xnw + xnn: "
+                          << xnw + xnn << std::endl;
+                newPhasePresence = bothPhases;
+                if (formulation == pnSw)
+                    globalSol[globalIdx][switchIdx] = 0.999;
+                else if (formulation == pwSn)
+                    globalSol[globalIdx][switchIdx] = 0.001;
+            }
+        }
+        else if (phasePresence == bothPhases)
+        {
+            Scalar Smin = 0.0;
+            if (staticVertexDat_[globalIdx].wasSwitched)
+                Smin = -0.01;
+
+            if (volVars.saturation(nPhaseIdx) <= Smin)
+            {
+                wouldSwitch = true;
+                // nonwetting phase disappears
+                std::cout << "Nonwetting phase disappears at vertex " << globalIdx
+                          << ", coordinates: " << globalPos << ", Sn: "
+                          << volVars.saturation(nPhaseIdx) << std::endl;
+                newPhasePresence = wPhaseOnly;
+
+                globalSol[globalIdx][switchIdx]
+                    = volVars.fluidState().massFraction(wPhaseIdx, nCompIdx);
+            }
+            else if (volVars.saturation(wPhaseIdx) <= Smin)
+            {
+                wouldSwitch = true;
+                // wetting phase disappears
+                std::cout << "Wetting phase disappears at vertex " << globalIdx
+                          << ", coordinates: " << globalPos << ", Sw: "
+                          << volVars.saturation(wPhaseIdx) << std::endl;
+                newPhasePresence = nPhaseOnly;
+
+                globalSol[globalIdx][switchIdx]
+                    = volVars.fluidState().massFraction(nPhaseIdx, wCompIdx);
+            }
+        }
+
+        staticVertexDat_[globalIdx].phasePresence = newPhasePresence;
+        staticVertexDat_[globalIdx].wasSwitched = wouldSwitch;
+        return phasePresence != newPhasePresence;
+    }
+
+protected:
+    // parameters given in constructor
+    std::vector<StaticVars> staticVertexDat_;
+    bool switchFlag_;
+    bool velocityOutput_;
+};
+
+}
+
+#include "2p2cpropertydefaults.hh"
+
+#endif
diff --git a/dumux/implicit/2p2c/2p2cnewtoncontroller.hh b/dumux/implicit/2p2c/2p2cnewtoncontroller.hh
new file mode 100644
index 0000000000..374ccf5931
--- /dev/null
+++ b/dumux/implicit/2p2c/2p2cnewtoncontroller.hh
@@ -0,0 +1,110 @@
+// -*- mode: C++; tab-width: 4; indent-tabs-mode: nil; c-basic-offset: 4 -*-
+// vi: set et ts=4 sw=4 sts=4:
+/*****************************************************************************
+ *   See the file COPYING for full copying permissions.                      *
+ *                                                                           *
+ *   This program is free software: you can redistribute it and/or modify    *
+ *   it under the terms of the GNU General Public License as published by    *
+ *   the Free Software Foundation, either version 2 of the License, or       *
+ *   (at your option) any later version.                                     *
+ *                                                                           *
+ *   This program is distributed in the hope that it will be useful,         *
+ *   but WITHOUT ANY WARRANTY; without even the implied warranty of          *
+ *   MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the            *
+ *   GNU General Public License for more details.                            *
+ *                                                                           *
+ *   You should have received a copy of the GNU General Public License       *
+ *   along with this program.  If not, see <http://www.gnu.org/licenses/>.   *
+ *****************************************************************************/
+/*!
+ * \file
+ * \brief A 2p2c specific controller for the newton solver.
+ *
+ * This controller 'knows' what a 'physically meaningful' solution is
+ * which allows the newton method to abort quicker if the solution is
+ * way out of bounds.
+ */
+#ifndef DUMUX_2P2C_NEWTON_CONTROLLER_HH
+#define DUMUX_2P2C_NEWTON_CONTROLLER_HH
+
+#include "2p2cproperties.hh"
+
+#include <dumux/nonlinear/newtoncontroller.hh>
+
+namespace Dumux {
+
+/*!
+ * \ingroup Newton
+ * \ingroup TwoPTwoCModel
+ * \brief A 2p2c specific controller for the newton solver.
+ *
+ * This controller 'knows' what a 'physically meaningful' solution is
+ * which allows the newton method to abort quicker if the solution is
+ * way out of bounds.
+ */
+template <class TypeTag>
+class TwoPTwoCNewtonController : public NewtonController<TypeTag>
+{
+    typedef NewtonController<TypeTag> ParentType;
+    typedef typename GET_PROP_TYPE(TypeTag, Problem) Problem;
+    typedef typename GET_PROP_TYPE(TypeTag, SolutionVector) SolutionVector;
+
+public:
+    TwoPTwoCNewtonController(const Problem &problem)
+        : ParentType(problem)
+    {}
+
+    /*!
+     * \brief
+     * Suggest a new time step size based either on the number of newton
+     * iterations required or on the variable switch
+     *
+     * \param uCurrentIter The current global solution vector
+     * \param uLastIter The previous global solution vector
+     *
+     */
+    void newtonEndStep(SolutionVector &uCurrentIter,
+                       const SolutionVector &uLastIter)
+    {
+        int succeeded;
+        try {
+            // call the method of the base class
+            this->method().model().updateStaticData(uCurrentIter, uLastIter);
+            ParentType::newtonEndStep(uCurrentIter, uLastIter);
+
+            succeeded = 1;
+            if (this->gridView_().comm().size() > 1)
+                succeeded = this->gridView_().comm().min(succeeded);
+        }
+        catch (Dumux::NumericalProblem &e)
+        {
+            std::cout << "rank " << this->problem_().gridView().comm().rank()
+                      << " caught an exception while updating:" << e.what()
+                      << "\n";
+            succeeded = 0;
+            if (this->gridView_().comm().size() > 1)
+                succeeded = this->gridView_().comm().min(succeeded);
+        }
+
+        if (!succeeded) {
+            DUNE_THROW(NumericalProblem,
+                       "A process did not succeed in linearizing the system");
+        }
+    }
+
+    /*!
+     * \brief
+     * Returns true if the current solution can be considered to
+     * be accurate enough
+     */
+    bool newtonConverged()
+    {
+        if (this->method().model().switched())
+            return false;
+
+        return ParentType::newtonConverged();
+    }
+};
+}
+
+#endif
diff --git a/dumux/implicit/2p2c/2p2cproperties.hh b/dumux/implicit/2p2c/2p2cproperties.hh
new file mode 100644
index 0000000000..0303514205
--- /dev/null
+++ b/dumux/implicit/2p2c/2p2cproperties.hh
@@ -0,0 +1,70 @@
+// -*- mode: C++; tab-width: 4; indent-tabs-mode: nil; c-basic-offset: 4 -*-
+// vi: set et ts=4 sw=4 sts=4:
+/*****************************************************************************
+ *   See the file COPYING for full copying permissions.                      *
+ *                                                                           *
+ *   This program is free software: you can redistribute it and/or modify    *
+ *   it under the terms of the GNU General Public License as published by    *
+ *   the Free Software Foundation, either version 2 of the License, or       *
+ *   (at your option) any later version.                                     *
+ *                                                                           *
+ *   This program is distributed in the hope that it will be useful,         *
+ *   but WITHOUT ANY WARRANTY; without even the implied warranty of          *
+ *   MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the            *
+ *   GNU General Public License for more details.                            *
+ *                                                                           *
+ *   You should have received a copy of the GNU General Public License       *
+ *   along with this program.  If not, see <http://www.gnu.org/licenses/>.   *
+ *****************************************************************************/
+/*!
+ * \ingroup Properties
+ * \ingroup BoxProperties
+ * \ingroup TwoPTwoCModel
+ */
+/*!
+ * \file
+ *
+ * \brief Defines the properties required for the 2p2c BOX model.
+ */
+#ifndef DUMUX_2P2C_PROPERTIES_HH
+#define DUMUX_2P2C_PROPERTIES_HH
+
+#include <dumux/boxmodels/common/boxproperties.hh>
+
+namespace Dumux
+{
+
+namespace Properties
+{
+//////////////////////////////////////////////////////////////////
+// Type tags
+//////////////////////////////////////////////////////////////////
+
+//! The type tag for the isothermal single phase problems
+NEW_TYPE_TAG(BoxTwoPTwoC, INHERITS_FROM(BoxModel));
+
+//////////////////////////////////////////////////////////////////
+// Property tags
+//////////////////////////////////////////////////////////////////
+
+NEW_PROP_TAG(NumPhases);   //!< Number of fluid phases in the system
+NEW_PROP_TAG(NumComponents); //!< Number of fluid components in the system
+NEW_PROP_TAG(Indices); //!< Enumerations for the model
+NEW_PROP_TAG(Formulation);   //!< The formulation of the model
+NEW_PROP_TAG(SpatialParams); //!< The type of the spatial parameters
+NEW_PROP_TAG(FluidSystem); //!< Type of the multi-component relations
+
+NEW_PROP_TAG(MaterialLaw);   //!< The material law which ought to be used (extracted from the spatial parameters)
+NEW_PROP_TAG(MaterialLawParams); //!< The parameters of the material law (extracted from the spatial parameters)
+
+NEW_PROP_TAG(ProblemEnableGravity); //!< Returns whether gravity is considered in the problem
+NEW_PROP_TAG(ImplicitMassUpwindWeight); //!< The value of the upwind weight for the mass conservation equations
+NEW_PROP_TAG(ImplicitMobilityUpwindWeight); //!< Weight for the upwind mobility in the velocity calculation
+NEW_PROP_TAG(ReplaceCompEqIdx); //!< The index of the total mass balance equation, if one component balance is replaced (ReplaceCompEqIdx < NumComponents)
+NEW_PROP_TAG(VtkAddVelocity); //!< Returns whether velocity vectors are written into the vtk output
+NEW_PROP_TAG(BaseFluxVariables); //! The base flux variables
+NEW_PROP_TAG(SpatialParamsForchCoeff); //!< Property for the forchheimer coefficient
+}
+}
+
+#endif
diff --git a/dumux/implicit/2p2c/2p2cpropertydefaults.hh b/dumux/implicit/2p2c/2p2cpropertydefaults.hh
new file mode 100644
index 0000000000..98c9a1f333
--- /dev/null
+++ b/dumux/implicit/2p2c/2p2cpropertydefaults.hh
@@ -0,0 +1,160 @@
+// -*- mode: C++; tab-width: 4; indent-tabs-mode: nil; c-basic-offset: 4 -*-
+// vi: set et ts=4 sw=4 sts=4:
+/*****************************************************************************
+ *   See the file COPYING for full copying permissions.                      *
+ *                                                                           *
+ *   This program is free software: you can redistribute it and/or modify    *
+ *   it under the terms of the GNU General Public License as published by    *
+ *   the Free Software Foundation, either version 2 of the License, or       *
+ *   (at your option) any later version.                                     *
+ *                                                                           *
+ *   This program is distributed in the hope that it will be useful,         *
+ *   but WITHOUT ANY WARRANTY; without even the implied warranty of          *
+ *   MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the            *
+ *   GNU General Public License for more details.                            *
+ *                                                                           *
+ *   You should have received a copy of the GNU General Public License       *
+ *   along with this program.  If not, see <http://www.gnu.org/licenses/>.   *
+ *****************************************************************************/
+/*!
+ * \ingroup Properties
+ * \ingroup BoxProperties
+ * \ingroup TwoPTwoCModel
+ * \file
+ *
+ * \brief Defines default values for most properties required by the
+ *        2p2c box model.
+ */
+#ifndef DUMUX_2P2C_PROPERTY_DEFAULTS_HH
+#define DUMUX_2P2C_PROPERTY_DEFAULTS_HH
+
+#include "2p2cmodel.hh"
+#include "2p2cindices.hh"
+#include "2p2cfluxvariables.hh"
+#include "2p2cvolumevariables.hh"
+#include "2p2cproperties.hh"
+#include "2p2cnewtoncontroller.hh"
+
+#include <dumux/boxmodels/common/boxdarcyfluxvariables.hh>
+#include <dumux/material/spatialparams/boxspatialparams.hh>
+
+namespace Dumux
+{
+
+namespace Properties {
+//////////////////////////////////////////////////////////////////
+// Property values
+//////////////////////////////////////////////////////////////////
+
+/*!
+ * \brief Set the property for the number of components.
+ *
+ * We just forward the number from the fluid system and use an static
+ * assert to make sure it is 2.
+ */
+SET_PROP(BoxTwoPTwoC, NumComponents)
+{
+ private:
+    typedef typename GET_PROP_TYPE(TypeTag, FluidSystem) FluidSystem;
+
+ public:
+    static const int value = FluidSystem::numComponents;
+
+    static_assert(value == 2,
+                  "Only fluid systems with 2 components are supported by the 2p-2c model!");
+};
+
+/*!
+ * \brief Set the property for the number of fluid phases.
+ *
+ * We just forward the number from the fluid system and use an static
+ * assert to make sure it is 2.
+ */
+SET_PROP(BoxTwoPTwoC, NumPhases)
+{
+ private:
+    typedef typename GET_PROP_TYPE(TypeTag, FluidSystem) FluidSystem;
+
+ public:
+    static const int value = FluidSystem::numPhases;
+    static_assert(value == 2,
+                  "Only fluid systems with 2 phases are supported by the 2p-2c model!");
+};
+
+SET_INT_PROP(BoxTwoPTwoC, NumEq, 2); //!< set the number of equations to 2
+
+//! Set the default formulation to pw-Sn
+SET_INT_PROP(BoxTwoPTwoC,
+             Formulation,
+             TwoPTwoCFormulation::pwSn);
+
+//! set as default that no component mass balance is replaced by the total mass balance
+SET_INT_PROP(BoxTwoPTwoC, ReplaceCompEqIdx, 2);
+
+/*!
+ * \brief Set the property for the material parameters by extracting
+ *        it from the material law.
+ */
+SET_PROP(BoxTwoPTwoC, MaterialLawParams)
+{
+ private:
+    typedef typename GET_PROP_TYPE(TypeTag, MaterialLaw) MaterialLaw;
+
+ public:
+    typedef typename MaterialLaw::Params type;
+};
+
+//! Use the 2p2c local jacobian operator for the 2p2c model
+SET_TYPE_PROP(BoxTwoPTwoC,
+              LocalResidual,
+              TwoPTwoCLocalResidual<TypeTag>);
+
+//! Use the 2p2c specific newton controller for the 2p2c model
+SET_TYPE_PROP(BoxTwoPTwoC, NewtonController, TwoPTwoCNewtonController<TypeTag>);
+
+//! the Model property
+SET_TYPE_PROP(BoxTwoPTwoC, Model, TwoPTwoCModel<TypeTag>);
+
+//! the VolumeVariables property
+SET_TYPE_PROP(BoxTwoPTwoC, VolumeVariables, TwoPTwoCVolumeVariables<TypeTag>);
+
+//! the FluxVariables property
+SET_TYPE_PROP(BoxTwoPTwoC, FluxVariables, TwoPTwoCFluxVariables<TypeTag>);
+
+//! define the base flux variables to realize Darcy flow
+SET_TYPE_PROP(BoxTwoPTwoC, BaseFluxVariables, BoxDarcyFluxVariables<TypeTag>);
+
+//! the upwind weight for the mass conservation equations.
+SET_SCALAR_PROP(BoxTwoPTwoC, ImplicitMassUpwindWeight, 1.0);
+
+//! set default mobility upwind weight to 1.0, i.e. fully upwind
+SET_SCALAR_PROP(BoxTwoPTwoC, ImplicitMobilityUpwindWeight, 1.0);
+
+//! The indices required by the isothermal 2p2c model
+SET_PROP(BoxTwoPTwoC, Indices) 
+{ private:
+    enum { Formulation = GET_PROP_VALUE(TypeTag, Formulation) };
+ public:
+    typedef TwoPTwoCIndices<TypeTag, Formulation, 0> type;
+};
+
+//! The spatial parameters to be employed. 
+//! Use BoxSpatialParams by default.
+SET_TYPE_PROP(BoxTwoPTwoC, SpatialParams, BoxSpatialParams<TypeTag>);
+
+// disable velocity output by default
+SET_BOOL_PROP(BoxTwoPTwoC, VtkAddVelocity, false);
+
+// enable gravity by default
+SET_BOOL_PROP(BoxTwoPTwoC, ProblemEnableGravity, true);
+
+//! default value for the forchheimer coefficient
+// Source: Ward, J.C. 1964 Turbulent flow in porous media. ASCE J. Hydraul. Div 90.
+//        Actually the Forchheimer coefficient is also a function of the dimensions of the
+//        porous medium. Taking it as a constant is only a first approximation
+//        (Nield, Bejan, Convection in porous media, 2006, p. 10)
+SET_SCALAR_PROP(BoxModel, SpatialParamsForchCoeff, 0.55);}
+
+}
+
+#endif
diff --git a/dumux/implicit/2p2c/2p2cvolumevariables.hh b/dumux/implicit/2p2c/2p2cvolumevariables.hh
new file mode 100644
index 0000000000..f097db5c20
--- /dev/null
+++ b/dumux/implicit/2p2c/2p2cvolumevariables.hh
@@ -0,0 +1,455 @@
+// -*- mode: C++; tab-width: 4; indent-tabs-mode: nil; c-basic-offset: 4 -*-
+// vi: set et ts=4 sw=4 sts=4:
+/*****************************************************************************
+ *   See the file COPYING for full copying permissions.                      *
+ *                                                                           *
+ *   This program is free software: you can redistribute it and/or modify    *
+ *   it under the terms of the GNU General Public License as published by    *
+ *   the Free Software Foundation, either version 2 of the License, or       *
+ *   (at your option) any later version.                                     *
+ *                                                                           *
+ *   This program is distributed in the hope that it will be useful,         *
+ *   but WITHOUT ANY WARRANTY; without even the implied warranty of          *
+ *   MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the            *
+ *   GNU General Public License for more details.                            *
+ *                                                                           *
+ *   You should have received a copy of the GNU General Public License       *
+ *   along with this program.  If not, see <http://www.gnu.org/licenses/>.   *
+ *****************************************************************************/
+/*!
+ * \file
+ *
+ * \brief Contains the quantities which are constant within a
+ *        finite volume in the two-phase, two-component model.
+ */
+#ifndef DUMUX_2P2C_VOLUME_VARIABLES_HH
+#define DUMUX_2P2C_VOLUME_VARIABLES_HH
+
+#include <dumux/boxmodels/common/boxmodel.hh>
+#include <dumux/common/math.hh>
+
+#include <dune/common/collectivecommunication.hh>
+#include <vector>
+#include <iostream>
+
+#include "2p2cproperties.hh"
+#include "2p2cindices.hh"
+
+#include <dumux/material/fluidstates/compositionalfluidstate.hh>
+#include <dumux/material/constraintsolvers/computefromreferencephase.hh>
+#include <dumux/material/constraintsolvers/misciblemultiphasecomposition.hh>
+
+namespace Dumux
+{
+
+/*!
+ * \ingroup TwoPTwoCModel
+ * \ingroup BoxVolumeVariables
+ * \brief Contains the quantities which are are constant within a
+ *        finite volume in the two-phase, two-component model.
+ */
+template <class TypeTag>
+class TwoPTwoCVolumeVariables : public BoxVolumeVariables<TypeTag>
+{
+    typedef BoxVolumeVariables<TypeTag> ParentType;
+
+    typedef typename GET_PROP_TYPE(TypeTag, VolumeVariables) Implementation;
+    typedef typename GET_PROP_TYPE(TypeTag, Problem) Problem;
+    typedef typename GET_PROP_TYPE(TypeTag, FVElementGeometry) FVElementGeometry;
+    typedef typename GET_PROP_TYPE(TypeTag, PrimaryVariables) PrimaryVariables;
+    typedef typename GET_PROP_TYPE(TypeTag, MaterialLaw) MaterialLaw;
+    typedef typename GET_PROP_TYPE(TypeTag, MaterialLawParams) MaterialLawParams;
+    enum {
+        numPhases = GET_PROP_VALUE(TypeTag, NumPhases),
+        numComponents = GET_PROP_VALUE(TypeTag, NumComponents)
+    };
+
+    typedef typename GET_PROP_TYPE(TypeTag, Indices) Indices;
+    enum {
+        wCompIdx = Indices::wCompIdx,
+        nCompIdx = Indices::nCompIdx,
+        wPhaseIdx = Indices::wPhaseIdx,
+        nPhaseIdx = Indices::nPhaseIdx
+    };
+
+    // present phases
+    enum {
+        wPhaseOnly = Indices::wPhaseOnly,
+        nPhaseOnly = Indices::nPhaseOnly,
+        bothPhases = Indices::bothPhases
+    };
+
+    // formulations
+    enum {
+        formulation = GET_PROP_VALUE(TypeTag, Formulation),
+        pwSn = TwoPTwoCFormulation::pwSn,
+        pnSw = TwoPTwoCFormulation::pnSw
+    };
+
+    // primary variable indices
+    enum {
+        switchIdx = Indices::switchIdx,
+        pressureIdx = Indices::pressureIdx
+    };
+
+    typedef typename GET_PROP_TYPE(TypeTag, GridView) GridView;
+    typedef typename GridView::template Codim<0>::Entity Element;
+    enum { dim = GridView::dimension};
+
+    typedef typename GET_PROP_TYPE(TypeTag, Scalar) Scalar;
+    typedef typename GET_PROP_TYPE(TypeTag, FluidSystem) FluidSystem;
+    typedef Dumux::MiscibleMultiPhaseComposition<Scalar, FluidSystem> MiscibleMultiPhaseComposition;
+    typedef Dumux::ComputeFromReferencePhase<Scalar, FluidSystem> ComputeFromReferencePhase;
+
+public:
+    //! The type of the object returned by the fluidState() method
+    typedef Dumux::CompositionalFluidState<Scalar, FluidSystem> FluidState;
+
+    /*!
+     * \copydoc BoxVolumeVariables::update
+     */
+    void update(const PrimaryVariables &priVars,
+                const Problem &problem,
+                const Element &element,
+                const FVElementGeometry &fvGeometry,
+                const int scvIdx,
+                const bool isOldSol)
+    {
+        ParentType::update(priVars,
+                           problem,
+                           element,
+                           fvGeometry,
+                           scvIdx,
+                           isOldSol);
+
+        completeFluidState(priVars, problem, element, fvGeometry, scvIdx, fluidState_, isOldSol);
+
+        /////////////
+        // calculate the remaining quantities
+        /////////////
+        const MaterialLawParams &materialParams =
+            problem.spatialParams().materialLawParams(element, fvGeometry, scvIdx);
+
+        // Second instance of a parameter cache.
+        // Could be avoided if diffusion coefficients also
+        // became part of the fluid state.
+        typename FluidSystem::ParameterCache paramCache;
+        paramCache.updateAll(fluidState_);
+        for (int phaseIdx = 0; phaseIdx < numPhases; ++phaseIdx) {
+            // relative permeabilities
+            Scalar kr;
+            if (phaseIdx == wPhaseIdx)
+                kr = MaterialLaw::krw(materialParams, saturation(wPhaseIdx));
+            else // ATTENTION: krn requires the wetting phase saturation
+                 // as parameter!
+                kr = MaterialLaw::krn(materialParams, saturation(wPhaseIdx));
+            relativePermeability_[phaseIdx] = kr;
+            Valgrind::CheckDefined(relativePermeability_[phaseIdx]);
+
+            // binary diffusion coefficients
+            diffCoeff_[phaseIdx] =
+                FluidSystem::binaryDiffusionCoefficient(fluidState_,
+                                                        paramCache,
+                                                        phaseIdx,
+                                                        wCompIdx,
+                                                        nCompIdx);
+            Valgrind::CheckDefined(diffCoeff_[phaseIdx]);
+        }
+
+        // porosity
+        porosity_ = problem.spatialParams().porosity(element,
+                                                     fvGeometry,
+                                                     scvIdx);
+        Valgrind::CheckDefined(porosity_);
+
+        // energy related quantities not contained in the fluid state
+        asImp_().updateEnergy_(priVars, problem, element, fvGeometry, scvIdx, isOldSol);
+    }
+
+    /*!
+     * \copydoc BoxModel::completeFluidState
+     * \param isOldSol Specifies whether this is the previous solution or the current one
+     */
+    static void completeFluidState(const PrimaryVariables& priVars,
+                                   const Problem& problem,
+                                   const Element& element,
+                                   const FVElementGeometry& fvGeometry,
+                                   int scvIdx,
+                                   FluidState& fluidState,
+                                   bool isOldSol = false)
+    {
+        Scalar t = Implementation::temperature_(priVars, problem, element,
+                                                fvGeometry, scvIdx);
+        fluidState.setTemperature(t);
+
+        unsigned numDofs = problem.model().numDofs();
+        unsigned numVertices = problem.gridView().size(dim);
+
+        int globalIdx;
+        if (numDofs != numVertices) // element data
+            globalIdx = problem.model().dofMapper().map(element);
+        else
+            globalIdx = problem.model().dofMapper().map(element, scvIdx, dim);
+
+        int phasePresence = problem.model().phasePresence(globalIdx, isOldSol);
+
+        /////////////
+        // set the saturations
+        /////////////
+        Scalar Sn;
+        if (phasePresence == nPhaseOnly)
+            Sn = 1.0;
+        else if (phasePresence == wPhaseOnly) {
+            Sn = 0.0;
+        }
+        else if (phasePresence == bothPhases) {
+            if (formulation == pwSn)
+                Sn = priVars[switchIdx];
+            else if (formulation == pnSw)
+                Sn = 1.0 - priVars[switchIdx];
+            else DUNE_THROW(Dune::InvalidStateException, "Formulation: " << formulation << " is invalid.");
+        }
+        else DUNE_THROW(Dune::InvalidStateException, "phasePresence: " << phasePresence << " is invalid.");
+        fluidState.setSaturation(wPhaseIdx, 1 - Sn);
+        fluidState.setSaturation(nPhaseIdx, Sn);
+
+        /////////////
+        // set the pressures of the fluid phases
+        /////////////
+
+        // calculate capillary pressure
+        const MaterialLawParams &materialParams =
+            problem.spatialParams().materialLawParams(element, fvGeometry, scvIdx);
+        Scalar pC = MaterialLaw::pC(materialParams, 1 - Sn);
+
+        if (formulation == pwSn) {
+            fluidState.setPressure(wPhaseIdx, priVars[pressureIdx]);
+            fluidState.setPressure(nPhaseIdx, priVars[pressureIdx] + pC);
+        }
+        else if (formulation == pnSw) {
+            fluidState.setPressure(nPhaseIdx, priVars[pressureIdx]);
+            fluidState.setPressure(wPhaseIdx, priVars[pressureIdx] - pC);
+        }
+        else DUNE_THROW(Dune::InvalidStateException, "Formulation: " << formulation << " is invalid.");
+
+        /////////////
+        // calculate the phase compositions
+        /////////////
+        typename FluidSystem::ParameterCache paramCache;
+
+        // now comes the tricky part: calculate phase compositions
+        if (phasePresence == bothPhases) {
+            // both phases are present, phase compositions are a
+            // result of the the nonwetting <-> wetting equilibrium. This is
+            // the job of the "MiscibleMultiPhaseComposition"
+            // constraint solver
+            MiscibleMultiPhaseComposition::solve(fluidState,
+                                                 paramCache,
+                                                 /*setViscosity=*/true,
+                                                 /*setInternalEnergy=*/false);
+
+        }
+        else if (phasePresence == nPhaseOnly) {
+            // only the nonwetting phase is present, i.e. nonwetting phase
+            // composition is stored explicitly.
+
+            // extract _mass_ fractions in the nonwetting phase
+            Scalar massFractionN[numComponents];
+            massFractionN[wCompIdx] = priVars[switchIdx];
+            massFractionN[nCompIdx] = 1 - massFractionN[wCompIdx];
+
+            // calculate average molar mass of the nonwetting phase
+            Scalar M1 = FluidSystem::molarMass(wCompIdx);
+            Scalar M2 = FluidSystem::molarMass(nCompIdx);
+            Scalar X2 = massFractionN[nCompIdx];
+            Scalar avgMolarMass = M1*M2/(M2 + X2*(M1 - M2));
+
+            // convert mass to mole fractions and set the fluid state
+            fluidState.setMoleFraction(nPhaseIdx, wCompIdx, massFractionN[wCompIdx]*avgMolarMass/M1);
+            fluidState.setMoleFraction(nPhaseIdx, nCompIdx, massFractionN[nCompIdx]*avgMolarMass/M2);
+
+            // calculate the composition of the remaining phases (as
+            // well as the densities of all phases). this is the job
+            // of the "ComputeFromReferencePhase" constraint solver
+            ComputeFromReferencePhase::solve(fluidState,
+                                             paramCache,
+                                             nPhaseIdx,
+                                             /*setViscosity=*/true,
+                                             /*setInternalEnergy=*/false);
+        }
+        else if (phasePresence == wPhaseOnly) {
+            // only the wetting phase is present, i.e. wetting phase
+            // composition is stored explicitly.
+
+            // extract _mass_ fractions in the nonwetting phase
+            Scalar massFractionW[numComponents];
+            massFractionW[nCompIdx] = priVars[switchIdx];
+            massFractionW[wCompIdx] = 1 - massFractionW[nCompIdx];
+
+            // calculate average molar mass of the nonwetting phase
+            Scalar M1 = FluidSystem::molarMass(wCompIdx);
+            Scalar M2 = FluidSystem::molarMass(nCompIdx);
+            Scalar X2 = massFractionW[nCompIdx];
+            Scalar avgMolarMass = M1*M2/(M2 + X2*(M1 - M2));
+
+            // convert mass to mole fractions and set the fluid state
+            fluidState.setMoleFraction(wPhaseIdx, wCompIdx, massFractionW[wCompIdx]*avgMolarMass/M1);
+            fluidState.setMoleFraction(wPhaseIdx, nCompIdx, massFractionW[nCompIdx]*avgMolarMass/M2);
+
+            // calculate the composition of the remaining phases (as
+            // well as the densities of all phases). this is the job
+            // of the "ComputeFromReferencePhase" constraint solver
+            ComputeFromReferencePhase::solve(fluidState,
+                                             paramCache,
+                                             wPhaseIdx,
+                                             /*setViscosity=*/true,
+                                             /*setInternalEnergy=*/false);
+        }
+
+        for (int phaseIdx = 0; phaseIdx < numPhases; ++phaseIdx) {
+            // compute and set the enthalpy
+            Scalar h = Implementation::enthalpy_(fluidState, paramCache, phaseIdx);
+            fluidState.setEnthalpy(phaseIdx, h);
+        }
+    }
+
+    /*!
+     * \brief Returns the phase state for the control-volume.
+     */
+    const FluidState &fluidState() const
+    { return fluidState_; }
+
+    /*!
+     * \brief Returns the effective saturation of a given phase within
+     *        the control volume.
+     *
+     * \param phaseIdx The phase index
+     */
+    Scalar saturation(const int phaseIdx) const
+    { return fluidState_.saturation(phaseIdx); }
+
+    /*!
+     * \brief Returns the mass density of a given phase within the
+     *        control volume.
+     *
+     * \param phaseIdx The phase index
+     */
+    Scalar density(const int phaseIdx) const
+    { return fluidState_.density(phaseIdx); }
+
+    /*!
+     * \brief Returns the mass density of a given phase within the
+     *        control volume.
+     *
+     * \param phaseIdx The phase index
+     */
+    Scalar molarDensity(const int phaseIdx) const
+    { return fluidState_.density(phaseIdx) / fluidState_.averageMolarMass(phaseIdx); }
+
+    /*!
+     * \brief Returns the effective pressure of a given phase within
+     *        the control volume.
+     *
+     * \param phaseIdx The phase index
+     */
+    Scalar pressure(const int phaseIdx) const
+    { return fluidState_.pressure(phaseIdx); }
+
+    /*!
+     * \brief Returns temperature inside the sub-control volume.
+     *
+     * Note that we assume thermodynamic equilibrium, i.e. the
+     * temperature of the rock matrix and of all fluid phases are
+     * identical.
+     */
+    Scalar temperature() const
+    { return fluidState_.temperature(/*phaseIdx=*/0); }
+
+    /*!
+     * \brief Returns the relative permeability of a given phase within
+     *        the control volume.
+     *
+     * \param phaseIdx The phase index
+     */
+    Scalar relativePermeability(const int phaseIdx) const
+    {
+        return relativePermeability_[phaseIdx];
+    }
+
+    /*!
+     * \brief Returns the effective mobility of a given phase within
+     *        the control volume.
+     *
+     * \param phaseIdx The phase index
+     */
+    Scalar mobility(const int phaseIdx) const
+    {
+        return relativePermeability_[phaseIdx]/fluidState_.viscosity(phaseIdx);
+    }
+
+    /*!
+     * \brief Returns the effective capillary pressure within the control volume.
+     */
+    Scalar capillaryPressure() const
+    { return fluidState_.pressure(nPhaseIdx) - fluidState_.pressure(wPhaseIdx); }
+
+    /*!
+     * \brief Returns the average porosity within the control volume.
+     */
+    Scalar porosity() const
+    { return porosity_; }
+
+    /*!
+     * \brief Returns the binary diffusion coefficients for a phase
+     */
+    Scalar diffCoeff(int phaseIdx) const
+    { return diffCoeff_[phaseIdx]; }
+
+
+protected:
+    static Scalar temperature_(const PrimaryVariables &priVars,
+                               const Problem& problem,
+                               const Element &element,
+                               const FVElementGeometry &fvGeometry,
+                               int scvIdx)
+    {
+        return problem.boxTemperature(element, fvGeometry, scvIdx);
+    }
+
+    template<class ParameterCache>
+    static Scalar enthalpy_(const FluidState& fluidState,
+                            const ParameterCache& paramCache,
+                            const int phaseIdx)
+    {
+        return 0;
+    }
+
+    /*!
+     * \brief Called by update() to compute the energy related quantities
+     */
+    void updateEnergy_(const PrimaryVariables &sol,
+                       const Problem &problem,
+                       const Element &element,
+                       const FVElementGeometry &fvGeometry,
+                       const int vertIdx,
+                       bool isOldSol)
+    { }
+
+    Scalar porosity_;        //!< Effective porosity within the control volume
+    Scalar relativePermeability_[numPhases];  //!< Relative permeability within the control volume
+    Scalar diffCoeff_[numPhases]; //!< Binary diffusion coefficients for the phases
+    FluidState fluidState_;
+
+private:
+    Implementation &asImp_()
+    { return *static_cast<Implementation*>(this); }
+
+    const Implementation &asImp_() const
+    { return *static_cast<const Implementation*>(this); }
+
+
+};
+
+} // end namespace
+
+#endif
diff --git a/dumux/implicit/2p2c/Makefile.am b/dumux/implicit/2p2c/Makefile.am
new file mode 100644
index 0000000000..f15c521752
--- /dev/null
+++ b/dumux/implicit/2p2c/Makefile.am
@@ -0,0 +1,4 @@
+2p2cdir = $(includedir)/dumux/boxmodels/2p2c
+2p2c_HEADERS = *.hh
+
+include $(top_srcdir)/am/global-rules
diff --git a/dumux/implicit/2p2cni/2p2cnifluxvariables.hh b/dumux/implicit/2p2cni/2p2cnifluxvariables.hh
new file mode 100644
index 0000000000..ca2b2a55f0
--- /dev/null
+++ b/dumux/implicit/2p2cni/2p2cnifluxvariables.hh
@@ -0,0 +1,146 @@
+// -*- mode: C++; tab-width: 4; indent-tabs-mode: nil; c-basic-offset: 4 -*-
+// vi: set et ts=4 sw=4 sts=4:
+/*****************************************************************************
+ *   See the file COPYING for full copying permissions.                      *
+ *                                                                           *
+ *   This program is free software: you can redistribute it and/or modify    *
+ *   it under the terms of the GNU General Public License as published by    *
+ *   the Free Software Foundation, either version 2 of the License, or       *
+ *   (at your option) any later version.                                     *
+ *                                                                           *
+ *   This program is distributed in the hope that it will be useful,         *
+ *   but WITHOUT ANY WARRANTY; without even the implied warranty of          *
+ *   MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the            *
+ *   GNU General Public License for more details.                            *
+ *                                                                           *
+ *   You should have received a copy of the GNU General Public License       *
+ *   along with this program.  If not, see <http://www.gnu.org/licenses/>.   *
+ *****************************************************************************/
+/*!
+ * \file
+ *
+ * \brief This file contains data which is required to calculate
+ *        the heat fluxes over a face of a finite volume.
+ *
+ * This means temperature gradients and the normal matrix
+ * heat flux.
+ */
+#ifndef DUMUX_2P2CNI_FLUX_VARIABLES_HH
+#define DUMUX_2P2CNI_FLUX_VARIABLES_HH
+
+#include <dumux/common/math.hh>
+#include <dumux/boxmodels/2p2c/2p2cfluxvariables.hh>
+
+namespace Dumux
+{
+
+/*!
+ * \ingroup TwoPTwoCNIModel
+ * \ingroup BoxFluxVariables
+ * \brief This template class contains data which is required to
+ *        calculate the heat fluxes over a face of a finite
+ *        volume for the non-isothermal two-phase, two-component model.
+ *        The mass fluxes are computed in the parent class.
+ *
+ * This means temperature gradients and the normal matrix
+ * heat flux.
+ */
+template <class TypeTag>
+class TwoPTwoCNIFluxVariables : public TwoPTwoCFluxVariables<TypeTag>
+{
+    typedef TwoPTwoCFluxVariables<TypeTag> ParentType;
+
+    typedef typename GET_PROP_TYPE(TypeTag, Scalar) Scalar;
+    typedef typename GET_PROP_TYPE(TypeTag, Problem) Problem;
+    typedef typename GET_PROP_TYPE(TypeTag, ElementVolumeVariables) ElementVolumeVariables;
+    typedef typename GET_PROP_TYPE(TypeTag, FVElementGeometry) FVElementGeometry;
+
+    typedef typename GET_PROP_TYPE(TypeTag, GridView) GridView;
+    typedef typename GridView::template Codim<0>::Entity Element;
+    enum { dimWorld = GridView::dimensionworld };
+    typedef Dune::FieldVector<Scalar, dimWorld> DimVector;
+
+public:
+    /*
+     * \brief The constructor
+     *
+     * \param problem The problem
+     * \param element The finite element
+     * \param elemGeom The finite-volume geometry in the box scheme
+     * \param faceIdx The local index of the SCV (sub-control-volume) face
+     * \param elemVolVars The volume variables of the current element
+     */
+    TwoPTwoCNIFluxVariables(const Problem &problem,
+                            const Element &element,
+                            const FVElementGeometry &fvGeometry,
+                            const int faceIdx,
+                            const ElementVolumeVariables &elemVolVars,
+                            bool onBoundary = false)
+        : ParentType(problem, element, fvGeometry, faceIdx, elemVolVars, onBoundary)
+    {
+        faceIdx_ = faceIdx;
+
+        calculateValues_(problem, element, elemVolVars);
+    }
+
+    /*!
+     * \brief The total heat flux \f$\mathrm{[J/s]}\f$ due to heat conduction
+     *        of the rock matrix over the sub-control volume face in
+     *        direction of the face normal.
+     */
+    Scalar normalMatrixHeatFlux() const
+    { return normalMatrixHeatFlux_; }
+
+    DimVector temperatureGradient() const
+    { return temperatureGrad_; }
+
+protected:
+    void calculateValues_(const Problem &problem,
+                          const Element &element,
+                          const ElementVolumeVariables &elemVolVars)
+    {
+        // calculate temperature gradient using finite element
+        // gradients
+        temperatureGrad_ = 0;
+        DimVector tmp(0.0);
+        for (int idx = 0; idx < this->fvGeometry_.numFAP; idx++)
+        {
+            tmp = this->face().grad[idx];
+
+            // index for the element volume variables 
+            int volVarsIdx = this->face().fapIndices[idx];
+
+            tmp *= elemVolVars[volVarsIdx].temperature();
+            temperatureGrad_ += tmp;
+        }
+
+        // The spatial parameters calculates the actual heat flux vector
+        if (this->face().i != this->face().j)
+            problem.spatialParams().matrixHeatFlux(tmp,
+                                                   *this,
+                                                   elemVolVars,
+                                                   temperatureGrad_,
+                                                   element,
+                                                   this->fvGeometry_,
+                                                   faceIdx_);
+        else // heat flux at outflow boundaries
+            problem.spatialParams().boundaryMatrixHeatFlux(tmp,
+                                                           *this,
+                                                           elemVolVars,
+                                                           this->face(),
+                                                           element,
+                                                           this->fvGeometry_);
+
+        // project the heat flux vector on the face's normal vector
+        normalMatrixHeatFlux_ = tmp*this->face().normal;
+    }
+
+private:
+    Scalar normalMatrixHeatFlux_;
+    DimVector temperatureGrad_;
+    int faceIdx_;
+};
+
+} // end namespace
+
+#endif
diff --git a/dumux/implicit/2p2cni/2p2cniindices.hh b/dumux/implicit/2p2cni/2p2cniindices.hh
new file mode 100644
index 0000000000..4eefa0d505
--- /dev/null
+++ b/dumux/implicit/2p2cni/2p2cniindices.hh
@@ -0,0 +1,51 @@
+// -*- mode: C++; tab-width: 4; indent-tabs-mode: nil; c-basic-offset: 4 -*-
+// vi: set et ts=4 sw=4 sts=4:
+/*****************************************************************************
+ *   See the file COPYING for full copying permissions.                      *
+ *                                                                           *
+ *   This program is free software: you can redistribute it and/or modify    *
+ *   it under the terms of the GNU General Public License as published by    *
+ *   the Free Software Foundation, either version 2 of the License, or       *
+ *   (at your option) any later version.                                     *
+ *                                                                           *
+ *   This program is distributed in the hope that it will be useful,         *
+ *   but WITHOUT ANY WARRANTY; without even the implied warranty of          *
+ *   MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the            *
+ *   GNU General Public License for more details.                            *
+ *                                                                           *
+ *   You should have received a copy of the GNU General Public License       *
+ *   along with this program.  If not, see <http://www.gnu.org/licenses/>.   *
+ *****************************************************************************/
+
+/*!
+ * \file
+ *
+ * \brief Defines the indices used by the 2p2cni box model
+ */
+#ifndef DUMUX_2P2CNI_INDICES_HH
+#define DUMUX_2P2CNI_INDICES_HH
+
+#include <dumux/boxmodels/2p2c/2p2cindices.hh>
+
+namespace Dumux
+{
+// \{
+
+/*!
+ * \ingroup TwoPTwoCNIModel
+ * \ingroup BoxIndices
+ * \brief Enumerations for the non-isothermal 2-phase 2-component model
+ *
+ * \tparam formulation The formulation, either pwSn or pnSw.
+ * \tparam PVOffset The first index in a primary variable vector.
+ */
+template <class TypeTag, int formulation, int PVOffset>
+class TwoPTwoCNIIndices : public TwoPTwoCIndices<TypeTag, formulation, PVOffset>
+{
+public:
+    static const int temperatureIdx = PVOffset + 2; //! The index for temperature in primary variable vectors.
+    static const int energyEqIdx = PVOffset + 2; //! The index for energy in equation vectors.
+};
+
+}
+#endif
diff --git a/dumux/implicit/2p2cni/2p2cnilocalresidual.hh b/dumux/implicit/2p2cni/2p2cnilocalresidual.hh
new file mode 100644
index 0000000000..2b1b43f40e
--- /dev/null
+++ b/dumux/implicit/2p2cni/2p2cnilocalresidual.hh
@@ -0,0 +1,175 @@
+// -*- mode: C++; tab-width: 4; indent-tabs-mode: nil; c-basic-offset: 4 -*-
+// vi: set et ts=4 sw=4 sts=4:
+/*****************************************************************************
+ *   See the file COPYING for full copying permissions.                      *
+ *                                                                           *
+ *   This program is free software: you can redistribute it and/or modify    *
+ *   it under the terms of the GNU General Public License as published by    *
+ *   the Free Software Foundation, either version 2 of the License, or       *
+ *   (at your option) any later version.                                     *
+ *                                                                           *
+ *   This program is distributed in the hope that it will be useful,         *
+ *   but WITHOUT ANY WARRANTY; without even the implied warranty of          *
+ *   MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the            *
+ *   GNU General Public License for more details.                            *
+ *                                                                           *
+ *   You should have received a copy of the GNU General Public License       *
+ *   along with this program.  If not, see <http://www.gnu.org/licenses/>.   *
+ *****************************************************************************/
+/*!
+ * \file
+ *
+ * \brief Element-wise calculation of the Jacobian matrix for problems
+ *        using the non-isothermal two-phase two-component box model.
+ *
+ */
+#ifndef DUMUX_NEW_2P2CNI_LOCAL_RESIDUAL_HH
+#define DUMUX_NEW_2P2CNI_LOCAL_RESIDUAL_HH
+
+#include <dumux/boxmodels/2p2c/2p2clocalresidual.hh>
+
+#include <dumux/boxmodels/2p2cni/2p2cnivolumevariables.hh>
+#include <dumux/boxmodels/2p2cni/2p2cnifluxvariables.hh>
+#include <dumux/boxmodels/2p2cni/2p2cniproperties.hh>
+
+namespace Dumux
+{
+/*!
+ * \ingroup TwoPTwoCNIModel
+ * \ingroup BoxLocalResidual
+ * \brief Element-wise calculation of the Jacobian matrix for problems
+ *        using the two-phase two-component box model.
+ */
+template<class TypeTag>
+class TwoPTwoCNILocalResidual : public TwoPTwoCLocalResidual<TypeTag>
+{
+    typedef TwoPTwoCLocalResidual<TypeTag> ParentType;
+
+    typedef typename GET_PROP_TYPE(TypeTag, Scalar) Scalar;
+    typedef typename GET_PROP_TYPE(TypeTag, PrimaryVariables) PrimaryVariables;
+    typedef typename GET_PROP_TYPE(TypeTag, VolumeVariables) VolumeVariables;
+    typedef typename GET_PROP_TYPE(TypeTag, FluxVariables) FluxVariables;
+    typedef typename GET_PROP_TYPE(TypeTag, ElementVolumeVariables) ElementVolumeVariables;
+
+    typedef typename GET_PROP_TYPE(TypeTag, Indices) Indices;
+    enum {
+        numPhases = GET_PROP_VALUE(TypeTag, NumPhases),
+        energyEqIdx = Indices::energyEqIdx,
+        temperatureIdx = Indices::temperatureIdx,
+        wPhaseIdx = Indices::wPhaseIdx,
+        nPhaseIdx = Indices::nPhaseIdx
+    };
+
+public:
+    /*!
+     * \brief Constructor. Sets the upwind weight.
+     */
+    TwoPTwoCNILocalResidual()
+    {
+        // retrieve the upwind weight for the mass conservation equations. Use the value
+        // specified via the property system as default, and overwrite
+        // it by the run-time parameter from the Dune::ParameterTree
+        massUpwindWeight_ = GET_PARAM_FROM_GROUP(TypeTag, Scalar, Implicit, MassUpwindWeight);
+    };
+
+    /*!
+     * \brief Evaluate the amount all conservation quantities
+     *        (e.g. phase mass) within a sub-control volume.
+     *
+     * The result should be averaged over the volume (e.g. phase mass
+     * inside a sub control volume divided by the volume)
+     *
+     *  \param storage The storage of the conservation quantity (mass or energy) within the sub-control volume
+     *  \param scvIdx The SCV (sub-control-volume) index
+     *  \param usePrevSol Evaluate function with solution of current or previous time step
+     */
+    void computeStorage(PrimaryVariables &storage, const int scvIdx, bool usePrevSol) const
+    {
+        // compute the storage term for phase mass
+        ParentType::computeStorage(storage, scvIdx, usePrevSol);
+
+        // if flag usePrevSol is set, the solution from the previous
+        // time step is used, otherwise the current solution is
+        // used. The secondary variables are used accordingly.  This
+        // is required to compute the derivative of the storage term
+        // using the implicit Euler method.
+        const ElementVolumeVariables &elemVolVars = usePrevSol ? this->prevVolVars_() : this->curVolVars_();
+        const VolumeVariables &volVars = elemVolVars[scvIdx];
+
+        // compute the energy storage
+        storage[energyEqIdx] =
+            volVars.porosity()*(volVars.density(wPhaseIdx) *
+                                volVars.internalEnergy(wPhaseIdx) *
+                                volVars.saturation(wPhaseIdx)
+                                +
+                                volVars.density(nPhaseIdx) *
+                                volVars.internalEnergy(nPhaseIdx) *
+                                volVars.saturation(nPhaseIdx))
+            +
+            // heat capacity is already multiplied by the density
+            // of the porous material and the porosity in the problem file
+            volVars.temperature()*volVars.heatCapacity();
+    }
+
+    /*!
+     * \brief Evaluates the advective mass flux and the heat flux
+     * over a face of a subcontrol volume and writes the result in
+     * the flux vector.
+     *
+     * \param flux The advective flux over the SCV (sub-control-volume) face for each component
+     * \param fluxVars The flux variables at the current SCV face
+     *
+     * This method is called by compute flux (base class)
+     */
+    void computeAdvectiveFlux(PrimaryVariables &flux,
+                              const FluxVariables &fluxVars) const
+    {
+        // advective mass flux
+        ParentType::computeAdvectiveFlux(flux, fluxVars);
+
+        // advective heat flux in all phases
+        flux[energyEqIdx] = 0;
+        for (int phaseIdx = 0; phaseIdx < numPhases; ++phaseIdx) {
+            // vertex data of the upstream and the downstream vertices
+            const VolumeVariables &up = this->curVolVars_(fluxVars.upstreamIdx(phaseIdx));
+            const VolumeVariables &dn = this->curVolVars_(fluxVars.downstreamIdx(phaseIdx));
+
+            flux[energyEqIdx] +=
+                fluxVars.volumeFlux(phaseIdx) * (massUpwindWeight_ * // upstream vertex
+                                                 (  up.density(phaseIdx) *
+                                                    up.enthalpy(phaseIdx))
+                                                 +
+                                                 (1-massUpwindWeight_) * // downstream vertex
+                                                 (  dn.density(phaseIdx) *
+                                                    dn.enthalpy(phaseIdx)) );
+        }
+    }
+
+    /*!
+     * \brief Adds the diffusive heat flux to the flux vector over
+     *        the face of a sub-control volume.
+     *
+     * \param flux The diffusive flux over the SCV (sub-control-volume) face for each conservation quantity (mass, energy)
+     * \param fluxVars The flux variables at the current SCV face
+     *
+     * This method is called by compute flux (base class)
+     */
+    void computeDiffusiveFlux(PrimaryVariables &flux,
+                              const FluxVariables &fluxVars) const
+    {
+        // diffusive mass flux
+        ParentType::computeDiffusiveFlux(flux, fluxVars);
+
+        // diffusive heat flux
+        flux[temperatureIdx] +=
+            fluxVars.normalMatrixHeatFlux();
+    }
+
+private:
+    Scalar massUpwindWeight_;
+
+};
+
+}
+
+#endif
diff --git a/dumux/implicit/2p2cni/2p2cnimodel.hh b/dumux/implicit/2p2cni/2p2cnimodel.hh
new file mode 100644
index 0000000000..6dac22eb31
--- /dev/null
+++ b/dumux/implicit/2p2cni/2p2cnimodel.hh
@@ -0,0 +1,98 @@
+// -*- mode: C++; tab-width: 4; indent-tabs-mode: nil; c-basic-offset: 4 -*-
+// vi: set et ts=4 sw=4 sts=4:
+/*****************************************************************************
+ *   See the file COPYING for full copying permissions.                      *
+ *                                                                           *
+ *   This program is free software: you can redistribute it and/or modify    *
+ *   it under the terms of the GNU General Public License as published by    *
+ *   the Free Software Foundation, either version 2 of the License, or       *
+ *   (at your option) any later version.                                     *
+ *                                                                           *
+ *   This program is distributed in the hope that it will be useful,         *
+ *   but WITHOUT ANY WARRANTY; without even the implied warranty of          *
+ *   MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the            *
+ *   GNU General Public License for more details.                            *
+ *                                                                           *
+ *   You should have received a copy of the GNU General Public License       *
+ *   along with this program.  If not, see <http://www.gnu.org/licenses/>.   *
+ *****************************************************************************/
+/*!
+ * \file
+ *
+ * \brief Adaption of the BOX scheme to the non-isothermal two-phase two-component flow model.
+ */
+#ifndef DUMUX_NEW_2P2CNI_MODEL_HH
+#define DUMUX_NEW_2P2CNI_MODEL_HH
+
+#include <dumux/boxmodels/2p2c/2p2cmodel.hh>
+
+namespace Dumux {
+/*!
+ * \ingroup TwoPTwoCNIModel
+ * \brief Adaption of the BOX scheme to the non-isothermal two-phase two-component flow model.
+ *
+ * This model implements a non-isothermal two-phase flow of two compressible and partly miscible fluids
+ * \f$\alpha \in \{ w, n \}\f$. Thus each component \f$\kappa \{ w, a \}\f$ can be present in
+ * each phase.
+ * Using the standard multiphase Darcy approach a mass balance equation is
+ * solved:
+ * \f{eqnarray*}
+ && \phi \frac{\partial (\sum_\alpha \varrho_\alpha X_\alpha^\kappa S_\alpha )}{\partial t}
+ - \sum_\alpha \text{div} \left\{ \varrho_\alpha X_\alpha^\kappa
+ \frac{k_{r\alpha}}{\mu_\alpha} \mbox{\bf K}
+ (\text{grad}\, p_\alpha - \varrho_{\alpha} \mbox{\bf g}) \right\}\\
+ &-& \sum_\alpha \text{div} \left\{{\bf D}_{\alpha, pm}^\kappa \varrho_{\alpha} \text{grad}\, X^\kappa_{\alpha} \right\}
+ - \sum_\alpha q_\alpha^\kappa = 0 \qquad \kappa \in \{w, a\} \, ,
+ \alpha \in \{w, n\}
+ *     \f}
+ * For the energy balance, local thermal equilibrium is assumed which results in one
+ * energy conservation equation for the porous solid matrix and the fluids:
+ * \f{eqnarray*}
+ && \phi \frac{\partial \left( \sum_\alpha \varrho_\alpha u_\alpha S_\alpha \right)}{\partial t}
+ + \left( 1 - \phi \right) \frac{\partial (\varrho_s c_s T)}{\partial t}
+ - \sum_\alpha \text{div} \left\{ \varrho_\alpha h_\alpha
+ \frac{k_{r\alpha}}{\mu_\alpha} \mathbf{K} \left( \text{grad}\,
+ p_\alpha
+ - \varrho_\alpha \mathbf{g} \right) \right\} \\
+ &-& \text{div} \left( \lambda_{pm} \text{grad} \, T \right)
+ - q^h = 0 \qquad \alpha \in \{w, n\}
+ \f}
+ *
+ * This is discretized using a fully-coupled vertex
+ * centered finite volume (box) scheme as spatial and
+ * the implicit Euler method as temporal discretization.
+ *
+ * By using constitutive relations for the capillary pressure \f$p_c =
+ * p_n - p_w\f$ and relative permeability \f$k_{r\alpha}\f$ and taking
+ * advantage of the fact that \f$S_w + S_n = 1\f$ and \f$X^\kappa_w + X^\kappa_n = 1\f$, the number of
+ * unknowns can be reduced to two.
+ * If both phases are present the primary variables are, like in the nonisothermal two-phase model, either \f$p_w\f$, \f$S_n\f$ and
+ * temperature or \f$p_n\f$, \f$S_w\f$ and temperature. The formulation which ought to be used can be
+ * specified by setting the <tt>Formulation</tt> property to either
+ * <tt>TwoPTwoCIndices::pWsN</tt> or <tt>TwoPTwoCIndices::pNsW</tt>. By
+ * default, the model uses \f$p_w\f$ and \f$S_n\f$.
+ * In case that only one phase (nonwetting or wetting phase) is present the second primary
+ * variable represents a mass fraction. The correct assignment of the second
+ * primary variable is performed by a phase state dependent primary variable switch. The phase state is stored for all nodes of the system. The following cases can be distinguished:
+ * <ul>
+ *  <li>
+ *    Both phases are present: The saturation is used (either\f$S_n\f$ or \f$S_w\f$, dependent on the chosen formulation).
+ *  </li>
+ *  <li>
+ *    Only wetting phase is present: The mass fraction of air in the wetting phase \f$X^a_w\f$ is used.
+ *  </li>
+ *  <li>
+ *    Only non-wetting phase is present: The mass fraction of water in the non-wetting phase, \f$X^w_n\f$, is used.
+ *  </li>
+ * </ul>
+ */
+template<class TypeTag>
+class TwoPTwoCNIModel : public TwoPTwoCModel<TypeTag>
+{
+};
+
+}
+
+#include "2p2cnipropertydefaults.hh"
+
+#endif
diff --git a/dumux/implicit/2p2cni/2p2cniproperties.hh b/dumux/implicit/2p2cni/2p2cniproperties.hh
new file mode 100644
index 0000000000..6e221dea1e
--- /dev/null
+++ b/dumux/implicit/2p2cni/2p2cniproperties.hh
@@ -0,0 +1,47 @@
+// -*- mode: C++; tab-width: 4; indent-tabs-mode: nil; c-basic-offset: 4 -*-
+// vi: set et ts=4 sw=4 sts=4:
+/*****************************************************************************
+ *   See the file COPYING for full copying permissions.                      *
+ *                                                                           *
+ *   This program is free software: you can redistribute it and/or modify    *
+ *   it under the terms of the GNU General Public License as published by    *
+ *   the Free Software Foundation, either version 2 of the License, or       *
+ *   (at your option) any later version.                                     *
+ *                                                                           *
+ *   This program is distributed in the hope that it will be useful,         *
+ *   but WITHOUT ANY WARRANTY; without even the implied warranty of          *
+ *   MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the            *
+ *   GNU General Public License for more details.                            *
+ *                                                                           *
+ *   You should have received a copy of the GNU General Public License       *
+ *   along with this program.  If not, see <http://www.gnu.org/licenses/>.   *
+ *****************************************************************************/
+/*!
+ * \ingroup Properties
+ * \ingroup BoxProperties
+ * \ingroup TwoPTwoCNIModel
+ * \file
+ *
+ * \brief Defines the properties required for the non-isothermal two-phase,
+ * two-component BOX model.
+ */
+#ifndef DUMUX_2P2CNI_PROPERTIES_HH
+#define DUMUX_2P2CNI_PROPERTIES_HH
+
+#include <dumux/boxmodels/2p2c/2p2cproperties.hh>
+
+namespace Dumux
+{
+
+namespace Properties
+{
+//////////////////////////////////////////////////////////////////
+// Type tags
+//////////////////////////////////////////////////////////////////
+
+//! The type tag for the non-isothermal two-phase, two-component problems
+NEW_TYPE_TAG(BoxTwoPTwoCNI, INHERITS_FROM(BoxTwoPTwoC));
+}
+}
+
+#endif
diff --git a/dumux/implicit/2p2cni/2p2cnipropertydefaults.hh b/dumux/implicit/2p2cni/2p2cnipropertydefaults.hh
new file mode 100644
index 0000000000..efc97a991c
--- /dev/null
+++ b/dumux/implicit/2p2cni/2p2cnipropertydefaults.hh
@@ -0,0 +1,76 @@
+// -*- mode: C++; tab-width: 4; indent-tabs-mode: nil; c-basic-offset: 4 -*-
+// vi: set et ts=4 sw=4 sts=4:
+/*****************************************************************************
+ *   See the file COPYING for full copying permissions.                      *
+ *                                                                           *
+ *   This program is free software: you can redistribute it and/or modify    *
+ *   it under the terms of the GNU General Public License as published by    *
+ *   the Free Software Foundation, either version 2 of the License, or       *
+ *   (at your option) any later version.                                     *
+ *                                                                           *
+ *   This program is distributed in the hope that it will be useful,         *
+ *   but WITHOUT ANY WARRANTY; without even the implied warranty of          *
+ *   MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the            *
+ *   GNU General Public License for more details.                            *
+ *                                                                           *
+ *   You should have received a copy of the GNU General Public License       *
+ *   along with this program.  If not, see <http://www.gnu.org/licenses/>.   *
+ *****************************************************************************/
+/*!
+ * \ingroup Properties
+ * \ingroup BoxProperties
+ * \ingroup TwoPTwoCNIModel
+ * \file
+ *
+ * \brief Defines default values for most properties required by the 2p2cni
+ *        box model.
+ */
+#ifndef DUMUX_2P2CNI_PROPERTY_DEFAULTS_HH
+#define DUMUX_2P2CNI_PROPERTY_DEFAULTS_HH
+
+#include <dumux/boxmodels/2p2c/2p2cpropertydefaults.hh>
+
+#include "2p2cnimodel.hh"
+#include "2p2cniindices.hh"
+#include "2p2cnilocalresidual.hh"
+#include "2p2cnivolumevariables.hh"
+#include "2p2cnifluxvariables.hh"
+
+namespace Dumux
+{
+
+namespace Properties
+{
+//////////////////////////////////////////////////////////////////
+// Property values
+//////////////////////////////////////////////////////////////////
+
+SET_INT_PROP(BoxTwoPTwoCNI, NumEq, 3); //!< set the number of equations to 3
+
+//! Use the 2p2cni local jacobian operator for the 2p2cni model
+SET_TYPE_PROP(BoxTwoPTwoCNI,
+              LocalResidual,
+              TwoPTwoCNILocalResidual<TypeTag>);
+
+//! the Model property
+SET_TYPE_PROP(BoxTwoPTwoCNI, Model, TwoPTwoCNIModel<TypeTag>);
+
+//! the VolumeVariables property
+SET_TYPE_PROP(BoxTwoPTwoCNI, VolumeVariables, TwoPTwoCNIVolumeVariables<TypeTag>);
+
+
+//! the FluxVariables property
+SET_TYPE_PROP(BoxTwoPTwoCNI, FluxVariables, TwoPTwoCNIFluxVariables<TypeTag>);
+
+//! The indices required by the non-isothermal 2p2c model
+SET_PROP(BoxTwoPTwoCNI, Indices) 
+{ private:
+    enum { formulation = GET_PROP_VALUE(TypeTag, Formulation) };
+ public:
+    typedef TwoPTwoCNIIndices<TypeTag, formulation, 0> type;
+};
+
+}
+
+}
+#endif
diff --git a/dumux/implicit/2p2cni/2p2cnivolumevariables.hh b/dumux/implicit/2p2cni/2p2cnivolumevariables.hh
new file mode 100644
index 0000000000..c6712a89e0
--- /dev/null
+++ b/dumux/implicit/2p2cni/2p2cnivolumevariables.hh
@@ -0,0 +1,144 @@
+// -*- mode: C++; tab-width: 4; indent-tabs-mode: nil; c-basic-offset: 4 -*-
+// vi: set et ts=4 sw=4 sts=4:
+/*****************************************************************************
+ *   See the file COPYING for full copying permissions.                      *
+ *                                                                           *
+ *   This program is free software: you can redistribute it and/or modify    *
+ *   it under the terms of the GNU General Public License as published by    *
+ *   the Free Software Foundation, either version 2 of the License, or       *
+ *   (at your option) any later version.                                     *
+ *                                                                           *
+ *   This program is distributed in the hope that it will be useful,         *
+ *   but WITHOUT ANY WARRANTY; without even the implied warranty of          *
+ *   MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the            *
+ *   GNU General Public License for more details.                            *
+ *                                                                           *
+ *   You should have received a copy of the GNU General Public License       *
+ *   along with this program.  If not, see <http://www.gnu.org/licenses/>.   *
+ *****************************************************************************/
+/*!
+ * \file
+ *
+ * \brief Contains the quantities which are constant within a
+ *        finite volume in the non-isothermal two-phase, two-component
+ *        model.
+ */
+#ifndef DUMUX_2P2CNI_VOLUME_VARIABLES_HH
+#define DUMUX_2P2CNI_VOLUME_VARIABLES_HH
+
+#include <dumux/boxmodels/2p2c/2p2cvolumevariables.hh>
+
+namespace Dumux
+{
+
+/*!
+ * \ingroup TwoPTwoCNIModel
+ * \ingroup BoxVolumeVariables
+ * \brief Contains the quantities which are are constant within a
+ *        finite volume in the non-isothermal two-phase, two-component
+ *        model.
+ */
+template <class TypeTag>
+class TwoPTwoCNIVolumeVariables : public TwoPTwoCVolumeVariables<TypeTag>
+{
+    //! \cond 0
+    typedef TwoPTwoCVolumeVariables<TypeTag> ParentType;
+    typedef typename ParentType::FluidState FluidState;
+
+    typedef typename GET_PROP_TYPE(TypeTag, Scalar) Scalar;
+    typedef typename GET_PROP_TYPE(TypeTag, FVElementGeometry) FVElementGeometry;
+    typedef typename GET_PROP_TYPE(TypeTag, Problem) Problem;
+    typedef typename GET_PROP_TYPE(TypeTag, PrimaryVariables) PrimaryVariables;
+    typedef typename GET_PROP_TYPE(TypeTag, FluidSystem) FluidSystem;
+
+    typedef typename GET_PROP_TYPE(TypeTag, Indices) Indices;
+    enum { temperatureIdx = Indices::temperatureIdx };
+
+    typedef typename GET_PROP_TYPE(TypeTag, GridView) GridView;
+    typedef typename GridView::template Codim<0>::Entity Element;
+    //! \endcond
+
+public:
+    /*!
+     * \brief Returns the total internal energy of a phase in the
+     *        sub-control volume.
+     *
+     * \param phaseIdx The phase index
+     */
+    Scalar internalEnergy(const int phaseIdx) const
+    { return this->fluidState_.internalEnergy(phaseIdx); };
+
+    /*!
+     * \brief Returns the total enthalpy of a phase in the sub-control
+     *        volume.
+     *
+     * \param phaseIdx The phase index
+     */
+    Scalar enthalpy(const int phaseIdx) const
+    { return this->fluidState_.enthalpy(phaseIdx); };
+
+    /*!
+     * \brief Returns the total heat capacity \f$\mathrm{[J/(K*m^3]}\f$ of the rock matrix in
+     *        the sub-control volume.
+     */
+    Scalar heatCapacity() const
+    { return heatCapacity_; };
+
+    /*!
+     * \brief Returns the thermal conductivity \f$\mathrm{[W/(m*K)]}\f$ of the fluid phase in
+     *        the sub-control volume.
+     */
+    Scalar thermalConductivity(const int phaseIdx) const
+    { return FluidSystem::thermalConductivity(this->fluidState_, phaseIdx); };
+
+
+protected:
+    // this method gets called by the parent class. since this method
+    // is protected, we are friends with our parent..
+    friend class TwoPTwoCVolumeVariables<TypeTag>;
+
+    static Scalar temperature_(const PrimaryVariables &priVars,
+                               const Problem& problem,
+                               const Element &element,
+                               const FVElementGeometry &fvGeometry,
+                               const int scvIdx)
+    {
+        return priVars[temperatureIdx];
+    }
+
+    template<class ParameterCache>
+    static Scalar enthalpy_(const FluidState& fluidState,
+                            const ParameterCache& paramCache,
+                            const int phaseIdx)
+    {
+        return FluidSystem::enthalpy(fluidState, paramCache, phaseIdx);
+    }
+
+    /*!
+     * \brief Update all quantities for a given control volume.
+     *
+     * \param sol The solution primary variables
+     * \param problem The problem
+     * \param element The element
+     * \param fvGeometry The current finite volume geometry of the element
+     * \param scvIdx The local index of the SCV (sub-control volume)
+     * \param isOldSol Evaluate function with solution of current or previous time step
+     */
+    void updateEnergy_(const PrimaryVariables &sol,
+                       const Problem &problem,
+                       const Element &element,
+                       const FVElementGeometry &fvGeometry,
+                       const int scvIdx,
+                       bool isOldSol)
+    {
+        // compute and set the heat capacity of the solid phase
+        heatCapacity_ = problem.spatialParams().heatCapacity(element, fvGeometry, scvIdx);
+        Valgrind::CheckDefined(heatCapacity_);
+    };
+
+    Scalar heatCapacity_;
+};
+
+} // end namespace
+
+#endif
diff --git a/dumux/implicit/2p2cni/Makefile.am b/dumux/implicit/2p2cni/Makefile.am
new file mode 100644
index 0000000000..79135402f3
--- /dev/null
+++ b/dumux/implicit/2p2cni/Makefile.am
@@ -0,0 +1,4 @@
+2p2cnidir = $(includedir)/dumux/boxmodels/2p2cni
+2p2cni_HEADERS = *.hh
+
+include $(top_srcdir)/am/global-rules
diff --git a/dumux/implicit/2pdfm/2pdfmfluxvariables.hh b/dumux/implicit/2pdfm/2pdfmfluxvariables.hh
new file mode 100644
index 0000000000..93ca3137d6
--- /dev/null
+++ b/dumux/implicit/2pdfm/2pdfmfluxvariables.hh
@@ -0,0 +1,234 @@
+/*****************************************************************************
+ *   See the file COPYING for full copying permissions.                      *
+ *                                                                           *
+ *   This program is free software: you can redistribute it and/or modify    *
+ *   it under the terms of the GNU General Public License as published by    *
+ *   the Free Software Foundation, either version 2 of the License, or       *
+ *   (at your option) any later version.                                     *
+ *                                                                           *
+ *   This program is distributed in the hope that it will be useful,         *
+ *   but WITHOUT ANY WARRANTY; without even the implied warranty of          *
+ *   MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the            *
+ *   GNU General Public License for more details.                            *
+ *                                                                           *
+ *   You should have received a copy of the GNU General Public License       *
+ *   along with this program. If not, see <http://www.gnu.org/licenses/>.    *
+ *****************************************************************************/
+/*!
+ * \file
+ *
+ * \brief This file contains the data which is required to calculate
+ *        all fluxes of fluid phases over a face of a finite volume in the
+ *        two phase discrete fracture-matrix model.
+ */
+#ifndef DUMUX_BOXMODELS_2PDFM_FLUX_VARIABLES_HH
+#define DUMUX_BOXMODELS_2PDFM_FLUX_VARIABLES_HH
+
+#include <dumux/common/math.hh>
+#include <dumux/common/parameters.hh>
+#include <dumux/common/valgrind.hh>
+#include <dumux/boxmodels/common/boxdarcyfluxvariables.hh>
+
+#include "2pdfmproperties.hh"
+
+namespace Dumux
+{
+
+/*!
+ * \ingroup TwoPDFMBoxModel
+ * \ingroup BoxDFMFluxVariables
+ * \brief Contains the data which is required to calculate the fluxes of 
+ *        the fluid phases over a face of a finite volume for the two-phase
+ *        discrete fracture-matrix model.
+ *
+ * This means pressure and concentration gradients, phase densities at
+ * the intergration point, etc.
+ */
+template <class TypeTag>
+class TwoPDFMFluxVariables : public BoxDarcyFluxVariables<TypeTag>
+{
+    typedef typename GET_PROP_TYPE(TypeTag, Problem) Problem;
+    typedef typename GET_PROP_TYPE(TypeTag, SpatialParams) SpatialParams;
+    typedef typename GET_PROP_TYPE(TypeTag, ElementVolumeVariables) ElementVolumeVariables;
+
+    typedef typename GET_PROP_TYPE(TypeTag, GridView) GridView;
+    typedef typename GridView::template Codim<0>::Entity Element;
+    enum {
+        dim = GridView::dimension,
+        dimWorld = GridView::dimensionworld,
+        numPhases = GET_PROP_VALUE(TypeTag, NumPhases)
+    };
+
+    typedef typename GET_PROP_TYPE(TypeTag, Scalar) Scalar;
+    typedef Dune::FieldVector<Scalar, dimWorld> Vector;
+
+    typedef typename GET_PROP_TYPE(TypeTag, FVElementGeometry) FVElementGeometry;
+    typedef typename FVElementGeometry::SubControlVolumeFace SCVFace;
+    typedef Dune::FieldVector<Scalar, dimWorld> GlobalPosition;
+    typedef Dune::FieldVector<Scalar, dim> LocalPosition;
+    typedef Dune::FieldVector<Scalar, numPhases> PhasesVector;
+
+public:
+    /*!
+     * \brief The constructor
+     *
+     * \param problem The problem
+     * \param element The finite element
+     * \param fvGeometry The finite-volume geometry in the box scheme
+     * \param faceIdx The local index of the SCV (sub-control-volume) face
+     * \param elemVolVars The volume variables of the current element
+     * \param onBoundary A boolean variable to specify whether the flux variables
+     * are calculated for interior SCV faces or boundary faces, default=false
+     */
+    TwoPDFMFluxVariables(const Problem &problem,
+                 const Element &element,
+                 const FVElementGeometry &fvGeometry,
+                 int faceIdx,
+                 const ElementVolumeVariables &elemVolVars,
+                 const bool onBoundary = false)
+        : BoxDarcyFluxVariables<TypeTag>(problem, element, fvGeometry, faceIdx, elemVolVars, onBoundary), 
+          fvGeometry_(fvGeometry), faceIdx_(faceIdx), onBoundary_(onBoundary)
+    {
+        faceSCV_ = &this->face();
+
+        for (int phase = 0; phase < numPhases; ++phase)
+        {
+            potentialGradFracture_[phase] = 0.0;
+        }
+
+        calculateGradientsInFractures_(problem, element, elemVolVars, faceIdx);
+        calculateVelocitiesFracture_(problem, element, elemVolVars, faceIdx);
+    };
+
+public:
+    /*!
+     * \brief Calculates the velocities in the lower-dimenstional fracture.
+     * 
+     * \param problem The problem
+     * \param element The finite element
+     * \param elemVolVars The volume variables of the current element
+     * \param faceIdx The local index of the SCV (sub-control-volume) face
+     */
+    void calculateVelocitiesFracture_(const Problem &problem,
+                                      const Element &element,
+                                      const ElementVolumeVariables &elemVolVars,
+                                      int faceIdx)
+    {
+        isFracture_ = problem.spatialParams().isEdgeFracture(element, faceIdx);
+        fractureWidth_ = problem.spatialParams().fractureWidth(element, faceIdx);
+
+        Scalar KFracture, KFi, KFj; //permeabilities of the fracture
+        if (isFracture_)
+        {
+            KFi = problem.spatialParams().
+                intrinsicPermeabilityFracture(element, this->fvGeometry_, this->face().i);
+            KFj = problem.spatialParams().
+                intrinsicPermeabilityFracture(element, this->fvGeometry_, this->face().j);
+        }
+        else
+        {
+            KFi = 0;
+            KFj = 0;
+        }
+
+        KFracture = Dumux::harmonicMean(KFi, KFj);
+
+        // temporary vector for the Darcy velocity
+        Scalar vDarcyFracture = 0;
+        for (int phase=0; phase < numPhases; phase++)
+        {
+            vDarcyFracture = - (KFracture * potentialGradFracture_[phase]);
+
+            Valgrind::CheckDefined(KFracture);
+            Valgrind::CheckDefined(fractureWidth_);
+            vDarcyFracture_[phase] = (vDarcyFracture * fractureWidth_);
+            Valgrind::CheckDefined(vDarcyFracture_[phase]);
+        }
+
+        // set the upstream and downstream vertices
+        for (int phase = 0; phase < numPhases; ++phase)
+        {
+            upstreamFractureIdx[phase] = faceSCV_->i;
+            downstreamFractureIdx[phase] = faceSCV_->j;
+
+            if (vDarcyFracture_[phase] < 0)
+            {
+                std::swap(upstreamFractureIdx[phase],
+                          downstreamFractureIdx[phase]);
+            }
+        }
+    }
+
+    /*!
+     * \brief Return the pressure potential gradient in the lower dimensional fracture.
+     *
+     * \param phaseIdx The index of the fluid phase
+     */
+    const Scalar &potentialGradFracture(int phaseIdx) const
+    {
+        return potentialGradFracture_[phaseIdx];
+    }
+
+
+    PhasesVector vDarcyFracture_;
+
+    int upstreamFractureIdx[numPhases];
+    int downstreamFractureIdx[numPhases];
+protected:
+    // gradients
+    Scalar potentialGradFracture_[numPhases];
+    const FVElementGeometry &fvGeometry_;
+    int faceIdx_;
+    const bool onBoundary_;
+    bool isFracture_;
+    Scalar fractureWidth_;
+    const SCVFace *faceSCV_;
+
+private:
+    /*!
+     * \brief Calculates the gradients in the lower-dimenstional fracture.
+     * 
+     * \param problem The problem
+     * \param element The finite element
+     * \param elemVolVars The volume variables of the current element
+     * \param faceIdx The local index of the SCV (sub-control-volume) face
+     */
+    void calculateGradientsInFractures_(const Problem &problem,
+                                        const Element &element,
+                                        const ElementVolumeVariables &elemVolVars,
+                                        int faceIdx)
+    {
+        // calculate gradients, loop over adjacent vertices
+        for (int idx = 0; idx < this->fvGeometry_.numFAP; idx++)
+        {
+            int i = this->face().i;
+            int j = this->face().j;
+
+            // compute sum of pressure gradients for each phaseGlobalPosition
+            for (int phase = 0; phase < numPhases; phase++)
+            {
+                const GlobalPosition localIdx_i = element.geometry().corner(i);
+                const GlobalPosition localIdx_j = element.geometry().corner(j);
+
+                isFracture_ = problem.spatialParams().isEdgeFracture(element, faceIdx);
+
+                if (isFracture_)
+                {
+                    GlobalPosition diff_ij = localIdx_j;
+                    diff_ij -= localIdx_i;
+                    potentialGradFracture_[phase] =
+                        (elemVolVars[j].pressure(phase) - elemVolVars[i].pressure(phase))
+                        / diff_ij.two_norm();
+                }
+                else
+                {
+                    potentialGradFracture_[phase] = 0;
+                }
+            }
+        }
+    }
+};
+
+} // end namepace
+
+#endif // DUMUX_BOXMODELS_2PDFM_FLUX_VARIABLES_HH
diff --git a/dumux/implicit/2pdfm/2pdfmindices.hh b/dumux/implicit/2pdfm/2pdfmindices.hh
new file mode 100644
index 0000000000..6326b0508f
--- /dev/null
+++ b/dumux/implicit/2pdfm/2pdfmindices.hh
@@ -0,0 +1,64 @@
+/*****************************************************************************
+ *   See the file COPYING for full copying permissions.                      *
+ *                                                                           *
+ *   This program is free software: you can redistribute it and/or modify    *
+ *   it under the terms of the GNU General Public License as published by    *
+ *   the Free Software Foundation, either version 2 of the License, or       *
+ *   (at your option) any later version.                                     *
+ *                                                                           *
+ *   This program is distributed in the hope that it will be useful,         *
+ *   but WITHOUT ANY WARRANTY; without even the implied warranty of          *
+ *   MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the            *
+ *   GNU General Public License for more details.                            *
+ *                                                                           *
+ *   You should have received a copy of the GNU General Public License       *
+ *   along with this program. If not, see <http://www.gnu.org/licenses/>.    *
+ *****************************************************************************/
+
+/*!
+ * \file
+ *
+ * \brief Defines the indices required for the finite volume in the
+ *        two phase discrete fracture-matrix model.
+ */
+#ifndef DUMUX_BOXMODELS_2PDFM_INDICES_HH
+#define DUMUX_BOXMODELS_2PDFM_INDICES_HH
+
+#include<dumux/boxmodels/2p/2pindices.hh>
+
+namespace Dumux
+{
+// \{
+
+/*!
+ * \ingroup TwoPDFMBoxModel
+ * \ingroup BoxIndices
+ * \brief The common indices for the \f$p_w-S_n\f$ formulation of the
+ *        isothermal two-phase discrete fracture-matrix model.
+ *
+ * \tparam TypeTag The problem type tag
+ * \tparam formulation The formulation, either pwSn or pnSw
+ * \tparam PVOffset The first index in a primary variable vector.
+ */
+template <class TypeTag, 
+          int formulation = TwoPFormulation::pwSn, 
+          int PVOffset = 0>
+struct TwoPDFMIndices : public TwoPIndices <TypeTag, formulation, PVOffset>
+{
+    // Primary variable indices
+    static const int pressureIdx = PVOffset + 0; //!< Index for wetting/non-wetting phase pressure (depending on formulation) in a solution vector
+    static const int saturationIdx = PVOffset + 1; //!< Index of the saturation of the non-wetting/wetting phase
+
+    // indices of the primary variables
+    static const int pwIdx = PVOffset + 0; //!< Pressure index of the wetting phase
+    static const int SnIdx = PVOffset + 1; //!< Saturation index of the wetting phase
+
+    // indices of the equations
+    static const int contiWEqIdx = PVOffset + 0; //!< Index of the continuity equation of the wetting phase
+    static const int contiNEqIdx = PVOffset + 1; //!< Index of the continuity equation of the non-wetting phase
+};
+
+// \}
+} // namespace Dumux
+
+#endif // DUMUX_BOXMODELS_2PDFM_INDICES_HH
diff --git a/dumux/implicit/2pdfm/2pdfmlocalresidual.hh b/dumux/implicit/2pdfm/2pdfmlocalresidual.hh
new file mode 100644
index 0000000000..3ab534a7b2
--- /dev/null
+++ b/dumux/implicit/2pdfm/2pdfmlocalresidual.hh
@@ -0,0 +1,335 @@
+/*****************************************************************************
+ *   See the file COPYING for full copying permissions.                      *
+ *                                                                           *
+ *   This program is free software: you can redistribute it and/or modify    *
+ *   it under the terms of the GNU General Public License as published by    *
+ *   the Free Software Foundation, either version 2 of the License, or       *
+ *   (at your option) any later version.                                     *
+ *                                                                           *
+ *   This program is distributed in the hope that it will be useful,         *
+ *   but WITHOUT ANY WARRANTY; without even the implied warranty of          *
+ *   MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the            *
+ *   GNU General Public License for more details.                            *
+ *                                                                           *
+ *   You should have received a copy of the GNU General Public License       *
+ *   along with this program. If not, see <http://www.gnu.org/licenses/>.    *
+ *****************************************************************************/
+/*!
+ * \file
+ *
+ * \brief Element-wise calculation of the residual for the finite volume in the
+ *        two phase discrete fracture-matrix model.
+ */
+#ifndef DUMUX_BOXMODELS_2PDFM_LOCAL_RESIDUAL_HH
+#define DUMUX_BOXMODELS_2PDFM_LOCAL_RESIDUAL_HH
+
+#include <dumux/boxmodels/2p/2plocalresidual.hh>
+#include "2pdfmproperties.hh"
+
+namespace Dumux
+{
+/*!
+ * \ingroup TwoPDFMBoxModel
+ * \ingroup BoxLocalResidual
+ * \brief Element-wise calculation of the Jacobian matrix for problems
+ *        using the two-phase discrete fracture box model.
+ */
+template<class TypeTag>
+class TwoPDFMLocalResidual : public TwoPLocalResidual<TypeTag>
+{
+protected:
+    typedef TwoPLocalResidual<TypeTag> ParentType;
+    typedef typename GET_PROP_TYPE(TypeTag, LocalResidual) Implementation;
+    typedef typename GET_PROP_TYPE(TypeTag, PrimaryVariables) PrimaryVariables;
+    typedef typename GET_PROP_TYPE(TypeTag, VolumeVariables) VolumeVariables;
+    typedef typename GET_PROP_TYPE(TypeTag, FluxVariables) FluxVariables;
+    typedef typename GET_PROP_TYPE(TypeTag, ElementVolumeVariables) ElementVolumeVariables;
+
+    typedef typename GET_PROP_TYPE(TypeTag, Indices) Indices;
+    enum
+    {
+        contiWEqIdx = Indices::contiWEqIdx,
+        contiNEqIdx = Indices::contiNEqIdx,
+        wPhaseIdx = Indices::wPhaseIdx,
+        nPhaseIdx = Indices::nPhaseIdx,
+        numPhases = GET_PROP_VALUE(TypeTag, NumPhases)
+    };
+    typedef typename GET_PROP_TYPE(TypeTag, GridView) GridView;
+    typedef Dune::UGGrid<2> GridType;
+    typedef typename GridType::ctype DT;
+    enum {
+        dim = GridView::dimension,
+        dimWorld = GridView::dimensionworld
+    };
+    typedef typename GridView::template Codim<0>::Entity Element;
+    typedef typename GridView::template Codim<0>::Iterator ElementIterator;
+    typedef typename GridView::template Codim<dim>::Entity Vertex;
+    typedef typename GridView::template Codim<dim>::Iterator VertexIterator;
+    typedef typename GET_PROP_TYPE(TypeTag, FVElementGeometry) FVElementGeometry;
+    typedef typename FVElementGeometry::SubControlVolumeFace SCVFace;
+
+    typedef typename GET_PROP_TYPE(TypeTag, Scalar) Scalar;
+    typedef Dune::FieldVector<Scalar, dimWorld> Vector;
+
+    typedef Dune::FieldVector<Scalar, dim> LocalPosition;
+    typedef Dune::FieldVector<Scalar, dimWorld> GlobalPosition;
+
+public:
+    /*!
+     * \brief Constructor. Sets the upwind weight.
+     */
+    TwoPDFMLocalResidual()
+    {
+        // retrieve the upwind weight for the mass conservation equations. Use the value
+        // specified via the property system as default, and overwrite
+        // it by the run-time parameter from the Dune::ParameterTree
+        massUpwindWeight_ = GET_PARAM_FROM_GROUP(TypeTag, Scalar, Implicit, MassUpwindWeight);
+    };
+
+    /*!
+     * \brief Evaluate the amount all conservation quantities
+     *        (e.g. phase mass) within a finite sub-control volume.
+     *
+     *  \param storage The phase mass within the sub-control volume
+     *  \param scvIdx The SCV (sub-control-volume) index
+     *  \param usePrevSol Evaluate function with solution of current or previous time step
+     */
+    void computeStorage(PrimaryVariables &storage, int scvIdx, bool usePrevSol) const
+    {
+        // if flag usePrevSol is set, the solution from the previous
+        // time step is used, otherwise the current solution is
+        // used. The secondary variables are used accordingly.  This
+        // is required to compute the derivative of the storage term
+        // using the implicit Euler method.
+        ParentType::computeStorage(storage,scvIdx,usePrevSol);
+        computeStorageFracture(storage,scvIdx,usePrevSol);
+    }
+
+    /*!
+     * \brief Evaluate the storage term of the current solution in a
+     *        lower-dimensional fracture.
+     *
+     *  \param storage The phase mass within the sub-control volume
+     *  \param scvIdx The SCV (sub-control-volume) index
+     *  \param usePrevSol Evaluate function with solution of current or previous time step
+     */
+    void computeStorageFracture(PrimaryVariables &storage, int scvIdx, bool usePrevSol) const
+    {
+        const ElementVolumeVariables &elemDat = usePrevSol ? this->prevVolVars_()
+                        : this->curVolVars_();
+        const VolumeVariables &vertDat = elemDat[scvIdx];
+        const Element &elem = this->element_();
+        bool isFracture = this->problem_().spatialParams().isVertexFracture(elem, scvIdx);
+        /*
+         * Sn = w_F * SnF + w_M * SnM
+         * First simple case before determining the real w_F is to assume that it is 0
+         * and w_M = 1
+         *
+         */
+        ///////////////////////////////////////////////////////////////////////
+        Scalar w_F, w_M; //volumetric fractions of fracture and matrix;
+        Scalar fractureVolume = 0.0;
+        w_F = 0.0;
+        /*
+         * Calculate the fracture volume fraction w_F = 0.5 * Fwidth * 0.5 * Length
+         */
+        Dune::GeometryType gt = elem.geometry().type();
+        const typename Dune::GenericReferenceElementContainer<DT,dim>::value_type&
+            refElem = Dune::GenericReferenceElements<DT,dim>::general(gt);
+
+        Scalar vol; //subcontrol volume
+        FVElementGeometry fvelem = this->fvGeometry_();
+        vol = fvelem.subContVol[scvIdx].volume;
+        for (int faceIdx=0; faceIdx<refElem.size(1); faceIdx++)
+        {
+            SCVFace face = fvelem.subContVolFace[faceIdx];
+            int i=face.i;
+            int j=face.j;
+
+            if (this->problem_().spatialParams().isEdgeFracture(elem, faceIdx)
+                    && (i == scvIdx || j == scvIdx))
+            {
+                Scalar fracture_width = this->problem_().spatialParams().fractureWidth(elem, faceIdx);
+
+                const GlobalPosition global_i = elem.geometry().corner(i);
+                const GlobalPosition global_j = elem.geometry().corner(j);
+                GlobalPosition diff_ij = global_j;
+                diff_ij -=global_i;
+                Scalar fracture_length = 0.5*diff_ij.two_norm();
+                //half is taken from the other element
+                fractureVolume += 0.5 * fracture_length * fracture_width;
+            }
+        }
+        w_F = fractureVolume/vol;
+        w_M = 1-w_F;
+        ///////////////////////////////////////////////////////////////////////
+        Scalar storageFracture[numPhases];
+        Scalar storageMatrix [numPhases];
+        storageFracture[wPhaseIdx]    = 0.0;
+        storageFracture[nPhaseIdx]    = 0.0;
+        storageMatrix[wPhaseIdx]    = 0.0;
+        storageMatrix[nPhaseIdx]    = 0.0;
+        //        const GlobalPosition &globalPos = elem.geometry().corner(scvIdx);
+
+        Scalar dSM_dSF = vertDat.dSM_dSF();
+        if (!this->problem_().useInterfaceCondition())
+        {
+            dSM_dSF = 1.0;
+        }
+
+        if (isFracture)
+        {
+            for (int phaseIdx = 0; phaseIdx<2; phaseIdx++)
+            {
+                storageFracture[phaseIdx] = vertDat.density(phaseIdx)
+                                        * vertDat.porosityFracture()
+                                        * w_F
+                                        * vertDat.saturationFracture(phaseIdx);
+                storageMatrix[phaseIdx] = vertDat.density(phaseIdx)
+                                        * vertDat.porosity()
+                                        * w_M
+                                        * dSM_dSF
+                                        * vertDat.saturationMatrix(phaseIdx);
+            }
+        }
+        else
+        {
+            for (int phaseIdx = 0; phaseIdx < 2; phaseIdx++)
+            {
+                storageFracture[phaseIdx] = 0.0;
+                storageMatrix[phaseIdx] = vertDat.density(phaseIdx)
+                                        * vertDat.porosity()
+                                        * vertDat.saturation(phaseIdx);
+            }
+
+        }
+        // wetting phase mass
+        storage[contiWEqIdx] =  storageFracture[wPhaseIdx]
+                            + storageMatrix[wPhaseIdx];
+
+        // non-wetting phase mass
+        storage[contiNEqIdx] =  storageFracture[nPhaseIdx]
+                            + storageMatrix[nPhaseIdx];
+    }
+
+    /*!
+     * \brief Evaluates the mass flux over a face of a sub-control
+     *        volume.
+     *
+     * \param flux The flux over the SCV (sub-control-volume) face for each phase
+     * \param faceIdx The index of the SCV face
+     * \param onBoundary A boolean variable to specify whether the flux variables
+     *        are calculated for interior SCV faces or boundary faces, default=false
+     */
+    void computeFlux(PrimaryVariables &flux, int faceIdx, const bool onBoundary=false) const
+    {
+        FluxVariables fluxVars(this->problem_(),
+                           this->element_(),
+                           this->fvGeometry_(),
+                           faceIdx,
+                           this->curVolVars_(),
+                           onBoundary);
+        flux = 0;
+        asImp_()->computeAdvectiveFlux(flux, fluxVars);
+        asImp_()->computeAdvectiveFluxFracture(flux, fluxVars);
+        asImp_()->computeDiffusiveFlux(flux, fluxVars);
+        asImp_()->computeDiffusiveFluxFracture(flux, fluxVars);
+    }
+
+    /*!
+     * \brief Adds the flux vector in the lower dimensional fracture to the
+     *        flux vector over the face of a sub-control volume.
+     *
+     * This method is called by compute flux and is mainly there for
+     * derived models to ease adding equations selectively.
+     *
+     * \param flux The advective flux over the sub-control-volume face for each phase
+     * \param fluxVars The flux variables at the current SCV
+     */
+    void computeAdvectiveFluxFracture(PrimaryVariables &flux, const FluxVariables &fluxVars) const
+    {
+        ////////
+        // advective fluxes of all components in all phases
+        ////////
+        Vector tmpVec;
+        for (int phaseIdx = 0; phaseIdx < numPhases; ++phaseIdx)
+        {
+            // calculate the flux in direction of the
+            // current fracture
+            //
+            // v = - (K grad p) * n
+            //
+            // (the minus comes from the Darcy law which states that
+            // the flux is from high to low pressure potentials.)
+
+            // data attached to upstream and the downstream vertices
+            // of the current phase
+            const VolumeVariables &upFracture =
+                    this->curVolVars_(fluxVars.upstreamFractureIdx[phaseIdx]);
+            const VolumeVariables &dnFracture =
+                    this->curVolVars_(fluxVars.downstreamFractureIdx[phaseIdx]);
+
+            Scalar fractureFlux =
+                          0.5 * fluxVars.vDarcyFracture_[phaseIdx]
+                              * ( massUpwindWeight_ // upstream vertex
+                                 *  (upFracture.density(phaseIdx)
+                                    * upFracture.mobilityFracture(phaseIdx))
+                                 + (1 - massUpwindWeight_) // downstream vertex
+                                    * (dnFracture.density(phaseIdx)
+                                      * dnFracture.mobilityFracture(phaseIdx)));
+
+            flux[phaseIdx] += fractureFlux;
+        }
+    }
+
+    /*!
+     * \brief Adds the diffusive flux of the fracture to the flux vector over
+     *        the face of a sub-control volume.
+     *
+     * \param flux The diffusive flux over the sub-control-volume face for each phase
+     * \param fluxData The flux variables at the current SCV
+     *
+     * It doesn't do anything in two-phase model but is used by the
+     * non-isothermal two-phase models to calculate diffusive heat
+     * fluxes
+     */
+    void computeDiffusiveFluxFracture(PrimaryVariables &flux, const FluxVariables &fluxData) const
+    {
+        // diffusive fluxes
+        flux += 0.0;
+    }
+
+    /*!
+     * \brief Calculate the source term of the equation
+     *
+     * \param source The source/sink in the SCV for each phase
+     * \param scvIdx The index of the SCV
+     *
+     */
+    void computeSource(PrimaryVariables &source, int scvIdx) const
+    {
+        // retrieve the source term intrinsic to the problem
+        this->problem_().boxSDSource(source,
+                                     this->element_(),
+                                     this->fvGeometry_(),
+                                     scvIdx,
+                                     this->curVolVars_());
+    }
+
+protected:
+    Implementation *asImp_()
+    {
+        return static_cast<Implementation *> (this);
+    }
+    const Implementation *asImp_() const
+    {
+        return static_cast<const Implementation *> (this);
+    }
+
+private:
+    Scalar massUpwindWeight_;
+};
+
+} // end namespace
+
+#endif // DUMUX_BOXMODELS_2PDFM_LOCAL_RESIDUAL_HH
diff --git a/dumux/implicit/2pdfm/2pdfmmodel.hh b/dumux/implicit/2pdfm/2pdfmmodel.hh
new file mode 100644
index 0000000000..07b9c92fd0
--- /dev/null
+++ b/dumux/implicit/2pdfm/2pdfmmodel.hh
@@ -0,0 +1,390 @@
+/*****************************************************************************
+ *   See the file COPYING for full copying permissions.                      *
+ *                                                                           *
+ *   This program is free software: you can redistribute it and/or modify    *
+ *   it under the terms of the GNU General Public License as published by    *
+ *   the Free Software Foundation, either version 2 of the License, or       *
+ *   (at your option) any later version.                                     *
+ *                                                                           *
+ *   This program is distributed in the hope that it will be useful,         *
+ *   but WITHOUT ANY WARRANTY; without even the implied warranty of          *
+ *   MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the            *
+ *   GNU General Public License for more details.                            *
+ *                                                                           *
+ *   You should have received a copy of the GNU General Public License       *
+ *   along with this program. If not, see <http://www.gnu.org/licenses/>.    *
+ *****************************************************************************/
+
+/*!
+* \file
+*
+* \brief Adaption of the box scheme to the two-phase flow in discrete fracture-matrix 
+*        model.
+*/
+
+#ifndef DUMUX_BOXMODELS_2PDFM_MODEL_HH
+#define DUMUX_BOXMODELS_2PDFM_MODEL_HH
+
+#include <dumux/boxmodels/2p/2pmodel.hh>
+
+#include "2pdfmproperties.hh"
+#include "2pdfmlocalresidual.hh"
+#include "2pdfmproblem.hh"
+
+namespace Dumux
+{
+
+/*!
+ * \ingroup TwoPDFMBoxModel
+ * \brief A two-phase, isothermal flow model using the box scheme.
+ *
+ * This model implements two-phase flow of two immiscible fluids
+ * \f$\alpha \in \{ w, n \}\f$ using a standard multiphase Darcy
+ * approach as the equation for the conservation of momentum, i.e.
+ \f[
+ v_\alpha = - \frac{k_{r\alpha}}{\mu_\alpha} \textbf{K}
+ \left(\textbf{grad}\, p_\alpha - \varrho_{\alpha} {\textbf g} \right)
+ \f]
+ *
+ * By inserting this into the equation for the conservation of the
+ * phase mass, one gets
+ \f[
+ \phi \frac{\partial \varrho_\alpha S_\alpha}{\partial t}
+ -
+ \text{div} \left\{
+ \varrho_\alpha \frac{k_{r\alpha}}{\mu_\alpha} \mbox{\bf K} \left(\textbf{grad}\, p_\alpha - \varrho_{\alpha} \mbox{\bf g} \right)
+ \right\} - q_\alpha = 0 \;,
+ \f]
+ *
+ * These equations are discretized by a fully-coupled vertex centered finite volume
+ * (box) scheme as spatial and the implicit Euler method as time
+ * discretization.
+ *
+ * By using constitutive relations for the capillary pressure \f$p_c =
+ * p_n - p_w\f$ and relative permeability \f$k_{r\alpha}\f$ and taking
+ * advantage of the fact that \f$S_w + S_n = 1\f$, the number of
+ * unknowns can be reduced to two. Currently the model supports
+ * choosing either \f$p_w\f$ and \f$S_n\f$ or \f$p_n\f$ and \f$S_w\f$
+ * as primary variables. The formulation which ought to be used can be
+ * specified by setting the <tt>Formulation</tt> property to either
+ * <tt>TwoPCommonIndices::pWsN</tt> or <tt>TwoPCommonIndices::pNsW</tt>. By
+ * default, the model uses \f$p_w\f$ and \f$S_n\f$.
+ */
+template<class TypeTag >
+class TwoPDFMModel : public TwoPModel<TypeTag>
+{
+    typedef TwoPModel<TypeTag> ParentType;
+    typedef typename GET_PROP_TYPE(TypeTag, FVElementGeometry) FVElementGeometry;
+    typedef typename GET_PROP_TYPE(TypeTag, VolumeVariables) VolumeVariables;
+    typedef typename GET_PROP_TYPE(TypeTag, SolutionVector) SolutionVector;
+    typedef typename GET_PROP_TYPE(TypeTag, FluxVariables) FluxVariables;
+    typedef typename GET_PROP_TYPE(TypeTag, ElementVolumeVariables) ElementVolumeVariables;
+
+    typedef typename GET_PROP_TYPE(TypeTag, Indices) Indices;
+    enum {
+        nPhaseIdx = Indices::nPhaseIdx,
+        wPhaseIdx = Indices::wPhaseIdx,
+        pressureIdx = Indices::pressureIdx,
+        numPhases = GET_PROP_VALUE(TypeTag, NumPhases)
+    };
+
+    typedef typename GET_PROP_TYPE(TypeTag, GridView) GridView;
+    typedef typename GridView::template Codim<0>::Entity Element;
+    typedef typename GridView::template Codim<0>::Iterator ElementIterator;
+    typedef typename GridView::ctype CoordScalar;
+    enum {
+        dim = GridView::dimension,
+        dimWorld = GridView::dimensionworld
+    };
+
+    typedef typename GET_PROP_TYPE(TypeTag, Scalar) Scalar;
+    typedef Dune::FieldVector<Scalar, numPhases> PhasesVector;
+    typedef Dune::FieldVector<Scalar, dimWorld> GlobalPosition;
+
+public:
+    /*!
+     * \brief Returns the relative weight of a primary variable for
+     *        calculating relative errors.
+     *
+     * \param globalIdx The global index of the vertex
+     * \param pvIdx The index of the primary variable
+     */
+    DUNE_DEPRECATED
+    Scalar primaryVarWeight(int globalIdx, int pvIdx) const
+    {
+        if (pressureIdx == pvIdx)
+        {
+            return std::min(10.0 / this->prevSol()[globalIdx][pvIdx], 1.0);
+        }
+        
+        return 1.0;
+    }
+
+    /*!
+     * \brief Append all quantities of interest which can be derived
+     *        from the solution of the current time step to the VTK
+     *        writer.
+     *
+     * \param sol The global solution vector
+     * \param writer The writer for multi-file VTK datasets
+     */
+    template<class MultiWriter>
+    void addOutputVtkFields(const SolutionVector &sol, MultiWriter &writer)
+    {
+        bool velocityOutput = GET_PARAM_FROM_GROUP(TypeTag, bool, Vtk, AddVelocity);
+        typedef Dune::BlockVector<Dune::FieldVector<double, 1> > ScalarField;
+        typedef Dune::BlockVector<Dune::FieldVector<double, dim> > VectorField;
+
+        // get the number of degrees of freedom and the number of vertices
+        unsigned numDofs = this->numDofs();
+        unsigned numVertices = this->problem_().gridView().size(dim);
+    
+        // velocity output currently only works for vertex data
+        if (numDofs != numVertices)
+        {
+            velocityOutput = false;
+        }
+    
+        // create the required scalar fields
+        ScalarField *pW = writer.allocateManagedBuffer(numDofs);
+        ScalarField *pN = writer.allocateManagedBuffer(numDofs);
+        ScalarField *pC = writer.allocateManagedBuffer(numDofs);
+        ScalarField *Sw = writer.allocateManagedBuffer(numDofs);
+        ScalarField *Sn = writer.allocateManagedBuffer(numDofs);
+        ScalarField *rhoW = writer.allocateManagedBuffer(numDofs);
+        ScalarField *rhoN = writer.allocateManagedBuffer(numDofs);
+        ScalarField *mobW = writer.allocateManagedBuffer(numDofs);
+        ScalarField *mobN = writer.allocateManagedBuffer(numDofs);
+        ScalarField *poro = writer.allocateManagedBuffer(numDofs);
+        ScalarField *Te = writer.allocateManagedBuffer(numDofs);
+        ScalarField *cellNum =writer.allocateManagedBuffer (numDofs);
+        VectorField *velocityN = writer.template allocateManagedBuffer<double, dim>(numDofs);
+        VectorField *velocityW = writer.template allocateManagedBuffer<double, dim>(numDofs);
+
+        if(velocityOutput) // check if velocity output is demanded
+        {
+            // initialize velocity fields
+            for (unsigned int i = 0; i < numVertices; ++i)
+            {
+                (*velocityN)[i] = Scalar(0);
+                (*velocityW)[i] = Scalar(0);
+                (*cellNum)[i] = Scalar(0.0);
+            }
+        }
+        unsigned numElements = this->gridView_().size(0);
+        ScalarField *rank = writer.allocateManagedBuffer(numElements);
+
+        FVElementGeometry fvGeometry;
+        VolumeVariables volVars;
+        ElementVolumeVariables elemVolVars;
+
+        ElementIterator elemIt = this->gridView_().template begin<0>();
+        ElementIterator elemEndIt = this->gridView_().template end<0>();
+        for (; elemIt != elemEndIt; ++elemIt)
+        {
+            if(velocityOutput && !elemIt->geometry().type().isCube()){
+                DUNE_THROW(Dune::InvalidStateException,
+                           "Currently, velocity output only works for cubes. "
+                           "Please set the EnableVelocityOutput property to false!");
+            }
+            int idx = this->elementMapper().map(*elemIt);
+            (*rank)[idx] = this->gridView_().comm().rank();
+
+            fvGeometry.update(this->gridView_(), *elemIt);
+
+            if (numDofs == numElements) // element data
+            {
+                volVars.update(sol[idx],
+                               this->problem_(),
+                               *elemIt,
+                               fvGeometry,
+                               /*scvIdx=*/0,
+                               false);
+
+                (*pW)[idx] = volVars.pressure(wPhaseIdx);
+                (*pN)[idx] = volVars.pressure(nPhaseIdx);
+                (*pC)[idx] = volVars.capillaryPressure();
+                (*Sw)[idx] = volVars.saturation(wPhaseIdx);
+                (*Sn)[idx] = volVars.saturation(nPhaseIdx);
+                (*rhoW)[idx] = volVars.density(wPhaseIdx);
+                (*rhoN)[idx] = volVars.density(nPhaseIdx);
+                (*mobW)[idx] = volVars.mobility(wPhaseIdx);
+                (*mobN)[idx] = volVars.mobility(nPhaseIdx);
+                (*poro)[idx] = volVars.porosity();
+                (*Te)[idx] = volVars.temperature();
+            }
+            else // vertex data
+            {
+                int numVerts = elemIt->template count<dim> ();
+                for (int scvIdx = 0; scvIdx < numVerts; ++scvIdx)
+                {
+                    int globalIdx = this->vertexMapper().map(*elemIt, scvIdx, dim);
+                    volVars.update(sol[globalIdx],
+                                   this->problem_(),
+                                   *elemIt,
+                                   fvGeometry,
+                                   scvIdx,
+                                   false);
+
+                    (*pW)[globalIdx] = volVars.pressure(wPhaseIdx);
+                    (*pN)[globalIdx] = volVars.pressure(nPhaseIdx);
+                    (*pC)[globalIdx] = volVars.capillaryPressure();
+                    (*Sw)[globalIdx] = volVars.saturation(wPhaseIdx);
+                    (*Sn)[globalIdx] = volVars.saturation(nPhaseIdx);
+                    (*rhoW)[globalIdx] = volVars.density(wPhaseIdx);
+                    (*rhoN)[globalIdx] = volVars.density(nPhaseIdx);
+                    (*mobW)[globalIdx] = volVars.mobility(wPhaseIdx);
+                    (*mobN)[globalIdx] = volVars.mobility(nPhaseIdx);
+                    (*poro)[globalIdx] = volVars.porosity();
+                    (*Te)[globalIdx] = volVars.temperature();
+                    if(velocityOutput)
+                    {
+                        (*cellNum)[globalIdx] += 1;
+                    }
+                }
+
+                if(velocityOutput)
+                {
+                    // calculate vertex velocities
+                    GlobalPosition tmpVelocity[numPhases];
+
+                    for(int phaseIdx = 0; phaseIdx < numPhases; ++phaseIdx)
+                    {
+                        tmpVelocity[phaseIdx]  = Scalar(0.0);
+                    }
+
+                    typedef Dune::BlockVector<Dune::FieldVector<Scalar, dim> > SCVVelocities;
+                    SCVVelocities scvVelocityW(8), scvVelocityN(8);
+
+                    scvVelocityW = 0;
+                    scvVelocityN = 0;
+
+                    ElementVolumeVariables elemVolVars;
+
+                    elemVolVars.update(this->problem_(),
+                                       *elemIt,
+                                       fvGeometry,
+                                       false /* oldSol? */);
+
+                    for (int faceIdx = 0; faceIdx < fvGeometry.numEdges; faceIdx++)
+                    {
+                        FluxVariables fluxVars(this->problem_(),
+                                             *elemIt,
+                                             fvGeometry,
+                                             faceIdx,
+                                             elemVolVars);
+
+                        for (int phaseIdx = 0; phaseIdx < numPhases; ++phaseIdx)
+                        {
+                            // local position of integration point
+                            const Dune::FieldVector<Scalar, dim>& localPosIP = fvGeometry.subContVolFace[faceIdx].ipLocal;
+
+                            // Transformation of the global normal vector to normal vector in the reference element
+                            const typename Element::Geometry::JacobianTransposed& jacobianT1 = 
+                                elemIt->geometry().jacobianTransposed(localPosIP);
+
+                            const GlobalPosition globalNormal = fluxVars.face().normal;
+                            GlobalPosition localNormal;
+                            jacobianT1.mv(globalNormal, localNormal);
+                            // note only works for cubes
+                            const Scalar localArea = pow(2,-(dim-1));
+
+                            localNormal /= localNormal.two_norm();
+
+                            // Get the Darcy velocities. The Darcy velocities are divided by the area of the subcontrolvolumeface
+                            // in the reference element.
+                            PhasesVector q;
+                            q[phaseIdx] = fluxVars.volumeFlux(phaseIdx) / localArea;
+
+                            // transform the normal Darcy velocity into a vector
+                            tmpVelocity[phaseIdx] = localNormal;
+                            tmpVelocity[phaseIdx] *= q[phaseIdx];
+
+                            if(phaseIdx == wPhaseIdx)
+                            {
+                                scvVelocityW[fluxVars.face().i] += tmpVelocity[phaseIdx];
+                                scvVelocityW[fluxVars.face().j] += tmpVelocity[phaseIdx];
+                            }
+                            else if(phaseIdx == nPhaseIdx)
+                            {
+                                scvVelocityN[fluxVars.face().i] += tmpVelocity[phaseIdx];
+                                scvVelocityN[fluxVars.face().j] += tmpVelocity[phaseIdx];
+                            }
+                        }
+                    }
+                    typedef Dune::GenericReferenceElements<Scalar, dim> ReferenceElements;
+                    const Dune::FieldVector<Scalar, dim> &localPos
+                        = ReferenceElements::general(elemIt->geometry().type()).position(0, 0);
+
+                    // get the transposed Jacobian of the element mapping
+                    const typename Element::Geometry::JacobianTransposed& jacobianT2
+                        = elemIt->geometry().jacobianTransposed(localPos);
+
+                    // transform vertex velocities from local to global coordinates
+                    for (int i = 0; i < numVerts; ++i)
+                    {
+                        int globalIdx = this->vertexMapper().map(*elemIt, i, dim);
+                        // calculate the subcontrolvolume velocity by the Piola transformation
+                        Dune::FieldVector<CoordScalar, dim> scvVelocity(0);
+
+                        jacobianT2.mtv(scvVelocityW[i], scvVelocity);
+                        scvVelocity /= elemIt->geometry().integrationElement(localPos);
+                        // add up the wetting phase subcontrolvolume velocities for each vertex
+                        (*velocityW)[globalIdx] += scvVelocity;
+
+                        jacobianT2.mtv(scvVelocityN[i], scvVelocity);
+                        scvVelocity /= elemIt->geometry().integrationElement(localPos);
+                        // add up the nonwetting phase subcontrolvolume velocities for each vertex
+                        (*velocityN)[globalIdx] += scvVelocity;
+                    }
+                }
+            }
+        }
+
+        if (numDofs == numElements) // element data
+        {
+            writer.attachCellData(*Sn, "Sn");
+            writer.attachCellData(*Sw, "Sw");
+            writer.attachCellData(*pN, "pn");
+            writer.attachCellData(*pW, "pw");
+            writer.attachCellData(*pC, "pc");
+            writer.attachCellData(*rhoW, "rhoW");
+            writer.attachCellData(*rhoN, "rhoN");
+            writer.attachCellData(*mobW, "mobW");
+            writer.attachCellData(*mobN, "mobN");
+            writer.attachCellData(*poro, "porosity");
+            writer.attachCellData(*Te, "temperature");
+        }
+        else // vertex data
+        {
+            writer.attachVertexData(*Sn, "Sn");
+            writer.attachVertexData(*Sw, "Sw");
+            writer.attachVertexData(*pN, "pn");
+            writer.attachVertexData(*pW, "pw");
+            writer.attachVertexData(*pC, "pc");
+            writer.attachVertexData(*rhoW, "rhoW");
+            writer.attachVertexData(*rhoN, "rhoN");
+            writer.attachVertexData(*mobW, "mobW");
+            writer.attachVertexData(*mobN, "mobN");
+            writer.attachVertexData(*poro, "porosity");
+            writer.attachVertexData(*Te, "temperature");
+            if(velocityOutput) // check if velocity output is demanded
+            {
+                // divide the vertex velocities by the number of adjacent scvs i.e. cells
+                for(unsigned int globalIdx = 0; globalIdx < numVertices; ++globalIdx)
+                {
+                    (*velocityW)[globalIdx] /= (*cellNum)[globalIdx];
+                    (*velocityN)[globalIdx] /= (*cellNum)[globalIdx];
+                }
+                writer.attachVertexData(*velocityW,  "velocityW", dim);
+                writer.attachVertexData(*velocityN,  "velocityN", dim);
+            }
+        }
+        writer.attachCellData(*rank, "process rank");
+    }
+};
+} // end namespace
+
+#include "2pdfmpropertydefaults.hh"
+
+#endif // DUMUX_BOXMODELS_2PDFM_MODEL_HH
diff --git a/dumux/implicit/2pdfm/2pdfmproblem.hh b/dumux/implicit/2pdfm/2pdfmproblem.hh
new file mode 100644
index 0000000000..fd65e2b68d
--- /dev/null
+++ b/dumux/implicit/2pdfm/2pdfmproblem.hh
@@ -0,0 +1,79 @@
+/*****************************************************************************
+ *   See the file COPYING for full copying permissions.                      *
+ *                                                                           *
+ *   This program is free software: you can redistribute it and/or modify    *
+ *   it under the terms of the GNU General Public License as published by    *
+ *   the Free Software Foundation, either version 2 of the License, or       *
+ *   (at your option) any later version.                                     *
+ *                                                                           *
+ *   This program is distributed in the hope that it will be useful,         *
+ *   but WITHOUT ANY WARRANTY; without even the implied warranty of          *
+ *   MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the            *
+ *   GNU General Public License for more details.                            *
+ *                                                                           *
+ *   You should have received a copy of the GNU General Public License       *
+ *   along with this program. If not, see <http://www.gnu.org/licenses/>.    *
+ *****************************************************************************/
+/*!
+ * \file
+ * \brief Base class for all problems which use the two-phase DFM box model
+ */
+#ifndef DUMUX_BOXMODELS_2PDFM_PROBLEM_HH
+#define DUMUX_BOXMODELS_2PDFM_PROBLEM_HH
+
+#include <dumux/boxmodels/common/porousmediaboxproblem.hh>
+#include "2pdfmproperties.hh"
+
+namespace Dumux
+{
+/*!
+ * \ingroup BoxBaseProblems
+ * \ingroup TwoPBoxModel
+ * \brief Base class for all problems which use the two-phase box model
+ */
+template<class TypeTag>
+class TwoPDFMProblem : public PorousMediaBoxProblem<TypeTag>
+{
+    typedef PorousMediaBoxProblem<TypeTag> ParentType;
+
+    typedef typename GET_PROP_TYPE(TypeTag, TimeManager) TimeManager;
+    typedef typename GET_PROP_TYPE(TypeTag, GridView) GridView;
+    typedef typename GET_PROP_TYPE(TypeTag, SpatialParams) SpatialParams;
+
+public:
+    /*!
+     * \brief The constructor
+     *
+     * \param timeManager The time manager
+     * \param gridView The grid view
+     * \param verbose Turn verbosity on or off
+     */
+    DUNE_DEPRECATED_MSG("use PorousMediaBoxProblem instead")
+    TwoPDFMProblem(TimeManager &timeManager,
+                const GridView &gridView,
+                bool verbose = true)
+        : ParentType(timeManager, gridView)
+    {}
+
+    /*!
+     * \brief The constructor
+     *
+     * \param timeManager The time manager
+     * \param gridView The grid view
+     * \param spatialParams The spatial parameters object
+     * \param verbose Turn verbosity on or off
+     */
+    TwoPDFMProblem(TimeManager &timeManager,
+                const GridView &gridView,
+                SpatialParams &spatialParams,
+                bool verbose = true)
+        : ParentType(timeManager, gridView)
+    {
+        this->newSpatialParams_ = false;
+    delete this->spatialParams_;
+    this->spatialParams_ = &spatialParams;
+    }
+};
+} // end namespace
+
+#endif // DUMUX_BOXMODELS_2PDFM_PROBLEM_HH
diff --git a/dumux/implicit/2pdfm/2pdfmproperties.hh b/dumux/implicit/2pdfm/2pdfmproperties.hh
new file mode 100644
index 0000000000..7d0d2631e0
--- /dev/null
+++ b/dumux/implicit/2pdfm/2pdfmproperties.hh
@@ -0,0 +1,69 @@
+/*****************************************************************************
+ *   See the file COPYING for full copying permissions.                      *
+ *                                                                           *
+ *   This program is free software: you can redistribute it and/or modify    *
+ *   it under the terms of the GNU General Public License as published by    *
+ *   the Free Software Foundation, either version 2 of the License, or       *
+ *   (at your option) any later version.                                     *
+ *                                                                           *
+ *   This program is distributed in the hope that it will be useful,         *
+ *   but WITHOUT ANY WARRANTY; without even the implied warranty of          *
+ *   MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the            *
+ *   GNU General Public License for more details.                            *
+ *                                                                           *
+ *   You should have received a copy of the GNU General Public License       *
+ *   along with this program. If not, see <http://www.gnu.org/licenses/>.    *
+ *****************************************************************************/
+/*!
+ * \file
+ *
+ * \brief Defines the properties required for the two phase DFM BOX model.
+ * 
+ * \ingroup Properties
+ * \ingroup BoxProperties
+ * \ingroup TwoPDFMBoxModel
+ */
+
+#ifndef DUMUX_BOXMODELS_2PDFM_PROPERTIES_HH
+#define DUMUX_BOXMODELS_2PDFM_PROPERTIES_HH
+
+#include <dumux/boxmodels/common/boxproperties.hh>
+
+namespace Dumux
+{
+
+////////////////////////////////
+// properties
+////////////////////////////////
+namespace Properties
+{
+
+//////////////////////////////////////////////////////////////////
+// Type tags
+//////////////////////////////////////////////////////////////////
+
+//! The type tag for 2pDFM problems
+NEW_TYPE_TAG(BoxTwoPDFM, INHERITS_FROM(BoxModel));
+
+//////////////////////////////////////////////////////////////////
+// Property tags
+//////////////////////////////////////////////////////////////////
+
+NEW_PROP_TAG(NumPhases);   //!< Number of fluid phases in the system
+NEW_PROP_TAG(ProblemEnableGravity); //!< Returns whether gravity is considered in the problem
+NEW_PROP_TAG(ImplicitMassUpwindWeight); //!< The value of the weight of the upwind direction in the mass conservation equations
+NEW_PROP_TAG(ImplicitMobilityUpwindWeight); //!< Weight for the upwind mobility in the velocity calculation
+NEW_PROP_TAG(Formulation);   //!< The formulation of the model
+NEW_PROP_TAG(TwoPDFMIndices); //!< Enumerations for the 2pDFM models
+NEW_PROP_TAG(SpatialParams); //!< The type of the spatial parameters
+NEW_PROP_TAG(MaterialLaw);   //!< The material law which ought to be used (extracted from the spatial parameters)
+NEW_PROP_TAG(MaterialLawParams); //!< The context material law (extracted from the spatial parameters)
+NEW_PROP_TAG(WettingPhase); //!< The wetting phase for two-phase models
+NEW_PROP_TAG(NonwettingPhase); //!< The non-wetting phase for two-phase models
+NEW_PROP_TAG(FluidSystem); //!<The fluid systems including the information about the phases
+NEW_PROP_TAG(FluidState); //!<The phases state
+NEW_PROP_TAG(VtkAddVelocity); //!< Returns whether velocity vectors are written into the vtk output
+} // end namespace Properties
+} // end namespace Dumux
+
+#endif // DUMUX_BOXMODELS_2PDFM_PROPERTIES_HH
diff --git a/dumux/implicit/2pdfm/2pdfmpropertydefaults.hh b/dumux/implicit/2pdfm/2pdfmpropertydefaults.hh
new file mode 100644
index 0000000000..84121c23b0
--- /dev/null
+++ b/dumux/implicit/2pdfm/2pdfmpropertydefaults.hh
@@ -0,0 +1,144 @@
+/*****************************************************************************
+ *   See the file COPYING for full copying permissions.                      *
+ *                                                                           *
+ *   This program is free software: you can redistribute it and/or modify    *
+ *   it under the terms of the GNU General Public License as published by    *
+ *   the Free Software Foundation, either version 2 of the License, or       *
+ *   (at your option) any later version.                                     *
+ *                                                                           *
+ *   This program is distributed in the hope that it will be useful,         *
+ *   but WITHOUT ANY WARRANTY; without even the implied warranty of          *
+ *   MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the            *
+ *   GNU General Public License for more details.                            *
+ *                                                                           *
+ *   You should have received a copy of the GNU General Public License       *
+ *   along with this program. If not, see <http://www.gnu.org/licenses/>.    *
+ *****************************************************************************/
+/*!
+ * \file
+ *
+ * \brief Defines default values for the properties required by the
+ *        2pDFM box model.
+ * 
+ * \ingroup Properties
+ * \ingroup TwoPDFMBoxModel
+ * \ingroup BoxProperties
+ */
+#ifndef DUMUX_BOXMODELS_2PDFM_PROPERTY_DEFAULTS_HH
+#define DUMUX_BOXMODELS_2PDFM_PROPERTY_DEFAULTS_HH
+
+#include <dumux/boxmodels/common/boxdarcyfluxvariables.hh>
+#include <dumux/material/components/nullcomponent.hh>
+#include <dumux/material/fluidstates/immisciblefluidstate.hh>
+#include <dumux/material/fluidsystems/2pimmisciblefluidsystem.hh>
+#include <dumux/material/fluidsystems/gasphase.hh>
+#include <dumux/material/fluidsystems/liquidphase.hh>
+#include <dumux/material/spatialparams/boxspatialparams.hh>
+
+#include "2pdfmmodel.hh"
+#include "2pdfmproblem.hh"
+#include "2pdfmindices.hh"
+#include "2pdfmfluxvariables.hh"
+#include "2pdfmvolumevariables.hh"
+#include "2pdfmproperties.hh"
+
+namespace Dumux
+{
+namespace Properties
+{
+//////////////////////////////////////////////////////////////////
+// Property defaults
+//////////////////////////////////////////////////////////////////
+SET_INT_PROP(BoxTwoPDFM, NumEq, 2); //!< set the number of equations to 2
+SET_INT_PROP(BoxTwoPDFM, NumPhases, 2); //!< The number of phases in the 2p model is 2
+
+//! Set the default formulation to pWsN
+SET_INT_PROP(BoxTwoPDFM,
+             Formulation,
+             TwoPFormulation::pwSn);
+
+//! Use the 2p local jacobian operator for the 2p model
+SET_TYPE_PROP(BoxTwoPDFM,
+              LocalResidual,
+              TwoPDFMLocalResidual<TypeTag>);
+
+//! the Model property
+SET_TYPE_PROP(BoxTwoPDFM, Model, TwoPDFMModel<TypeTag>);
+
+//! the VolumeVariables property
+SET_TYPE_PROP(BoxTwoPDFM, VolumeVariables, TwoPDFMVolumeVariables<TypeTag>);
+
+//! the FluxVariables property
+SET_TYPE_PROP(BoxTwoPDFM, FluxVariables, TwoPDFMFluxVariables<TypeTag>);
+
+//! the upwind weight for the mass conservation equations.
+SET_SCALAR_PROP(BoxTwoPDFM, ImplicitMassUpwindWeight, 1.0);
+
+//! weight for the upwind mobility in the velocity calculation
+SET_SCALAR_PROP(BoxTwoPDFM, ImplicitMobilityUpwindWeight, 1.0);
+
+//! The indices required by the isothermal 2pDFM model
+SET_PROP(BoxTwoPDFM, Indices)
+{ private:
+    enum { Formulation = GET_PROP_VALUE(TypeTag, Formulation) };
+ public:
+    typedef TwoPDFMIndices<TypeTag, Formulation, 0> type;
+};
+
+
+//! The spatial parameters to be employed.
+//! Use BoxSpatialParams by default.
+SET_TYPE_PROP(BoxTwoPDFM, SpatialParams, BoxSpatialParams<TypeTag>);
+
+/*!
+ * \brief Set the property for the material parameters by extracting
+ *        it from the material law.
+ */
+SET_TYPE_PROP(BoxTwoPDFM,
+              MaterialLawParams,
+              typename GET_PROP_TYPE(TypeTag, MaterialLaw)::Params);
+
+SET_PROP(BoxTwoPDFM, WettingPhase)
+{ private:
+    typedef typename GET_PROP_TYPE(TypeTag, Scalar) Scalar;
+public:
+    typedef Dumux::LiquidPhase<Scalar, Dumux::NullComponent<Scalar> > type;
+};
+
+SET_PROP(BoxTwoPDFM, NonwettingPhase)
+{ private:
+    typedef typename GET_PROP_TYPE(TypeTag, Scalar) Scalar;
+public:
+    typedef Dumux::LiquidPhase<Scalar, Dumux::NullComponent<Scalar> > type;
+};
+
+SET_PROP(BoxTwoPDFM, FluidSystem)
+{ private:
+    typedef typename GET_PROP_TYPE(TypeTag, Scalar) Scalar;
+    typedef typename GET_PROP_TYPE(TypeTag, WettingPhase) WettingPhase;
+    typedef typename GET_PROP_TYPE(TypeTag, NonwettingPhase) NonwettingPhase;
+
+public:
+    typedef Dumux::FluidSystems::TwoPImmiscible<Scalar,
+                                                WettingPhase,
+                                                NonwettingPhase> type;
+};
+
+SET_PROP(BoxTwoPDFM, FluidState)
+{
+private:
+    typedef typename GET_PROP_TYPE(TypeTag, Scalar) Scalar;
+    typedef typename GET_PROP_TYPE(TypeTag, FluidSystem) FluidSystem;
+public:
+    typedef ImmiscibleFluidState<Scalar, FluidSystem> type;
+};
+
+// disable velocity output by default
+SET_BOOL_PROP(BoxTwoPDFM, VtkAddVelocity, false);
+
+// enable gravity by default
+SET_BOOL_PROP(BoxTwoPDFM, ProblemEnableGravity, true);
+} // end namespace Properties
+} // end namespace Dumux
+
+#endif // DUMUX_BOXMODELS_2PDFM_PROPERTY_DEFAULTS_HH
diff --git a/dumux/implicit/2pdfm/2pdfmvolumevariables.hh b/dumux/implicit/2pdfm/2pdfmvolumevariables.hh
new file mode 100644
index 0000000000..520d902aa3
--- /dev/null
+++ b/dumux/implicit/2pdfm/2pdfmvolumevariables.hh
@@ -0,0 +1,386 @@
+/*****************************************************************************
+ *   See the file COPYING for full copying permissions.                      *
+ *                                                                           *
+ *   This program is free software: you can redistribute it and/or modify    *
+ *   it under the terms of the GNU General Public License as published by    *
+ *   the Free Software Foundation, either version 2 of the License, or       *
+ *   (at your option) any later version.                                     *
+ *                                                                           *
+ *   This program is distributed in the hope that it will be useful,         *
+ *   but WITHOUT ANY WARRANTY; without even the implied warranty of          *
+ *   MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the            *
+ *   GNU General Public License for more details.                            *
+ *                                                                           *
+ *   You should have received a copy of the GNU General Public License       *
+ *   along with this program. If not, see <http://www.gnu.org/licenses/>.    *
+ *****************************************************************************/
+/*!
+ * \file
+ *
+ * \brief Contains the quantities which are constant within a
+ *        finite volume in the two-phase discrete fracture-matrix model.
+ */
+#ifndef DUMUX_BOXMODELS_2PDFM_VOLUME_VARIABLES_HH
+#define DUMUX_BOXMODELS_2PDFM_VOLUME_VARIABLES_HH
+
+#include <dune/common/fvector.hh>
+
+#include <dumux/boxmodels/2p/2pvolumevariables.hh>
+
+#include "2pdfmproperties.hh"
+
+namespace Dumux
+{
+/*!
+ * \ingroup TwoPDFMBoxModel
+ * \ingroup BoxVolumeVariables
+ * \brief Contains the quantities which are are constant within a
+ *        finite volume in the two-phase discrete fracture-matrix model.
+ */
+template <class TypeTag>
+class TwoPDFMVolumeVariables : public TwoPVolumeVariables<TypeTag>
+{
+    typedef TwoPVolumeVariables<TypeTag> ParentType;
+
+    typedef typename GET_PROP_TYPE(TypeTag, VolumeVariables) Implementation;
+    typedef typename GET_PROP_TYPE(TypeTag, Scalar) Scalar;
+    typedef typename GET_PROP_TYPE(TypeTag, Problem) Problem;
+    typedef typename GET_PROP_TYPE(TypeTag, FluidSystem) FluidSystem;
+    typedef typename GET_PROP_TYPE(TypeTag, FluidState) FluidState;
+    typedef typename GET_PROP_TYPE(TypeTag, MaterialLaw) MaterialLaw;
+    typedef typename GET_PROP_TYPE(TypeTag, MaterialLawParams) MaterialLawParams;
+    typedef typename GET_PROP_TYPE(TypeTag, FVElementGeometry) FVElementGeometry;
+    typedef typename GET_PROP_TYPE(TypeTag, PrimaryVariables) PrimaryVariables;
+    typedef typename FVElementGeometry::SubControlVolumeFace SCVFace;
+
+    typedef typename GET_PROP_TYPE(TypeTag, Indices) Indices;
+    enum {
+        pwSn = Indices::pwSn,
+        pnSw = Indices::pnSw,
+        pressureIdx = Indices::pressureIdx,
+        saturationIdx = Indices::saturationIdx,
+        wPhaseIdx = Indices::wPhaseIdx,
+        nPhaseIdx = Indices::nPhaseIdx,
+        numPhases = GET_PROP_VALUE(TypeTag, NumPhases),
+        formulation = GET_PROP_VALUE(TypeTag, Formulation)
+    };
+
+    typedef typename GET_PROP_TYPE(TypeTag, GridView) GridView;
+    typedef typename GridView::template Codim<0>::Entity Element;
+    typedef Dune::UGGrid<2> GridType;
+    typedef typename GridType::ctype DT;
+    enum {
+            dim = GridView::dimension,
+            dimWorld = GridView::dimensionworld
+    };
+    typedef Dune::FieldVector<Scalar, dimWorld> GlobalPosition;
+    typedef Dune::FieldVector<Scalar, dim> LocalPosition;
+
+public:
+    /*!
+     * \copydoc BoxVolumeVariables::update
+     */
+    void update(const PrimaryVariables &priVars,
+                const Problem &problem,
+                const Element &element,
+                const FVElementGeometry &fvGeometry,
+                int scvIdx,
+                bool isOldSol)
+    {
+        ParentType::update(priVars,
+                           problem,
+                           element,
+                           fvGeometry,
+                           scvIdx,
+                           isOldSol);
+
+        this->completeFluidState(priVars, problem, element, fvGeometry, scvIdx, fluidState_);
+
+        const MaterialLawParams &materialParams =
+            problem.spatialParams().materialLawParams(element, fvGeometry, scvIdx);
+
+        mobilityMatrix_[wPhaseIdx] =
+            MaterialLaw::krw(materialParams, fluidState_.saturation(wPhaseIdx))
+            / fluidState_.viscosity(wPhaseIdx);
+
+        mobilityMatrix_[nPhaseIdx] =
+            MaterialLaw::krn(materialParams, fluidState_.saturation(wPhaseIdx))
+            / fluidState_.viscosity(nPhaseIdx);
+
+        // porosity
+        porosityMatrix_ = problem.spatialParams().porosity(element, fvGeometry, scvIdx);
+
+        // energy related quantities not belonging to the fluid state
+        asImp_().updateEnergy_(priVars, problem, element, fvGeometry, scvIdx, isOldSol);
+        asImp_().updateFracture(priVars, problem, element, fvGeometry, scvIdx, isOldSol);
+    }
+
+    /*!
+     * \brief Construct the volume variables for all fracture vertices.
+     *
+     * \param priVars Primary variables.
+     * \param problem The problem which needs to be simulated.
+     * \param element The DUNE Codim<0> entity for which the volume variables ought to be calculated
+     * \param fvGeometry The finite volume geometry of the element
+     * \param scvIdx Sub-control volume index
+     * \param isOldSol Tells whether the model's previous or current solution should be used.
+     */
+    void updateFracture(const PrimaryVariables &priVars,
+                        const Problem &problem,
+                        const Element &element,
+                        const FVElementGeometry &fvGeometry,
+                        int scvIdx,
+                        bool isOldSol)
+    {
+        PrimaryVariables varsFracture;
+        const MaterialLawParams &materialParamsMatrix =
+                    problem.spatialParams().materialLawParams(element, fvGeometry, scvIdx);
+        Scalar pressure[numPhases];
+        Scalar pMatrix[numPhases];
+        Scalar pFract[numPhases];
+
+        satNMatrix_  = priVars[saturationIdx];
+        satWMatrix_  = 1.0 - satNMatrix_;
+        satN_ = satNMatrix_;
+        satW_ = satWMatrix_;
+
+        pCMatrix_ = MaterialLaw::pC(materialParamsMatrix, satWMatrix_);
+        pC_ = pCMatrix_;
+        //pressures
+        pMatrix[wPhaseIdx] = priVars[pressureIdx];
+        pMatrix[nPhaseIdx] = pMatrix[wPhaseIdx] + pCMatrix_;
+        //Initialize pFract with the same values as the ones in the matrix
+        pFract[wPhaseIdx] = pMatrix[wPhaseIdx];
+        pFract[nPhaseIdx] = satNMatrix_;
+
+        varsFracture[pressureIdx] = pFract[wPhaseIdx];
+        varsFracture[saturationIdx] = pFract[wPhaseIdx];
+
+        this->completeFluidState(priVars, problem, element, fvGeometry, scvIdx, fluidStateFracture_);
+
+        //Checks if the node is on a fracture
+        isNodeOnFracture_ = problem.spatialParams().isVertexFracture(element, scvIdx);
+
+        ///////////////////////////////////////////////////////////////////////////////
+        if (isNodeOnFracture_)
+        {
+            const MaterialLawParams &materialParamsFracture =
+                    problem.spatialParams().materialLawParamsFracture(element, fvGeometry, scvIdx);
+
+            satNFracture_ = priVars[saturationIdx];
+            satWFracture_ = 1 - satNFracture_;
+            pCFracture_ = MaterialLaw::pC(materialParamsFracture, satWFracture_);
+            pFract[wPhaseIdx] = priVars[pressureIdx];
+            pFract[nPhaseIdx] = pFract[wPhaseIdx] + pCFracture_;
+            pEntryMatrix_ = MaterialLaw::pC(materialParamsMatrix, 1);
+
+            //use interface condition - extended capillary pressure inteface condition
+            if (problem.useInterfaceCondition())
+            {
+                interfaceCondition(materialParamsMatrix);
+            }
+            pC_ = pCFracture_;
+            satW_ = satWFracture_; //for plotting we are interested in the saturations of the fracture
+            satN_ = satNFracture_;
+            mobilityFracture_[wPhaseIdx] =
+                    MaterialLaw::krw(materialParamsFracture, fluidStateFracture_.saturation(wPhaseIdx))
+                    / fluidStateFracture_.viscosity(wPhaseIdx);
+
+            mobilityFracture_[nPhaseIdx] =
+                    MaterialLaw::krn(materialParamsFracture, fluidStateFracture_.saturation(wPhaseIdx))
+                        / fluidStateFracture_.viscosity(nPhaseIdx);
+
+            // derivative resulted from BrooksCorey pc_Sw formulation
+            dSM_dSF_ = (1 - problem.spatialParams().SwrM_) / (1 - problem.spatialParams().SwrF_)
+                    * pow((problem.spatialParams().pdM_/ problem.spatialParams().pdF_),problem.spatialParams().lambdaM_)
+                    * (problem.spatialParams().lambdaM_ / problem.spatialParams().lambdaF_)
+                    * pow((satWFracture_ - problem.spatialParams().SwrF_ ) / (1 - problem.spatialParams().SwrF_),
+                            (problem.spatialParams().lambdaM_ / problem.spatialParams().lambdaF_) - 1);
+        }// end if (node)
+        ///////////////////////////////////////////////////////////////////////////////
+        else
+        {
+            /* the values of pressure and saturation of the fractures in the volumes where
+                there are no fracture are set unphysical*/
+            satNFracture_ = -1;
+            satWFracture_ = -1;
+            pCFracture_ = -1e100;
+            pFract[wPhaseIdx] = -1e100;
+            pFract[nPhaseIdx] = -1e100;
+            pEntryMatrix_ = -1e100;
+            mobilityFracture_[wPhaseIdx] = 0.0;
+            mobilityFracture_[nPhaseIdx] = 0.0;
+        }
+        ///////////////////////////////////////////////////////////////////////////////
+        pressure[wPhaseIdx] = priVars[pressureIdx];
+        pressure[nPhaseIdx] = pressure[wPhaseIdx] + pC_;
+
+        porosityFracture_ = problem.spatialParams().porosityFracture(element,
+                                                                  fvGeometry,
+                                                                  scvIdx);
+    }
+
+    /*!
+     * \brief Extended capillary pressure saturation interface condition
+     *
+     * \param materialParamsMatrix the material law o calculate the Sw as inverse of capillary pressure function
+     *
+     * This method is called by updateFracture
+     */
+    void interfaceCondition(const MaterialLawParams &materialParamsMatrix)
+    {
+        /*2nd condition Niessner, J., R. Helmig, H. Jakobs, and J.E. Roberts. 2005, eq.10
+        * if the capillary pressure in the fracture is smaller than the entry pressure
+        * in the matrix than in the matrix
+        * */
+        if (pCFracture_ <= pEntryMatrix_)
+        {
+            satWMatrix_ = 1.0;
+            satNMatrix_ = 1 - satWMatrix_;
+        }
+        //3rd condition Niessner, J., R. Helmig, H. Jakobs, and J.E. Roberts. 2005, eq.10
+        else
+        {
+            /*
+             * Inverse capillary pressure function SwM = pcM^(-1)(pcF(SwF))
+             */
+            satWMatrix_ = MaterialLaw::Sw(materialParamsMatrix, pCFracture_);
+            satNMatrix_ = 1 - satWMatrix_;
+        }
+    }
+
+    /*!
+     * \brief Calculates the volume of the fracture inside the SCV
+     */
+    Scalar calculateSCVFractureVolume ( const Problem &problem,
+                                        const Element &element,
+                                        const FVElementGeometry &fvGeometry,
+                                        int scvIdx)
+    {
+        Scalar volSCVFracture;
+        Dune::GeometryType gt = element.geometry().type();
+        const typename Dune::GenericReferenceElementContainer<DT,dim>::value_type&
+            refElem = Dune::GenericReferenceElements<DT,dim>::general(gt);
+
+        for (int faceIdx=0; faceIdx<refElem.size(1); faceIdx++)
+        {
+            SCVFace face = fvGeometry.subContVolFace[faceIdx];
+            int i=face.i;
+            int j=face.j;
+
+            if (problem.spatialParams().isEdgeFracture(element, faceIdx)
+                && (i == scvIdx || j == scvIdx))
+            {
+                Scalar fracture_width = problem.spatialParams().fractureWidth();
+
+                const GlobalPosition global_i = element.geometry().corner(i);
+                const GlobalPosition global_j = element.geometry().corner(j);
+                GlobalPosition diff_ij = global_j;
+                diff_ij -=global_i;
+                //fracture length in the subcontrol volume is half d_ij
+                Scalar fracture_length = 0.5*diff_ij.two_norm();
+
+                volSCVFracture += 0.5 * fracture_length * fracture_width;
+            }
+        }
+        return volSCVFracture;
+    }
+
+    /*!
+     * \brief Returns the effective saturation fracture of a given phase within
+     *        the control volume.
+     *
+     * \param phaseIdx The phase index
+     */
+    Scalar saturationFracture(int phaseIdx) const
+    {
+        if (phaseIdx == wPhaseIdx)
+            return satWFracture_;
+        else
+            return satNFracture_;
+    }
+    Scalar saturationMatrix(int phaseIdx) const
+    {
+         if (phaseIdx == wPhaseIdx)
+             return satWMatrix_;
+         else
+             return satNMatrix_;
+    }
+
+    /*!
+     * \brief Returns the effective mobility of a given phase within
+     *        the control volume.
+     *
+     * \param phaseIdx The phase index
+     */
+    Scalar mobility(int phaseIdx) const
+    { return mobilityMatrix_[phaseIdx]; }
+
+    /*!
+     * \brief Returns the effective mobility of a given phase within
+     *        the control volume.
+     *
+     * \param phaseIdx The phase index
+     */
+    Scalar mobilityFracture(int phaseIdx) const
+    { return mobilityFracture_[phaseIdx]; }
+
+    /*!
+     * \brief Returns the average porosity within the matrix control volume.
+     */
+    Scalar porosity() const
+    { return porosityMatrix_; }
+
+    /*!
+     * \brief Returns the average porosity within the fracture.
+     */
+    Scalar porosityFracture() const
+    { return porosityFracture_; }
+
+    /*!
+     * \brief Returns the average permeability within the fracture.
+     */
+    Scalar permeabilityFracture() const
+    { return permeabilityFracture_; }
+
+    /*!
+     * \brief Returns the derivative dSM/dSF
+     */
+    Scalar dSM_dSF() const
+    { return dSM_dSF_;}
+
+protected:
+    FluidState fluidState_;
+    FluidState fluidStateFracture_;
+    Scalar porosityMatrix_;
+    Scalar porosityFracture_;
+    Scalar permeability_;
+    Scalar permeabilityFracture_;
+    Scalar mobilityMatrix_[numPhases];
+    Scalar mobilityFracture_[numPhases];
+
+    Scalar satW_;
+    Scalar satWFracture_;
+    Scalar satWMatrix_;
+    Scalar satN_;
+    Scalar satNFracture_;
+    Scalar satNMatrix_;
+
+    Scalar pC_;
+    Scalar pCFracture_;
+    Scalar pCMatrix_;
+    Scalar pEntryMatrix_;
+    Scalar dSM_dSF_;
+
+    bool isNodeOnFracture_;
+
+private:
+    Implementation &asImp_()
+    { return *static_cast<Implementation*>(this); }
+
+    const Implementation &asImp_() const
+    { return *static_cast<const Implementation*>(this); }
+};
+} // end namespace
+
+#endif // DUMUX_BOXMODELS_2PDFM_VOLUME_VARIABLES_HH
diff --git a/dumux/implicit/2pdfm/Makefile.am b/dumux/implicit/2pdfm/Makefile.am
new file mode 100644
index 0000000000..117f16d6c2
--- /dev/null
+++ b/dumux/implicit/2pdfm/Makefile.am
@@ -0,0 +1,4 @@
+2pdfmdir = $(includedir)/dumux/boxmodels/2pdfm
+2pdfm_HEADERS = *.hh
+
+include $(top_srcdir)/am/global-rules
diff --git a/dumux/implicit/2pni/2pnifluxvariables.hh b/dumux/implicit/2pni/2pnifluxvariables.hh
new file mode 100644
index 0000000000..ae3f474f72
--- /dev/null
+++ b/dumux/implicit/2pni/2pnifluxvariables.hh
@@ -0,0 +1,127 @@
+// -*- mode: C++; tab-width: 4; indent-tabs-mode: nil; c-basic-offset: 4 -*-
+// vi: set et ts=4 sw=4 sts=4:
+/*****************************************************************************
+ *   See the file COPYING for full copying permissions.                      *
+ *                                                                           *
+ *   This program is free software: you can redistribute it and/or modify    *
+ *   it under the terms of the GNU General Public License as published by    *
+ *   the Free Software Foundation, either version 2 of the License, or       *
+ *   (at your option) any later version.                                     *
+ *                                                                           *
+ *   This program is distributed in the hope that it will be useful,         *
+ *   but WITHOUT ANY WARRANTY; without even the implied warranty of          *
+ *   MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the            *
+ *   GNU General Public License for more details.                            *
+ *                                                                           *
+ *   You should have received a copy of the GNU General Public License       *
+ *   along with this program.  If not, see <http://www.gnu.org/licenses/>.   *
+ *****************************************************************************/
+/*!
+ * \file
+ *
+ * \brief This file contains the data which is required to calculate
+ *        all fluxes (mass and energy) of all phases over a face of a finite volume.
+ *
+ * This means pressure and temperature gradients, phase densities at
+ * the integration point, etc.
+ */
+#ifndef DUMUX_2PNI_FLUX_VARIABLES_HH
+#define DUMUX_2PNI_FLUX_VARIABLES_HH
+
+#include <dumux/common/math.hh>
+#include <dumux/boxmodels/common/boxdarcyfluxvariables.hh>
+
+namespace Dumux
+{
+
+/*!
+ * \ingroup TwoPNIModel
+ * \ingroup BoxFluxVariables
+ * \brief This template class contains the data which is required to
+ *        calculate all fluxes (mass and energy) of all phases over a
+ *        face of a finite volume for the non-isothermal two-phase model.
+ *
+ * This means pressure and concentration gradients, phase densities at
+ * the integration point, etc.
+ */
+template <class TypeTag>
+class TwoPNIFluxVariables : public BoxDarcyFluxVariables<TypeTag>
+{
+    typedef BoxDarcyFluxVariables<TypeTag> ParentType;
+
+    typedef typename GET_PROP_TYPE(TypeTag, Scalar) Scalar;
+    typedef typename GET_PROP_TYPE(TypeTag, Problem) Problem;
+    typedef typename GET_PROP_TYPE(TypeTag, ElementVolumeVariables) ElementVolumeVariables;
+    typedef typename GET_PROP_TYPE(TypeTag, FVElementGeometry) FVElementGeometry;
+
+    typedef typename GET_PROP_TYPE(TypeTag, GridView) GridView;
+    typedef typename GridView::template Codim<0>::Entity Element;
+    enum { dimWorld = GridView::dimensionworld };
+
+    typedef typename GridView::ctype CoordScalar;
+    typedef Dune::FieldVector<CoordScalar, dimWorld> Vector;
+
+public:
+
+    /*
+     * \brief The constructor
+     *
+     * \param problem The problem
+     * \param element The finite element
+     * \param fvGeometry The finite-volume geometry in the box scheme
+     * \param faceIdx The local index of the SCV (sub-control-volume) face
+     * \param elemVolVars The volume variables of the current element
+     * \param onBoundary A boolean variable to specify whether the flux variables
+     * are calculated for interior SCV faces or boundary faces, default=false
+     */
+
+    TwoPNIFluxVariables(const Problem &problem,
+                   const Element &element,
+                   const FVElementGeometry &fvGeometry,
+                   int faceIdx,
+                   const ElementVolumeVariables &elemVolVars,
+                   const bool onBoundary = false)
+        : ParentType(problem, element, fvGeometry, faceIdx, elemVolVars, onBoundary)
+    {
+        // calculate temperature gradient using finite element
+        // gradients
+        Vector temperatureGrad(0);
+        for (int idx = 0; idx < fvGeometry.numFAP; idx++)
+        {
+            Vector feGrad = this->face().grad[idx];
+
+            // index for the element volume variables 
+            int volVarsIdx = this->face().fapIndices[idx];
+            
+            feGrad *= elemVolVars[volVarsIdx].temperature();
+            temperatureGrad += feGrad;
+        }
+
+        // The spatial parameters calculates the actual heat flux vector
+        Vector heatFlux;
+        problem.spatialParams().matrixHeatFlux(heatFlux,
+                                                   *this,
+                                                   elemVolVars,
+                                                   temperatureGrad,
+                                                   element,
+                                                   fvGeometry,
+                                                   faceIdx);
+        // project the heat flux vector on the face's normal vector
+        normalMatrixHeatFlux_ = heatFlux * this->face().normal;
+    }
+
+    /*!
+     * \brief The total heat flux \f$\mathrm{[J/s]}\f$ due to heat conduction
+     *        of the rock matrix over the sub-control volume's face in
+     *        direction of the face normal.
+     */
+    Scalar normalMatrixHeatFlux() const
+    { return normalMatrixHeatFlux_; }
+
+private:
+    Scalar normalMatrixHeatFlux_;
+};
+
+} // end namepace
+
+#endif
diff --git a/dumux/implicit/2pni/2pniindices.hh b/dumux/implicit/2pni/2pniindices.hh
new file mode 100644
index 0000000000..2eafe784d3
--- /dev/null
+++ b/dumux/implicit/2pni/2pniindices.hh
@@ -0,0 +1,48 @@
+// -*- mode: C++; tab-width: 4; indent-tabs-mode: nil; c-basic-offset: 4 -*-
+// vi: set et ts=4 sw=4 sts=4:
+/*****************************************************************************
+ *   See the file COPYING for full copying permissions.                      *
+ *                                                                           *
+ *   This program is free software: you can redistribute it and/or modify    *
+ *   it under the terms of the GNU General Public License as published by    *
+ *   the Free Software Foundation, either version 2 of the License, or       *
+ *   (at your option) any later version.                                     *
+ *                                                                           *
+ *   This program is distributed in the hope that it will be useful,         *
+ *   but WITHOUT ANY WARRANTY; without even the implied warranty of          *
+ *   MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the            *
+ *   GNU General Public License for more details.                            *
+ *                                                                           *
+ *   You should have received a copy of the GNU General Public License       *
+ *   along with this program.  If not, see <http://www.gnu.org/licenses/>.   *
+ *****************************************************************************/
+/*!
+ * \file
+ *
+ * \brief Defines the indices used by the non-isotherm two-phase BOX model.
+ */
+#ifndef DUMUX_2PNI_INDICES_HH
+#define DUMUX_2PNI_INDICES_HH
+
+#include <dumux/boxmodels/2p/2pindices.hh>
+
+namespace Dumux
+{
+// \{
+
+/*!
+ * \ingroup TwoPNIModel
+ * \ingroup BoxIndices
+ * \brief Enumerations for the non-isothermal two-phase model
+ */
+template <class TypeTag, int PVOffset = 0>
+class TwoPNIIndices : public TwoPIndices<TypeTag, PVOffset>
+{
+public:
+    static const int temperatureIdx = PVOffset + 2; //! The primary variable index for temperature
+    static const int energyEqIdx = PVOffset + 2; //! The equation index of the energy equation
+};
+// \}
+}
+
+#endif
diff --git a/dumux/implicit/2pni/2pnilocalresidual.hh b/dumux/implicit/2pni/2pnilocalresidual.hh
new file mode 100644
index 0000000000..bb1f1e3b90
--- /dev/null
+++ b/dumux/implicit/2pni/2pnilocalresidual.hh
@@ -0,0 +1,182 @@
+// -*- mode: C++; tab-width: 4; indent-tabs-mode: nil; c-basic-offset: 4 -*-
+// vi: set et ts=4 sw=4 sts=4:
+/*****************************************************************************
+ *   See the file COPYING for full copying permissions.                      *
+ *                                                                           *
+ *   This program is free software: you can redistribute it and/or modify    *
+ *   it under the terms of the GNU General Public License as published by    *
+ *   the Free Software Foundation, either version 2 of the License, or       *
+ *   (at your option) any later version.                                     *
+ *                                                                           *
+ *   This program is distributed in the hope that it will be useful,         *
+ *   but WITHOUT ANY WARRANTY; without even the implied warranty of          *
+ *   MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the            *
+ *   GNU General Public License for more details.                            *
+ *                                                                           *
+ *   You should have received a copy of the GNU General Public License       *
+ *   along with this program.  If not, see <http://www.gnu.org/licenses/>.   *
+ *****************************************************************************/
+/*!
+ * \file
+ *
+ * \brief Element-wise calculation of the Jacobian matrix for problems
+ *        using the non-isothermal two-phase box model.
+ *
+ */
+#ifndef DUMUX_NEW_2PNI_LOCAL_RESIDUAL_HH
+#define DUMUX_NEW_2PNI_LOCAL_RESIDUAL_HH
+
+#include "2pniproperties.hh"
+
+#include <dumux/boxmodels/2p/2plocalresidual.hh>
+
+#include <dumux/boxmodels/2pni/2pnivolumevariables.hh>
+#include <dumux/boxmodels/2pni/2pnifluxvariables.hh>
+
+namespace Dumux
+{
+/*!
+ * \ingroup TwoPNIModel
+ * \ingroup BoxLocalResidual
+ * \brief Element-wise calculation of the Jacobian matrix for problems
+ *        using the non-isothermal two-phase box model.
+ */
+
+template<class TypeTag>
+class TwoPNILocalResidual : public TwoPLocalResidual<TypeTag>
+{
+    typedef TwoPLocalResidual<TypeTag> ParentType;
+
+    typedef typename GET_PROP_TYPE(TypeTag, PrimaryVariables) PrimaryVariables;
+    typedef typename GET_PROP_TYPE(TypeTag, VolumeVariables) VolumeVariables;
+    typedef typename GET_PROP_TYPE(TypeTag, FluxVariables) FluxVariables;
+    typedef typename GET_PROP_TYPE(TypeTag, ElementVolumeVariables) ElementVolumeVariables;
+
+    typedef typename GET_PROP_TYPE(TypeTag, Indices) Indices;
+    enum {
+        numPhases = GET_PROP_VALUE(TypeTag, NumPhases),
+        temperatureIdx = Indices::temperatureIdx,
+        energyEqIdx = Indices::energyEqIdx,
+        wPhaseIdx = Indices::wPhaseIdx,
+        nPhaseIdx = Indices::nPhaseIdx
+    };
+
+    typedef typename GET_PROP_TYPE(TypeTag, GridView) GridView;
+    enum { dimWorld = GridView::dimensionworld };
+
+    typedef typename GET_PROP_TYPE(TypeTag, Scalar) Scalar;
+    typedef Dune::FieldVector<Scalar, dimWorld> Vector;
+
+public:
+    /*!
+     * \brief Constructor. Sets the upwind weight.
+     */
+    TwoPNILocalResidual()
+    {
+        // retrieve the upwind weight for the mass conservation equations. Use the value
+        // specified via the property system as default, and overwrite
+        // it by the run-time parameter from the Dune::ParameterTree
+        massUpwindWeight_ = GET_PARAM_FROM_GROUP(TypeTag, Scalar, Implicit, MassUpwindWeight);
+    };
+
+    /*!
+     * \brief Evaluate the amount all conservation quantites
+     *        (e.g. phase mass and energy storage) within a sub-control volume.
+     *
+     * The result should be averaged over the volume (e.g. phase mass
+     * inside a sub control volume divided by the volume)
+     *
+     *  \param storage The phase mass within the sub-control volume
+     *  \param scvIdx The SCV (sub-control-volume) index
+     *  \param usePrevSol Evaluate function with solution of current or previous time step
+     */
+    void computeStorage(PrimaryVariables &storage, int scvIdx, bool usePrevSol) const
+    {
+        // compute the storage term for phase mass
+        ParentType::computeStorage(storage, scvIdx, usePrevSol);
+
+        // if flag usePrevSol is set, the solution from the previous
+        // time step is used, otherwise the current solution is
+        // used. The secondary variables are used accordingly.  This
+        // is required to compute the derivative of the storage term
+        // using the implicit euler method.
+        const ElementVolumeVariables &elemVolVars = usePrevSol ? this->prevVolVars_() : this->curVolVars_();
+        const VolumeVariables &volVars = elemVolVars[scvIdx];
+
+        // compute the energy storage
+        storage[temperatureIdx] =
+            volVars.porosity()*(volVars.density(wPhaseIdx) *
+                                volVars.internalEnergy(wPhaseIdx) *
+                                volVars.saturation(wPhaseIdx)
+                                +
+                                volVars.density(nPhaseIdx) *
+                                volVars.internalEnergy(nPhaseIdx) *
+                                volVars.saturation(nPhaseIdx))
+          + volVars.temperature()*volVars.heatCapacity();
+    }
+
+    /*!
+     * \brief Evaluates the advective mass flux and the heat flux
+     * over a face of a subcontrol volume and writes the result in
+     * the flux vector.
+     *
+     * \param flux The advective flux over the sub-control-volume face for each phase
+     * \param fluxVars The flux variables at the current SCV
+     *
+     *
+     * This method is called by compute flux (base class)
+     */
+    void computeAdvectiveFlux(PrimaryVariables &flux,
+                              const FluxVariables &fluxVars) const
+    {
+        // advective mass flux
+        ParentType::computeAdvectiveFlux(flux, fluxVars);
+
+        // advective heat flux in all phases
+        flux[energyEqIdx] = 0;
+        for (int phaseIdx = 0; phaseIdx < numPhases; ++phaseIdx) {
+            // data attached to upstream and the downstream vertices
+            // of the current phase
+            const VolumeVariables &up = this->curVolVars_(fluxVars.upstreamIdx(phaseIdx));
+            const VolumeVariables &dn = this->curVolVars_(fluxVars.downstreamIdx(phaseIdx));
+
+            // add advective energy flux in current phase
+            flux[energyEqIdx] +=
+                fluxVars.volumeFlux(phaseIdx)
+                *
+                ((    massUpwindWeight_)*
+                 up.density(phaseIdx)*
+                 up.enthalpy(phaseIdx)
+                 +
+                 (1 - massUpwindWeight_)*
+                 dn.density(phaseIdx)*
+                 dn.enthalpy(phaseIdx));
+        }
+    }
+
+    /*!
+     * \brief Adds the diffusive heat flux to the flux vector over
+     *        the face of a sub-control volume.
+     *
+     * \param flux The diffusive flux over the sub-control-volume face for each phase
+     * \param fluxVars The flux variables at the current SCV
+     *
+     */
+    void computeDiffusiveFlux(PrimaryVariables &flux,
+                              const FluxVariables &fluxVars) const
+    {
+        // diffusive mass flux
+        ParentType::computeDiffusiveFlux(flux, fluxVars);
+
+        // diffusive heat flux
+        flux[energyEqIdx] += fluxVars.normalMatrixHeatFlux();
+    }
+
+private:
+    Scalar massUpwindWeight_;
+
+};
+
+}
+
+#endif
diff --git a/dumux/implicit/2pni/2pnimodel.hh b/dumux/implicit/2pni/2pnimodel.hh
new file mode 100644
index 0000000000..81352b3569
--- /dev/null
+++ b/dumux/implicit/2pni/2pnimodel.hh
@@ -0,0 +1,93 @@
+// -*- mode: C++; tab-width: 4; indent-tabs-mode: nil; c-basic-offset: 4 -*-
+// vi: set et ts=4 sw=4 sts=4:
+/*****************************************************************************
+ *   See the file COPYING for full copying permissions.                      *
+ *                                                                           *
+ *   This program is free software: you can redistribute it and/or modify    *
+ *   it under the terms of the GNU General Public License as published by    *
+ *   the Free Software Foundation, either version 2 of the License, or       *
+ *   (at your option) any later version.                                     *
+ *                                                                           *
+ *   This program is distributed in the hope that it will be useful,         *
+ *   but WITHOUT ANY WARRANTY; without even the implied warranty of          *
+ *   MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the            *
+ *   GNU General Public License for more details.                            *
+ *                                                                           *
+ *   You should have received a copy of the GNU General Public License       *
+ *   along with this program.  If not, see <http://www.gnu.org/licenses/>.   *
+ *****************************************************************************/
+/*!
+ * \file
+ *
+ * \brief Adaption of the BOX scheme to the non-isothermal twophase flow model.
+ */
+#ifndef DUMUX_2PNI_MODEL_HH
+#define DUMUX_2PNI_MODEL_HH
+
+#include <dumux/boxmodels/2p/2pmodel.hh>
+
+namespace Dumux {
+
+/*!
+ * \ingroup TwoPNIBoxModel
+ * \brief A two-phase, non-isothermal flow model using the box scheme.
+ *
+ * This model implements a non-isothermal two-phase flow for two
+ * immiscible fluids \f$\alpha \in \{ w, n \}\f$. Using the standard
+ * multiphase Darcy approach, the mass conservation equations for both
+ * phases can be described as follows:
+ * \f[
+ \phi \frac{\partial \phi \varrho_\alpha S_\alpha}{\partial t}
+ - 
+ \text{div} 
+ \left\{ 
+ \varrho_\alpha \frac{k_{r\alpha}}{\mu_\alpha} \mathrm{K}
+ \left( \textrm{grad}\, p_\alpha - \varrho_{\alpha} \mathbf{g} \right)
+ \right\}
+ -
+ q_\alpha = 0 \qquad \alpha \in \{w, n\}
+ \f]
+ *
+ * For the energy balance, local thermal equilibrium is assumed. This
+ * results in one energy conservation equation for the porous solid
+ * matrix and the fluids: 
+ 
+ \f{align*}{
+ \frac{\partial \phi \sum_\alpha \varrho_\alpha u_\alpha S_\alpha}{\partial t}
+ & + 
+ \left( 1 - \phi \right) \frac{\partial (\varrho_s c_s T)}{\partial t}
+ - 
+ \sum_\alpha \text{div} 
+ \left\{
+ \varrho_\alpha h_\alpha
+ \frac{k_{r\alpha}}{\mu_\alpha} \mathbf{K} 
+ \left( \textbf{grad}\,p_\alpha - \varrho_\alpha \mbox{\bf g} \right)
+ \right\} \\
+    & - \text{div} \left(\lambda_{pm} \textbf{grad} \, T \right)
+    - q^h = 0, \qquad \alpha \in \{w, n\} \;,
+ \f}
+ * where \f$h_\alpha\f$ is the specific enthalpy of a fluid phase
+ * \f$\alpha\f$ and \f$u_\alpha = h_\alpha -
+ * p_\alpha/\varrho_\alpha\f$ is the specific internal energy of the
+ * phase.
+ *
+ * The equations are discretized using a fully-coupled vertex centered
+ * finite volume (box) scheme as spatial and the implicit Euler method
+ * as time discretization.
+ *
+ * Currently the model supports choosing either \f$p_w\f$, \f$S_n\f$
+ * and \f$T\f$ or \f$p_n\f$, \f$S_w\f$ and \f$T\f$ as primary
+ * variables. The formulation which ought to be used can be specified
+ * by setting the <tt>Formulation</tt> property to either
+ * <tt>TwoPNIIndices::pWsN</tt> or <tt>TwoPIndices::pNsW</tt>. By
+ * default, the model uses \f$p_w\f$, \f$S_n\f$ and \f$T\f$.
+ */
+template<class TypeTag>
+class TwoPNIModel: public TwoPModel<TypeTag>
+{};
+
+}
+
+#include "2pnipropertydefaults.hh"
+
+#endif
diff --git a/dumux/implicit/2pni/2pniproperties.hh b/dumux/implicit/2pni/2pniproperties.hh
new file mode 100644
index 0000000000..d58ba13095
--- /dev/null
+++ b/dumux/implicit/2pni/2pniproperties.hh
@@ -0,0 +1,47 @@
+// -*- mode: C++; tab-width: 4; indent-tabs-mode: nil; c-basic-offset: 4 -*-
+// vi: set et ts=4 sw=4 sts=4:
+/*****************************************************************************
+ *   See the file COPYING for full copying permissions.                      *
+ *                                                                           *
+ *   This program is free software: you can redistribute it and/or modify    *
+ *   it under the terms of the GNU General Public License as published by    *
+ *   the Free Software Foundation, either version 2 of the License, or       *
+ *   (at your option) any later version.                                     *
+ *                                                                           *
+ *   This program is distributed in the hope that it will be useful,         *
+ *   but WITHOUT ANY WARRANTY; without even the implied warranty of          *
+ *   MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the            *
+ *   GNU General Public License for more details.                            *
+ *                                                                           *
+ *   You should have received a copy of the GNU General Public License       *
+ *   along with this program.  If not, see <http://www.gnu.org/licenses/>.   *
+ *****************************************************************************/
+/*!
+ * \ingroup Properties
+ * \ingroup BoxProperties
+ *  \ingroup TwoPNIBoxModel
+ * \file
+ *
+ * \brief Defines the properties required for the non-isotherm two-phase BOX model.
+ */
+#ifndef DUMUX_2PNI_PROPERTIES_HH
+#define DUMUX_2PNI_PROPERTIES_HH
+
+#include <dumux/boxmodels/2p/2pproperties.hh>
+
+namespace Dumux
+{
+
+namespace Properties
+{
+//////////////////////////////////////////////////////////////////
+// Type tags
+//////////////////////////////////////////////////////////////////
+
+//! The type tag for the non-isothermal two-phase problems
+NEW_TYPE_TAG(BoxTwoPNI, INHERITS_FROM(BoxTwoP));
+
+}
+}
+
+#endif
diff --git a/dumux/implicit/2pni/2pnipropertydefaults.hh b/dumux/implicit/2pni/2pnipropertydefaults.hh
new file mode 100644
index 0000000000..2a96f75eb1
--- /dev/null
+++ b/dumux/implicit/2pni/2pnipropertydefaults.hh
@@ -0,0 +1,72 @@
+// -*- mode: C++; tab-width: 4; indent-tabs-mode: nil; c-basic-offset: 4 -*-
+// vi: set et ts=4 sw=4 sts=4:
+/*****************************************************************************
+ *   See the file COPYING for full copying permissions.                      *
+ *                                                                           *
+ *   This program is free software: you can redistribute it and/or modify    *
+ *   it under the terms of the GNU General Public License as published by    *
+ *   the Free Software Foundation, either version 2 of the License, or       *
+ *   (at your option) any later version.                                     *
+ *                                                                           *
+ *   This program is distributed in the hope that it will be useful,         *
+ *   but WITHOUT ANY WARRANTY; without even the implied warranty of          *
+ *   MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the            *
+ *   GNU General Public License for more details.                            *
+ *                                                                           *
+ *   You should have received a copy of the GNU General Public License       *
+ *   along with this program.  If not, see <http://www.gnu.org/licenses/>.   *
+ *****************************************************************************/
+/*!
+ * \ingroup Properties
+ * \ingroup BoxProperties
+ *  \ingroup TwoPNIBoxModel
+ * \file
+ *
+ * \brief Defines the default values for most of the properties
+ *        required by the non-isotherm two-phase box model.
+ */
+
+#ifndef DUMUX_2PNI_PROPERTY_DEFAULTS_HH
+#define DUMUX_2PNI_PROPERTY_DEFAULTS_HH
+
+#include "2pniproperties.hh"
+#include "2pnimodel.hh"
+#include "2pnilocalresidual.hh"
+#include "2pnivolumevariables.hh"
+#include "2pnifluxvariables.hh"
+#include "2pniindices.hh"
+
+namespace Dumux
+{
+
+
+namespace Properties
+{
+//////////////////////////////////////////////////////////////////
+// Property values
+//////////////////////////////////////////////////////////////////
+
+SET_INT_PROP(BoxTwoPNI, NumEq, 3); //!< set the number of equations to 3
+
+//! Use the 2pni local jacobian operator for the 2pni model
+SET_TYPE_PROP(BoxTwoPNI,
+              LocalResidual,
+              TwoPNILocalResidual<TypeTag>);
+
+//! the Model property
+SET_TYPE_PROP(BoxTwoPNI, Model, TwoPNIModel<TypeTag>);
+
+//! the VolumeVariables property
+SET_TYPE_PROP(BoxTwoPNI, VolumeVariables, TwoPNIVolumeVariables<TypeTag>);
+
+//! the FluxVariables property
+SET_TYPE_PROP(BoxTwoPNI, FluxVariables, TwoPNIFluxVariables<TypeTag>);
+
+//! The indices required by the non-isothermal two-phase model
+SET_TYPE_PROP(BoxTwoPNI, Indices, TwoPNIIndices<TypeTag, 0>);
+
+}
+
+}
+
+#endif
diff --git a/dumux/implicit/2pni/2pnivolumevariables.hh b/dumux/implicit/2pni/2pnivolumevariables.hh
new file mode 100644
index 0000000000..eec5780365
--- /dev/null
+++ b/dumux/implicit/2pni/2pnivolumevariables.hh
@@ -0,0 +1,124 @@
+// -*- mode: C++; tab-width: 4; indent-tabs-mode: nil; c-basic-offset: 4 -*-
+// vi: set et ts=4 sw=4 sts=4:
+/*****************************************************************************
+ *   See the file COPYING for full copying permissions.                      *
+ *                                                                           *
+ *   This program is free software: you can redistribute it and/or modify    *
+ *   it under the terms of the GNU General Public License as published by    *
+ *   the Free Software Foundation, either version 2 of the License, or       *
+ *   (at your option) any later version.                                     *
+ *                                                                           *
+ *   This program is distributed in the hope that it will be useful,         *
+ *   but WITHOUT ANY WARRANTY; without even the implied warranty of          *
+ *   MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the            *
+ *   GNU General Public License for more details.                            *
+ *                                                                           *
+ *   You should have received a copy of the GNU General Public License       *
+ *   along with this program.  If not, see <http://www.gnu.org/licenses/>.   *
+ *****************************************************************************/
+/*!
+ * \file
+ *
+ * \brief Contains the quantities which are are constant within a
+ *        finite volume in the non-isothermal two-phase model.
+ */
+#ifndef DUMUX_2PNI_VOLUME_VARIABLES_HH
+#define DUMUX_2PNI_VOLUME_VARIABLES_HH
+
+#include <dumux/boxmodels/2p/2pvolumevariables.hh>
+
+namespace Dumux
+{
+
+/*!
+ * \ingroup TwoPNIModel
+ * \ingroup BoxVolumeVariables
+ * \brief Contains the quantities which are constant within a
+ *        finite volume in the non-isothermal two-phase model.
+ */
+template <class TypeTag>
+class TwoPNIVolumeVariables : public TwoPVolumeVariables<TypeTag>
+{
+    typedef typename GET_PROP_TYPE(TypeTag, Scalar) Scalar;
+    typedef typename GET_PROP_TYPE(TypeTag, FVElementGeometry) FVElementGeometry;
+    typedef typename GET_PROP_TYPE(TypeTag, Problem) Problem;
+    typedef typename GET_PROP_TYPE(TypeTag, FluidSystem) FluidSystem;
+    typedef typename GET_PROP_TYPE(TypeTag, FluidState) FluidState;
+    typedef typename GET_PROP_TYPE(TypeTag, PrimaryVariables) PrimaryVariables;
+
+    typedef typename GET_PROP_TYPE(TypeTag, Indices) Indices;
+    enum { temperatureIdx = Indices::temperatureIdx };
+
+    typedef typename GET_PROP_TYPE(TypeTag, GridView) GridView;
+    typedef typename GridView::template Codim<0>::Entity Element;
+
+public:
+    /*!
+     * \brief Returns the total internal energy of a phase in the
+     *        sub-control volume.
+     *
+     * \param phaseIdx The phase index
+     *
+     */
+    Scalar internalEnergy(int phaseIdx) const
+    { return this->fluidState_.internalEnergy(phaseIdx); };
+
+    /*!
+     * \brief Returns the total enthalpy of a phase in the sub-control
+     *        volume.
+     *
+     *  \param phaseIdx The phase index
+     */
+    Scalar enthalpy(int phaseIdx) const
+    { return this->fluidState_.enthalpy(phaseIdx); };
+
+    /*!
+     * \brief Returns the total heat capacity \f$\mathrm{[J/K*m^3]}\f$ of the rock matrix in
+     *        the sub-control volume.
+     */
+    Scalar heatCapacity() const
+    { return heatCapacity_; };
+
+protected:
+    // this method gets called by the parent class. since this method
+    // is protected, we are friends with our parent..
+    friend class TwoPVolumeVariables<TypeTag>;
+
+    static Scalar temperature_(const PrimaryVariables &priVars,
+                            const Problem& problem,
+                            const Element &element,
+                            const FVElementGeometry &fvGeometry,
+                            int scvIdx)
+    {
+        return priVars[Indices::temperatureIdx];
+    }
+
+    template<class ParameterCache>
+    static Scalar enthalpy_(const FluidState& fluidState,
+                            const ParameterCache& paramCache,
+                            int phaseIdx)
+    {
+        return FluidSystem::enthalpy(fluidState, paramCache, phaseIdx);
+    }
+
+    /*!
+     * \brief Called by update() to compute the energy related quantities
+     */
+    void updateEnergy_(const PrimaryVariables &priVars,
+                       const Problem &problem,
+                       const Element &element,
+                       const FVElementGeometry &fvGeometry,
+                       int scvIdx,
+                       bool isOldSol)
+    {
+        // copmute and set the heat capacity of the solid phase
+        heatCapacity_ = problem.spatialParams().heatCapacity(element, fvGeometry, scvIdx);
+        Valgrind::CheckDefined(heatCapacity_);
+    }
+
+    Scalar heatCapacity_;
+};
+
+} // end namepace
+
+#endif
diff --git a/dumux/implicit/2pni/Makefile.am b/dumux/implicit/2pni/Makefile.am
new file mode 100644
index 0000000000..5e4f338ee1
--- /dev/null
+++ b/dumux/implicit/2pni/Makefile.am
@@ -0,0 +1,4 @@
+2pnidir = $(includedir)/dumux/boxmodels/2pni
+2pni_HEADERS = *.hh
+
+include $(top_srcdir)/am/global-rules
diff --git a/dumux/implicit/3p3c/3p3cfluxvariables.hh b/dumux/implicit/3p3c/3p3cfluxvariables.hh
new file mode 100644
index 0000000000..a687fb3d64
--- /dev/null
+++ b/dumux/implicit/3p3c/3p3cfluxvariables.hh
@@ -0,0 +1,335 @@
+// -*- mode: C++; tab-width: 4; indent-tabs-mode: nil; c-basic-offset: 4 -*-
+// vi: set et ts=4 sw=4 sts=4:
+/*****************************************************************************
+ *   See the file COPYING for full copying permissions.                      *
+ *                                                                           *
+ *   This program is free software: you can redistribute it and/or modify    *
+ *   it under the terms of the GNU General Public License as published by    *
+ *   the Free Software Foundation, either version 2 of the License, or       *
+ *   (at your option) any later version.                                     *
+ *                                                                           *
+ *   This program is distributed in the hope that it will be useful,         *
+ *   but WITHOUT ANY WARRANTY; without even the implied warranty of          *
+ *   MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the            *
+ *   GNU General Public License for more details.                            *
+ *                                                                           *
+ *   You should have received a copy of the GNU General Public License       *
+ *   along with this program.  If not, see <http://www.gnu.org/licenses/>.   *
+ *****************************************************************************/
+/*!
+ * \file
+ *
+ * \brief   This file contains the data which is required to calculate
+ *          all fluxes of components over a face of a finite volume for
+ *          the two-phase, two-component model.
+ */
+/*!
+ * \ingroup ThreePThreeCModel
+ */
+#ifndef DUMUX_3P3C_FLUX_VARIABLES_HH
+#define DUMUX_3P3C_FLUX_VARIABLES_HH
+
+#include <dumux/common/math.hh>
+#include <dumux/common/spline.hh>
+
+#include "3p3cproperties.hh"
+
+namespace Dumux
+{
+
+/*!
+ * \brief This template class contains the data which is required to
+ *        calculate all fluxes of components over a face of a finite
+ *        volume for the two-phase, two-component model.
+ *
+ * This means pressure and concentration gradients, phase densities at
+ * the integration point, etc.
+ */
+template <class TypeTag>
+class ThreePThreeCFluxVariables : public GET_PROP_TYPE(TypeTag, BaseFluxVariables)
+{
+    typedef typename GET_PROP_TYPE(TypeTag, BaseFluxVariables) BaseFluxVariables;
+    typedef typename GET_PROP_TYPE(TypeTag, Scalar) Scalar;
+    typedef typename GET_PROP_TYPE(TypeTag, GridView) GridView;
+
+    typedef typename GET_PROP_TYPE(TypeTag, Problem) Problem;
+    typedef typename GET_PROP_TYPE(TypeTag, VolumeVariables) VolumeVariables;
+
+    typedef typename GridView::template Codim<0>::Entity Element;
+    typedef typename GET_PROP_TYPE(TypeTag, ElementVolumeVariables) ElementVolumeVariables;
+
+    enum {
+        dim = GridView::dimension,
+        dimWorld = GridView::dimensionworld,
+        numPhases = GET_PROP_VALUE(TypeTag, NumPhases),
+        numComponents = GET_PROP_VALUE(TypeTag, NumComponents)
+    };
+
+    typedef typename GET_PROP_TYPE(TypeTag, FVElementGeometry) FVElementGeometry;
+    typedef typename GET_PROP_TYPE(TypeTag, SpatialParams) SpatialParams;
+    typedef typename FVElementGeometry::SubControlVolumeFace SCVFace;
+
+    typedef Dune::FieldVector<Scalar, dim> 	DimVector;
+    typedef Dune::FieldMatrix<Scalar, dim, dim> DimMatrix;
+
+    typedef typename GET_PROP_TYPE(TypeTag, Indices) Indices;
+    enum {
+        wPhaseIdx = Indices::wPhaseIdx,
+        nPhaseIdx = Indices::nPhaseIdx,
+        gPhaseIdx = Indices::gPhaseIdx,
+
+        wCompIdx = Indices::wCompIdx,
+        nCompIdx = Indices::nCompIdx,
+        gCompIdx = Indices::gCompIdx
+    };
+
+public:
+    /*
+     * \brief The constructor
+     *
+     * \param problem The problem
+     * \param element The finite element
+     * \param fvGeometry The finite-volume geometry in the box scheme
+     * \param faceIdx The local index of the SCV (sub-control-volume) face
+     * \param elemVolVars The volume variables of the current element
+     * \param onBoundary A boolean variable to specify whether the flux variables
+     * are calculated for interior SCV faces or boundary faces, default=false
+     */
+    ThreePThreeCFluxVariables(const Problem &problem,
+                              const Element &element,
+                              const FVElementGeometry &fvGeometry,
+                              const int faceIdx,
+                              const ElementVolumeVariables &elemVolVars,
+                              const bool onBoundary = false)
+    : BaseFluxVariables(problem, element, fvGeometry, faceIdx, elemVolVars, onBoundary)
+    {
+        for (int phaseIdx = 0; phaseIdx < numPhases; ++phaseIdx) {
+            density_[phaseIdx] = Scalar(0);
+            molarDensity_[phaseIdx] = Scalar(0);
+            massFractionCompWGrad_[phaseIdx] = Scalar(0);
+            massFractionCompNGrad_[phaseIdx] = Scalar(0);
+            massFractionCompGGrad_[phaseIdx] = Scalar(0);
+            moleFractionCompWGrad_[phaseIdx] = Scalar(0);
+            moleFractionCompNGrad_[phaseIdx] = Scalar(0);
+            moleFractionCompGGrad_[phaseIdx] = Scalar(0);
+        }
+
+        calculateGradients_(problem, element, elemVolVars);
+        calculateporousDiffCoeff_(problem, element, elemVolVars);
+    };
+
+private:
+    void calculateGradients_(const Problem &problem,
+                             const Element &element,
+                             const ElementVolumeVariables &elemVolVars)
+    {
+        // calculate gradients
+    	DimVector tmp(0.0);
+        for (int idx = 0;
+             idx < this->fvGeometry_.numFAP;
+             idx++) // loop over adjacent vertices
+        {
+            // FE gradient at vertex idx
+            const DimVector &feGrad = this->face().grad[idx];
+
+            // index for the element volume variables 
+            int volVarsIdx = this->face().fapIndices[idx];
+
+            // the concentration gradient of the components
+            // component in the phases
+            tmp = feGrad;
+            tmp *= elemVolVars[volVarsIdx].fluidState().massFraction(wPhaseIdx, wCompIdx);
+            massFractionCompWGrad_[wPhaseIdx] += tmp;
+
+            tmp = feGrad;
+            tmp *= elemVolVars[volVarsIdx].fluidState().massFraction(nPhaseIdx, wCompIdx);
+            massFractionCompWGrad_[nPhaseIdx] += tmp;
+
+            tmp = feGrad;
+            tmp *= elemVolVars[volVarsIdx].fluidState().massFraction(gPhaseIdx, wCompIdx);
+            massFractionCompWGrad_[gPhaseIdx] += tmp;
+
+            tmp = feGrad;
+            tmp *= elemVolVars[volVarsIdx].fluidState().massFraction(wPhaseIdx, nCompIdx);
+            massFractionCompNGrad_[wPhaseIdx] += tmp;
+
+            tmp = feGrad;
+            tmp *= elemVolVars[volVarsIdx].fluidState().massFraction(nPhaseIdx, nCompIdx);
+            massFractionCompNGrad_[nPhaseIdx] += tmp;
+
+            tmp = feGrad;
+            tmp *= elemVolVars[volVarsIdx].fluidState().massFraction(gPhaseIdx, nCompIdx);
+            massFractionCompNGrad_[gPhaseIdx] += tmp;
+
+            tmp = feGrad;
+            tmp *= elemVolVars[volVarsIdx].fluidState().massFraction(wPhaseIdx, gCompIdx);
+            massFractionCompGGrad_[wPhaseIdx] += tmp;
+
+            tmp = feGrad;
+            tmp *= elemVolVars[volVarsIdx].fluidState().massFraction(nPhaseIdx, gCompIdx);
+            massFractionCompGGrad_[nPhaseIdx] += tmp;
+
+            tmp = feGrad;
+            tmp *= elemVolVars[volVarsIdx].fluidState().massFraction(gPhaseIdx, gCompIdx);
+            massFractionCompGGrad_[gPhaseIdx] += tmp;
+
+            // the molar concentration gradients of the components
+            // in the phases
+            tmp = feGrad;
+            tmp *= elemVolVars[volVarsIdx].fluidState().moleFraction(wPhaseIdx, wCompIdx);
+            moleFractionCompWGrad_[wPhaseIdx] += tmp;
+
+            tmp = feGrad;
+            tmp *= elemVolVars[volVarsIdx].fluidState().moleFraction(nPhaseIdx, wCompIdx);
+            moleFractionCompWGrad_[nPhaseIdx] += tmp;
+
+            tmp = feGrad;
+            tmp *= elemVolVars[volVarsIdx].fluidState().moleFraction(gPhaseIdx, wCompIdx);
+            moleFractionCompWGrad_[gPhaseIdx] += tmp;
+
+            tmp = feGrad;
+            tmp *= elemVolVars[volVarsIdx].fluidState().moleFraction(wPhaseIdx, nCompIdx);
+            moleFractionCompNGrad_[wPhaseIdx] += tmp;
+
+            tmp = feGrad;
+            tmp *= elemVolVars[volVarsIdx].fluidState().moleFraction(nPhaseIdx, nCompIdx);
+            moleFractionCompNGrad_[nPhaseIdx] += tmp;
+
+            tmp = feGrad;
+            tmp *= elemVolVars[volVarsIdx].fluidState().moleFraction(gPhaseIdx, nCompIdx);
+            moleFractionCompNGrad_[gPhaseIdx] += tmp;
+
+            tmp = feGrad;
+            tmp *= elemVolVars[volVarsIdx].fluidState().moleFraction(wPhaseIdx, gCompIdx);
+            moleFractionCompGGrad_[wPhaseIdx] += tmp;
+
+            tmp = feGrad;
+            tmp *= elemVolVars[volVarsIdx].fluidState().moleFraction(nPhaseIdx, gCompIdx);
+            moleFractionCompGGrad_[nPhaseIdx] += tmp;
+
+            tmp = feGrad;
+            tmp *= elemVolVars[volVarsIdx].fluidState().moleFraction(gPhaseIdx, gCompIdx);
+            moleFractionCompGGrad_[gPhaseIdx] += tmp;
+        }
+    }
+
+    Scalar rhoFactor_(int phaseIdx, int scvIdx, const ElementVolumeVariables &elemVolVars)
+    {
+        static const Scalar eps = 1e-2;
+        const Scalar sat = elemVolVars[scvIdx].density(phaseIdx);
+        if (sat > eps)
+            return 0.5;
+        if (sat <= 0)
+            return 0;
+
+        static const Dumux::Spline<Scalar> sp(0, eps, // x0, x1
+                                              0, 0.5, // y0, y1
+                                              0, 0); // m0, m1
+        return sp.eval(sat);
+    }
+
+    void calculateporousDiffCoeff_(const Problem &problem,
+                               const Element &element,
+                               const ElementVolumeVariables &elemVolVars)
+    {
+
+        const VolumeVariables &volVarsI = elemVolVars[this->face().i];
+        const VolumeVariables &volVarsJ = elemVolVars[this->face().j];
+
+        Dune::FieldMatrix<Scalar, numPhases, numComponents> diffusionCoefficientMatrix_i = volVarsI.diffusionCoefficient();
+        Dune::FieldMatrix<Scalar, numPhases, numComponents> diffusionCoefficientMatrix_j = volVarsJ.diffusionCoefficient();
+
+        for (int phaseIdx = 0; phaseIdx < numPhases; ++phaseIdx)
+        {
+            // make sure to calculate only diffusion coefficents
+            // for phases which exist in both finite volumes
+            /* \todo take care: This should be discussed once again
+             * as long as a meaningful value can be found for the required mole fraction
+             * diffusion should work even without this one here */
+            if (volVarsI.saturation(phaseIdx) <= 0 ||
+                volVarsJ.saturation(phaseIdx) <= 0)
+            {
+                porousDiffCoeff_[phaseIdx][wCompIdx] = 0.0;
+                porousDiffCoeff_[phaseIdx][nCompIdx] = 0.0;
+                porousDiffCoeff_[phaseIdx][gCompIdx] = 0.0;
+                continue;
+            }
+
+            // calculate tortuosity at the nodes i and j needed
+            // for porous media diffusion coefficient
+
+            Scalar tauI =
+                1.0/(volVarsI.porosity() * volVarsI.porosity()) *
+                pow(volVarsI.porosity() * volVarsI.saturation(phaseIdx), 7.0/3);
+            Scalar tauJ =
+                1.0/(volVarsJ.porosity() * volVarsJ.porosity()) *
+                pow(volVarsJ.porosity() * volVarsJ.saturation(phaseIdx), 7.0/3);
+            // Diffusion coefficient in the porous medium
+
+            // -> harmonic mean
+            porousDiffCoeff_[phaseIdx][wCompIdx] = harmonicMean(volVarsI.porosity() * volVarsI.saturation(phaseIdx) * tauI * diffusionCoefficientMatrix_i[phaseIdx][wCompIdx],
+                                                                volVarsJ.porosity() * volVarsJ.saturation(phaseIdx) * tauJ * diffusionCoefficientMatrix_j[phaseIdx][wCompIdx]);
+            porousDiffCoeff_[phaseIdx][nCompIdx] = harmonicMean(volVarsI.porosity() * volVarsI.saturation(phaseIdx) * tauI * diffusionCoefficientMatrix_i[phaseIdx][nCompIdx],
+                                                                volVarsJ.porosity() * volVarsJ.saturation(phaseIdx) * tauJ * diffusionCoefficientMatrix_j[phaseIdx][nCompIdx]);
+            porousDiffCoeff_[phaseIdx][gCompIdx] = harmonicMean(volVarsI.porosity() * volVarsI.saturation(phaseIdx) * tauI * diffusionCoefficientMatrix_i[phaseIdx][gCompIdx],
+                                                                volVarsJ.porosity() * volVarsJ.saturation(phaseIdx) * tauJ * diffusionCoefficientMatrix_j[phaseIdx][gCompIdx]);
+
+        }
+    }
+
+public:
+    /*!
+     * \brief The diffusivity matrix
+     */
+    Dune::FieldMatrix<Scalar, numPhases, numComponents> porousDiffCoeff() const
+    { return porousDiffCoeff_; };
+
+    /*!
+     * \brief Return density \f$\mathrm{[kg/m^3]}\f$ of a phase.
+     */
+    Scalar density(int phaseIdx) const
+    { return density_[phaseIdx]; }
+
+    /*!
+     * \brief Return molar density \f$\mathrm{[mol/m^3]}\f$ of a phase.
+     */
+    Scalar molarDensity(int phaseIdx) const
+    { return molarDensity_[phaseIdx]; }
+
+    const DimVector &massFractionCompWGrad(int phaseIdx) const
+    {return massFractionCompWGrad_[phaseIdx];}
+
+    const DimVector &massFractionCompNGrad(int phaseIdx) const
+    { return massFractionCompNGrad_[phaseIdx]; };
+
+    const DimVector &massFractionCompGGrad(int phaseIdx) const
+    { return massFractionCompGGrad_[phaseIdx]; };
+
+    const DimVector &moleFractionCompWGrad(int phaseIdx) const
+    { return moleFractionCompWGrad_[phaseIdx]; };
+
+    const DimVector &moleFractionCompNGrad(int phaseIdx) const
+    { return moleFractionCompNGrad_[phaseIdx]; };
+
+    const DimVector &moleFractionCompGGrad(int phaseIdx) const
+    { return moleFractionCompGGrad_[phaseIdx]; };
+
+protected:
+    // gradients
+    DimVector massFractionCompWGrad_[numPhases];
+    DimVector massFractionCompNGrad_[numPhases];
+    DimVector massFractionCompGGrad_[numPhases];
+    DimVector moleFractionCompWGrad_[numPhases];
+    DimVector moleFractionCompNGrad_[numPhases];
+    DimVector moleFractionCompGGrad_[numPhases];
+
+    // density of each face at the integration point
+    Scalar density_[numPhases], molarDensity_[numPhases];
+
+    // the diffusivity matrix for the porous medium
+    Dune::FieldMatrix<Scalar, numPhases, numComponents> porousDiffCoeff_;
+};
+
+} // end namepace
+
+#endif
diff --git a/dumux/implicit/3p3c/3p3cindices.hh b/dumux/implicit/3p3c/3p3cindices.hh
new file mode 100644
index 0000000000..33935edd82
--- /dev/null
+++ b/dumux/implicit/3p3c/3p3cindices.hh
@@ -0,0 +1,85 @@
+// -*- mode: C++; tab-width: 4; indent-tabs-mode: nil; c-basic-offset: 4 -*-
+// vi: set et ts=4 sw=4 sts=4:
+/*****************************************************************************
+ *   See the file COPYING for full copying permissions.                      *
+ *                                                                           *
+ *   This program is free software: you can redistribute it and/or modify    *
+ *   it under the terms of the GNU General Public License as published by    *
+ *   the Free Software Foundation, either version 2 of the License, or       *
+ *   (at your option) any later version.                                     *
+ *                                                                           *
+ *   This program is distributed in the hope that it will be useful,         *
+ *   but WITHOUT ANY WARRANTY; without even the implied warranty of          *
+ *   MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the            *
+ *   GNU General Public License for more details.                            *
+ *                                                                           *
+ *   You should have received a copy of the GNU General Public License       *
+ *   along with this program.  If not, see <http://www.gnu.org/licenses/>.   *
+ *****************************************************************************/
+/*!
+ * \file
+ *
+ * \brief Defines the indices required for the 3p3c BOX model.
+ */
+#ifndef DUMUX_3P3C_INDICES_HH
+#define DUMUX_3P3C_INDICES_HH
+
+#include "3p3cproperties.hh"
+
+namespace Dumux
+{
+
+/*!
+ * \brief The indices for the isothermal ThreePThreeC model.
+ *
+ * \tparam formulation The formulation, only pgSwSn
+ * \tparam PVOffset The first index in a primary variable vector.
+ */
+template <class TypeTag, int PVOffset = 0>
+class ThreePThreeCIndices
+{
+    typedef typename GET_PROP_TYPE(TypeTag, FluidSystem) FluidSystem;
+
+public:
+    // Phase indices
+    static const int wPhaseIdx = FluidSystem::wPhaseIdx; //!< index of the wetting liquid phase
+    static const int nPhaseIdx = FluidSystem::nPhaseIdx; //!< index of the nonwetting liquid phase
+    static const int gPhaseIdx = FluidSystem::gPhaseIdx; //!< index of the gas phase
+
+    // Component indices to indicate the main component 
+    // of the corresponding phase at atmospheric pressure 1 bar 
+    // and room temperature 20°C:
+    static const int wCompIdx = FluidSystem::wCompIdx; 
+    static const int nCompIdx = FluidSystem::nCompIdx; 
+    static const int gCompIdx = FluidSystem::gCompIdx; 
+
+    // present phases (-> 'pseudo' primary variable)
+    static const int threePhases = 1; //!< All three phases are present
+    static const int wPhaseOnly = 2; //!< Only the water phase is present
+    static const int gnPhaseOnly = 3; //!< Only gas and NAPL phases are present
+    static const int wnPhaseOnly = 4; //!< Only water and NAPL phases are present
+    static const int gPhaseOnly = 5; //!< Only gas phase is present
+    static const int wgPhaseOnly = 6; //!< Only water and gas phases are present
+
+    // Primary variable indices
+    static const int pressureIdx = PVOffset + 0; //!< Index for gas phase pressure in a solution vector
+    static const int switch1Idx = PVOffset + 1; //!< Index 1 of saturation or mole fraction
+    static const int switch2Idx = PVOffset + 2; //!< Index 2 of saturation or mole fraction
+
+    static const int pgIdx = pressureIdx; //!< Index for gas phase pressure in a solution vector
+    static const int SOrX1Idx = switch1Idx; //!< Index of the either the saturation of the gas phase or the mass fraction secondary component if a phase is not present
+    static const int SOrX2Idx = switch2Idx; //!< Index of the either the saturation of the gas phase or the mass fraction secondary component if a phase is not present
+
+    // equation indices
+    static const int conti0EqIdx = PVOffset    + wCompIdx; //!< Index of the mass conservation equation for the water component
+    static const int conti1EqIdx = conti0EqIdx + nCompIdx; //!< Index of the mass conservation equation for the contaminant component
+    static const int conti2EqIdx = conti0EqIdx + gCompIdx; //!< Index of the mass conservation equation for the gas component
+
+    static const int contiWEqIdx = conti0EqIdx + wCompIdx; //!< index of the mass conservation equation for the water component
+    static const int contiNEqIdx = conti0EqIdx + nCompIdx; //!< index of the mass conservation equation for the contaminant component
+    static const int contiGEqIdx = conti0EqIdx + gCompIdx; //!< index of the mass conservation equation for the air component
+};
+
+}
+
+#endif
diff --git a/dumux/implicit/3p3c/3p3clocalresidual.hh b/dumux/implicit/3p3c/3p3clocalresidual.hh
new file mode 100644
index 0000000000..03b0e2474f
--- /dev/null
+++ b/dumux/implicit/3p3c/3p3clocalresidual.hh
@@ -0,0 +1,264 @@
+// -*- mode: C++; tab-width: 4; indent-tabs-mode: nil; c-basic-offset: 4 -*-
+// vi: set et ts=4 sw=4 sts=4:
+/*****************************************************************************
+ *   See the file COPYING for full copying permissions.                      *
+ *                                                                           *
+ *   This program is free software: you can redistribute it and/or modify    *
+ *   it under the terms of the GNU General Public License as published by    *
+ *   the Free Software Foundation, either version 2 of the License, or       *
+ *   (at your option) any later version.                                     *
+ *                                                                           *
+ *   This program is distributed in the hope that it will be useful,         *
+ *   but WITHOUT ANY WARRANTY; without even the implied warranty of          *
+ *   MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the            *
+ *   GNU General Public License for more details.                            *
+ *                                                                           *
+ *   You should have received a copy of the GNU General Public License       *
+ *   along with this program.  If not, see <http://www.gnu.org/licenses/>.   *
+ *****************************************************************************/
+/*!
+ * \file
+ *
+ * \brief Element-wise calculation of the Jacobian matrix for problems
+ *        using the two-phase two-component box model.
+ */
+#ifndef DUMUX_3P3C_LOCAL_RESIDUAL_HH
+#define DUMUX_3P3C_LOCAL_RESIDUAL_HH
+
+#include <dumux/boxmodels/common/boxmodel.hh>
+#include <dumux/common/math.hh>
+
+#include "3p3cproperties.hh"
+#include "3p3cvolumevariables.hh"
+#include "3p3cfluxvariables.hh"
+#include "3p3cnewtoncontroller.hh"
+#include "3p3cproperties.hh"
+
+#include <iostream>
+#include <vector>
+
+//#define VELOCITY_OUTPUT 1 // uncomment this line if an output of the velocity is needed
+
+namespace Dumux
+{
+/*!
+ * \ingroup ThreePThreeCModel
+ * \brief Element-wise calculation of the Jacobian matrix for problems
+ *        using the two-phase two-component box model.
+ *
+ * This class is used to fill the gaps in BoxLocalResidual for the 3P3C flow.
+ */
+template<class TypeTag>
+class ThreePThreeCLocalResidual: public GET_PROP_TYPE(TypeTag, BaseLocalResidual)
+{
+protected:
+    typedef typename GET_PROP_TYPE(TypeTag, LocalResidual) Implementation;
+
+    typedef typename GET_PROP_TYPE(TypeTag, Scalar) Scalar;
+    typedef typename GET_PROP_TYPE(TypeTag, PrimaryVariables) PrimaryVariables;
+    typedef typename GET_PROP_TYPE(TypeTag, Indices) Indices;
+
+    enum {
+        numPhases = GET_PROP_VALUE(TypeTag, NumPhases),
+        numComponents = GET_PROP_VALUE(TypeTag, NumComponents),
+
+        conti0EqIdx = Indices::conti0EqIdx,//!< Index of the mass conservation equation for the water component
+        conti1EqIdx = Indices::conti1EqIdx,//!< Index of the mass conservation equation for the contaminant component
+        conti2EqIdx = Indices::conti2EqIdx,//!< Index of the mass conservation equation for the gas component
+
+        wPhaseIdx = Indices::wPhaseIdx,
+        nPhaseIdx = Indices::nPhaseIdx,
+        gPhaseIdx = Indices::gPhaseIdx,
+
+        wCompIdx = Indices::wCompIdx,
+        nCompIdx = Indices::nCompIdx,
+        gCompIdx = Indices::gCompIdx
+    };
+
+    typedef typename GET_PROP_TYPE(TypeTag, VolumeVariables) VolumeVariables;
+    typedef typename GET_PROP_TYPE(TypeTag, ElementVolumeVariables) ElementVolumeVariables;
+    typedef typename GET_PROP_TYPE(TypeTag, FluxVariables) FluxVariables;
+
+public:
+    /*!
+     * \brief Evaluate the amount all conservation quantities
+     *        (e.g. phase mass) within a sub-control volume.
+     *
+     * The result should be averaged over the volume (e.g. phase mass
+     * inside a sub control volume divided by the volume)
+     *
+     *  \param storage The mass of the component within the sub-control volume
+     *  \param scvIdx The SCV (sub-control-volume) index
+     *  \param usePrevSol Evaluate function with solution of current or previous time step
+     */
+    void computeStorage(PrimaryVariables &storage, const int scvIdx, bool usePrevSol) const
+    {
+        // if flag usePrevSol is set, the solution from the previous
+        // time step is used, otherwise the current solution is
+        // used. The secondary variables are used accordingly.  This
+        // is required to compute the derivative of the storage term
+        // using the implicit euler method.
+        const ElementVolumeVariables &elemVolVars =
+            usePrevSol
+            ? this->prevVolVars_()
+            : this->curVolVars_();
+        const VolumeVariables &volVars = elemVolVars[scvIdx];
+
+        // compute storage term of all components within all phases
+        storage = 0;
+        for (int compIdx = 0; compIdx < numComponents; ++compIdx)
+        {
+            for (int phaseIdx = 0; phaseIdx < numPhases; ++phaseIdx)
+            {
+                storage[conti0EqIdx + compIdx] +=
+                    volVars.porosity()
+                    * volVars.saturation(phaseIdx)
+                    * volVars.molarDensity(phaseIdx)
+                    * volVars.fluidState().moleFraction(phaseIdx, compIdx);
+            }
+        }
+    }
+
+    /*!
+     * \brief Evaluates the total flux of all conservation quantities
+     *        over a face of a sub-control volume.
+     *
+     * \param flux The flux over the SCV (sub-control-volume) face for each component
+     * \param faceIdx The index of the SCV face
+     * \param onBoundary A boolean variable to specify whether the flux variables
+     *        are calculated for interior SCV faces or boundary faces, default=false
+     */
+    void computeFlux(PrimaryVariables &flux, const int faceIdx, const bool onBoundary=false) const
+    {
+        FluxVariables fluxVars(this->problem_(),
+                           this->element_(),
+                           this->fvGeometry_(),
+                           faceIdx,
+                           this->curVolVars_(),
+                           onBoundary);
+
+        flux = 0;
+        asImp_()->computeAdvectiveFlux(flux, fluxVars);
+        asImp_()->computeDiffusiveFlux(flux, fluxVars);
+    }
+
+    /*!
+     * \brief Evaluates the advective mass flux of all components over
+     *        a face of a subcontrol volume.
+     *
+     * \param flux The advective flux over the sub-control-volume face for each component
+     * \param fluxVars The flux variables at the current SCV
+     */
+
+    void computeAdvectiveFlux(PrimaryVariables &flux, const FluxVariables &fluxVars) const
+    {
+        Scalar massUpwindWeight = GET_PARAM_FROM_GROUP(TypeTag, Scalar, Implicit, MassUpwindWeight);
+
+        ////////
+        // advective fluxes of all components in all phases
+        ////////
+        for (int phaseIdx = 0; phaseIdx < numPhases; ++phaseIdx)
+        {
+            // data attached to upstream and the downstream vertices
+            // of the current phase
+            const VolumeVariables &up = this->curVolVars_(fluxVars.upstreamIdx(phaseIdx));
+            const VolumeVariables &dn = this->curVolVars_(fluxVars.downstreamIdx(phaseIdx));
+
+            for (int compIdx = 0; compIdx < numComponents; ++compIdx)
+            {
+                // add advective flux of current component in current
+                // phase
+                // if alpha > 0 und alpha < 1 then both upstream and downstream
+                // nodes need their contribution
+                // if alpha == 1 (which is mostly the case) then, the downstream
+                // node is not evaluated
+                int eqIdx = conti0EqIdx + compIdx;
+                flux[eqIdx] += fluxVars.volumeFlux(phaseIdx)
+                    * (massUpwindWeight
+                       * up.fluidState().molarDensity(phaseIdx)
+                       * up.fluidState().moleFraction(phaseIdx, compIdx)
+                       +
+                       (1.0 - massUpwindWeight)
+                       * dn.fluidState().molarDensity(phaseIdx)
+                       * dn.fluidState().moleFraction(phaseIdx, compIdx));
+            }
+        }
+    }
+
+    /*!
+     * \brief Adds the diffusive mass flux of all components over
+     *        a face of a subcontrol volume.
+     *
+     * \param flux The diffusive flux over the sub-control-volume face for each component
+     * \param fluxVars The flux variables at the current SCV
+     */
+
+    void computeDiffusiveFlux(PrimaryVariables &flux, const FluxVariables &fluxVars) const
+    {
+        // TODO: reference!?  Dune::FieldMatrix<Scalar, numPhases, numComponents> averagedPorousDiffCoeffMatrix = fluxVars.porousDiffCoeff();
+        // add diffusive flux of gas component in liquid phase
+        Scalar tmp = - fluxVars.porousDiffCoeff()[wPhaseIdx][gCompIdx] * fluxVars.molarDensity(wPhaseIdx);
+        tmp *= (fluxVars.moleFractionCompGGrad(wPhaseIdx) * fluxVars.face().normal);
+        Scalar jGW = tmp;
+
+        tmp = - fluxVars.porousDiffCoeff()[wPhaseIdx][nCompIdx] * fluxVars.molarDensity(wPhaseIdx);
+        tmp *= (fluxVars.moleFractionCompNGrad(wPhaseIdx) * fluxVars.face().normal);
+        Scalar jNW = tmp;
+
+        Scalar jWW = -(jGW+jNW);
+
+        tmp = - fluxVars.porousDiffCoeff()[gPhaseIdx][wCompIdx] * fluxVars.molarDensity(gPhaseIdx);
+        tmp *= (fluxVars.moleFractionCompWGrad(gPhaseIdx) * fluxVars.face().normal);
+        Scalar jWG = tmp;
+
+        tmp = - fluxVars.porousDiffCoeff()[gPhaseIdx][nCompIdx] * fluxVars.molarDensity(gPhaseIdx);
+        tmp *= (fluxVars.moleFractionCompNGrad(gPhaseIdx) * fluxVars.face().normal);
+        Scalar jNG = tmp;
+
+        Scalar jGG = -(jWG+jNG);
+
+        tmp = - fluxVars.porousDiffCoeff()[nPhaseIdx][wCompIdx] * fluxVars.molarDensity(nPhaseIdx);
+        tmp *= (fluxVars.moleFractionCompWGrad(nPhaseIdx) * fluxVars.face().normal);
+        Scalar jWN = tmp;
+
+        tmp = - fluxVars.porousDiffCoeff()[nPhaseIdx][gCompIdx] * fluxVars.molarDensity(nPhaseIdx);
+        tmp *= (fluxVars.moleFractionCompGGrad(nPhaseIdx) * fluxVars.face().normal);
+        Scalar jGN = tmp;
+
+        Scalar jNN = -(jGN+jWN);
+
+        flux[conti0EqIdx] += jWW+jWG+jWN;
+        flux[conti1EqIdx] += jNW+jNG+jNN;
+        flux[conti2EqIdx] += jGW+jGG+jGN;
+    }
+
+    /*!
+     * \brief Calculate the source term of the equation
+     *
+     * \param source The source/sink in the SCV for each component
+     * \param scvIdx The index of the SCV
+     */
+    void computeSource(PrimaryVariables &source, const int scvIdx)
+    {
+        this->problem_().boxSDSource(source,
+                                     this->element_(),
+                                     this->fvGeometry_(),
+                                     scvIdx,
+                                     this->curVolVars_());
+    }
+
+protected:
+    Implementation *asImp_()
+    {
+        return static_cast<Implementation *> (this);
+    }
+
+    const Implementation *asImp_() const
+    {
+        return static_cast<const Implementation *> (this);
+    }
+};
+
+} // end namepace
+
+#endif
diff --git a/dumux/implicit/3p3c/3p3cmodel.hh b/dumux/implicit/3p3c/3p3cmodel.hh
new file mode 100644
index 0000000000..c12cadbb93
--- /dev/null
+++ b/dumux/implicit/3p3c/3p3cmodel.hh
@@ -0,0 +1,952 @@
+// -*- mode: C++; tab-width: 4; indent-tabs-mode: nil; c-basic-offset: 4 -*-
+// vi: set et ts=4 sw=4 sts=4:
+/*****************************************************************************
+ *   See the file COPYING for full copying permissions.                      *
+ *                                                                           *
+ *   This program is free software: you can redistribute it and/or modify    *
+ *   it under the terms of the GNU General Public License as published by    *
+ *   the Free Software Foundation, either version 2 of the License, or       *
+ *   (at your option) any later version.                                     *
+ *                                                                           *
+ *   This program is distributed in the hope that it will be useful,         *
+ *   but WITHOUT ANY WARRANTY; without even the implied warranty of          *
+ *   MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the            *
+ *   GNU General Public License for more details.                            *
+ *                                                                           *
+ *   You should have received a copy of the GNU General Public License       *
+ *   along with this program.  If not, see <http://www.gnu.org/licenses/>.   *
+ *****************************************************************************/
+/*!
+ * \file
+ *
+ * \brief Adaption of the BOX scheme to the three-phase three-component flow model.
+ *
+ * The model is designed for simulating three fluid phases with water, gas, and
+ * a liquid contaminant (NAPL - non-aqueous phase liquid)
+ */
+#ifndef DUMUX_3P3C_MODEL_HH
+#define DUMUX_3P3C_MODEL_HH
+
+#include <dumux/material/fluidstates/compositionalfluidstate.hh>
+
+#include "3p3cproperties.hh"
+#include "3p3clocalresidual.hh"
+
+namespace Dumux
+{
+/*!
+ * \ingroup ThreePThreeCModel
+ * \brief Adaption of the BOX scheme to the three-phase three-component flow model.
+ *
+ * This model implements three-phase three-component flow of three fluid phases
+ * \f$\alpha \in \{ water, gas, NAPL \}\f$ each composed of up to three components
+ * \f$\kappa \in \{ water, air, contaminant \}\f$. The standard multiphase Darcy
+ * approach is used as the equation for the conservation of momentum:
+ * \f[
+ v_\alpha = - \frac{k_{r\alpha}}{\mu_\alpha} \mbox{\bf K}
+ \left(\text{grad}\, p_\alpha - \varrho_{\alpha} \mbox{\bf g} \right)
+ * \f]
+ *
+ * By inserting this into the equations for the conservation of the
+ * components, one transport equation for each component is obtained as
+ * \f{eqnarray*}
+ && \phi \frac{\partial (\sum_\alpha \varrho_{\text{mol}, \alpha} x_\alpha^\kappa
+ S_\alpha )}{\partial t}
+ - \sum\limits_\alpha \text{div} \left\{ \frac{k_{r\alpha}}{\mu_\alpha}
+ \varrho_{\text{mol}, \alpha} x_\alpha^\kappa \mbox{\bf K}
+ (\text{grad}\, p_\alpha - \varrho_{\text{mass}, \alpha} \mbox{\bf g}) \right\}
+ \nonumber \\
+ \nonumber \\
+ && - \sum\limits_\alpha \text{div} \left\{ D_{pm}^\kappa \varrho_{\text{mol},
+ \alpha } \text{grad}\, x_\alpha^\kappa \right\}
+ - q^\kappa = 0 \qquad \forall \kappa , \; \forall \alpha
+ \f}
+ *
+ * Note that these balance equations are molar.
+ *
+ * The equations are discretized using a fully-coupled vertex
+ * centered finite volume (BOX) scheme as spatial scheme and
+ * the implicit Euler method as temporal discretization.
+ *
+ * The model uses commonly applied auxiliary conditions like
+ * \f$S_w + S_n + S_g = 1\f$ for the saturations and
+ * \f$x^w_\alpha + x^a_\alpha + x^c_\alpha = 1\f$ for the mole fractions.
+ * Furthermore, the phase pressures are related to each other via
+ * capillary pressures between the fluid phases, which are functions of
+ * the saturation, e.g. according to the approach of Parker et al.
+ *
+ * The used primary variables are dependent on the locally present fluid phases
+ * An adaptive primary variable switch is included. The phase state is stored for all nodes
+ * of the system. The following cases can be distinguished:
+ * <ul>
+ *  <li> All three phases are present: Primary variables are two saturations \f$(S_w\f$ and \f$S_n)\f$, and a pressure, in this case \f$p_g\f$. </li>
+ *  <li> Only the water phase is present: Primary variables are now the mole fractions of air and contaminant in the water phase \f$(x_w^a\f$ and \f$x_w^c)\f$, as well as the gas pressure, which is, of course, in a case where only the water phase is present, just the same as the water pressure. </li>
+ *  <li> Gas and NAPL phases are present: Primary variables \f$(S_n\f$, \f$x_g^w\f$, \f$p_g)\f$. </li>
+ *  <li> Water and NAPL phases are present: Primary variables \f$(S_n\f$, \f$x_w^a\f$, \f$p_g)\f$. </li>
+ *  <li> Only gas phase is present: Primary variables \f$(x_g^w\f$, \f$x_g^c\f$, \f$p_g)\f$. </li>
+ *  <li> Water and gas phases are present: Primary variables \f$(S_w\f$, \f$x_w^g\f$, \f$p_g)\f$. </li>
+ * </ul>
+ */
+template<class TypeTag>
+class ThreePThreeCModel: public GET_PROP_TYPE(TypeTag, BaseModel)
+{
+    typedef typename GET_PROP_TYPE(TypeTag, BaseModel) ParentType;
+
+    typedef typename GET_PROP_TYPE(TypeTag, Scalar) Scalar;
+    typedef typename GET_PROP_TYPE(TypeTag, Problem) Problem;
+    typedef typename GET_PROP_TYPE(TypeTag, FluidSystem) FluidSystem;
+    typedef typename GET_PROP_TYPE(TypeTag, GridView) GridView;
+
+    typedef typename GET_PROP_TYPE(TypeTag, FVElementGeometry) FVElementGeometry;
+    typedef typename GET_PROP_TYPE(TypeTag, PrimaryVariables) PrimaryVariables;
+    typedef typename GET_PROP_TYPE(TypeTag, VolumeVariables) VolumeVariables;
+    typedef typename GET_PROP_TYPE(TypeTag, SolutionVector) SolutionVector;
+    typedef typename GET_PROP_TYPE(TypeTag, Indices) Indices;
+
+    enum {
+        dim = GridView::dimension,
+        dimWorld = GridView::dimensionworld,
+
+        numPhases = GET_PROP_VALUE(TypeTag, NumPhases),
+        numComponents = GET_PROP_VALUE(TypeTag, NumComponents),
+
+        pressureIdx = Indices::pressureIdx,
+        switch1Idx = Indices::switch1Idx,
+        switch2Idx = Indices::switch2Idx,
+
+
+        wPhaseIdx = Indices::wPhaseIdx,
+        nPhaseIdx = Indices::nPhaseIdx,
+        gPhaseIdx = Indices::gPhaseIdx,
+
+        wCompIdx = Indices::wCompIdx,
+        nCompIdx = Indices::nCompIdx,
+        gCompIdx = Indices::gCompIdx,
+
+        threePhases = Indices::threePhases,
+        wPhaseOnly  = Indices::wPhaseOnly,
+        gnPhaseOnly = Indices::gnPhaseOnly,
+        wnPhaseOnly = Indices::wnPhaseOnly,
+        gPhaseOnly  = Indices::gPhaseOnly,
+        wgPhaseOnly = Indices::wgPhaseOnly
+
+    };
+
+
+    typedef typename GridView::template Codim<dim>::Entity Vertex;
+    typedef typename GridView::template Codim<0>::Entity Element;
+    typedef typename GridView::template Codim<0>::Iterator ElementIterator;
+    typedef typename GridView::template Codim<dim>::Iterator VertexIterator;
+
+    typedef Dune::FieldVector<Scalar, dimWorld> GlobalPosition;
+public:
+    /*!
+     * \brief Initialize the static data with the initial solution.
+     *
+     * \param problem The problem to be solved
+     */
+    void init(Problem &problem)
+    {
+        ParentType::init(problem);
+
+        staticVertexDat_.resize(this->gridView_().size(dim));
+
+        setSwitched_(false);
+
+        VertexIterator it = this->gridView_().template begin<dim> ();
+        const VertexIterator &endit = this->gridView_().template end<dim> ();
+        for (; it != endit; ++it)
+        {
+            int globalIdx = this->dofMapper().map(*it);
+            const GlobalPosition &globalPos = it->geometry().corner(0);
+
+            // initialize phase presence
+            staticVertexDat_[globalIdx].phasePresence
+                = this->problem_().initialPhasePresence(*it, globalIdx,
+                                                        globalPos);
+            staticVertexDat_[globalIdx].wasSwitched = false;
+
+            staticVertexDat_[globalIdx].oldPhasePresence
+                = staticVertexDat_[globalIdx].phasePresence;
+        }
+    }
+
+    /*!
+     * \brief Compute the total storage inside one phase of all
+     *        conservation quantities.
+     *
+     * \param dest Contains the storage of each component for one phase
+     * \param phaseIdx The phase index
+     */
+    void globalPhaseStorage(PrimaryVariables &dest, int phaseIdx)
+    {
+        dest = 0;
+
+        ElementIterator elemIt = this->gridView_().template begin<0>();
+        const ElementIterator elemEndIt = this->gridView_().template end<0>();
+        for (; elemIt != elemEndIt; ++elemIt) {
+            this->localResidual().evalPhaseStorage(*elemIt, phaseIdx);
+
+            for (int i = 0; i < elemIt->template count<dim>(); ++i)
+                dest += this->localResidual().residual(i);
+        }
+
+        if (this->gridView_().comm().size() > 1)
+            dest = this->gridView_().comm().sum(dest);
+    }
+
+    /*!
+     * \brief Called by the update() method if applying the newton
+     *         method was unsuccessful.
+     */
+    void updateFailed()
+    {
+        ParentType::updateFailed();
+
+        setSwitched_(false);
+        resetPhasePresence_();
+    };
+
+    /*!
+     * \brief Called by the problem if a time integration was
+     *        successful, post processing of the solution is done and the
+     *        result has been written to disk.
+     *
+     * This should prepare the model for the next time integration.
+     */
+    void advanceTimeLevel()
+    {
+        ParentType::advanceTimeLevel();
+
+        // update the phase state
+        updateOldPhasePresence_();
+        setSwitched_(false);
+    }
+
+    /*!
+     * \brief Return true if the primary variables were switched for
+     *        at least one vertex after the last timestep.
+     */
+    bool switched() const
+    {
+        return switchFlag_;
+    }
+
+    /*!
+     * \brief Returns the phase presence of the current or the old solution of a vertex.
+     *
+     * \param globalVertexIdx The global vertex index
+     * \param oldSol Evaluate function with solution of current or previous time step
+     */
+    int phasePresence(int globalVertexIdx, bool oldSol) const
+    {
+        return
+            oldSol
+            ? staticVertexDat_[globalVertexIdx].oldPhasePresence
+            : staticVertexDat_[globalVertexIdx].phasePresence;
+    }
+
+    /*!
+     * \brief Append all quantities of interest which can be derived
+     *        from the solution of the current time step to the VTK
+     *        writer.
+     *
+     * \param sol The solution vector
+     * \param writer The writer for multi-file VTK datasets
+     */
+    template<class MultiWriter>
+    void addOutputVtkFields(const SolutionVector &sol,
+                            MultiWriter &writer)
+    {
+        typedef Dune::BlockVector<Dune::FieldVector<double, 1> > ScalarField;
+
+        // create the required scalar fields
+        unsigned numVertices = this->problem_().gridView().size(dim);
+
+        ScalarField *saturation[numPhases];
+        ScalarField *pressure[numPhases];
+        ScalarField *density[numPhases];
+
+        for (int phaseIdx = 0; phaseIdx < numPhases; ++ phaseIdx) {
+            saturation[phaseIdx] = writer.allocateManagedBuffer(numVertices);
+            pressure[phaseIdx] = writer.allocateManagedBuffer(numVertices);
+            density[phaseIdx] = writer.allocateManagedBuffer(numVertices);
+        }
+
+        ScalarField *phasePresence = writer.allocateManagedBuffer (numVertices);
+        ScalarField *moleFraction[numPhases][numComponents];
+        for (int i = 0; i < numPhases; ++i)
+            for (int j = 0; j < numComponents; ++j)
+                moleFraction[i][j] = writer.allocateManagedBuffer (numVertices);
+        ScalarField *temperature = writer.allocateManagedBuffer (numVertices);
+        ScalarField *poro = writer.allocateManagedBuffer(numVertices);
+        ScalarField *perm = writer.allocateManagedBuffer(numVertices);
+
+        unsigned numElements = this->gridView_().size(0);
+        ScalarField *rank =
+            writer.allocateManagedBuffer (numElements);
+
+        FVElementGeometry fvGeometry;
+        VolumeVariables volVars;
+
+        ElementIterator elemIt = this->gridView_().template begin<0>();
+        ElementIterator elemEndIt = this->gridView_().template end<0>();
+        for (; elemIt != elemEndIt; ++elemIt)
+        {
+            int idx = this->problem_().elementMapper().map(*elemIt);
+            (*rank)[idx] = this->gridView_().comm().rank();
+            fvGeometry.update(this->gridView_(), *elemIt);
+
+            int numVerts = elemIt->template count<dim> ();
+            for (int i = 0; i < numVerts; ++i)
+            {
+                int globalIdx = this->vertexMapper().map(*elemIt, i, dim);
+                volVars.update(sol[globalIdx],
+                               this->problem_(),
+                               *elemIt,
+                               fvGeometry,
+                               i,
+                               false);
+
+                for (int phaseIdx = 0; phaseIdx < numPhases; ++ phaseIdx) {
+                    (*saturation[phaseIdx])[globalIdx] = volVars.fluidState().saturation(phaseIdx);
+                    (*pressure[phaseIdx])[globalIdx] = volVars.fluidState().pressure(phaseIdx);
+                    (*density[phaseIdx])[globalIdx] = volVars.fluidState().density(phaseIdx);
+                }
+
+                for (int phaseIdx = 0; phaseIdx < numPhases; ++phaseIdx) {
+                    for (int compIdx = 0; compIdx < numComponents; ++compIdx) {
+                        (*moleFraction[phaseIdx][compIdx])[globalIdx] =
+                            volVars.fluidState().moleFraction(phaseIdx,
+                                                              compIdx);
+
+                        Valgrind::CheckDefined((*moleFraction[phaseIdx][compIdx])[globalIdx]);
+                    }
+                }
+
+                (*poro)[globalIdx] = volVars.porosity();
+                (*perm)[globalIdx] = volVars.permeability();
+                (*temperature)[globalIdx] = volVars.temperature();
+                (*phasePresence)[globalIdx] = staticVertexDat_[globalIdx].phasePresence;
+            }
+
+        }
+
+        writer.attachVertexData(*saturation[wPhaseIdx], "Sw");
+        writer.attachVertexData(*saturation[nPhaseIdx], "Sn");
+        writer.attachVertexData(*saturation[gPhaseIdx], "Sg");
+        writer.attachVertexData(*pressure[wPhaseIdx], "pw");
+        writer.attachVertexData(*pressure[nPhaseIdx], "pn");
+        writer.attachVertexData(*pressure[gPhaseIdx], "pg");
+        writer.attachVertexData(*density[wPhaseIdx], "rhow");
+        writer.attachVertexData(*density[nPhaseIdx], "rhon");
+        writer.attachVertexData(*density[gPhaseIdx], "rhog");
+
+        for (int i = 0; i < numPhases; ++i)
+        {
+            for (int j = 0; j < numComponents; ++j)
+            {
+                std::ostringstream oss;
+                oss << "x^"
+                    << FluidSystem::phaseName(i)
+                    << "_"
+                    << FluidSystem::componentName(j);
+                writer.attachVertexData(*moleFraction[i][j], oss.str().c_str());
+            }
+        }
+        writer.attachVertexData(*poro, "porosity");
+        writer.attachVertexData(*perm, "permeability");
+        writer.attachVertexData(*temperature, "temperature");
+        writer.attachVertexData(*phasePresence, "phase presence");
+        writer.attachCellData(*rank, "process rank");
+    }
+
+    /*!
+     * \brief Write the current solution to a restart file.
+     *
+     * \param outStream The output stream of one vertex for the restart file
+     * \param vert The vertex
+     */
+    void serializeEntity(std::ostream &outStream, const Vertex &vert)
+    {
+        // write primary variables
+        ParentType::serializeEntity(outStream, vert);
+
+        int vertIdx = this->dofMapper().map(vert);
+        if (!outStream.good())
+            DUNE_THROW(Dune::IOError, "Could not serialize vertex " << vertIdx);
+
+        outStream << staticVertexDat_[vertIdx].phasePresence << " ";
+    }
+
+    /*!
+     * \brief Reads the current solution for a vertex from a restart
+     *        file.
+     *
+     * \param inStream The input stream of one vertex from the restart file
+     * \param vert The vertex
+     */
+    void deserializeEntity(std::istream &inStream, const Vertex &vert)
+    {
+        // read primary variables
+        ParentType::deserializeEntity(inStream, vert);
+
+        // read phase presence
+        int vertIdx = this->dofMapper().map(vert);
+        if (!inStream.good())
+            DUNE_THROW(Dune::IOError,
+                       "Could not deserialize vertex " << vertIdx);
+
+        inStream >> staticVertexDat_[vertIdx].phasePresence;
+        staticVertexDat_[vertIdx].oldPhasePresence
+            = staticVertexDat_[vertIdx].phasePresence;
+
+    }
+
+    /*!
+     * \brief Update the static data of all vertices in the grid.
+     *
+     * \param curGlobalSol The current global solution
+     * \param oldGlobalSol The previous global solution
+     */
+    void updateStaticData(SolutionVector &curGlobalSol,
+                          const SolutionVector &oldGlobalSol)
+    {
+        bool wasSwitched = false;
+
+        for (unsigned i = 0; i < staticVertexDat_.size(); ++i)
+            staticVertexDat_[i].visited = false;
+
+        FVElementGeometry fvGeometry;
+        static VolumeVariables volVars;
+        ElementIterator it = this->gridView_().template begin<0> ();
+        const ElementIterator &endit = this->gridView_().template end<0> ();
+        for (; it != endit; ++it)
+        {
+            fvGeometry.update(this->gridView_(), *it);
+            for (int i = 0; i < fvGeometry.numVertices; ++i)
+            {
+                int globalIdx = this->vertexMapper().map(*it, i, dim);
+
+                if (staticVertexDat_[globalIdx].visited)
+                    continue;
+
+                staticVertexDat_[globalIdx].visited = true;
+                volVars.update(curGlobalSol[globalIdx],
+                               this->problem_(),
+                               *it,
+                               fvGeometry,
+                               i,
+                               false);
+                const GlobalPosition &global = it->geometry().corner(i);
+                if (primaryVarSwitch_(curGlobalSol,
+                                      volVars,
+                                      globalIdx,
+                                      global))
+                    wasSwitched = true;
+            }
+        }
+
+        // make sure that if there was a variable switch in an
+        // other partition we will also set the switch flag
+        // for our partition.
+        if (this->gridView_().comm().size() > 1)
+            wasSwitched = this->gridView_().comm().max(wasSwitched);
+
+        setSwitched_(wasSwitched);
+    }
+
+protected:
+    /*!
+     * \brief Data which is attached to each vertex and is not only
+     *        stored locally.
+     */
+    struct StaticVars
+    {
+        int phasePresence;
+        bool wasSwitched;
+
+        int oldPhasePresence;
+        bool visited;
+    };
+
+    /*!
+     * \brief Reset the current phase presence of all vertices to the old one.
+     *
+     * This is done after an update failed.
+     */
+    void resetPhasePresence_()
+    {
+        int numVertices = this->gridView_().size(dim);
+        for (int i = 0; i < numVertices; ++i)
+        {
+            staticVertexDat_[i].phasePresence
+                = staticVertexDat_[i].oldPhasePresence;
+            staticVertexDat_[i].wasSwitched = false;
+        }
+    }
+
+    /*!
+     * \brief Set the old phase of all verts state to the current one.
+     */
+    void updateOldPhasePresence_()
+    {
+        int numVertices = this->gridView_().size(dim);
+        for (int i = 0; i < numVertices; ++i)
+        {
+            staticVertexDat_[i].oldPhasePresence
+                = staticVertexDat_[i].phasePresence;
+            staticVertexDat_[i].wasSwitched = false;
+        }
+    }
+
+    /*!
+     * \brief Set whether there was a primary variable switch after in
+     *        the last timestep.
+     */
+    void setSwitched_(bool yesno)
+    {
+        switchFlag_ = yesno;
+    }
+
+    //  perform variable switch at a vertex; Returns true if a
+    //  variable switch was performed.
+    bool primaryVarSwitch_(SolutionVector &globalSol,
+                           const VolumeVariables &volVars,
+                           int globalIdx,
+                           const GlobalPosition &globalPos)
+    {
+        // evaluate primary variable switch
+        bool wouldSwitch = false;
+        int phasePresence = staticVertexDat_[globalIdx].phasePresence;
+        int newPhasePresence = phasePresence;
+
+        // check if a primary var switch is necessary
+        if (phasePresence == threePhases)
+        {
+            Scalar Smin = 0;
+            if (staticVertexDat_[globalIdx].wasSwitched)
+                Smin = -0.01;
+
+            if (volVars.saturation(gPhaseIdx) <= Smin)
+            {
+                wouldSwitch = true;
+                // gas phase disappears
+                std::cout << "Gas phase disappears at vertex " << globalIdx
+                          << ", coordinates: " << globalPos << ", Sg: "
+                          << volVars.saturation(gPhaseIdx) << std::endl;
+                newPhasePresence = wnPhaseOnly;
+
+                globalSol[globalIdx][switch1Idx]
+                    = volVars.fluidState().moleFraction(wPhaseIdx, gCompIdx);
+            }
+            else if (volVars.saturation(wPhaseIdx) <= Smin)
+            {
+                wouldSwitch = true;
+                // water phase disappears
+                std::cout << "Water phase disappears at vertex " << globalIdx
+                          << ", coordinates: " << globalPos << ", Sw: "
+                          << volVars.saturation(wPhaseIdx) << std::endl;
+                newPhasePresence = gnPhaseOnly;
+
+                globalSol[globalIdx][switch1Idx]
+                    = volVars.fluidState().moleFraction(gPhaseIdx, wCompIdx);
+            }
+            else if (volVars.saturation(nPhaseIdx) <= Smin)
+            {
+                wouldSwitch = true;
+                // NAPL phase disappears
+                std::cout << "NAPL phase disappears at vertex " << globalIdx
+                          << ", coordinates: " << globalPos << ", Sn: "
+                          << volVars.saturation(nPhaseIdx) << std::endl;
+                newPhasePresence = wgPhaseOnly;
+
+                globalSol[globalIdx][switch2Idx]
+                    = volVars.fluidState().moleFraction(gPhaseIdx, nCompIdx);
+            }
+        }
+        else if (phasePresence == wPhaseOnly)
+        {
+            bool gasFlag = 0;
+            bool nonwettingFlag = 0;
+            // calculate fractions of the partial pressures in the
+            // hypothetical gas phase
+            Scalar xwg = volVars.fluidState().moleFraction(gPhaseIdx, wCompIdx);
+            Scalar xgg = volVars.fluidState().moleFraction(gPhaseIdx, gCompIdx);
+            Scalar xng = volVars.fluidState().moleFraction(gPhaseIdx, nCompIdx);
+            /* take care:
+               for xgg in case wPhaseOnly we compute xgg=henry_air*x2w
+               for xwg in case wPhaseOnly we compute xwg=pwsat
+               for xng in case wPhaseOnly we compute xng=henry_NAPL*x1w
+            */
+
+            Scalar xgMax = 1.0;
+            if (xwg + xgg + xng > xgMax)
+                wouldSwitch = true;
+            if (staticVertexDat_[globalIdx].wasSwitched)
+                xgMax *= 1.02;
+
+            // if the sum of the mole fractions would be larger than
+            // 100%, gas phase appears
+            if (xwg + xgg + xng > xgMax)
+            {
+                // gas phase appears
+                std::cout << "gas phase appears at vertex " << globalIdx
+                          << ", coordinates: " << globalPos << ", xwg + xgg + xng: "
+                          << xwg + xgg + xng << std::endl;
+                gasFlag = 1;
+            }
+
+            // calculate fractions in the hypothetical NAPL phase
+            Scalar xnn = volVars.fluidState().moleFraction(nPhaseIdx, nCompIdx);
+            /* take care:
+               for xnn in case wPhaseOnly we compute xnn=henry_mesitylene*x1w,
+               where a hypothetical gas pressure is assumed for the Henry
+               x0n is set to NULL  (all NAPL phase is dirty)
+               x2n is set to NULL  (all NAPL phase is dirty)
+            */
+
+            Scalar xnMax = 1.0;
+            if (xnn > xnMax)
+                wouldSwitch = true;
+            if (staticVertexDat_[globalIdx].wasSwitched)
+                xnMax *= 1.02;
+
+            // if the sum of the hypothetical mole fractions would be larger than
+            // 100%, NAPL phase appears
+            if (xnn > xnMax)
+            {
+                // NAPL phase appears
+                std::cout << "NAPL phase appears at vertex " << globalIdx
+                          << ", coordinates: " << globalPos << ", xnn: "
+                          << xnn << std::endl;
+                nonwettingFlag = 1;
+            }
+
+            if ((gasFlag == 1) && (nonwettingFlag == 0))
+            {
+                newPhasePresence = wgPhaseOnly;
+                globalSol[globalIdx][switch1Idx] = 0.9999;
+                globalSol[globalIdx][switch2Idx] = 0.0001;
+            }
+            else if ((gasFlag == 1) && (nonwettingFlag == 1))
+            {
+                newPhasePresence = threePhases;
+                globalSol[globalIdx][switch1Idx] = 0.9999;
+                globalSol[globalIdx][switch2Idx] = 0.0001;
+            }
+            else if ((gasFlag == 0) && (nonwettingFlag == 1))
+            {
+                newPhasePresence = wnPhaseOnly;
+                globalSol[globalIdx][switch1Idx]
+                    = volVars.fluidState().moleFraction(wPhaseIdx, gCompIdx);
+                globalSol[globalIdx][switch2Idx] = 0.0001;
+            }
+        }
+        else if (phasePresence == gnPhaseOnly)
+        {
+            bool nonwettingFlag = 0;
+            bool wettingFlag = 0;
+
+            Scalar Smin = 0.0;
+            if (staticVertexDat_[globalIdx].wasSwitched)
+                Smin = -0.01;
+
+            if (volVars.saturation(nPhaseIdx) <= Smin)
+            {
+                wouldSwitch = true;
+                // NAPL phase disappears
+                std::cout << "NAPL phase disappears at vertex " << globalIdx
+                          << ", coordinates: " << globalPos << ", Sn: "
+                          << volVars.saturation(nPhaseIdx) << std::endl;
+                nonwettingFlag = 1;
+            }
+
+
+            // calculate fractions of the hypothetical water phase
+            Scalar xww = volVars.fluidState().moleFraction(wPhaseIdx, wCompIdx);
+            /*
+              take care:, xww, if no water is present, then take xww=xwg*pg/pwsat .
+              If this is larger than 1, then water appears
+            */
+            Scalar xwMax = 1.0;
+            if (xww > xwMax)
+                wouldSwitch = true;
+            if (staticVertexDat_[globalIdx].wasSwitched)
+                xwMax *= 1.02;
+
+            // if the sum of the mole fractions would be larger than
+            // 100%, gas phase appears
+            if (xww > xwMax)
+            {
+                // water phase appears
+                std::cout << "water phase appears at vertex " << globalIdx
+                          << ", coordinates: " << globalPos << ", xww=xwg*pg/pwsat : "
+                          << xww << std::endl;
+                wettingFlag = 1;
+            }
+
+            if ((wettingFlag == 1) && (nonwettingFlag == 0))
+            {
+                newPhasePresence = threePhases;
+                globalSol[globalIdx][switch1Idx] = 0.0001;
+                globalSol[globalIdx][switch2Idx] = volVars.saturation(nPhaseIdx);
+            }
+            else if ((wettingFlag == 1) && (nonwettingFlag == 1))
+            {
+                newPhasePresence = wgPhaseOnly;
+                globalSol[globalIdx][switch1Idx] = 0.0001;
+                globalSol[globalIdx][switch2Idx]
+                    = volVars.fluidState().moleFraction(gPhaseIdx, nCompIdx);
+            }
+            else if ((wettingFlag == 0) && (nonwettingFlag == 1))
+            {
+                newPhasePresence = gPhaseOnly;
+                globalSol[globalIdx][switch1Idx]
+                    = volVars.fluidState().moleFraction(gPhaseIdx, wCompIdx);
+                globalSol[globalIdx][switch2Idx]
+                    = volVars.fluidState().moleFraction(gPhaseIdx, nCompIdx);
+            }
+        }
+        else if (phasePresence == wnPhaseOnly)
+        {
+            bool nonwettingFlag = 0;
+            bool gasFlag = 0;
+
+            Scalar Smin = 0.0;
+            if (staticVertexDat_[globalIdx].wasSwitched)
+                Smin = -0.01;
+
+            if (volVars.saturation(nPhaseIdx) <= Smin)
+            {
+                wouldSwitch = true;
+                // NAPL phase disappears
+                std::cout << "NAPL phase disappears at vertex " << globalIdx
+                          << ", coordinates: " << globalPos << ", Sn: "
+                          << volVars.saturation(nPhaseIdx) << std::endl;
+                nonwettingFlag = 1;
+            }
+
+            // calculate fractions of the partial pressures in the
+            // hypothetical gas phase
+            Scalar xwg = volVars.fluidState().moleFraction(gPhaseIdx, wCompIdx);
+            Scalar xgg = volVars.fluidState().moleFraction(gPhaseIdx, gCompIdx);
+            Scalar xng = volVars.fluidState().moleFraction(gPhaseIdx, nCompIdx);
+            /* take care:
+               for xgg in case wPhaseOnly we compute xgg=henry_air*x2w
+               for xwg in case wPhaseOnly we compute xwg=pwsat
+               for xng in case wPhaseOnly we compute xng=henry_NAPL*x1w
+            */
+            Scalar xgMax = 1.0;
+            if (xwg + xgg + xng > xgMax)
+                wouldSwitch = true;
+            if (staticVertexDat_[globalIdx].wasSwitched)
+                xgMax *= 1.02;
+
+            // if the sum of the mole fractions would be larger than
+            // 100%, gas phase appears
+            if (xwg + xgg + xng > xgMax)
+            {
+                // gas phase appears
+                std::cout << "gas phase appears at vertex " << globalIdx
+                          << ", coordinates: " << globalPos << ", xwg + xgg + xng: "
+                          << xwg + xgg + xng << std::endl;
+                gasFlag = 1;
+            }
+
+            if ((gasFlag == 1) && (nonwettingFlag == 0))
+            {
+                newPhasePresence = threePhases;
+                globalSol[globalIdx][switch1Idx] = volVars.saturation(wPhaseIdx);
+                globalSol[globalIdx][switch2Idx] = volVars.saturation(nPhaseIdx);;
+            }
+            else if ((gasFlag == 1) && (nonwettingFlag == 1))
+            {
+                newPhasePresence = wgPhaseOnly;
+                globalSol[globalIdx][switch1Idx] = volVars.saturation(wPhaseIdx);
+                globalSol[globalIdx][switch2Idx]
+                    = volVars.fluidState().moleFraction(gPhaseIdx, nCompIdx);
+            }
+            else if ((gasFlag == 0) && (nonwettingFlag == 1))
+            {
+                newPhasePresence = wPhaseOnly;
+                globalSol[globalIdx][switch1Idx]
+                    = volVars.fluidState().moleFraction(wPhaseIdx, gCompIdx);
+                globalSol[globalIdx][switch2Idx]
+                    = volVars.fluidState().moleFraction(wPhaseIdx, nCompIdx);
+            }
+        }
+        else if (phasePresence == gPhaseOnly)
+        {
+            bool nonwettingFlag = 0;
+            bool wettingFlag = 0;
+
+            // calculate fractions in the hypothetical NAPL phase
+            Scalar xnn = volVars.fluidState().moleFraction(nPhaseIdx, nCompIdx);
+            /*
+              take care:, xnn, if no NAPL phase is there, take xnn=xng*pg/pcsat
+              if this is larger than 1, then NAPL appears
+            */
+
+            Scalar xnMax = 1.0;
+            if (xnn > xnMax)
+                wouldSwitch = true;
+            if (staticVertexDat_[globalIdx].wasSwitched)
+                xnMax *= 1.02;
+
+            // if the sum of the hypothetical mole fraction would be larger than
+            // 100%, NAPL phase appears
+            if (xnn > xnMax)
+            {
+                // NAPL phase appears
+                std::cout << "NAPL phase appears at vertex " << globalIdx
+                          << ", coordinates: " << globalPos << ", xnn: "
+                          << xnn << std::endl;
+                nonwettingFlag = 1;
+            }
+            // calculate fractions of the hypothetical water phase
+            Scalar xww = volVars.fluidState().moleFraction(wPhaseIdx, wCompIdx);
+            /*
+              take care:, xww, if no water is present, then take xww=xwg*pg/pwsat .
+              If this is larger than 1, then water appears
+            */
+            Scalar xwMax = 1.0;
+            if (xww > xwMax)
+                wouldSwitch = true;
+            if (staticVertexDat_[globalIdx].wasSwitched)
+                xwMax *= 1.02;
+
+            // if the sum of the mole fractions would be larger than
+            // 100%, gas phase appears
+            if (xww > xwMax)
+            {
+                // water phase appears
+                std::cout << "water phase appears at vertex " << globalIdx
+                          << ", coordinates: " << globalPos << ", xww=xwg*pg/pwsat : "
+                          << xww << std::endl;
+                wettingFlag = 1;
+            }
+            if ((wettingFlag == 1) && (nonwettingFlag == 0))
+            {
+                newPhasePresence = wgPhaseOnly;
+                globalSol[globalIdx][switch1Idx] = 0.0001;
+                globalSol[globalIdx][switch2Idx]
+                    = volVars.fluidState().moleFraction(gPhaseIdx, nCompIdx);
+            }
+            else if ((wettingFlag == 1) && (nonwettingFlag == 1))
+            {
+                newPhasePresence = threePhases;
+                globalSol[globalIdx][switch1Idx] = 0.0001;
+                globalSol[globalIdx][switch2Idx] = 0.0001;
+            }
+            else if ((wettingFlag == 0) && (nonwettingFlag == 1))
+            {
+                newPhasePresence = gnPhaseOnly;
+                globalSol[globalIdx][switch1Idx]
+                    = volVars.fluidState().moleFraction(gPhaseIdx, wCompIdx);
+                globalSol[globalIdx][switch2Idx] = 0.0001;
+            }
+        }
+        else if (phasePresence == wgPhaseOnly)
+        {
+            bool nonwettingFlag = 0;
+            bool gasFlag = 0;
+            bool wettingFlag = 0;
+
+            // get the fractions in the hypothetical NAPL phase
+            Scalar xnn = volVars.fluidState().moleFraction(nPhaseIdx, nCompIdx);
+
+            // take care: if the NAPL phase is not present, take
+            // xnn=xng*pg/pcsat if this is larger than 1, then NAPL
+            // appears
+            Scalar xnMax = 1.0;
+            if (xnn > xnMax)
+                wouldSwitch = true;
+            if (staticVertexDat_[globalIdx].wasSwitched)
+                xnMax *= 1.02;
+
+            // if the sum of the hypothetical mole fraction would be larger than
+            // 100%, NAPL phase appears
+            if (xnn > xnMax)
+            {
+                // NAPL phase appears
+                std::cout << "NAPL phase appears at vertex " << globalIdx
+                          << ", coordinates: " << globalPos << ", xnn: "
+                          << xnn << std::endl;
+                nonwettingFlag = 1;
+            }
+
+            Scalar Smin = -1.e-6;
+            if (staticVertexDat_[globalIdx].wasSwitched)
+                Smin = -0.01;
+
+            if (volVars.saturation(gPhaseIdx) <= Smin)
+            {
+                wouldSwitch = true;
+                // gas phase disappears
+                std::cout << "Gas phase disappears at vertex " << globalIdx
+                          << ", coordinates: " << globalPos << ", Sg: "
+                          << volVars.saturation(gPhaseIdx) << std::endl;
+                gasFlag = 1;
+            }
+
+            Smin = 0.0;
+            if (staticVertexDat_[globalIdx].wasSwitched)
+                Smin = -0.01;
+
+            if (volVars.saturation(wPhaseIdx) <= Smin)
+            {
+                wouldSwitch = true;
+                // gas phase disappears
+                std::cout << "Water phase disappears at vertex " << globalIdx
+                          << ", coordinates: " << globalPos << ", Sw: "
+                          << volVars.saturation(wPhaseIdx) << std::endl;
+                wettingFlag = 1;
+            }
+
+            if ((gasFlag == 0) && (nonwettingFlag == 1) && (wettingFlag == 1))
+            {
+                newPhasePresence = gnPhaseOnly;
+                globalSol[globalIdx][switch1Idx]
+                    = volVars.fluidState().moleFraction(gPhaseIdx, wCompIdx);
+                globalSol[globalIdx][switch2Idx] = 0.0001;
+            }
+            else if ((gasFlag == 0) && (nonwettingFlag == 1) && (wettingFlag == 0))
+            {
+                newPhasePresence = threePhases;
+                globalSol[globalIdx][switch1Idx] = volVars.saturation(wPhaseIdx);
+                globalSol[globalIdx][switch2Idx] = 0.0;
+            }
+            else if ((gasFlag == 1) && (nonwettingFlag == 0) && (wettingFlag == 0))
+            {
+                newPhasePresence = wPhaseOnly;
+                globalSol[globalIdx][switch1Idx]
+                    = volVars.fluidState().moleFraction(wPhaseIdx, gCompIdx);
+                globalSol[globalIdx][switch2Idx]
+                    = volVars.fluidState().moleFraction(wPhaseIdx, nCompIdx);
+            }
+            else if ((gasFlag == 0) && (nonwettingFlag == 0) && (wettingFlag == 1))
+            {
+                newPhasePresence = gPhaseOnly;
+                globalSol[globalIdx][switch1Idx]
+                    = volVars.fluidState().moleFraction(gPhaseIdx, wCompIdx);
+                globalSol[globalIdx][switch2Idx]
+                    = volVars.fluidState().moleFraction(gPhaseIdx, nCompIdx);
+            }
+        }
+
+        staticVertexDat_[globalIdx].phasePresence = newPhasePresence;
+        staticVertexDat_[globalIdx].wasSwitched = wouldSwitch;
+        return phasePresence != newPhasePresence;
+    }
+
+    // parameters given in constructor
+    std::vector<StaticVars> staticVertexDat_;
+    bool switchFlag_;
+};
+
+}
+
+#include "3p3cpropertydefaults.hh"
+
+#endif
diff --git a/dumux/implicit/3p3c/3p3cnewtoncontroller.hh b/dumux/implicit/3p3c/3p3cnewtoncontroller.hh
new file mode 100644
index 0000000000..f0d47996da
--- /dev/null
+++ b/dumux/implicit/3p3c/3p3cnewtoncontroller.hh
@@ -0,0 +1,85 @@
+// -*- mode: C++; tab-width: 4; indent-tabs-mode: nil; c-basic-offset: 4 -*-
+// vi: set et ts=4 sw=4 sts=4:
+/*****************************************************************************
+ *   See the file COPYING for full copying permissions.                      *
+ *                                                                           *
+ *   This program is free software: you can redistribute it and/or modify    *
+ *   it under the terms of the GNU General Public License as published by    *
+ *   the Free Software Foundation, either version 2 of the License, or       *
+ *   (at your option) any later version.                                     *
+ *                                                                           *
+ *   This program is distributed in the hope that it will be useful,         *
+ *   but WITHOUT ANY WARRANTY; without even the implied warranty of          *
+ *   MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the            *
+ *   GNU General Public License for more details.                            *
+ *                                                                           *
+ *   You should have received a copy of the GNU General Public License       *
+ *   along with this program.  If not, see <http://www.gnu.org/licenses/>.   *
+ *****************************************************************************/
+/*!
+ * \file
+ * \brief A 3p3c specific controller for the newton solver.
+ *
+ * This controller 'knows' what a 'physically meaningful' solution is
+ * which allows the newton method to abort quicker if the solution is
+ * way out of bounds.
+ */
+#ifndef DUMUX_3P3C_NEWTON_CONTROLLER_HH
+#define DUMUX_3P3C_NEWTON_CONTROLLER_HH
+
+#include "3p3cproperties.hh"
+
+#include <dumux/nonlinear/newtoncontroller.hh>
+
+namespace Dumux {
+/*!
+ * \ingroup ThreePThreeCModel
+ * \brief A 3p3c specific controller for the newton solver.
+ *
+ * This controller 'knows' what a 'physically meaningful' solution is
+ * which allows the newton method to abort quicker if the solution is
+ * way out of bounds.
+ */
+template <class TypeTag>
+class ThreePThreeCNewtonController : public NewtonController<TypeTag>
+{
+    typedef NewtonController<TypeTag> ParentType;
+    typedef typename GET_PROP_TYPE(TypeTag, Problem) Problem;
+    typedef typename GET_PROP_TYPE(TypeTag, SolutionVector) SolutionVector;
+
+public:
+    ThreePThreeCNewtonController(const Problem &problem)
+        : ParentType(problem)
+    {};
+
+
+    /*!
+     * \brief Called after each Newton update
+     *
+     * \param uCurrentIter The current global solution vector
+     * \param uLastIter The previous global solution vector
+     */
+    void newtonEndStep(SolutionVector &uCurrentIter,
+                       const SolutionVector &uLastIter)
+    {
+        // call the method of the base class
+        this->method().model().updateStaticData(uCurrentIter, uLastIter);
+        ParentType::newtonEndStep(uCurrentIter, uLastIter);
+    }
+
+
+    /*!
+     * \brief Returns true if the current solution can be considered to
+     *        be accurate enough
+     */
+    bool newtonConverged()
+    {
+        if (this->method().model().switched())
+            return false;
+
+        return ParentType::newtonConverged();
+    };
+};
+}
+
+#endif
diff --git a/dumux/implicit/3p3c/3p3cproperties.hh b/dumux/implicit/3p3c/3p3cproperties.hh
new file mode 100644
index 0000000000..90ddfaa0d3
--- /dev/null
+++ b/dumux/implicit/3p3c/3p3cproperties.hh
@@ -0,0 +1,66 @@
+// -*- mode: C++; tab-width: 4; indent-tabs-mode: nil; c-basic-offset: 4 -*-
+// vi: set et ts=4 sw=4 sts=4:
+/*****************************************************************************
+ *   See the file COPYING for full copying permissions.                      *
+ *                                                                           *
+ *   This program is free software: you can redistribute it and/or modify    *
+ *   it under the terms of the GNU General Public License as published by    *
+ *   the Free Software Foundation, either version 2 of the License, or       *
+ *   (at your option) any later version.                                     *
+ *                                                                           *
+ *   This program is distributed in the hope that it will be useful,         *
+ *   but WITHOUT ANY WARRANTY; without even the implied warranty of          *
+ *   MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the            *
+ *   GNU General Public License for more details.                            *
+ *                                                                           *
+ *   You should have received a copy of the GNU General Public License       *
+ *   along with this program.  If not, see <http://www.gnu.org/licenses/>.   *
+ *****************************************************************************/
+/*!
+ * \ingroup ThreePThreeCModel
+ */
+/*!
+ * \file
+ *
+ * \brief Defines the properties required for the 3p3c BOX model.
+ */
+#ifndef DUMUX_3P3C_PROPERTIES_HH
+#define DUMUX_3P3C_PROPERTIES_HH
+
+#include <dumux/boxmodels/common/boxproperties.hh>
+
+namespace Dumux
+{
+
+namespace Properties
+{
+//////////////////////////////////////////////////////////////////
+// Type tags
+//////////////////////////////////////////////////////////////////
+
+//! The type tag for the isothermal single phase problems
+NEW_TYPE_TAG(BoxThreePThreeC, INHERITS_FROM(BoxModel));
+
+//////////////////////////////////////////////////////////////////
+// Property tags
+//////////////////////////////////////////////////////////////////
+
+NEW_PROP_TAG(NumPhases);   //!< Number of fluid phases in the system
+NEW_PROP_TAG(NumComponents); //!< Number of fluid components in the system
+NEW_PROP_TAG(Indices); //!< Enumerations for the model
+NEW_PROP_TAG(SpatialParams); //!< The type of the spatial parameters
+NEW_PROP_TAG(FluidSystem); //!< Type of the multi-component relations
+
+NEW_PROP_TAG(MaterialLaw);   //!< The material law which ought to be used (extracted from the spatial parameters)
+NEW_PROP_TAG(MaterialLawParams); //!< The parameters of the material law (extracted from the spatial parameters)
+
+NEW_PROP_TAG(ProblemEnableGravity); //!< Returns whether gravity is considered in the problem
+NEW_PROP_TAG(ImplicitMassUpwindWeight); //!< The value of the upwind parameter for the mobility
+NEW_PROP_TAG(ImplicitMobilityUpwindWeight); //!< Weight for the upwind mobility in the velocity calculation
+NEW_PROP_TAG(UseConstraintSolver); //!< Determines whether a constraint solver should be used explicitly
+NEW_PROP_TAG(BaseFluxVariables); //! The base flux variables
+NEW_PROP_TAG(SpatialParamsForchCoeff); //!< Property for the forchheimer coefficient
+}
+}
+
+#endif
diff --git a/dumux/implicit/3p3c/3p3cpropertydefaults.hh b/dumux/implicit/3p3c/3p3cpropertydefaults.hh
new file mode 100644
index 0000000000..421ddab7bc
--- /dev/null
+++ b/dumux/implicit/3p3c/3p3cpropertydefaults.hh
@@ -0,0 +1,143 @@
+// -*- mode: C++; tab-width: 4; indent-tabs-mode: nil; c-basic-offset: 4 -*-
+// vi: set et ts=4 sw=4 sts=4:
+/*****************************************************************************
+ *   See the file COPYING for full copying permissions.                      *
+ *                                                                           *
+ *   This program is free software: you can redistribute it and/or modify    *
+ *   it under the terms of the GNU General Public License as published by    *
+ *   the Free Software Foundation, either version 2 of the License, or       *
+ *   (at your option) any later version.                                     *
+ *                                                                           *
+ *   This program is distributed in the hope that it will be useful,         *
+ *   but WITHOUT ANY WARRANTY; without even the implied warranty of          *
+ *   MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the            *
+ *   GNU General Public License for more details.                            *
+ *                                                                           *
+ *   You should have received a copy of the GNU General Public License       *
+ *   along with this program.  If not, see <http://www.gnu.org/licenses/>.   *
+ *****************************************************************************/
+/*!
+ * \ingroup ThreePThreeCModel
+ */
+/*!
+ * \file
+ *
+ * \brief Defines default values for most properties required by the
+ *        3p3c box model.
+ */
+#ifndef DUMUX_3P3C_PROPERTY_DEFAULTS_HH
+#define DUMUX_3P3C_PROPERTY_DEFAULTS_HH
+
+#include "3p3cindices.hh"
+
+#include "3p3cmodel.hh"
+#include "3p3cindices.hh"
+#include "3p3cfluxvariables.hh"
+#include "3p3cvolumevariables.hh"
+#include "3p3cproperties.hh"
+#include "3p3cnewtoncontroller.hh"
+// #include "3p3cboundaryvariables.hh"
+
+#include <dumux/boxmodels/common/boxdarcyfluxvariables.hh>
+#include <dumux/material/spatialparams/boxspatialparams.hh>
+
+namespace Dumux
+{
+
+namespace Properties {
+//////////////////////////////////////////////////////////////////
+// Property values
+//////////////////////////////////////////////////////////////////
+
+/*!
+ * \brief Set the property for the number of components.
+ *
+ * We just forward the number from the fluid system and use an static
+ * assert to make sure it is 2.
+ */
+SET_PROP(BoxThreePThreeC, NumComponents)
+{
+ private:
+    typedef typename GET_PROP_TYPE(TypeTag, FluidSystem) FluidSystem;
+
+ public:
+    static const int value = FluidSystem::numComponents;
+
+    static_assert(value == 3,
+                  "Only fluid systems with 3 components are supported by the 3p3c model!");
+};
+
+/*!
+ * \brief Set the property for the number of fluid phases.
+ *
+ * We just forward the number from the fluid system and use an static
+ * assert to make sure it is 2.
+ */
+SET_PROP(BoxThreePThreeC, NumPhases)
+{
+ private:
+    typedef typename GET_PROP_TYPE(TypeTag, FluidSystem) FluidSystem;
+
+ public:
+    static const int value = FluidSystem::numPhases;
+    static_assert(value == 3,
+                  "Only fluid systems with 3 phases are supported by the 3p3c model!");
+};
+
+SET_INT_PROP(BoxThreePThreeC, NumEq, 3); //!< set the number of equations to 2
+
+/*!
+ * \brief Set the property for the material parameters by extracting
+ *        it from the material law.
+ */
+SET_TYPE_PROP(BoxThreePThreeC, MaterialLawParams, typename GET_PROP_TYPE(TypeTag, MaterialLaw)::Params);
+
+//! The local residual function of the conservation equations
+SET_TYPE_PROP(BoxThreePThreeC, LocalResidual, ThreePThreeCLocalResidual<TypeTag>);
+
+//! Use the 3p3c specific newton controller for the 3p3c model
+SET_TYPE_PROP(BoxThreePThreeC, NewtonController, ThreePThreeCNewtonController<TypeTag>);
+
+//! the Model property
+SET_TYPE_PROP(BoxThreePThreeC, Model, ThreePThreeCModel<TypeTag>);
+
+//! the VolumeVariables property
+SET_TYPE_PROP(BoxThreePThreeC, VolumeVariables, ThreePThreeCVolumeVariables<TypeTag>);
+
+//! the FluxVariables property
+SET_TYPE_PROP(BoxThreePThreeC, FluxVariables, ThreePThreeCFluxVariables<TypeTag>);
+
+//! define the base flux variables to realize Darcy flow
+SET_TYPE_PROP(BoxThreePThreeC, BaseFluxVariables, BoxDarcyFluxVariables<TypeTag>);
+
+//! the upwind factor for the mobility.
+SET_SCALAR_PROP(BoxThreePThreeC, ImplicitMassUpwindWeight, 1.0);
+
+//! set default mobility upwind weight to 1.0, i.e. fully upwind
+SET_SCALAR_PROP(BoxThreePThreeC, ImplicitMobilityUpwindWeight, 1.0);
+
+//! Determines whether a constraint solver should be used explicitly
+SET_BOOL_PROP(BoxThreePThreeC, UseConstraintSolver, false);
+
+//! The indices required by the isothermal 3p3c model
+SET_TYPE_PROP(BoxThreePThreeC, Indices, ThreePThreeCIndices<TypeTag, /*PVOffset=*/0>);
+
+//! The spatial parameters to be employed. 
+//! Use BoxSpatialParams by default.
+SET_TYPE_PROP(BoxThreePThreeC, SpatialParams, BoxSpatialParams<TypeTag>);
+
+// enable gravity by default
+SET_BOOL_PROP(BoxThreePThreeC, ProblemEnableGravity, true);
+
+//! default value for the forchheimer coefficient
+// Source: Ward, J.C. 1964 Turbulent flow in porous media. ASCE J. Hydraul. Div 90.
+//        Actually the Forchheimer coefficient is also a function of the dimensions of the
+//        porous medium. Taking it as a constant is only a first approximation
+//        (Nield, Bejan, Convection in porous media, 2006, p. 10)
+SET_SCALAR_PROP(BoxModel, SpatialParamsForchCoeff, 0.55);
+
+}
+
+}
+
+#endif
diff --git a/dumux/implicit/3p3c/3p3cvolumevariables.hh b/dumux/implicit/3p3c/3p3cvolumevariables.hh
new file mode 100644
index 0000000000..ce6349ef8c
--- /dev/null
+++ b/dumux/implicit/3p3c/3p3cvolumevariables.hh
@@ -0,0 +1,732 @@
+// -*- mode: C++; tab-width: 4; indent-tabs-mode: nil; c-basic-offset: 4 -*-
+// vi: set et ts=4 sw=4 sts=4:
+/*****************************************************************************
+ *   See the file COPYING for full copying permissions.                      *
+ *                                                                           *
+ *   This program is free software: you can redistribute it and/or modify    *
+ *   it under the terms of the GNU General Public License as published by    *
+ *   the Free Software Foundation, either version 2 of the License, or       *
+ *   (at your option) any later version.                                     *
+ *                                                                           *
+ *   This program is distributed in the hope that it will be useful,         *
+ *   but WITHOUT ANY WARRANTY; without even the implied warranty of          *
+ *   MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the            *
+ *   GNU General Public License for more details.                            *
+ *                                                                           *
+ *   You should have received a copy of the GNU General Public License       *
+ *   along with this program.  If not, see <http://www.gnu.org/licenses/>.   *
+ *****************************************************************************/
+/*!
+ * \file
+ *
+ * \brief Contains the quantities which are constant within a
+ *        finite volume in the two-phase, two-component model.
+ */
+#ifndef DUMUX_3P3C_VOLUME_VARIABLES_HH
+#define DUMUX_3P3C_VOLUME_VARIABLES_HH
+
+#include <dumux/boxmodels/common/boxmodel.hh>
+#include <dumux/common/math.hh>
+
+#include <dune/common/collectivecommunication.hh>
+#include <vector>
+#include <iostream>
+
+#include "3p3cproperties.hh"
+
+#include <dumux/material/constants.hh>
+#include <dumux/material/fluidstates/compositionalfluidstate.hh>
+#include <dumux/material/constraintsolvers/computefromreferencephase.hh>
+#include <dumux/material/constraintsolvers/misciblemultiphasecomposition.hh>
+
+namespace Dumux
+{
+
+/*!
+ * \ingroup ThreePThreeCModel
+ * \brief Contains the quantities which are are constant within a
+ *        finite volume in the two-phase, two-component model.
+ */
+template <class TypeTag>
+class ThreePThreeCVolumeVariables : public BoxVolumeVariables<TypeTag>
+{
+    typedef BoxVolumeVariables<TypeTag> ParentType;
+    typedef typename GET_PROP_TYPE(TypeTag, VolumeVariables) Implementation;
+
+    typedef typename GET_PROP_TYPE(TypeTag, Scalar) Scalar;
+    typedef typename GET_PROP_TYPE(TypeTag, GridView) GridView;
+    typedef typename GET_PROP_TYPE(TypeTag, Problem) Problem;
+    typedef typename GET_PROP_TYPE(TypeTag, FVElementGeometry) FVElementGeometry;
+    typedef typename GET_PROP_TYPE(TypeTag, PrimaryVariables) PrimaryVariables;
+    typedef typename GET_PROP_TYPE(TypeTag, FluidSystem) FluidSystem;
+    typedef typename GET_PROP_TYPE(TypeTag, MaterialLaw) MaterialLaw;
+    typedef typename GET_PROP_TYPE(TypeTag, MaterialLawParams) MaterialLawParams;
+
+    // constraint solvers
+    typedef Dumux::MiscibleMultiPhaseComposition<Scalar, FluidSystem> MiscibleMultiPhaseComposition;
+    typedef Dumux::ComputeFromReferencePhase<Scalar, FluidSystem> ComputeFromReferencePhase;
+
+    typedef typename GET_PROP_TYPE(TypeTag, Indices) Indices;
+    enum {
+        dim = GridView::dimension,
+
+        numPhases = GET_PROP_VALUE(TypeTag, NumPhases),
+        numComponents = GET_PROP_VALUE(TypeTag, NumComponents),
+
+        wCompIdx = Indices::wCompIdx,
+        gCompIdx = Indices::gCompIdx,
+        nCompIdx = Indices::nCompIdx,
+
+        wPhaseIdx = Indices::wPhaseIdx,
+        gPhaseIdx = Indices::gPhaseIdx,
+        nPhaseIdx = Indices::nPhaseIdx,
+
+        switch1Idx = Indices::switch1Idx,
+        switch2Idx = Indices::switch2Idx,
+        pressureIdx = Indices::pressureIdx
+    };
+
+    // present phases
+    enum {
+        threePhases = Indices::threePhases,
+        wPhaseOnly  = Indices::wPhaseOnly,
+        gnPhaseOnly = Indices::gnPhaseOnly,
+        wnPhaseOnly = Indices::wnPhaseOnly,
+        gPhaseOnly  = Indices::gPhaseOnly,
+        wgPhaseOnly = Indices::wgPhaseOnly
+    };
+
+    typedef typename GridView::template Codim<0>::Entity Element;
+
+    static const Scalar R; // universial gas constant
+
+public:
+    //! The type of the object returned by the fluidState() method
+    typedef Dumux::CompositionalFluidState<Scalar, FluidSystem> FluidState;
+
+
+    /*!
+     * \copydoc BoxVolumeVariables::update
+     */
+    void update(const PrimaryVariables &priVars,
+                const Problem &problem,
+                const Element &element,
+                const FVElementGeometry &fvGeometry,
+                const int scvIdx,
+                bool isOldSol)
+    {
+        ParentType::update(priVars,
+                           problem,
+                           element,
+                           fvGeometry,
+                           scvIdx,
+                           isOldSol);
+
+        bool useConstraintSolver = GET_PROP_VALUE(TypeTag, UseConstraintSolver);
+
+        // capillary pressure parameters
+        const MaterialLawParams &materialParams =
+            problem.spatialParams().materialLawParams(element, fvGeometry, scvIdx);
+
+        int globalVertIdx = problem.model().dofMapper().map(element, scvIdx, dim);
+        int phasePresence = problem.model().phasePresence(globalVertIdx, isOldSol);
+
+        Scalar temp = Implementation::temperature_(priVars, problem, element, fvGeometry, scvIdx);
+        fluidState_.setTemperature(temp);
+
+        /* first the saturations */
+        if (phasePresence == threePhases)
+        {
+            Sw_ = priVars[switch1Idx];
+            Sn_ = priVars[switch2Idx];
+            Sg_ = 1. - Sw_ - Sn_;
+        }
+        else if (phasePresence == wPhaseOnly)
+        {
+            Sw_ = 1.;
+            Sn_ = 0.;
+            Sg_ = 0.;
+        }
+        else if (phasePresence == gnPhaseOnly)
+        {
+            Sw_ = 0.;
+            Sn_ = priVars[switch2Idx];
+            Sg_ = 1. - Sn_;
+        }
+        else if (phasePresence == wnPhaseOnly)
+        {
+            Sn_ = priVars[switch2Idx];
+            Sw_ = 1. - Sn_;
+            Sg_ = 0.;
+        }
+        else if (phasePresence == gPhaseOnly)
+        {
+            Sw_ = 0.;
+            Sn_ = 0.;
+            Sg_ = 1.;
+        }
+        else if (phasePresence == wgPhaseOnly)
+        {
+            Sw_ = priVars[switch1Idx];
+            Sn_ = 0.;
+            Sg_ = 1. - Sw_;
+        }
+        else DUNE_THROW(Dune::InvalidStateException, "phasePresence: " << phasePresence << " is invalid.");
+        Valgrind::CheckDefined(Sg_);
+
+        fluidState_.setSaturation(wPhaseIdx, Sw_);
+        fluidState_.setSaturation(gPhaseIdx, Sg_);
+        fluidState_.setSaturation(nPhaseIdx, Sn_);
+
+        /* now the pressures */
+        pg_ = priVars[pressureIdx];
+
+        // calculate capillary pressures
+        Scalar pCGW = MaterialLaw::pCGW(materialParams, Sw_);
+        Scalar pCNW = MaterialLaw::pCNW(materialParams, Sw_);
+        Scalar pCGN = MaterialLaw::pCGN(materialParams, Sw_ + Sn_);
+
+        Scalar pcAlpha = MaterialLaw::pCAlpha(materialParams, Sn_);
+        Scalar pcNW1 = 0.0; // TODO: this should be possible to assign in the problem file
+
+        pn_ = pg_- pcAlpha * pCGN - (1.-pcAlpha)*(pCGW - pcNW1);
+        pw_ = pn_ - pcAlpha * pCNW - (1.-pcAlpha)*pcNW1;
+
+        fluidState_.setPressure(wPhaseIdx, pw_);
+        fluidState_.setPressure(gPhaseIdx, pg_);
+        fluidState_.setPressure(nPhaseIdx, pn_);
+
+        // calculate and set all fugacity coefficients. this is
+        // possible because we require all phases to be an ideal
+        // mixture, i.e. fugacity coefficients are not supposed to
+        // depend on composition!
+        typename FluidSystem::ParameterCache paramCache;
+        // assert(FluidSystem::isIdealGas(gPhaseIdx));
+        for (int phaseIdx = 0; phaseIdx < numPhases; ++ phaseIdx) {
+            assert(FluidSystem::isIdealMixture(phaseIdx));
+
+            for (int compIdx = 0; compIdx < numComponents; ++ compIdx) {
+                Scalar phi = FluidSystem::fugacityCoefficient(fluidState_, paramCache, phaseIdx, compIdx);
+                fluidState_.setFugacityCoefficient(phaseIdx, compIdx, phi);
+            }
+        }
+
+        // now comes the tricky part: calculate phase composition
+        if (phasePresence == threePhases) {
+            // all phases are present, phase compositions are a
+            // result of the the gas <-> liquid equilibrium. This is
+            // the job of the "MiscibleMultiPhaseComposition"
+            // constraint solver ...
+            if (useConstraintSolver) {
+                MiscibleMultiPhaseComposition::solve(fluidState_,
+                                                     paramCache,
+                                                     /*setViscosity=*/true,
+                                                     /*setInternalEnergy=*/false);
+            } 
+            // ... or calculated explicitly this way ...
+            else {    
+                Scalar partPressH2O = FluidSystem::fugacityCoefficient(fluidState_, 
+                                                                      wPhaseIdx, 
+                                                                      wCompIdx) * pw_;
+                Scalar partPressNAPL = FluidSystem::fugacityCoefficient(fluidState_, 
+                                                                       nPhaseIdx, 
+                                                                       nCompIdx) * pn_;
+                Scalar partPressAir = pg_ - partPressH2O - partPressNAPL;
+
+                Scalar xgn = partPressNAPL/pg_;
+                Scalar xgw = partPressH2O/pg_;
+                Scalar xgg = partPressAir/pg_;
+
+                // actually, it's nothing else than Henry coefficient
+                Scalar xwn = partPressNAPL
+                             / (FluidSystem::fugacityCoefficient(fluidState_,
+                                                                 wPhaseIdx,nCompIdx) 
+                                * pw_);
+                Scalar xwg = partPressAir
+                             / (FluidSystem::fugacityCoefficient(fluidState_,
+                                                                 wPhaseIdx,gCompIdx) 
+                                * pw_);
+                Scalar xww = 1.-xwg-xwn;
+
+                Scalar xnn = 1.-2.e-10;
+                Scalar xna = 1.e-10;
+                Scalar xnw = 1.e-10;
+                 
+                fluidState_.setMoleFraction(wPhaseIdx, wCompIdx, xww);
+                fluidState_.setMoleFraction(wPhaseIdx, gCompIdx, xwg);
+                fluidState_.setMoleFraction(wPhaseIdx, nCompIdx, xwn);
+                fluidState_.setMoleFraction(gPhaseIdx, wCompIdx, xgw);
+                fluidState_.setMoleFraction(gPhaseIdx, gCompIdx, xgg);
+                fluidState_.setMoleFraction(gPhaseIdx, nCompIdx, xgn);
+                fluidState_.setMoleFraction(nPhaseIdx, wCompIdx, xnw);
+                fluidState_.setMoleFraction(nPhaseIdx, gCompIdx, xna);
+                fluidState_.setMoleFraction(nPhaseIdx, nCompIdx, xnn);
+
+                Scalar rhoW = FluidSystem::density(fluidState_, wPhaseIdx);
+                Scalar rhoG = FluidSystem::density(fluidState_, gPhaseIdx);
+                Scalar rhoN = FluidSystem::density(fluidState_, nPhaseIdx);
+
+                fluidState_.setDensity(wPhaseIdx, rhoW);
+                fluidState_.setDensity(gPhaseIdx, rhoG);
+                fluidState_.setDensity(nPhaseIdx, rhoN);
+            }
+        }
+        else if (phasePresence == wPhaseOnly) {
+            // only the water phase is present, water phase composition is
+            // stored explicitly.
+
+            // extract mole fractions in the water phase
+            Scalar xwg = priVars[switch1Idx];
+            Scalar xwn = priVars[switch2Idx];
+            Scalar xww = 1 - xwg - xwn;
+
+            // write water mole fractions in the fluid state
+            fluidState_.setMoleFraction(wPhaseIdx, wCompIdx, xww);
+            fluidState_.setMoleFraction(wPhaseIdx, gCompIdx, xwg);
+            fluidState_.setMoleFraction(wPhaseIdx, nCompIdx, xwn);
+
+            // calculate the composition of the remaining phases (as
+            // well as the densities of all phases). this is the job
+            // of the "ComputeFromReferencePhase" constraint solver ...
+            if (useConstraintSolver)
+            {
+                ComputeFromReferencePhase::solve(fluidState_,
+                                                 paramCache,
+                                                 wPhaseIdx,
+                                                 /*setViscosity=*/true,
+                                                 /*setInternalEnergy=*/false);
+            }
+            // ... or calculated explicitly this way ...
+            else {    
+                // note that the gas phase is actually not existing!
+                // thus, this is used as phase switch criterion
+                Scalar xgg = xwg * FluidSystem::fugacityCoefficient(fluidState_,
+                                                                    wPhaseIdx,gCompIdx)
+                                   * pw_ / pg_;
+                Scalar xgn = xwn * FluidSystem::fugacityCoefficient(fluidState_,
+                                                                    wPhaseIdx,nCompIdx)
+                                   * pw_ / pg_;
+                Scalar xgw = FluidSystem::fugacityCoefficient(fluidState_,
+                                                              wPhaseIdx,wCompIdx)
+                                   * pw_ / pg_;
+
+
+                // note that the gas phase is actually not existing!
+                // thus, this is used as phase switch criterion
+                Scalar xnn = xwn * FluidSystem::fugacityCoefficient(fluidState_,
+                                                                    wPhaseIdx,nCompIdx)
+                                   * pw_;
+                Scalar xna = 1.e-10;
+                Scalar xnw = 1.e-10;
+                 
+                fluidState_.setMoleFraction(gPhaseIdx, wCompIdx, xgw);
+                fluidState_.setMoleFraction(gPhaseIdx, gCompIdx, xgg);
+                fluidState_.setMoleFraction(gPhaseIdx, nCompIdx, xgn);
+                fluidState_.setMoleFraction(nPhaseIdx, wCompIdx, xnw);
+                fluidState_.setMoleFraction(nPhaseIdx, gCompIdx, xna);
+                fluidState_.setMoleFraction(nPhaseIdx, nCompIdx, xnn);
+
+                Scalar rhoW = FluidSystem::density(fluidState_, wPhaseIdx);
+                Scalar rhoG = FluidSystem::density(fluidState_, gPhaseIdx);
+                Scalar rhoN = FluidSystem::density(fluidState_, nPhaseIdx);
+
+                fluidState_.setDensity(wPhaseIdx, rhoW);
+                fluidState_.setDensity(gPhaseIdx, rhoG);
+                fluidState_.setDensity(nPhaseIdx, rhoN);
+            }
+        }
+        else if (phasePresence == gnPhaseOnly) {
+            // only gas and NAPL phases are present
+            // we have all (partly hypothetical) phase pressures
+            // and temperature and the mole fraction of water in
+            // the gas phase
+
+            // we have all (partly hypothetical) phase pressures
+            // and temperature and the mole fraction of water in
+            // the gas phase
+            Scalar partPressNAPL = fluidState_.fugacityCoefficient(nPhaseIdx, nCompIdx)*pn_;
+
+            Scalar xgw = priVars[switch1Idx];
+            Scalar xgn = partPressNAPL/pg_;
+            Scalar xgg = 1.-xgw-xgn;
+
+            // write mole fractions in the fluid state
+            fluidState_.setMoleFraction(gPhaseIdx, wCompIdx, xgw);
+            fluidState_.setMoleFraction(gPhaseIdx, gCompIdx, xgg);
+            fluidState_.setMoleFraction(gPhaseIdx, nCompIdx, xgn);
+
+            // calculate the composition of the remaining phases (as
+            // well as the densities of all phases). this is the job
+            // of the "ComputeFromReferencePhase" constraint solver
+            ComputeFromReferencePhase::solve(fluidState_,
+                                             paramCache,
+                                             gPhaseIdx,
+                                             /*setViscosity=*/true,
+                                             /*setInternalEnergy=*/false);
+        }
+        else if (phasePresence == wnPhaseOnly) {
+            // only water and NAPL phases are present
+            Scalar pPartialC = fluidState_.fugacityCoefficient(nPhaseIdx,nCompIdx)*pn_;
+            Scalar henryC = fluidState_.fugacityCoefficient(wPhaseIdx,nCompIdx)*pw_;
+
+            Scalar xwg = priVars[switch1Idx];
+            Scalar xwn = pPartialC/henryC;
+            Scalar xww = 1.-xwg-xwn;
+
+            // write mole fractions in the fluid state
+            fluidState_.setMoleFraction(wPhaseIdx, wCompIdx, xww);
+            fluidState_.setMoleFraction(wPhaseIdx, gCompIdx, xwg);
+            fluidState_.setMoleFraction(wPhaseIdx, nCompIdx, xwn);
+
+            // calculate the composition of the remaining phases (as
+            // well as the densities of all phases). this is the job
+            // of the "ComputeFromReferencePhase" constraint solver
+            ComputeFromReferencePhase::solve(fluidState_,
+                                             paramCache,
+                                             wPhaseIdx,
+                                             /*setViscosity=*/true,
+                                             /*setInternalEnergy=*/false);
+        }
+        else if (phasePresence == gPhaseOnly) {
+            // only the gas phase is present, gas phase composition is
+            // stored explicitly here below.
+
+            const Scalar xgw = priVars[switch1Idx];
+            const Scalar xgn = priVars[switch2Idx];
+            Scalar xgg = 1 - xgw - xgn;
+
+            // write mole fractions in the fluid state
+            fluidState_.setMoleFraction(gPhaseIdx, wCompIdx, xgw);
+            fluidState_.setMoleFraction(gPhaseIdx, gCompIdx, xgg);
+            fluidState_.setMoleFraction(gPhaseIdx, nCompIdx, xgn);
+
+            // calculate the composition of the remaining phases (as
+            // well as the densities of all phases). this is the job
+            // of the "ComputeFromReferencePhase" constraint solver ...
+            if (useConstraintSolver)
+            {
+                ComputeFromReferencePhase::solve(fluidState_,
+                                                 paramCache,
+                                                 gPhaseIdx,
+                                                 /*setViscosity=*/true,
+                                                 /*setInternalEnergy=*/false);
+            }
+            // ... or calculated explicitly this way ...
+            else {    
+
+                // note that the water phase is actually not existing!
+                // thus, this is used as phase switch criterion
+                Scalar xww = xgw * pg_
+                             / (FluidSystem::fugacityCoefficient(fluidState_,
+                                                                 wPhaseIdx,wCompIdx)
+                                * pw_);
+                Scalar xwn = 1.e-10;
+                Scalar xwg = 1.e-10;
+
+                // note that the NAPL phase is actually not existing!
+                // thus, this is used as phase switch criterion
+                Scalar xnn = xgn * pg_
+                             / (FluidSystem::fugacityCoefficient(fluidState_,
+                                                                 nPhaseIdx,nCompIdx)
+                                * pn_);
+                Scalar xna = 1.e-10;
+                Scalar xnw = 1.e-10;
+                 
+                fluidState_.setMoleFraction(wPhaseIdx, wCompIdx, xww);
+                fluidState_.setMoleFraction(wPhaseIdx, gCompIdx, xwg);
+                fluidState_.setMoleFraction(wPhaseIdx, nCompIdx, xwn);
+                fluidState_.setMoleFraction(nPhaseIdx, wCompIdx, xnw);
+                fluidState_.setMoleFraction(nPhaseIdx, gCompIdx, xna);
+                fluidState_.setMoleFraction(nPhaseIdx, nCompIdx, xnn);
+
+                Scalar rhoW = FluidSystem::density(fluidState_, wPhaseIdx);
+                Scalar rhoG = FluidSystem::density(fluidState_, gPhaseIdx);
+                Scalar rhoN = FluidSystem::density(fluidState_, nPhaseIdx);
+
+                fluidState_.setDensity(wPhaseIdx, rhoW);
+                fluidState_.setDensity(gPhaseIdx, rhoG);
+                fluidState_.setDensity(nPhaseIdx, rhoN);
+            }
+        }
+        else if (phasePresence == wgPhaseOnly) {
+            // only water and gas phases are present
+            Scalar xgn = priVars[switch2Idx];
+            Scalar partPressH2O = fluidState_.fugacityCoefficient(wPhaseIdx, wCompIdx)*pw_;
+
+            Scalar xgw = partPressH2O/pg_;
+            Scalar xgg = 1.-xgn-xgw;
+
+            // write mole fractions in the fluid state
+            fluidState_.setMoleFraction(gPhaseIdx, wCompIdx, xgw);
+            fluidState_.setMoleFraction(gPhaseIdx, gCompIdx, xgg);
+            fluidState_.setMoleFraction(gPhaseIdx, nCompIdx, xgn);
+
+            // calculate the composition of the remaining phases (as
+            // well as the densities of all phases). this is the job
+            // of the "ComputeFromReferencePhase" constraint solver ...
+            if (useConstraintSolver)
+            {
+                ComputeFromReferencePhase::solve(fluidState_,
+                                                 paramCache,
+                                                 gPhaseIdx,
+                                                 /*setViscosity=*/true,
+                                                 /*setInternalEnergy=*/false);
+            }
+            // ... or calculated explicitly this way ...
+            else {    
+                // actually, it's nothing else than Henry coefficient
+                Scalar xwn = xgn * pg_
+                             / (FluidSystem::fugacityCoefficient(fluidState_,
+                                                                 wPhaseIdx,nCompIdx) 
+                                * pw_);
+                Scalar xwg = xgg * pg_
+                             / (FluidSystem::fugacityCoefficient(fluidState_,
+                                                                 wPhaseIdx,gCompIdx) 
+                                * pw_);
+                Scalar xww = 1.-xwg-xwn;
+
+                // note that the NAPL phase is actually not existing!
+                // thus, this is used as phase switch criterion
+                Scalar xnn = xgn * pg_
+                             / (FluidSystem::fugacityCoefficient(fluidState_,
+                                                                 nPhaseIdx,nCompIdx)
+                                * pn_);;
+                Scalar xna = 1.e-10;
+                Scalar xnw = 1.e-10;
+                 
+                fluidState_.setMoleFraction(wPhaseIdx, wCompIdx, xww);
+                fluidState_.setMoleFraction(wPhaseIdx, gCompIdx, xwg);
+                fluidState_.setMoleFraction(wPhaseIdx, nCompIdx, xwn);
+                fluidState_.setMoleFraction(nPhaseIdx, wCompIdx, xnw);
+                fluidState_.setMoleFraction(nPhaseIdx, gCompIdx, xna);
+                fluidState_.setMoleFraction(nPhaseIdx, nCompIdx, xnn);
+
+                Scalar rhoW = FluidSystem::density(fluidState_, wPhaseIdx);
+                Scalar rhoG = FluidSystem::density(fluidState_, gPhaseIdx);
+                Scalar rhoN = FluidSystem::density(fluidState_, nPhaseIdx);
+
+                fluidState_.setDensity(wPhaseIdx, rhoW);
+                fluidState_.setDensity(gPhaseIdx, rhoG);
+                fluidState_.setDensity(nPhaseIdx, rhoN);
+            }
+        }
+        else
+            assert(false); // unhandled phase state
+
+        for (int phaseIdx = 0; phaseIdx < numPhases; ++phaseIdx) {
+            // Mobilities
+            const Scalar mu =
+                FluidSystem::viscosity(fluidState_,
+                                       paramCache,
+                                       phaseIdx);
+            fluidState_.setViscosity(phaseIdx,mu);
+
+            Scalar kr;
+            kr = MaterialLaw::kr(materialParams, phaseIdx,
+                                 fluidState_.saturation(wPhaseIdx),
+                                 fluidState_.saturation(nPhaseIdx),
+                                 fluidState_.saturation(gPhaseIdx));
+            mobility_[phaseIdx] = kr / mu;
+            Valgrind::CheckDefined(mobility_[phaseIdx]);
+        }
+
+        // material dependent parameters for NAPL adsorption
+        bulkDensTimesAdsorpCoeff_ =
+            MaterialLaw::bulkDensTimesAdsorpCoeff(materialParams);
+
+        /* ATTENTION: The conversion to effective diffusion parameters
+         *            for the porous media happens at another place!
+         */
+
+        // diffusivity coefficents
+        diffusionCoefficient_[gPhaseIdx][wCompIdx] =
+            FluidSystem::diffusionCoefficient(fluidState_,
+                                              paramCache,
+                                              gPhaseIdx,
+                                              wCompIdx);
+        diffusionCoefficient_[gPhaseIdx][nCompIdx] =
+            FluidSystem::diffusionCoefficient(fluidState_,
+                                              paramCache,
+                                              gPhaseIdx,
+                                              nCompIdx);
+        diffusionCoefficient_[gPhaseIdx][gCompIdx] = 0.0; // dummy, should not be used !
+
+        diffusionCoefficient_[wPhaseIdx][gCompIdx] =
+            FluidSystem::diffusionCoefficient(fluidState_,
+                                              paramCache,
+                                              wPhaseIdx,
+                                              gCompIdx);
+        diffusionCoefficient_[wPhaseIdx][nCompIdx] =
+            FluidSystem::diffusionCoefficient(fluidState_,
+                                              paramCache,
+                                              wPhaseIdx,
+                                              nCompIdx);
+        diffusionCoefficient_[wPhaseIdx][wCompIdx] = 0.0; // dummy, should not be used !
+
+        /* no diffusion in NAPL phase considered  at the moment */
+        diffusionCoefficient_[nPhaseIdx][nCompIdx] = 0.0;
+        diffusionCoefficient_[nPhaseIdx][wCompIdx] = 0.0;
+        diffusionCoefficient_[nPhaseIdx][gCompIdx] = 0.0;
+
+        Valgrind::CheckDefined(diffusionCoefficient_);
+
+        // porosity
+        porosity_ = problem.spatialParams().porosity(element,
+                                                         fvGeometry,
+                                                         scvIdx);
+        Valgrind::CheckDefined(porosity_);
+
+        // permeability
+        permeability_ = problem.spatialParams().intrinsicPermeability(element,
+                                                                          fvGeometry,
+                                                                          scvIdx);
+        Valgrind::CheckDefined(permeability_);
+
+        // energy related quantities not contained in the fluid state
+        asImp_().updateEnergy_(priVars, problem, element, fvGeometry, scvIdx, isOldSol);
+    }
+
+    /*!
+     * \brief Returns the phase state for the control-volume.
+     */
+    const FluidState &fluidState() const
+    { return fluidState_; }
+
+    /*!
+     * \brief Returns the effective saturation of a given phase within
+     *        the control volume.
+     *
+     * \param phaseIdx The phase index
+     */
+    Scalar saturation(const int phaseIdx) const
+    { return fluidState_.saturation(phaseIdx); }
+
+    /*!
+     * \brief Returns the mass density of a given phase within the
+     *        control volume.
+     *
+     * \param phaseIdx The phase index
+     */
+    Scalar density(const int phaseIdx) const
+    { return fluidState_.density(phaseIdx); }
+
+    /*!
+     * \brief Returns the molar density of a given phase within the
+     *        control volume.
+     *
+     * \param phaseIdx The phase index
+     */
+    Scalar molarDensity(const int phaseIdx) const
+    { return fluidState_.density(phaseIdx) / fluidState_.averageMolarMass(phaseIdx); }
+
+    /*!
+     * \brief Returns the effective pressure of a given phase within
+     *        the control volume.
+     *
+     * \param phaseIdx The phase index
+     */
+    Scalar pressure(const int phaseIdx) const
+    { return fluidState_.pressure(phaseIdx); }
+
+    /*!
+     * \brief Returns temperature inside the sub-control volume.
+     *
+     * Note that we assume thermodynamic equilibrium, i.e. the
+     * temperatures of the rock matrix and of all fluid phases are
+     * identical.
+     */
+    Scalar temperature() const
+    { return fluidState_.temperature(/*phaseIdx=*/0); }
+
+    /*!
+     * \brief Returns the effective mobility of a given phase within
+     *        the control volume.
+     *
+     * \param phaseIdx The phase index
+     */
+    Scalar mobility(const int phaseIdx) const
+    {
+        return mobility_[phaseIdx];
+    }
+
+    /*!
+     * \brief Returns the effective capillary pressure within the control volume.
+     */
+    Scalar capillaryPressure() const
+    { return fluidState_.capillaryPressure(); }
+
+    /*!
+     * \brief Returns the average porosity within the control volume.
+     */
+    Scalar porosity() const
+    { return porosity_; }
+
+    /*!
+     * \brief Returns the permeability within the control volume.
+     */
+    Scalar permeability() const
+    { return permeability_; }
+
+    /*!
+     * \brief Returns the diffusivity coefficient matrix
+     */
+    Dune::FieldMatrix<Scalar, numPhases, numComponents> diffusionCoefficient() const
+    { return diffusionCoefficient_; }
+
+    /*!
+     * \brief Returns the adsorption information
+     */
+    Scalar bulkDensTimesAdsorpCoeff() const
+    { return bulkDensTimesAdsorpCoeff_; }
+
+
+protected:
+
+    static Scalar temperature_(const PrimaryVariables &priVars,
+                               const Problem &problem,
+                               const Element &element,
+                               const FVElementGeometry &fvGeometry,
+                               const int scvIdx)
+    {
+        return problem.boxTemperature(element, fvGeometry, scvIdx);
+    }
+
+    /*!
+     * \brief Called by update() to compute the energy related quantities
+     */
+    void updateEnergy_(const PrimaryVariables &priVars,
+                       const Problem &problem,
+                       const Element &element,
+                       const FVElementGeometry &fvGeometry,
+                       const int scvIdx,
+                       bool isOldSol)
+    { }
+
+    Scalar Sw_, Sg_, Sn_, pg_, pw_, pn_;
+
+    Scalar moleFrac_[numPhases][numComponents];
+    Scalar massFrac_[numPhases][numComponents];
+
+    Scalar porosity_;        //!< Effective porosity within the control volume
+    Scalar permeability_;        //!< Effective porosity within the control volume
+    Scalar mobility_[numPhases];  //!< Effective mobility within the control volume
+    Scalar bulkDensTimesAdsorpCoeff_; //!< the basis for calculating adsorbed NAPL
+    /* We need a tensor here !! */
+    //!< Binary diffusion coefficients of the 3 components in the phases
+    Dune::FieldMatrix<Scalar, numPhases, numComponents> diffusionCoefficient_;
+    FluidState fluidState_;
+
+private:
+    Implementation &asImp_()
+    { return *static_cast<Implementation*>(this); }
+
+    const Implementation &asImp_() const
+    { return *static_cast<const Implementation*>(this); }
+};
+
+template <class TypeTag>
+const typename ThreePThreeCVolumeVariables<TypeTag>::Scalar ThreePThreeCVolumeVariables<TypeTag>::R = Constants<typename GET_PROP_TYPE(TypeTag, Scalar)>::R;
+
+} // end namepace
+
+#endif
diff --git a/dumux/implicit/3p3c/Makefile.am b/dumux/implicit/3p3c/Makefile.am
new file mode 100644
index 0000000000..561eac1db7
--- /dev/null
+++ b/dumux/implicit/3p3c/Makefile.am
@@ -0,0 +1,4 @@
+3p3cdir = $(includedir)/dumux/boxmodels/3p3c
+3p3c_HEADERS = *.hh
+
+include $(top_srcdir)/am/global-rules
diff --git a/dumux/implicit/3p3cni/3p3cnifluxvariables.hh b/dumux/implicit/3p3cni/3p3cnifluxvariables.hh
new file mode 100644
index 0000000000..83b40fd835
--- /dev/null
+++ b/dumux/implicit/3p3cni/3p3cnifluxvariables.hh
@@ -0,0 +1,129 @@
+// -*- mode: C++; tab-width: 4; indent-tabs-mode: nil; c-basic-offset: 4 -*-
+// vi: set et ts=4 sw=4 sts=4:
+/*****************************************************************************
+ *   See the file COPYING for full copying permissions.                      *
+ *                                                                           *
+ *   This program is free software: you can redistribute it and/or modify    *
+ *   it under the terms of the GNU General Public License as published by    *
+ *   the Free Software Foundation, either version 2 of the License, or       *
+ *   (at your option) any later version.                                     *
+ *                                                                           *
+ *   This program is distributed in the hope that it will be useful,         *
+ *   but WITHOUT ANY WARRANTY; without even the implied warranty of          *
+ *   MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the            *
+ *   GNU General Public License for more details.                            *
+ *                                                                           *
+ *   You should have received a copy of the GNU General Public License       *
+ *   along with this program.  If not, see <http://www.gnu.org/licenses/>.   *
+ *****************************************************************************/
+/*!
+ * \file
+ *
+ * \brief This file contains the data which is required to calculate
+ *        all fluxes (mass of components and energy) over a face of a finite volume.
+ *
+ * This means pressure, concentration and temperature gradients, phase
+ * densities at the integration point, etc.
+ */
+#ifndef DUMUX_3P3CNI_FLUX_VARIABLES_HH
+#define DUMUX_3P3CNI_FLUX_VARIABLES_HH
+
+#include <dumux/common/math.hh>
+#include <dumux/boxmodels/3p3c/3p3cfluxvariables.hh>
+
+namespace Dumux
+{
+
+/*!
+ * \ingroup ThreePThreeCNIModel
+ * \brief This template class contains the data which is required to
+ *        calculate all fluxes (mass of components and energy) over a face of a finite
+ *        volume for the non-isothermal three-phase, three-component model.
+ *
+ * This means pressure and concentration gradients, phase densities at
+ * the integration point, etc.
+ */
+template <class TypeTag>
+class ThreePThreeCNIFluxVariables : public ThreePThreeCFluxVariables<TypeTag>
+{
+    typedef ThreePThreeCFluxVariables<TypeTag> ParentType;
+    typedef typename GET_PROP_TYPE(TypeTag, Scalar) Scalar;
+    typedef typename GET_PROP_TYPE(TypeTag, GridView) GridView;
+
+    typedef typename GET_PROP_TYPE(TypeTag, Problem) Problem;
+
+    typedef typename GridView::ctype CoordScalar;
+    typedef typename GridView::template Codim<0>::Entity Element;
+    typedef typename GET_PROP_TYPE(TypeTag, ElementVolumeVariables) ElementVolumeVariables;
+
+    enum {
+        dim = GridView::dimension,
+        dimWorld = GridView::dimensionworld
+    };
+
+    typedef typename GET_PROP_TYPE(TypeTag, FVElementGeometry) FVElementGeometry;
+
+    typedef Dune::FieldVector<CoordScalar, dim> DimVector;
+
+public:
+    /*
+     * \brief The constructor
+     *
+     * \param problem The problem
+     * \param element The finite element
+     * \param fvGeometry The finite-volume geometry in the box scheme
+     * \param faceIdx The local index of the SCV (sub-control-volume) face
+     * \param elemVolVars The volume variables of the current element
+     * \param onBoundary A boolean variable to specify whether the flux variables
+     * are calculated for interior SCV faces or boundary faces, default=false
+     */
+    ThreePThreeCNIFluxVariables(const Problem &problem,
+                                const Element &element,
+                                const FVElementGeometry &fvGeometry,
+                                const int faceIdx,
+                                const ElementVolumeVariables &elemVolVars,
+                                const bool onBoundary = false)
+        : ParentType(problem, element, fvGeometry, faceIdx, elemVolVars, onBoundary)
+    {
+        // calculate temperature gradient using finite element
+        // gradients
+        DimVector temperatureGrad(0);
+        DimVector tmp(0.0);
+        for (int vertIdx = 0; vertIdx < fvGeometry.numFAP; vertIdx++)
+        {
+            tmp = this->face().grad[vertIdx];
+
+            // index for the element volume variables 
+            int volVarsIdx = this->face().fapIndices[vertIdx];
+
+            tmp *= elemVolVars[volVarsIdx].temperature();
+            temperatureGrad += tmp;
+        }
+
+        // The spatial parameters calculates the actual heat flux vector
+        problem.spatialParams().matrixHeatFlux(tmp,
+                                                   *this,
+                                                   elemVolVars,
+                                                   temperatureGrad,
+                                                   element,
+                                                   fvGeometry,
+                                                   faceIdx);
+        // project the heat flux vector on the face's normal vector
+        normalMatrixHeatFlux_ = tmp*this->face().normal;
+    }
+
+    /*!
+     * \brief The total heat flux \f$\mathrm{[J/s]}\f$ due to heat conduction
+     *        of the rock matrix over the sub-control volume's face in
+     *        direction of the face normal.
+     */
+    Scalar normalMatrixHeatFlux() const
+    { return normalMatrixHeatFlux_; }
+
+private:
+    Scalar normalMatrixHeatFlux_;
+};
+
+} // end namepace
+
+#endif
diff --git a/dumux/implicit/3p3cni/3p3cniindices.hh b/dumux/implicit/3p3cni/3p3cniindices.hh
new file mode 100644
index 0000000000..753a23a540
--- /dev/null
+++ b/dumux/implicit/3p3cni/3p3cniindices.hh
@@ -0,0 +1,51 @@
+// -*- mode: C++; tab-width: 4; indent-tabs-mode: nil; c-basic-offset: 4 -*-
+// vi: set et ts=4 sw=4 sts=4:
+/*****************************************************************************
+ *   See the file COPYING for full copying permissions.                      *
+ *                                                                           *
+ *   This program is free software: you can redistribute it and/or modify    *
+ *   it under the terms of the GNU General Public License as published by    *
+ *   the Free Software Foundation, either version 2 of the License, or       *
+ *   (at your option) any later version.                                     *
+ *                                                                           *
+ *   This program is distributed in the hope that it will be useful,         *
+ *   but WITHOUT ANY WARRANTY; without even the implied warranty of          *
+ *   MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the            *
+ *   GNU General Public License for more details.                            *
+ *                                                                           *
+ *   You should have received a copy of the GNU General Public License       *
+ *   along with this program.  If not, see <http://www.gnu.org/licenses/>.   *
+ *****************************************************************************/
+
+/*!
+ * \file
+ *
+ * \brief Defines the indices used by the 3p3cni box model
+ */
+#ifndef DUMUX_3P3CNI_INDICES_HH
+#define DUMUX_3P3CNI_INDICES_HH
+
+#include <dumux/boxmodels/3p3c/3p3cindices.hh>
+
+namespace Dumux
+{
+/*!
+ * \ingroup ThreePThreeCNIModel
+ */
+// \{
+
+/*!
+ * \brief Enumerations for the non-isothermal 3-phase 3-component model
+ *
+ * \tparam PVOffset The first index in a primary variable vector.
+ */
+template <class TypeTag, int PVOffset>
+class ThreePThreeCNIIndices : public ThreePThreeCIndices<TypeTag, PVOffset>
+{
+public:
+    static const int temperatureIdx = PVOffset + 3; //! The index for temperature in primary variable vectors.
+    static const int energyEqIdx = PVOffset + 3; //! The index for energy in equation vectors.
+};
+
+}
+#endif
diff --git a/dumux/implicit/3p3cni/3p3cnilocalresidual.hh b/dumux/implicit/3p3cni/3p3cnilocalresidual.hh
new file mode 100644
index 0000000000..5dfb6dce37
--- /dev/null
+++ b/dumux/implicit/3p3cni/3p3cnilocalresidual.hh
@@ -0,0 +1,193 @@
+// -*- mode: C++; tab-width: 4; indent-tabs-mode: nil; c-basic-offset: 4 -*-
+// vi: set et ts=4 sw=4 sts=4:
+/*****************************************************************************
+ *   See the file COPYING for full copying permissions.                      *
+ *                                                                           *
+ *   This program is free software: you can redistribute it and/or modify    *
+ *   it under the terms of the GNU General Public License as published by    *
+ *   the Free Software Foundation, either version 2 of the License, or       *
+ *   (at your option) any later version.                                     *
+ *                                                                           *
+ *   This program is distributed in the hope that it will be useful,         *
+ *   but WITHOUT ANY WARRANTY; without even the implied warranty of          *
+ *   MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the            *
+ *   GNU General Public License for more details.                            *
+ *                                                                           *
+ *   You should have received a copy of the GNU General Public License       *
+ *   along with this program.  If not, see <http://www.gnu.org/licenses/>.   *
+ *****************************************************************************/
+/*!
+ * \file
+ *
+ * \brief Element-wise calculation of the Jacobian matrix for problems
+ *        using the non-isothermal three-phase three-component box model.
+ *
+ */
+#ifndef DUMUX_NEW_3P3CNI_LOCAL_RESIDUAL_HH
+#define DUMUX_NEW_3P3CNI_LOCAL_RESIDUAL_HH
+
+#include <dumux/boxmodels/3p3c/3p3clocalresidual.hh>
+
+
+#include "3p3cnivolumevariables.hh"
+#include "3p3cnifluxvariables.hh"
+
+#include "3p3cniproperties.hh"
+
+namespace Dumux
+{
+/*!
+ * \ingroup ThreePThreeCNIModel
+ * \brief Element-wise calculation of the Jacobian matrix for problems
+ *        using the three-phase three-component box model.
+ */
+template<class TypeTag>
+class ThreePThreeCNILocalResidual : public ThreePThreeCLocalResidual<TypeTag>
+{
+    typedef ThreePThreeCLocalResidual<TypeTag> ParentType;
+
+    typedef typename GET_PROP_TYPE(TypeTag, Scalar) Scalar;
+
+
+    typedef typename GET_PROP_TYPE(TypeTag, PrimaryVariables) PrimaryVariables;
+
+    typedef typename GET_PROP_TYPE(TypeTag, Indices) Indices;
+
+    enum {
+
+        numPhases = GET_PROP_VALUE(TypeTag, NumPhases),
+
+        energyEqIdx = Indices::energyEqIdx,
+        temperatureIdx = Indices::temperatureIdx,
+
+        wPhaseIdx = Indices::wPhaseIdx,
+        nPhaseIdx = Indices::nPhaseIdx,
+        gPhaseIdx = Indices::gPhaseIdx
+    };
+
+
+    typedef typename GET_PROP_TYPE(TypeTag, VolumeVariables) VolumeVariables;
+    typedef typename GET_PROP_TYPE(TypeTag, FluxVariables) FluxVariables;
+    typedef typename GET_PROP_TYPE(TypeTag, ElementVolumeVariables) ElementVolumeVariables;
+    
+public:
+    /*!
+     * \brief Evaluate the amount all conservation quantities
+     *        (e.g. phase mass) within a sub-control volume.
+     *
+     * The result should be averaged over the volume (e.g. phase mass
+     * inside a sub control volume divided by the volume)
+     *
+     *  \param storage The storage of the conservation quantitiy (mass or energy) within the sub-control volume
+     *  \param scvIdx The SCV (sub-control-volume) index
+     *  \param usePrevSol Evaluate function with solution of current or previous time step
+     */
+    void computeStorage(PrimaryVariables &storage, const int scvIdx, bool usePrevSol) const
+    {
+        // compute the storage term for phase mass
+        ParentType::computeStorage(storage, scvIdx, usePrevSol);
+
+        // if flag usePrevSol is set, the solution from the previous
+        // time step is used, otherwise the current solution is
+        // used. The secondary variables are used accordingly.  This
+        // is required to compute the derivative of the storage term
+        // using the implicit euler method.
+        const ElementVolumeVariables &elemDat = usePrevSol ? this->prevVolVars_() : this->curVolVars_();
+        const VolumeVariables &vertDat = elemDat[scvIdx];
+
+        // compute the energy storage
+        Scalar wdens = vertDat.density(wPhaseIdx);
+        Scalar ndens = vertDat.density(nPhaseIdx);
+        Scalar gdens = vertDat.density(gPhaseIdx);
+        Scalar wInEnerg = vertDat.internalEnergy(wPhaseIdx);
+        Scalar nInEnerg = vertDat.internalEnergy(nPhaseIdx);
+        Scalar gInEnerg = vertDat.internalEnergy(gPhaseIdx);
+        Scalar wsat = vertDat.saturation(wPhaseIdx);
+        Scalar nsat = vertDat.saturation(nPhaseIdx);
+        Scalar gsat = vertDat.saturation(gPhaseIdx);
+        Scalar temp = vertDat.temperature();
+        Scalar heatCap = vertDat.heatCapacity();
+        Scalar poro = vertDat.porosity();
+
+        storage[energyEqIdx] = temp*heatCap
+            + poro * (gdens*gInEnerg*gsat
+                      + wdens*wInEnerg*wsat
+                      + ndens*nInEnerg*nsat);
+        /*
+          vertDat.porosity()*(vertDat.density(wPhaseIdx) *
+          vertDat.internalEnergy(wPhaseIdx) *
+          vertDat.saturation(wPhaseIdx)
+          +
+          vertDat.density(nPhaseIdx) *
+          vertDat.internalEnergy(nPhaseIdx) *
+          vertDat.saturation(nPhaseIdx)
+          +
+          vertDat.density(gPhaseIdx) *
+          vertDat.internalEnergy(gPhaseIdx) *
+          vertDat.saturation(gPhaseIdx))
+          +
+          vertDat.temperature()*vertDat.heatCapacity();
+        */
+    }
+
+    /*!
+     * \brief Evaluates the advective mass flux and the heat flux
+     * over a face of a subcontrol volume and writes the result in
+     * the flux vector.
+     *
+     * \param flux The advective flux over the SCV (sub-control-volume) face for each component
+     * \param fluxData The flux variables at the current SCV face
+     *
+     * This method is called by compute flux (base class)
+     */
+    void computeAdvectiveFlux(PrimaryVariables &flux,
+                              const FluxVariables &fluxData) const
+    {
+        // advective mass flux
+        ParentType::computeAdvectiveFlux(flux, fluxData);
+
+        static const Scalar massUpwindWeight = GET_PARAM_FROM_GROUP(TypeTag, Scalar, Implicit, MassUpwindWeight);
+
+        // advective heat flux in all phases
+        flux[energyEqIdx] = 0;
+        for (int phaseIdx = 0; phaseIdx < numPhases; ++phaseIdx) {
+            // vertex data of the upstream and the downstream vertices
+            const VolumeVariables &up = this->curVolVars_(fluxData.upstreamIdx(phaseIdx));
+            const VolumeVariables &dn = this->curVolVars_(fluxData.downstreamIdx(phaseIdx));
+
+            flux[energyEqIdx] +=
+                fluxData.volumeFlux(phaseIdx) * (
+                                              massUpwindWeight * // upstream vertex
+                                              (  up.density(phaseIdx) *
+                                                 up.enthalpy(phaseIdx))
+                                              +
+                                              (1-massUpwindWeight) * // downstream vertex
+                                              (  dn.density(phaseIdx) *
+                                                 dn.enthalpy(phaseIdx)) );
+        }
+    }
+
+    /*!
+     * \brief Adds the diffusive heat flux to the flux vector over
+     *        the face of a sub-control volume.
+     *
+     * \param flux The diffusive flux over the SCV (sub-control-volume) face for each conservation quantity (mass, energy)
+     * \param fluxData The flux variables at the current SCV face
+     *
+     * This method is called by compute flux (base class)
+     */
+    void computeDiffusiveFlux(PrimaryVariables &flux,
+                              const FluxVariables &fluxData) const
+    {
+        // diffusive mass flux
+        ParentType::computeDiffusiveFlux(flux, fluxData);
+
+        // diffusive heat flux
+        flux[temperatureIdx] +=
+            fluxData.normalMatrixHeatFlux();
+    }
+};
+
+}
+
+#endif
diff --git a/dumux/implicit/3p3cni/3p3cnimodel.hh b/dumux/implicit/3p3cni/3p3cnimodel.hh
new file mode 100644
index 0000000000..7873dee5ce
--- /dev/null
+++ b/dumux/implicit/3p3cni/3p3cnimodel.hh
@@ -0,0 +1,108 @@
+// -*- mode: C++; tab-width: 4; indent-tabs-mode: nil; c-basic-offset: 4 -*-
+// vi: set et ts=4 sw=4 sts=4:
+/*****************************************************************************
+ *   See the file COPYING for full copying permissions.                      *
+ *                                                                           *
+ *   This program is free software: you can redistribute it and/or modify    *
+ *   it under the terms of the GNU General Public License as published by    *
+ *   the Free Software Foundation, either version 2 of the License, or       *
+ *   (at your option) any later version.                                     *
+ *                                                                           *
+ *   This program is distributed in the hope that it will be useful,         *
+ *   but WITHOUT ANY WARRANTY; without even the implied warranty of          *
+ *   MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the            *
+ *   GNU General Public License for more details.                            *
+ *                                                                           *
+ *   You should have received a copy of the GNU General Public License       *
+ *   along with this program.  If not, see <http://www.gnu.org/licenses/>.   *
+ *****************************************************************************/
+/*!
+ * \file
+ *
+ * \brief Adaption of the BOX scheme to the non-isothermal three-phase three-component flow model.
+ */
+#ifndef DUMUX_NEW_3P3CNI_MODEL_HH
+#define DUMUX_NEW_3P3CNI_MODEL_HH
+
+#include <dumux/boxmodels/3p3c/3p3cmodel.hh>
+
+namespace Dumux {
+/*!
+ * \ingroup ThreePThreeCNIModel
+ * \brief Adaption of the BOX scheme to the non-isothermal three-phase three-component flow model.
+ *
+ * This model implements three-phase three-component flow of three fluid phases
+ * \f$\alpha \in \{ water, gas, NAPL \}\f$ each composed of up to three components
+ * \f$\kappa \in \{ water, air, contaminant \}\f$. The standard multiphase Darcy
+ * approach is used as the equation for the conservation of momentum:
+ * \f[
+ v_\alpha = - \frac{k_{r\alpha}}{\mu_\alpha} \mbox{\bf K}
+ \left(\text{grad}\, p_\alpha - \varrho_{\alpha} \mbox{\bf g} \right)
+ * \f]
+ *
+ * By inserting this into the equations for the conservation of the
+ * components, one transport equation for each component is obtained as
+ * \f{eqnarray*}
+ && \phi \frac{\partial (\sum_\alpha \varrho_{\text{mol}, \alpha} x_\alpha^\kappa
+ S_\alpha )}{\partial t}
+ - \sum\limits_\alpha \text{div} \left\{ \frac{k_{r\alpha}}{\mu_\alpha}
+ \varrho_{\text{mol}, \alpha} x_\alpha^\kappa \mbox{\bf K}
+ (\text{grad}\; p_\alpha - \varrho_{\text{mass}, \alpha} \mbox{\bf g}) \right\}
+ \nonumber \\
+ \nonumber \\
+ && - \sum\limits_\alpha \text{div} \left\{ D_{pm}^\kappa \varrho_{\text{mol},
+ \alpha } \text{grad} \; x_\alpha^\kappa \right\}
+ - q^\kappa = 0 \qquad \forall \kappa , \; \forall \alpha
+ \f}
+ *
+ * Note that these balance equations above are molar.
+ * In addition to that, a single balance of thermal energy is formulated
+ * for the fluid-filled porous medium under the assumption of local thermal
+ * equilibrium
+ * \f{eqnarray*}
+ && \phi \frac{\partial \left( \sum_\alpha \varrho_\alpha u_\alpha S_\alpha \right)}{\partial t}
+ + \left( 1 - \phi \right) \frac{\partial (\varrho_s c_s T)}{\partial t}
+ - \sum_\alpha \text{div} \left\{ \varrho_\alpha h_\alpha
+ \frac{k_{r\alpha}}{\mu_\alpha} \mathbf{K} \left( \text{grad}\,
+ p_\alpha
+ - \varrho_\alpha \mathbf{g} \right) \right\} \\
+ &-& \text{div} \left( \lambda_{pm} \text{grad} \, T \right)
+ - q^h = 0 \qquad \alpha \in \{w, n, g\}
+ \f}
+ *
+
+ *
+ * The equations are discretized using a fully-coupled vertex
+ * centered finite volume (BOX) scheme as spatial scheme and
+ * the implicit Euler method as temporal discretization.
+ *
+ * The model uses commonly applied auxiliary conditions like
+ * \f$S_w + S_n + S_g = 1\f$ for the saturations and
+ * \f$x^w_\alpha + x^a_\alpha + x^c_\alpha = 1\f$ for the mole fractions.
+ * Furthermore, the phase pressures are related to each other via
+ * capillary pressures between the fluid phases, which are functions of
+ * the saturation, e.g. according to the approach of Parker et al.
+ *
+ * The used primary variables are dependent on the locally present fluid phases
+ * An adaptive primary variable switch is included. The phase state is stored for all nodes
+ * of the system. The following cases can be distinguished:
+ * <ul>
+ *  <li> All three phases are present: Primary variables are two saturations \f$(S_w\f$ and \f$S_n)\f$, a pressure, in this case \f$p_g\f$, and the temperature \f$T\f$. </li>
+ *  <li> Only the water phase is present: Primary variables are now the mole fractions of air and contaminant in the water phase \f$(x_w^a\f$ and \f$x_w^c)\f$, as well as temperature and the gas pressure, which is, of course, in a case where only the water phase is present, just the same as the water pressure. </li>
+ *  <li> Gas and NAPL phases are present: Primary variables \f$(S_n\f$, \f$x_g^w\f$, \f$p_g\f$, \f$T)\f$. </li>
+ *  <li> Water and NAPL phases are present: Primary variables \f$(S_n\f$, \f$x_w^a\f$, \f$p_g\f$, \f$T)\f$. </li>
+ *  <li> Only gas phase is present: Primary variables \f$(x_g^w\f$, \f$x_g^c\f$, \f$p_g\f$, \f$T)\f$. </li>
+ *  <li> Water and gas phases are present: Primary variables \f$(S_w\f$, \f$x_w^g\f$, \f$p_g\f$, \f$T)\f$. </li>
+ * </ul>
+ *
+ */
+template<class TypeTag>
+class ThreePThreeCNIModel : public ThreePThreeCModel<TypeTag>
+{
+};
+
+}
+
+#include "3p3cnipropertydefaults.hh"
+
+#endif
diff --git a/dumux/implicit/3p3cni/3p3cniproperties.hh b/dumux/implicit/3p3cni/3p3cniproperties.hh
new file mode 100644
index 0000000000..0c69522f03
--- /dev/null
+++ b/dumux/implicit/3p3cni/3p3cniproperties.hh
@@ -0,0 +1,47 @@
+// -*- mode: C++; tab-width: 4; indent-tabs-mode: nil; c-basic-offset: 4 -*-
+// vi: set et ts=4 sw=4 sts=4:
+/*****************************************************************************
+ *   See the file COPYING for full copying permissions.                      *
+ *                                                                           *
+ *   This program is free software: you can redistribute it and/or modify    *
+ *   it under the terms of the GNU General Public License as published by    *
+ *   the Free Software Foundation, either version 2 of the License, or       *
+ *   (at your option) any later version.                                     *
+ *                                                                           *
+ *   This program is distributed in the hope that it will be useful,         *
+ *   but WITHOUT ANY WARRANTY; without even the implied warranty of          *
+ *   MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the            *
+ *   GNU General Public License for more details.                            *
+ *                                                                           *
+ *   You should have received a copy of the GNU General Public License       *
+ *   along with this program.  If not, see <http://www.gnu.org/licenses/>.   *
+ *****************************************************************************/
+/*!
+ * \ingroup ThreePThreeCNIModel
+ */
+/*!
+ * \file
+ *
+ * \brief Defines the properties required for the non-isothermal three-phase,
+ * three-component BOX model.
+ */
+#ifndef DUMUX_3P3CNI_PROPERTIES_HH
+#define DUMUX_3P3CNI_PROPERTIES_HH
+
+#include <dumux/boxmodels/3p3c/3p3cproperties.hh>
+
+namespace Dumux
+{
+
+namespace Properties
+{
+//////////////////////////////////////////////////////////////////
+// Type tags
+//////////////////////////////////////////////////////////////////
+
+//! The type tag for the non-isothermal three-phase, three-component problems
+NEW_TYPE_TAG(BoxThreePThreeCNI, INHERITS_FROM(BoxThreePThreeC));
+}
+}
+
+#endif
diff --git a/dumux/implicit/3p3cni/3p3cnipropertydefaults.hh b/dumux/implicit/3p3cni/3p3cnipropertydefaults.hh
new file mode 100644
index 0000000000..a00787502d
--- /dev/null
+++ b/dumux/implicit/3p3cni/3p3cnipropertydefaults.hh
@@ -0,0 +1,71 @@
+// -*- mode: C++; tab-width: 4; indent-tabs-mode: nil; c-basic-offset: 4 -*-
+// vi: set et ts=4 sw=4 sts=4:
+/*****************************************************************************
+ *   See the file COPYING for full copying permissions.                      *
+ *                                                                           *
+ *   This program is free software: you can redistribute it and/or modify    *
+ *   it under the terms of the GNU General Public License as published by    *
+ *   the Free Software Foundation, either version 2 of the License, or       *
+ *   (at your option) any later version.                                     *
+ *                                                                           *
+ *   This program is distributed in the hope that it will be useful,         *
+ *   but WITHOUT ANY WARRANTY; without even the implied warranty of          *
+ *   MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the            *
+ *   GNU General Public License for more details.                            *
+ *                                                                           *
+ *   You should have received a copy of the GNU General Public License       *
+ *   along with this program.  If not, see <http://www.gnu.org/licenses/>.   *
+ *****************************************************************************/
+/*!
+ * \ingroup ThreePThreeCNIModel
+ */
+/*!
+ * \file
+ *
+ * \brief Defines default values for most properties required by the 3p3cni
+ *        box model.
+ */
+#ifndef DUMUX_3P3CNI_PROPERTY_DEFAULTS_HH
+#define DUMUX_3P3CNI_PROPERTY_DEFAULTS_HH
+
+#include <dumux/boxmodels/3p3c/3p3cpropertydefaults.hh>
+
+#include "3p3cnimodel.hh"
+#include "3p3cniindices.hh"
+#include "3p3cnilocalresidual.hh"
+#include "3p3cnivolumevariables.hh"
+#include "3p3cnifluxvariables.hh"
+
+namespace Dumux
+{
+
+namespace Properties
+{
+//////////////////////////////////////////////////////////////////
+// Property values
+//////////////////////////////////////////////////////////////////
+
+SET_INT_PROP(BoxThreePThreeCNI, NumEq, 4); //!< set the number of equations to 4
+
+//! Use the 3p3cni local jacobian operator for the 3p3cni model
+SET_TYPE_PROP(BoxThreePThreeCNI,
+              LocalResidual,
+              ThreePThreeCNILocalResidual<TypeTag>);
+
+//! the Model property
+SET_TYPE_PROP(BoxThreePThreeCNI, Model, ThreePThreeCNIModel<TypeTag>);
+
+//! the VolumeVariables property
+SET_TYPE_PROP(BoxThreePThreeCNI, VolumeVariables, ThreePThreeCNIVolumeVariables<TypeTag>);
+
+
+//! the FluxVariables property
+SET_TYPE_PROP(BoxThreePThreeCNI, FluxVariables, ThreePThreeCNIFluxVariables<TypeTag>);
+
+//! The indices required by the non-isothermal 3p3c model
+SET_TYPE_PROP(BoxThreePThreeCNI, Indices, ThreePThreeCNIIndices<TypeTag, 0>);
+
+}
+
+}
+#endif
diff --git a/dumux/implicit/3p3cni/3p3cnivolumevariables.hh b/dumux/implicit/3p3cni/3p3cnivolumevariables.hh
new file mode 100644
index 0000000000..d24cecadf1
--- /dev/null
+++ b/dumux/implicit/3p3cni/3p3cnivolumevariables.hh
@@ -0,0 +1,157 @@
+// -*- mode: C++; tab-width: 4; indent-tabs-mode: nil; c-basic-offset: 4 -*-
+// vi: set et ts=4 sw=4 sts=4:
+/*****************************************************************************
+ *   See the file COPYING for full copying permissions.                      *
+ *                                                                           *
+ *   This program is free software: you can redistribute it and/or modify    *
+ *   it under the terms of the GNU General Public License as published by    *
+ *   the Free Software Foundation, either version 2 of the License, or       *
+ *   (at your option) any later version.                                     *
+ *                                                                           *
+ *   This program is distributed in the hope that it will be useful,         *
+ *   but WITHOUT ANY WARRANTY; without even the implied warranty of          *
+ *   MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the            *
+ *   GNU General Public License for more details.                            *
+ *                                                                           *
+ *   You should have received a copy of the GNU General Public License       *
+ *   along with this program.  If not, see <http://www.gnu.org/licenses/>.   *
+ *****************************************************************************/
+/*!
+ * \file
+ *
+ * \brief Contains the quantities which are constant within a
+ *        finite volume in the non-isothermal three-phase, three-component
+ *        model.
+ */
+#ifndef DUMUX_3P3CNI_VOLUME_VARIABLES_HH
+#define DUMUX_3P3CNI_VOLUME_VARIABLES_HH
+
+#include <dumux/boxmodels/3p3c/3p3cvolumevariables.hh>
+
+
+namespace Dumux
+{
+
+/*!
+ * \ingroup ThreePThreeCNIModel
+ * \brief Contains the quantities which are are constant within a
+ *        finite volume in the non-isothermal three-phase, three-component
+ *        model.
+ */
+template <class TypeTag>
+class ThreePThreeCNIVolumeVariables : public ThreePThreeCVolumeVariables<TypeTag>
+{
+    //! \cond 0
+    typedef ThreePThreeCVolumeVariables<TypeTag> ParentType;
+
+    typedef typename GET_PROP_TYPE(TypeTag, Scalar) Scalar;
+    typedef typename GET_PROP_TYPE(TypeTag, GridView) GridView;
+
+    typedef typename GridView::template Codim<0>::Entity Element;
+    typedef typename GET_PROP_TYPE(TypeTag, FVElementGeometry) FVElementGeometry;
+    typedef typename GET_PROP_TYPE(TypeTag, Problem) Problem;
+
+    typedef typename GET_PROP_TYPE(TypeTag, FluidSystem) FluidSystem;
+    typedef typename GET_PROP_TYPE(TypeTag, Indices) Indices;
+    enum { numPhases = GET_PROP_VALUE(TypeTag, NumPhases) };
+    enum { temperatureIdx = Indices::temperatureIdx };
+
+    typedef typename GET_PROP_TYPE(TypeTag, PrimaryVariables) PrimaryVariables;
+    //! \endcond
+
+public:
+    /*!
+     * \copydoc BoxVolumeVariables::update
+     */
+    void update(const PrimaryVariables &priVars,
+                const Problem &problem,
+                const Element &element,
+                const FVElementGeometry &fvGeometry,
+                const int scvIdx,
+                bool isOldSol)
+    {
+        // vertex update data for the mass balance
+        ParentType::update(priVars,
+                           problem,
+                           element,
+                           fvGeometry,
+                           scvIdx,
+                           isOldSol);
+
+        typename FluidSystem::ParameterCache paramCache;
+        paramCache.updateAll(this->fluidState());
+
+        // the internal energies and the enthalpies
+        for (int phaseIdx = 0; phaseIdx < numPhases; ++phaseIdx) {
+            Scalar h = FluidSystem::enthalpy(this->fluidState_, paramCache, phaseIdx);
+            this->fluidState_.setEnthalpy(phaseIdx, h);
+        }
+    };
+
+    /*!
+     * \brief Returns the total internal energy of a phase in the
+     *        sub-control volume.
+     *
+     * \param phaseIdx The phase index
+     */
+    Scalar internalEnergy(int phaseIdx) const
+    { return this->fluidState_.internalEnergy(phaseIdx); };
+
+    /*!
+     * \brief Returns the total enthalpy of a phase in the sub-control
+     *        volume.
+     *
+     * \param phaseIdx The phase index
+     */
+    Scalar enthalpy(int phaseIdx) const
+    { return this->fluidState_.enthalpy(phaseIdx); };
+
+    /*!
+     * \brief Returns the total heat capacity \f$\mathrm{[J/(K*m^3]}\f$ of the rock matrix in
+     *        the sub-control volume.
+     */
+    Scalar heatCapacity() const
+    { return heatCapacity_; };
+
+protected:
+    // this method gets called by the parent class. since this method
+    // is protected, we are friends with our parent..
+    friend class ThreePThreeCVolumeVariables<TypeTag>;
+
+    static Scalar temperature_(const PrimaryVariables &primaryVars,
+                               const Problem& problem,
+                               const Element &element,
+                               const FVElementGeometry &fvGeometry,
+                               const int scvIdx)
+    {
+        return primaryVars[temperatureIdx];
+    }
+
+    /*!
+     * \brief Update all quantities for a given control volume.
+     *
+     * \param priVars The solution primary variables
+     * \param problem The problem
+     * \param element The element
+     * \param fvGeometry Evaluate function with solution of current or previous time step
+     * \param scvIdx The local index of the SCV (sub-control volume)
+     * \param isOldSol Evaluate function with solution of current or previous time step
+     */
+    void updateEnergy_(const PrimaryVariables &priVars,
+                       const Problem &problem,
+                       const Element &element,
+                       const FVElementGeometry &fvGeometry,
+                       const int scvIdx,
+                       bool isOldSol)
+    {
+        // copmute and set the heat capacity of the solid phase
+        heatCapacity_ = problem.spatialParams().heatCapacity(element, fvGeometry, scvIdx);
+        Valgrind::CheckDefined(heatCapacity_);
+    };
+
+    Scalar heatCapacity_;
+};
+
+} // end namepace
+
+#endif
diff --git a/dumux/implicit/3p3cni/Makefile.am b/dumux/implicit/3p3cni/Makefile.am
new file mode 100644
index 0000000000..9045919660
--- /dev/null
+++ b/dumux/implicit/3p3cni/Makefile.am
@@ -0,0 +1,4 @@
+3p3cnidir = $(includedir)/dumux/boxmodels/3p3cni
+3p3cni_HEADERS = *.hh
+
+include $(top_srcdir)/am/global-rules
diff --git a/dumux/implicit/Makefile.am b/dumux/implicit/Makefile.am
new file mode 100644
index 0000000000..0c3d2aaeab
--- /dev/null
+++ b/dumux/implicit/Makefile.am
@@ -0,0 +1,5 @@
+SUBDIRS = common co2 co2ni 1p 1p2c 2p 2p2c 2p2cni 2pni 2pdfm 3p3c 3p3cni mpnc richards
+
+boxmodelsdir = $(includedir)/dumux/boxmodels
+
+include $(top_srcdir)/am/global-rules
diff --git a/dumux/implicit/box/Makefile.am b/dumux/implicit/box/Makefile.am
new file mode 100644
index 0000000000..2fd0a582d6
--- /dev/null
+++ b/dumux/implicit/box/Makefile.am
@@ -0,0 +1,4 @@
+commondir = $(includedir)/dumux/boxmodels/common
+common_HEADERS = *.hh
+
+include $(top_srcdir)/am/global-rules
diff --git a/dumux/implicit/box/boxassembler.hh b/dumux/implicit/box/boxassembler.hh
new file mode 100644
index 0000000000..18e196c3e8
--- /dev/null
+++ b/dumux/implicit/box/boxassembler.hh
@@ -0,0 +1,858 @@
+// -*- mode: C++; tab-width: 4; indent-tabs-mode: nil; c-basic-offset: 4 -*-
+// vi: set et ts=4 sw=4 sts=4:
+/*****************************************************************************
+ *   See the file COPYING for full copying permissions.                      *
+ *                                                                           *
+ *   This program is free software: you can redistribute it and/or modify    *
+ *   it under the terms of the GNU General Public License as published by    *
+ *   the Free Software Foundation, either version 2 of the License, or       *
+ *   (at your option) any later version.                                     *
+ *                                                                           *
+ *   This program is distributed in the hope that it will be useful,         *
+ *   but WITHOUT ANY WARRANTY; without even the implied warranty of          *
+ *   MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the            *
+ *   GNU General Public License for more details.                            *
+ *                                                                           *
+ *   You should have received a copy of the GNU General Public License       *
+ *   along with this program.  If not, see <http://www.gnu.org/licenses/>.   *
+ *****************************************************************************/
+/*!
+ * \file
+ *
+ * \brief An assembler for the global Jacobian matrix for models using the box discretization.
+ */
+#ifndef DUMUX_BOX_ASSEMBLER_HH
+#define DUMUX_BOX_ASSEMBLER_HH
+
+#include <dune/grid/common/gridenums.hh>
+
+#include <dumux/boxmodels/common/boxproperties.hh>
+#include <dumux/linear/vertexborderlistfromgrid.hh>
+#include <dumux/linear/foreignoverlapfrombcrsmatrix.hh>
+#include <dumux/parallel/vertexhandles.hh>
+
+namespace Dumux {
+
+/*!
+ * \brief An assembler for the global Jacobian matrix for models using the box discretization.
+ */
+template<class TypeTag>
+class BoxAssembler
+{
+    typedef typename GET_PROP_TYPE(TypeTag, Model) Model;
+    typedef typename GET_PROP_TYPE(TypeTag, Problem) Problem;
+    typedef typename GET_PROP_TYPE(TypeTag, GridView) GridView;
+    typedef typename GET_PROP_TYPE(TypeTag, Scalar) Scalar;
+    typedef typename GET_PROP_TYPE(TypeTag, VertexMapper) VertexMapper;
+    typedef typename GET_PROP_TYPE(TypeTag, ElementMapper) ElementMapper;
+
+    typedef typename GET_PROP_TYPE(TypeTag, SolutionVector) SolutionVector;
+    typedef typename GET_PROP_TYPE(TypeTag, JacobianMatrix) JacobianMatrix;
+    typedef typename GET_PROP_TYPE(TypeTag, PrimaryVariables) PrimaryVariables;
+
+    enum{ dim = GridView::dimension };
+    typedef typename GridView::template Codim<0>::Entity Element;
+    typedef typename GridView::template Codim<0>::Iterator ElementIterator;
+    typedef typename GridView::template Codim<dim>::EntityPointer VertexPointer;
+
+    enum { numEq = GET_PROP_VALUE(TypeTag, NumEq) };
+    typedef Dune::FieldMatrix<Scalar, numEq, numEq> MatrixBlock;
+    typedef Dune::FieldVector<Scalar, numEq> VectorBlock;
+
+    // copying the jacobian assembler is not a good idea
+    BoxAssembler(const BoxAssembler &);
+
+public:
+    /*!
+     * \brief The colors of elements and vertices required for partial
+     *        Jacobian reassembly.
+     */
+    enum EntityColor {
+        /*!
+         * Vertex/element that needs to be reassembled because some
+         * relative error is above the tolerance
+         */
+        Red = 0,
+
+        /*!
+         * Vertex/element that needs to be reassembled because a
+         * neighboring element/vertex is red
+         */
+        Yellow = 1,
+
+        /*!
+         * Yellow vertex has only non-green neighbor elements.
+         *
+         * This means that its relative error is below the tolerance,
+         * but its defect can be linearized without any additional
+         * cost. This is just an "internal" color which is not used
+         * ouside of the jacobian assembler.
+         */
+        Orange = 2,
+
+        /*!
+         * Vertex/element that does not need to be reassembled
+         */
+        Green = 3
+    };
+
+    BoxAssembler()
+    {
+        problemPtr_ = 0;
+        matrix_ = 0;
+
+        // set reassemble accuracy to 0, so that if partial reassembly
+        // of the jacobian matrix is disabled, the reassemble accuracy
+        // is always smaller than the current relative tolerance
+        reassembleAccuracy_ = 0.0;
+    }
+
+    ~BoxAssembler()
+    {
+        delete matrix_;
+    }
+
+    /*!
+     * \brief Initialize the jacobian assembler.
+     *
+     * At this point we can assume that all objects in the problem and
+     * the model have been allocated. We can not assume that they are
+     * fully initialized, though.
+     *
+     * \param problem The problem object
+     */
+    void init(Problem& problem)
+    {
+        problemPtr_ = &problem;
+
+        // initialize the BCRS matrix
+        createMatrix_();
+
+        // initialize the jacobian matrix and the right hand side
+        // vector
+        *matrix_ = 0;
+        reuseMatrix_ = false;
+
+        int numVerts = gridView_().size(dim);
+        int numElems = gridView_().size(0);
+
+        residual_.resize(numVerts);
+
+        // initialize the storage part of the Jacobian matrix. Since
+        // we only need this if Jacobian matrix recycling is enabled,
+        // we do not waste space if it is disabled
+        if (enableJacobianRecycling_()) {
+            storageJacobian_.resize(numVerts);
+            storageTerm_.resize(numVerts);
+        }
+
+        if (gridView_().comm().size() > 1)
+            totalElems_ = gridView_().comm().sum(numElems);
+        else
+            totalElems_ = numElems;
+
+        // initialize data needed for partial reassembly
+        if (enablePartialReassemble_()) {
+            vertexColor_.resize(numVerts);
+            vertexDelta_.resize(numVerts);
+            elementColor_.resize(numElems);
+        }
+        reassembleAll();
+    }
+
+    /*!
+     * \brief Assemble the global Jacobian of the residual and the residual for the current solution.
+     *
+     * The current state of affairs (esp. the previous and the current
+     * solutions) is represented by the model object.
+     */
+    void assemble()
+    {
+        bool printReassembleStatistics = enablePartialReassemble_() && !reuseMatrix_;
+        int succeeded;
+        try {
+            assemble_();
+            succeeded = 1;
+            if (gridView_().comm().size() > 1)
+                succeeded = gridView_().comm().min(succeeded);
+        }
+        catch (Dumux::NumericalProblem &e)
+        {
+            std::cout << "rank " << problem_().gridView().comm().rank()
+                      << " caught an exception while assembling:" << e.what()
+                      << "\n";
+            succeeded = 0;
+            if (gridView_().comm().size() > 1)
+                succeeded = gridView_().comm().min(succeeded);
+        }
+
+        if (!succeeded) {
+            DUNE_THROW(NumericalProblem,
+                       "A process did not succeed in linearizing the system");
+        }
+
+        if (printReassembleStatistics)
+        {
+            if (gridView_().comm().size() > 1)
+            {
+                greenElems_ = gridView_().comm().sum(greenElems_);
+                reassembleAccuracy_ = gridView_().comm().max(nextReassembleAccuracy_);
+            }
+            else
+            {
+                reassembleAccuracy_ = nextReassembleAccuracy_;
+            }
+
+            problem_().newtonController().endIterMsg()
+                << ", reassembled "
+                << totalElems_ - greenElems_ << "/" << totalElems_
+                << " (" << 100*Scalar(totalElems_ - greenElems_)/totalElems_ << "%) elems @accuracy="
+                << reassembleAccuracy_;
+        }
+
+        // reset all vertex colors to green
+        for (unsigned int i = 0; i < vertexColor_.size(); ++i) {
+            vertexColor_[i] = Green;
+        }
+    }
+
+    /*!
+     * \brief If Jacobian matrix recycling is enabled, this method
+     *        specifies whether the next call to assemble() just
+     *        rescales the storage term or does a full reassembly
+     *
+     * \param yesno If true, only rescale; else do full Jacobian assembly.
+     */
+    void setMatrixReuseable(const bool yesno = true)
+    {
+        if (enableJacobianRecycling_())
+            reuseMatrix_ = yesno;
+    }
+
+    /*!
+     * \brief If partial Jacobian matrix reassembly is enabled, this
+     *        method causes all elements to be reassembled in the next
+     *        assemble() call.
+     */
+    void reassembleAll()
+    {
+        // do not reuse the current linearization
+        reuseMatrix_ = false;
+
+        // do not use partial reassembly for the next iteration
+        nextReassembleAccuracy_ = 0.0;
+        if (enablePartialReassemble_()) {
+            std::fill(vertexColor_.begin(),
+                      vertexColor_.end(),
+                      Red);
+            std::fill(elementColor_.begin(),
+                      elementColor_.end(),
+                      Red);
+            std::fill(vertexDelta_.begin(),
+                      vertexDelta_.end(),
+                      0.0);
+        }
+    }
+
+    /*!
+     * \brief Returns the largest relative error of a "green" vertex
+     *        for the most recent call of the assemble() method.
+     *
+     * This only has an effect if partial Jacobian reassembly is
+     * enabled. If it is disabled, then this method always returns 0.
+     *
+     * This returns the _actual_ relative computed seen by
+     * computeColors(), not the tolerance which it was given.
+     */
+    Scalar reassembleAccuracy() const
+    { return reassembleAccuracy_; }
+
+    /*!
+     * \brief Update the distance where the non-linear system was
+     *        originally insistently linearized and the point where it
+     *        will be linerized the next time.
+     *
+     * This only has an effect if partial reassemble is enabled.
+     */
+    void updateDiscrepancy(const SolutionVector &u,
+                           const SolutionVector &uDelta)
+    {
+        if (!enablePartialReassemble_())
+            return;
+
+        // update the vector with the distances of the current
+        // evaluation point used for linearization from the original
+        // evaluation point
+        for (unsigned int i = 0; i < vertexDelta_.size(); ++i) {
+            PrimaryVariables currentPriVars(u[i]);
+            PrimaryVariables nextPriVars(currentPriVars);
+            nextPriVars -= uDelta[i];
+
+            // we need to add the distance the solution was moved for
+            // this vertex
+            Scalar dist = model_().relativeErrorVertex(i,
+                                                       currentPriVars,
+                                                       nextPriVars);
+            vertexDelta_[i] += std::abs(dist);
+        }
+
+    }
+
+    /*!
+     * \brief Force to reassemble a given vertex next time the
+     *        assemble() method is called.
+     *
+     * \param globalVertIdx The global index of the vertex which ought
+     *                      to be red.
+     */
+    void markVertexRed(const int globalVertIdx)
+    {
+        if (!enablePartialReassemble_())
+            return;
+
+        vertexColor_[globalVertIdx] = Red;
+    }
+
+    /*!
+     * \brief Determine the colors of vertices and elements for partial
+     *        reassembly given a relative tolerance.
+     *
+     * The following approach is used:
+     *
+     * - Set all vertices and elements to 'green'
+     * - Mark all vertices as 'red' which exhibit an relative error above
+     *   the tolerance
+     * - Mark all elements which feature a 'red' vetex as 'red'
+     * - Mark all vertices which are not 'red' and are part of a
+     *   'red' element as 'yellow'
+     * - Mark all elements which are not 'red' and contain a
+     *   'yellow' vertex as 'yellow'
+     *
+     * \param relTol The relative error below which a vertex won't be
+     *               reassembled. Note that this specifies the
+     *               worst-case relative error between the last
+     *               linearization point and the current solution and
+     *               _not_ the delta vector of the Newton iteration!
+     */
+    void computeColors(const Scalar relTol)
+    {
+        if (!enablePartialReassemble_())
+            return;
+
+        ElementIterator elemIt = gridView_().template begin<0>();
+        ElementIterator elemEndIt = gridView_().template end<0>();
+
+        // mark the red vertices and update the tolerance of the
+        // linearization which actually will get achieved
+        nextReassembleAccuracy_ = 0;
+        for (unsigned int i = 0; i < vertexColor_.size(); ++i) {
+            if (vertexDelta_[i] > relTol)
+                // mark vertex as red if discrepancy is larger than
+                // the relative tolerance
+                vertexColor_[i] = Red;
+            else
+                nextReassembleAccuracy_ =
+                    std::max(nextReassembleAccuracy_, vertexDelta_[i]);
+        }
+
+        // Mark all red elements
+        for (; elemIt != elemEndIt; ++elemIt) {
+            // find out whether the current element features a red
+            // vertex
+            bool isRed = false;
+            int numVerts = elemIt->template count<dim>();
+            for (int i=0; i < numVerts; ++i) {
+                int globalI = vertexMapper_().map(*elemIt, i, dim);
+                if (vertexColor_[globalI] == Red) {
+                    isRed = true;
+                    break;
+                }
+            }
+
+            // if yes, the element color is also red, else it is not
+            // red, i.e. green for the mean time
+            int globalElemIdx = elementMapper_().map(*elemIt);
+            if (isRed)
+                elementColor_[globalElemIdx] = Red;
+            else
+                elementColor_[globalElemIdx] = Green;
+        }
+
+        // Mark yellow vertices (as orange for the mean time)
+        elemIt = gridView_().template begin<0>();
+        for (; elemIt != elemEndIt; ++elemIt) {
+            int elemIdx = this->elementMapper_().map(*elemIt);
+            if (elementColor_[elemIdx] != Red)
+                continue; // non-red elements do not tint vertices
+                          // yellow!
+
+            int numVerts = elemIt->template count<dim>();
+            for (int i=0; i < numVerts; ++i) {
+                int globalI = vertexMapper_().map(*elemIt, i, dim);
+                // if a vertex is already red, don't recolor it to
+                // yellow!
+                if (vertexColor_[globalI] != Red) {
+                    vertexColor_[globalI] = Orange;
+                }
+            }
+        }
+
+        // at this point we communicate the yellow vertices to the
+        // neighboring processes because a neigbor process may not see
+        // the red vertex for yellow border vertices
+        VertexHandleMin<EntityColor, std::vector<EntityColor>,  VertexMapper>
+            minHandle(vertexColor_, vertexMapper_());
+        gridView_().communicate(minHandle,
+                                Dune::InteriorBorder_InteriorBorder_Interface,
+                                Dune::ForwardCommunication);
+
+        // Mark yellow elements
+        elemIt = gridView_().template begin<0>();
+        for (; elemIt != elemEndIt; ++elemIt) {
+            int elemIdx = this->elementMapper_().map(*elemIt);
+            if (elementColor_[elemIdx] == Red) {
+                continue; // element is red already!
+            }
+
+            // check whether the element features a yellow
+            // (resp. orange at this point) vertex
+            bool isYellow = false;
+            int numVerts = elemIt->template count<dim>();
+            for (int i=0; i < numVerts; ++i) {
+                int globalI = vertexMapper_().map(*elemIt, i, dim);
+                if (vertexColor_[globalI] == Orange) {
+                    isYellow = true;
+                    break;
+                }
+            }
+
+            if (isYellow)
+                elementColor_[elemIdx] = Yellow;
+        }
+
+        // Demote orange vertices to yellow ones if it has at least
+        // one green element as a neighbor.
+        elemIt = gridView_().template begin<0>();
+        for (; elemIt != elemEndIt; ++elemIt) {
+            int elemIdx = this->elementMapper_().map(*elemIt);
+            if (elementColor_[elemIdx] != Green)
+                continue; // yellow and red elements do not make
+                          // orange vertices yellow!
+
+            int numVerts = elemIt->template count<dim>();
+            for (int i=0; i < numVerts; ++i) {
+                int globalI = vertexMapper_().map(*elemIt, i, dim);
+                // if a vertex is orange, recolor it to yellow!
+                if (vertexColor_[globalI] == Orange)
+                    vertexColor_[globalI] = Yellow;
+            }
+        }
+
+        // demote the border orange vertices
+        VertexHandleMax<EntityColor, std::vector<EntityColor>,  VertexMapper>
+            maxHandle(vertexColor_,
+                      vertexMapper_());
+        gridView_().communicate(maxHandle,
+                                Dune::InteriorBorder_InteriorBorder_Interface,
+                                Dune::ForwardCommunication);
+
+        // promote the remaining orange vertices to red
+        for (unsigned int i=0; i < vertexColor_.size(); ++i) {
+            // if a vertex is green or yellow don't do anything!
+            if (vertexColor_[i] == Green || vertexColor_[i] == Yellow)
+                continue;
+
+            // make sure the vertex is red (this is a no-op vertices
+            // which are already red!)
+            vertexColor_[i] = Red;
+
+            // set the error of this vertex to 0 because the system
+            // will be consistently linearized at this vertex
+            vertexDelta_[i] = 0.0;
+        }
+    }
+
+    /*!
+     * \brief Returns the reassemble color of a vertex
+     *
+     * \param element An element which contains the vertex
+     * \param vertIdx The local index of the vertex in the element.
+     */
+    int vertexColor(const Element &element, const int vertIdx) const
+    {
+        if (!enablePartialReassemble_())
+            return Red; // reassemble unconditionally!
+
+        int globalIdx = vertexMapper_().map(element, vertIdx, dim);
+        return vertexColor_[globalIdx];
+    }
+
+    /*!
+     * \brief Returns the reassemble color of a vertex
+     *
+     * \param globalVertIdx The global index of the vertex.
+     */
+    int vertexColor(const int globalVertIdx) const
+    {
+        if (!enablePartialReassemble_())
+            return Red; // reassemble unconditionally!
+        return vertexColor_[globalVertIdx];
+    }
+
+    /*!
+     * \brief Returns the Jacobian reassemble color of an element
+     *
+     * \param element The Codim-0 DUNE entity
+     */
+    int elementColor(const Element &element) const
+    {
+        if (!enablePartialReassemble_())
+            return Red; // reassemble unconditionally!
+
+        int globalIdx = elementMapper_().map(element);
+        return elementColor_[globalIdx];
+    }
+
+    /*!
+     * \brief Returns the Jacobian reassemble color of an element
+     *
+     * \param globalElementIdx The global index of the element.
+     */
+    int elementColor(const int globalElementIdx) const
+    {
+        if (!enablePartialReassemble_())
+            return Red; // reassemble unconditionally!
+        return elementColor_[globalElementIdx];
+    }
+
+    /*!
+     * \brief Return constant reference to global Jacobian matrix.
+     */
+    const JacobianMatrix& matrix() const
+    { return *matrix_; }
+    JacobianMatrix& matrix()
+    { return *matrix_; }
+
+    /*!
+     * \brief Return constant reference to global residual vector.
+     */
+    const SolutionVector& residual() const
+    { return residual_; }
+    SolutionVector& residual() 
+    { return residual_; }
+
+private:
+    static bool enableJacobianRecycling_()
+    { return GET_PARAM_FROM_GROUP(TypeTag, bool, Implicit, EnableJacobianRecycling); }
+    static bool enablePartialReassemble_()
+    { return GET_PARAM_FROM_GROUP(TypeTag, bool, Implicit, EnablePartialReassemble); }
+
+    // Construct the BCRS matrix for the global jacobian
+    void createMatrix_()
+    {
+        int numVerticesGlobal = gridView_().size(dim);
+
+        // allocate raw matrix
+        matrix_ = new JacobianMatrix(numVerticesGlobal, numVerticesGlobal, JacobianMatrix::random);
+
+        // find out the global indices of the neighboring vertices of
+        // each vertex
+        typedef std::set<int> NeighborSet;
+        std::vector<NeighborSet> neighbors(numVerticesGlobal);
+        ElementIterator eIt = gridView_().template begin<0>();
+        const ElementIterator eEndIt = gridView_().template end<0>();
+        for (; eIt != eEndIt; ++eIt) {
+            const Element &elem = *eIt;
+            int numVerticesLocal = elem.template count<dim>();
+
+            // if the element is not in the interior or the process
+            // border, all dofs just contain main-diagonal entries
+            if (elem.partitionType() != Dune::InteriorEntity &&
+                elem.partitionType() != Dune::BorderEntity)
+            {
+                for (int i = 0; i < numVerticesLocal; ++i) {
+                    int globalI = vertexMapper_().map(*eIt, i, dim);
+                    neighbors[globalI].insert(globalI);
+                }
+            }
+            else
+            {
+                // loop over all element vertices
+                for (int i = 0; i < numVerticesLocal - 1; ++i) {
+                    int globalI = vertexMapper_().map(*eIt, i, dim);
+                    for (int j = i + 1; j < numVerticesLocal; ++j) {
+                        int globalJ = vertexMapper_().map(*eIt, j, dim);
+                        // make sure that vertex j is in the neighbor set
+                        // of vertex i and vice-versa
+                        neighbors[globalI].insert(globalJ);
+                        neighbors[globalJ].insert(globalI);
+                    }
+                }
+            }
+        }
+
+        // make vertices neighbors to themselfs
+        for (int i = 0; i < numVerticesGlobal; ++i) {
+            neighbors[i].insert(i);
+        }
+        
+        // allocate space for the rows of the matrix
+        for (int i = 0; i < numVerticesGlobal; ++i) {
+            matrix_->setrowsize(i, neighbors[i].size());
+        }
+        matrix_->endrowsizes();
+
+        // fill the rows with indices. each vertex talks to all of its
+        // neighbors. (it also talks to itself since vertices are
+        // sometimes quite egocentric.)
+        for (int i = 0; i < numVerticesGlobal; ++i) {
+            typename NeighborSet::iterator nIt = neighbors[i].begin();
+            typename NeighborSet::iterator nEndIt = neighbors[i].end();
+            for (; nIt != nEndIt; ++nIt) {
+                matrix_->addindex(i, *nIt);
+            }
+        }
+        matrix_->endindices();
+    }
+
+    // reset the global linear system of equations. if partial
+    // reassemble is enabled, this means that the jacobian matrix must
+    // only be erased partially!
+    void resetSystem_()
+    {
+        // do not do anything if we can re-use the current linearization
+        if (reuseMatrix_)
+            return;
+
+        // reset the right hand side.
+        residual_ = 0.0;
+
+        if (!enablePartialReassemble_()) {
+            // If partial reassembly of the jacobian is not enabled,
+            // we can just reset everything!
+            (*matrix_) = 0;
+
+            // reset the parts needed for Jacobian recycling
+            if (enableJacobianRecycling_()) {
+                int numVerticesGlobal = matrix_->N();
+                for (int i=0; i < numVerticesGlobal; ++ i) {
+                    storageJacobian_[i] = 0;
+                    storageTerm_[i] = 0;
+                }
+            }
+
+            return;
+        }
+
+        // reset all entries corrosponding to a red or yellow vertex
+        for (unsigned int rowIdx = 0; rowIdx < matrix_->N(); ++rowIdx) {
+            if (vertexColor_[rowIdx] == Green)
+                continue; // the equations for this control volume are
+                          // already below the treshold
+
+            // here we have yellow or red vertices...
+
+            // reset the parts needed for Jacobian recycling
+            if (enableJacobianRecycling_()) {
+                storageJacobian_[rowIdx] = 0;
+                storageTerm_[rowIdx] = 0;
+            }
+
+            // set all matrix entries in the row to 0
+            typedef typename JacobianMatrix::ColIterator ColIterator;
+            ColIterator colIt = (*matrix_)[rowIdx].begin();
+            const ColIterator &colEndIt = (*matrix_)[rowIdx].end();
+            for (; colIt != colEndIt; ++colIt) {
+                (*colIt) = 0.0;
+            }
+        }
+    }
+
+    // linearize the whole system
+    void assemble_()
+    {
+        resetSystem_();
+
+        // if we can "recycle" the current linearization, we do it
+        // here and be done with it...
+        Scalar curDt = problem_().timeManager().timeStepSize();
+        if (reuseMatrix_) {
+            int numVerticesGlobal = storageJacobian_.size();
+            for (int i = 0; i < numVerticesGlobal; ++i) {
+                // rescale the mass term of the jacobian matrix
+                MatrixBlock &J_i_i = (*matrix_)[i][i];
+
+                J_i_i -= storageJacobian_[i];
+                storageJacobian_[i] *= oldDt_/curDt;
+                J_i_i += storageJacobian_[i];
+
+                // use the flux term plus the source term as the new
+                // residual (since the delta in the d(storage)/dt is 0
+                // for the first iteration and the residual is
+                // approximately 0 in the last iteration, the flux
+                // term plus the source term must be equal to the
+                // negative change of the storage term of the last
+                // iteration of the last time step...)
+                residual_[i] = storageTerm_[i];
+                residual_[i] *= -1;
+            }
+
+            reuseMatrix_ = false;
+            oldDt_ = curDt;
+            return;
+        }
+
+        oldDt_ = curDt;
+        greenElems_ = 0;
+
+        // reassemble the elements...
+        ElementIterator elemIt = gridView_().template begin<0>();
+        ElementIterator elemEndIt = gridView_().template end<0>();
+        for (; elemIt != elemEndIt; ++elemIt) {
+            const Element &elem = *elemIt;
+            if (elem.partitionType() != Dune::InteriorEntity  &&
+                elem.partitionType() != Dune::BorderEntity)
+            {
+                assembleGhostElement_(elem);
+            }
+            else
+            {
+                assembleElement_(elem);
+            }
+        }
+    }
+
+    // assemble a non-ghost element
+    void assembleElement_(const Element &elem)
+    {
+        if (enablePartialReassemble_()) {
+            int globalElemIdx = model_().elementMapper().map(elem);
+            if (elementColor_[globalElemIdx] == Green) {
+                ++greenElems_;
+
+                assembleGreenElement_(elem);
+                return;
+            }
+        }
+
+        model_().localJacobian().assemble(elem);
+
+        int numVerticesLocal = elem.template count<dim>();
+        for (int i=0; i < numVerticesLocal; ++ i) {
+            int globI = vertexMapper_().map(elem, i, dim);
+
+            // update the right hand side
+            residual_[globI] += model_().localJacobian().residual(i);
+            for (int j = 0; j < residual_[globI].dimension; ++j)
+                assert(std::isfinite(residual_[globI][j]));
+            if (enableJacobianRecycling_()) {
+                storageTerm_[globI] +=
+                    model_().localJacobian().storageTerm(i);
+            }
+
+            // only update the jacobian matrix for non-green vertices
+            if (vertexColor(globI) != Green) {
+                if (enableJacobianRecycling_())
+                    storageJacobian_[globI] +=
+                        model_().localJacobian().storageJacobian(i);
+
+                // update the jacobian matrix
+                for (int j=0; j < numVerticesLocal; ++ j) {
+                    int globJ = vertexMapper_().map(elem, j, dim);
+                    (*matrix_)[globI][globJ] +=
+                        model_().localJacobian().mat(i,j);
+                }
+            }
+        }
+    }
+
+    // "assemble" a green element. green elements only get the
+    // residual updated, but the jacobian is left alone...
+    void assembleGreenElement_(const Element &elem)
+    {
+        model_().localResidual().eval(elem);
+
+        int numVerticesLocal = elem.template count<dim>();
+        for (int i=0; i < numVerticesLocal; ++ i) {
+            int globI = vertexMapper_().map(elem, i, dim);
+
+            // update the right hand side
+            residual_[globI] += model_().localResidual().residual(i);
+            if (enableJacobianRecycling_())
+                storageTerm_[globI] += model_().localResidual().storageTerm(i);
+        }
+    }
+
+    // "assemble" a ghost element
+    void assembleGhostElement_(const Element &elem)
+    {
+        int numVerticesLocal = elem.template count<dim>();
+        for (int i=0; i < numVerticesLocal; ++i) {
+            const VertexPointer vp = elem.template subEntity<dim>(i);
+
+            if (vp->partitionType() == Dune::InteriorEntity ||
+                vp->partitionType() == Dune::BorderEntity)
+            {
+                // do not change the non-ghost vertices
+                continue;
+            }
+
+            // set main diagonal entries for the vertex
+            int vIdx = vertexMapper_().map(*vp);
+            typedef typename JacobianMatrix::block_type BlockType;
+            BlockType &J = (*matrix_)[vIdx][vIdx];
+            for (int j = 0; j < BlockType::rows; ++j)
+                J[j][j] = 1.0;
+
+            // set residual for the vertex
+            residual_[vIdx] = 0;
+        }
+    }
+
+
+    Problem &problem_()
+    { return *problemPtr_; }
+    const Problem &problem_() const
+    { return *problemPtr_; }
+    const Model &model_() const
+    { return problem_().model(); }
+    Model &model_()
+    { return problem_().model(); }
+    const GridView &gridView_() const
+    { return problem_().gridView(); }
+    const VertexMapper &vertexMapper_() const
+    { return problem_().vertexMapper(); }
+    const ElementMapper &elementMapper_() const
+    { return problem_().elementMapper(); }
+
+    Problem *problemPtr_;
+
+    // the jacobian matrix
+    JacobianMatrix *matrix_;
+    // the right-hand side
+    SolutionVector residual_;
+
+    // attributes required for jacobian matrix recycling
+    bool reuseMatrix_;
+    // The storage part of the local Jacobian
+    std::vector<MatrixBlock> storageJacobian_;
+    std::vector<VectorBlock> storageTerm_;
+    // time step size of last assembly
+    Scalar oldDt_;
+
+
+    // attributes required for partial jacobian reassembly
+    std::vector<EntityColor> vertexColor_;
+    std::vector<EntityColor> elementColor_;
+    std::vector<Scalar> vertexDelta_;
+
+    int totalElems_;
+    int greenElems_;
+
+    Scalar nextReassembleAccuracy_;
+    Scalar reassembleAccuracy_;
+};
+
+} // namespace Dumux
+
+#endif
diff --git a/dumux/implicit/box/boxdarcyfluxvariables.hh b/dumux/implicit/box/boxdarcyfluxvariables.hh
new file mode 100644
index 0000000000..6e5d3df449
--- /dev/null
+++ b/dumux/implicit/box/boxdarcyfluxvariables.hh
@@ -0,0 +1,313 @@
+// -*- mode: C++; tab-width: 4; indent-tabs-mode: nil; c-basic-offset: 4 -*-
+// vi: set et ts=4 sw=4 sts=4:
+/*****************************************************************************
+ *   See the file COPYING for full copying permissions.                      *
+ *                                                                           *
+ *   This program is free software: you can redistribute it and/or modify    *
+ *   it under the terms of the GNU General Public License as published by    *
+ *   the Free Software Foundation, either version 2 of the License, or       *
+ *   (at your option) any later version.                                     *
+ *                                                                           *
+ *   This program is distributed in the hope that it will be useful,         *
+ *   but WITHOUT ANY WARRANTY; without even the implied warranty of          *
+ *   MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the            *
+ *   GNU General Public License for more details.                            *
+ *                                                                           *
+ *   You should have received a copy of the GNU General Public License       *
+ *   along with this program.  If not, see <http://www.gnu.org/licenses/>.   *
+ *****************************************************************************/
+/*!
+ * \file
+ *
+ * \brief This file contains the data which is required to calculate
+ *        all fluxes of fluid phases over a face of a finite volume.
+ *
+ * This means pressure and temperature gradients, phase densities at
+ * the integration point, etc.
+ */
+#ifndef DUMUX_BOX_DARCY_FLUX_VARIABLES_HH
+#define DUMUX_BOX_DARCY_FLUX_VARIABLES_HH
+
+#include "boxproperties.hh"
+
+#include <dumux/common/parameters.hh>
+#include <dumux/common/math.hh>
+
+namespace Dumux
+{
+    
+namespace Properties
+{
+// forward declaration of properties 
+NEW_PROP_TAG(ImplicitMobilityUpwindWeight);
+NEW_PROP_TAG(SpatialParams);
+NEW_PROP_TAG(NumPhases);
+NEW_PROP_TAG(ProblemEnableGravity);
+}   
+
+/*!
+ * \ingroup BoxModel
+ * \ingroup BoxFluxVariables
+ * \brief Evaluates the normal component of the Darcy velocity 
+ * on a (sub)control volume face.
+ */
+template <class TypeTag>
+class BoxDarcyFluxVariables
+{
+    typedef typename GET_PROP_TYPE(TypeTag, Problem) Problem;
+    typedef typename GET_PROP_TYPE(TypeTag, SpatialParams) SpatialParams;
+    typedef typename GET_PROP_TYPE(TypeTag, ElementVolumeVariables) ElementVolumeVariables;
+    typedef typename GET_PROP_TYPE(TypeTag, VolumeVariables) VolumeVariables;
+    
+    typedef typename GET_PROP_TYPE(TypeTag, GridView) GridView;
+    typedef typename GridView::template Codim<0>::Entity Element;
+
+    enum { dim = GridView::dimension} ;
+    enum { dimWorld = GridView::dimensionworld} ;
+    enum { numPhases = GET_PROP_VALUE(TypeTag, NumPhases)} ;
+
+    typedef typename GET_PROP_TYPE(TypeTag, Scalar) Scalar;
+    typedef Dune::FieldMatrix<Scalar, dimWorld, dimWorld> Tensor;
+    typedef Dune::FieldVector<Scalar, dimWorld> DimVector;
+
+    typedef typename GET_PROP_TYPE(TypeTag, FVElementGeometry) FVElementGeometry;
+    typedef typename FVElementGeometry::SubControlVolumeFace SCVFace;
+
+public:
+    /*
+     * \brief The constructor
+     *
+     * \param problem The problem
+     * \param element The finite element
+     * \param fvGeometry The finite-volume geometry in the box scheme
+     * \param faceIdx The local index of the SCV (sub-control-volume) face
+     * \param elemVolVars The volume variables of the current element
+     * \param onBoundary A boolean variable to specify whether the flux variables
+     * are calculated for interior SCV faces or boundary faces, default=false
+     */
+    BoxDarcyFluxVariables(const Problem &problem,
+                 const Element &element,
+                 const FVElementGeometry &fvGeometry,
+                 const int faceIdx,
+                 const ElementVolumeVariables &elemVolVars,
+                 const bool onBoundary = false)
+        : fvGeometry_(fvGeometry), faceIdx_(faceIdx), onBoundary_(onBoundary)
+    {
+        mobilityUpwindWeight_ = GET_PARAM_FROM_GROUP(TypeTag, Scalar, Implicit, MobilityUpwindWeight);
+        calculateGradients_(problem, element, elemVolVars);
+        calculateNormalVelocity_(problem, element, elemVolVars);
+    }
+
+public:
+    /*!
+     * \brief Return the volumetric flux over a face of a given phase.
+     *
+     *        This is the calculated velocity multiplied by the unit normal
+     *        and the area of the face.
+     *        face().normal
+     *        has already the magnitude of the area.
+     *
+     * \param phaseIdx index of the phase
+     */
+    Scalar volumeFlux(const unsigned int phaseIdx) const
+    { return volumeFlux_[phaseIdx]; }
+    
+    /*!
+     * \brief Return the velocity of a given phase.
+     *
+     *        This is the full velocity vector on the
+     *        face (without being multiplied with normal).
+     *
+     * \param phaseIdx index of the phase
+     */
+    DimVector velocity(const unsigned int phaseIdx) const
+    { return velocity_[phaseIdx] ; }
+
+    /*!
+     * \brief Return intrinsic permeability multiplied with potential
+     *        gradient multiplied with normal.
+     *        I.e. everything that does not need upwind decisions.
+     *
+     * \param phaseIdx index of the phase
+     */
+    Scalar kGradPNormal(const unsigned int phaseIdx) const
+    { return kGradPNormal_[phaseIdx] ; }
+
+    /*!
+     * \brief Return the local index of the downstream control volume
+     *        for a given phase.
+     *
+     * \param phaseIdx index of the phase
+     */
+    const unsigned int downstreamIdx(const unsigned phaseIdx) const
+    { return downstreamIdx_[phaseIdx]; }
+    
+    /*!
+     * \brief Return the local index of the upstream control volume
+     *        for a given phase.
+     *
+     * \param phaseIdx index of the phase
+     */
+    const unsigned int upstreamIdx(const unsigned phaseIdx) const
+    { return upstreamIdx_[phaseIdx]; }
+
+    /*!
+     * \brief Return the SCV (sub-control-volume) face. This may be either
+     *        a face within the element or a face on the element boundary,
+     *        depending on the value of onBoundary_.
+     */
+    const SCVFace &face() const
+    {
+        if (onBoundary_)
+            return fvGeometry_.boundaryFace[faceIdx_];
+        else
+            return fvGeometry_.subContVolFace[faceIdx_];
+    }
+
+protected:
+    const FVElementGeometry &fvGeometry_;   //!< Information about the geometry of discretization
+    const unsigned int faceIdx_;            //!< The index of the sub control volume face
+    const bool      onBoundary_;                //!< Specifying whether we are currently on the boundary of the simulation domain
+    unsigned int    upstreamIdx_[numPhases] , downstreamIdx_[numPhases]; //!< local index of the upstream / downstream vertex
+    Scalar          volumeFlux_[numPhases] ;    //!< Velocity multiplied with normal (magnitude=area)
+    DimVector       velocity_[numPhases] ;      //!< The velocity as determined by Darcy's law or by the Forchheimer relation
+    Scalar          kGradPNormal_[numPhases] ;  //!< Permeability multiplied with gradient in potential, multiplied with normal (magnitude=area)
+    DimVector       kGradP_[numPhases] ; //!< Permeability multiplied with gradient in potential
+    DimVector       gradPotential_[numPhases] ; //!< Gradient of potential, which drives flow
+    Scalar          mobilityUpwindWeight_;      //!< Upwind weight for mobility. Set to one for full upstream weighting
+
+    /*
+     * \brief Calculation of the potential gradients
+     *
+     * \param problem The problem
+     * \param element The finite element
+     * \param elemVolVars The volume variables of the current element
+     * are calculated for interior SCV faces or boundary faces, default=false
+     */
+    void calculateGradients_(const Problem &problem,
+                             const Element &element,
+                             const ElementVolumeVariables &elemVolVars)
+    {
+        // loop over all phases
+        for (int phaseIdx = 0; phaseIdx < numPhases; phaseIdx++)
+        {
+            gradPotential_[phaseIdx]= 0.0 ;
+            for (int idx = 0;
+                 idx < fvGeometry_.numFAP;
+                 idx++) // loop over adjacent vertices
+            {
+                // FE gradient at vertex idx
+                const DimVector &feGrad = face().grad[idx];
+
+                // index for the element volume variables
+                int volVarsIdx = face().fapIndices[idx];
+
+                // the pressure gradient
+                DimVector tmp(feGrad);
+                tmp *= elemVolVars[volVarsIdx].fluidState().pressure(phaseIdx);
+                gradPotential_[phaseIdx] += tmp;
+            }
+
+            // correct the pressure gradient by the gravitational acceleration
+            if (GET_PARAM_FROM_GROUP(TypeTag, bool, Problem, EnableGravity))
+            {
+                // estimate the gravitational acceleration at a given SCV face
+                // using the arithmetic mean
+                DimVector g(problem.boxGravity(element, fvGeometry_, face().i));
+                g += problem.boxGravity(element, fvGeometry_, face().j);
+                g /= 2;
+
+                // calculate the phase density at the integration point. we
+                // only do this if the wetting phase is present in both cells
+                Scalar SI = elemVolVars[face().i].fluidState().saturation(phaseIdx);
+                Scalar SJ = elemVolVars[face().j].fluidState().saturation(phaseIdx);
+                Scalar rhoI = elemVolVars[face().i].fluidState().density(phaseIdx);
+                Scalar rhoJ = elemVolVars[face().j].fluidState().density(phaseIdx);
+                Scalar fI = std::max(0.0, std::min(SI/1e-5, 0.5));
+                Scalar fJ = std::max(0.0, std::min(SJ/1e-5, 0.5));
+                if (fI + fJ == 0)
+                    // doesn't matter because no wetting phase is present in
+                    // both cells!
+                    fI = fJ = 0.5;
+                const Scalar density = (fI*rhoI + fJ*rhoJ)/(fI + fJ);
+
+                // make gravity acceleration a force
+                DimVector f(g);
+                f *= density;
+
+                // calculate the final potential gradient
+                gradPotential_[phaseIdx] -= f;
+            } // gravity
+        } // loop over all phases
+     }
+
+    /*
+     * \brief Actual calculation of the normal Darcy velocities.
+     *
+     * \param problem The problem
+     * \param element The finite element
+     * \param elemVolVars The volume variables of the current element
+     */
+    void calculateNormalVelocity_(const Problem &problem,
+                                  const Element &element,
+                                  const ElementVolumeVariables &elemVolVars)
+    {
+        // calculate the mean intrinsic permeability
+        const SpatialParams &spatialParams = problem.spatialParams();
+        Tensor K;
+        spatialParams.meanK(K,
+                            spatialParams.intrinsicPermeability(element,
+                                                                fvGeometry_,
+                                                                face().i),
+                            spatialParams.intrinsicPermeability(element,
+                                                                fvGeometry_,
+                                                                face().j));
+        // loop over all phases
+        for (int phaseIdx = 0; phaseIdx < numPhases; phaseIdx++)
+        {
+            // calculate the flux in the normal direction of the
+            // current sub control volume face:
+            //
+            // v = - (K_f grad phi) * n
+            // with K_f = rho g / mu K
+            //
+            // Mind, that the normal has the length of it's area.
+            // This means that we are actually calculating
+            //  Q = - (K grad phi) dot n /|n| * A
+
+
+            K.mv(gradPotential_[phaseIdx], kGradP_[phaseIdx]);
+            kGradPNormal_[phaseIdx] = kGradP_[phaseIdx]*face().normal;
+
+            // determine the upwind direction
+            if (kGradPNormal_[phaseIdx] < 0)
+            {
+                upstreamIdx_[phaseIdx] = face().i;
+                downstreamIdx_[phaseIdx] = face().j;
+            }
+            else
+            {
+                upstreamIdx_[phaseIdx] = face().j;
+                downstreamIdx_[phaseIdx] = face().i;
+            }
+            
+            // obtain the upwind volume variables
+            const VolumeVariables& upVolVars = elemVolVars[ upstreamIdx(phaseIdx) ];
+            const VolumeVariables& downVolVars = elemVolVars[ downstreamIdx(phaseIdx) ];
+
+            // the minus comes from the Darcy relation which states that
+            // the flux is from high to low potentials.
+            // set the velocity
+            velocity_[phaseIdx] = kGradP_[phaseIdx];
+            velocity_[phaseIdx] *= - ( mobilityUpwindWeight_*upVolVars.mobility(phaseIdx)
+                    + (1.0 - mobilityUpwindWeight_)*downVolVars.mobility(phaseIdx)) ;
+
+            // set the volume flux
+            volumeFlux_[phaseIdx] = velocity_[phaseIdx] * face().normal ;
+        }// loop all phases
+    }
+};
+
+} // end namespace
+
+#endif
diff --git a/dumux/implicit/box/boxelementboundarytypes.hh b/dumux/implicit/box/boxelementboundarytypes.hh
new file mode 100644
index 0000000000..fe7e02a09c
--- /dev/null
+++ b/dumux/implicit/box/boxelementboundarytypes.hh
@@ -0,0 +1,148 @@
+// -*- mode: C++; tab-width: 4; indent-tabs-mode: nil; c-basic-offset: 4 -*-
+// vi: set et ts=4 sw=4 sts=4:
+/*****************************************************************************
+ *   See the file COPYING for full copying permissions.                      *
+ *                                                                           *
+ *   This program is free software: you can redistribute it and/or modify    *
+ *   it under the terms of the GNU General Public License as published by    *
+ *   the Free Software Foundation, either version 2 of the License, or       *
+ *   (at your option) any later version.                                     *
+ *                                                                           *
+ *   This program is distributed in the hope that it will be useful,         *
+ *   but WITHOUT ANY WARRANTY; without even the implied warranty of          *
+ *   MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the            *
+ *   GNU General Public License for more details.                            *
+ *                                                                           *
+ *   You should have received a copy of the GNU General Public License       *
+ *   along with this program.  If not, see <http://www.gnu.org/licenses/>.   *
+ *****************************************************************************/
+/*!
+ * \file
+ *
+ * \brief Boundary types gathered on an element
+ */
+#ifndef DUMUX_BOX_ELEMENT_BOUNDARY_TYPES_HH
+#define DUMUX_BOX_ELEMENT_BOUNDARY_TYPES_HH
+
+#include "boxproperties.hh"
+
+#include <dumux/common/valgrind.hh>
+
+namespace Dumux
+{
+
+/*!
+ * \ingroup BoxModel
+ * \ingroup BoxBoundaryTypes
+ *
+ * \brief This class stores an array of BoundaryTypes objects
+ */
+template<class TypeTag>
+class BoxElementBoundaryTypes : public std::vector<typename GET_PROP_TYPE(TypeTag, BoundaryTypes) >
+{
+    typedef typename GET_PROP_TYPE(TypeTag, BoundaryTypes) BoundaryTypes;
+    typedef std::vector<BoundaryTypes> ParentType;
+
+    typedef typename GET_PROP_TYPE(TypeTag, Problem) Problem;
+    typedef typename GET_PROP_TYPE(TypeTag, GridView) GridView;
+    typedef typename GET_PROP_TYPE(TypeTag, FVElementGeometry) FVElementGeometry;
+
+    enum { dim = GridView::dimension };
+    typedef typename GridView::template Codim<0>::Entity Element;
+    typedef typename GridView::template Codim<dim>::EntityPointer VertexPointer;
+
+public:
+    /*!
+     * \brief Copy constructor.
+     *
+     * Copying a the boundary types of an element should be explicitly
+     * requested
+     */
+    explicit BoxElementBoundaryTypes(const BoxElementBoundaryTypes &v)
+        : ParentType(v)
+    {}
+
+    /*!
+     * \brief Default constructor.
+     */
+    BoxElementBoundaryTypes()
+    {
+        hasDirichlet_ = false;
+        hasNeumann_ = false;
+        hasOutflow_ = false;
+    }
+
+    /*!
+     * \brief Update the boundary types for all vertices of an element.
+     *
+     * \param problem The problem object which needs to be simulated
+     * \param element The DUNE Codim<0> entity for which the boundary
+     *                types should be collected
+     */
+    void update(const Problem &problem,
+                const Element &element)
+    {
+        int numVerts = element.template count<dim>();
+        this->resize(numVerts);
+
+        hasDirichlet_ = false;
+        hasNeumann_ = false;
+        hasOutflow_ = false;
+
+        for (int i = 0; i < numVerts; ++i) {
+            (*this)[i].reset();
+
+            if (problem.model().onBoundary(element, i)) {
+                const VertexPointer vptr = element.template subEntity<dim>(i);
+                problem.boundaryTypes((*this)[i], *vptr);
+
+                hasDirichlet_ = hasDirichlet_ || (*this)[i].hasDirichlet();
+                hasNeumann_ = hasNeumann_ || (*this)[i].hasNeumann();
+                hasOutflow_ = hasOutflow_ || (*this)[i].hasOutflow();
+            }
+        }
+    }
+
+    /*!
+     * \brief Update the boundary types for all vertices of an element.
+     *
+     * \param problem The problem object which needs to be simulated
+     * \param element The DUNE Codim<0> entity for which the boundary
+     *                types should be collected
+     * \param fvGeometry The element's finite volume geometry
+     */
+    void update(const Problem &problem,
+                const Element &element,
+                const FVElementGeometry &fvGeometry)
+    { update(problem, element); }
+    
+    /*!
+     * \brief Returns whether the element has a vertex which contains
+     *        a Dirichlet value.
+     */
+    bool hasDirichlet() const
+    { return hasDirichlet_; }
+
+    /*!
+     * \brief Returns whether the element potentially features a
+     *        Neumann boundary segment.
+     */
+    bool hasNeumann() const
+    { return hasNeumann_; }
+
+    /*!
+     * \brief Returns whether the element potentially features an
+     *        outflow boundary segment.
+     */
+    bool hasOutflow() const
+    { return hasOutflow_; }
+
+protected:
+    bool hasDirichlet_;
+    bool hasNeumann_;
+    bool hasOutflow_;
+};
+
+} // namespace Dumux
+
+#endif
diff --git a/dumux/implicit/box/boxelementvolumevariables.hh b/dumux/implicit/box/boxelementvolumevariables.hh
new file mode 100644
index 0000000000..c791bee09b
--- /dev/null
+++ b/dumux/implicit/box/boxelementvolumevariables.hh
@@ -0,0 +1,138 @@
+// -*- mode: C++; tab-width: 4; indent-tabs-mode: nil; c-basic-offset: 4 -*-
+// vi: set et ts=4 sw=4 sts=4:
+/*****************************************************************************
+ *   See the file COPYING for full copying permissions.                      *
+ *                                                                           *
+ *   This program is free software: you can redistribute it and/or modify    *
+ *   it under the terms of the GNU General Public License as published by    *
+ *   the Free Software Foundation, either version 2 of the License, or       *
+ *   (at your option) any later version.                                     *
+ *                                                                           *
+ *   This program is distributed in the hope that it will be useful,         *
+ *   but WITHOUT ANY WARRANTY; without even the implied warranty of          *
+ *   MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the            *
+ *   GNU General Public License for more details.                            *
+ *                                                                           *
+ *   You should have received a copy of the GNU General Public License       *
+ *   along with this program.  If not, see <http://www.gnu.org/licenses/>.   *
+ *****************************************************************************/
+/*!
+ * \file
+ *
+ * \brief Volume variables gathered on an element
+ */
+#ifndef DUMUX_BOX_ELEMENT_VOLUME_VARIABLES_HH
+#define DUMUX_BOX_ELEMENT_VOLUME_VARIABLES_HH
+
+#include "boxproperties.hh"
+
+
+namespace Dumux
+{
+
+/*!
+ * \ingroup BoxModel
+ *
+ * \brief This class stores an array of VolumeVariables objects, one
+ *        volume variables object for each of the element's vertices
+ */
+template<class TypeTag>
+class BoxElementVolumeVariables : public std::vector<typename GET_PROP_TYPE(TypeTag, VolumeVariables) >
+{
+    typedef typename GET_PROP_TYPE(TypeTag, Problem) Problem;
+    typedef typename GET_PROP_TYPE(TypeTag, FVElementGeometry) FVElementGeometry;
+    typedef typename GET_PROP_TYPE(TypeTag, SolutionVector) SolutionVector;
+    typedef typename GET_PROP_TYPE(TypeTag, VertexMapper) VertexMapper;
+    typedef typename GET_PROP_TYPE(TypeTag, PrimaryVariables) PrimaryVariables;
+
+    typedef typename GET_PROP_TYPE(TypeTag, GridView) GridView;
+    typedef typename GridView::template Codim<0>::Entity Element;
+
+    enum { dim = GridView::dimension };
+    enum { numEq = GET_PROP_VALUE(TypeTag, NumEq) };
+
+public:
+    /*!
+     * \brief The constructor.
+     */
+    BoxElementVolumeVariables()
+    { }
+
+    /*!
+     * \brief Construct the volume variables for all of vertices of an element.
+     *
+     * \param problem The problem which needs to be simulated.
+     * \param element The DUNE Codim<0> entity for which the volume variables ought to be calculated
+     * \param fvGeometry The finite volume geometry of the element
+     * \param oldSol Tells whether the model's previous or current solution should be used.
+     */
+    void update(const Problem &problem,
+                const Element &element,
+                const FVElementGeometry &fvGeometry,
+                const bool oldSol)
+    {
+        const SolutionVector &globalSol =
+            oldSol?
+            problem.model().prevSol():
+            problem.model().curSol();
+        const VertexMapper &vertexMapper = problem.vertexMapper();
+        // we assert that the i-th shape function is
+        // associated to the i-th vert of the element.
+        int numVertices = element.template count<dim>();
+        this->resize(numVertices);
+        for (int scvIdx = 0; scvIdx < numVertices; scvIdx++) {
+            const PrimaryVariables &priVars
+                = globalSol[vertexMapper.map(element, scvIdx, dim)];
+
+            // reset evaluation point to zero
+            (*this)[scvIdx].setEvalPoint(0);
+
+            (*this)[scvIdx].update(priVars,
+                              problem,
+                              element,
+                              fvGeometry,
+                              scvIdx,
+                              oldSol);
+        }
+    }
+
+    /*!
+     * \brief Construct the volume variables for all of vertices of an
+     *        element given a solution vector computed by PDELab.
+     *
+     * \tparam ElementSolutionVector The container type which stores the
+     *                           primary variables of the element
+     *                           using _local_ indices
+     *
+     * \param problem The problem which needs to be simulated.
+     * \param element The DUNE Codim<0> entity for which the volume variables ought to be calculated
+     * \param fvGeometry The finite volume geometry of the element
+     * \param elementSolVector The local solution for the element using PDELab ordering
+     */
+    template<typename ElementSolutionVector>
+    void updatePDELab(const Problem &problem,
+                      const Element &element,
+                      const FVElementGeometry &fvGeometry,
+                      const ElementSolutionVector& elementSolVector)
+    {
+        int numVertices = element.template count<dim>();
+        this->resize(numVertices);
+        for (int scvIdx = 0; scvIdx < numVertices; scvIdx++)
+        {
+            PrimaryVariables priVars(0);
+            for (int eqnIdx = 0; eqnIdx < numEq; eqnIdx++)
+                priVars[eqnIdx] = elementSolVector[scvIdx + eqnIdx*numVertices];
+            (*this)[scvIdx].update(priVars,
+                                      problem,
+                                      element,
+                                      fvGeometry,
+                                      scvIdx,
+                                      false);
+
+        }
+    }
+};
+
+} // namespace Dumux
+
+#endif
diff --git a/dumux/implicit/box/boxforchheimerfluxvariables.hh b/dumux/implicit/box/boxforchheimerfluxvariables.hh
new file mode 100644
index 0000000000..e7f7e3bf32
--- /dev/null
+++ b/dumux/implicit/box/boxforchheimerfluxvariables.hh
@@ -0,0 +1,358 @@
+// -*- mode: C++; tab-width: 4; indent-tabs-mode: nil; c-basic-offset: 4 -*-
+// vi: set et ts=4 sw=4 sts=4:
+/*****************************************************************************
+ *   See the file COPYING for full copying permissions.                      *
+ *                                                                           *
+ *   This program is free software: you can redistribute it and/or modify    *
+ *   it under the terms of the GNU General Public License as published by    *
+ *   the Free Software Foundation, either version 2 of the License, or       *
+ *   (at your option) any later version.                                     *
+ *                                                                           *
+ *   This program is distributed in the hope that it will be useful,         *
+ *   but WITHOUT ANY WARRANTY; without even the implied warranty of          *
+ *   MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the            *
+ *   GNU General Public License for more details.                            *
+ *                                                                           *
+ *   You should have received a copy of the GNU General Public License       *
+ *   along with this program.  If not, see <http://www.gnu.org/licenses/>.   *
+ *****************************************************************************/
+/*!
+ * \file
+ *
+ * \brief This file contains the data which is required to calculate
+ *        all fluxes of fluid phases over a face of a finite volume,
+ *        according to the Forchheimer-relation between velocity and pressure.
+ *
+ */
+#ifndef DUMUX_BOX_FORCHHEIMER_FLUX_VARIABLES_HH
+#define DUMUX_BOX_FORCHHEIMER_FLUX_VARIABLES_HH
+
+#include "boxproperties.hh"
+
+#include <dumux/common/parameters.hh>
+#include <dumux/common/math.hh>
+#include <dumux/boxmodels/common/boxdarcyfluxvariables.hh>
+
+namespace Dumux
+{
+    
+namespace Properties
+{
+// forward declaration of properties 
+NEW_PROP_TAG(MobilityUpwindWeight);
+NEW_PROP_TAG(SpatialParams);
+NEW_PROP_TAG(NumPhases);
+NEW_PROP_TAG(ProblemEnableGravity);
+}   
+
+/*!
+ * \ingroup BoxModel
+ * \ingroup BoxFluxVariables
+ * \brief Evaluates the normal component of the Forchheimer velocity
+ *        on a (sub)control volume face.
+ *
+ *        The commonly used Darcy relation looses it's validity for \f$ Re < 1\f$.
+ *        If one encounters flow velocities in porous media above this Reynolds number,
+ *        the Forchheimer relation can be used. Like the Darcy relation, it relates
+ *        the gradient in potential to velocity.
+ *        However, this relation is not linear (as in the Darcy case) any more.
+ *
+ *        Therefore, a Newton scheme is implemented in this class in order to calculate a
+ *        velocity from the current set of variables. This velocity can subsequently be used
+ *        e.g. by the localresidual.
+ *
+ *        For Reynolds numbers above \f$ 500\f$ the (Standard) forchheimer relation also
+ *        looses it's validity.
+ *
+ *        The Forchheimer equation looks as follows:
+ *         \f[ \nabla \left({p_\alpha + \rho_\alpha g z} \right)=  - \frac{\mu_\alpha}{k_{r \alpha} K} \underline{v_\alpha} - \frac{c_F}{\eta_{\alpha r} \sqrt{K}} \rho_\alpha |\underline{v_\alpha}| \underline{v_\alpha} \f]
+ *
+ *        For the formulation that is actually used in this class, see the documentation of the function calculating the residual.
+ *
+ *        - This algorithm does not find a solution if the fluid is incompressible and the
+ *          initial pressure distribution is uniform.
+ *        - This algorithm assumes the relative passabilities to have the same functional
+ *          form as the relative permeabilities.
+ */
+template <class TypeTag>
+class BoxForchheimerFluxVariables
+    : public BoxDarcyFluxVariables<TypeTag>
+{
+    typedef typename GET_PROP_TYPE(TypeTag, Problem) Problem;
+    typedef typename GET_PROP_TYPE(TypeTag, SpatialParams) SpatialParams;
+    typedef typename GET_PROP_TYPE(TypeTag, ElementVolumeVariables) ElementVolumeVariables;
+    typedef typename GET_PROP_TYPE(TypeTag, VolumeVariables) VolumeVariables;
+    typedef typename GET_PROP_TYPE(TypeTag, GridView) GridView;
+    typedef typename GridView::template Codim<0>::Entity Element;
+
+    enum { dim = GridView::dimension} ;
+    enum { dimWorld = GridView::dimensionworld} ;
+    enum { numPhases = GET_PROP_VALUE(TypeTag, NumPhases)} ;
+
+    typedef typename GET_PROP_TYPE(TypeTag, Scalar) Scalar;
+    typedef Dune::FieldMatrix<Scalar, dimWorld, dimWorld> Tensor;
+    typedef Dune::FieldVector<Scalar, dimWorld> DimVector;
+    typedef typename GET_PROP_TYPE(TypeTag, FVElementGeometry) FVElementGeometry;
+    typedef typename FVElementGeometry::SubControlVolumeFace SCVFace;
+
+public:
+    /*!
+     * \brief The constructor
+     *
+     * \param problem The problem
+     * \param element The finite element
+     * \param fvGeometry The finite-volume geometry in the box scheme
+     * \param faceIdx The local index of the SCV (sub-control-volume) face
+     * \param elemVolVars The volume variables of the current element
+     * \param onBoundary A boolean variable to specify whether the flux variables
+     * are calculated for interior SCV faces or boundary faces, default=false
+     */
+    BoxForchheimerFluxVariables(const Problem &problem,
+                 const Element &element,
+                 const FVElementGeometry &fvGeometry,
+                 const unsigned int faceIdx,
+                 const ElementVolumeVariables &elemVolVars,
+                 const bool onBoundary = false)
+        :   BoxDarcyFluxVariables<TypeTag>(problem, element, fvGeometry, faceIdx, elemVolVars, onBoundary)
+    {
+        calculateNormalVelocity_(problem, element, elemVolVars);
+    }
+
+protected:
+    /*!
+     * \brief Function for calculation of velocities.
+     *
+     * \param problem The problem
+     * \param element The finite element
+     * \param elemVolVars The volume variables of the current element
+     */
+    void calculateNormalVelocity_(const Problem &problem,
+                                  const Element &element,
+                                  const ElementVolumeVariables &elemVolVars)
+    {
+        // calculate the mean intrinsic permeability
+        const SpatialParams &spatialParams = problem.spatialParams();
+        Tensor K;
+        spatialParams.meanK(K,
+                            spatialParams.intrinsicPermeability(element,
+                                                                this->fvGeometry_,
+                                                                this->face().i),
+                            spatialParams.intrinsicPermeability(element,
+                                                                this->fvGeometry_,
+                                                                this->face().j));
+
+        // obtain the Forchheimer coefficient from the spatial parameters
+        const Scalar forchCoeff = spatialParams.forchCoeff(element,
+                                                          this->fvGeometry_,
+                                                          this->face().i);
+
+        // Make sure the permeability matrix does not have off-diagonal entries
+        assert( isDiagonal_(K) );
+
+        Tensor sqrtK(0.0);
+        for (int i = 0; i < dim; ++i)
+            sqrtK[i][i] = std::sqrt(K[i][i]);
+
+        // loop over all phases
+        for (int phaseIdx = 0; phaseIdx < numPhases; phaseIdx++)
+        {
+            // initial guess of velocity: Darcy relation
+            // first taken from base class, later overwritten in base class
+            DimVector velocity = this-> velocity(phaseIdx);
+
+            DimVector deltaV;           // the change in velocity between Newton iterations
+            DimVector residual(10e10);  // the residual (function value that is to be minimized ) of the equation that is to be fulfilled
+            DimVector tmp;              // temporary variable for numerical differentiation
+            Tensor    gradF;            // slope of equation that is to be solved
+
+            // search by means of the Newton method for a root of Forchheimer equation
+            for (int k = 0; residual.two_norm() > 1e-12 ; ++k) {
+
+                if (k >= 30)
+                    DUNE_THROW(NumericalProblem, "could not determine forchheimer velocity within "<< k <<" iterations");
+
+                // calculate current value of Forchheimer equation
+                forchheimerResidual_(residual,
+                                    forchCoeff,
+                                    sqrtK,
+                                    K,
+                                    velocity,
+                                    elemVolVars,
+                                    this->gradPotential_[phaseIdx],
+                                    phaseIdx);
+
+                // newton's method: slope (gradF) and current value (residual) of function is known,
+                forchheimerDerivative_(gradF,
+                                       forchCoeff,
+                                       sqrtK,
+                                       velocity,
+                                       elemVolVars,
+                                       phaseIdx);
+
+                // solve for change in velocity ("x-Axis intercept")
+                gradF.solve(deltaV, residual);
+                velocity -= deltaV;
+            }
+
+            this->velocity_[phaseIdx]     =  velocity ;                  // store the converged velocity solution
+            this->volumeFlux_[phaseIdx]   =  velocity * this->face().normal; // velocity dot normal times cross sectional area is volume flux
+        }// end loop over all phases
+    }
+
+    /*! \brief Function for calculation of Forchheimer relation.
+     *
+     *  The relative passability \f$ \eta_r\f$ is the "Forchheimer-equivalent" to the relative permeability \f$ k_r\f$.
+     *  We use the same function as for \f$ k_r \f$ (VG, BC, linear) other authors use a simple power law e.g.: \f$\eta_{rw} = S_w^3\f$
+     *
+     *  Some rearrangements have been made to the original Forchheimer relation:
+     *
+     * \f[  \underline{v_\alpha} + c_F \sqrt{K} \frac{\rho_\alpha}{\mu_\alpha } |\underline{v_\alpha}| \underline{v_\alpha} + \frac{k_{r \alpha}}{\mu_\alpha} K \nabla \left(p_\alpha + \rho_\alpha g z \right)=  0 \f]
+     *
+     * This already includes the assumption \f$ k_r(S_w) = \eta_r(S_w)\f$:
+     * - \f$\eta_{rw} = S_w^x\f$ looks very similar to e.g. Van Genuchten relative permeabilities
+     * - Fichot, et al. (2006), Nuclear Engineering and Design, state that several authors claim that \f$ k_r(S_w), \eta_r(S_w)\f$ can be chosen equal
+     * - It leads to the equation not degenerating for the case of \f$S_w=1\f$, because I do not need to multiply with two different functions, and therefore there are terms not being zero.
+     * - If this assumption is not to be made: Some regularization needs to be introduced ensuring that not all terms become zero for \f$S_w=1\f$.
+     *
+     *  As long as the correct velocity is not found yet, the above equation is not fulfilled, but
+     *  the left hand side yields some residual. This function calculates the left hand side of the
+     *  equation and returns the residual.
+     *
+     * \param residual The current function value for the given velocity
+     * \param forchCoeff The Forchheimer coefficient
+     * \param sqrtK A diagonal matrix whose entries are square roots of the permeability matrix entries
+     * \param K The permeability matrix
+     * \param velocity The current velocity approximation.
+     * \param elemVolVars The volume variables of the current element
+     * \param gradPotential The gradient in potential
+     * \param phaseIdx The index of the currently considered phase
+     */
+     void forchheimerResidual_(DimVector & residual,
+         const Scalar forchCoeff,
+         const Tensor & sqrtK,
+         const Tensor & K,
+         const DimVector & velocity,
+         const ElementVolumeVariables & elemVolVars,
+         const DimVector & gradPotential ,
+         const unsigned int phaseIdx) const
+     {
+         const VolumeVariables upVolVars    = elemVolVars[this->upstreamIdx(phaseIdx)];
+         const VolumeVariables downVolVars  = elemVolVars[this->downstreamIdx(phaseIdx)];
+
+         // Obtaining the physical quantities
+         const Scalar mobility = this->mobilityUpwindWeight_ * upVolVars.mobility(phaseIdx)
+                 + (1.-this->mobilityUpwindWeight_)*  downVolVars.mobility(phaseIdx) ;
+
+         const Scalar viscosity = this->mobilityUpwindWeight_ * upVolVars.fluidState().viscosity(phaseIdx)
+                 + (1.-this->mobilityUpwindWeight_)*  downVolVars.fluidState().viscosity(phaseIdx) ;
+
+         const Scalar density = this->mobilityUpwindWeight_ * upVolVars.fluidState().density(phaseIdx)
+                 + (1.-this->mobilityUpwindWeight_) * downVolVars.fluidState().density(phaseIdx) ;
+
+         // residual  = v
+         residual = velocity;
+
+         // residual += k_r/mu  K grad p
+         K.usmv(mobility, gradPotential, residual);
+
+         // residual += c_F rho / mu abs(v) sqrt(K) v
+         sqrtK.usmv(forchCoeff * density / viscosity * velocity.two_norm(), velocity, residual);
+     }
+
+
+     /*! \brief Function for calculation of the gradient of Forchheimer relation with respect to velocity.
+      *
+      *  This function already exploits that \f$ \sqrt{K}\f$ is a diagonal matrix. Therefore, we only have
+      *  to deal with the main entries.
+      *  The gradient of the Forchheimer relations looks as follows (mind that \f$ \sqrt{K}\f$ is a tensor):
+      *
+      * \f[  f\left(\underline{v_\alpha}\right) =
+      * \left(
+      * \begin{array}{ccc}
+      * 1 & 0 &0 \\
+      * 0 & 1 &0 \\
+      * 0 & 0 &1 \\
+      * \end{array}
+      * \right)
+      * +
+      * c_F \frac{\rho_\alpha}{\mu_\alpha} |\underline{v}_\alpha| \sqrt{K}
+      * +
+      * c_F \frac{\rho_\alpha}{\mu_\alpha}\frac{1}{|\underline{v}_\alpha|} \sqrt{K}
+      * \left(
+      * \begin{array}{ccc}
+      * v_x^2 & v_xv_y & v_xv_z \\
+      * v_yv_x & v_{y}^2 & v_yv_z \\
+      * v_zv_x & v_zv_y &v_{z}^2 \\
+      * \end{array}
+      * \right)
+      *  \f]
+      *
+      * \param derivative The gradient of the forchheimer equation
+      * \param forchCoeff Forchheimer coefficient
+      * \param sqrtK A diagonal matrix whose entries are square roots of the permeability matrix entries.
+      * \param velocity The current velocity approximation.
+      * \param elemVolVars The volume variables of the current element
+      * \param phaseIdx The index of the currently considered phase
+      */
+     void forchheimerDerivative_(Tensor & derivative,
+             const Scalar forchCoeff,
+             const Tensor & sqrtK,
+             const DimVector & velocity,
+             const ElementVolumeVariables & elemVolVars,
+             const unsigned int phaseIdx) const
+     {
+         const VolumeVariables upVolVars    = elemVolVars[this->upstreamIdx(phaseIdx)];
+         const VolumeVariables downVolVars  = elemVolVars[this->downstreamIdx(phaseIdx)];
+
+         // Obtaining the physical quantities
+         const Scalar viscosity = this->mobilityUpwindWeight_ * upVolVars.fluidState().viscosity(phaseIdx)
+                 + (1.-this->mobilityUpwindWeight_)*  downVolVars.fluidState().viscosity(phaseIdx) ;
+
+         const Scalar density = this->mobilityUpwindWeight_ * upVolVars.fluidState().density(phaseIdx)
+                 + (1.-this->mobilityUpwindWeight_) * downVolVars.fluidState().density(phaseIdx) ;
+
+         // Initialize because for low velocities, we add and do not set the entries.
+         derivative = 0.;
+
+         const Scalar absV = velocity.two_norm() ;
+         // This part of the derivative is only calculated if the velocity is sufficiently small: do not divide by zero!
+         // This should not be very bad because the derivative is only intended to give an approximation of the gradient of the
+         // function that goes into the Newton scheme.
+         // This is important in the case of a one-phase region in two-phase flow. The non-existing phase has a velocity of zero (kr=0).
+         // f = sqrtK * vTimesV (this is  a matrix)
+         // f *= forchCoeff density / |velocity| / viscosity (multiply all entries with scalars)
+         if(absV > 1e-20)
+             for (int i=0; i<dim; i++)
+                 for (int k=0; k<dim; k++)
+                     derivative[i][k]= sqrtK[i][i] * velocity[i] * velocity[k] * forchCoeff * density /  absV  / viscosity;
+
+         // add on the main diagonal:
+         // 1 + sqrtK_i forchCoeff density |v| / viscosity
+         for (int i=0; i<dim; i++)
+             derivative[i][i] += (1.0 + ( sqrtK[i][i]*forchCoeff * density * absV / viscosity ) ) ;
+     }
+
+     /*!
+      * \brief Check whether all off-diagonal entries of a tensor are zero.
+      *
+      * \param K the tensor that is to be checked.
+      *
+      * \return True iff all off-diagonals are zero.
+      *
+     */
+     const bool isDiagonal_(const Tensor & K) const
+     {
+         for (int i = 0; i < dim; i++) {
+             for (int k = 0; k < dim; k++) {
+                 if ((i != k) && (std::abs(K[i][k]) >= 1e-25)) {
+                   return false;
+                 }
+             }
+         }
+         return true;
+     }
+};
+
+} // end namespace
+
+#endif
diff --git a/dumux/implicit/box/boxfvelementgeometry.hh b/dumux/implicit/box/boxfvelementgeometry.hh
new file mode 100644
index 0000000000..fd0b5c89e2
--- /dev/null
+++ b/dumux/implicit/box/boxfvelementgeometry.hh
@@ -0,0 +1,933 @@
+// -*- mode: C++; tab-width: 4; indent-tabs-mode: nil; c-basic-offset: 4 -*-
+// vi: set et ts=4 sw=4 sts=4:
+/*****************************************************************************
+ *   See the file COPYING for full copying permissions.                      *
+ *                                                                           *
+ *   This program is free software: you can redistribute it and/or modify    *
+ *   it under the terms of the GNU General Public License as published by    *
+ *   the Free Software Foundation, either version 2 of the License, or       *
+ *   (at your option) any later version.                                     *
+ *                                                                           *
+ *   This program is distributed in the hope that it will be useful,         *
+ *   but WITHOUT ANY WARRANTY; without even the implied warranty of          *
+ *   MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the            *
+ *   GNU General Public License for more details.                            *
+ *                                                                           *
+ *   You should have received a copy of the GNU General Public License       *
+ *   along with this program.  If not, see <http://www.gnu.org/licenses/>.   *
+ *****************************************************************************/
+/*!
+ * \file
+ *
+ * \brief Represents the finite volume geometry of a single element in
+ *        the box scheme.
+ */
+#ifndef DUMUX_BOX_FV_ELEMENTGEOMETRY_HH
+#define DUMUX_BOX_FV_ELEMENTGEOMETRY_HH
+
+#include <dune/common/version.hh>
+#include <dune/geometry/referenceelements.hh>
+#include <dune/grid/common/intersectioniterator.hh>
+#include <dune/localfunctions/lagrange/pqkfactory.hh>
+
+#include <dumux/common/parameters.hh>
+#include <dumux/common/propertysystem.hh>
+#include "boxproperties.hh"
+
+namespace Dumux
+{
+namespace Properties
+{
+NEW_PROP_TAG(GridView);
+NEW_PROP_TAG(Scalar);
+NEW_PROP_TAG(ImplicitUseTwoPointFlux);
+}
+
+/////////////////////
+// HACK: Functions to initialize the subcontrol volume data
+// structures of BoxFVElementGeomerty.
+//
+// this is a work around to be able to to use specialization for
+// doing this.  it is required since it is not possible to
+// specialize member functions of template classes because of some
+// weird reason I didn't really get...
+
+//! \cond INTERNAL
+
+template <typename BoxFVElementGeometry, int dim>
+class _BoxFVElemGeomHelper
+{
+public:
+    static void fillSubContVolData(BoxFVElementGeometry &eg, int numVertices)
+    {
+        DUNE_THROW(Dune::NotImplemented, "_BoxFVElemGeomHelper::fillSubContVolData dim = " << dim);
+    }
+};
+
+template <typename BoxFVElementGeometry>
+class _BoxFVElemGeomHelper<BoxFVElementGeometry, 1>
+{
+public:
+    enum { dim = 1 };
+    static void fillSubContVolData(BoxFVElementGeometry &eg, int numVertices)
+    {
+        // 1D
+        eg.subContVol[0].volume = 0.5*eg.elementVolume;
+        eg.subContVol[1].volume = 0.5*eg.elementVolume;
+    }
+};
+
+template <typename BoxFVElementGeometry>
+class _BoxFVElemGeomHelper<BoxFVElementGeometry, 2>
+{
+public:
+    enum { dim = 2 };
+
+    static void fillSubContVolData(BoxFVElementGeometry &eg, int numVertices)
+    {
+        switch (numVertices) {
+        case 3: // 2D, triangle
+            eg.subContVol[0].volume = eg.elementVolume/3;
+            eg.subContVol[1].volume = eg.elementVolume/3;
+            eg.subContVol[2].volume = eg.elementVolume/3;
+            break;
+        case 4: // 2D, quadrilinear
+            eg.subContVol[0].volume = eg.quadrilateralArea(eg.subContVol[0].global, eg.edgeCoord[2], eg.elementGlobal, eg.edgeCoord[0]);
+            eg.subContVol[1].volume = eg.quadrilateralArea(eg.subContVol[1].global, eg.edgeCoord[1], eg.elementGlobal, eg.edgeCoord[2]);
+            eg.subContVol[2].volume = eg.quadrilateralArea(eg.subContVol[2].global, eg.edgeCoord[0], eg.elementGlobal, eg.edgeCoord[3]);
+            eg.subContVol[3].volume = eg.quadrilateralArea(eg.subContVol[3].global, eg.edgeCoord[3], eg.elementGlobal, eg.edgeCoord[1]);
+            break;
+        default:
+            DUNE_THROW(Dune::NotImplemented, "_BoxFVElemGeomHelper::fillSubContVolData dim = " << dim << ", numVertices = " << numVertices);
+        }
+    }
+};
+
+template <typename BoxFVElementGeometry>
+class _BoxFVElemGeomHelper<BoxFVElementGeometry, 3>
+{
+public:
+    enum { dim = 3 };
+
+    static void fillSubContVolData(BoxFVElementGeometry &eg, int numVertices)
+    {
+        switch (numVertices) {
+        case 4: // 3D, tetrahedron
+            for (int k = 0; k < eg.numVertices; k++)
+                eg.subContVol[k].volume = eg.elementVolume / 4.0;
+            break;
+        case 5: // 3D, pyramid
+            eg.subContVol[0].volume = eg.hexahedronVolume(eg.subContVol[0].global,
+                                                          eg.edgeCoord[2],
+                                                          eg.faceCoord[0],
+                                                          eg.edgeCoord[0],
+                                                          eg.edgeCoord[4],
+                                                          eg.faceCoord[3],
+                                                          eg.elementGlobal,
+                                                          eg.faceCoord[1]);
+            eg.subContVol[1].volume = eg.hexahedronVolume(eg.subContVol[1].global,
+                                                          eg.edgeCoord[1],
+                                                          eg.faceCoord[0],
+                                                          eg.edgeCoord[2],
+                                                          eg.edgeCoord[5],
+                                                          eg.faceCoord[2],
+                                                          eg.elementGlobal,
+                                                          eg.faceCoord[3]);
+            eg.subContVol[2].volume = eg.hexahedronVolume(eg.subContVol[2].global,
+                                                          eg.edgeCoord[0],
+                                                          eg.faceCoord[0],
+                                                          eg.edgeCoord[3],
+                                                          eg.edgeCoord[6],
+                                                          eg.faceCoord[1],
+                                                          eg.elementGlobal,
+                                                          eg.faceCoord[4]);
+            eg.subContVol[3].volume = eg.hexahedronVolume(eg.subContVol[3].global,
+                                                          eg.edgeCoord[3],
+                                                          eg.faceCoord[0],
+                                                          eg.edgeCoord[1],
+                                                          eg.edgeCoord[7],
+                                                          eg.faceCoord[4],
+                                                          eg.elementGlobal,
+                                                          eg.faceCoord[2]);
+            eg.subContVol[4].volume = eg.elementVolume -
+                eg.subContVol[0].volume -
+                eg.subContVol[1].volume -
+                eg.subContVol[2].volume -
+                eg.subContVol[3].volume;
+            break;
+        case 6: // 3D, prism
+            eg.subContVol[0].volume = eg.hexahedronVolume(eg.subContVol[0].global,
+                                                          eg.edgeCoord[3],
+                                                          eg.faceCoord[3],
+                                                          eg.edgeCoord[4],
+                                                          eg.edgeCoord[0],
+                                                          eg.faceCoord[0],
+                                                          eg.elementGlobal,
+                                                          eg.faceCoord[1]);
+            eg.subContVol[1].volume = eg.hexahedronVolume(eg.subContVol[1].global,
+                                                          eg.edgeCoord[5],
+                                                          eg.faceCoord[3],
+                                                          eg.edgeCoord[3],
+                                                          eg.edgeCoord[1],
+                                                          eg.faceCoord[2],
+                                                          eg.elementGlobal,
+                                                          eg.faceCoord[0]);
+            eg.subContVol[2].volume = eg.hexahedronVolume(eg.subContVol[2].global,
+                                                          eg.edgeCoord[4],
+                                                          eg.faceCoord[3],
+                                                          eg.edgeCoord[5],
+                                                          eg.edgeCoord[2],
+                                                          eg.faceCoord[1],
+                                                          eg.elementGlobal,
+                                                          eg.faceCoord[2]);
+            eg.subContVol[3].volume = eg.hexahedronVolume(eg.edgeCoord[0],
+                                                          eg.faceCoord[0],
+                                                          eg.elementGlobal,
+                                                          eg.faceCoord[1],
+                                                          eg.subContVol[3].global,
+                                                          eg.edgeCoord[6],
+                                                          eg.faceCoord[4],
+                                                          eg.edgeCoord[7]);
+            eg.subContVol[4].volume = eg.hexahedronVolume(eg.edgeCoord[1],
+                                                          eg.faceCoord[2],
+                                                          eg.elementGlobal,
+                                                          eg.faceCoord[0],
+                                                          eg.subContVol[4].global,
+                                                          eg.edgeCoord[8],
+                                                          eg.faceCoord[4],
+                                                          eg.edgeCoord[6]);
+            eg.subContVol[5].volume = eg.hexahedronVolume(eg.edgeCoord[2],
+                                                          eg.faceCoord[1],
+                                                          eg.elementGlobal,
+                                                          eg.faceCoord[2],
+                                                          eg.subContVol[5].global,
+                                                          eg.edgeCoord[7],
+                                                          eg.faceCoord[4],
+                                                          eg.edgeCoord[8]);
+            break;
+        case 8: // 3D, hexahedron
+            eg.subContVol[0].volume = eg.hexahedronVolume(eg.subContVol[0].global,
+                                                          eg.edgeCoord[6],
+                                                          eg.faceCoord[4],
+                                                          eg.edgeCoord[4],
+                                                          eg.edgeCoord[0],
+                                                          eg.faceCoord[2],
+                                                          eg.elementGlobal,
+                                                          eg.faceCoord[0]);
+            eg.subContVol[1].volume = eg.hexahedronVolume(eg.subContVol[1].global,
+                                                          eg.edgeCoord[5],
+                                                          eg.faceCoord[4],
+                                                          eg.edgeCoord[6],
+                                                          eg.edgeCoord[1],
+                                                          eg.faceCoord[1],
+                                                          eg.elementGlobal,
+                                                          eg.faceCoord[2]);
+            eg.subContVol[2].volume = eg.hexahedronVolume(eg.subContVol[2].global,
+                                                          eg.edgeCoord[4],
+                                                          eg.faceCoord[4],
+                                                          eg.edgeCoord[7],
+                                                          eg.edgeCoord[2],
+                                                          eg.faceCoord[0],
+                                                          eg.elementGlobal,
+                                                          eg.faceCoord[3]);
+            eg.subContVol[3].volume = eg.hexahedronVolume(eg.subContVol[3].global,
+                                                          eg.edgeCoord[7],
+                                                          eg.faceCoord[4],
+                                                          eg.edgeCoord[5],
+                                                          eg.edgeCoord[3],
+                                                          eg.faceCoord[3],
+                                                          eg.elementGlobal,
+                                                          eg.faceCoord[1]);
+            eg.subContVol[4].volume = eg.hexahedronVolume(eg.edgeCoord[0],
+                                                          eg.faceCoord[2],
+                                                          eg.elementGlobal,
+                                                          eg.faceCoord[0],
+                                                          eg.subContVol[4].global,
+                                                          eg.edgeCoord[10],
+                                                          eg.faceCoord[5],
+                                                          eg.edgeCoord[8]);
+            eg.subContVol[5].volume = eg.hexahedronVolume(eg.edgeCoord[1],
+                                                          eg.faceCoord[1],
+                                                          eg.elementGlobal,
+                                                          eg.faceCoord[2],
+                                                          eg.subContVol[5].global,
+                                                          eg.edgeCoord[9],
+                                                          eg.faceCoord[5],
+                                                          eg.edgeCoord[10]);
+            eg.subContVol[6].volume = eg.hexahedronVolume(eg.edgeCoord[2],
+                                                          eg.faceCoord[0],
+                                                          eg.elementGlobal,
+                                                          eg.faceCoord[3],
+                                                          eg.subContVol[6].global,
+                                                          eg.edgeCoord[8],
+                                                          eg.faceCoord[5],
+                                                          eg.edgeCoord[11]);
+            eg.subContVol[7].volume = eg.hexahedronVolume(eg.edgeCoord[3],
+                                                          eg.faceCoord[3],
+                                                          eg.elementGlobal,
+                                                          eg.faceCoord[1],
+                                                          eg.subContVol[7].global,
+                                                          eg.edgeCoord[11],
+                                                          eg.faceCoord[5],
+                                                          eg.edgeCoord[9]);
+            break;
+        default:
+            DUNE_THROW(Dune::NotImplemented, "_BoxFVElemGeomHelper::fillSubContVolData dim = " << dim << ", numVertices = " << numVertices);
+        }
+    }
+};
+
+//! \endcond
+
+// END HACK
+/////////////////////
+
+/*!
+ * \brief Represents the finite volume geometry of a single element in
+ *        the box scheme.
+ *
+ * The box scheme is a vertex centered finite volume approach. This
+ * means that each vertex corrosponds to a control volume which
+ * intersects each of the vertex' neighboring elements. If only
+ * looking at a single element of the primary grid (which is what this
+ * class does), the element is subdivided into multiple fragments of
+ * control volumes called sub-control volumes. Each of the element's
+ * vertices corrosponds to exactly one sub-control volume in this
+ * scenario.
+ *
+ * For the box methods the sub-control volumes are constructed by
+ * connecting the element's center with each edge of the element.
+ */
+template<class TypeTag>
+class BoxFVElementGeometry
+{
+    typedef typename GET_PROP_TYPE(TypeTag, GridView) GridView;
+    enum{dim = GridView::dimension};
+    enum{dimWorld = GridView::dimensionworld};
+
+    typedef BoxFVElementGeometry<TypeTag>   ThisType;
+
+    /** \todo Please doc me! */
+    friend class _BoxFVElemGeomHelper<ThisType, dim>;
+
+    typedef _BoxFVElemGeomHelper<ThisType, dim> BoxFVElemGeomHelper;
+
+    enum{maxNC = (dim < 3 ? 4 : 8)};
+    enum{maxNE = (dim < 3 ? 4 : 12)};
+    enum{maxNF = (dim < 3 ? 1 : 6)};
+    enum{maxCOS = (dim < 3 ? 2 : 4)};
+    enum{maxBF = (dim < 3 ? 8 : 24)};
+    enum{maxNFAP = (dim < 3 ? 4 : 8)};
+    typedef typename GET_PROP_TYPE(TypeTag, Scalar) Scalar;
+    typedef typename GridView::ctype CoordScalar;
+    typedef typename GridView::Traits::template Codim<0>::Entity Element;
+    typedef typename Element::Geometry Geometry;
+    typedef Dune::FieldVector<Scalar,dimWorld> Vector;
+    typedef Dune::FieldVector<CoordScalar,dimWorld> GlobalPosition;
+    typedef Dune::FieldVector<CoordScalar,dim> LocalPosition;
+    typedef typename GridView::IntersectionIterator IntersectionIterator;
+#if DUNE_VERSION_NEWER_REV(DUNE_GRID, 2, 3, 0)
+    typedef typename Geometry::JacobianInverseTransposed JacobianInverseTransposed;
+#else
+    typedef typename Geometry::Jacobian JacobianInverseTransposed;    
+#endif
+
+    typedef Dune::PQkLocalFiniteElementCache<CoordScalar, Scalar, dim, 1> LocalFiniteElementCache;
+    typedef typename LocalFiniteElementCache::FiniteElementType LocalFiniteElement;
+    typedef typename LocalFiniteElement::Traits::LocalBasisType::Traits LocalBasisTraits;
+    typedef typename LocalBasisTraits::JacobianType ShapeJacobian;
+
+    Scalar quadrilateralArea(const GlobalPosition& p0, const GlobalPosition& p1, const GlobalPosition& p2, const GlobalPosition& p3)
+    {
+        return 0.5*fabs((p3[0] - p1[0])*(p2[1] - p0[1]) - (p3[1] - p1[1])*(p2[0] - p0[0]));
+    }
+
+    void crossProduct(Vector& c, const Vector& a, const Vector& b)
+    {
+        c[0] = a[1]*b[2] - a[2]*b[1];
+        c[1] = a[2]*b[0] - a[0]*b[2];
+        c[2] = a[0]*b[1] - a[1]*b[0];
+    }
+
+    Scalar pyramidVolume (const GlobalPosition& p0, const GlobalPosition& p1, const GlobalPosition& p2, const GlobalPosition& p3, const GlobalPosition& p4)
+    {
+        Vector a(p2); a -= p0;
+        Vector b(p3); b -= p1;
+
+        Vector n;
+        crossProduct(n, a, b);
+
+        a = p4; a -= p0;
+
+        return 1.0/6.0*(n*a);
+    }
+
+    Scalar prismVolume (const GlobalPosition& p0, const GlobalPosition& p1, const GlobalPosition& p2, const GlobalPosition& p3, const GlobalPosition& p4, const GlobalPosition& p5)
+    {
+        Vector a(p4);
+        for (int k = 0; k < dimWorld; ++k)
+            a[k] -= p0[k];
+        Vector b(p1);
+        for (int k = 0; k < dimWorld; ++k)
+            b[k] -= p3[k];
+        Vector m;
+        crossProduct(m, a, b);
+
+        a = p1;
+        for (int k = 0; k < dimWorld; ++k)
+            a[k] -= p0[k];
+        b = p2;
+        for (int k = 0; k < dimWorld; ++k)
+            b[k] -= p0[k];
+        Vector n;
+        crossProduct(n, a, b);
+        n += m;
+
+        a = p5;
+        for (int k = 0; k < dimWorld; ++k)
+            a[k] -= p0[k];
+
+        return fabs(1.0/6.0*(n*a));
+    }
+
+    Scalar hexahedronVolume (const GlobalPosition& p0, const GlobalPosition& p1, const GlobalPosition& p2, const GlobalPosition& p3,
+                             const GlobalPosition& p4, const GlobalPosition& p5, const GlobalPosition& p6, const GlobalPosition& p7)
+    {
+        return
+            prismVolume(p0,p1,p2,p4,p5,p6)
+            + prismVolume(p0,p2,p3,p4,p6,p7);
+    }
+
+    void normalOfQuadrilateral3D(Vector &normal, const GlobalPosition& p0, const GlobalPosition& p1, const GlobalPosition& p2, const GlobalPosition& p3)
+    {
+        Vector a(p2);
+        for (int k = 0; k < dimWorld; ++k)
+            a[k] -= p0[k];
+        Vector b(p3);
+        for (int k = 0; k < dimWorld; ++k)
+            b[k] -= p1[k];
+
+        crossProduct(normal, a, b);
+        normal *= 0.5;
+    }
+
+    Scalar quadrilateralArea3D(const GlobalPosition& p0, const GlobalPosition& p1, const GlobalPosition& p2, const GlobalPosition& p3)
+    {
+        Vector normal;
+        normalOfQuadrilateral3D(normal, p0, p1, p2, p3);
+        return normal.two_norm();
+    }
+
+    void getFaceIndices(int numVertices, int k, int& leftFace, int& rightFace)
+    {
+        static const int edgeToFaceTet[2][6] = {
+            {1, 0, 3, 2, 1, 3},
+            {0, 2, 0, 1, 3, 2}
+        };
+        static const int edgeToFacePyramid[2][8] = {
+            {1, 2, 3, 4, 1, 3, 4, 2},
+            {0, 0, 0, 0, 3, 2, 1, 4}
+        };
+        static const int edgeToFacePrism[2][9] = {
+            {1, 0, 2, 0, 1, 2, 4, 4, 4},
+            {0, 2, 1, 3, 3, 3, 0, 1, 2}
+        };
+        static const int edgeToFaceHex[2][12] = {
+            {0, 2, 3, 1, 4, 1, 2, 4, 0, 5, 5, 3},
+            {2, 1, 0, 3, 0, 4, 4, 3, 5, 1, 2, 5}
+        };
+
+        switch (numVertices) {
+        case 4:
+            leftFace = edgeToFaceTet[0][k];
+            rightFace = edgeToFaceTet[1][k];
+            break;
+        case 5:
+            leftFace = edgeToFacePyramid[0][k];
+            rightFace = edgeToFacePyramid[1][k];
+            break;
+        case 6:
+            leftFace = edgeToFacePrism[0][k];
+            rightFace = edgeToFacePrism[1][k];
+            break;
+        case 8:
+            leftFace = edgeToFaceHex[0][k];
+            rightFace = edgeToFaceHex[1][k];
+            break;
+        default:
+            DUNE_THROW(Dune::NotImplemented, "BoxFVElementGeometry :: getFaceIndices for numVertices = " << numVertices);
+            break;
+        }
+    }
+
+    void getEdgeIndices(int numVertices, int face, int vert, int& leftEdge, int& rightEdge)
+    {
+        static const int faceAndVertexToLeftEdgeTet[4][4] = {
+            { 0, 0, 2, -1},
+            { 0, 0, -1, 3},
+            { 1, -1, 1, 3},
+            {-1, 2, 2, 4}
+        };
+        static const int faceAndVertexToRightEdgeTet[4][4] = {
+            { 1, 2, 1, -1},
+            { 3, 4, -1, 4},
+            { 3, -1, 5, 5},
+            {-1, 4, 5, 5}
+        };
+        static const int faceAndVertexToLeftEdgePyramid[5][5] = {
+            { 0, 2, 3, 1, -1},
+            { 0, -1, 0, -1, 4},
+            {-1, 1, -1, 1, 5},
+            { 2, 2, -1, -1, 4},
+            {-1, -1, 3, 3, 7}
+        };
+        static const int faceAndVertexToRightEdgePyramid[5][5] = {
+            { 2, 1, 0, 3, -1},
+            { 4, -1, 6, -1, 6},
+            {-1, 5, -1, 7, 7},
+            { 4, 5, -1, -1, 5},
+            {-1, -1, 6, 7, 6}
+        };
+        static const int faceAndVertexToLeftEdgePrism[5][6] = {
+            { 3, 3, -1, 0, 1, -1},
+            { 4, -1, 4, 0, -1, 2},
+            {-1, 5, 5, -1, 1, 2},
+            { 3, 3, 5, -1, -1, -1},
+            {-1, -1, -1, 6, 6, 8}
+        };
+        static const int faceAndVertexToRightEdgePrism[5][6] = {
+            { 0, 1, -1, 6, 6, -1},
+            { 0, -1, 2, 7, -1, 7},
+            {-1, 1, 2, -1, 8, 8},
+            { 4, 5, 4, -1, -1, -1},
+            {-1, -1, -1, 7, 8, 7}
+        };
+        static const int faceAndVertexToLeftEdgeHex[6][8] = {
+            { 0, -1, 4, -1, 8, -1, 2, -1},
+            {-1, 5, -1, 3, -1, 1, -1, 9},
+            { 6, 1, -1, -1, 0, 10, -1, -1},
+            {-1, -1, 2, 7, -1, -1, 11, 3},
+            { 4, 6, 7, 5, -1, -1, -1, -1},
+            {-1, -1, -1, -1, 10, 9, 8, 11}
+        };
+        static const int faceAndVertexToRightEdgeHex[6][8] = {
+            { 4, -1, 2, -1, 0, -1, 8, -1},
+            {-1, 1, -1, 5, -1, 9, -1, 3},
+            { 0, 6, -1, -1, 10, 1, -1, -1},
+            {-1, -1, 7, 3, -1, -1, 2, 11},
+            { 6, 5, 4, 7, -1, -1, -1, -1},
+            {-1, -1, -1, -1, 8, 10, 11, 9}
+        };
+
+        switch (numVertices) {
+        case 4:
+            leftEdge = faceAndVertexToLeftEdgeTet[face][vert];
+            rightEdge = faceAndVertexToRightEdgeTet[face][vert];
+            break;
+        case 5:
+            leftEdge = faceAndVertexToLeftEdgePyramid[face][vert];
+            rightEdge = faceAndVertexToRightEdgePyramid[face][vert];
+            break;
+        case 6:
+            leftEdge = faceAndVertexToLeftEdgePrism[face][vert];
+            rightEdge = faceAndVertexToRightEdgePrism[face][vert];
+            break;
+        case 8:
+            leftEdge = faceAndVertexToLeftEdgeHex[face][vert];
+            rightEdge = faceAndVertexToRightEdgeHex[face][vert];
+            break;
+        default:
+            DUNE_THROW(Dune::NotImplemented, "BoxFVElementGeometry :: getFaceIndices for numVertices = " << numVertices);
+            break;
+        }
+    }
+
+public:
+    int boundaryFaceIndex(const int face, const int vertInFace) const
+    {
+        return (face*maxCOS + vertInFace);
+    }
+
+    struct SubControlVolume //! FV intersected with element
+    {
+        LocalPosition local; //!< local vert position
+        GlobalPosition global; //!< global vert position
+        LocalPosition localCenter; //!< local position of scv center
+        Scalar volume; //!< volume of scv
+        Dune::FieldVector<Vector, maxNC> grad; //! derivative of shape function associated with the sub control volume
+        Dune::FieldVector<Vector, maxNC> gradCenter; //! derivative of shape function at the center of the sub control volume
+        Dune::FieldVector<Scalar, maxNC> shapeValue; //! value of shape function associated with the sub control volume
+        bool inner;
+    };
+
+    struct SubControlVolumeFace //! interior face of a sub control volume
+    {
+        int i,j; //!< scvf seperates corner i and j of elem
+        LocalPosition ipLocal; //!< integration point in local coords
+        GlobalPosition ipGlobal; //!< integration point in global coords
+        Vector normal; //!< normal on face pointing to CV j or outward of the domain with length equal to |scvf|
+        Scalar area; //!< area of face
+        Dune::FieldVector<Vector, maxNC> grad; //!< derivatives of shape functions at ip
+        Dune::FieldVector<Scalar, maxNC> shapeValue; //!< value of shape functions at ip
+        Dune::FieldVector<int, maxNFAP> fapIndices; //!< indices w.r.t.neighbors of the flux approximation points
+    };
+
+    typedef SubControlVolumeFace BoundaryFace; //!< compatibility typedef
+
+    LocalPosition elementLocal; //!< local coordinate of element center
+    GlobalPosition elementGlobal; //!< global coordinate of element center
+    Scalar elementVolume; //!< element volume
+    SubControlVolume subContVol[maxNC]; //!< data of the sub control volumes
+    SubControlVolumeFace subContVolFace[maxNE]; //!< data of the sub control volume faces
+    BoundaryFace boundaryFace[maxBF]; //!< data of the boundary faces
+    GlobalPosition edgeCoord[maxNE]; //!< global coordinates of the edge centers
+    GlobalPosition faceCoord[maxNF]; //!< global coordinates of the face centers
+    int numVertices; //!< number of verts
+    int numEdges; //!< number of edges
+    int numFaces; //!< number of faces (0 in < 3D)
+    int numSCV; //!< number of subcontrol volumes
+    int numFAP; //!< number of flux approximation points
+
+    const LocalFiniteElementCache feCache_;
+
+    void update(const GridView& gridView, const Element& element)
+    {
+        const Geometry& geometry = element.geometry();
+        Dune::GeometryType gt = geometry.type();
+
+        const typename Dune::GenericReferenceElementContainer<CoordScalar,dim>::value_type&
+            referenceElement = Dune::GenericReferenceElements<CoordScalar,dim>::general(gt);
+
+        const LocalFiniteElement
+            &localFiniteElement = feCache_.get(gt);
+
+        elementVolume = geometry.volume();
+        elementLocal = referenceElement.position(0,0);
+        elementGlobal = geometry.global(elementLocal);
+
+        numVertices = referenceElement.size(dim);
+        numEdges = referenceElement.size(dim-1);
+        numFaces = (dim<3)?0:referenceElement.size(1);
+        numSCV = numVertices;
+
+        bool useTwoPointFlux
+            = GET_PARAM_FROM_GROUP(TypeTag, bool, Implicit, UseTwoPointFlux);
+        if (useTwoPointFlux)
+            numFAP = 2;
+        else
+            numFAP = numVertices;
+
+        // corners:
+        for (int vert = 0; vert < numVertices; vert++) {
+            subContVol[vert].local = referenceElement.position(vert, dim);
+            subContVol[vert].global = geometry.global(subContVol[vert].local);
+            subContVol[vert].inner = true;
+        }
+
+        // edges:
+        for (int edge = 0; edge < numEdges; edge++) {
+            edgeCoord[edge] = geometry.global(referenceElement.position(edge, dim-1));
+        }
+
+        // faces:
+        for (int face = 0; face < numFaces; face++) {
+            faceCoord[face] = geometry.global(referenceElement.position(face, 1));
+        }
+
+        // fill sub control volume data use specialization for this
+        // \todo maybe it would be a good idea to migrate everything
+        // which is dependend of the grid's dimension to
+        // _BoxFVElemGeomHelper in order to benefit from more aggressive
+        // compiler optimizations...
+        BoxFVElemGeomHelper::fillSubContVolData(*this, numVertices);
+
+        // fill sub control volume face data:
+        for (int k = 0; k < numEdges; k++) { // begin loop over edges / sub control volume faces
+            int i = referenceElement.subEntity(k, dim-1, 0, dim);
+            int j = referenceElement.subEntity(k, dim-1, 1, dim);
+            if (numEdges == 4 && (i == 2 || j == 2))
+                std::swap(i, j);
+            subContVolFace[k].i = i;
+            subContVolFace[k].j = j;
+
+            // calculate the local integration point and
+            // the face normal. note that since dim is a
+            // constant which is known at compile time
+            // the compiler can optimize away all if
+            // cases which don't apply.
+            LocalPosition ipLocal;
+            Vector diffVec;
+            if (dim==1) {
+                subContVolFace[k].ipLocal = 0.5;
+                subContVolFace[k].normal = 1.0;
+                ipLocal = subContVolFace[k].ipLocal;
+            }
+            else if (dim==2) {
+                ipLocal = referenceElement.position(k, dim-1) + elementLocal;
+                ipLocal *= 0.5;
+                subContVolFace[k].ipLocal = ipLocal;
+                diffVec = elementGlobal - edgeCoord[k];
+                subContVolFace[k].normal[0] = diffVec[1];
+                subContVolFace[k].normal[1] = -diffVec[0];
+
+                diffVec = subContVol[j].global;
+                for (int m = 0; m < dimWorld; ++m)
+                    diffVec[m] -= subContVol[i].global[m];
+                // make sure the normal points to the right direction
+                if (subContVolFace[k].normal * diffVec < 0)
+                    subContVolFace[k].normal *= -1;
+
+            }
+            else if (dim==3) {
+                int leftFace;
+                int rightFace;
+                getFaceIndices(numVertices, k, leftFace, rightFace);
+                ipLocal = referenceElement.position(k, dim-1) + elementLocal
+                    + referenceElement.position(leftFace, 1)
+                    + referenceElement.position(rightFace, 1);
+                ipLocal *= 0.25;
+                subContVolFace[k].ipLocal = ipLocal;
+                normalOfQuadrilateral3D(subContVolFace[k].normal,
+                                        edgeCoord[k], faceCoord[rightFace],
+                                        elementGlobal, faceCoord[leftFace]);
+            }
+
+            if (useTwoPointFlux)
+            {
+                GlobalPosition distVec = subContVol[i].global;
+                distVec -= subContVol[j].global;
+                distVec /= distVec.two_norm2();
+
+                // gradients using a two-point flux approximation
+                for (int idx = 0; idx < 2; idx++)
+                {
+                    subContVolFace[k].grad[idx] = distVec;
+                    subContVolFace[k].shapeValue[idx] = 0.5;
+                }
+                subContVolFace[k].grad[1] *= -1.0;
+
+                subContVolFace[k].fapIndices[0] = subContVolFace[k].i;
+                subContVolFace[k].fapIndices[1] = subContVolFace[k].j;
+            }
+            else
+            {
+                // get the global integration point and the Jacobian inverse
+                subContVolFace[k].ipGlobal = geometry.global(ipLocal);
+                JacobianInverseTransposed jacInvT = 
+                    geometry.jacobianInverseTransposed(ipLocal);
+
+                // calculate the shape function gradients
+                //typedef Dune::FieldVector< Dune::FieldVector< CoordScalar, dim >, 1 > ShapeJacobian;
+                typedef Dune::FieldVector< Scalar, 1 > ShapeValue;
+                std::vector<ShapeJacobian> localJac;
+                std::vector<ShapeValue>    shapeVal;
+                localFiniteElement.localBasis().evaluateJacobian(subContVolFace[k].ipLocal, localJac);
+                localFiniteElement.localBasis().evaluateFunction(subContVolFace[k].ipLocal, shapeVal);
+                for (int vert = 0; vert < numVertices; vert++) {
+                    jacInvT.mv(localJac[vert][0], subContVolFace[k].grad[vert]);
+                    subContVolFace[k].shapeValue[vert] = Scalar(shapeVal[vert]);
+                    subContVolFace[k].fapIndices[vert] = vert;
+                }
+            }
+        } // end loop over edges / sub control volume faces
+
+        // fill boundary face data:
+        IntersectionIterator endit = gridView.iend(element);
+        for (IntersectionIterator it = gridView.ibegin(element); it != endit; ++it)
+            if (it->boundary())
+            {
+                int face = it->indexInInside();
+                int numVerticesOfFace = referenceElement.size(face, 1, dim);
+                for (int vertInFace = 0; vertInFace < numVerticesOfFace; vertInFace++)
+                {
+                    int vertInElement = referenceElement.subEntity(face, 1, vertInFace, dim);
+                    int bfIdx = boundaryFaceIndex(face, vertInFace);
+                    subContVol[vertInElement].inner = false;
+                    switch ((short) dim) {
+                    case 1:
+                        boundaryFace[bfIdx].ipLocal = referenceElement.position(vertInElement, dim);
+                        boundaryFace[bfIdx].area = 1.0;
+                        break;
+                    case 2:
+                        boundaryFace[bfIdx].ipLocal = referenceElement.position(vertInElement, dim)
+                            + referenceElement.position(face, 1);
+                        boundaryFace[bfIdx].ipLocal *= 0.5;
+                        boundaryFace[bfIdx].area = 0.5*it->geometry().volume();
+                        break;
+                    case 3:
+                        int leftEdge;
+                        int rightEdge;
+                        getEdgeIndices(numVertices, face, vertInElement, leftEdge, rightEdge);
+                        boundaryFace[bfIdx].ipLocal = referenceElement.position(vertInElement, dim)
+                            + referenceElement.position(face, 1)
+                            + referenceElement.position(leftEdge, dim-1)
+                            + referenceElement.position(rightEdge, dim-1);
+                        boundaryFace[bfIdx].ipLocal *= 0.25;
+                        boundaryFace[bfIdx].area = quadrilateralArea3D(subContVol[vertInElement].global,
+                                                                       edgeCoord[rightEdge], faceCoord[face], edgeCoord[leftEdge]);
+                        break;
+                    default:
+                        DUNE_THROW(Dune::NotImplemented, "BoxFVElementGeometry for dim = " << dim);
+                    }
+                    boundaryFace[bfIdx].ipGlobal = geometry.global(boundaryFace[bfIdx].ipLocal);
+                    boundaryFace[bfIdx].i = vertInElement;
+                    boundaryFace[bfIdx].j = vertInElement;
+
+                    // ASSUME constant normal
+                    Dune::FieldVector<CoordScalar, dim-1> localDimM1(0);
+                    boundaryFace[bfIdx].normal = it->unitOuterNormal(localDimM1);
+                    boundaryFace[bfIdx].normal *= boundaryFace[bfIdx].area;
+
+                    typedef Dune::FieldVector< Scalar, 1 > ShapeValue;
+                    std::vector<ShapeJacobian> localJac;
+                    std::vector<ShapeValue>    shapeVal;
+                    localFiniteElement.localBasis().evaluateJacobian(boundaryFace[bfIdx].ipLocal, localJac);
+                    localFiniteElement.localBasis().evaluateFunction(boundaryFace[bfIdx].ipLocal, shapeVal);
+
+                    JacobianInverseTransposed jacInvT = 
+                        geometry.jacobianInverseTransposed(boundaryFace[bfIdx].ipLocal);
+                    for (int vert = 0; vert < numVertices; vert++)
+                    {
+                        jacInvT.mv(localJac[vert][0], boundaryFace[bfIdx].grad[vert]);
+                        boundaryFace[bfIdx].shapeValue[vert] = Scalar(shapeVal[vert]);
+                        boundaryFace[bfIdx].fapIndices[vert] = vert;
+                    }
+                }
+            }
+
+        bool evalGradientsAtSCVCenter = GET_PROP_VALUE(TypeTag, EvalGradientsAtSCVCenter);
+        if(evalGradientsAtSCVCenter)
+        {
+            // calculate gradients at the center of the scv
+            for (int scvIdx = 0; scvIdx < numVertices; scvIdx++){
+                if (dim == 2)
+                {
+                    switch (scvIdx)
+                    {
+                    case 0:
+                        if (numVertices == 4) {
+                            subContVol[scvIdx].localCenter[0] = 0.25;
+                            subContVol[scvIdx].localCenter[1] = 0.25;
+                        }
+                        else {
+                            subContVol[scvIdx].localCenter[0] = 1.0/6.0;
+                            subContVol[scvIdx].localCenter[1] = 1.0/6.0;
+                        }
+                        break;
+                    case 1:
+                        if (numVertices == 4) {
+                            subContVol[scvIdx].localCenter[0] = 0.75;
+                            subContVol[scvIdx].localCenter[1] = 0.25;
+                        }
+                        else {
+                            subContVol[scvIdx].localCenter[0] = 4.0/6.0;
+                            subContVol[scvIdx].localCenter[1] = 1.0/6.0;
+                        }
+                        break;
+                    case 2:
+                        if (numVertices == 4) {
+                            subContVol[scvIdx].localCenter[0] = 0.25;
+                            subContVol[scvIdx].localCenter[1] = 0.75;
+                        }
+                        else {
+                            subContVol[scvIdx].localCenter[0] = 1.0/6.0;
+                            subContVol[scvIdx].localCenter[1] = 4.0/6.0;
+                        }
+                        break;
+                    case 3:
+                        subContVol[scvIdx].localCenter[0] = 0.75;
+                        subContVol[scvIdx].localCenter[1] = 0.75;
+                        break;
+                    }
+                }
+
+                else if (dim == 3)
+                {
+                    switch (scvIdx)
+                    {
+                    case 0:
+                        if (numVertices == 8) {
+                            subContVol[scvIdx].localCenter[0] = 0.25;
+                            subContVol[scvIdx].localCenter[1] = 0.25;
+                            subContVol[scvIdx].localCenter[2] = 0.25;
+                        }
+                        else if (numVertices == 4) {
+                            subContVol[scvIdx].localCenter[0] = 3.0/16.0;
+                            subContVol[scvIdx].localCenter[1] = 3.0/16.0;
+                            subContVol[scvIdx].localCenter[2] = 3.0/16.0;
+                        }
+                        break;
+                    case 1:
+                        if (numVertices == 8) {
+                            subContVol[scvIdx].localCenter[0] = 0.75;
+                            subContVol[scvIdx].localCenter[1] = 0.25;
+                            subContVol[scvIdx].localCenter[2] = 0.25;
+                        }
+                        else if (numVertices == 4) {
+                            subContVol[scvIdx].localCenter[0] = 7.0/16.0;
+                            subContVol[scvIdx].localCenter[1] = 3.0/16.0;
+                            subContVol[scvIdx].localCenter[2] = 3.0/16.0;
+                        }
+                        break;
+                    case 2:
+                        if (numVertices == 8) {
+                            subContVol[scvIdx].localCenter[0] = 0.25;
+                            subContVol[scvIdx].localCenter[1] = 0.75;
+                            subContVol[scvIdx].localCenter[2] = 0.25;
+                        }
+                        else if (numVertices == 4) {
+                            subContVol[scvIdx].localCenter[0] = 3.0/16.0;
+                            subContVol[scvIdx].localCenter[1] = 7.0/16.0;
+                            subContVol[scvIdx].localCenter[2] = 3.0/16.0;
+                        }
+                        break;
+                    case 3:
+                        if (numVertices == 8) {
+                            subContVol[scvIdx].localCenter[0] = 0.75;
+                            subContVol[scvIdx].localCenter[1] = 0.75;
+                            subContVol[scvIdx].localCenter[2] = 0.25;
+                        }
+                        else if (numVertices == 4) {
+                            subContVol[scvIdx].localCenter[0] = 3.0/16.0;
+                            subContVol[scvIdx].localCenter[1] = 3.0/16.0;
+                            subContVol[scvIdx].localCenter[2] = 7.0/16.0;
+                        }
+                        break;
+                    case 4:
+                        subContVol[scvIdx].localCenter[0] = 0.25;
+                        subContVol[scvIdx].localCenter[1] = 0.25;
+                        subContVol[scvIdx].localCenter[2] = 0.75;
+                        break;
+                    case 5:
+                        subContVol[scvIdx].localCenter[0] = 0.75;
+                        subContVol[scvIdx].localCenter[1] = 0.25;
+                        subContVol[scvIdx].localCenter[2] = 0.75;
+                        break;
+                    case 6:
+                        subContVol[scvIdx].localCenter[0] = 0.25;
+                        subContVol[scvIdx].localCenter[1] = 0.75;
+                        subContVol[scvIdx].localCenter[2] = 0.75;
+                        break;
+                    case 7:
+                        subContVol[scvIdx].localCenter[0] = 0.75;
+                        subContVol[scvIdx].localCenter[1] = 0.75;
+                        subContVol[scvIdx].localCenter[2] = 0.75;
+                        break;
+                    }
+                }
+                std::vector<ShapeJacobian> localJac;
+                localFiniteElement.localBasis().evaluateJacobian(subContVol[scvIdx].localCenter, localJac);
+
+                JacobianInverseTransposed jacInvT =
+                    geometry.jacobianInverseTransposed(subContVol[scvIdx].localCenter);
+                for (int vert = 0; vert < numVertices; vert++)
+                    jacInvT.mv(localJac[vert][0], subContVol[scvIdx].gradCenter[vert]);
+            }
+        }
+    }
+};
+
+}
+
+#endif
+
diff --git a/dumux/implicit/box/boxlocaljacobian.hh b/dumux/implicit/box/boxlocaljacobian.hh
new file mode 100644
index 0000000000..7fc5140d25
--- /dev/null
+++ b/dumux/implicit/box/boxlocaljacobian.hh
@@ -0,0 +1,534 @@
+// -*- mode: C++; tab-width: 4; indent-tabs-mode: nil; c-basic-offset: 4 -*-
+// vi: set et ts=4 sw=4 sts=4:
+/*****************************************************************************
+ *   See the file COPYING for full copying permissions.                      *
+ *                                                                           *
+ *   This program is free software: you can redistribute it and/or modify    *
+ *   it under the terms of the GNU General Public License as published by    *
+ *   the Free Software Foundation, either version 2 of the License, or       *
+ *   (at your option) any later version.                                     *
+ *                                                                           *
+ *   This program is distributed in the hope that it will be useful,         *
+ *   but WITHOUT ANY WARRANTY; without even the implied warranty of          *
+ *   MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the            *
+ *   GNU General Public License for more details.                            *
+ *                                                                           *
+ *   You should have received a copy of the GNU General Public License       *
+ *   along with this program.  If not, see <http://www.gnu.org/licenses/>.   *
+ *****************************************************************************/
+/*!
+ * \file
+ * \brief Caculates the Jacobian of the local residual for box models
+ */
+#ifndef DUMUX_BOX_LOCAL_JACOBIAN_HH
+#define DUMUX_BOX_LOCAL_JACOBIAN_HH
+
+#include <dune/istl/matrix.hh>
+
+#include <dumux/common/math.hh>
+#include "boxelementboundarytypes.hh"
+
+namespace Dumux
+{
+/*!
+ * \ingroup BoxModel
+ * \ingroup BoxLocalJacobian
+ * \brief Calculates the Jacobian of the local residual for box models
+ *
+ * The default behavior is to use numeric differentiation, i.e.
+ * forward or backward differences (2nd order), or central
+ * differences (3rd order). The method used is determined by the
+ * "NumericDifferenceMethod" property:
+ *
+ * - if the value of this property is smaller than 0, backward
+ *   differences are used, i.e.:
+ *   \f[
+ \frac{\partial f(x)}{\partial x} \approx \frac{f(x) - f(x - \epsilon)}{\epsilon}
+ *   \f]
+ *
+ * - if the value of this property is 0, central
+ *   differences are used, i.e.:
+ *   \f[
+ \frac{\partial f(x)}{\partial x} \approx \frac{f(x + \epsilon) - f(x - \epsilon)}{2 \epsilon}
+ *   \f]
+ *
+ * - if the value of this property is larger than 0, forward
+ *   differences are used, i.e.:
+ *   \f[
+ \frac{\partial f(x)}{\partial x} \approx \frac{f(x + \epsilon) - f(x)}{\epsilon}
+ *   \f]
+ *
+ * Here, \f$ f \f$ is the residual function for all equations, \f$x\f$
+ * is the value of a sub-control volume's primary variable at the
+ * evaluation point and \f$\epsilon\f$ is a small value larger than 0.
+ */
+template<class TypeTag>
+class BoxLocalJacobian
+{
+private:
+    typedef typename GET_PROP_TYPE(TypeTag, LocalJacobian) Implementation;
+    typedef typename GET_PROP_TYPE(TypeTag, LocalResidual) LocalResidual;
+    typedef typename GET_PROP_TYPE(TypeTag, Problem) Problem;
+    typedef typename GET_PROP_TYPE(TypeTag, Model) Model;
+    typedef typename GET_PROP_TYPE(TypeTag, GridView) GridView;
+    typedef typename GridView::template Codim<0>::Entity Element;
+    typedef typename GET_PROP_TYPE(TypeTag, JacobianAssembler) JacobianAssembler;
+
+    enum {
+        numEq = GET_PROP_VALUE(TypeTag, NumEq),
+        dim = GridView::dimension,
+
+        Green = JacobianAssembler::Green
+    };
+
+    typedef typename GET_PROP_TYPE(TypeTag, FVElementGeometry) FVElementGeometry;
+    typedef typename GET_PROP_TYPE(TypeTag, VertexMapper) VertexMapper;
+    typedef typename GET_PROP_TYPE(TypeTag, ElementSolutionVector) ElementSolutionVector;
+    typedef typename GET_PROP_TYPE(TypeTag, PrimaryVariables) PrimaryVariables;
+
+    typedef typename GET_PROP_TYPE(TypeTag, VolumeVariables) VolumeVariables;
+    typedef typename GET_PROP_TYPE(TypeTag, ElementVolumeVariables) ElementVolumeVariables;
+    typedef typename GET_PROP_TYPE(TypeTag, ElementBoundaryTypes) ElementBoundaryTypes;
+
+    typedef typename GET_PROP_TYPE(TypeTag, Scalar) Scalar;
+    typedef Dune::FieldMatrix<Scalar, numEq, numEq> MatrixBlock;
+    typedef Dune::Matrix<MatrixBlock> LocalBlockMatrix;
+
+    // copying a local jacobian is not a good idea
+    BoxLocalJacobian(const BoxLocalJacobian &);
+
+public:
+    BoxLocalJacobian()
+    {
+        numericDifferenceMethod_ = GET_PARAM_FROM_GROUP(TypeTag, int, Implicit, NumericDifferenceMethod);
+        Valgrind::SetUndefined(problemPtr_);
+    }
+
+
+    /*!
+     * \brief Initialize the local Jacobian object.
+     *
+     * At this point we can assume that everything has been allocated,
+     * although some objects may not yet be completely initialized.
+     *
+     * \param prob The problem which we want to simulate.
+     */
+    void init(Problem &prob)
+    {
+        problemPtr_ = &prob;
+        localResidual_.init(prob);
+
+        // assume quadrilinears as elements with most vertices
+        A_.setSize(2<<dim, 2<<dim);
+        storageJacobian_.resize(2<<dim);
+    }
+
+    /*!
+     * \brief Assemble an element's local Jacobian matrix of the
+     *        defect.
+     *
+     * \param element The DUNE Codim<0> entity which we look at.
+     */
+    void assemble(const Element &element)
+    {
+        // set the current grid element and update the element's
+        // finite volume geometry
+        elemPtr_ = &element;
+        fvElemGeom_.update(gridView_(), element);
+        reset_();
+
+        bcTypes_.update(problem_(), element_(), fvElemGeom_);
+
+        // this is pretty much a HACK because the internal state of
+        // the problem is not supposed to be changed during the
+        // evaluation of the residual. (Reasons: It is a violation of
+        // abstraction, makes everything more prone to errors and is
+        // not thread save.) The real solution are context objects!
+        problem_().updateCouplingParams(element_());
+
+        // set the hints for the volume variables
+        model_().setHints(element, prevVolVars_, curVolVars_);
+
+        // update the secondary variables for the element at the last
+        // and the current time levels
+        prevVolVars_.update(problem_(),
+                            element_(),
+                            fvElemGeom_,
+                            true /* isOldSol? */);
+
+        curVolVars_.update(problem_(),
+                           element_(),
+                           fvElemGeom_,
+                           false /* isOldSol? */);
+
+        // update the hints of the model
+        model_().updateCurHints(element, curVolVars_);
+
+        // calculate the local residual
+        localResidual().eval(element_(),
+                             fvElemGeom_,
+                             prevVolVars_,
+                             curVolVars_,
+                             bcTypes_);
+        residual_ = localResidual().residual();
+        storageTerm_ = localResidual().storageTerm();
+
+        model_().updatePVWeights(element_(), curVolVars_);
+
+        // calculate the local jacobian matrix
+        int numVertices = fvElemGeom_.numVertices;
+        ElementSolutionVector partialDeriv(numVertices);
+        PrimaryVariables storageDeriv;
+        for (int j = 0; j < numVertices; j++) {
+            for (int pvIdx = 0; pvIdx < numEq; pvIdx++) {
+                asImp_().evalPartialDerivative_(partialDeriv,
+                                                storageDeriv,
+                                                j,
+                                                pvIdx);
+
+                // update the local stiffness matrix with the current partial
+                // derivatives
+                updateLocalJacobian_(j,
+                                     pvIdx,
+                                     partialDeriv,
+                                     storageDeriv);
+            }
+        }
+    }
+
+    /*!
+     * \brief Returns a reference to the object which calculates the
+     *        local residual.
+     */
+    const LocalResidual &localResidual() const
+    { return localResidual_; }
+
+    /*!
+     * \brief Returns a reference to the object which calculates the
+     *        local residual.
+     */
+    LocalResidual &localResidual()
+    { return localResidual_; }
+
+    /*!
+     * \brief Returns the Jacobian of the equations at vertex i to the
+     *        primary variables at vertex j.
+     *
+     * \param i The local vertex (or sub-control volume) index on which
+     *          the equations are defined
+     * \param j The local vertex (or sub-control volume) index which holds
+     *          primary variables
+     */
+    const MatrixBlock &mat(const int i, const int j) const
+    { return A_[i][j]; }
+
+    /*!
+     * \brief Returns the Jacobian of the storage term at vertex i.
+     *
+     * \param i The local vertex (or sub-control volume) index
+     */
+    const MatrixBlock &storageJacobian(const int i) const
+    { return storageJacobian_[i]; }
+
+    /*!
+     * \brief Returns the residual of the equations at vertex i.
+     *
+     * \param i The local vertex (or sub-control volume) index on which
+     *          the equations are defined
+     */
+    const PrimaryVariables &residual(const int i) const
+    { return residual_[i]; }
+
+    /*!
+     * \brief Returns the storage term for vertex i.
+     *
+     * \param i The local vertex (or sub-control volume) index on which
+     *          the equations are defined
+     */
+    const PrimaryVariables &storageTerm(const int i) const
+    { return storageTerm_[i]; }
+
+    /*!
+     * \brief Returns the epsilon value which is added and removed
+     *        from the current solution.
+     *
+     * \param scvIdx     The local index of the element's vertex for
+     *                   which the local derivative ought to be calculated.
+     * \param pvIdx      The index of the primary variable which gets varied
+     */
+    Scalar numericEpsilon(const int scvIdx,
+                          const int pvIdx) const
+    {
+        // define the base epsilon as the geometric mean of 1 and the
+        // resolution of the scalar type. E.g. for standard 64 bit
+        // floating point values, the resolution is about 10^-16 and
+        // the base epsilon is thus approximately 10^-8.
+        /*
+        static const Scalar baseEps
+            = Dumux::geometricMean<Scalar>(std::numeric_limits<Scalar>::epsilon(), 1.0);
+        */
+        static const Scalar baseEps = 1e-10;
+        assert(std::numeric_limits<Scalar>::epsilon()*1e4 < baseEps);
+        // the epsilon value used for the numeric differentiation is
+        // now scaled by the absolute value of the primary variable...
+        Scalar priVar = this->curVolVars_[scvIdx].priVar(pvIdx);
+        return baseEps*(std::abs(priVar) + 1.0);
+    }
+
+protected:
+    Implementation &asImp_()
+    { return *static_cast<Implementation*>(this); }
+    const Implementation &asImp_() const
+    { return *static_cast<const Implementation*>(this); }
+
+    /*!
+     * \brief Returns a reference to the problem.
+     */
+    const Problem &problem_() const
+    {
+        Valgrind::CheckDefined(problemPtr_);
+        return *problemPtr_;
+    };
+
+    /*!
+     * \brief Returns a reference to the grid view.
+     */
+    const GridView &gridView_() const
+    { return problem_().gridView(); }
+
+    /*!
+     * \brief Returns a reference to the element.
+     */
+    const Element &element_() const
+    {
+        Valgrind::CheckDefined(elemPtr_);
+        return *elemPtr_;
+    };
+
+    /*!
+     * \brief Returns a reference to the model.
+     */
+    const Model &model_() const
+    { return problem_().model(); };
+
+    /*!
+     * \brief Returns a reference to the jacobian assembler.
+     */
+    const JacobianAssembler &jacAsm_() const
+    { return model_().jacobianAssembler(); }
+
+    /*!
+     * \brief Returns a reference to the vertex mapper.
+     */
+    const VertexMapper &vertexMapper_() const
+    { return problem_().vertexMapper(); };
+
+    /*!
+     * \brief Reset the local jacobian matrix to 0
+     */
+    void reset_()
+    {
+        int n = element_().template count<dim>();
+        for (int i = 0; i < n; ++ i) {
+            storageJacobian_[i] = 0.0;
+            for (int j = 0; j < n; ++ j) {
+                A_[i][j] = 0.0;
+            }
+        }
+    }
+
+    /*!
+     * \brief Compute the partial derivatives to a primary variable at
+     *        an degree of freedom.
+     *
+     * This method can be overwritten by the implementation if a
+     * better scheme than numerical differentiation is available.
+     *
+     * The default implementation of this method uses numeric
+     * differentiation, i.e. forward or backward differences (2nd
+     * order), or central differences (3rd order). The method used is
+     * determined by the "NumericDifferenceMethod" property:
+     *
+     * - if the value of this property is smaller than 0, backward
+     *   differences are used, i.e.:
+     *   \f[
+         \frac{\partial f(x)}{\partial x} \approx \frac{f(x) - f(x - \epsilon)}{\epsilon}
+     *   \f]
+     *
+     * - if the value of this property is 0, central
+     *   differences are used, i.e.:
+     *   \f[
+           \frac{\partial f(x)}{\partial x} \approx \frac{f(x + \epsilon) - f(x - \epsilon)}{2 \epsilon}
+     *   \f]
+     *
+     * - if the value of this property is larger than 0, forward
+     *   differences are used, i.e.:
+     *   \f[
+           \frac{\partial f(x)}{\partial x} \approx \frac{f(x + \epsilon) - f(x)}{\epsilon}
+     *   \f]
+     *
+     * Here, \f$ f \f$ is the residual function for all equations, \f$x\f$
+     * is the value of a sub-control volume's primary variable at the
+     * evaluation point and \f$\epsilon\f$ is a small value larger than 0.
+     *
+     * \param partialDeriv The vector storing the partial derivatives of all
+     *              equations
+     * \param storageDeriv the mass matrix contributions
+     * \param scvIdx The sub-control volume index of the current
+     *               finite element for which the partial derivative
+     *               ought to be calculated
+     * \param pvIdx The index of the primary variable at the scvIdx'
+     *              sub-control volume of the current finite element
+     *              for which the partial derivative ought to be
+     *              calculated
+     */
+    void evalPartialDerivative_(ElementSolutionVector &partialDeriv,
+                                PrimaryVariables &storageDeriv,
+                                const int scvIdx,
+                                const int pvIdx)
+    {
+        int globalIdx = vertexMapper_().map(element_(), scvIdx, dim);
+
+        PrimaryVariables priVars(model_().curSol()[globalIdx]);
+        VolumeVariables origVolVars(curVolVars_[scvIdx]);
+
+        curVolVars_[scvIdx].setEvalPoint(&origVolVars);
+        Scalar eps = asImp_().numericEpsilon(scvIdx, pvIdx);
+        Scalar delta = 0;
+
+        if (numericDifferenceMethod_ >= 0) {
+            // we are not using backward differences, i.e. we need to
+            // calculate f(x + \epsilon)
+
+            // deflect primary variables
+            priVars[pvIdx] += eps;
+            delta += eps;
+
+            // calculate the residual
+            curVolVars_[scvIdx].update(priVars,
+                                       problem_(),
+                                       element_(),
+                                       fvElemGeom_,
+                                       scvIdx,
+                                       false);
+            localResidual().eval(element_(),
+                                 fvElemGeom_,
+                                 prevVolVars_,
+                                 curVolVars_,
+                                 bcTypes_);
+
+            // store the residual and the storage term
+            partialDeriv = localResidual().residual();
+            storageDeriv = localResidual().storageTerm()[scvIdx];
+        }
+        else {
+            // we are using backward differences, i.e. we don't need
+            // to calculate f(x + \epsilon) and we can recycle the
+            // (already calculated) residual f(x)
+            partialDeriv = residual_;
+            storageDeriv = storageTerm_[scvIdx];
+        }
+
+
+        if (numericDifferenceMethod_ <= 0) {
+            // we are not using forward differences, i.e. we don't
+            // need to calculate f(x - \epsilon)
+
+            // deflect the primary variables
+            priVars[pvIdx] -= delta + eps;
+            delta += eps;
+
+            // calculate residual again
+            curVolVars_[scvIdx].update(priVars,
+                                       problem_(),
+                                       element_(),
+                                       fvElemGeom_,
+                                       scvIdx,
+                                       false);
+            localResidual().eval(element_(),
+                                 fvElemGeom_,
+                                 prevVolVars_,
+                                 curVolVars_,
+                                 bcTypes_);
+            partialDeriv -= localResidual().residual();
+            storageDeriv -= localResidual().storageTerm()[scvIdx];
+        }
+        else {
+            // we are using forward differences, i.e. we don't need to
+            // calculate f(x - \epsilon) and we can recycle the
+            // (already calculated) residual f(x)
+            partialDeriv -= residual_;
+            storageDeriv -= storageTerm_[scvIdx];
+        }
+
+        // divide difference in residuals by the magnitude of the
+        // deflections between the two function evaluation
+        partialDeriv /= delta;
+        storageDeriv /= delta;
+
+        // restore the original state of the element's volume variables
+        curVolVars_[scvIdx] = origVolVars;
+
+#if HAVE_VALGRIND
+        for (unsigned i = 0; i < partialDeriv.size(); ++i)
+            Valgrind::CheckDefined(partialDeriv[i]);
+#endif
+    }
+
+    /*!
+     * \brief Updates the current local Jacobian matrix with the
+     *        partial derivatives of all equations in regard to the
+     *        primary variable 'pvIdx' at vertex 'scvIdx' .
+     */
+    void updateLocalJacobian_(const int scvIdx,
+                              const int pvIdx,
+                              const ElementSolutionVector &partialDeriv,
+                              const PrimaryVariables &storageDeriv)
+    {
+        // store the derivative of the storage term
+        for (int eqIdx = 0; eqIdx < numEq; eqIdx++) {
+            storageJacobian_[scvIdx][eqIdx][pvIdx] = storageDeriv[eqIdx];
+        }
+
+        for (int i = 0; i < fvElemGeom_.numVertices; i++)
+        {
+            // Green vertices are not to be changed!
+            if (jacAsm_().vertexColor(element_(), i) != Green) {
+                for (int eqIdx = 0; eqIdx < numEq; eqIdx++) {
+                    // A[i][scvIdx][eqIdx][pvIdx] is the rate of change of
+                    // the residual of equation 'eqIdx' at vertex 'i'
+                    // depending on the primary variable 'pvIdx' at vertex
+                    // 'scvIdx'.
+                    this->A_[i][scvIdx][eqIdx][pvIdx] = partialDeriv[i][eqIdx];
+                    Valgrind::CheckDefined(this->A_[i][scvIdx][eqIdx][pvIdx]);
+                }
+            }
+        }
+    }
+
+    const Element *elemPtr_;
+    FVElementGeometry fvElemGeom_;
+
+    ElementBoundaryTypes bcTypes_;
+
+    // The problem we would like to solve
+    Problem *problemPtr_;
+
+    // secondary variables at the previous and at the current time
+    // levels
+    ElementVolumeVariables prevVolVars_;
+    ElementVolumeVariables curVolVars_;
+
+    LocalResidual localResidual_;
+
+    LocalBlockMatrix A_;
+    std::vector<MatrixBlock> storageJacobian_;
+
+    ElementSolutionVector residual_;
+    ElementSolutionVector storageTerm_;
+
+    int numericDifferenceMethod_;
+};
+}
+
+#endif
diff --git a/dumux/implicit/box/boxlocalresidual.hh b/dumux/implicit/box/boxlocalresidual.hh
new file mode 100644
index 0000000000..8c02754133
--- /dev/null
+++ b/dumux/implicit/box/boxlocalresidual.hh
@@ -0,0 +1,742 @@
+// -*- mode: C++; tab-width: 4; indent-tabs-mode: nil; c-basic-offset: 4 -*-
+// vi: set et ts=4 sw=4 sts=4:
+/*****************************************************************************
+ *   See the file COPYING for full copying permissions.                      *
+ *                                                                           *
+ *   This program is free software: you can redistribute it and/or modify    *
+ *   it under the terms of the GNU General Public License as published by    *
+ *   the Free Software Foundation, either version 2 of the License, or       *
+ *   (at your option) any later version.                                     *
+ *                                                                           *
+ *   This program is distributed in the hope that it will be useful,         *
+ *   but WITHOUT ANY WARRANTY; without even the implied warranty of          *
+ *   MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the            *
+ *   GNU General Public License for more details.                            *
+ *                                                                           *
+ *   You should have received a copy of the GNU General Public License       *
+ *   along with this program.  If not, see <http://www.gnu.org/licenses/>.   *
+ *****************************************************************************/
+/*!
+ * \file
+ * \brief Calculates the residual of models based on the box scheme element-wise.
+ */
+#ifndef DUMUX_BOX_LOCAL_RESIDUAL_HH
+#define DUMUX_BOX_LOCAL_RESIDUAL_HH
+
+#include <dune/istl/matrix.hh>
+#include <dune/grid/common/geometry.hh>
+
+#include <dumux/common/valgrind.hh>
+
+#include "boxproperties.hh"
+
+namespace Dumux
+{
+/*!
+ * \ingroup BoxModel
+ * \ingroup BoxLocalResidual
+ * \brief Element-wise calculation of the residual matrix for models
+ *        based on the box scheme.
+ *
+ * \todo Please doc me more!
+ */
+template<class TypeTag>
+class BoxLocalResidual
+{
+private:
+    typedef typename GET_PROP_TYPE(TypeTag, LocalResidual) Implementation;
+    typedef typename GET_PROP_TYPE(TypeTag, Problem) Problem;
+    typedef typename GET_PROP_TYPE(TypeTag, Model) Model;
+    typedef typename GET_PROP_TYPE(TypeTag, Scalar) Scalar;
+    typedef typename GET_PROP_TYPE(TypeTag, GridView) GridView;
+
+    enum {
+        numEq = GET_PROP_VALUE(TypeTag, NumEq),
+        dim = GridView::dimension
+    };
+
+    typedef typename GridView::template Codim<0>::Entity Element;
+    typedef typename GridView::template Codim<dim>::EntityPointer VertexPointer;
+    typedef typename GridView::IntersectionIterator IntersectionIterator;
+
+    typedef typename GridView::Grid::ctype CoordScalar;
+    typedef typename Dune::GenericReferenceElements<CoordScalar, dim> ReferenceElements;
+    typedef typename Dune::GenericReferenceElement<CoordScalar, dim> ReferenceElement;
+
+    typedef typename GET_PROP_TYPE(TypeTag, FVElementGeometry) FVElementGeometry;
+    typedef typename GET_PROP_TYPE(TypeTag, VertexMapper) VertexMapper;
+    typedef typename GET_PROP_TYPE(TypeTag, ElementSolutionVector) ElementSolutionVector;
+    typedef typename GET_PROP_TYPE(TypeTag, PrimaryVariables) PrimaryVariables;
+    typedef typename GET_PROP_TYPE(TypeTag, BoundaryTypes) BoundaryTypes;
+    typedef typename GET_PROP_TYPE(TypeTag, ElementBoundaryTypes) ElementBoundaryTypes;
+    typedef typename GET_PROP_TYPE(TypeTag, VolumeVariables) VolumeVariables;
+    typedef typename GET_PROP_TYPE(TypeTag, ElementVolumeVariables) ElementVolumeVariables;
+
+    // copying the local residual class is not a good idea
+    BoxLocalResidual(const BoxLocalResidual &);
+
+public:
+    BoxLocalResidual()
+    { }
+
+    ~BoxLocalResidual()
+    { }
+
+    /*!
+     * \brief Initialize the local residual.
+     *
+     * This assumes that all objects of the simulation have been fully
+     * allocated but not necessarily initialized completely.
+     *
+     * \param problem The representation of the physical problem to be
+     *             solved.
+     */
+    void init(Problem &problem)
+    { problemPtr_ = &problem; }
+
+    /*!
+     * \brief Compute the local residual, i.e. the deviation of the
+     *        equations from zero.
+     *
+     * \param element The DUNE Codim<0> entity for which the residual
+     *                ought to be calculated
+     */
+    void eval(const Element &element)
+    {
+        FVElementGeometry fvGeometry;
+
+        fvGeometry.update(gridView_(), element);
+        fvElemGeomPtr_ = &fvGeometry;
+
+        ElementVolumeVariables volVarsPrev, volVarsCur;
+        // update the hints
+        model_().setHints(element, volVarsPrev, volVarsCur);
+
+        volVarsPrev.update(problem_(),
+                           element,
+                           fvGeometry_(),
+                           true /* oldSol? */);
+        volVarsCur.update(problem_(),
+                          element,
+                          fvGeometry_(),
+                          false /* oldSol? */);
+
+        ElementBoundaryTypes bcTypes;
+        bcTypes.update(problem_(), element, fvGeometry_());
+
+        // this is pretty much a HACK because the internal state of
+        // the problem is not supposed to be changed during the
+        // evaluation of the residual. (Reasons: It is a violation of
+        // abstraction, makes everything more prone to errors and is
+        // not thread save.) The real solution are context objects!
+        problem_().updateCouplingParams(element);
+
+        asImp_().eval(element, fvGeometry_(), volVarsPrev, volVarsCur, bcTypes);
+    }
+
+    /*!
+     * \brief Compute the storage term for the current solution.
+     *
+     * This can be used to figure out how much of each conservation
+     * quantity is inside the element.
+     *
+     * \param element The DUNE Codim<0> entity for which the storage
+     *                term ought to be calculated
+     */
+    void evalStorage(const Element &element)
+    {
+        elemPtr_ = &element;
+
+        FVElementGeometry fvGeometry;
+        fvGeometry.update(gridView_(), element);
+        fvElemGeomPtr_ = &fvGeometry;
+
+        ElementBoundaryTypes bcTypes;
+        bcTypes.update(problem_(), element, fvGeometry_());
+        bcTypesPtr_ = &bcTypes;
+
+        // no previous volume variables!
+        prevVolVarsPtr_ = 0;
+
+        ElementVolumeVariables volVars;
+
+        // update the hints
+        model_().setHints(element, volVars);
+
+        // calculate volume current variables
+        volVars.update(problem_(), element, fvGeometry_(), false);
+        curVolVarsPtr_ = &volVars;
+
+        asImp_().evalStorage_();
+    }
+
+    /*!
+     * \brief Compute the flux term for the current solution.
+     *
+     * \param element The DUNE Codim<0> entity for which the residual
+     *                ought to be calculated
+     * \param curVolVars The volume averaged variables for all
+     *                   sub-contol volumes of the element
+     */
+    void evalFluxes(const Element &element,
+                    const ElementVolumeVariables &curVolVars)
+    {
+        elemPtr_ = &element;
+
+        FVElementGeometry fvGeometry;
+        fvGeometry.update(gridView_(), element);
+        fvElemGeomPtr_ = &fvGeometry;
+
+        ElementBoundaryTypes bcTypes;
+        bcTypes.update(problem_(), element, fvGeometry_());
+
+        residual_.resize(fvGeometry_().numVertices);
+        residual_ = 0;
+
+        bcTypesPtr_ = &bcTypes;
+        prevVolVarsPtr_ = 0;
+        curVolVarsPtr_ = &curVolVars;
+        asImp_().evalFluxes_();
+    }
+
+    /*!
+     * \brief Compute the local residual, i.e. the deviation of the
+     *        equations from zero.
+     *
+     * \param element The DUNE Codim<0> entity for which the residual
+     *                ought to be calculated
+     * \param fvGeometry The finite-volume geometry of the element
+     * \param prevVolVars The volume averaged variables for all
+     *                   sub-control volumes of the element at the previous
+     *                   time level
+     * \param curVolVars The volume averaged variables for all
+     *                   sub-control volumes of the element at the current
+     *                   time level
+     * \param bcTypes The types of the boundary conditions for all
+     *                vertices of the element
+     */
+    void eval(const Element &element,
+              const FVElementGeometry &fvGeometry,
+              const ElementVolumeVariables &prevVolVars,
+              const ElementVolumeVariables &curVolVars,
+              const ElementBoundaryTypes &bcTypes)
+    {
+        Valgrind::CheckDefined(prevVolVars);
+        Valgrind::CheckDefined(curVolVars);
+
+#if !defined NDEBUG && HAVE_VALGRIND
+        for (int i=0; i < fvGeometry.numVertices; i++) {
+            prevVolVars[i].checkDefined();
+            curVolVars[i].checkDefined();
+        }
+#endif // HAVE_VALGRIND
+
+        elemPtr_ = &element;
+        fvElemGeomPtr_ = &fvGeometry;
+        bcTypesPtr_ = &bcTypes;
+        prevVolVarsPtr_ = &prevVolVars;
+        curVolVarsPtr_ = &curVolVars;
+
+        // resize the vectors for all terms
+        int numVerts = fvGeometry_().numVertices;
+        residual_.resize(numVerts);
+        storageTerm_.resize(numVerts);
+
+        residual_ = 0.0;
+        storageTerm_ = 0.0;
+
+        asImp_().evalFluxes_();
+
+#if !defined NDEBUG && HAVE_VALGRIND
+        for (int i=0; i < fvGeometry_().numVertices; i++)
+            Valgrind::CheckDefined(residual_[i]);
+#endif // HAVE_VALGRIND
+
+        asImp_().evalVolumeTerms_();
+
+#if !defined NDEBUG && HAVE_VALGRIND
+        for (int i=0; i < fvGeometry_().numVertices; i++) {
+            Valgrind::CheckDefined(residual_[i]);
+        }
+#endif // HAVE_VALGRIND
+
+        // evaluate the boundary conditions
+        asImp_().evalBoundary_();
+
+#if !defined NDEBUG && HAVE_VALGRIND
+        for (int i=0; i < fvGeometry_().numVertices; i++)
+            Valgrind::CheckDefined(residual_[i]);
+#endif // HAVE_VALGRIND
+    }
+
+    /*!
+     * \brief Returns the local residual for all sub-control
+     *        volumes of the element.
+     */
+    const ElementSolutionVector &residual() const
+    { return residual_; }
+
+    /*!
+     * \brief Returns the local residual for a given sub-control
+     *        volume of the element.
+     *
+     * \param scvIdx The local index of the sub-control volume
+     *               (i.e. the element's local vertex index)
+     */
+    const PrimaryVariables &residual(const int scvIdx) const
+    { return residual_[scvIdx]; }
+
+    /*!
+     * \brief Returns the storage term for all sub-control volumes of the
+     *        element.
+     */
+    const ElementSolutionVector &storageTerm() const
+    { return storageTerm_; }
+
+    /*!
+     * \brief Returns the storage term for a given sub-control volumes
+     *        of the element.
+     */
+    const PrimaryVariables &storageTerm(const int scvIdx) const
+    { return storageTerm_[scvIdx]; }
+
+protected:
+    Implementation &asImp_()
+    {
+        assert(static_cast<Implementation*>(this) != 0);
+        return *static_cast<Implementation*>(this);
+    }
+
+    const Implementation &asImp_() const
+    {
+        assert(static_cast<const Implementation*>(this) != 0);
+        return *static_cast<const Implementation*>(this);
+    }
+
+    /*!
+     * \brief Evaluate the boundary conditions
+     *        of the current element.
+     */
+    void evalBoundary_()
+    {
+        if (bcTypes_().hasNeumann() || bcTypes_().hasOutflow())
+            asImp_().evalBoundaryFluxes_();
+#if !defined NDEBUG && HAVE_VALGRIND
+        for (int i=0; i < fvGeometry_().numVertices; i++)
+            Valgrind::CheckDefined(residual_[i]);
+#endif // HAVE_VALGRIND
+
+        if (bcTypes_().hasDirichlet())
+            asImp_().evalDirichlet_();
+    }
+
+    /*!
+     * \brief Set the values of the Dirichlet boundary control volumes
+     *        of the current element.
+     */
+    void evalDirichlet_()
+    {
+        PrimaryVariables dirichletValues(0);
+        for (int scvIdx = 0; scvIdx < fvGeometry_().numVertices; ++scvIdx) {
+            const BoundaryTypes &bcTypes = bcTypes_(scvIdx);
+            
+            if (bcTypes.hasDirichlet()) {
+                // ask the problem for the dirichlet values
+                const VertexPointer vPtr = element_().template subEntity<dim>(scvIdx);
+                Valgrind::SetUndefined(dirichletValues);
+                asImp_().problem_().dirichlet(dirichletValues, *vPtr);
+
+                // set the dirichlet conditions
+                for (int eqIdx = 0; eqIdx < numEq; ++eqIdx) {
+                    if (bcTypes.isDirichlet(eqIdx)) {
+                        int pvIdx = bcTypes.eqToDirichletIndex(eqIdx);
+                        assert(0 <= pvIdx && pvIdx < numEq);
+                        Valgrind::CheckDefined(dirichletValues[pvIdx]);
+
+                        residual_[scvIdx][eqIdx] =
+                                curPriVar_(scvIdx, pvIdx) - dirichletValues[pvIdx];
+
+                        storageTerm_[scvIdx][eqIdx] = 0.0;
+                    }
+                }
+            }
+        }
+    }
+
+    /*!
+     * \brief Add all Neumann and outflow boundary conditions to the local
+     *        residual.
+     */
+    void evalBoundaryFluxes_()
+    {
+        Dune::GeometryType geoType = element_().geometry().type();
+        const ReferenceElement &refElement = ReferenceElements::general(geoType);
+
+        IntersectionIterator isIt = gridView_().ibegin(element_());
+        const IntersectionIterator &endIt = gridView_().iend(element_());
+        for (; isIt != endIt; ++isIt)
+        {
+            // handle only faces on the boundary
+            if (isIt->boundary()) {
+                // Assemble the boundary for all vertices of the current
+                // face
+                int faceIdx = isIt->indexInInside();
+                int numFaceVerts = refElement.size(faceIdx, 1, dim);
+                for (int faceVertIdx = 0;
+                    faceVertIdx < numFaceVerts;
+                    ++faceVertIdx)
+                {
+                    int scvIdx = refElement.subEntity(faceIdx,
+                                                        1,
+                                                        faceVertIdx,
+                                                        dim);
+
+                    int boundaryFaceIdx =
+                        fvGeometry_().boundaryFaceIndex(faceIdx, faceVertIdx);
+
+                    // add the residual of all vertices of the boundary
+                    // segment
+                    asImp_().evalNeumannSegment_(isIt,
+                                                scvIdx,
+                                                boundaryFaceIdx);
+                    // evaluate the outflow conditions at the boundary face
+                    // ATTENTION: This is so far a beta version that is only for the 2p2c and 2p2cni model
+                    //              available and not thoroughly tested.
+                    asImp_().evalOutflowSegment_(isIt,
+                                                scvIdx,
+                                                boundaryFaceIdx);
+                }
+            }
+        }
+    }
+
+    /*!
+     * \brief Add Neumann boundary conditions for a single sub-control
+     *        volume face to the local residual.
+     */
+    void evalNeumannSegment_(const IntersectionIterator &isIt,
+                             const int scvIdx,
+                             const int boundaryFaceIdx)
+    {
+        // temporary vector to store the neumann boundary fluxes
+        PrimaryVariables neumannFlux(0.0);
+        const BoundaryTypes &bcTypes = bcTypes_(scvIdx);
+
+        // deal with neumann boundaries
+        if (bcTypes.hasNeumann()) {
+            Valgrind::SetUndefined(neumannFlux);
+            problem_().boxSDNeumann(neumannFlux,
+                                    element_(),
+                                    fvGeometry_(),
+                                    *isIt,
+                                    scvIdx,
+                                    boundaryFaceIdx,
+                                    curVolVars_());
+            neumannFlux *=
+                fvGeometry_().boundaryFace[boundaryFaceIdx].area
+                * curVolVars_(scvIdx).extrusionFactor();
+            Valgrind::CheckDefined(neumannFlux);
+
+            // set the neumann conditions
+            for (int eqIdx = 0; eqIdx < numEq; ++eqIdx) {
+                if (!bcTypes.isNeumann(eqIdx))
+                    continue;
+                residual_[scvIdx][eqIdx] += neumannFlux[eqIdx];
+            }
+        }
+    }
+
+    /*!
+    * \brief Add outflow boundary conditions for a single sub-control
+    *        volume face to the local residual.
+    *
+    * \param isIt   The intersection iterator of current element
+    * \param scvIdx The index of the considered face of the sub-control volume
+    * \param boundaryFaceIdx The index of the considered boundary face of the sub control volume
+    */
+    void evalOutflowSegment_(const IntersectionIterator &isIt,
+                            const int scvIdx,
+                            const int boundaryFaceIdx)
+    {
+        const BoundaryTypes &bcTypes = this->bcTypes_(scvIdx);
+        // deal with outflow boundaries
+        if (bcTypes.hasOutflow())
+        {
+            //calculate outflow fluxes
+            PrimaryVariables values(0.0);
+            asImp_().computeFlux(values, boundaryFaceIdx, true);
+            Valgrind::CheckDefined(values);
+            
+            for (int equationIdx = 0; equationIdx < numEq; ++equationIdx)
+            {
+                if (!bcTypes.isOutflow(equationIdx) )
+                    continue;
+                // deduce outflow
+                this->residual_[scvIdx][equationIdx] += values[equationIdx];
+            }
+        }
+    }
+
+    /*!
+     * \brief Add the flux terms to the local residual of all
+     *        sub-control volumes of the current element.
+     */
+    void evalFluxes_()
+    {
+        // calculate the mass flux over the faces and subtract
+        // it from the local rates
+        for (int scvfIdx = 0; scvfIdx < fvGeometry_().numEdges; scvfIdx++)
+        {
+            int i = fvGeometry_().subContVolFace[scvfIdx].i;
+            int j = fvGeometry_().subContVolFace[scvfIdx].j;
+
+            PrimaryVariables flux;
+
+            Valgrind::SetUndefined(flux);
+            asImp_().computeFlux(flux, scvfIdx);
+            Valgrind::CheckDefined(flux);
+
+            Scalar extrusionFactor =
+                (curVolVars_(i).extrusionFactor()
+                 + curVolVars_(j).extrusionFactor())
+                / 2;
+            flux *= extrusionFactor;
+
+            // The balance equation for a finite volume is:
+            //
+            // dStorage/dt = Flux + Source
+            //
+            // where the 'Flux' and the 'Source' terms represent the
+            // mass per second which _ENTER_ the finite
+            // volume. Re-arranging this, we get
+            //
+            // dStorage/dt - Source - Flux = 0
+            //
+            // Since the flux calculated by computeFlux() goes _OUT_
+            // of sub-control volume i and _INTO_ sub-control volume
+            // j, we need to add the flux to finite volume i and
+            // subtract it from finite volume j
+            residual_[i] += flux;
+            residual_[j] -= flux;
+        }
+    }
+
+    /*!
+     * \brief Set the local residual to the storage terms of all
+     *        sub-control volumes of the current element.
+     */
+    void evalStorage_()
+    {
+        storageTerm_.resize(fvGeometry_().numVertices);
+        storageTerm_ = 0;
+
+        // calculate the amount of conservation each quantity inside
+        // all sub control volumes
+        for (int scvIdx = 0; scvIdx < fvGeometry_().numVertices; scvIdx++) {
+            Valgrind::SetUndefined(storageTerm_[scvIdx]);
+            asImp_().computeStorage(storageTerm_[scvIdx], scvIdx, /*isOldSol=*/false);
+            storageTerm_[scvIdx] *=
+                fvGeometry_().subContVol[scvIdx].volume
+                * curVolVars_(scvIdx).extrusionFactor();
+            Valgrind::CheckDefined(storageTerm_[scvIdx]);
+        }
+    }
+
+    /*!
+     * \brief Add the change in the storage terms and the source term
+     *        to the local residual of all sub-control volumes of the
+     *        current element.
+     */
+    void evalVolumeTerms_()
+    {
+        // evaluate the volume terms (storage + source terms)
+        for (int scvIdx = 0; scvIdx < fvGeometry_().numVertices; scvIdx++)
+        {
+            Scalar extrusionFactor =
+                curVolVars_(scvIdx).extrusionFactor();
+
+            PrimaryVariables values(0.0);
+
+            // mass balance within the element. this is the
+            // \f$\frac{m}{\partial t}\f$ term if using implicit
+            // euler as time discretization.
+            //
+            // TODO (?): we might need a more explicit way for
+            // doing the time discretization...
+            Valgrind::SetUndefined(storageTerm_[scvIdx]);
+            Valgrind::SetUndefined(values);
+            asImp_().computeStorage(storageTerm_[scvIdx], scvIdx, false);
+            asImp_().computeStorage(values, scvIdx, true);
+            Valgrind::CheckDefined(storageTerm_[scvIdx]);
+            Valgrind::CheckDefined(values);
+
+            storageTerm_[scvIdx] -= values;
+            storageTerm_[scvIdx] *=
+                fvGeometry_().subContVol[scvIdx].volume
+                / problem_().timeManager().timeStepSize()
+                * extrusionFactor;
+            residual_[scvIdx] += storageTerm_[scvIdx];
+
+            // subtract the source term from the local rate
+            Valgrind::SetUndefined(values);
+            asImp_().computeSource(values, scvIdx);
+            Valgrind::CheckDefined(values);
+            values *= fvGeometry_().subContVol[scvIdx].volume * extrusionFactor;
+            residual_[scvIdx] -= values;
+
+            // make sure that only defined quantities were used
+            // to calculate the residual.
+            Valgrind::CheckDefined(residual_[scvIdx]);
+        }
+    }
+
+    /*!
+     * \brief Returns a reference to the problem.
+     */
+    const Problem &problem_() const
+    { return *problemPtr_; };
+
+    /*!
+     * \brief Returns a reference to the model.
+     */
+    const Model &model_() const
+    { return problem_().model(); };
+
+    /*!
+     * \brief Returns a reference to the vertex mapper.
+     */
+    const VertexMapper &vertexMapper_() const
+    { return problem_().vertexMapper(); };
+
+    /*!
+     * \brief Returns a reference to the grid view.
+     */
+    const GridView &gridView_() const
+    { return problem_().gridView(); }
+
+    /*!
+     * \brief Returns a reference to the current element.
+     */
+    const Element &element_() const
+    {
+        Valgrind::CheckDefined(elemPtr_);
+        return *elemPtr_;
+    }
+    
+    /*!
+     * \brief Returns a reference to the current element's finite
+     *        volume geometry.
+     */
+    const FVElementGeometry &fvGeometry_() const
+    {
+        Valgrind::CheckDefined(fvElemGeomPtr_);
+        return *fvElemGeomPtr_;
+    }
+
+    /*!
+     * \brief Returns a reference to the primary variables of
+     *           the last time step of the i'th
+     *        sub-control volume of the current element.
+     */
+    const PrimaryVariables &prevPriVars_(const int i) const
+    {
+        return prevVolVars_(i).priVars();
+    }
+
+    /*!
+     * \brief Returns a reference to the primary variables of the i'th
+     *        sub-control volume of the current element.
+     */
+    const PrimaryVariables &curPriVars_(const int i) const
+    {
+        return curVolVars_(i).priVars();
+    }
+
+    /*!
+     * \brief Returns the j'th primary of the i'th sub-control volume
+     *        of the current element.
+     */
+    Scalar curPriVar_(const int i, const int j) const
+    {
+        return curVolVars_(i).priVar(j);
+    }
+
+    /*!
+     * \brief Returns a reference to the current volume variables of
+     *        all sub-control volumes of the current element.
+     */
+    const ElementVolumeVariables &curVolVars_() const
+    {
+        Valgrind::CheckDefined(curVolVarsPtr_);
+        return *curVolVarsPtr_;
+    }
+
+    /*!
+     * \brief Returns a reference to the volume variables of the i-th
+     *        sub-control volume of the current element.
+     */
+    const VolumeVariables &curVolVars_(const int i) const
+    {
+        return curVolVars_()[i];
+    }
+
+    /*!
+     * \brief Returns a reference to the previous time step's volume
+     *        variables of all sub-control volumes of the current
+     *        element.
+     */
+    const ElementVolumeVariables &prevVolVars_() const
+    {
+        Valgrind::CheckDefined(prevVolVarsPtr_);
+        return *prevVolVarsPtr_;
+    }
+
+    /*!
+     * \brief Returns a reference to the previous time step's volume
+     *        variables of the i-th sub-control volume of the current
+     *        element.
+     */
+    const VolumeVariables &prevVolVars_(const int i) const
+    {
+        return prevVolVars_()[i];
+    }
+
+    /*!
+     * \brief Returns a reference to the boundary types of all
+     *        sub-control volumes of the current element.
+     */
+    const ElementBoundaryTypes &bcTypes_() const
+    {
+        Valgrind::CheckDefined(bcTypesPtr_);
+        return *bcTypesPtr_;
+    }
+
+    /*!
+     * \brief Returns a reference to the boundary types of the i-th
+     *        sub-control volume of the current element.
+     */
+    const BoundaryTypes &bcTypes_(const int i) const
+    {
+        return bcTypes_()[i];
+    }
+
+protected:
+    ElementSolutionVector storageTerm_;
+    ElementSolutionVector residual_;
+
+    // The problem we would like to solve
+    Problem *problemPtr_;
+
+    const Element *elemPtr_;
+    const FVElementGeometry *fvElemGeomPtr_;
+
+    // current and previous secondary variables for the element
+    const ElementVolumeVariables *prevVolVarsPtr_;
+    const ElementVolumeVariables *curVolVarsPtr_;
+
+    const ElementBoundaryTypes *bcTypesPtr_;
+};
+
+}
+
+#endif
diff --git a/dumux/implicit/box/boxmodel.hh b/dumux/implicit/box/boxmodel.hh
new file mode 100644
index 0000000000..567d706dd7
--- /dev/null
+++ b/dumux/implicit/box/boxmodel.hh
@@ -0,0 +1,927 @@
+// -*- mode: C++; tab-width: 4; indent-tabs-mode: nil; c-basic-offset: 4 -*-
+// vi: set et ts=4 sw=4 sts=4:
+/*****************************************************************************
+ *   See the file COPYING for full copying permissions.                      *
+ *                                                                           *
+ *   This program is free software: you can redistribute it and/or modify    *
+ *   it under the terms of the GNU General Public License as published by    *
+ *   the Free Software Foundation, either version 2 of the License, or       *
+ *   (at your option) any later version.                                     *
+ *                                                                           *
+ *   This program is distributed in the hope that it will be useful,         *
+ *   but WITHOUT ANY WARRANTY; without even the implied warranty of          *
+ *   MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the            *
+ *   GNU General Public License for more details.                            *
+ *                                                                           *
+ *   You should have received a copy of the GNU General Public License       *
+ *   along with this program.  If not, see <http://www.gnu.org/licenses/>.   *
+ *****************************************************************************/
+/*!
+ * \file
+ *
+ * \brief Base class for models using box discretization
+ */
+#ifndef DUMUX_BOX_MODEL_HH
+#define DUMUX_BOX_MODEL_HH
+
+#include "boxproperties.hh"
+#include "boxpropertydefaults.hh"
+
+#include "boxelementvolumevariables.hh"
+#include "boxlocaljacobian.hh"
+#include "boxlocalresidual.hh"
+
+#include <dumux/parallel/vertexhandles.hh>
+
+#include <dune/grid/common/geometry.hh>
+
+namespace Dumux
+{
+
+/*!
+ * \ingroup BoxModel
+ *
+ * \brief The base class for the vertex centered finite volume
+ *        discretization scheme.
+ */
+template<class TypeTag>
+class BoxModel
+{
+    typedef typename GET_PROP_TYPE(TypeTag, Model) Implementation;
+    typedef typename GET_PROP_TYPE(TypeTag, Problem) Problem;
+    typedef typename GET_PROP_TYPE(TypeTag, GridView) GridView;
+    typedef typename GET_PROP_TYPE(TypeTag, Scalar) Scalar;
+    typedef typename GET_PROP_TYPE(TypeTag, ElementMapper) ElementMapper;
+    typedef typename GET_PROP_TYPE(TypeTag, VertexMapper) VertexMapper;
+    typedef typename GET_PROP_TYPE(TypeTag, DofMapper) DofMapper;
+    typedef typename GET_PROP_TYPE(TypeTag, SolutionVector) SolutionVector;
+    typedef typename GET_PROP_TYPE(TypeTag, PrimaryVariables) PrimaryVariables;
+    typedef typename GET_PROP_TYPE(TypeTag, JacobianAssembler) JacobianAssembler;
+    typedef typename GET_PROP_TYPE(TypeTag, ElementVolumeVariables) ElementVolumeVariables;
+    typedef typename GET_PROP_TYPE(TypeTag, VolumeVariables) VolumeVariables;
+
+    enum {
+        numEq = GET_PROP_VALUE(TypeTag, NumEq),
+        dim = GridView::dimension
+    };
+
+    typedef typename GET_PROP_TYPE(TypeTag, FVElementGeometry) FVElementGeometry;
+    typedef typename GET_PROP_TYPE(TypeTag, LocalJacobian) LocalJacobian;
+    typedef typename GET_PROP_TYPE(TypeTag, LocalResidual) LocalResidual;
+    typedef typename GET_PROP_TYPE(TypeTag, NewtonMethod) NewtonMethod;
+    typedef typename GET_PROP_TYPE(TypeTag, NewtonController) NewtonController;
+
+    typedef typename GridView::ctype CoordScalar;
+    typedef typename GridView::template Codim<0>::Entity Element;
+    typedef typename GridView::template Codim<0>::Iterator ElementIterator;
+    typedef typename GridView::template Codim<dim>::Entity Vertex;
+    typedef typename GridView::template Codim<dim>::Iterator VertexIterator;
+    typedef typename GridView::IntersectionIterator IntersectionIterator;
+
+    typedef typename Dune::GenericReferenceElements<CoordScalar, dim> ReferenceElements;
+    typedef typename Dune::GenericReferenceElement<CoordScalar, dim> ReferenceElement;
+
+    // copying a model is not a good idea
+    BoxModel(const BoxModel &);
+
+public:
+    /*!
+     * \brief The constructor.
+     */
+    BoxModel()
+    {
+        enableHints_ = GET_PARAM_FROM_GROUP(TypeTag, bool, Implicit, EnableHints);
+    }
+
+    ~BoxModel()
+    { delete jacAsm_;  }
+
+    /*!
+     * \brief Apply the initial conditions to the model.
+     *
+     * \param problem The object representing the problem which needs to
+     *             be simulated.
+     */
+    void init(Problem &problem)
+    {
+        problemPtr_ = &problem;
+
+        updateBoundaryIndices_();
+
+        int nDofs = asImp_().numDofs();
+        uCur_.resize(nDofs);
+        uPrev_.resize(nDofs);
+        boxVolume_.resize(nDofs);
+
+        localJacobian_.init(problem_());
+        jacAsm_ = new JacobianAssembler();
+        jacAsm_->init(problem_());
+
+        asImp_().applyInitialSolution_();
+
+        // resize the hint vectors
+        if (enableHints_) {
+            int nVerts = gridView_().size(dim);
+            curHints_.resize(nVerts);
+            prevHints_.resize(nVerts);
+            hintsUsable_.resize(nVerts);
+            std::fill(hintsUsable_.begin(),
+                      hintsUsable_.end(),
+                      false);
+        }
+
+        // also set the solution of the "previous" time step to the
+        // initial solution.
+        uPrev_ = uCur_;
+    }
+
+    void setHints(const Element &element,
+                  ElementVolumeVariables &prevVolVars,
+                  ElementVolumeVariables &curVolVars) const
+    {
+        if (!enableHints_)
+            return;
+
+        int n = element.template count<dim>();
+        prevVolVars.resize(n);
+        curVolVars.resize(n);
+        for (int i = 0; i < n; ++i) {
+            int globalIdx = vertexMapper().map(element, i, dim);
+
+            if (!hintsUsable_[globalIdx]) {
+                curVolVars[i].setHint(NULL);
+                prevVolVars[i].setHint(NULL);
+            }
+            else {
+                curVolVars[i].setHint(&curHints_[globalIdx]);
+                prevVolVars[i].setHint(&prevHints_[globalIdx]);
+            }
+        }
+    }
+
+    void setHints(const Element &element,
+                  ElementVolumeVariables &curVolVars) const
+    {
+        if (!enableHints_)
+            return;
+
+        int n = element.template count<dim>();
+        curVolVars.resize(n);
+        for (int i = 0; i < n; ++i) {
+            int globalIdx = vertexMapper().map(element, i, dim);
+
+            if (!hintsUsable_[globalIdx])
+                curVolVars[i].setHint(NULL);
+            else
+                curVolVars[i].setHint(&curHints_[globalIdx]);
+        }
+    }
+
+    void updatePrevHints()
+    {
+        if (!enableHints_)
+            return;
+
+        prevHints_ = curHints_;
+    }
+
+    void updateCurHints(const Element &element,
+                        const ElementVolumeVariables &elemVolVars) const
+    {
+        if (!enableHints_)
+            return;
+
+        for (unsigned int i = 0; i < elemVolVars.size(); ++i) {
+            int globalIdx = vertexMapper().map(element, i, dim);
+            curHints_[globalIdx] = elemVolVars[i];
+            if (!hintsUsable_[globalIdx])
+                prevHints_[globalIdx] = elemVolVars[i];
+            hintsUsable_[globalIdx] = true;
+        }
+    }
+
+
+    /*!
+     * \brief Compute the global residual for an arbitrary solution
+     *        vector.
+     *
+     * \param residual Stores the result
+     * \param u The solution for which the residual ought to be calculated
+     */
+    Scalar globalResidual(SolutionVector &residual,
+                          const SolutionVector &u)
+    {
+        SolutionVector tmp(curSol());
+        curSol() = u;
+        Scalar res = globalResidual(residual);
+        curSol() = tmp;
+        return res;
+    }
+
+    /*!
+     * \brief Compute the global residual for the current solution
+     *        vector.
+     *
+     * \param residual Stores the result
+     */
+    Scalar globalResidual(SolutionVector &residual)
+    {
+        residual = 0;
+
+        ElementIterator elemIt = gridView_().template begin<0>();
+        const ElementIterator elemEndIt = gridView_().template end<0>();
+        for (; elemIt != elemEndIt; ++elemIt) {
+            localResidual().eval(*elemIt);
+
+            for (int i = 0; i < elemIt->template count<dim>(); ++i) {
+                int globalI = vertexMapper().map(*elemIt, i, dim);
+                residual[globalI] += localResidual().residual(i);
+            }
+        }
+
+        // calculate the square norm of the residual
+        Scalar result2 = residual.two_norm2();
+        if (gridView_().comm().size() > 1)
+            result2 = gridView_().comm().sum(result2);
+
+        // add up the residuals on the process borders
+        if (gridView_().comm().size() > 1) {
+            VertexHandleSum<PrimaryVariables, SolutionVector, VertexMapper>
+                sumHandle(residual, vertexMapper());
+            gridView_().communicate(sumHandle,
+                                    Dune::InteriorBorder_InteriorBorder_Interface,
+                                    Dune::ForwardCommunication);
+        }
+
+        return std::sqrt(result2);
+    }
+
+    /*!
+     * \brief Compute the integral over the domain of the storage
+     *        terms of all conservation quantities.
+     *
+     * \param storage Stores the result
+     */
+    void globalStorage(PrimaryVariables &storage)
+    {
+        storage = 0;
+
+        ElementIterator elemIt = gridView_().template begin<0>();
+        const ElementIterator elemEndIt = gridView_().template end<0>();
+        for (; elemIt != elemEndIt; ++elemIt) {
+            localResidual().evalStorage(*elemIt);
+
+            for (int i = 0; i < elemIt->template count<dim>(); ++i)
+                storage += localResidual().storageTerm()[i];
+        }
+
+        if (gridView_().comm().size() > 1)
+            storage = gridView_().comm().sum(storage);
+    }
+
+    /*!
+     * \brief Returns the volume \f$\mathrm{[m^3]}\f$ of a given control volume.
+     *
+     * \param globalIdx The global index of the control volume's
+     *                  associated vertex
+     */
+    Scalar boxVolume(const int globalIdx) const
+    { return boxVolume_[globalIdx][0]; }
+
+    /*!
+     * \brief Reference to the current solution as a block vector.
+     */
+    const SolutionVector &curSol() const
+    { return uCur_; }
+
+    /*!
+     * \brief Reference to the current solution as a block vector.
+     */
+    SolutionVector &curSol()
+    { return uCur_; }
+
+    /*!
+     * \brief Reference to the previous solution as a block vector.
+     */
+    const SolutionVector &prevSol() const
+    { return uPrev_; }
+
+    /*!
+     * \brief Reference to the previous solution as a block vector.
+     */
+    SolutionVector &prevSol()
+    { return uPrev_; }
+
+    /*!
+     * \brief Returns the operator assembler for the global jacobian of
+     *        the problem.
+     */
+    JacobianAssembler &jacobianAssembler()
+    { return *jacAsm_; }
+
+    /*!
+     * \copydoc jacobianAssembler()
+     */
+    const JacobianAssembler &jacobianAssembler() const
+    { return *jacAsm_; }
+
+    /*!
+     * \brief Returns the local jacobian which calculates the local
+     *        stiffness matrix for an arbitrary element.
+     *
+     * The local stiffness matrices of the element are used by
+     * the jacobian assembler to produce a global linerization of the
+     * problem.
+     */
+    LocalJacobian &localJacobian()
+    { return localJacobian_; }
+    /*!
+     * \copydoc localJacobian()
+     */
+    const LocalJacobian &localJacobian() const
+    { return localJacobian_; }
+
+    /*!
+     * \brief Returns the local residual function.
+     */
+    LocalResidual &localResidual()
+    { return localJacobian().localResidual(); }
+    /*!
+     * \copydoc localResidual()
+     */
+    const LocalResidual &localResidual() const
+    { return localJacobian().localResidual(); }
+
+    /*!
+     * \brief Returns the relative error between two vectors of
+     *        primary variables.
+     *
+     * \param vertexIdx The global index of the control volume's
+     *                  associated vertex
+     * \param priVars1 The first vector of primary variables
+     * \param priVars2 The second vector of primary variables
+     *
+     * \todo The vertexIdx argument is pretty hacky. it is required by
+     *       models with pseudo primary variables (i.e. the primary
+     *       variable switching models). the clean solution would be
+     *       to access the pseudo primary variables from the primary
+     *       variables.
+     */
+    Scalar relativeErrorVertex(const int vertexIdx,
+                               const PrimaryVariables &priVars1,
+                               const PrimaryVariables &priVars2)
+    {
+        Scalar result = 0.0;
+        for (int j = 0; j < numEq; ++j) {
+            Scalar eqErr = std::abs(priVars1[j] - priVars2[j]);
+            eqErr /= std::max<Scalar>(1.0, std::abs(priVars1[j] + priVars2[j])/2);
+
+            result = std::max(result, eqErr);
+        }
+        return result;
+    }
+
+    /*!
+     * \brief Try to progress the model to the next timestep.
+     *
+     * \param solver The non-linear solver
+     * \param controller The controller which specifies the behaviour
+     *                   of the non-linear solver
+     */
+    bool update(NewtonMethod &solver,
+                NewtonController &controller)
+    {
+#if HAVE_VALGRIND
+        for (size_t i = 0; i < curSol().size(); ++i)
+            Valgrind::CheckDefined(curSol()[i]);
+#endif // HAVE_VALGRIND
+
+        asImp_().updateBegin();
+
+        bool converged = solver.execute(controller);
+        if (converged) {
+            asImp_().updateSuccessful();
+        }
+        else
+            asImp_().updateFailed();
+
+#if HAVE_VALGRIND
+        for (size_t i = 0; i < curSol().size(); ++i) {
+            Valgrind::CheckDefined(curSol()[i]);
+        }
+#endif // HAVE_VALGRIND
+
+        return converged;
+    }
+
+
+    /*!
+     * \brief Called by the update() method before it tries to
+     *        apply the newton method. This is primary a hook
+     *        which the actual model can overload.
+     */
+    void updateBegin()
+    { }
+
+
+    /*!
+     * \brief Called by the update() method if it was
+     *        successful. This is primary a hook which the actual
+     *        model can overload.
+     */
+    void updateSuccessful()
+    { }
+
+    /*!
+     * \brief Called by the update() method if it was
+     *        unsuccessful. This is primary a hook which the actual
+     *        model can overload.
+     */
+    void updateFailed()
+    {
+        // Reset the current solution to the one of the
+        // previous time step so that we can start the next
+        // update at a physically meaningful solution.
+        uCur_ = uPrev_;
+        curHints_ = prevHints_;
+
+        jacAsm_->reassembleAll();
+    }
+
+    /*!
+     * \brief Called by the problem if a time integration was
+     *        successful, post processing of the solution is done and
+     *        the result has been written to disk.
+     *
+     * This should prepare the model for the next time integration.
+     */
+    void advanceTimeLevel()
+    {
+        // make the current solution the previous one.
+        uPrev_ = uCur_;
+        prevHints_ = curHints_;
+
+        updatePrevHints();
+    }
+
+    /*!
+     * \brief Serializes the current state of the model.
+     *
+     * \tparam Restarter The type of the serializer class
+     *
+     * \param res The serializer object
+     */
+    template <class Restarter>
+    void serialize(Restarter &res)
+    { res.template serializeEntities<dim>(asImp_(), this->gridView_()); }
+
+    /*!
+     * \brief Deserializes the state of the model.
+     *
+     * \tparam Restarter The type of the serializer class
+     *
+     * \param res The serializer object
+     */
+    template <class Restarter>
+    void deserialize(Restarter &res)
+    {
+        res.template deserializeEntities<dim>(asImp_(), this->gridView_());
+        prevSol() = curSol();
+    }
+
+    /*!
+     * \brief Write the current solution for a vertex to a restart
+     *        file.
+     *
+     * \param outstream The stream into which the vertex data should
+     *                  be serialized to
+     * \param vertex The DUNE Codim<dim> entity which's data should be
+     *             serialized
+     */
+    void serializeEntity(std::ostream &outstream,
+                         const Vertex &vertex)
+    {
+        int vertIdx = dofMapper().map(vertex);
+
+        // write phase state
+        if (!outstream.good()) {
+            DUNE_THROW(Dune::IOError,
+                       "Could not serialize vertex "
+                       << vertIdx);
+        }
+
+        for (int eqIdx = 0; eqIdx < numEq; ++eqIdx) {
+            outstream << curSol()[vertIdx][eqIdx] << " ";
+        }
+    }
+
+    /*!
+     * \brief Reads the current solution variables for a vertex from a
+     *        restart file.
+     *
+     * \param instream The stream from which the vertex data should
+     *                  be deserialized from
+     * \param vertex The DUNE Codim<dim> entity which's data should be
+     *             deserialized
+     */
+    void deserializeEntity(std::istream &instream,
+                           const Vertex &vertex)
+    {
+        int vertIdx = dofMapper().map(vertex);
+        for (int eqIdx = 0; eqIdx < numEq; ++eqIdx) {
+            if (!instream.good())
+                DUNE_THROW(Dune::IOError,
+                           "Could not deserialize vertex "
+                           << vertIdx);
+            instream >> curSol()[vertIdx][eqIdx];
+        }
+    }
+
+    /*!
+     * \brief Returns the number of global degrees of freedoms (DOFs)
+     */
+    size_t numDofs() const
+    { return gridView_().size(dim); }
+
+    /*!
+     * \brief Mapper for the entities where degrees of freedoms are
+     *        defined to indices.
+     *
+     * This usually means a mapper for vertices.
+     */
+    const DofMapper &dofMapper() const
+    { return problem_().vertexMapper(); }
+
+    /*!
+     * \brief Mapper for vertices to indices.
+     */
+    const VertexMapper &vertexMapper() const
+    { return problem_().vertexMapper(); }
+
+    /*!
+     * \brief Mapper for elements to indices.
+     */
+    const ElementMapper &elementMapper() const
+    { return problem_().elementMapper(); }
+
+    /*!
+     * \brief Resets the Jacobian matrix assembler, so that the
+     *        boundary types can be altered.
+     */
+    void resetJacobianAssembler ()
+    {
+        delete jacAsm_;
+        jacAsm_ = new JacobianAssembler;
+        jacAsm_->init(problem_());
+    }
+
+    /*!
+     * \brief Update the weights of all primary variables within an
+     *        element given the complete set of volume variables
+     *
+     * \param element The DUNE codim 0 entity
+     * \param volVars All volume variables for the element
+     */
+    void updatePVWeights(const Element &element,
+                         const ElementVolumeVariables &volVars) const
+    { }
+
+    /*!
+     * \brief Add the vector fields for analysing the convergence of
+     *        the newton method to the a VTK multi writer.
+     *
+     * \tparam MultiWriter The type of the VTK multi writer
+     *
+     * \param writer  The VTK multi writer object on which the fields should be added.
+     * \param u       The solution function
+     * \param deltaU  The delta of the solution function before and after the Newton update
+     */
+    template <class MultiWriter>
+    void addConvergenceVtkFields(MultiWriter &writer,
+                                 const SolutionVector &u,
+                                 const SolutionVector &deltaU)
+    {
+        typedef Dune::BlockVector<Dune::FieldVector<double, 1> > ScalarField;
+
+        SolutionVector residual(u);
+        asImp_().globalResidual(residual, u);
+
+        // create the required scalar fields
+        unsigned numVertices = this->gridView_().size(dim);
+
+        // global defect of the two auxiliary equations
+        ScalarField* def[numEq];
+        ScalarField* delta[numEq];
+        ScalarField* x[numEq];
+        for (int eqIdx = 0; eqIdx < numEq; ++eqIdx) {
+            x[eqIdx] = writer.allocateManagedBuffer(numVertices);
+            delta[eqIdx] = writer.allocateManagedBuffer(numVertices);
+            def[eqIdx] = writer.allocateManagedBuffer(numVertices);
+        }
+
+        VertexIterator vIt = this->gridView_().template begin<dim>();
+        VertexIterator vEndIt = this->gridView_().template end<dim>();
+        for (; vIt != vEndIt; ++ vIt)
+        {
+            int globalIdx = vertexMapper().map(*vIt);
+            for (int eqIdx = 0; eqIdx < numEq; ++eqIdx) {
+                (*x[eqIdx])[globalIdx] = u[globalIdx][eqIdx];
+                (*delta[eqIdx])[globalIdx] = - deltaU[globalIdx][eqIdx];
+                (*def[eqIdx])[globalIdx] = residual[globalIdx][eqIdx];
+            }
+        }
+
+        for (int eqIdx = 0; eqIdx < numEq; ++eqIdx) {
+            std::ostringstream oss;
+            oss.str(""); oss << "x_" << eqIdx;
+            writer.attachVertexData(*x[eqIdx], oss.str());
+            oss.str(""); oss << "delta_" << eqIdx;
+            writer.attachVertexData(*delta[eqIdx], oss.str());
+            oss.str(""); oss << "defect_" << eqIdx;
+            writer.attachVertexData(*def[eqIdx], oss.str());
+        }
+
+        asImp_().addOutputVtkFields(u, writer);
+    }
+
+    /*!
+     * \brief Add the quantities of a time step which ought to be written to disk.
+     *
+     * This should be overwritten by the actual model if any secondary
+     * variables should be written out. Read: This should _always_ be
+     * overwritten by well behaved models!
+     *
+     * \tparam MultiWriter The type of the VTK multi writer
+     *
+     * \param sol The global vector of primary variable values.
+     * \param writer The VTK multi writer where the fields should be added.
+     */
+    template <class MultiWriter>
+    void addOutputVtkFields(const SolutionVector &sol,
+                            MultiWriter &writer)
+    {
+        typedef Dune::BlockVector<Dune::FieldVector<Scalar, 1> > ScalarField;
+
+        // create the required scalar fields
+        unsigned numVertices = this->gridView_().size(dim);
+
+        // global defect of the two auxiliary equations
+        ScalarField* x[numEq];
+        for (int eqIdx = 0; eqIdx < numEq; ++eqIdx) {
+            x[eqIdx] = writer.allocateManagedBuffer(numVertices);
+        }
+
+        VertexIterator vIt = this->gridView_().template begin<dim>();
+        VertexIterator vEndIt = this->gridView_().template end<dim>();
+        for (; vIt != vEndIt; ++ vIt)
+        {
+            int globalIdx = vertexMapper().map(*vIt);
+            for (int eqIdx = 0; eqIdx < numEq; ++eqIdx) {
+                (*x[eqIdx])[globalIdx] = sol[globalIdx][eqIdx];
+            }
+        }
+
+        for (int eqIdx = 0; eqIdx < numEq; ++eqIdx) {
+            std::ostringstream oss;
+            oss << "primaryVar_" << eqIdx;
+            writer.attachVertexData(*x[eqIdx], oss.str());
+        }
+    }
+
+    /*!
+     * \brief Reference to the grid view of the spatial domain.
+     */
+    const GridView &gridView() const
+    { return problem_().gridView(); }
+
+    /*!
+     * \brief Returns true if the vertex with 'globalVertIdx' is
+     *        located on the grid's boundary.
+     *
+     * \param globalVertIdx The global index of the control volume's
+     *                      associated vertex
+     */
+    bool onBoundary(const int globalVertIdx) const
+    { return boundaryIndices_[globalVertIdx]; }
+
+    /*!
+     * \brief Returns true if a vertex is located on the grid's
+     *        boundary.
+     *
+     * \param element A DUNE Codim<0> entity which contains the control
+     *             volume's associated vertex.
+     * \param vIdx The local vertex index inside element
+     */
+    bool onBoundary(const Element &element, const int vIdx) const
+    { return onBoundary(vertexMapper().map(element, vIdx, dim)); }
+
+    /*!
+     * \brief Fill the fluid state according to the primary variables. 
+     * 
+     * Taking the information from the primary variables, 
+     * the fluid state is filled with every information that is 
+     * necessary to evaluate the model's local residual. 
+     * 
+     * \param priVars The primary variables of the model.
+     * \param problem The problem at hand. 
+     * \param element The current element. 
+     * \param fvGeometry The finite volume element geometry.
+     * \param scvIdx The index of the subcontrol volume. 
+     * \param fluidState The fluid state to fill. 
+     */
+    template <class FluidState>
+    static void completeFluidState(const PrimaryVariables& priVars,
+                                   const Problem& problem,
+                                   const Element& element,
+                                   const FVElementGeometry& fvGeometry,
+                                   const int scvIdx,
+                                   FluidState& fluidState)
+    {
+        VolumeVariables::completeFluidState(priVars, problem, element,
+                                            fvGeometry, scvIdx, fluidState);
+    }
+protected:
+    /*!
+     * \brief A reference to the problem on which the model is applied.
+     */
+    Problem &problem_()
+    { return *problemPtr_; }
+    /*!
+     * \copydoc problem_()
+     */
+    const Problem &problem_() const
+    { return *problemPtr_; }
+
+    /*!
+     * \brief Reference to the grid view of the spatial domain.
+     */
+    const GridView &gridView_() const
+    { return problem_().gridView(); }
+
+    /*!
+     * \brief Reference to the local residal object
+     */
+    LocalResidual &localResidual_()
+    { return localJacobian_.localResidual(); }
+
+    /*!
+     * \brief Applies the initial solution for all vertices of the grid.
+     */
+    void applyInitialSolution_()
+    {
+        // first set the whole domain to zero
+        uCur_ = Scalar(0.0);
+        boxVolume_ = Scalar(0.0);
+
+        FVElementGeometry fvGeometry;
+
+        // iterate through leaf grid and evaluate initial
+        // condition at the center of each sub control volume
+        //
+        // TODO: the initial condition needs to be unique for
+        // each vertex. we should think about the API...
+        ElementIterator eIt = gridView_().template begin<0>();
+        const ElementIterator &eEndIt = gridView_().template end<0>();
+        for (; eIt != eEndIt; ++eIt) {
+            // deal with the current element
+            fvGeometry.update(gridView_(), *eIt);
+
+            // loop over all element vertices, i.e. sub control volumes
+            for (int scvIdx = 0; scvIdx < fvGeometry.numVertices; scvIdx++)
+            {
+                // map the local vertex index to the global one
+                int globalIdx = vertexMapper().map(*eIt,
+                                                   scvIdx,
+                                                   dim);
+
+                // let the problem do the dirty work of nailing down
+                // the initial solution.
+                PrimaryVariables initPriVars;
+                Valgrind::SetUndefined(initPriVars);
+                problem_().initial(initPriVars,
+                                   *eIt,
+                                   fvGeometry,
+                                   scvIdx);
+                Valgrind::CheckDefined(initPriVars);
+
+                // add up the initial values of all sub-control
+                // volumes. If the initial values disagree for
+                // different sub control volumes, the initial value
+                // will be the arithmetic mean.
+                initPriVars *= fvGeometry.subContVol[scvIdx].volume;
+                boxVolume_[globalIdx] += fvGeometry.subContVol[scvIdx].volume;
+                uCur_[globalIdx] += initPriVars;
+                Valgrind::CheckDefined(uCur_[globalIdx]);
+            }
+        }
+
+        // add up the primary variables and the volumes of the boxes
+        // which cross process borders
+        if (gridView_().comm().size() > 1) {
+            VertexHandleSum<Dune::FieldVector<Scalar, 1>,
+                Dune::BlockVector<Dune::FieldVector<Scalar, 1> >,
+                VertexMapper> sumVolumeHandle(boxVolume_, vertexMapper());
+            gridView_().communicate(sumVolumeHandle,
+                                    Dune::InteriorBorder_InteriorBorder_Interface,
+                                    Dune::ForwardCommunication);
+
+            VertexHandleSum<PrimaryVariables, SolutionVector, VertexMapper>
+                sumPVHandle(uCur_, vertexMapper());
+            gridView_().communicate(sumPVHandle,
+                                    Dune::InteriorBorder_InteriorBorder_Interface,
+                                    Dune::ForwardCommunication);
+        }
+
+        // divide all primary variables by the volume of their boxes
+        int n = gridView_().size(dim);
+        for (int i = 0; i < n; ++i) {
+            uCur_[i] /= boxVolume(i);
+        }
+    }
+
+    /*!
+     * \brief Find all indices of boundary vertices.
+     *
+     * For this we need to loop over all intersections (which is slow
+     * in general). If the DUNE grid interface would provide a
+     * onBoundary() method for entities this could be done in a much
+     * nicer way (actually this would not be necessary)
+     */
+    void updateBoundaryIndices_()
+    {
+        boundaryIndices_.resize(numDofs());
+        std::fill(boundaryIndices_.begin(), boundaryIndices_.end(), false);
+
+        ElementIterator eIt = gridView_().template begin<0>();
+        ElementIterator eEndIt = gridView_().template end<0>();
+        for (; eIt != eEndIt; ++eIt) {
+            Dune::GeometryType geoType = eIt->geometry().type();
+            const ReferenceElement &refElement = ReferenceElements::general(geoType);
+
+            IntersectionIterator isIt = gridView_().ibegin(*eIt);
+            IntersectionIterator isEndIt = gridView_().iend(*eIt);
+            for (; isIt != isEndIt; ++isIt) {
+                if (isIt->boundary()) {
+                    // add all vertices on the intersection to the set of
+                    // boundary vertices
+                    int faceIdx = isIt->indexInInside();
+                    int numFaceVerts = refElement.size(faceIdx, 1, dim);
+                    for (int faceVertIdx = 0;
+                        faceVertIdx < numFaceVerts;
+                        ++faceVertIdx)
+                    {
+                        int elemVertIdx = refElement.subEntity(faceIdx,
+                                                            1,
+                                                            faceVertIdx,
+                                                            dim);
+                        int globalVertIdx = vertexMapper().map(*eIt, elemVertIdx, dim);
+                        boundaryIndices_[globalVertIdx] = true;
+                    }
+                }
+            }
+        }
+    }
+
+    // the hint cache for the previous and the current volume
+    // variables
+    mutable std::vector<bool> hintsUsable_;
+    mutable std::vector<VolumeVariables> curHints_;
+    mutable std::vector<VolumeVariables> prevHints_;
+
+    // the problem we want to solve. defines the constitutive
+    // relations, matxerial laws, etc.
+    Problem *problemPtr_;
+
+    // calculates the local jacobian matrix for a given element
+    LocalJacobian localJacobian_;
+    // Linearizes the problem at the current time step using the
+    // local jacobian
+    JacobianAssembler *jacAsm_;
+
+    // the set of all indices of vertices on the boundary
+    std::vector<bool> boundaryIndices_;
+
+    // cur is the current iterative solution, prev the converged
+    // solution of the previous time step
+    SolutionVector uCur_;
+    SolutionVector uPrev_;
+
+    Dune::BlockVector<Dune::FieldVector<Scalar, 1> > boxVolume_;
+
+private:
+    /*!
+     * \brief Returns whether messages should be printed
+     */
+    bool verbose_() const
+    { return gridView_().comm().rank() == 0; }
+
+    Implementation &asImp_()
+    { return *static_cast<Implementation*>(this); }
+    const Implementation &asImp_() const
+    { return *static_cast<const Implementation*>(this); }
+
+    bool enableHints_;
+};
+}
+
+#endif
diff --git a/dumux/implicit/box/boxproblem.hh b/dumux/implicit/box/boxproblem.hh
new file mode 100644
index 0000000000..c455443807
--- /dev/null
+++ b/dumux/implicit/box/boxproblem.hh
@@ -0,0 +1,835 @@
+// -*- mode: C++; tab-width: 4; indent-tabs-mode: nil; c-basic-offset: 4 -*-
+// vi: set et ts=4 sw=4 sts=4:
+/*****************************************************************************
+ *   See the file COPYING for full copying permissions.                      *
+ *                                                                           *
+ *   This program is free software: you can redistribute it and/or modify    *
+ *   it under the terms of the GNU General Public License as published by    *
+ *   the Free Software Foundation, either version 2 of the License, or       *
+ *   (at your option) any later version.                                     *
+ *                                                                           *
+ *   This program is distributed in the hope that it will be useful,         *
+ *   but WITHOUT ANY WARRANTY; without even the implied warranty of          *
+ *   MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the            *
+ *   GNU General Public License for more details.                            *
+ *                                                                           *
+ *   You should have received a copy of the GNU General Public License       *
+ *   along with this program.  If not, see <http://www.gnu.org/licenses/>.   *
+ *****************************************************************************/
+/*!
+ * \file
+ * \brief Base class for all problems which use the box scheme
+ */
+#ifndef DUMUX_BOX_PROBLEM_HH
+#define DUMUX_BOX_PROBLEM_HH
+
+#include "boxproperties.hh"
+
+#include <dumux/io/vtkmultiwriter.hh>
+#include <dumux/io/restart.hh>
+
+namespace Dumux
+{
+/*!
+ * \ingroup BoxModel
+ * \ingroup BoxBaseProblems
+ * \brief Base class for all problems which use the box scheme.
+ *
+ * \note All quantities are specified assuming a threedimensional
+ *       world. Problems discretized using 2D grids are assumed to be
+ *       extruded by \f$1 m\f$ and 1D grids are assumed to have a
+ *       cross section of \f$1m \times 1m\f$.
+ */
+template<class TypeTag>
+class BoxProblem
+{
+private:
+    typedef typename GET_PROP_TYPE(TypeTag, Problem) Implementation;
+    typedef typename GET_PROP_TYPE(TypeTag, GridView) GridView;
+
+    typedef Dumux::VtkMultiWriter<GridView> VtkMultiWriter;
+
+    typedef typename GET_PROP_TYPE(TypeTag, NewtonMethod) NewtonMethod;
+    typedef typename GET_PROP_TYPE(TypeTag, NewtonController) NewtonController;
+
+    typedef typename GET_PROP_TYPE(TypeTag, Model) Model;
+    typedef typename GET_PROP_TYPE(TypeTag, Scalar) Scalar;
+    typedef typename GET_PROP_TYPE(TypeTag, TimeManager) TimeManager;
+
+    typedef typename GET_PROP_TYPE(TypeTag, VertexMapper) VertexMapper;
+    typedef typename GET_PROP_TYPE(TypeTag, ElementMapper) ElementMapper;
+
+    typedef typename GET_PROP_TYPE(TypeTag, PrimaryVariables) PrimaryVariables;
+    typedef typename GET_PROP_TYPE(TypeTag, ElementVolumeVariables) ElementVolumeVariables;
+    typedef typename GET_PROP_TYPE(TypeTag, FVElementGeometry) FVElementGeometry;
+    typedef typename GET_PROP_TYPE(TypeTag, BoundaryTypes) BoundaryTypes;
+
+    enum {
+        dim = GridView::dimension,
+        dimWorld = GridView::dimensionworld
+    };
+
+    typedef typename GridView::template Codim<0>::Entity Element;
+    typedef typename GridView::template Codim<dim>::Entity Vertex;
+    typedef typename GridView::template Codim<dim>::Iterator VertexIterator;
+    typedef typename GridView::Intersection Intersection;
+
+    typedef typename GridView::Grid::ctype CoordScalar;
+    typedef Dune::FieldVector<CoordScalar, dimWorld> GlobalPosition;
+
+    // copying a problem is not a good idea
+    BoxProblem(const BoxProblem &);
+
+public:
+    /*!
+     * \brief Constructor
+     *
+     * \param timeManager The TimeManager which is used by the simulation
+     * \param gridView The simulation's idea about physical space
+     */
+    BoxProblem(TimeManager &timeManager, const GridView &gridView)
+        : gridView_(gridView)
+        , bboxMin_(std::numeric_limits<double>::max())
+        , bboxMax_(-std::numeric_limits<double>::max())
+        , elementMapper_(gridView)
+        , vertexMapper_(gridView)
+        , timeManager_(&timeManager)
+        , newtonMethod_(asImp_())
+        , newtonCtl_(asImp_())
+    {
+        // calculate the bounding box of the local partition of the grid view
+        VertexIterator vIt = gridView.template begin<dim>();
+        const VertexIterator vEndIt = gridView.template end<dim>();
+        for (; vIt!=vEndIt; ++vIt) {
+            for (int i=0; i<dim; i++) {
+                bboxMin_[i] = std::min(bboxMin_[i], vIt->geometry().corner(0)[i]);
+                bboxMax_[i] = std::max(bboxMax_[i], vIt->geometry().corner(0)[i]);
+            }
+        }
+
+        // communicate to get the bounding box of the whole domain
+        if (gridView.comm().size() > 1)
+            for (int i = 0; i < dim; ++i) {
+                bboxMin_[i] = gridView.comm().min(bboxMin_[i]);
+                bboxMax_[i] = gridView.comm().max(bboxMax_[i]);
+            }
+
+        // set a default name for the problem
+        simName_ = "sim";
+
+        resultWriter_ = NULL;
+    }
+
+    ~BoxProblem()
+    {
+        delete resultWriter_;
+    };
+
+
+    /*!
+     * \brief Called by the Dumux::TimeManager in order to
+     *        initialize the problem.
+     *
+     * If you overload this method don't forget to call
+     * ParentType::init()
+     */
+    void init()
+    {
+        // set the initial condition of the model
+        model().init(asImp_());
+    }
+
+    /*!
+     * \brief Specifies which kind of boundary condition should be
+     *        used for which equation on a given boundary segment.
+     *
+     * \param values The boundary types for the conservation equations
+     * \param vertex The vertex for which the boundary type is set
+     */
+    void boundaryTypes(BoundaryTypes &values,
+                       const Vertex &vertex) const
+    {
+        // forward it to the method which only takes the global coordinate
+        asImp_().boundaryTypesAtPos(values, vertex.geometry().center());
+    }
+
+    /*!
+     * \brief Specifies which kind of boundary condition should be
+     *        used for which equation on a given boundary segment.
+     *
+     * \param values The boundary types for the conservation equations
+     * \param pos The position of the finite volume in global coordinates
+     */
+    void boundaryTypesAtPos(BoundaryTypes &values,
+                            const GlobalPosition &pos) const
+    {
+        // Throw an exception (there is no reasonable default value
+        // for Dirichlet conditions)
+        DUNE_THROW(Dune::InvalidStateException,
+                   "The problem does not provide "
+                   "a boundaryTypes() method.");
+    }
+
+
+    /*!
+     * \brief Evaluate the boundary conditions for a dirichlet
+     *        control volume.
+     *
+     * \param values The dirichlet values for the primary variables
+     * \param vertex The vertex representing the "half volume on the boundary"
+     *
+     * For this method, the \a values parameter stores primary variables.
+     */
+    void dirichlet(PrimaryVariables &values,
+                   const Vertex &vertex) const
+    {
+        // forward it to the method which only takes the global coordinate
+        asImp_().dirichletAtPos(values, vertex.geometry().center());
+    }
+
+    /*!
+     * \brief Evaluate the boundary conditions for a dirichlet
+     *        control volume.
+     *
+     * \param values The dirichlet values for the primary variables
+     * \param pos The position of the center of the finite volume
+     *            for which the dirichlet condition ought to be
+     *            set in global coordinates
+     *
+     * For this method, the \a values parameter stores primary variables.
+     */
+    void dirichletAtPos(PrimaryVariables &values,
+                        const GlobalPosition &pos) const
+    {
+        // Throw an exception (there is no reasonable default value
+        // for Dirichlet conditions)
+        DUNE_THROW(Dune::InvalidStateException,
+                   "The problem specifies that some boundary "
+                   "segments are dirichlet, but does not provide "
+                   "a dirichlet() method.");
+    }
+
+    /*!
+     * \brief Evaluate the boundary conditions for a neumann
+     *        boundary segment.
+     *
+     * This is the method for the case where the Neumann condition is
+     * potentially solution dependent and requires some box method
+     * specific things.
+     *
+     * \param values The neumann values for the conservation equations [kg / (m^2 *s )]
+     * \param element The finite element
+     * \param fvGeometry The finite-volume geometry in the box scheme
+     * \param is The intersection between element and boundary
+     * \param scvIdx The local vertex index
+     * \param boundaryFaceIdx The index of the boundary face
+     * \param elemVolVars All volume variables for the element
+     *
+     * For this method, the \a values parameter stores the mass flux
+     * in normal direction of each phase. Negative values mean influx.
+     */
+    void boxSDNeumann(PrimaryVariables &values,
+                      const Element &element,
+                      const FVElementGeometry &fvGeometry,
+                      const Intersection &is,
+                      const int scvIdx,
+                      const int boundaryFaceIdx,
+                      const ElementVolumeVariables &elemVolVars) const
+    {
+        // forward it to the interface without the volume variables
+        asImp_().neumann(values,
+                         element,
+                         fvGeometry,
+                         is,
+                         scvIdx,
+                         boundaryFaceIdx);
+    }
+
+    /*!
+     * \brief Evaluate the boundary conditions for a neumann
+     *        boundary segment.
+     *
+     * \param values The neumann values for the conservation equations [kg / (m^2 *s )]
+     * \param element The finite element
+     * \param fvGeometry The finite-volume geometry in the box scheme
+     * \param is The intersection between element and boundary
+     * \param scvIdx The local vertex index
+     * \param boundaryFaceIdx The index of the boundary face
+     *
+     * For this method, the \a values parameter stores the mass flux
+     * in normal direction of each phase. Negative values mean influx.
+     */
+    void neumann(PrimaryVariables &values,
+                 const Element &element,
+                 const FVElementGeometry &fvGeometry,
+                 const Intersection &is,
+                 const int scvIdx,
+                 const int boundaryFaceIdx) const
+    {
+        // forward it to the interface with only the global position
+        asImp_().neumannAtPos(values, fvGeometry.boundaryFace[boundaryFaceIdx].ipGlobal);
+    }
+
+    /*!
+     * \brief Evaluate the boundary conditions for a neumann
+     *        boundary segment.
+     *
+     * \param values The neumann values for the conservation equations [kg / (m^2 *s )]
+     * \param pos The position of the boundary face's integration point in global coordinates
+     *
+     * For this method, the \a values parameter stores the mass flux
+     * in normal direction of each phase. Negative values mean influx.
+     */
+    void neumannAtPos(PrimaryVariables &values,
+                      const GlobalPosition &pos) const
+    {
+        // Throw an exception (there is no reasonable default value
+        // for Neumann conditions)
+        DUNE_THROW(Dune::InvalidStateException,
+                   "The problem specifies that some boundary "
+                   "segments are neumann, but does not provide "
+                   "a neumannAtPos() method.");
+    }
+
+    /*!
+     * \brief Evaluate the source term for all phases within a given
+     *        sub-control-volume.
+     *
+     * This is the method for the case where the source term is
+     * potentially solution dependent and requires some box method
+     * specific things.
+     *
+     * \param values The source and sink values for the conservation equations
+     * \param element The finite element
+     * \param fvGeometry The finite-volume geometry in the box scheme
+     * \param scvIdx The local vertex index
+     * \param elemVolVars All volume variables for the element
+     *
+     * For this method, the \a values parameter stores the rate mass
+     * generated or annihilate per volume unit. Positive values mean
+     * that mass is created, negative ones mean that it vanishes.
+     */
+    void boxSDSource(PrimaryVariables &values,
+                     const Element &element,
+                     const FVElementGeometry &fvGeometry,
+                     const int scvIdx,
+                     const ElementVolumeVariables &elemVolVars) const
+    {
+        // forward to solution independent, box specific interface
+        asImp_().source(values, element, fvGeometry, scvIdx);
+    }
+
+    /*!
+     * \brief Evaluate the source term for all phases within a given
+     *        sub-control-volume.
+     *
+     * \param values The source and sink values for the conservation equations
+     * \param element The finite element
+     * \param fvGeometry The finite-volume geometry in the box scheme
+     * \param scvIdx The local vertex index
+     *
+     * For this method, the \a values parameter stores the rate mass
+     * generated or annihilate per volume unit. Positive values mean
+     * that mass is created, negative ones mean that it vanishes.
+     */
+    void source(PrimaryVariables &values,
+                const Element &element,
+                const FVElementGeometry &fvGeometry,
+                const int scvIdx) const
+    {
+        // forward to generic interface
+        asImp_().sourceAtPos(values, fvGeometry.subContVol[scvIdx].global);
+    }
+
+    /*!
+     * \brief Evaluate the source term for all phases within a given
+     *        sub-control-volume.
+     *
+     * \param values The source and sink values for the conservation equations
+     * \param pos The position of the center of the finite volume
+     *            for which the source term ought to be
+     *            specified in global coordinates
+     *
+     * For this method, the \a values parameter stores the rate mass
+     * generated or annihilate per volume unit. Positive values mean
+     * that mass is created, negative ones mean that it vanishes.
+     */
+    void sourceAtPos(PrimaryVariables &values,
+                     const GlobalPosition &pos) const
+    {
+        DUNE_THROW(Dune::InvalidStateException,
+                   "The problem does not provide "
+                   "a sourceAtPos() method.");
+    }
+
+    /*!
+     * \brief Evaluate the initial value for a control volume.
+     *
+     * \param values The initial values for the primary variables
+     * \param element The finite element
+     * \param fvGeometry The finite-volume geometry in the box scheme
+     * \param scvIdx The local vertex index
+     *
+     * For this method, the \a values parameter stores primary
+     * variables.
+     */
+    void initial(PrimaryVariables &values,
+                 const Element &element,
+                 const FVElementGeometry &fvGeometry,
+                 const int scvIdx) const
+    {
+        // forward to generic interface
+        asImp_().initialAtPos(values, fvGeometry.subContVol[scvIdx].global);
+    }
+
+    /*!
+     * \brief Evaluate the initial value for a control volume.
+     *
+     * \param values The dirichlet values for the primary variables
+     * \param pos The position of the center of the finite volume
+     *            for which the initial values ought to be
+     *            set (in global coordinates)
+     *
+     * For this method, the \a values parameter stores primary variables.
+     */
+    void initialAtPos(PrimaryVariables &values,
+                      const GlobalPosition &pos) const
+    {
+        // Throw an exception (there is no reasonable default value
+        // for Dirichlet conditions)
+        DUNE_THROW(Dune::InvalidStateException,
+                   "The problem does not provide "
+                   "a initialAtPos() method.");
+    }
+
+    /*!
+     * \brief Return how much the domain is extruded at a given sub-control volume.
+     *
+     * This means the factor by which a lower-dimensional (1D or 2D)
+     * entity needs to be expanded to get a full dimensional cell. The
+     * default is 1.0 which means that 1D problems are actually
+     * thought as pipes with a cross section of 1 m^2 and 2D problems
+     * are assumed to extend 1 m to the back.
+     */
+    Scalar boxExtrusionFactor(const Element &element,
+                              const FVElementGeometry &fvGeometry,
+                              const int scvIdx) const
+    {
+        // forward to generic interface
+        return asImp_().extrusionFactorAtPos(fvGeometry.subContVol[scvIdx].global);
+    }
+
+    /*!
+     * \brief Return how much the domain is extruded at a given position.
+     *
+     * This means the factor by which a lower-dimensional (1D or 2D)
+     * entity needs to be expanded to get a full dimensional cell. The
+     * default is 1.0 which means that 1D problems are actually
+     * thought as pipes with a cross section of 1 m^2 and 2D problems
+     * are assumed to extend 1 m to the back.
+     */
+    Scalar extrusionFactorAtPos(const GlobalPosition &pos) const
+    { return 1.0; }
+
+    /*!
+     * \brief If model coupling is used, this updates the parameters
+     *        required to calculate the coupling fluxes between the
+     *        sub-models.
+     *
+     * By default it does nothing
+     *
+     * \param element The DUNE Codim<0> entity for which the coupling
+     *                parameters should be computed.
+     */
+    void updateCouplingParams(const Element &element) const
+    {}
+
+    /*!
+     * \name Simulation steering
+     */
+    // \{
+
+    /*!
+     * \brief Called by the time manager before the time integration.
+     */
+    void preTimeStep()
+    {}
+
+    /*!
+     * \brief Called by Dumux::TimeManager in order to do a time
+     *        integration on the model.
+     */
+    void timeIntegration()
+    {
+        const int maxFails = 10;
+        for (int i = 0; i < maxFails; ++i) {
+            if (model_.update(newtonMethod_, newtonCtl_))
+                return;
+
+            Scalar dt = timeManager().timeStepSize();
+            Scalar nextDt = dt / 2;
+            timeManager().setTimeStepSize(nextDt);
+
+            // update failed
+            std::cout << "Newton solver did not converge with dt="<<dt<<" seconds. Retrying with time step of "
+                      << nextDt << " seconds\n";
+        }
+
+        DUNE_THROW(Dune::MathError,
+                   "Newton solver didn't converge after "
+                   << maxFails
+                   << " time-step divisions. dt="
+                   << timeManager().timeStepSize());
+    }
+
+    /*!
+     * \brief Returns the newton method object
+     */
+    NewtonMethod &newtonMethod()
+    { return newtonMethod_; }
+
+    /*!
+     * \copydoc newtonMethod()
+     */
+    const NewtonMethod &newtonMethod() const
+    { return newtonMethod_; }
+
+    /*!
+     * \brief Returns the newton contoller object
+     */
+    NewtonController &newtonController()
+    { return newtonCtl_; }
+
+    /*!
+     * \copydoc newtonController()
+     */
+    const NewtonController &newtonController() const
+    { return newtonCtl_; }
+
+    /*!
+     * \brief Called by Dumux::TimeManager whenever a solution for a
+     *        time step has been computed and the simulation time has
+     *        been updated.
+     *
+     * \param dt The current time-step size
+     */
+    Scalar nextTimeStepSize(const Scalar dt)
+    {
+        return std::min(GET_PARAM_FROM_GROUP(TypeTag, Scalar, TimeManager, MaxTimeStepSize),
+                        newtonCtl_.suggestTimeStepSize(dt));
+    };
+
+    /*!
+     * \brief Returns true if a restart file should be written to
+     *        disk.
+     *
+     * The default behavior is to write one restart file every 5 time
+     * steps. This file is intended to be overwritten by the
+     * implementation.
+     */
+    bool shouldWriteRestartFile() const
+    {
+        return timeManager().timeStepIndex() > 0 &&
+            (timeManager().timeStepIndex() % 10 == 0);
+    }
+
+    /*!
+     * \brief Returns true if the current solution should be written to
+     *        disk (i.e. as a VTK file)
+     *
+     * The default behavior is to write out every the solution for
+     * very time step. This file is intended to be overwritten by the
+     * implementation.
+     */
+    bool shouldWriteOutput() const
+    { return true; }
+
+    /*!
+     * \brief Called by the time manager after the time integration to
+     *        do some post processing on the solution.
+     */
+    void postTimeStep()
+    { }
+
+    /*!
+     * \brief Called by the time manager after everything which can be
+     *        done about the current time step is finished and the
+     *        model should be prepared to do the next time integration.
+     */
+    void advanceTimeLevel()
+    {
+        model_.advanceTimeLevel();
+    }
+
+    /*!
+     * \brief Called when the end of an simulation episode is reached.
+     *
+     * Typically a new episode should be started in this method.
+     */
+    void episodeEnd()
+    {
+        std::cerr << "The end of an episode is reached, but the problem "
+                  << "does not override the episodeEnd() method. "
+                  << "Doing nothing!\n";
+    };
+    // \}
+
+    /*!
+     * \brief The problem name.
+     *
+     * This is used as a prefix for files generated by the simulation.
+     * It could be either overwritten by the problem files, or simply
+     * declared over the setName() function in the application file.
+     */
+    const char *name() const
+    {
+        return simName_.c_str();
+    }
+
+    /*!
+     * \brief Set the problem name.
+     *
+     * This static method sets the simulation name, which should be
+     * called before the application problem is declared! If not, the
+     * default name "sim" will be used.
+     *
+     * \param newName The problem's name
+     */
+    void setName(const char *newName)
+    {
+        simName_ = newName;
+    }
+
+
+    /*!
+     * \brief Returns the number of the current VTK file.
+     */
+    int currentVTKFileNumber()
+    {
+        createResultWriter_();
+        return resultWriter_->curWriterNum();
+    }
+
+    /*!
+     * \brief The GridView which used by the problem.
+     */
+    const GridView &gridView() const
+    { return gridView_; }
+
+    /*!
+     * \brief The coordinate of the corner of the GridView's bounding
+     *        box with the smallest values.
+     */
+    const GlobalPosition &bboxMin() const
+    { return bboxMin_; }
+
+    /*!
+     * \brief The coordinate of the corner of the GridView's bounding
+     *        box with the largest values.
+     */
+    const GlobalPosition &bboxMax() const
+    { return bboxMax_; }
+
+    /*!
+     * \brief Returns the mapper for vertices to indices.
+     */
+    const VertexMapper &vertexMapper() const
+    { return vertexMapper_; }
+
+    /*!
+     * \brief Returns the mapper for elements to indices.
+     */
+    const ElementMapper &elementMapper() const
+    { return elementMapper_; }
+
+    /*!
+     * \brief Returns TimeManager object used by the simulation
+     */
+    TimeManager &timeManager()
+    { return *timeManager_; }
+
+    /*!
+     * \copydoc timeManager()
+     */
+    const TimeManager &timeManager() const
+    { return *timeManager_; }
+
+    /*!
+     * \brief Returns numerical model used for the problem.
+     */
+    Model &model()
+    { return model_; }
+
+    /*!
+     * \copydoc model()
+     */
+    const Model &model() const
+    { return model_; }
+    // \}
+
+    /*!
+     * \name Restart mechanism
+     */
+    // \{
+
+    /*!
+     * \brief This method writes the complete state of the simulation
+     *        to the harddisk.
+     *
+     * The file will start with the prefix returned by the name()
+     * method, has the current time of the simulation clock in it's
+     * name and uses the extension <tt>.drs</tt>. (Dumux ReStart
+     * file.)  See Dumux::Restart for details.
+     */
+    void serialize()
+    {
+        typedef Dumux::Restart Restarter;
+        Restarter res;
+        res.serializeBegin(asImp_());
+        if (gridView().comm().rank() == 0)
+            std::cout << "Serialize to file '" << res.fileName() << "'\n";
+
+        timeManager().serialize(res);
+        asImp_().serialize(res);
+        res.serializeEnd();
+    }
+
+    /*!
+     * \brief This method writes the complete state of the problem
+     *        to the harddisk.
+     *
+     * The file will start with the prefix returned by the name()
+     * method, has the current time of the simulation clock in it's
+     * name and uses the extension <tt>.drs</tt>. (Dumux ReStart
+     * file.)  See Dumux::Restart for details.
+     *
+     * \tparam Restarter The serializer type
+     *
+     * \param res The serializer object
+     */
+    template <class Restarter>
+    void serialize(Restarter &res)
+    {
+        createResultWriter_();
+        resultWriter_->serialize(res);
+        model().serialize(res);
+    }
+
+    /*!
+     * \brief Load a previously saved state of the whole simulation
+     *        from disk.
+     *
+     * \param tRestart The simulation time on which the program was
+     *                 written to disk.
+     */
+    void restart(const Scalar tRestart)
+    {
+        typedef Dumux::Restart Restarter;
+
+        Restarter res;
+
+        res.deserializeBegin(asImp_(), tRestart);
+        if (gridView().comm().rank() == 0)
+            std::cout << "Deserialize from file '" << res.fileName() << "'\n";
+        timeManager().deserialize(res);
+        asImp_().deserialize(res);
+        res.deserializeEnd();
+    }
+
+    /*!
+     * \brief This method restores the complete state of the problem
+     *        from disk.
+     *
+     * It is the inverse of the serialize() method.
+     *
+     * \tparam Restarter The deserializer type
+     *
+     * \param res The deserializer object
+     */
+    template <class Restarter>
+    void deserialize(Restarter &res)
+    {
+        createResultWriter_();
+        resultWriter_->deserialize(res);
+        model().deserialize(res);
+    }
+
+    // \}
+
+    /*!
+     * \brief Adds additional VTK output data to the VTKWriter. Function is called by writeOutput().
+     */
+    void addOutputVtkFields()
+    {}
+
+    /*!
+     * \brief Write the relevant secondary variables of the current
+     *        solution into an VTK output file.
+     */
+    void writeOutput(const bool verbose = true)
+    {
+        // write the current result to disk
+        if (asImp_().shouldWriteOutput()) {
+            if (verbose && gridView().comm().rank() == 0)
+                std::cout << "Writing result file for \"" << asImp_().name() << "\"\n";
+
+            // calculate the time _after_ the time was updated
+            Scalar t = timeManager().time() + timeManager().timeStepSize();
+            createResultWriter_();
+            resultWriter_->beginWrite(t);
+            model().addOutputVtkFields(model().curSol(), *resultWriter_);
+            asImp_().addOutputVtkFields();
+            resultWriter_->endWrite();
+        }
+    }
+
+protected:
+    //! Returns the implementation of the problem (i.e. static polymorphism)
+    Implementation &asImp_()
+    { return *static_cast<Implementation *>(this); }
+
+    //! \copydoc asImp_()
+    const Implementation &asImp_() const
+    { return *static_cast<const Implementation *>(this); }
+
+    //! Returns the applied VTK-writer for the output
+    VtkMultiWriter& resultWriter()
+    {
+        createResultWriter_();
+        return *resultWriter_;
+    }
+    //! \copydoc Dumux::IMPETProblem::resultWriter()
+    VtkMultiWriter& resultWriter() const
+    {
+        createResultWriter_();
+        return *resultWriter_;
+    }
+
+
+private:
+    // makes sure that the result writer exists
+    void createResultWriter_()
+    { if (!resultWriter_) resultWriter_ = new VtkMultiWriter(gridView_, asImp_().name()); };
+
+    std::string simName_;
+    const GridView gridView_;
+
+    GlobalPosition bboxMin_;
+    GlobalPosition bboxMax_;
+
+    ElementMapper elementMapper_;
+    VertexMapper vertexMapper_;
+
+    TimeManager *timeManager_;
+
+    Model model_;
+
+    NewtonMethod newtonMethod_;
+    NewtonController newtonCtl_;
+
+    VtkMultiWriter *resultWriter_;
+};
+
+}
+
+#endif
diff --git a/dumux/implicit/box/boxproperties.hh b/dumux/implicit/box/boxproperties.hh
new file mode 100644
index 0000000000..9fd7fffa05
--- /dev/null
+++ b/dumux/implicit/box/boxproperties.hh
@@ -0,0 +1,142 @@
+// -*- mode: C++; tab-width: 4; indent-tabs-mode: nil; c-basic-offset: 4 -*-
+// vi: set et ts=4 sw=4 sts=4:
+/*****************************************************************************
+ *   See the file COPYING for full copying permissions.                      *
+ *                                                                           *
+ *   This program is free software: you can redistribute it and/or modify    *
+ *   it under the terms of the GNU General Public License as published by    *
+ *   the Free Software Foundation, either version 2 of the License, or       *
+ *   (at your option) any later version.                                     *
+ *                                                                           *
+ *   This program is distributed in the hope that it will be useful,         *
+ *   but WITHOUT ANY WARRANTY; without even the implied warranty of          *
+ *   MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the            *
+ *   GNU General Public License for more details.                            *
+ *                                                                           *
+ *   You should have received a copy of the GNU General Public License       *
+ *   along with this program.  If not, see <http://www.gnu.org/licenses/>.   *
+ *****************************************************************************/
+#ifndef DUMUX_BOX_PROPERTIES_HH
+#define DUMUX_BOX_PROPERTIES_HH
+
+#include <dumux/common/propertysystem.hh>
+
+#include <dumux/common/basicproperties.hh>
+#include <dumux/linear/linearsolverproperties.hh>
+#include <dumux/nonlinear/newtonmethod.hh>
+
+/*!
+ * \ingroup Properties
+ * \ingroup BoxProperties
+ * \ingroup BoxModel
+ * \file
+ * \brief Specify the shape functions, operator assemblers, etc
+ *        used for the BoxModel.
+ */
+namespace Dumux
+{
+
+namespace Properties
+{
+/*!
+ * \ingroup BoxModel
+ */
+// \{
+
+//////////////////////////////////////////////////////////////////
+// Type tags
+//////////////////////////////////////////////////////////////////
+
+//! The type tag for models based on the box-scheme
+NEW_TYPE_TAG(BoxModel, INHERITS_FROM(NewtonMethod, LinearSolverTypeTag, ImplicitModel));
+
+//////////////////////////////////////////////////////////////////
+// Property tags
+//////////////////////////////////////////////////////////////////
+
+NEW_PROP_TAG(Grid);     //!< The type of the DUNE grid
+NEW_PROP_TAG(GridView); //!< The type of the grid view
+
+NEW_PROP_TAG(FVElementGeometry); //! The type of the finite-volume geometry in the box scheme
+NEW_PROP_TAG(EvalGradientsAtSCVCenter); //! Evaluate shape function gradients additionally at the sub-control volume center
+
+NEW_PROP_TAG(Problem); //!< The type of the problem
+NEW_PROP_TAG(BaseModel); //!< The type of the base class of the model
+NEW_PROP_TAG(Model); //!< The type of the model
+NEW_PROP_TAG(NumEq); //!< Number of equations in the system of PDEs
+NEW_PROP_TAG(BaseLocalResidual); //!< The type of the base class of the local residual
+NEW_PROP_TAG(LocalResidual); //!< The type of the local residual function
+NEW_PROP_TAG(LocalJacobian); //!< The type of the local jacobian operator
+
+NEW_PROP_TAG(JacobianAssembler); //!< Assembles the global jacobian matrix
+NEW_PROP_TAG(JacobianMatrix); //!< Type of the global jacobian matrix
+NEW_PROP_TAG(BoundaryTypes); //!< Stores the boundary types of a single degree of freedom
+NEW_PROP_TAG(ElementBoundaryTypes); //!< Stores the boundary types on an element
+
+NEW_PROP_TAG(PrimaryVariables); //!< A vector of primary variables within a sub-control volume
+NEW_PROP_TAG(SolutionVector); //!< Vector containing all primary variable vector of the grid
+NEW_PROP_TAG(ElementSolutionVector); //!< A vector of primary variables within a sub-control volume
+
+NEW_PROP_TAG(VolumeVariables);  //!< The secondary variables within a sub-control volume
+NEW_PROP_TAG(ElementVolumeVariables); //!< The secondary variables of all sub-control volumes in an element
+NEW_PROP_TAG(FluxVariables); //!< Data required to calculate a flux over a face
+NEW_PROP_TAG(BoundaryVariables); //!< Data required to calculate fluxes over boundary faces (outflow)
+
+// high level simulation control
+NEW_PROP_TAG(TimeManager);  //!< Manages the simulation time
+NEW_PROP_TAG(NewtonMethod);     //!< The type of the newton method
+NEW_PROP_TAG(NewtonController); //!< The type of the newton controller
+
+//! Specify whether the jacobian matrix of the last iteration of a
+//! time step should be re-used as the jacobian of the first iteration
+//! of the next time step.
+NEW_PROP_TAG(ImplicitEnableJacobianRecycling);
+
+//! Specify whether the jacobian matrix should be only reassembled for
+//! elements where at least one vertex is above the specified
+//! tolerance
+NEW_PROP_TAG(ImplicitEnablePartialReassemble);
+/*!
+ * \brief Specify the maximum size of a time integration [s].
+ *
+ * The default is to not limit the step size.
+ */
+NEW_PROP_TAG(TimeManagerMaxTimeStepSize);
+
+/*!
+ * \brief Specify which kind of method should be used to numerically
+ * calculate the partial derivatives of the residual.
+ *
+ * -1 means backward differences, 0 means central differences, 1 means
+ * forward differences. By default we use central differences.
+ */
+NEW_PROP_TAG(ImplicitNumericDifferenceMethod);
+
+/*!
+ * \brief Specify whether to use the already calculated solutions as
+ *        starting values of the volume variables.
+ *
+ * This only makes sense if the calculation of the volume variables is
+ * very expensive (e.g. for non-linear fugacity functions where the
+ * solver converges faster).
+ */
+NEW_PROP_TAG(ImplicitEnableHints);
+
+//! indicates whether two-point flux should be used
+NEW_PROP_TAG(ImplicitUseTwoPointFlux); 
+
+// mappers from local to global indices
+
+//! maper for vertices
+NEW_PROP_TAG(VertexMapper);
+//! maper for elements
+NEW_PROP_TAG(ElementMapper);
+//! maper for degrees of freedom
+NEW_PROP_TAG(DofMapper);
+
+}
+}
+
+// \}
+
+#endif
diff --git a/dumux/implicit/box/boxpropertydefaults.hh b/dumux/implicit/box/boxpropertydefaults.hh
new file mode 100644
index 0000000000..50ec31e2c7
--- /dev/null
+++ b/dumux/implicit/box/boxpropertydefaults.hh
@@ -0,0 +1,207 @@
+// -*- mode: C++; tab-width: 4; indent-tabs-mode: nil; c-basic-offset: 4 -*-
+// vi: set et ts=4 sw=4 sts=4:
+/*****************************************************************************
+ *   See the file COPYING for full copying permissions.                      *
+ *                                                                           *
+ *   This program is free software: you can redistribute it and/or modify    *
+ *   it under the terms of the GNU General Public License as published by    *
+ *   the Free Software Foundation, either version 2 of the License, or       *
+ *   (at your option) any later version.                                     *
+ *                                                                           *
+ *   This program is distributed in the hope that it will be useful,         *
+ *   but WITHOUT ANY WARRANTY; without even the implied warranty of          *
+ *   MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the            *
+ *   GNU General Public License for more details.                            *
+ *                                                                           *
+ *   You should have received a copy of the GNU General Public License       *
+ *   along with this program.  If not, see <http://www.gnu.org/licenses/>.   *
+ *****************************************************************************/
+/*!
+ * \ingroup Properties
+ * \ingroup BoxProperties
+ * \ingroup BoxModel
+ * \file
+ *
+ * \brief Default properties for box models
+ */
+#ifndef DUMUX_BOX_PROPERTY_DEFAULTS_HH
+#define DUMUX_BOX_PROPERTY_DEFAULTS_HH
+
+#include <dumux/nonlinear/newtonmethod.hh>
+#include <dumux/nonlinear/newtoncontroller.hh>
+
+#include "boxassembler.hh"
+#include "boxmodel.hh"
+#include "boxfvelementgeometry.hh"
+#include "boxelementboundarytypes.hh"
+#include "boxlocaljacobian.hh"
+#include "boxlocalresidual.hh"
+#include "boxelementvolumevariables.hh"
+#include "boxvolumevariables.hh"
+
+#include <dumux/common/boundarytypes.hh>
+#include <dumux/common/timemanager.hh>
+
+#include "boxproperties.hh"
+
+#include <limits>
+
+namespace Dumux {
+
+// forward declaration
+template<class TypeTag>
+class BoxModel;
+
+namespace Properties {
+//////////////////////////////////////////////////////////////////
+// Some defaults for very fundamental properties
+//////////////////////////////////////////////////////////////////
+
+//! Set the default type for the time manager
+SET_TYPE_PROP(BoxModel, TimeManager, Dumux::TimeManager<TypeTag>);
+
+//////////////////////////////////////////////////////////////////
+// Properties
+//////////////////////////////////////////////////////////////////
+
+//! Use the leaf grid view if not defined otherwise
+SET_TYPE_PROP(BoxModel,
+              GridView,
+              typename GET_PROP_TYPE(TypeTag, Grid)::LeafGridView);
+
+//! Set the default for the FVElementGeometry
+SET_TYPE_PROP(BoxModel, FVElementGeometry, Dumux::BoxFVElementGeometry<TypeTag>);
+
+//! Disable evaluation of shape function gradients at the sub-control volume center by default
+// The shape function gradients at the sub-control volume center are currently only
+// needed for the stokes and the linear elastic models
+SET_BOOL_PROP(BoxModel, EvalGradientsAtSCVCenter, false);
+
+//! Set the default for the ElementBoundaryTypes
+SET_TYPE_PROP(BoxModel, ElementBoundaryTypes, Dumux::BoxElementBoundaryTypes<TypeTag>);
+
+//! use the plain newton method for the box scheme by default
+SET_TYPE_PROP(BoxModel, NewtonMethod, Dumux::NewtonMethod<TypeTag>);
+
+//! use the plain newton controller for the box scheme by default
+SET_TYPE_PROP(BoxModel, NewtonController, Dumux::NewtonController<TypeTag>);
+
+//! Mapper for the grid view's vertices.
+SET_TYPE_PROP(BoxModel,
+              VertexMapper,
+              Dune::MultipleCodimMultipleGeomTypeMapper<typename GET_PROP_TYPE(TypeTag, GridView),
+                                                        Dune::MCMGVertexLayout>);
+
+//! Mapper for the grid view's elements.
+SET_TYPE_PROP(BoxModel,
+              ElementMapper,
+              Dune::MultipleCodimMultipleGeomTypeMapper<typename GET_PROP_TYPE(TypeTag, GridView),
+                                                        Dune::MCMGElementLayout>);
+
+//! Mapper for the degrees of freedoms.
+SET_TYPE_PROP(BoxModel, DofMapper, typename GET_PROP_TYPE(TypeTag, VertexMapper));
+
+//! Set the BaseLocalResidual to BoxLocalResidual
+SET_TYPE_PROP(BoxModel, BaseLocalResidual, Dumux::BoxLocalResidual<TypeTag>);
+
+//! Set the BaseModel to BoxModel
+SET_TYPE_PROP(BoxModel, BaseModel, Dumux::BoxModel<TypeTag>);
+
+//! The local jacobian operator for the box scheme
+SET_TYPE_PROP(BoxModel, LocalJacobian, Dumux::BoxLocalJacobian<TypeTag>);
+
+/*!
+ * \brief The type of a solution for the whole grid at a fixed time.
+ */
+SET_TYPE_PROP(BoxModel,
+              SolutionVector,
+              Dune::BlockVector<typename GET_PROP_TYPE(TypeTag, PrimaryVariables)>);
+
+/*!
+ * \brief The type of a solution for a whole element.
+ */
+SET_TYPE_PROP(BoxModel,
+              ElementSolutionVector,
+              Dune::BlockVector<typename GET_PROP_TYPE(TypeTag, PrimaryVariables)>);
+
+/*!
+ * \brief A vector of primary variables.
+ */
+SET_TYPE_PROP(BoxModel,
+              PrimaryVariables,
+              Dune::FieldVector<typename GET_PROP_TYPE(TypeTag, Scalar),
+                                GET_PROP_VALUE(TypeTag, NumEq)>);
+
+/*!
+ * \brief The volume variable class.
+ *
+ * This should almost certainly be overloaded by the model...
+ */
+SET_TYPE_PROP(BoxModel, VolumeVariables, Dumux::BoxVolumeVariables<TypeTag>);
+
+/*!
+ * \brief An array of secondary variable containers.
+ */
+SET_TYPE_PROP(BoxModel, ElementVolumeVariables, Dumux::BoxElementVolumeVariables<TypeTag>);
+
+/*!
+ * \brief Boundary types at a single degree of freedom.
+ */
+SET_TYPE_PROP(BoxModel,
+              BoundaryTypes,
+              Dumux::BoundaryTypes<GET_PROP_VALUE(TypeTag, NumEq)>);
+
+/*!
+ * \brief Assembler for the global jacobian matrix.
+ */
+SET_TYPE_PROP(BoxModel, JacobianAssembler, Dumux::BoxAssembler<TypeTag>);
+
+//! use an unlimited time step size by default
+SET_SCALAR_PROP(BoxModel, TimeManagerMaxTimeStepSize, 1e100);
+
+//! use forward differences to calculate the jacobian by default
+SET_INT_PROP(BoxModel, ImplicitNumericDifferenceMethod, +1);
+
+//! do not use hints by default
+SET_BOOL_PROP(BoxModel, ImplicitEnableHints, false);
+
+// disable jacobian matrix recycling by default
+SET_BOOL_PROP(BoxModel, ImplicitEnableJacobianRecycling, false);
+
+// disable partial reassembling by default
+SET_BOOL_PROP(BoxModel, ImplicitEnablePartialReassemble, false);
+
+// disable two-point-flux by default
+SET_BOOL_PROP(BoxModel, ImplicitUseTwoPointFlux, false);
+
+//! Set the type of a global jacobian matrix from the solution types
+SET_PROP(BoxModel, JacobianMatrix)
+{
+private:
+    typedef typename GET_PROP_TYPE(TypeTag, Scalar) Scalar;
+    enum { numEq = GET_PROP_VALUE(TypeTag, NumEq) };
+    typedef typename Dune::FieldMatrix<Scalar, numEq, numEq> MatrixBlock;
+public:
+    typedef typename Dune::BCRSMatrix<MatrixBlock> type;
+};
+
+// use the stabilized BiCG solver preconditioned by the ILU-0 by default
+SET_TYPE_PROP(BoxModel, LinearSolver, Dumux::BoxBiCGStabILU0Solver<TypeTag> );
+
+// if the deflection of the newton method is large, we do not
+// need to solve the linear approximation accurately. Assuming
+// that the initial value for the delta vector u is quite
+// close to the final value, a reduction of 6 orders of
+// magnitude in the defect should be sufficient...
+SET_SCALAR_PROP(BoxModel, LinearSolverResidualReduction, 1e-6);
+
+//! set the default number of maximum iterations for the linear solver
+SET_INT_PROP(BoxModel, LinearSolverMaxIterations, 250);
+
+//! set number of equations of the mathematical model as default
+SET_INT_PROP(BoxModel, LinearSolverBlockSize, GET_PROP_VALUE(TypeTag, NumEq));
+
+} // namespace Properties
+} // namespace Dumux
+
+#endif
diff --git a/dumux/implicit/box/boxvolumevariables.hh b/dumux/implicit/box/boxvolumevariables.hh
new file mode 100644
index 0000000000..0c0bb6d8f6
--- /dev/null
+++ b/dumux/implicit/box/boxvolumevariables.hh
@@ -0,0 +1,190 @@
+// -*- mode: C++; tab-width: 4; indent-tabs-mode: nil; c-basic-offset: 4 -*-
+// vi: set et ts=4 sw=4 sts=4:
+/*****************************************************************************
+ *   See the file COPYING for full copying permissions.                      *
+ *                                                                           *
+ *   This program is free software: you can redistribute it and/or modify    *
+ *   it under the terms of the GNU General Public License as published by    *
+ *   the Free Software Foundation, either version 2 of the License, or       *
+ *   (at your option) any later version.                                     *
+ *                                                                           *
+ *   This program is distributed in the hope that it will be useful,         *
+ *   but WITHOUT ANY WARRANTY; without even the implied warranty of          *
+ *   MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the            *
+ *   GNU General Public License for more details.                            *
+ *                                                                           *
+ *   You should have received a copy of the GNU General Public License       *
+ *   along with this program.  If not, see <http://www.gnu.org/licenses/>.   *
+ *****************************************************************************/
+/*!
+ * \file
+ *
+ * \brief Base class for the model specific class which provides
+ *        access to all volume averaged quantities.
+ */
+#ifndef DUMUX_BOX_VOLUME_VARIABLES_HH
+#define DUMUX_BOX_VOLUME_VARIABLES_HH
+
+#include "boxproperties.hh"
+
+#include <dumux/common/valgrind.hh>
+
+namespace Dumux
+{
+
+/*!
+ * \ingroup BoxModel
+ * \ingroup BoxVolumeVariables
+ * \brief Base class for the model specific class which provides
+ *        access to all volume averaged quantities.
+ */
+template <class TypeTag>
+class BoxVolumeVariables
+{
+    typedef typename GET_PROP_TYPE(TypeTag, VolumeVariables) Implementation;
+
+    typedef typename GET_PROP_TYPE(TypeTag, Scalar) Scalar;
+    typedef typename GET_PROP_TYPE(TypeTag, Problem) Problem;
+    typedef typename GET_PROP_TYPE(TypeTag, GridView) GridView;
+    typedef typename GridView::template Codim<0>::Entity Element;
+    typedef typename GET_PROP_TYPE(TypeTag, FVElementGeometry) FVElementGeometry;
+
+    typedef typename GET_PROP_TYPE(TypeTag, PrimaryVariables) PrimaryVariables;
+
+public:
+    // default constructor
+    BoxVolumeVariables()
+    { evalPoint_ = 0; };
+
+    // copy constructor
+    BoxVolumeVariables(const BoxVolumeVariables &v)
+    {
+        evalPoint_ = 0;
+        priVars_ = v.priVars_;
+        extrusionFactor_ = v.extrusionFactor_;
+    };
+
+    /*!
+     * \brief Assignment operator
+     */
+    BoxVolumeVariables &operator=(const BoxVolumeVariables &v)
+    {
+        evalPoint_ = 0;
+        priVars_ = v.priVars_;
+        extrusionFactor_ = v.extrusionFactor_;
+
+        return *this;
+    };
+
+    /*!
+     * \brief Sets the evaluation point used by the local jacobian.
+     *
+     * The evaluation point is only used by semi-smooth models.
+     */
+    void setEvalPoint(const Implementation *ep)
+    {
+        evalPoint_ = ep;
+        Valgrind::CheckDefined(evalPoint_);
+    }
+
+    /*!
+     * \brief Returns the evaluation point used by the local jacobian.
+     *
+     * The evaluation point is only used by semi-smooth models.
+     */
+    const Implementation &evalPoint() const
+    { return (evalPoint_ == 0)?asImp_():*evalPoint_; }
+
+    /*!
+     * \brief Set the volume variables which should be used as initial
+     *        conditions for complex calculations.
+     */
+    void setHint(const Implementation *hint)
+    {};
+
+    /*!
+     * \brief Update all quantities for a given control volume
+     *
+     * \param priVars A vector containing the primary variables for the control volume
+     * \param problem The object specifying the problem which ought to
+     *                be simulated
+     * \param element An element which contains part of the control volume
+     * \param fvGeometry The finite volume geometry for the element
+     * \param scvIdx Local index of the sub control volume which is inside the element
+     * \param isOldSol Specifies whether this is the previous solution or the current one
+     *
+     * \todo Eliminate the 'isOldSol' parameter. This implies that the
+     *       'pseudo-primary variables' must be somehow be stored
+     *       inside the PrimaryVariables. (e.g. we need to know the
+     *       phase state in the 2p2c model)
+     */
+    void update(const PrimaryVariables &priVars,
+                const Problem &problem,
+                const Element &element,
+                const FVElementGeometry &fvGeometry,
+                const int scvIdx,
+                const bool isOldSol)
+    {
+        Valgrind::CheckDefined(priVars);
+        priVars_ = priVars;
+        extrusionFactor_ = problem.boxExtrusionFactor(element, fvGeometry, scvIdx);
+    }
+
+    /*!
+     * \brief Return the vector of primary variables
+     */
+    const PrimaryVariables &priVars() const
+    { return priVars_; }
+
+    /*!
+     * \brief Return a component of primary variable vector
+     *
+     * \param pvIdx The index of the primary variable of interest
+     */
+    Scalar priVar(const int pvIdx) const
+    {
+        return priVars_[pvIdx];
+    }
+
+    /*!
+     * \brief Return how much the sub-control volume is extruded.
+     *
+     * This means the factor by which a lower-dimensional (1D or 2D)
+     * entity needs to be expanded to get a full dimensional cell. The
+     * default is 1.0 which means that 1D problems are actually
+     * thought as pipes with a cross section of 1 m^2 and 2D problems
+     * are assumed to extend 1 m to the back.
+     */
+    Scalar extrusionFactor() const
+    { return extrusionFactor_; }
+
+    /*!
+     * \brief If running in valgrind this makes sure that all
+     *        quantities in the volume variables are defined.
+     */
+    void checkDefined() const
+    {
+#if !defined NDEBUG && HAVE_VALGRIND
+        Valgrind::CheckDefined(priVars_);
+        Valgrind::CheckDefined(evalPoint_);
+        if (evalPoint_ && evalPoint_ != this)
+            evalPoint_->checkDefined();
+#endif
+    };
+
+protected:
+    const Implementation &asImp_() const
+    { return *static_cast<const Implementation*>(this); }
+    Implementation &asImp_()
+    { return *static_cast<Implementation*>(this); }
+
+    // the evaluation point of the local jacobian
+    const Implementation *evalPoint_;
+
+    PrimaryVariables priVars_;
+    Scalar extrusionFactor_;
+};
+
+} // end namepace
+
+#endif
diff --git a/dumux/implicit/box/intersectiontovertexbc.hh b/dumux/implicit/box/intersectiontovertexbc.hh
new file mode 100644
index 0000000000..f57fddb434
--- /dev/null
+++ b/dumux/implicit/box/intersectiontovertexbc.hh
@@ -0,0 +1,112 @@
+/*****************************************************************************
+ *   Copyright (C) 2010 by Bernd Flemisch                                    *
+ *   Institute for Modelling Hydraulic and Environmental Systems             *
+ *   University of Stuttgart, Germany                                        *
+ *   email: <givenname>.<name>@iws.uni-stuttgart.de                          *
+ *                                                                           *
+ *   This program is free software: you can redistribute it and/or modify    *
+ *   it under the terms of the GNU General Public License as published by    *
+ *   the Free Software Foundation, either version 2 of the License, or       *
+ *   (at your option) any later version.                                     *
+ *                                                                           *
+ *   This program is distributed in the hope that it will be useful,         *
+ *   but WITHOUT ANY WARRANTY; without even the implied warranty of          *
+ *   MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the           *
+ *   GNU General Public License for more details.                            *
+ *                                                                           *
+ *   You should have received a copy of the GNU General Public License       *
+ *   along with this program.  If not, see <http://www.gnu.org/licenses/>.   *
+ *****************************************************************************/
+/*!
+ * \file
+ * \brief Base class for all problems which use the box scheme
+ */
+#ifndef DUMUX_INTERSECTIONTOVERTEXBC_HH
+#define DUMUX_INTERSECTIONTOVERTEXBC_HH
+
+#include <dumux/boxmodels/common/boxproperties.hh>
+
+namespace Dumux
+{
+
+template<typename TypeTag> 
+class IntersectionToVertexBC
+{
+    typedef typename GET_PROP_TYPE(TypeTag, BoundaryTypes) BoundaryTypes;
+    typedef typename GET_PROP_TYPE(TypeTag, Problem) Problem;
+    typedef typename GET_PROP_TYPE(TypeTag, GridView) GridView;
+    typedef typename GET_PROP_TYPE(TypeTag, Scalar) Scalar;
+
+    enum {
+        numEq = GET_PROP_VALUE(TypeTag, NumEq),
+        dim = GridView::dimension,
+    };
+
+    typedef typename GridView::template Codim<0>::Iterator ElementIterator;
+    typedef typename GridView::IntersectionIterator IntersectionIterator;
+    typedef typename GridView::template Codim<dim>::Entity Vertex;
+
+    typedef typename Dune::GenericReferenceElements<Scalar, dim> ReferenceElements;
+    typedef typename Dune::GenericReferenceElement<Scalar, dim> ReferenceElement;
+
+public:
+    IntersectionToVertexBC(const Problem& problem)
+    : problem_(problem)
+    {
+	vertexBC.resize(problem.vertexMapper().size());
+        for (int vertIdx = 0; vertIdx < vertexBC.size(); vertIdx++)
+            vertexBC[vertIdx].setAllNeumann();
+
+        ElementIterator eIt = problem.gridView().template begin<0>();
+        const ElementIterator elemEndIt = problem.gridView().template end<0>();
+        for (; eIt != elemEndIt; ++eIt) {
+            Dune::GeometryType geoType = eIt->geometry().type();
+            const ReferenceElement &refElem = ReferenceElements::general(geoType);
+
+            IntersectionIterator isIt = problem.gridView().ibegin(*eIt);
+            IntersectionIterator isEndIt = problem.gridView().iend(*eIt);
+            for (; isIt != isEndIt; ++isIt) {
+                if (!isIt->boundary())
+                    continue;
+
+                BoundaryTypes bcTypes;
+		problem.boundaryTypes(bcTypes, *isIt);
+
+		if (!bcTypes.hasDirichlet())
+                    continue;
+
+                int faceIdx = isIt->indexInInside();
+                int numFaceVerts = refElem.size(faceIdx, 1, dim);
+                for (int faceVertIdx = 0; faceVertIdx < numFaceVerts; ++faceVertIdx)
+                {
+                    int elemVertIdx = refElem.subEntity(faceIdx, 1, faceVertIdx, dim);
+                    int globalVertIdx = problem.vertexMapper().map(*eIt, elemVertIdx, dim);
+
+                    for (int eqIdx = 0; eqIdx < numEq; eqIdx++)
+                      if (bcTypes.isDirichlet(eqIdx))
+                          vertexBC[globalVertIdx].setDirichlet(eqIdx);
+                }
+            }
+        }
+    }
+
+    void boundaryTypes(BoundaryTypes& values, const Vertex& vertex) const
+    {
+        values.setAllNeumann();
+
+	int vertIdx = problem_.vertexMapper().map(vertex);
+	const BoundaryTypes& bcTypes = vertexBC[vertIdx];
+
+        for (int eqIdx = 0; eqIdx < numEq; eqIdx++)
+            if (bcTypes.isDirichlet(eqIdx))
+                values.setDirichlet(eqIdx);
+    }
+
+private: 
+    const Problem& problem_;
+    std::vector<BoundaryTypes> vertexBC;
+};
+}
+
+#endif
+
diff --git a/dumux/implicit/box/porousmediaboxproblem.hh b/dumux/implicit/box/porousmediaboxproblem.hh
new file mode 100644
index 0000000000..151f953703
--- /dev/null
+++ b/dumux/implicit/box/porousmediaboxproblem.hh
@@ -0,0 +1,197 @@
+// -*- mode: C++; tab-width: 4; indent-tabs-mode: nil; c-basic-offset: 4 -*-
+// vi: set et ts=4 sw=4 sts=4:
+/*****************************************************************************
+ *                 2012 by Bernd Flemisch                                    *
+ *   See the file COPYING for full copying permissions.                      *
+ *                                                                           *
+ *   This program is free software: you can redistribute it and/or modify    *
+ *   it under the terms of the GNU General Public License as published by    *
+ *   the Free Software Foundation, either version 2 of the License, or       *
+ *   (at your option) any later version.                                     *
+ *                                                                           *
+ *   This program is distributed in the hope that it will be useful,         *
+ *   but WITHOUT ANY WARRANTY; without even the implied warranty of          *
+ *   MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the            *
+ *   GNU General Public License for more details.                            *
+ *                                                                           *
+ *   You should have received a copy of the GNU General Public License       *
+ *   along with this program.  If not, see <http://www.gnu.org/licenses/>.   *
+ *****************************************************************************/
+/*!
+ * \file
+ * \brief Base class for all problems which use the two-phase box model
+ */
+#ifndef DUMUX_POROUS_MEDIA_BOX_PROBLEM_HH
+#define DUMUX_POROUS_MEDIA_BOX_PROBLEM_HH
+
+#include "boxproperties.hh"
+
+#include <dumux/boxmodels/common/boxproblem.hh>
+
+namespace Dumux
+{
+namespace Properties
+{
+NEW_PROP_TAG(SpatialParams); //!< The type of the spatial parameters object
+NEW_PROP_TAG(ProblemEnableGravity); //!< Returns whether gravity is considered in the problem
+}
+
+/*!
+ * \ingroup BoxBaseProblems
+ * \brief Base class for all porous media box problems
+ */
+template<class TypeTag>
+class PorousMediaBoxProblem : public BoxProblem<TypeTag>
+{
+    typedef BoxProblem<TypeTag> ParentType;
+
+    typedef typename GET_PROP_TYPE(TypeTag, Problem) Implementation;
+    typedef typename GET_PROP_TYPE(TypeTag, TimeManager) TimeManager;
+    typedef typename GET_PROP_TYPE(TypeTag, FVElementGeometry) FVElementGeometry;
+    typedef typename GET_PROP_TYPE(TypeTag, SpatialParams) SpatialParams;
+
+    typedef typename GET_PROP_TYPE(TypeTag, GridView) GridView;
+    typedef typename GridView::template Codim<0>::Entity Element;
+    enum {
+        dim = GridView::dimension,
+        dimWorld = GridView::dimensionworld
+    };
+
+    typedef typename GridView::ctype CoordScalar;
+    typedef Dune::FieldVector<CoordScalar, dimWorld> GlobalPosition;
+    typedef typename GET_PROP_TYPE(TypeTag, Scalar) Scalar;
+    typedef Dune::FieldVector<Scalar, dim> DimVector;
+
+public:
+    /*!
+     * \brief The constructor
+     *
+     * \param timeManager The time manager
+     * \param gridView The grid view
+     * \param verbose Turn verbosity on or off
+     */
+    PorousMediaBoxProblem(TimeManager &timeManager,
+                const GridView &gridView,
+                const bool verbose = true)
+        : ParentType(timeManager, gridView),
+          gravity_(0)
+    {
+        newSpatialParams_ = true;
+        spatialParams_ = new SpatialParams(gridView);
+
+        if (GET_PARAM_FROM_GROUP(TypeTag, bool, Problem, EnableGravity))
+            gravity_[dim-1]  = -9.81;
+    }
+
+    ~PorousMediaBoxProblem()
+    {
+        if (newSpatialParams_)
+            delete spatialParams_;
+    }
+
+    /*!
+     * \name Problem parameters
+     */
+    // \{
+
+    /*!
+     * \brief Returns the temperature \f$\mathrm{[K]}\f$ within a control volume.
+     *
+     * This is the discretization specific interface for the box
+     * method. By default it just calls temperature(pos).
+     *
+     * \param element The DUNE Codim<0> enitiy which intersects with
+     *                the finite volume.
+     * \param fvGeometry The finite volume geometry of the element.
+     * \param scvIdx The local index of the sub control volume inside the element
+     */
+    Scalar boxTemperature(const Element &element,
+                          const FVElementGeometry fvGeometry,
+                          const int scvIdx) const
+    { return asImp_().temperatureAtPos(fvGeometry.subContVol[scvIdx].global); }
+
+    /*!
+     * \brief Returns the temperature \f$\mathrm{[K]}\f$ at a given global position.
+     *
+     * This is not specific to the discretization. By default it just
+     * calls temperature().
+     *
+     * \param pos The position in global coordinates where the temperature should be specified.
+     */
+    Scalar temperatureAtPos(const GlobalPosition &pos) const
+    { return asImp_().temperature(); }
+
+    /*!
+     * \brief Returns the temperature \f$\mathrm{[K]}\f$ for an isothermal problem.
+     *
+     * This is not specific to the discretization. By default it just
+     * throws an exception so it must be overloaded by the problem if
+     * no energy equation is used.
+     */
+    Scalar temperature() const
+    { DUNE_THROW(Dune::NotImplemented, "temperature() method not implemented by the actual problem"); };
+
+    /*!
+     * \brief Returns the acceleration due to gravity \f$\mathrm{[m/s^2]}\f$.
+     *
+     * This is the box discretization specific interface. By default
+     * it just calls gravityAtPos().
+     */
+    const DimVector &boxGravity(const Element &element,
+                                const FVElementGeometry &fvGeometry,
+                                const int scvIdx) const
+    { return asImp_().gravityAtPos(fvGeometry.subContVol[scvIdx].global); }
+
+    /*!
+     * \brief Returns the acceleration due to gravity \f$\mathrm{[m/s^2]}\f$.
+     *
+     * This is discretization independent interface. By default it
+     * just calls gravity().
+     */
+    const DimVector &gravityAtPos(const GlobalPosition &pos) const
+    { return asImp_().gravity(); }
+
+    /*!
+     * \brief Returns the acceleration due to gravity \f$\mathrm{[m/s^2]}\f$.
+     *
+     * This method is used for problems where the gravitational
+     * acceleration does not depend on the spatial position. The
+     * default behaviour is that if the <tt>EnableGravity</tt>
+     * property is true, \f$\boldsymbol{g} = ( 0,\dots,\ -9.81)^T \f$ holds,
+     * else \f$\boldsymbol{g} = ( 0,\dots, 0)^T \f$.
+     */
+    const DimVector &gravity() const
+    { return gravity_; }
+
+    /*!
+     * \brief Returns the spatial parameters object.
+     */
+    SpatialParams &spatialParams()
+    { return *spatialParams_; }
+    
+    /*!
+     * \brief Returns the spatial parameters object.
+     */
+    const SpatialParams &spatialParams() const
+    { return *spatialParams_; }
+
+    // \}
+
+protected:
+    //! Returns the implementation of the problem (i.e. static polymorphism)
+    Implementation &asImp_()
+    { return *static_cast<Implementation *>(this); }
+    //! \copydoc asImp_()
+    const Implementation &asImp_() const
+    { return *static_cast<const Implementation *>(this); }
+
+    DimVector gravity_;
+
+    // fluids and material properties
+    SpatialParams*  spatialParams_;
+    bool newSpatialParams_;
+};
+
+}
+
+#endif
diff --git a/dumux/implicit/cellcentered/Makefile.am b/dumux/implicit/cellcentered/Makefile.am
new file mode 100644
index 0000000000..79882bb6f4
--- /dev/null
+++ b/dumux/implicit/cellcentered/Makefile.am
@@ -0,0 +1,4 @@
+commondir = $(includedir)/dumux/ccmodels/common
+common_HEADERS = *.hh
+
+include $(top_srcdir)/am/global-rules
diff --git a/dumux/implicit/cellcentered/ccassembler.hh b/dumux/implicit/cellcentered/ccassembler.hh
new file mode 100644
index 0000000000..b4a761a169
--- /dev/null
+++ b/dumux/implicit/cellcentered/ccassembler.hh
@@ -0,0 +1,683 @@
+// -*- mode: C++; tab-width: 4; indent-tabs-mode: nil; c-basic-offset: 4 -*-
+// vi: set et ts=4 sw=4 sts=4:
+/*****************************************************************************
+ *   Copyright (C) 2010-2011 by Andreas Lauser                               *
+ *   Copyright (C) 2009-2010 by Bernd Flemisch                               *
+ *   Institute for Modelling Hydraulic and Environmental Systems             *
+ *   University of Stuttgart, Germany                                        *
+ *   email: <givenname>.<name>@iws.uni-stuttgart.de                          *
+ *                                                                           *
+ *   This program is free software: you can redistribute it and/or modify    *
+ *   it under the terms of the GNU General Public License as published by    *
+ *   the Free Software Foundation, either version 2 of the License, or       *
+ *   (at your option) any later version.                                     *
+ *                                                                           *
+ *   This program is distributed in the hope that it will be useful,         *
+ *   but WITHOUT ANY WARRANTY; without even the implied warranty of          *
+ *   MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the           *
+ *   GNU General Public License for more details.                            *
+ *                                                                           *
+ *   You should have received a copy of the GNU General Public License       *
+ *   along with this program.  If not, see <http://www.gnu.org/licenses/>.   *
+ *****************************************************************************/
+/*!
+ * \file
+ *
+ * \brief An assembler for the global Jacobian matrix for models using the box discretization.
+ */
+#ifndef DUMUX_CC_ASSEMBLER_HH
+#define DUMUX_CC_ASSEMBLER_HH
+
+#include <dune/grid/common/gridenums.hh>
+
+#include <dumux/ccmodels/common/ccproperties.hh>
+#include <dumux/linear/vertexborderlistfromgrid.hh>
+#include <dumux/linear/foreignoverlapfrombcrsmatrix.hh>
+#include <dumux/parallel/vertexhandles.hh>
+
+namespace Dumux {
+
+/*!
+ * \brief An assembler for the global Jacobian matrix for models using the box discretization.
+ */
+template<class TypeTag>
+class CCAssembler
+{
+    typedef typename GET_PROP_TYPE(TypeTag, Model) Model;
+    typedef typename GET_PROP_TYPE(TypeTag, Problem) Problem;
+    typedef typename GET_PROP_TYPE(TypeTag, GridView) GridView;
+    typedef typename GET_PROP_TYPE(TypeTag, Scalar) Scalar;
+    typedef typename GET_PROP_TYPE(TypeTag, VertexMapper) VertexMapper;
+    typedef typename GET_PROP_TYPE(TypeTag, ElementMapper) ElementMapper;
+
+    typedef typename GET_PROP_TYPE(TypeTag, SolutionVector) SolutionVector;
+    typedef typename GET_PROP_TYPE(TypeTag, JacobianMatrix) JacobianMatrix;
+    typedef typename GET_PROP_TYPE(TypeTag, PrimaryVariables) PrimaryVariables;
+
+    enum{ dim = GridView::dimension };
+    typedef typename GridView::template Codim<0>::Entity Element;
+    typedef typename GridView::template Codim<0>::Iterator ElementIterator;
+    typedef typename GridView::template Codim<dim>::EntityPointer VertexPointer;
+    typedef typename GridView::IntersectionIterator IntersectionIterator;
+
+    enum { numEq = GET_PROP_VALUE(TypeTag, NumEq) };
+    typedef Dune::FieldMatrix<Scalar, numEq, numEq> MatrixBlock;
+    typedef Dune::FieldVector<Scalar, numEq> VectorBlock;
+
+    // copying the jacobian assembler is not a good idea
+    CCAssembler(const CCAssembler &);
+
+public:
+    /*!
+     * \brief The colors of elements required for partial
+     *        Jacobian reassembly.
+     */
+    enum EntityColor {
+        /*!
+         * Element that needs to be reassembled because some
+         * relative error is above the tolerance
+         */
+        Red = 0,
+
+        /*!
+         * Element that does not need to be reassembled
+         */
+        Green = 3
+    };
+
+    CCAssembler()
+    {
+        problemPtr_ = 0;
+        matrix_ = 0;
+
+        // set reassemble accuracy to 0, so that if partial reassembly
+        // of the jacobian matrix is disabled, the reassemble accuracy
+        // is always smaller than the current relative tolerance
+        reassembleAccuracy_ = 0.0;
+    }
+
+    ~CCAssembler()
+    {
+        delete matrix_;
+    }
+
+    /*!
+     * \brief Initialize the jacobian assembler.
+     *
+     * At this point we can assume that all objects in the problem and
+     * the model have been allocated. We can not assume that they are
+     * fully initialized, though.
+     *
+     * \param problem The problem object
+     */
+    void init(Problem& problem)
+    {
+        problemPtr_ = &problem;
+
+        // initialize the BCRS matrix
+        createMatrix_();
+
+        // initialize the jacobian matrix and the right hand side
+        // vector
+        *matrix_ = 0;
+        reuseMatrix_ = false;
+
+        int numElems = gridView_().size(0);
+
+        residual_.resize(numElems);
+
+        // initialize the storage part of the Jacobian matrix. Since
+        // we only need this if Jacobian matrix recycling is enabled,
+        // we do not waste space if it is disabled
+        if (enableJacobianRecycling_()) {
+            storageJacobian_.resize(numElems);
+            storageTerm_.resize(numElems);
+        }
+
+        if (gridView_().comm().size() > 1)
+            totalElems_ = gridView_().comm().sum(numElems);
+        else
+            totalElems_ = numElems;
+
+        // initialize data needed for partial reassembly
+        if (enablePartialReassemble_()) 
+        {
+            elementColor_.resize(numElems);
+            elementDelta_.resize(numElems);
+        }
+        
+        reassembleAll();
+    }
+
+    /*!
+     * \brief Assemble the global Jacobian of the residual and the residual for the current solution.
+     *
+     * The current state of affairs (esp. the previous and the current
+     * solutions) is represented by the model object.
+     */
+    void assemble()
+    {
+        bool printReassembleStatistics = enablePartialReassemble_() && !reuseMatrix_;
+        int succeeded;
+        try {
+            assemble_();
+            succeeded = 1;
+            if (gridView_().comm().size() > 1)
+                succeeded = gridView_().comm().min(succeeded);
+        }
+        catch (Dumux::NumericalProblem &e)
+        {
+            std::cout << "rank " << problem_().gridView().comm().rank()
+                      << " caught an exception while assembling:" << e.what()
+                      << "\n";
+            succeeded = 0;
+            if (gridView_().comm().size() > 1)
+                succeeded = gridView_().comm().min(succeeded);
+        }
+
+        if (!succeeded) {
+            DUNE_THROW(NumericalProblem,
+                       "A process did not succeed in linearizing the system");
+        }
+        
+        if (printReassembleStatistics)
+        {
+            if (gridView_().comm().size() > 1)
+            {
+                greenElems_ = gridView_().comm().sum(greenElems_);
+                reassembleAccuracy_ = gridView_().comm().max(nextReassembleAccuracy_);
+            }
+            else
+            {
+                reassembleAccuracy_ = nextReassembleAccuracy_;
+            }
+
+            problem_().newtonController().endIterMsg()
+                << ", reassembled "
+                << totalElems_ - greenElems_ << "/" << totalElems_
+                << " (" << 100*Scalar(totalElems_ - greenElems_)/totalElems_ << "%) elems @accuracy="
+                << reassembleAccuracy_;
+        }
+    }
+
+   /*!
+    * \brief If Jacobian matrix recycling is enabled, this method
+    *        specifies whether the next call to assemble() just
+    *        rescales the storage term or does a full reassembly
+    *
+    * \param yesno If true, only rescale; else do full Jacobian assembly.
+    */
+   void setMatrixReuseable(bool yesno = true) 
+    {
+        if (enableJacobianRecycling_())
+            reuseMatrix_ = yesno;        
+    }
+    
+    /*!
+     * \brief If partial Jacobian matrix reassembly is enabled, this
+     *        method causes all elements to be reassembled in the next
+     *        assemble() call.
+     */
+    void reassembleAll() 
+    {
+        // do not reuse the current linearization
+        reuseMatrix_ = false;
+
+        // do not use partial reassembly for the next iteration
+        nextReassembleAccuracy_ = 0.0;
+        if (enablePartialReassemble_()) {
+            std::fill(elementColor_.begin(),
+                      elementColor_.end(),
+                      Red);
+            std::fill(elementDelta_.begin(),
+                      elementDelta_.end(),
+                      0.0);
+        }
+    }
+    
+    /*!
+     * \brief Returns the largest relative error of a "green" vertex
+     *        for the most recent call of the assemble() method.
+     *
+     * This only has an effect if partial Jacobian reassembly is
+     * enabled. If it is disabled, then this method always returns 0.
+     *
+     * This returns the _actual_ relative computed seen by
+     * computeColors(), not the tolerance which it was given.
+     */
+    Scalar reassembleAccuracy() const
+    { return reassembleAccuracy_; }
+
+    /*!
+     * \brief Update the distance where the non-linear system was
+     *        originally insistently linearized and the point where it
+     *        will be linerized the next time.
+     *
+     * This only has an effect if partial reassemble is enabled.
+     */
+    void updateDiscrepancy(const SolutionVector &u,
+                           const SolutionVector &uDelta) 
+    {
+        if (!enablePartialReassemble_())
+            return;
+
+        // update the vector with the distances of the current
+        // evaluation point used for linearization from the original
+        // evaluation point
+        for (unsigned int i = 0; i < elementDelta_.size(); ++i) {
+            PrimaryVariables currentPriVars(u[i]);
+            PrimaryVariables nextPriVars(currentPriVars);
+            nextPriVars -= uDelta[i];
+
+            // we need to add the distance the solution was moved for
+            // this vertex
+            Scalar dist = model_().relativeErrorVertex(i,
+                                                       currentPriVars,
+                                                       nextPriVars);
+            elementDelta_[i] += std::abs(dist);
+        }
+    }
+    
+    /*!
+     * \brief Determine the colors of elements for partial
+     *        reassembly given a relative tolerance.
+     *
+     * The following approach is used:
+     *
+     * - Set all elements to 'green'
+     * - Mark all elements as 'red' which exhibit an relative error above
+     *   the tolerance
+     * - Mark all neighbors of 'red' elements also 'red'
+     *
+     * \param relTol The relative error below which an element won't be
+     *               reassembled. Note that this specifies the
+     *               worst-case relative error between the last
+     *               linearization point and the current solution and
+     *               _not_ the delta vector of the Newton iteration!
+     */
+    void computeColors(Scalar relTol) 
+    {
+        if (!enablePartialReassemble_())
+            return;
+
+        ElementIterator elemIt = gridView_().template begin<0>();
+        ElementIterator elemEndIt = gridView_().template end<0>();
+
+        // mark the red elements and update the tolerance of the
+        // linearization which actually will get achieved
+        nextReassembleAccuracy_ = 0;
+        for (; elemIt != elemEndIt; ++elemIt) {
+            int elemIdx = this->elementMapper_().map(*elemIt);
+            if (elementDelta_[elemIdx] > relTol)
+            {
+                // mark element as red if discrepancy is larger than
+                // the relative tolerance
+                elementColor_[elemIdx] = Red;
+            }
+            else
+            {
+                elementColor_[elemIdx] = Green;
+                nextReassembleAccuracy_ =
+                    std::max(nextReassembleAccuracy_, elementDelta_[elemIdx]);
+            }
+        }
+
+        // mark the neighbors also red
+        elemIt = gridView_().template begin<0>();
+        for (; elemIt != elemEndIt; ++elemIt) {
+            int elemIdx = this->elementMapper_().map(*elemIt);
+            if (elementColor_[elemIdx] == Red) 
+                continue; // element is red already!
+
+            if (elementDelta_[elemIdx] > relTol)
+            {
+                // also mark the neighbors 
+               IntersectionIterator endIsIt = gridView_().iend(*elemIt);
+               for (IntersectionIterator isIt = gridView_().ibegin(*elemIt); isIt != endIsIt; ++isIt)
+               {
+                   if (isIt->neighbor())
+                   {
+                       int neighborIdx = this->elementMapper_().map(*isIt->outside());
+                       elementColor_[neighborIdx] = Red;
+                   }
+               }
+            }
+        }
+        
+        // set the discrepancy of the red elements to zero
+        for (int i = 0; i < elementDelta_.size(); i++)
+            if (elementColor_[i] == Red)
+                elementDelta_[i] = 0;
+    }
+    
+    /*!
+     * \brief Returns the Jacobian reassemble color of an element
+     *
+     * \param element The Codim-0 DUNE entity
+     */
+    int elementColor(const Element &element) const
+    {
+        if (!enablePartialReassemble_())
+            return Red; // reassemble unconditionally!
+
+        int globalIdx = elementMapper_().map(element);
+        return elementColor_[globalIdx];
+    }
+
+    /*!
+     * \brief Returns the Jacobian reassemble color of an element
+     *
+     * \param globalElementIdx The global index of the element.
+     */
+    int elementColor(const int globalElementIdx) const
+    {
+        if (!enablePartialReassemble_())
+            return Red; // reassemble unconditionally!
+        return elementColor_[globalElementIdx];
+    }
+
+    /*!
+     * \brief Return constant reference to global Jacobian matrix.
+     */
+    const JacobianMatrix& matrix() const
+    { return *matrix_; }
+    JacobianMatrix& matrix()
+    { return *matrix_; }
+    
+    /*!
+     * \brief Return constant reference to global residual vector.
+     */
+    const SolutionVector& residual() const
+    { return residual_; }
+    SolutionVector& residual() 
+    { return residual_; }
+    
+    // functions needed for interface consistence
+    void markVertexRed(const int globalVertIdx) {}
+
+private:
+    static bool enableJacobianRecycling_()
+    { return GET_PARAM_FROM_GROUP(TypeTag, bool, Implicit, EnableJacobianRecycling); }
+    static bool enablePartialReassemble_()
+    { return GET_PARAM_FROM_GROUP(TypeTag, bool, Implicit, EnablePartialReassemble); }
+
+    // Construct the BCRS matrix for the global jacobian
+    void createMatrix_()
+    {
+        int nElems = gridView_().size(0);
+
+        // allocate raw matrix
+        matrix_ = new JacobianMatrix(nElems, nElems, JacobianMatrix::random);
+
+        // find out the global indices of the neighboring elements of
+        // each element
+        typedef std::set<int> NeighborSet;
+        std::vector<NeighborSet> neighbors(nElems);
+        ElementIterator eIt = gridView_().template begin<0>();
+        const ElementIterator eEndIt = gridView_().template end<0>();
+        for (; eIt != eEndIt; ++eIt) {
+            const Element &elem = *eIt;
+            
+            int globalI = elementMapper_().map(elem);
+            neighbors[globalI].insert(globalI);
+
+            // if the element is ghost,
+            // all dofs just contain main-diagonal entries
+            //if (elem.partitionType() == Dune::GhostEntity)
+            //    continue;
+
+            // loop over all neighbors
+            IntersectionIterator isIt = gridView_().ibegin(elem);
+            const IntersectionIterator &endIt = gridView_().iend(elem);
+            for (; isIt != endIt; ++isIt)
+            {
+                if (isIt->neighbor())
+                {
+                    int globalJ = elementMapper_().map(*(isIt->outside()));
+                    neighbors[globalI].insert(globalJ);
+                }
+            }
+        }
+
+        // allocate space for the rows of the matrix
+        for (int i = 0; i < nElems; ++i) {
+            matrix_->setrowsize(i, neighbors[i].size());
+        }
+        matrix_->endrowsizes();
+
+        // fill the rows with indices. each element talks to all of its
+        // neighbors and itself.
+        for (int i = 0; i < nElems; ++i) {
+            typename NeighborSet::iterator nIt = neighbors[i].begin();
+            typename NeighborSet::iterator nEndIt = neighbors[i].end();
+            for (; nIt != nEndIt; ++nIt) {
+                matrix_->addindex(i, *nIt);
+            }
+        }
+        matrix_->endindices();
+    }
+    
+    // reset the global linear system of equations. if partial
+    // reassemble is enabled, this means that the jacobian matrix must
+    // only be erased partially!
+    void resetSystem_()
+    {
+        // do not do anything if we can re-use the current linearization
+        if (reuseMatrix_)
+            return;
+
+        // reset the right hand side.
+        residual_ = 0.0;
+
+        if (!enablePartialReassemble_()) {
+            // If partial reassembly of the jacobian is not enabled,
+            // we can just reset everything!
+            (*matrix_) = 0;
+
+            // reset the parts needed for Jacobian recycling
+            if (enableJacobianRecycling_()) {
+                int numElementsGlobal = matrix_->N();
+                for (int i=0; i < numElementsGlobal; ++ i) {
+                    storageJacobian_[i] = 0;
+                    storageTerm_[i] = 0;
+                }
+            }
+
+            return;
+        }
+
+        // reset all entries corrosponding to a red or yellow vertex
+        for (unsigned int rowIdx = 0; rowIdx < matrix_->N(); ++rowIdx) {
+            if (elementColor_[rowIdx] == Green)
+                continue; // the equations for this control volume are
+                          // already below the treshold
+
+            // reset the parts needed for Jacobian recycling
+            if (enableJacobianRecycling_()) {
+                storageJacobian_[rowIdx] = 0;
+                storageTerm_[rowIdx] = 0;
+            }
+
+            // set all matrix entries in the row to 0
+            typedef typename JacobianMatrix::ColIterator ColIterator;
+            ColIterator colIt = (*matrix_)[rowIdx].begin();
+            const ColIterator &colEndIt = (*matrix_)[rowIdx].end();
+            for (; colIt != colEndIt; ++colIt) {
+                (*colIt) = 0.0;
+            }
+        }
+    }
+
+    // linearize the whole system
+    void assemble_()
+    {
+        resetSystem_();
+
+        // if we can "recycle" the current linearization, we do it
+        // here and be done with it...
+        Scalar curDt = problem_().timeManager().timeStepSize();
+        if (reuseMatrix_) {
+            int numElementsGlobal = storageJacobian_.size();
+            for (int i = 0; i < numElementsGlobal; ++i) {
+                // rescale the mass term of the jacobian matrix
+                MatrixBlock &J_i_i = (*matrix_)[i][i];
+
+                J_i_i -= storageJacobian_[i];
+                storageJacobian_[i] *= oldDt_/curDt;
+                J_i_i += storageJacobian_[i];
+
+                // use the flux term plus the source term as the new
+                // residual (since the delta in the d(storage)/dt is 0
+                // for the first iteration and the residual is
+                // approximately 0 in the last iteration, the flux
+                // term plus the source term must be equal to the
+                // negative change of the storage term of the last
+                // iteration of the last time step...)
+                residual_[i] = storageTerm_[i];
+                residual_[i] *= -1;
+            }
+
+            reuseMatrix_ = false;
+            oldDt_ = curDt;
+            return;
+        }
+
+        oldDt_ = curDt;
+        greenElems_ = 0;
+        
+        // reassemble the elements...
+        ElementIterator elemIt = gridView_().template begin<0>();
+        ElementIterator elemEndIt = gridView_().template end<0>();
+        for (; elemIt != elemEndIt; ++elemIt) {
+            const Element &elem = *elemIt;
+            if (elem.partitionType() == Dune::GhostEntity)
+            {
+                assembleGhostElement_(elem);
+            }
+            else
+            {
+                assembleElement_(elem);
+            }
+        }
+    }
+
+    // assemble a non-ghost element
+    void assembleElement_(const Element &elem)
+    {
+        if (enablePartialReassemble_()) {
+            int globalElemIdx = model_().elementMapper().map(elem);
+            if (elementColor_[globalElemIdx] == Green) {
+                ++greenElems_;
+
+                assembleGreenElement_(elem);
+                return;
+            }
+        }
+
+        model_().localJacobian().assemble(elem);
+
+        int globalI = elementMapper_().map(elem);
+
+        // update the right hand side
+        residual_[globalI] = model_().localJacobian().residual(0);
+        for (int j = 0; j < residual_[globalI].dimension; ++j)
+            assert(std::isfinite(residual_[globalI][j]));
+        if (enableJacobianRecycling_()) {
+            storageTerm_[globalI] +=
+                model_().localJacobian().storageTerm(0);
+        }
+
+        if (enableJacobianRecycling_())
+            storageJacobian_[globalI] +=
+                model_().localJacobian().storageJacobian(0);
+
+        // update the diagonal entry 
+        (*matrix_)[globalI][globalI] = model_().localJacobian().mat(0,0);
+
+        IntersectionIterator isIt = gridView_().ibegin(elem);
+        const IntersectionIterator &endIt = gridView_().iend(elem);
+        for (int j = 0; isIt != endIt; ++isIt)
+        {
+            if (isIt->neighbor())
+            {
+                int globalJ = elementMapper_().map(*(isIt->outside()));
+                (*matrix_)[globalI][globalJ] = model_().localJacobian().mat(0,++j);
+            }
+        }
+    }
+
+    // "assemble" a green element. green elements only get the
+    // residual updated, but the jacobian is left alone...
+    void assembleGreenElement_(const Element &elem)
+    {
+        model_().localResidual().eval(elem);
+
+        int globalI = elementMapper_().map(elem);
+
+        // update the right hand side
+        residual_[globalI] += model_().localResidual().residual(0);
+        if (enableJacobianRecycling_())
+            storageTerm_[globalI] += model_().localResidual().storageTerm(0);
+    }
+
+    // "assemble" a ghost element
+    void assembleGhostElement_(const Element &elem)
+    {
+        int globalI = elementMapper_().map(elem);
+
+        // update the right hand side
+        residual_[globalI] = 0.0;
+
+        // update the diagonal entry 
+        typedef typename JacobianMatrix::block_type BlockType;
+        BlockType &J = (*matrix_)[globalI][globalI];
+        for (int j = 0; j < BlockType::rows; ++j)
+            J[j][j] = 1.0;
+    }
+
+
+    Problem &problem_()
+    { return *problemPtr_; }
+    const Problem &problem_() const
+    { return *problemPtr_; }
+    const Model &model_() const
+    { return problem_().model(); }
+    Model &model_()
+    { return problem_().model(); }
+    const GridView &gridView_() const
+    { return problem_().gridView(); }
+    const VertexMapper &vertexMapper_() const
+    { return problem_().vertexMapper(); }
+    const ElementMapper &elementMapper_() const
+    { return problem_().elementMapper(); }
+
+    Problem *problemPtr_;
+
+    // the jacobian matrix
+    JacobianMatrix *matrix_;
+    // the right-hand side
+    SolutionVector residual_;
+    
+    // attributes required for jacobian matrix recycling
+    bool reuseMatrix_;
+    // The storage part of the local Jacobian
+    std::vector<MatrixBlock> storageJacobian_;
+    std::vector<VectorBlock> storageTerm_;
+    // time step size of last assembly
+    Scalar oldDt_;
+
+
+    // attributes required for partial jacobian reassembly
+    std::vector<EntityColor> elementColor_;
+    std::vector<Scalar> elementDelta_;
+
+    int totalElems_;
+    int greenElems_;
+
+    Scalar nextReassembleAccuracy_;
+    Scalar reassembleAccuracy_;
+};
+
+} // namespace Dumux
+
+#endif
diff --git a/dumux/implicit/cellcentered/ccelementboundarytypes.hh b/dumux/implicit/cellcentered/ccelementboundarytypes.hh
new file mode 100644
index 0000000000..dd4c7ff2b5
--- /dev/null
+++ b/dumux/implicit/cellcentered/ccelementboundarytypes.hh
@@ -0,0 +1,150 @@
+// -*- mode: C++; tab-width: 4; indent-tabs-mode: nil; c-basic-offset: 4 -*-
+// vi: set et ts=4 sw=4 sts=4:
+/*****************************************************************************
+ *   Copyright (C) 2010 by Andreas Lauser                                    *
+ *   Institute for Modelling Hydraulic and Environmental Systems             *
+ *   University of Stuttgart, Germany                                        *
+ *   email: <givenname>.<name>@iws.uni-stuttgart.de                          *
+ *                                                                           *
+ *   This program is free software: you can redistribute it and/or modify    *
+ *   it under the terms of the GNU General Public License as published by    *
+ *   the Free Software Foundation, either version 2 of the License, or       *
+ *   (at your option) any later version.                                     *
+ *                                                                           *
+ *   This program is distributed in the hope that it will be useful,         *
+ *   but WITHOUT ANY WARRANTY; without even the implied warranty of          *
+ *   MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the           *
+ *   GNU General Public License for more details.                            *
+ *                                                                           *
+ *   You should have received a copy of the GNU General Public License       *
+ *   along with this program.  If not, see <http://www.gnu.org/licenses/>.   *
+ *****************************************************************************/
+/*!
+ * \file
+ *
+ * \brief Boundary types gathered on an element
+ */
+#ifndef DUMUX_CC_ELEMENT_BOUNDARY_TYPES_HH
+#define DUMUX_CC_ELEMENT_BOUNDARY_TYPES_HH
+
+#include "ccproperties.hh"
+
+#include <dumux/common/valgrind.hh>
+
+namespace Dumux
+{
+
+/*!
+ * \ingroup CCModel
+ * \ingroup CCBoundaryTypes
+ *
+ * \brief This class stores an array of BoundaryTypes objects
+ */
+template<class TypeTag>
+class CCElementBoundaryTypes : public std::vector<typename GET_PROP_TYPE(TypeTag, BoundaryTypes) >
+{
+    typedef typename GET_PROP_TYPE(TypeTag, BoundaryTypes) BoundaryTypes;
+    typedef std::vector<BoundaryTypes> ParentType;
+
+    typedef typename GET_PROP_TYPE(TypeTag, Problem) Problem;
+    typedef typename GET_PROP_TYPE(TypeTag, GridView) GridView;
+    typedef typename GET_PROP_TYPE(TypeTag, FVElementGeometry) FVElementGeometry;
+
+    enum { dim = GridView::dimension };
+    typedef typename GridView::template Codim<0>::Entity Element;
+    typedef typename GridView::template Codim<dim>::EntityPointer VertexPointer;
+    typedef typename GridView::IntersectionIterator IntersectionIterator;
+
+public:
+    /*!
+     * \brief Copy constructor.
+     *
+     * Copying a the boundary types of an element should be explicitly
+     * requested
+     */
+    explicit CCElementBoundaryTypes(const CCElementBoundaryTypes &v)
+        : ParentType(v)
+    {}
+
+    /*!
+     * \brief Default constructor.
+     */
+    CCElementBoundaryTypes()
+    {
+        hasDirichlet_ = false;
+        hasNeumann_ = false;
+        hasOutflow_ = false;
+    }
+
+    /*!
+     * \brief Update the boundary types for all vertices of an element.
+     *
+     * \param problem The problem object which needs to be simulated
+     * \param element The DUNE Codim<0> entity for which the boundary
+     *                types should be collected
+     */
+    void update(const Problem &problem,
+                const Element &element)
+    {
+        this->resize(1);
+
+        hasDirichlet_ = false;
+        hasNeumann_ = false;
+        hasOutflow_ = false;
+
+        (*this)[0].reset();
+
+        if (!problem.model().onBoundary(element))
+            return;
+
+        IntersectionIterator isIt = problem.gridView().ibegin(element);
+        IntersectionIterator isEndIt = problem.gridView().iend(element);
+        for (; isIt != isEndIt; ++isIt) {
+            if (!isIt->boundary())
+                continue;
+
+            problem.boundaryTypes((*this)[0], *isIt);
+
+            hasDirichlet_ = hasDirichlet_ || (*this)[0].hasDirichlet();
+            hasNeumann_ = hasNeumann_ || (*this)[0].hasNeumann();
+            hasOutflow_ = hasOutflow_ || (*this)[0].hasOutflow();
+        }
+    }
+
+    void update(const Problem &problem,
+                const Element &element,
+                const FVElementGeometry &fvGeometry)
+    {
+        update(problem, element);
+    }
+
+    /*!
+     * \brief Returns whether the element has a vertex which contains
+     *        a Dirichlet value.
+     */
+    bool hasDirichlet() const
+    { return hasDirichlet_; }
+
+    /*!
+     * \brief Returns whether the element potentially features a
+     *        Neumann boundary segment.
+     */
+    bool hasNeumann() const
+    { return hasNeumann_; }
+
+    /*!
+     * \brief Returns whether the element potentially features an
+     *        outflow boundary segment.
+     */
+    bool hasOutflow() const
+    { return hasOutflow_; }
+
+protected:
+    bool hasDirichlet_;
+    bool hasNeumann_;
+    bool hasOutflow_;
+};
+
+} // namespace Dumux
+
+#endif
diff --git a/dumux/implicit/cellcentered/ccelementvolumevariables.hh b/dumux/implicit/cellcentered/ccelementvolumevariables.hh
new file mode 100644
index 0000000000..6700444b86
--- /dev/null
+++ b/dumux/implicit/cellcentered/ccelementvolumevariables.hh
@@ -0,0 +1,107 @@
+// -*- mode: C++; tab-width: 4; indent-tabs-mode: nil; c-basic-offset: 4 -*-
+// vi: set et ts=4 sw=4 sts=4:
+/*****************************************************************************
+ *   Copyright (C) 2010 by Andreas Lauser                                    *
+ *   Institute for Modelling Hydraulic and Environmental Systems             *
+ *   University of Stuttgart, Germany                                        *
+ *   email: <givenname>.<name>@iws.uni-stuttgart.de                          *
+ *                                                                           *
+ *   This program is free software: you can redistribute it and/or modify    *
+ *   it under the terms of the GNU General Public License as published by    *
+ *   the Free Software Foundation, either version 2 of the License, or       *
+ *   (at your option) any later version.                                     *
+ *                                                                           *
+ *   This program is distributed in the hope that it will be useful,         *
+ *   but WITHOUT ANY WARRANTY; without even the implied warranty of          *
+ *   MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the           *
+ *   GNU General Public License for more details.                            *
+ *                                                                           *
+ *   You should have received a copy of the GNU General Public License       *
+ *   along with this program.  If not, see <http://www.gnu.org/licenses/>.   *
+ *****************************************************************************/
+/*!
+ * \file
+ *
+ * \brief Volume variables gathered on an element
+ */
+#ifndef DUMUX_CC_ELEMENT_VOLUME_VARIABLES_HH
+#define DUMUX_CC_ELEMENT_VOLUME_VARIABLES_HH
+
+#include "ccproperties.hh"
+
+
+namespace Dumux
+{
+
+/*!
+ * \ingroup CCModel
+ *
+ * \brief This class stores an array of VolumeVariables objects, one
+ *        volume variables object for each of the element's vertices
+ */
+template<class TypeTag>
+class CCElementVolumeVariables : public std::vector<typename GET_PROP_TYPE(TypeTag, VolumeVariables) >
+{
+    typedef typename GET_PROP_TYPE(TypeTag, Problem) Problem;
+    typedef typename GET_PROP_TYPE(TypeTag, FVElementGeometry) FVElementGeometry;
+    typedef typename GET_PROP_TYPE(TypeTag, SolutionVector) SolutionVector;
+    typedef typename GET_PROP_TYPE(TypeTag, VertexMapper) VertexMapper;
+    typedef typename GET_PROP_TYPE(TypeTag, PrimaryVariables) PrimaryVariables;
+
+    typedef typename GET_PROP_TYPE(TypeTag, GridView) GridView;
+    typedef typename GridView::template Codim<0>::Entity Element;
+
+    enum { dim = GridView::dimension };
+    enum { numEq = GET_PROP_VALUE(TypeTag, NumEq) };
+
+public:
+    /*!
+     * \brief The constructor.
+     */
+    CCElementVolumeVariables()
+    { }
+
+    /*!
+     * \brief Construct the volume variables for all of vertices of an element.
+     *
+     * \param problem The problem which needs to be simulated.
+     * \param element The DUNE Codim<0> entity for which the volume variables ought to be calculated
+     * \param fvElemGeom The finite volume geometry of the element
+     * \param oldSol Tells whether the model's previous or current solution should be used.
+     */
+    void update(const Problem &problem,
+                const Element &element,
+                const FVElementGeometry &fvElemGeom,
+                bool oldSol)
+    {
+        const SolutionVector &globalSol =
+            oldSol?
+            problem.model().prevSol():
+            problem.model().curSol();
+
+        int numNeighbors = fvElemGeom.numNeighbors;
+        this->resize(numNeighbors);
+        
+        for (int i = 0; i < numNeighbors; i++)
+        {
+            const Element& neighbor = *(fvElemGeom.neighbors[i]);
+            
+            const PrimaryVariables &solI
+                    = globalSol[problem.elementMapper().map(neighbor)];
+
+            FVElementGeometry neighborFVGeom;
+            neighborFVGeom.updateInner(problem.gridView(), neighbor);
+            
+            (*this)[i].update(solI,
+                              problem,
+                              neighbor,
+                              neighborFVGeom,
+                              /*scvIdx=*/0,
+                              oldSol);
+        }
+    }
+};
+
+} // namespace Dumux
+
+#endif
diff --git a/dumux/implicit/cellcentered/ccfvelementgeometry.hh b/dumux/implicit/cellcentered/ccfvelementgeometry.hh
new file mode 100644
index 0000000000..9c9020db23
--- /dev/null
+++ b/dumux/implicit/cellcentered/ccfvelementgeometry.hh
@@ -0,0 +1,219 @@
+// -*- mode: C++; tab-width: 4; indent-tabs-mode: nil; c-basic-offset: 4 -*-
+// vi: set et ts=4 sw=4 sts=4:
+/*****************************************************************************
+ *   Copyright (C) 2008-2012 by Bernd Flemisch, Andreas Lauser               *
+ *   Institute for Modelling Hydraulic and Environmental Systems             *
+ *   University of Stuttgart, Germany                                        *
+ *   email: <givenname>.<name>@iws.uni-stuttgart.de                          *
+ *                                                                           *
+ *   This program is free software: you can redistribute it and/or modify    *
+ *   it under the terms of the GNU General Public License as published by    *
+ *   the Free Software Foundation, either version 2 of the License, or       *
+ *   (at your option) any later version.                                     *
+ *                                                                           *
+ *   This program is distributed in the hope that it will be useful,         *
+ *   but WITHOUT ANY WARRANTY; without even the implied warranty of          *
+ *   MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the           *
+ *   GNU General Public License for more details.                            *
+ *                                                                           *
+ *   You should have received a copy of the GNU General Public License       *
+ *   along with this program.  If not, see <http://www.gnu.org/licenses/>.   *
+ *****************************************************************************/
+/*!
+ * \file
+ *
+ * \brief Represents the finite volume geometry of a single element in
+ *        the box scheme.
+ */
+#ifndef DUMUX_CC_FV_ELEMENTGEOMETRY_HH
+#define DUMUX_CC_FV_ELEMENTGEOMETRY_HH
+
+#include <dune/common/version.hh>
+#include <dune/grid/common/intersectioniterator.hh>
+
+#if DUNE_VERSION_NEWER_REV(DUNE_COMMON, 2, 2, 0)
+// dune 2.2
+#include <dune/geometry/referenceelements.hh>
+#else
+// dune 2.1
+#include <dune/geometry/referenceelements.hh>
+#endif
+
+#include <dune/localfunctions/lagrange/pqkfactory.hh>
+
+#include <dumux/common/propertysystem.hh>
+
+namespace Dumux
+{
+namespace Properties
+{
+NEW_PROP_TAG(GridView);
+NEW_PROP_TAG(Scalar);
+}
+
+/*!
+ * \brief Represents the finite volume geometry of a single element in
+ *        the cell centered fv scheme.
+ */
+template<class TypeTag>
+class CCFVElementGeometry
+{
+    typedef typename GET_PROP_TYPE(TypeTag, GridView) GridView;
+    enum{dim = GridView::dimension};
+    enum{dimWorld = GridView::dimensionworld};
+
+    enum{maxNFAP = 2};
+    enum{maxNE = (dim < 3 ? 4 : 12)};
+    enum{maxNF = (dim < 3 ? 1 : 6)};
+    enum{maxCOS = (dim < 3 ? 2 : 4)};
+    enum{maxBF = (dim < 3 ? 8 : 24)};
+    typedef typename GET_PROP_TYPE(TypeTag, Scalar) Scalar;
+    typedef typename GridView::ctype CoordScalar;
+    typedef typename GridView::Traits::template Codim<0>::Entity Element;
+    typedef typename GridView::Traits::template Codim<0>::EntityPointer ElementPointer;
+    typedef typename Element::Geometry Geometry;
+    typedef Dune::FieldVector<Scalar,dimWorld> Vector;
+    typedef Dune::FieldVector<CoordScalar,dimWorld> GlobalPosition;
+    typedef Dune::FieldVector<CoordScalar,dim> LocalPosition;
+    typedef typename GridView::IntersectionIterator IntersectionIterator;
+
+public:
+    struct SubControlVolume //! FV intersected with element
+    {
+        LocalPosition local; //!< local vert position
+        GlobalPosition global; //!< global vert position
+        Scalar volume; //!< volume of scv
+        bool inner;
+    };
+
+    struct SubControlVolumeFace //! interior face of a sub control volume
+    {
+        int i,j; //!< scvf seperates corner i and j of elem
+        LocalPosition ipLocal; //!< integration point in local coords
+        GlobalPosition ipGlobal; //!< integration point in global coords
+        Vector normal; //!< normal on face pointing to CV j or outward of the domain with length equal to |scvf|
+        Scalar area; //!< area of face
+        Dune::FieldVector<Vector, maxNFAP> grad; //!< derivatives of shape functions at ip
+        Dune::FieldVector<Scalar, maxNFAP> shapeValue; //!< value of shape functions at ip
+        Dune::FieldVector<int, maxNFAP> fapIndices; //!< indices w.r.t.neighbors of the flux approximation points
+    };
+
+    typedef SubControlVolumeFace BoundaryFace; //!< compatibility typedef
+
+    LocalPosition elementLocal; //!< local coordinate of element center
+    GlobalPosition elementGlobal; //!< global coordinate of element center
+    Scalar elementVolume; //!< element volume
+    SubControlVolume subContVol[1]; //!< data of the sub control volumes
+    SubControlVolumeFace subContVolFace[maxNE]; //!< data of the sub control volume faces
+    BoundaryFace boundaryFace[maxBF]; //!< data of the boundary faces
+    int numVertices; //!< number of verts
+    int numEdges; //!< number of edges
+    int numFaces; //!< number of faces (0 in < 3D)
+    int numSCV; //!< number of subcontrol volumes
+    int numNeighbors; //!< number of neighboring elements including the element itself
+    int numFAP; //!< number of flux approximation points
+    std::vector<ElementPointer> neighbors; //!< stores pointers for the neighboring elements
+    
+    void updateInner(const GridView& gridView, const Element& e)
+    {
+        const Geometry& geometry = e.geometry();
+
+        elementVolume = geometry.volume();
+        elementGlobal = geometry.center();
+        elementLocal = geometry.local(elementGlobal);
+
+        numVertices = e.template count<dim>();
+        numEdges = e.template count<dim-1>();
+        numFaces = (dim<3)? 0 : e.template count<1>();
+        numSCV = 1;
+        numFAP = 2;
+        
+        subContVol[0].local = elementLocal;
+        subContVol[0].global = elementGlobal;
+        subContVol[0].inner = true;
+        subContVol[0].volume = elementVolume;
+
+        // initialize neighbors list with self: 
+        numNeighbors = 1;
+        neighbors.clear();
+        neighbors.reserve(maxNE);
+        ElementPointer elementPointer(e);
+        neighbors.push_back(elementPointer);
+    }
+    
+    void update(const GridView& gridView, const Element& e)
+    {
+        updateInner(gridView, e);
+        
+        const Geometry& geometry = e.geometry();
+
+        // fill neighbor information and control volume face data:
+        IntersectionIterator endit = gridView.iend(e);
+        for (IntersectionIterator it = gridView.ibegin(e); it != endit; ++it)
+        {
+            // neighbor information and inner cvf data:
+            if (it->neighbor())
+            {
+                numNeighbors++;
+                ElementPointer elementPointer(it->outside());
+                neighbors.push_back(elementPointer);
+                
+                int k = numNeighbors - 2;
+                
+                subContVolFace[k].i = 0;
+                subContVolFace[k].j = k+1;
+                
+                subContVolFace[k].ipGlobal = it->geometry().center();
+                subContVolFace[k].ipLocal =  geometry.local(subContVolFace[k].ipGlobal);
+                subContVolFace[k].normal = it->centerUnitOuterNormal();
+                subContVolFace[k].normal *= it->geometry().volume();
+                subContVolFace[k].area = it->geometry().volume();
+
+                GlobalPosition distVec = elementGlobal;
+                distVec -= neighbors[k+1]->geometry().center();
+                distVec /= distVec.two_norm2();
+                
+                // gradients using a two-point flux approximation
+                for (int idx = 0; idx < 2; idx++)
+                {
+                    subContVolFace[k].grad[idx] = distVec;
+                    subContVolFace[k].shapeValue[idx] = 0.5;
+                }
+                subContVolFace[k].grad[1] *= -1.0;
+                
+                subContVolFace[k].fapIndices[0] = subContVolFace[k].i;
+                subContVolFace[k].fapIndices[1] = subContVolFace[k].j;
+            }
+
+            // boundary cvf data
+            if (it->boundary())
+            {
+                int bfIdx = it->indexInInside();
+                boundaryFace[bfIdx].ipGlobal = it->geometry().center();
+                boundaryFace[bfIdx].ipLocal =  geometry.local(boundaryFace[bfIdx].ipGlobal);
+                boundaryFace[bfIdx].normal = it->centerUnitOuterNormal();
+                boundaryFace[bfIdx].normal *= it->geometry().volume();
+                boundaryFace[bfIdx].area = it->geometry().volume();
+                boundaryFace[bfIdx].i = 0;
+                boundaryFace[bfIdx].j = 0;
+
+                GlobalPosition distVec = elementGlobal;
+                distVec -= boundaryFace[bfIdx].ipGlobal;
+                distVec /= distVec.two_norm2();
+                
+                // gradients using a two-point flux approximation
+                for (int idx = 0; idx < 2; idx++)
+                {
+                    boundaryFace[bfIdx].grad[idx] = distVec;
+                    boundaryFace[bfIdx].shapeValue[idx] = 0.5;
+                }
+                boundaryFace[bfIdx].grad[1] *= -1.0;
+            }
+        }
+    }
+};
+
+}
+
+#endif
+
diff --git a/dumux/implicit/cellcentered/cclocaljacobian.hh b/dumux/implicit/cellcentered/cclocaljacobian.hh
new file mode 100644
index 0000000000..2da777b72a
--- /dev/null
+++ b/dumux/implicit/cellcentered/cclocaljacobian.hh
@@ -0,0 +1,541 @@
+// -*- mode: C++; tab-width: 4; indent-tabs-mode: nil; c-basic-offset: 4 -*-
+// vi: set et ts=4 sw=4 sts=4:
+/*****************************************************************************
+ *   Copyright (C) 2008-2009 by Andreas Lauser                               *
+ *   Copyright (C) 2007-2009 by Bernd Flemisch                               *
+ *   Institute for Modelling Hydraulic and Environmental Systems             *
+ *   University of Stuttgart, Germany                                        *
+ *   email: <givenname>.<name>@iws.uni-stuttgart.de                          *
+ *                                                                           *
+ *   This program is free software: you can redistribute it and/or modify    *
+ *   it under the terms of the GNU General Public License as published by    *
+ *   the Free Software Foundation, either version 2 of the License, or       *
+ *   (at your option) any later version.                                     *
+ *                                                                           *
+ *   This program is distributed in the hope that it will be useful,         *
+ *   but WITHOUT ANY WARRANTY; without even the implied warranty of          *
+ *   MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the           *
+ *   GNU General Public License for more details.                            *
+ *                                                                           *
+ *   You should have received a copy of the GNU General Public License       *
+ *   along with this program.  If not, see <http://www.gnu.org/licenses/>.   *
+ *****************************************************************************/
+/*!
+ * \file
+ * \brief Caculates the Jacobian of the local residual for box models
+ */
+#ifndef DUMUX_CC_LOCAL_JACOBIAN_HH
+#define DUMUX_CC_LOCAL_JACOBIAN_HH
+
+#include <dune/istl/matrix.hh>
+
+#include <dumux/common/math.hh>
+#include "ccelementboundarytypes.hh"
+
+namespace Dumux
+{
+/*!
+ * \ingroup CCModel
+ * \ingroup CCLocalJacobian
+ * \brief Calculates the Jacobian of the local residual for box models
+ *
+ * The default behavior is to use numeric differentiation, i.e.
+ * forward or backward differences (2nd order), or central
+ * differences (3rd order). The method used is determined by the
+ * "NumericDifferenceMethod" property:
+ *
+ * - if the value of this property is smaller than 0, backward
+ *   differences are used, i.e.:
+ *   \f[
+ \frac{\partial f(x)}{\partial x} \approx \frac{f(x) - f(x - \epsilon)}{\epsilon}
+ *   \f]
+ *
+ * - if the value of this property is 0, central
+ *   differences are used, i.e.:
+ *   \f[
+ \frac{\partial f(x)}{\partial x} \approx \frac{f(x + \epsilon) - f(x - \epsilon)}{2 \epsilon}
+ *   \f]
+ *
+ * - if the value of this property is larger than 0, forward
+ *   differences are used, i.e.:
+ *   \f[
+ \frac{\partial f(x)}{\partial x} \approx \frac{f(x + \epsilon) - f(x)}{\epsilon}
+ *   \f]
+ *
+ * Here, \f$ f \f$ is the residual function for all equations, \f$x\f$
+ * is the value of a sub-control volume's primary variable at the
+ * evaluation point and \f$\epsilon\f$ is a small value larger than 0.
+ */
+template<class TypeTag>
+class CCLocalJacobian
+{
+private:
+    typedef typename GET_PROP_TYPE(TypeTag, LocalJacobian) Implementation;
+    typedef typename GET_PROP_TYPE(TypeTag, LocalResidual) LocalResidual;
+    typedef typename GET_PROP_TYPE(TypeTag, Problem) Problem;
+    typedef typename GET_PROP_TYPE(TypeTag, Model) Model;
+    typedef typename GET_PROP_TYPE(TypeTag, GridView) GridView;
+    typedef typename GridView::template Codim<0>::Entity Element;
+    typedef typename GET_PROP_TYPE(TypeTag, JacobianAssembler) JacobianAssembler;
+
+    enum {
+        numEq = GET_PROP_VALUE(TypeTag, NumEq),
+        dim = GridView::dimension
+    };
+
+    typedef typename GET_PROP_TYPE(TypeTag, FVElementGeometry) FVElementGeometry;
+    typedef typename GET_PROP_TYPE(TypeTag, VertexMapper) VertexMapper;
+    typedef typename GET_PROP_TYPE(TypeTag, ElementSolutionVector) ElementSolutionVector;
+    typedef typename GET_PROP_TYPE(TypeTag, PrimaryVariables) PrimaryVariables;
+
+    typedef typename GET_PROP_TYPE(TypeTag, VolumeVariables) VolumeVariables;
+    typedef typename GET_PROP_TYPE(TypeTag, ElementVolumeVariables) ElementVolumeVariables;
+    typedef typename GET_PROP_TYPE(TypeTag, ElementBoundaryTypes) ElementBoundaryTypes;
+
+    typedef typename GET_PROP_TYPE(TypeTag, Scalar) Scalar;
+    typedef Dune::FieldMatrix<Scalar, numEq, numEq> MatrixBlock;
+    typedef Dune::Matrix<MatrixBlock> LocalBlockMatrix;
+
+    // copying a local jacobian is not a good idea
+    CCLocalJacobian(const CCLocalJacobian &);
+
+public:
+    CCLocalJacobian()
+    {
+        numericDifferenceMethod_ = GET_PARAM(TypeTag, int, ImplicitNumericDifferenceMethod);
+        Valgrind::SetUndefined(problemPtr_);
+    }
+
+
+    /*!
+     * \brief Initialize the local Jacobian object.
+     *
+     * At this point we can assume that everything has been allocated,
+     * although some objects may not yet be completely initialized.
+     *
+     * \param prob The problem which we want to simulate.
+     */
+    void init(Problem &prob)
+    {
+        problemPtr_ = &prob;
+        localResidual_.init(prob);
+
+        // assume quadrilinears as elements with most vertices
+        A_.setSize(1, 2<<dim);
+        storageJacobian_.resize(1);
+    }
+
+    /*!
+     * \brief Assemble an element's local Jacobian matrix of the
+     *        defect.
+     *
+     * \param element The DUNE Codim<0> entity which we look at.
+     */
+    void assemble(const Element &element)
+    {
+        // set the current grid element and update the element's
+        // finite volume geometry
+        elemPtr_ = &element;
+        fvElemGeom_.update(gridView_(), element);
+        reset_();
+
+        bcTypes_.update(problem_(), elem_(), fvElemGeom_);
+
+        // this is pretty much a HACK because the internal state of
+        // the problem is not supposed to be changed during the
+        // evaluation of the residual. (Reasons: It is a violation of
+        // abstraction, makes everything more prone to errors and is
+        // not thread save.) The real solution are context objects!
+        problem_().updateCouplingParams(elem_());
+
+        // set the hints for the volume variables
+        model_().setHints(element, prevVolVars_, curVolVars_);
+
+        // update the secondary variables for the element at the last
+        // and the current time levels
+        prevVolVars_.update(problem_(),
+                            elem_(),
+                            fvElemGeom_,
+                            true /* isOldSol? */);
+
+        curVolVars_.update(problem_(),
+                           elem_(),
+                           fvElemGeom_,
+                           false /* isOldSol? */);
+
+        // update the hints of the model
+        model_().updateCurHints(element, curVolVars_);
+
+        // calculate the local residual
+        localResidual().eval(elem_(),
+                             fvElemGeom_,
+                             prevVolVars_,
+                             curVolVars_,
+                             bcTypes_);
+        residual_ = localResidual().residual();
+        storageTerm_ = localResidual().storageTerm();
+
+        model_().updatePVWeights(elem_(), curVolVars_);
+
+        // calculate the local jacobian matrix
+        int numNeighbors = fvElemGeom_.numNeighbors;
+        ElementSolutionVector partialDeriv(1);
+        PrimaryVariables storageDeriv(0.0);
+        for (int j = 0; j < numNeighbors; j++) {
+            for (int pvIdx = 0; pvIdx < numEq; pvIdx++) {
+                asImp_().evalPartialDerivative_(partialDeriv,
+                                                storageDeriv,
+                                                j,
+                                                pvIdx);
+
+                // update the local stiffness matrix with the current partial
+                // derivatives
+                updateLocalJacobian_(j,
+                                     pvIdx,
+                                     partialDeriv,
+                                     storageDeriv);
+            }
+        }
+    }
+
+    /*!
+     * \brief Returns a reference to the object which calculates the
+     *        local residual.
+     */
+    const LocalResidual &localResidual() const
+    { return localResidual_; }
+
+    /*!
+     * \brief Returns a reference to the object which calculates the
+     *        local residual.
+     */
+    LocalResidual &localResidual()
+    { return localResidual_; }
+
+    /*!
+     * \brief Returns the Jacobian of the equations at vertex i to the
+     *        primary variables at vertex j.
+     *
+     * \param i The local vertex (or sub-control volume) index on which
+     *          the equations are defined
+     * \param j The local vertex (or sub-control volume) index which holds
+     *          primary variables
+     */
+    const MatrixBlock &mat(int i, int j) const
+    { return A_[i][j]; }
+
+    /*!
+     * \brief Returns the Jacobian of the storage term at vertex i.
+     *
+     * \param i The local vertex (or sub-control volume) index
+     */
+    const MatrixBlock &storageJacobian(int i) const
+    { return storageJacobian_[i]; }
+
+    /*!
+     * \brief Returns the residual of the equations at vertex i.
+     *
+     * \param i The local vertex (or sub-control volume) index on which
+     *          the equations are defined
+     */
+    const PrimaryVariables &residual(int i) const
+    { return residual_[i]; }
+
+    /*!
+     * \brief Returns the storage term for vertex i.
+     *
+     * \param i The local vertex (or sub-control volume) index on which
+     *          the equations are defined
+     */
+    const PrimaryVariables &storageTerm(int i) const
+    { return storageTerm_[i]; }
+
+    /*!
+     * \brief Returns the epsilon value which is added and removed
+     *        from the current solution.
+     *
+     * \param scvIdx     The local index of the element's vertex for
+     *                   which the local derivative ought to be calculated.
+     * \param pvIdx      The index of the primary variable which gets varied
+     */
+    Scalar numericEpsilon(int scvIdx,
+                          int pvIdx) const
+    {
+        // define the base epsilon as the geometric mean of 1 and the
+        // resolution of the scalar type. E.g. for standard 64 bit
+        // floating point values, the resolution is about 10^-16 and
+        // the base epsilon is thus approximately 10^-8.
+        /*
+        static const Scalar baseEps
+            = Dumux::geometricMean<Scalar>(std::numeric_limits<Scalar>::epsilon(), 1.0);
+        */
+        static const Scalar baseEps = 1e-10;
+        assert(std::numeric_limits<Scalar>::epsilon()*1e4 < baseEps);
+        // the epsilon value used for the numeric differentiation is
+        // now scaled by the absolute value of the primary variable...
+        Scalar pv = this->curVolVars_[scvIdx].priVar(pvIdx);
+        return baseEps*(std::abs(pv) + 1.0);
+    }
+
+protected:
+    Implementation &asImp_()
+    { return *static_cast<Implementation*>(this); }
+    const Implementation &asImp_() const
+    { return *static_cast<const Implementation*>(this); }
+
+    /*!
+     * \brief Returns a reference to the problem.
+     */
+    const Problem &problem_() const
+    {
+        Valgrind::CheckDefined(problemPtr_);
+        return *problemPtr_;
+    };
+
+    /*!
+     * \brief Returns a reference to the grid view.
+     */
+    const GridView &gridView_() const
+    { return problem_().gridView(); }
+
+    /*!
+     * \brief Returns a reference to the element.
+     */
+    const Element &elem_() const
+    {
+        Valgrind::CheckDefined(elemPtr_);
+        return *elemPtr_;
+    };
+
+    /*!
+     * \brief Returns a reference to the model.
+     */
+    const Model &model_() const
+    { return problem_().model(); };
+
+    /*!
+     * \brief Returns a reference to the jacobian assembler.
+     */
+    const JacobianAssembler &jacAsm_() const
+    { return model_().jacobianAssembler(); }
+
+    /*!
+     * \brief Returns a reference to the vertex mapper.
+     */
+    const VertexMapper &vertexMapper_() const
+    { return problem_().vertexMapper(); };
+
+    /*!
+     * \brief Reset the local jacobian matrix to 0
+     */
+    void reset_()
+    {
+        for (int i = 0; i < 1; ++ i) {
+            storageJacobian_[i] = 0.0;
+            for (int j = 0; j < A_.M(); ++ j) {
+                A_[i][j] = 0.0;
+            }
+        }
+    }
+
+    /*!
+     * \brief Compute the partial derivatives to a primary variable at
+     *        an degree of freedom.
+     *
+     * This method can be overwritten by the implementation if a
+     * better scheme than numerical differentiation is available.
+     *
+     * The default implementation of this method uses numeric
+     * differentiation, i.e. forward or backward differences (2nd
+     * order), or central differences (3rd order). The method used is
+     * determined by the "NumericDifferenceMethod" property:
+     *
+     * - if the value of this property is smaller than 0, backward
+     *   differences are used, i.e.:
+     *   \f[
+         \frac{\partial f(x)}{\partial x} \approx \frac{f(x) - f(x - \epsilon)}{\epsilon}
+     *   \f]
+     *
+     * - if the value of this property is 0, central
+     *   differences are used, i.e.:
+     *   \f[
+           \frac{\partial f(x)}{\partial x} \approx \frac{f(x + \epsilon) - f(x - \epsilon)}{2 \epsilon}
+     *   \f]
+     *
+     * - if the value of this property is larger than 0, forward
+     *   differences are used, i.e.:
+     *   \f[
+           \frac{\partial f(x)}{\partial x} \approx \frac{f(x + \epsilon) - f(x)}{\epsilon}
+     *   \f]
+     *
+     * Here, \f$ f \f$ is the residual function for all equations, \f$x\f$
+     * is the value of a sub-control volume's primary variable at the
+     * evaluation point and \f$\epsilon\f$ is a small value larger than 0.
+     *
+     * \param dest The vector storing the partial derivatives of all
+     *              equations
+     * \param destStorage the mass matrix contributions
+     * \param scvIdx The sub-control volume index of the current
+     *               finite element for which the partial derivative
+     *               ought to be calculated
+     * \param pvIdx The index of the primary variable at the scvIdx'
+     *              sub-control volume of the current finite element
+     *              for which the partial derivative ought to be
+     *              calculated
+     */
+    void evalPartialDerivative_(ElementSolutionVector &dest,
+                                PrimaryVariables &destStorage,
+                                int neighborIdx,
+                                int pvIdx)
+    {
+        const Element& neighbor = *(fvElemGeom_.neighbors[neighborIdx]);
+	FVElementGeometry neighborFVGeom;
+	neighborFVGeom.updateInner(problemPtr_->gridView(), neighbor);
+	
+        int globalIdx = problemPtr_->elementMapper().map(neighbor);
+
+        PrimaryVariables priVars(model_().curSol()[globalIdx]);
+        VolumeVariables origVolVars(curVolVars_[neighborIdx]);
+
+        curVolVars_[neighborIdx].setEvalPoint(&origVolVars);
+        Scalar eps = asImp_().numericEpsilon(neighborIdx, pvIdx);
+        Scalar delta = 0;
+
+        if (numericDifferenceMethod_ >= 0) {
+            // we are not using backward differences, i.e. we need to
+            // calculate f(x + \epsilon)
+
+            // deflect primary variables
+            priVars[pvIdx] += eps;
+            delta += eps;
+
+            // calculate the residual
+            curVolVars_[neighborIdx].update(priVars,
+                                       problem_(),
+                                       neighbor,
+                                       neighborFVGeom,
+                                       /*scvIdx=*/0,
+                                       false);
+            localResidual().eval(elem_(),
+                                 fvElemGeom_,
+                                 prevVolVars_,
+                                 curVolVars_,
+                                 bcTypes_);
+
+            // store the residual and the storage term
+            dest = localResidual().residual();
+	    if (neighborIdx == 0)
+                destStorage = localResidual().storageTerm()[neighborIdx];
+        }
+        else {
+            // we are using backward differences, i.e. we don't need
+            // to calculate f(x + \epsilon) and we can recycle the
+            // (already calculated) residual f(x)
+            dest = residual_;
+	    if (neighborIdx == 0)
+                destStorage = storageTerm_[neighborIdx];
+        }
+
+
+        if (numericDifferenceMethod_ <= 0) {
+            // we are not using forward differences, i.e. we don't
+            // need to calculate f(x - \epsilon)
+
+            // deflect the primary variables
+            priVars[pvIdx] -= delta + eps;
+            delta += eps;
+
+            // calculate residual again
+            curVolVars_[neighborIdx].update(priVars,
+                                       problem_(),
+                                       neighbor,
+                                       neighborFVGeom,
+                                       /*scvIdx=*/0,
+                                       false);
+            localResidual().eval(elem_(),
+                                 fvElemGeom_,
+                                 prevVolVars_,
+                                 curVolVars_,
+                                 bcTypes_);
+            dest -= localResidual().residual();
+	    if (neighborIdx == 0)
+                destStorage -= localResidual().storageTerm()[neighborIdx];
+        }
+        else {
+            // we are using forward differences, i.e. we don't need to
+            // calculate f(x - \epsilon) and we can recycle the
+            // (already calculated) residual f(x)
+            dest -= residual_;
+	    if (neighborIdx == 0)
+                destStorage -= storageTerm_[neighborIdx];
+        }
+
+        // divide difference in residuals by the magnitude of the
+        // deflections between the two function evaluation
+        dest /= delta;
+        destStorage /= delta;
+
+        // restore the original state of the element's volume variables
+        curVolVars_[neighborIdx] = origVolVars;
+
+#if HAVE_VALGRIND
+        for (unsigned i = 0; i < dest.size(); ++i)
+            Valgrind::CheckDefined(dest[i]);
+#endif
+    }
+
+    /*!
+     * \brief Updates the current local Jacobian matrix with the
+     *        partial derivatives of all equations in regard to the
+     *        primary variable 'pvIdx' at vertex 'scvIdx' .
+     */
+    void updateLocalJacobian_(int neighborIdx,
+                              int pvIdx,
+                              const ElementSolutionVector &deriv,
+                              const PrimaryVariables &storageDeriv)
+    {
+        // store the derivative of the storage term
+        if (neighborIdx == 0)
+            for (int eqIdx = 0; eqIdx < numEq; eqIdx++) {
+                storageJacobian_[neighborIdx][eqIdx][pvIdx] = storageDeriv[eqIdx];
+            }
+
+        for (int i = 0; i < 1; i++)
+        {
+            for (int eqIdx = 0; eqIdx < numEq; eqIdx++) {
+                // A[i][scvIdx][eqIdx][pvIdx] is the rate of change of
+                // the residual of equation 'eqIdx' at vertex 'i'
+                // depending on the primary variable 'pvIdx' at vertex
+                // 'scvIdx'.
+                this->A_[i][neighborIdx][eqIdx][pvIdx] = deriv[i][eqIdx];
+                Valgrind::CheckDefined(this->A_[i][neighborIdx][eqIdx][pvIdx]);
+            }
+        }
+    }
+
+    const Element *elemPtr_;
+    FVElementGeometry fvElemGeom_;
+
+    ElementBoundaryTypes bcTypes_;
+
+    // The problem we would like to solve
+    Problem *problemPtr_;
+
+    // secondary variables at the previous and at the current time
+    // levels
+    ElementVolumeVariables prevVolVars_;
+    ElementVolumeVariables curVolVars_;
+
+    LocalResidual localResidual_;
+
+    LocalBlockMatrix A_;
+    std::vector<MatrixBlock> storageJacobian_;
+
+    ElementSolutionVector residual_;
+    ElementSolutionVector storageTerm_;
+
+    int numericDifferenceMethod_;
+};
+}
+
+#endif
diff --git a/dumux/implicit/cellcentered/cclocalresidual.hh b/dumux/implicit/cellcentered/cclocalresidual.hh
new file mode 100644
index 0000000000..cdc914e8b2
--- /dev/null
+++ b/dumux/implicit/cellcentered/cclocalresidual.hh
@@ -0,0 +1,710 @@
+// -*- mode: C++; tab-width: 4; indent-tabs-mode: nil; c-basic-offset: 4 -*-
+// vi: set et ts=4 sw=4 sts=4:
+/*****************************************************************************
+ *   Copyright (C) 2008-2011 by Andreas Lauser                               *
+ *   Copyright (C) 2007-2009 by Bernd Flemisch                               *
+ *   Institute for Modelling Hydraulic and Environmental Systems             *
+ *   University of Stuttgart, Germany                                        *
+ *   email: <givenname>.<name>@iws.uni-stuttgart.de                          *
+ *                                                                           *
+ *   This program is free software: you can redistribute it and/or modify    *
+ *   it under the terms of the GNU General Public License as published by    *
+ *   the Free Software Foundation, either version 2 of the License, or       *
+ *   (at your option) any later version.                                     *
+ *                                                                           *
+ *   This program is distributed in the hope that it will be useful,         *
+ *   but WITHOUT ANY WARRANTY; without even the implied warranty of          *
+ *   MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the           *
+ *   GNU General Public License for more details.                            *
+ *                                                                           *
+ *   You should have received a copy of the GNU General Public License       *
+ *   along with this program.  If not, see <http://www.gnu.org/licenses/>.   *
+ *****************************************************************************/
+/*!
+ * \file
+ * \brief Calculates the residual of models based on the box scheme element-wise.
+ */
+#ifndef DUMUX_CC_LOCAL_RESIDUAL_HH
+#define DUMUX_CC_LOCAL_RESIDUAL_HH
+
+#include <dune/istl/matrix.hh>
+#include <dune/grid/common/geometry.hh>
+
+#include <dumux/common/valgrind.hh>
+
+#include "ccproperties.hh"
+
+namespace Dumux
+{
+/*!
+ * \ingroup CCModel
+ * \ingroup CCLocalResidual
+ * \brief Element-wise calculation of the residual matrix for models
+ *        based on the box scheme.
+ *
+ * \todo Please doc me more!
+ */
+template<class TypeTag>
+class CCLocalResidual
+{
+private:
+    typedef typename GET_PROP_TYPE(TypeTag, LocalResidual) Implementation;
+    typedef typename GET_PROP_TYPE(TypeTag, Problem) Problem;
+    typedef typename GET_PROP_TYPE(TypeTag, Model) Model;
+    typedef typename GET_PROP_TYPE(TypeTag, Scalar) Scalar;
+    typedef typename GET_PROP_TYPE(TypeTag, GridView) GridView;
+
+    enum {
+        numEq = GET_PROP_VALUE(TypeTag, NumEq),
+        dim = GridView::dimension
+    };
+
+    typedef typename GridView::template Codim<0>::Entity Element;
+    typedef typename GridView::template Codim<dim>::EntityPointer VertexPointer;
+    typedef typename GridView::IntersectionIterator IntersectionIterator;
+
+    typedef typename GET_PROP_TYPE(TypeTag, FVElementGeometry) FVElementGeometry;
+    typedef typename GET_PROP_TYPE(TypeTag, VertexMapper) VertexMapper;
+    typedef typename GET_PROP_TYPE(TypeTag, ElementSolutionVector) ElementSolutionVector;
+    typedef typename GET_PROP_TYPE(TypeTag, PrimaryVariables) PrimaryVariables;
+    typedef typename GET_PROP_TYPE(TypeTag, BoundaryTypes) BoundaryTypes;
+    typedef typename GET_PROP_TYPE(TypeTag, ElementBoundaryTypes) ElementBoundaryTypes;
+    typedef typename GET_PROP_TYPE(TypeTag, VolumeVariables) VolumeVariables;
+    typedef typename GET_PROP_TYPE(TypeTag, ElementVolumeVariables) ElementVolumeVariables;
+
+    // copying the local residual class is not a good idea
+    CCLocalResidual(const CCLocalResidual &);
+
+public:
+    CCLocalResidual()
+    { }
+
+    ~CCLocalResidual()
+    { }
+
+    /*!
+     * \brief Initialize the local residual.
+     *
+     * This assumes that all objects of the simulation have been fully
+     * allocated but not necessarily initialized completely.
+     *
+     * \param prob The representation of the physical problem to be
+     *             solved.
+     */
+    void init(Problem &prob)
+    { problemPtr_ = &prob; }
+
+    /*!
+     * \brief Compute the local residual, i.e. the deviation of the
+     *        equations from zero.
+     *
+     * \param element The DUNE Codim<0> entity for which the residual
+     *                ought to be calculated
+     */
+    void eval(const Element &element)
+    {
+        FVElementGeometry fvElemGeom;
+
+        fvElemGeom.update(gridView_(), element);
+        fvElemGeomPtr_ = &fvElemGeom;
+
+        ElementVolumeVariables volVarsPrev, volVarsCur;
+        // update the hints
+        model_().setHints(element, volVarsPrev, volVarsCur);
+
+        volVarsPrev.update(problem_(),
+                           element,
+                           fvGeometry_(),
+                           true /* oldSol? */);
+        volVarsCur.update(problem_(),
+                          element,
+                          fvGeometry_(),
+                          false /* oldSol? */);
+
+        ElementBoundaryTypes bcTypes;
+        bcTypes.update(problem_(), element, fvGeometry_());
+
+        // this is pretty much a HACK because the internal state of
+        // the problem is not supposed to be changed during the
+        // evaluation of the residual. (Reasons: It is a violation of
+        // abstraction, makes everything more prone to errors and is
+        // not thread save.) The real solution are context objects!
+        problem_().updateCouplingParams(element);
+
+        asImp_().eval(element, fvGeometry_(), volVarsPrev, volVarsCur, bcTypes);
+    }
+
+    /*!
+     * \brief Compute the storage term for the current solution.
+     *
+     * This can be used to figure out how much of each conservation
+     * quantity is inside the element.
+     *
+     * \param element The DUNE Codim<0> entity for which the storage
+     *                term ought to be calculated
+     */
+    void evalStorage(const Element &element)
+    {
+        elemPtr_ = &element;
+
+        FVElementGeometry fvElemGeom;
+        fvElemGeom.update(gridView_(), element);
+        fvElemGeomPtr_ = &fvElemGeom;
+
+        ElementBoundaryTypes bcTypes;
+        bcTypes.update(problem_(), element, fvGeometry_());
+        bcTypesPtr_ = &bcTypes;
+
+        // no previous volume variables!
+        prevVolVarsPtr_ = 0;
+
+        ElementVolumeVariables volVars;
+
+        // update the hints
+        model_().setHints(element, volVars);
+
+        // calculate volume current variables
+        volVars.update(problem_(), element, fvGeometry_(), false);
+        curVolVarsPtr_ = &volVars;
+
+        asImp_().evalStorage_();
+    }
+
+    /*!
+     * \brief Compute the flux term for the current solution.
+     *
+     * \param element The DUNE Codim<0> entity for which the residual
+     *                ought to be calculated
+     * \param curVolVars The volume averaged variables for all
+     *                   sub-contol volumes of the element
+     */
+    void evalFluxes(const Element &element,
+                    const ElementVolumeVariables &curVolVars)
+    {
+        elemPtr_ = &element;
+
+        FVElementGeometry fvElemGeom;
+        fvElemGeom.update(gridView_(), element);
+        fvElemGeomPtr_ = &fvElemGeom;
+
+        ElementBoundaryTypes bcTypes;
+        bcTypes.update(problem_(), element, fvGeometry_());
+
+        residual_.resize(1);
+        residual_ = 0;
+
+        bcTypesPtr_ = &bcTypes;
+        prevVolVarsPtr_ = 0;
+        curVolVarsPtr_ = &curVolVars;
+        asImp_().evalFluxes_();
+    }
+
+    /*!
+     * \brief Compute the local residual, i.e. the deviation of the
+     *        equations from zero.
+     *
+     * \param element The DUNE Codim<0> entity for which the residual
+     *                ought to be calculated
+     * \param fvElemGeom The finite-volume geometry of the element
+     * \param prevVolVars The volume averaged variables for all
+     *                   sub-control volumes of the element at the previous
+     *                   time level
+     * \param curVolVars The volume averaged variables for all
+     *                   sub-control volumes of the element at the current
+     *                   time level
+     * \param bcTypes The types of the boundary conditions for all
+     *                vertices of the element
+     */
+    void eval(const Element &element,
+              const FVElementGeometry &fvElemGeom,
+              const ElementVolumeVariables &prevVolVars,
+              const ElementVolumeVariables &curVolVars,
+              const ElementBoundaryTypes &bcTypes)
+    {
+        Valgrind::CheckDefined(prevVolVars);
+        Valgrind::CheckDefined(curVolVars);
+
+#if !defined NDEBUG && HAVE_VALGRIND
+        for (int i=0; i < fvElemGeom.numNeighbors; i++) {
+            prevVolVars[i].checkDefined();
+            curVolVars[i].checkDefined();
+        }
+#endif // HAVE_VALGRIND
+
+        elemPtr_ = &element;
+        fvElemGeomPtr_ = &fvElemGeom;
+        bcTypesPtr_ = &bcTypes;
+        prevVolVarsPtr_ = &prevVolVars;
+        curVolVarsPtr_ = &curVolVars;
+
+        // resize the vectors for all terms
+        residual_.resize(1);
+        storageTerm_.resize(1);
+
+        residual_ = 0.0;
+        storageTerm_ = 0.0;
+
+        asImp_().evalFluxes_();
+
+#if !defined NDEBUG && HAVE_VALGRIND
+        Valgrind::CheckDefined(residual_[0]);
+#endif // HAVE_VALGRIND
+
+        asImp_().evalVolumeTerms_();
+
+#if !defined NDEBUG && HAVE_VALGRIND
+        Valgrind::CheckDefined(residual_[0]);
+#endif // HAVE_VALGRIND
+
+        // evaluate the boundary conditions
+        asImp_().evalBoundary_();
+
+#if !defined NDEBUG && HAVE_VALGRIND
+        Valgrind::CheckDefined(residual_[0]);
+#endif // HAVE_VALGRIND
+    }
+
+    /*!
+     * \brief Add Outflow boundary conditions for a single sub-control
+     *        volume face to the local residual.
+     *
+     * \note This is so far an empty method doing not more than
+     *       nothing. A beta version is available for the 2p2c and
+     *       2p2cni model. There you can find a sample implementation.
+     */
+    void evalOutflowSegment(const IntersectionIterator &isIt,
+                            int scvIdx,
+                            int boundaryFaceIdx)
+    {}
+
+    /*!
+     * \brief Returns the local residual for all sub-control
+     *        volumes of the element.
+     */
+    const ElementSolutionVector &residual() const
+    { return residual_; }
+
+    /*!
+     * \brief Returns the local residual for a given sub-control
+     *        volume of the element.
+     *
+     * \param scvIdx The local index of the sub-control volume
+     *               (i.e. the element's local vertex index)
+     */
+    const PrimaryVariables &residual(int scvIdx) const
+    { return residual_[scvIdx]; }
+
+    /*!
+     * \brief Returns the storage term for all sub-control volumes of the
+     *        element.
+     */
+    const ElementSolutionVector &storageTerm() const
+    { return storageTerm_; }
+
+    /*!
+     * \brief Returns the storage term for a given sub-control volumes
+     *        of the element.
+     */
+    const PrimaryVariables &storageTerm(int scvIdx) const
+    { return storageTerm_[scvIdx]; }
+
+    void evalOutflowSegment(const IntersectionIterator &isIt)
+    {
+        const BoundaryTypes &bcTypes = this->bcTypes_(0);
+        
+        // deal with outflow boundaries
+        if (bcTypes.hasOutflow())
+        {
+            PrimaryVariables values(0.0);
+            asImp_().computeFlux(values, 
+                                  /*boundaryFaceIdx=*/isIt->indexInInside(), 
+                                  true);
+            Valgrind::CheckDefined(values);
+            
+            for (int eqIdx = 0; eqIdx < numEq; ++eqIdx)
+            {
+                if (!bcTypes.isOutflow(eqIdx) )
+                    continue;
+                this->residual_[0][eqIdx] += values[eqIdx];
+            }
+        }
+    }
+protected:
+    Implementation &asImp_()
+    {
+        assert(static_cast<Implementation*>(this) != 0);
+        return *static_cast<Implementation*>(this);
+    }
+
+    const Implementation &asImp_() const
+    {
+        assert(static_cast<const Implementation*>(this) != 0);
+        return *static_cast<const Implementation*>(this);
+    }
+
+    /*!
+     * \brief Evaluate the boundary conditions
+     *        of the current element.
+     */
+    void evalBoundary_()
+    {
+        if (bcTypes_().hasNeumann() || bcTypes_().hasOutflow())
+            asImp_().evalBoundaryFluxes_();
+
+#if !defined NDEBUG && HAVE_VALGRIND
+        Valgrind::CheckDefined(residual_[0]);
+#endif // HAVE_VALGRIND
+
+        if (bcTypes_().hasDirichlet())
+            asImp_().evalDirichlet_();
+    }
+
+    /*!
+     * \brief Set the values of the Dirichlet boundary control volumes
+     *        of the current element.
+     */
+    void evalDirichlet_()
+    {
+        PrimaryVariables tmp(0);
+
+        const BoundaryTypes &bcTypes = bcTypes_(0);
+        if (! bcTypes.hasDirichlet())
+            return;
+
+        Valgrind::SetUndefined(tmp);
+	// HACK: ask for Dirichlet value at element center
+        asImp_().problem_().dirichletAtPos(tmp, element_().geometry().center());
+
+        // set the dirichlet conditions
+        for (int eqIdx = 0; eqIdx < numEq; ++eqIdx) {
+            if (!bcTypes.isDirichlet(eqIdx))
+                continue;
+            int pvIdx = bcTypes.eqToDirichletIndex(eqIdx);
+            assert(0 <= pvIdx && pvIdx < numEq);
+            Valgrind::CheckDefined(tmp[pvIdx]);
+
+            residual_[0][eqIdx] =
+                    (curPriVar_(0, pvIdx) - tmp[pvIdx]);
+
+            storageTerm_[0][eqIdx] = 0.0;
+        }
+    }
+
+    /*!
+     * \brief Add all Neumann and outflow boundary conditions to the local
+     *        residual.
+     */
+    void evalBoundaryFluxes_()
+    {
+        IntersectionIterator isIt = gridView_().ibegin(element_());
+        const IntersectionIterator &endIt = gridView_().iend(element_());
+        for (; isIt != endIt; ++isIt)
+        {
+            // handle only faces on the boundary
+            if (!isIt->boundary())
+                continue;
+
+            // add the residual of all vertices of the boundary
+            // segment
+            asImp_().evalNeumannSegment_(isIt);
+		
+            // evaluate the outflow conditions at the boundary face
+            // ATTENTION: This is so far a beta version that is only for the 2p2c and 2p2cni model
+            //              available and not thoroughly tested.
+            asImp_().evalOutflowSegment(isIt);
+        }
+    }
+
+    /*!
+     * \brief Add Neumann boundary conditions for a single sub-control
+     *        volume face to the local residual.
+     */
+    void evalNeumannSegment_(const IntersectionIterator &isIt)
+    {
+        // temporary vector to store the neumann boundary fluxes
+        PrimaryVariables values(0.0);
+
+        BoundaryTypes bcTypes;
+        problem_().boundaryTypes(bcTypes, *isIt);
+
+        // deal with neumann boundaries
+        if (bcTypes.hasNeumann()) {
+            Valgrind::SetUndefined(values);
+            problem_().boxSDNeumann(values,
+                                    element_(),
+                                    fvGeometry_(),
+                                    *isIt,
+                                    /*scvIdx=*/0,
+                                    /*boundaryFaceIdx=*/isIt->indexInInside(),
+                                    curVolVars_());
+            values *= isIt->geometry().volume()
+                * curVolVars_(0).extrusionFactor();
+            Valgrind::CheckDefined(values);
+
+            // set the neumann conditions
+            for (int eqIdx = 0; eqIdx < numEq; ++eqIdx) {
+                if (!bcTypes.isNeumann(eqIdx))
+                    continue;
+                residual_[0][eqIdx] += values[eqIdx];
+            }
+        }
+    }
+
+    /*!
+     * \brief Add the flux terms to the local residual of all
+     *        sub-control volumes of the current element.
+     */
+    void evalFluxes_()
+    {
+        // calculate the mass flux over the faces and subtract
+        // it from the local rates
+        int faceIdx = -1;
+        IntersectionIterator isIt = gridView_().ibegin(element_());
+        IntersectionIterator isEndIt = gridView_().iend(element_());
+        for (; isIt != isEndIt; ++isIt) {
+            if (!isIt->neighbor())
+                continue;
+
+            faceIdx++;
+	    PrimaryVariables flux;
+
+            Valgrind::SetUndefined(flux);
+            asImp_().computeFlux(flux, faceIdx);
+            Valgrind::CheckDefined(flux);
+
+            flux *= curVolVars_(0).extrusionFactor();
+
+            // The balance equation for a finite volume is:
+            //
+            // dStorage/dt = Flux + Source
+            //
+            // where the 'Flux' and the 'Source' terms represent the
+            // mass per second which _ENTER_ the finite
+            // volume. Re-arranging this, we get
+            //
+            // dStorage/dt - Source - Flux = 0
+            //
+            // Since the flux calculated by computeFlux() goes _OUT_
+            // of sub-control volume i and _INTO_ sub-control volume
+            // j, we need to add the flux to finite volume i and
+            // subtract it from finite volume j
+            residual_[0] += flux;
+        }
+    }
+
+    /*!
+     * \brief Set the local residual to the storage terms of all
+     *        sub-control volumes of the current element.
+     */
+    void evalStorage_()
+    {
+        storageTerm_.resize(1);
+        storageTerm_ = 0;
+
+        // calculate the amount of conservation each quantity inside
+        // all sub control volumes
+        Valgrind::SetUndefined(storageTerm_[0]);
+        asImp_().computeStorage(storageTerm_[0], 0, /*isOldSol=*/false);
+        storageTerm_[0] *= fvGeometry_().subContVol[0].volume
+                * curVolVars_(0).extrusionFactor();
+        Valgrind::CheckDefined(storageTerm_[0]);
+    }
+
+    /*!
+     * \brief Add the change in the storage terms and the source term
+     *        to the local residual of all sub-control volumes of the
+     *        current element.
+     */
+    void evalVolumeTerms_()
+    {
+        // evaluate the volume terms (storage + source terms)
+        for (int i=0; i < 1; i++)
+        {
+            Scalar extrusionFactor =
+                curVolVars_(i).extrusionFactor();
+
+            PrimaryVariables tmp(0.);
+
+            // mass balance within the element. this is the
+            // \f$\frac{m}{\partial t}\f$ term if using implicit
+            // euler as time discretization.
+            //
+            // TODO (?): we might need a more explicit way for
+            // doing the time discretization...
+            Valgrind::SetUndefined(storageTerm_[i]);
+            Valgrind::SetUndefined(tmp);
+            asImp_().computeStorage(storageTerm_[i], i, false);
+            asImp_().computeStorage(tmp, i, true);
+            Valgrind::CheckDefined(storageTerm_[i]);
+            Valgrind::CheckDefined(tmp);
+
+            storageTerm_[i] -= tmp;
+            storageTerm_[i] *=
+                fvGeometry_().subContVol[i].volume
+                / problem_().timeManager().timeStepSize()
+                * extrusionFactor;
+            residual_[i] += storageTerm_[i];
+
+            // subtract the source term from the local rate
+            Valgrind::SetUndefined(tmp);
+            asImp_().computeSource(tmp, i);
+            Valgrind::CheckDefined(tmp);
+            tmp *= fvGeometry_().subContVol[i].volume * extrusionFactor;
+            residual_[i] -= tmp;
+
+            // make sure that only defined quantities were used
+            // to calculate the residual.
+            Valgrind::CheckDefined(residual_[i]);
+        }
+    }
+
+    /*!
+     * \brief Returns a reference to the problem.
+     */
+    const Problem &problem_() const
+    { return *problemPtr_; };
+
+    /*!
+     * \brief Returns a reference to the model.
+     */
+    const Model &model_() const
+    { return problem_().model(); };
+
+    /*!
+     * \brief Returns a reference to the vertex mapper.
+     */
+    const VertexMapper &vertexMapper_() const
+    { return problem_().vertexMapper(); };
+
+    /*!
+     * \brief Returns a reference to the grid view.
+     */
+    const GridView &gridView_() const
+    { return problem_().gridView(); }
+
+    /*!
+     * \brief Returns a reference to the current element.
+     */
+    const Element &element_() const
+    {
+        Valgrind::CheckDefined(elemPtr_);
+        return *elemPtr_;
+    }
+
+    /*!
+     * \brief Returns a reference to the current element's finite
+     *        volume geometry.
+     */
+    const FVElementGeometry &fvGeometry_() const
+    {
+        Valgrind::CheckDefined(fvElemGeomPtr_);
+        return *fvElemGeomPtr_;
+    }
+
+    /*!
+     * \brief Returns a reference to the primary variables of
+     *           the last time step of the i'th
+     *        sub-control volume of the current element.
+     */
+    const PrimaryVariables &prevPriVars_(int i) const
+    {
+        return prevVolVars_(i).priVars();
+    }
+
+    /*!
+     * \brief Returns a reference to the primary variables of the i'th
+     *        sub-control volume of the current element.
+     */
+    const PrimaryVariables &curPriVars_(int i) const
+    {
+        return curVolVars_(i).priVars();
+    }
+
+    /*!
+     * \brief Returns the j'th primary of the i'th sub-control volume
+     *        of the current element.
+     */
+    Scalar curPriVar_(int i, int j) const
+    {
+        return curVolVars_(i).priVar(j);
+    }
+
+    /*!
+     * \brief Returns a reference to the current volume variables of
+     *        all sub-control volumes of the current element.
+     */
+    const ElementVolumeVariables &curVolVars_() const
+    {
+        Valgrind::CheckDefined(curVolVarsPtr_);
+        return *curVolVarsPtr_;
+    }
+
+    /*!
+     * \brief Returns a reference to the volume variables of the i-th
+     *        sub-control volume of the current element.
+     */
+    const VolumeVariables &curVolVars_(int i) const
+    {
+        return curVolVars_()[i];
+    }
+
+    /*!
+     * \brief Returns a reference to the previous time step's volume
+     *        variables of all sub-control volumes of the current
+     *        element.
+     */
+    const ElementVolumeVariables &prevVolVars_() const
+    {
+        Valgrind::CheckDefined(prevVolVarsPtr_);
+        return *prevVolVarsPtr_;
+    }
+
+    /*!
+     * \brief Returns a reference to the previous time step's volume
+     *        variables of the i-th sub-control volume of the current
+     *        element.
+     */
+    const VolumeVariables &prevVolVars_(int i) const
+    {
+        return prevVolVars_()[i];
+    }
+
+    /*!
+     * \brief Returns a reference to the boundary types of all
+     *        sub-control volumes of the current element.
+     */
+    const ElementBoundaryTypes &bcTypes_() const
+    {
+        Valgrind::CheckDefined(bcTypesPtr_);
+        return *bcTypesPtr_;
+    }
+
+    /*!
+     * \brief Returns a reference to the boundary types of the i-th
+     *        sub-control volume of the current element.
+     */
+    const BoundaryTypes &bcTypes_(int i) const
+    {
+        return bcTypes_()[i];
+    }
+
+protected:
+    ElementSolutionVector storageTerm_;
+    ElementSolutionVector residual_;
+
+    // The problem we would like to solve
+    Problem *problemPtr_;
+
+    const Element *elemPtr_;
+    const FVElementGeometry *fvElemGeomPtr_;
+
+    // current and previous secondary variables for the element
+    const ElementVolumeVariables *prevVolVarsPtr_;
+    const ElementVolumeVariables *curVolVarsPtr_;
+
+    const ElementBoundaryTypes *bcTypesPtr_;
+};
+
+}
+
+#endif
diff --git a/dumux/implicit/cellcentered/ccmodel.hh b/dumux/implicit/cellcentered/ccmodel.hh
new file mode 100644
index 0000000000..0f29321213
--- /dev/null
+++ b/dumux/implicit/cellcentered/ccmodel.hh
@@ -0,0 +1,755 @@
+// -*- mode: C++; tab-width: 4; indent-tabs-mode: nil; c-basic-offset: 4 -*-
+// vi: set et ts=4 sw=4 sts=4:
+/*****************************************************************************
+ *   Copyright (C) 2008-2010 by Andreas Lauser                               *
+ *   Copyright (C) 2008-2010 by Bernd Flemisch                               *
+ *   Institute for Modelling Hydraulic and Environmental Systems             *
+ *   University of Stuttgart, Germany                                        *
+ *   email: <givenname>.<name>@iws.uni-stuttgart.de                          *
+ *                                                                           *
+ *   This program is free software: you can redistribute it and/or modify    *
+ *   it under the terms of the GNU General Public License as published by    *
+ *   the Free Software Foundation, either version 2 of the License, or       *
+ *   (at your option) any later version.                                     *
+ *                                                                           *
+ *   This program is distributed in the hope that it will be useful,         *
+ *   but WITHOUT ANY WARRANTY; without even the implied warranty of          *
+ *   MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the           *
+ *   GNU General Public License for more details.                            *
+ *                                                                           *
+ *   You should have received a copy of the GNU General Public License       *
+ *   along with this program.  If not, see <http://www.gnu.org/licenses/>.   *
+ *****************************************************************************/
+/*!
+ * \file
+ *
+ * \brief Base class for models using box discretization
+ */
+#ifndef DUMUX_CC_MODEL_HH
+#define DUMUX_CC_MODEL_HH
+
+#include "ccproperties.hh"
+#include "ccpropertydefaults.hh"
+
+#include "ccelementvolumevariables.hh"
+#include "cclocaljacobian.hh"
+#include "cclocalresidual.hh"
+
+#include <dumux/parallel/vertexhandles.hh>
+
+#include <dune/grid/common/geometry.hh>
+
+namespace Dumux
+{
+
+/*!
+ * \ingroup CCModel
+ *
+ * \brief The base class for the vertex centered finite volume
+ *        discretization scheme.
+ */
+template<class TypeTag>
+class CCModel
+{
+    typedef typename GET_PROP_TYPE(TypeTag, Model) Implementation;
+    typedef typename GET_PROP_TYPE(TypeTag, Problem) Problem;
+    typedef typename GET_PROP_TYPE(TypeTag, GridView) GridView;
+    typedef typename GET_PROP_TYPE(TypeTag, Scalar) Scalar;
+    typedef typename GET_PROP_TYPE(TypeTag, ElementMapper) ElementMapper;
+    typedef typename GET_PROP_TYPE(TypeTag, VertexMapper) VertexMapper;
+    typedef typename GET_PROP_TYPE(TypeTag, DofMapper) DofMapper;
+    typedef typename GET_PROP_TYPE(TypeTag, SolutionVector) SolutionVector;
+    typedef typename GET_PROP_TYPE(TypeTag, PrimaryVariables) PrimaryVariables;
+    typedef typename GET_PROP_TYPE(TypeTag, JacobianAssembler) JacobianAssembler;
+    typedef typename GET_PROP_TYPE(TypeTag, ElementVolumeVariables) ElementVolumeVariables;
+    typedef typename GET_PROP_TYPE(TypeTag, VolumeVariables) VolumeVariables;
+
+    enum {
+        numEq = GET_PROP_VALUE(TypeTag, NumEq),
+        dim = GridView::dimension
+    };
+
+    typedef typename GET_PROP_TYPE(TypeTag, FVElementGeometry) FVElementGeometry;
+    typedef typename GET_PROP_TYPE(TypeTag, LocalJacobian) LocalJacobian;
+    typedef typename GET_PROP_TYPE(TypeTag, LocalResidual) LocalResidual;
+    typedef typename GET_PROP_TYPE(TypeTag, NewtonMethod) NewtonMethod;
+    typedef typename GET_PROP_TYPE(TypeTag, NewtonController) NewtonController;
+
+    typedef typename GridView::ctype CoordScalar;
+    typedef typename GridView::template Codim<0>::Entity Element;
+    typedef typename GridView::template Codim<0>::Iterator ElementIterator;
+    typedef typename GridView::template Codim<dim>::Entity Vertex;
+    typedef typename GridView::template Codim<dim>::Iterator VertexIterator;
+    typedef typename GridView::IntersectionIterator IntersectionIterator;
+
+    typedef typename Dune::GenericReferenceElements<CoordScalar, dim> ReferenceElements;
+    typedef typename Dune::GenericReferenceElement<CoordScalar, dim> ReferenceElement;
+
+    // copying a model is not a good idea
+    CCModel(const CCModel &);
+
+public:
+    /*!
+     * \brief The constructor.
+     */
+    CCModel()
+    {}
+
+    ~CCModel()
+    { delete jacAsm_;  }
+
+    /*!
+     * \brief Apply the initial conditions to the model.
+     *
+     * \param prob The object representing the problem which needs to
+     *             be simulated.
+     */
+    void init(Problem &prob)
+    {
+        problemPtr_ = &prob;
+
+        updateBoundaryIndices_();
+
+        int nDofs = asImp_().numDofs();
+        uCur_.resize(nDofs);
+        uPrev_.resize(nDofs);
+
+        localJacobian_.init(problem_());
+        jacAsm_ = new JacobianAssembler();
+        jacAsm_->init(problem_());
+
+        asImp_().applyInitialSolution_();
+
+        // also set the solution of the "previous" time step to the
+        // initial solution.
+        uPrev_ = uCur_;
+    }
+
+    // functions for interface consistence
+    void setHints(const Element &elem,
+                  ElementVolumeVariables &prevVolVars,
+                  ElementVolumeVariables &curVolVars) const
+    {}
+
+    void setHints(const Element &elem,
+                  ElementVolumeVariables &curVolVars) const
+    {}
+
+    void updatePrevHints()
+    {}
+
+    void updateCurHints(const Element &elem,
+                        const ElementVolumeVariables &ev) const
+    {}
+
+    /*!
+     * \brief Compute the global residual for an arbitrary solution
+     *        vector.
+     *
+     * \param dest Stores the result
+     * \param u The solution for which the residual ought to be calculated
+     */
+    Scalar globalResidual(SolutionVector &dest,
+                          const SolutionVector &u)
+    {
+        SolutionVector tmp(curSol());
+        curSol() = u;
+        Scalar res = globalResidual(dest);
+        curSol() = tmp;
+        return res;
+    }
+
+    /*!
+     * \brief Compute the global residual for the current solution
+     *        vector.
+     *
+     * \param dest Stores the result
+     */
+    Scalar globalResidual(SolutionVector &dest)
+    {
+        dest = 0;
+
+        ElementIterator elemIt = gridView_().template begin<0>();
+        const ElementIterator elemEndIt = gridView_().template end<0>();
+        for (; elemIt != elemEndIt; ++elemIt) {
+            localResidual().eval(*elemIt);
+
+            int globalI = elementMapper().map(*elemIt);
+            dest[globalI] = localResidual().residual(0);
+        }
+
+        // calculate the square norm of the residual
+        Scalar result2 = dest.two_norm2();
+        if (gridView_().comm().size() > 1)
+            result2 = gridView_().comm().sum(result2);
+
+        return std::sqrt(result2);
+    }
+
+    /*!
+     * \brief Compute the integral over the domain of the storage
+     *        terms of all conservation quantities.
+     *
+     * \param dest Stores the result
+     */
+    void globalStorage(PrimaryVariables &dest)
+    {
+        dest = 0;
+
+        ElementIterator elemIt = gridView_().template begin<0>();
+        const ElementIterator elemEndIt = gridView_().template end<0>();
+        for (; elemIt != elemEndIt; ++elemIt) {
+            localResidual().evalStorage(*elemIt);
+
+            dest += localResidual().storageTerm()[0];
+        };
+
+        if (gridView_().comm().size() > 1)
+            dest = gridView_().comm().sum(dest);
+    }
+
+    /*!
+     * \brief Reference to the current solution as a block vector.
+     */
+    const SolutionVector &curSol() const
+    { return uCur_; }
+
+    /*!
+     * \brief Reference to the current solution as a block vector.
+     */
+    SolutionVector &curSol()
+    { return uCur_; }
+
+    /*!
+     * \brief Reference to the previous solution as a block vector.
+     */
+    const SolutionVector &prevSol() const
+    { return uPrev_; }
+
+    /*!
+     * \brief Reference to the previous solution as a block vector.
+     */
+    SolutionVector &prevSol()
+    { return uPrev_; }
+
+    /*!
+     * \brief Returns the operator assembler for the global jacobian of
+     *        the problem.
+     */
+    JacobianAssembler &jacobianAssembler()
+    { return *jacAsm_; }
+
+    /*!
+     * \copydoc jacobianAssembler()
+     */
+    const JacobianAssembler &jacobianAssembler() const
+    { return *jacAsm_; }
+
+    /*!
+     * \brief Returns the local jacobian which calculates the local
+     *        stiffness matrix for an arbitrary element.
+     *
+     * The local stiffness matrices of the element are used by
+     * the jacobian assembler to produce a global linerization of the
+     * problem.
+     */
+    LocalJacobian &localJacobian()
+    { return localJacobian_; }
+    /*!
+     * \copydoc localJacobian()
+     */
+    const LocalJacobian &localJacobian() const
+    { return localJacobian_; }
+
+    /*!
+     * \brief Returns the local residual function.
+     */
+    LocalResidual &localResidual()
+    { return localJacobian().localResidual(); }
+    /*!
+     * \copydoc localResidual()
+     */
+    const LocalResidual &localResidual() const
+    { return localJacobian().localResidual(); }
+
+    /*!
+     * \brief Returns the relative weight of a primary variable for
+     *        calculating relative errors.
+     *
+     * \param dofIdx The global index of the control volume
+     * \param pvIdx The index of the primary variable
+     */
+    Scalar primaryVarWeight(int dofIdx, int pvIdx) const
+    {
+        return 1.0/std::max(std::abs(this->prevSol()[dofIdx][pvIdx]), 1.0);
+    }
+
+    /*!
+     * \brief Returns the relative error between two vectors of
+     *        primary variables.
+     *
+     * \param vertexIdx The global index of the control volume's
+     *                  associated vertex
+     * \param pv1 The first vector of primary variables
+     * \param pv2 The second vector of primary variables
+     *
+     * \todo The vertexIdx argument is pretty hacky. it is required by
+     *       models with pseudo primary variables (i.e. the primary
+     *       variable switching models). the clean solution would be
+     *       to access the pseudo primary variables from the primary
+     *       variables.
+     */
+    Scalar relativeErrorVertex(int vertexIdx,
+                               const PrimaryVariables &pv1,
+                               const PrimaryVariables &pv2)
+    {
+        Scalar result = 0.0;
+        for (int j = 0; j < numEq; ++j) {
+            //Scalar weight = asImp_().primaryVarWeight(vertexIdx, j);
+            //Scalar eqErr = std::abs(pv1[j] - pv2[j])*weight;
+            Scalar eqErr = std::abs(pv1[j] - pv2[j]);
+            eqErr /= std::max<Scalar>(1.0, std::abs(pv1[j] + pv2[j])/2);
+
+            result = std::max(result, eqErr);
+        }
+        return result;
+    }
+
+    /*!
+     * \brief Try to progress the model to the next timestep.
+     *
+     * \param solver The non-linear solver
+     * \param controller The controller which specifies the behaviour
+     *                   of the non-linear solver
+     */
+    bool update(NewtonMethod &solver,
+                NewtonController &controller)
+    {
+#if HAVE_VALGRIND
+        for (size_t i = 0; i < curSol().size(); ++i)
+            Valgrind::CheckDefined(curSol()[i]);
+#endif // HAVE_VALGRIND
+
+        asImp_().updateBegin();
+
+        bool converged = solver.execute(controller);
+        if (converged) {
+            asImp_().updateSuccessful();
+        }
+        else
+            asImp_().updateFailed();
+
+#if HAVE_VALGRIND
+        for (size_t i = 0; i < curSol().size(); ++i) {
+            Valgrind::CheckDefined(curSol()[i]);
+        }
+#endif // HAVE_VALGRIND
+
+        return converged;
+    }
+
+
+    /*!
+     * \brief Called by the update() method before it tries to
+     *        apply the newton method. This is primary a hook
+     *        which the actual model can overload.
+     */
+    void updateBegin()
+    { }
+
+
+    /*!
+     * \brief Called by the update() method if it was
+     *        successful. This is primary a hook which the actual
+     *        model can overload.
+     */
+    void updateSuccessful()
+    { };
+
+    /*!
+     * \brief Called by the update() method if it was
+     *        unsuccessful. This is primary a hook which the actual
+     *        model can overload.
+     */
+    void updateFailed()
+    {
+        // Reset the current solution to the one of the
+        // previous time step so that we can start the next
+        // update at a physically meaningful solution.
+        uCur_ = uPrev_;
+
+        jacAsm_->reassembleAll();
+    };
+
+    /*!
+     * \brief Called by the problem if a time integration was
+     *        successful, post processing of the solution is done and
+     *        the result has been written to disk.
+     *
+     * This should prepare the model for the next time integration.
+     */
+    void advanceTimeLevel()
+    {
+        // make the current solution the previous one.
+        uPrev_ = uCur_;
+
+        updatePrevHints();
+    }
+
+    /*!
+     * \brief Serializes the current state of the model.
+     *
+     * \tparam Restarter The type of the serializer class
+     *
+     * \param res The serializer object
+     */
+    template <class Restarter>
+    void serialize(Restarter &res)
+    { res.template serializeEntities<0>(asImp_(), this->gridView_()); }
+
+    /*!
+     * \brief Deserializes the state of the model.
+     *
+     * \tparam Restarter The type of the serializer class
+     *
+     * \param res The serializer object
+     */
+    template <class Restarter>
+    void deserialize(Restarter &res)
+    {
+        res.template deserializeEntities<0>(asImp_(), this->gridView_());
+        prevSol() = curSol();
+    }
+
+    /*!
+     * \brief Write the current solution for a vertex to a restart
+     *        file.
+     *
+     * \param outstream The stream into which the vertex data should
+     *                  be serialized to
+     * \param vert The DUNE Codim<dim> entity which's data should be
+     *             serialized
+     */
+    void serializeEntity(std::ostream &outstream,
+                         const Element &element)
+    {
+        int elemIdx = dofMapper().map(element);
+
+        // write phase state
+        if (!outstream.good()) {
+            DUNE_THROW(Dune::IOError,
+                       "Could not serialize element "
+                       << elemIdx);
+        }
+
+        for (int eqIdx = 0; eqIdx < numEq; ++eqIdx) {
+            outstream << curSol()[elemIdx][eqIdx] << " ";
+        }
+    }
+
+    /*!
+     * \brief Reads the current solution variables for a vertex from a
+     *        restart file.
+     *
+     * \param instream The stream from which the vertex data should
+     *                  be deserialized from
+     * \param vert The DUNE Codim<dim> entity which's data should be
+     *             deserialized
+     */
+    void deserializeEntity(std::istream &instream,
+                           const Element &element)
+    {
+        int elemIdx = dofMapper().map(element);
+        for (int eqIdx = 0; eqIdx < numEq; ++eqIdx) {
+            if (!instream.good())
+                DUNE_THROW(Dune::IOError,
+                           "Could not deserialize element "
+                           << elemIdx);
+            instream >> curSol()[elemIdx][eqIdx];
+        }
+    }
+
+    /*!
+     * \brief Returns the number of global degrees of freedoms (DOFs)
+     */
+    size_t numDofs() const
+    { return gridView_().size(0); }
+
+    /*!
+     * \brief Mapper for the entities where degrees of freedoms are
+     *        defined to indices.
+     *
+     * Here, this means a mapper for elements.
+     */
+    const DofMapper &dofMapper() const
+    { return problem_().elementMapper(); };
+
+    /*!
+     * \brief Mapper for vertices to indices.
+     */
+    const VertexMapper &vertexMapper() const
+    { return problem_().vertexMapper(); };
+
+    /*!
+     * \brief Mapper for elements to indices.
+     */
+    const ElementMapper &elementMapper() const
+    { return problem_().elementMapper(); };
+
+    /*!
+     * \brief Resets the Jacobian matrix assembler, so that the
+     *        boundary types can be altered.
+     */
+    void resetJacobianAssembler ()
+    {
+        delete jacAsm_;
+        jacAsm_ = new JacobianAssembler;
+        jacAsm_->init(problem_());
+    }
+
+    /*!
+     * \brief Update the weights of all primary variables within an
+     *        element given the complete set of volume variables
+     *
+     * \param element The DUNE codim 0 entity
+     * \param volVars All volume variables for the element
+     */
+    void updatePVWeights(const Element &element,
+                         const ElementVolumeVariables &volVars) const
+    { };
+
+    /*!
+     * \brief Add the vector fields for analysing the convergence of
+     *        the newton method to the a VTK multi writer.
+     *
+     * \tparam MultiWriter The type of the VTK multi writer
+     *
+     * \param writer  The VTK multi writer object on which the fields should be added.
+     * \param u       The solution function
+     * \param deltaU  The delta of the solution function before and after the Newton update
+     */
+    template <class MultiWriter>
+    void addConvergenceVtkFields(MultiWriter &writer,
+                                 const SolutionVector &u,
+                                 const SolutionVector &deltaU)
+    {}
+
+    /*!
+     * \brief Add the quantities of a time step which ought to be written to disk.
+     *
+     * This should be overwritten by the actual model if any secondary
+     * variables should be written out. Read: This should _always_ be
+     * overwritten by well behaved models!
+     *
+     * \tparam MultiWriter The type of the VTK multi writer
+     *
+     * \param sol The global vector of primary variable values.
+     * \param writer The VTK multi writer where the fields should be added.
+     */
+    template <class MultiWriter>
+    void addOutputVtkFields(const SolutionVector &sol,
+                            MultiWriter &writer)
+    {
+        typedef Dune::BlockVector<Dune::FieldVector<Scalar, 1> > ScalarField;
+
+        // create the required scalar fields
+        unsigned numElements = this->gridView_().size(0);
+
+        // global defect of the two auxiliary equations
+        ScalarField* x[numEq];
+        for (int i = 0; i < numEq; ++i) {
+            x[i] = writer.allocateManagedBuffer(numElements);
+        }
+
+        ElementIterator eIt = this->gridView_().template begin<0>();
+        ElementIterator eEndIt = this->gridView_().template end<0>();
+        for (; eIt != eEndIt; ++ eIt)
+        {
+            int globalIdx = elementMapper().map(*eIt);
+            for (int i = 0; i < numEq; ++i) {
+                (*x[i])[globalIdx] = sol[globalIdx][i];
+            }
+        }
+
+        for (int i = 0; i < numEq; ++i) {
+            std::ostringstream oss;
+            oss << "primaryVar_" << i;
+            writer.attachCellData(*x[i], oss.str());
+        }
+    }
+
+    /*!
+     * \brief Reference to the grid view of the spatial domain.
+     */
+    const GridView &gridView() const
+    { return problem_().gridView(); }
+
+    /*!
+     * \brief Returns true if the control volume touches
+     *        the grid's boundary.
+     *
+     * \param globalIdx The global index of the control volume
+     */
+    bool onBoundary(int globalIdx) const
+    { return boundaryIndices_[globalIdx]; }
+
+    /*!
+     * \brief Returns true if the control volume touches
+     *        the grid's boundary.
+     *
+     * \param elem A DUNE Codim<0> entity coinciding with the control
+     *             volume.
+     */
+    bool onBoundary(const Element &elem) const
+    { return onBoundary(elementMapper().map(elem)); }
+
+    /*!
+     * \brief Fill the fluid state according to the primary variables. 
+     * 
+     * Taking the information from the primary variables, 
+     * the fluid state is filled with every information that is 
+     * necessary to evaluate the model's local residual. 
+     * 
+     * \param primaryVariables The primary variables of the model. 
+     * \param problem The problem at hand. 
+     * \param element The current element. 
+     * \param elementGeometry The finite volume element geometry. 
+     * \param scvIdx The index of the subcontrol volume. 
+     * \param fluidState The fluid state to fill. 
+     */
+    template <class FluidState>
+    static void completeFluidState(const PrimaryVariables& primaryVariables,
+                                   const Problem& problem,
+                                   const Element& element,
+                                   const FVElementGeometry& elementGeometry,
+                                   FluidState& fluidState)
+    {
+        VolumeVariables::completeFluidState(primaryVariables, problem, element,
+                                            elementGeometry, fluidState);
+    }
+protected:
+    /*!
+     * \brief A reference to the problem on which the model is applied.
+     */
+    Problem &problem_()
+    { return *problemPtr_; }
+    /*!
+     * \copydoc problem_()
+     */
+    const Problem &problem_() const
+    { return *problemPtr_; }
+
+    /*!
+     * \brief Reference to the grid view of the spatial domain.
+     */
+    const GridView &gridView_() const
+    { return problem_().gridView(); }
+
+    /*!
+     * \brief Reference to the local residal object
+     */
+    LocalResidual &localResidual_()
+    { return localJacobian_.localResidual(); }
+
+    /*!
+     * \brief Applies the initial solution for all vertices of the grid.
+     */
+    void applyInitialSolution_()
+    {
+        // first set the whole domain to zero
+        uCur_ = Scalar(0.0);
+
+        FVElementGeometry fvElemGeom;
+
+        // iterate through leaf grid and evaluate initial
+        // condition at the center of each sub control volume
+        //
+        // TODO: the initial condition needs to be unique for
+        // each vertex. we should think about the API...
+        ElementIterator it = gridView_().template begin<0>();
+        const ElementIterator &eendit = gridView_().template end<0>();
+        for (; it != eendit; ++it) {
+            // deal with the current element
+            fvElemGeom.update(gridView_(), *it);
+
+            // map the local vertex index to the global one
+            int globalIdx = elementMapper().map(*it);
+
+            // let the problem do the dirty work of nailing down
+            // the initial solution.
+            PrimaryVariables initVal;
+            Valgrind::SetUndefined(initVal);
+            problem_().initial(initVal,
+                               *it,
+                               fvElemGeom,
+                               0);
+            Valgrind::CheckDefined(initVal);
+
+            uCur_[globalIdx] = initVal;
+            Valgrind::CheckDefined(uCur_[globalIdx]);
+        }
+    }
+
+    /*!
+     * \brief Find all indices of boundary vertices.
+     *
+     * For this we need to loop over all intersections (which is slow
+     * in general). If the DUNE grid interface would provide a
+     * onBoundary() method for entities this could be done in a much
+     * nicer way (actually this would not be necessary)
+     */
+    void updateBoundaryIndices_()
+    {
+        boundaryIndices_.resize(numDofs());
+        std::fill(boundaryIndices_.begin(), boundaryIndices_.end(), false);
+
+        ElementIterator eIt = gridView_().template begin<0>();
+        ElementIterator eEndIt = gridView_().template end<0>();
+        for (; eIt != eEndIt; ++eIt) {
+            IntersectionIterator isIt = gridView_().ibegin(*eIt);
+            IntersectionIterator isEndIt = gridView_().iend(*eIt);
+            for (; isIt != isEndIt; ++isIt) {
+                if (!isIt->boundary())
+                    continue;
+
+                int globalIdx = elementMapper().map(*eIt);
+                boundaryIndices_[globalIdx] = true;
+            }
+        }
+    }
+
+    // the problem we want to solve. defines the constitutive
+    // relations, matxerial laws, etc.
+    Problem *problemPtr_;
+
+    // calculates the local jacobian matrix for a given element
+    LocalJacobian localJacobian_;
+    // Linearizes the problem at the current time step using the
+    // local jacobian
+    JacobianAssembler *jacAsm_;
+
+    // the set of all indices of vertices on the boundary
+    std::vector<bool> boundaryIndices_;
+
+    // cur is the current iterative solution, prev the converged
+    // solution of the previous time step
+    SolutionVector uCur_;
+    SolutionVector uPrev_;
+
+private:
+    /*!
+     * \brief Returns whether messages should be printed
+     */
+    bool verbose_() const
+    { return gridView_().comm().rank() == 0; };
+
+    Implementation &asImp_()
+    { return *static_cast<Implementation*>(this); }
+    const Implementation &asImp_() const
+    { return *static_cast<const Implementation*>(this); }
+
+    bool enableHints_;
+};
+}
+
+#endif
diff --git a/dumux/implicit/cellcentered/ccproblem.hh b/dumux/implicit/cellcentered/ccproblem.hh
new file mode 100644
index 0000000000..ed4dbeb073
--- /dev/null
+++ b/dumux/implicit/cellcentered/ccproblem.hh
@@ -0,0 +1,849 @@
+// -*- mode: C++; tab-width: 4; indent-tabs-mode: nil; c-basic-offset: 4 -*-
+// vi: set et ts=4 sw=4 sts=4:
+/*****************************************************************************
+ *   Copyright (C) 2009 by Andreas Lauser                                    *
+ *   Institute for Modelling Hydraulic and Environmental Systems             *
+ *   University of Stuttgart, Germany                                        *
+ *   email: <givenname>.<name>@iws.uni-stuttgart.de                          *
+ *                                                                           *
+ *   This program is free software: you can redistribute it and/or modify    *
+ *   it under the terms of the GNU General Public License as published by    *
+ *   the Free Software Foundation, either version 2 of the License, or       *
+ *   (at your option) any later version.                                     *
+ *                                                                           *
+ *   This program is distributed in the hope that it will be useful,         *
+ *   but WITHOUT ANY WARRANTY; without even the implied warranty of          *
+ *   MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the           *
+ *   GNU General Public License for more details.                            *
+ *                                                                           *
+ *   You should have received a copy of the GNU General Public License       *
+ *   along with this program.  If not, see <http://www.gnu.org/licenses/>.   *
+ *****************************************************************************/
+/*!
+ * \file
+ * \brief Base class for all problems which use the box scheme
+ */
+#ifndef DUMUX_CC_PROBLEM_HH
+#define DUMUX_CC_PROBLEM_HH
+
+#include "ccproperties.hh"
+
+#include <dumux/io/vtkmultiwriter.hh>
+#include <dumux/io/restart.hh>
+
+namespace Dumux
+{
+/*!
+ * \ingroup CCModel
+ * \ingroup CCBaseProblems
+ * \brief Base class for all problems which use the box scheme.
+ *
+ * \note All quantities are specified assuming a threedimensional
+ *       world. Problems discretized using 2D grids are assumed to be
+ *       extruded by \f$1 m\f$ and 1D grids are assumed to have a
+ *       cross section of \f$1m \times 1m\f$.
+ */
+template<class TypeTag>
+class CCProblem
+{
+private:
+    typedef typename GET_PROP_TYPE(TypeTag, Problem) Implementation;
+    typedef typename GET_PROP_TYPE(TypeTag, GridView) GridView;
+
+    typedef Dumux::VtkMultiWriter<GridView> VtkMultiWriter;
+
+    typedef typename GET_PROP_TYPE(TypeTag, NewtonMethod) NewtonMethod;
+    typedef typename GET_PROP_TYPE(TypeTag, NewtonController) NewtonController;
+
+    typedef typename GET_PROP_TYPE(TypeTag, Model) Model;
+    typedef typename GET_PROP_TYPE(TypeTag, Scalar) Scalar;
+    typedef typename GET_PROP_TYPE(TypeTag, TimeManager) TimeManager;
+
+    typedef typename GET_PROP_TYPE(TypeTag, VertexMapper) VertexMapper;
+    typedef typename GET_PROP_TYPE(TypeTag, ElementMapper) ElementMapper;
+
+    typedef typename GET_PROP_TYPE(TypeTag, PrimaryVariables) PrimaryVariables;
+    typedef typename GET_PROP_TYPE(TypeTag, ElementVolumeVariables) ElementVolumeVariables;
+    typedef typename GET_PROP_TYPE(TypeTag, FVElementGeometry) FVElementGeometry;
+    typedef typename GET_PROP_TYPE(TypeTag, BoundaryTypes) BoundaryTypes;
+
+    enum {
+        dim = GridView::dimension,
+        dimWorld = GridView::dimensionworld
+    };
+
+    typedef typename GridView::template Codim<0>::Entity Element;
+    typedef typename GridView::template Codim<dim>::Entity Vertex;
+    typedef typename GridView::template Codim<dim>::Iterator VertexIterator;
+    typedef typename GridView::template Codim<0>::Iterator ElementIterator;
+    typedef typename GridView::Intersection Intersection;
+
+    typedef typename GridView::Grid::ctype CoordScalar;
+    typedef Dune::FieldVector<CoordScalar, dimWorld> GlobalPosition;
+
+    // copying a problem is not a good idea
+    CCProblem(const CCProblem &);
+
+public:
+    /*!
+     * \brief Constructor
+     *
+     * \param timeManager The TimeManager which is used by the simulation
+     * \param gridView The simulation's idea about physical space
+     */
+    CCProblem(TimeManager &timeManager, const GridView &gridView)
+        : gridView_(gridView)
+        , bboxMin_(std::numeric_limits<double>::max())
+        , bboxMax_(-std::numeric_limits<double>::max())
+        , elementMapper_(gridView)
+        , vertexMapper_(gridView)
+        , timeManager_(&timeManager)
+        , newtonMethod_(asImp_())
+        , newtonCtl_(asImp_())
+    {
+        // calculate the bounding box of the local partition of the grid view
+//        VertexIterator vIt = gridView.template begin<dim>();
+//        const VertexIterator vEndIt = gridView.template end<dim>();
+//        for (; vIt!=vEndIt; ++vIt) {
+//            for (int i=0; i<dim; i++) {
+//                bboxMin_[i] = std::min(bboxMin_[i], vIt->geometry().corner(0)[i]);
+//                bboxMax_[i] = std::max(bboxMax_[i], vIt->geometry().corner(0)[i]);
+//            }
+//        }
+
+        // HACK due to current handling of Dirichlet boundary conditions
+        ElementIterator it = gridView.template begin<0>();
+        const ElementIterator endIt = gridView.template end<0>();
+        for (; it!=endIt; ++it) {
+            for (int i=0; i<dim; i++) {
+                bboxMin_[i] = std::min(bboxMin_[i], it->geometry().center()[i]);
+                bboxMax_[i] = std::max(bboxMax_[i], it->geometry().center()[i]);
+            }
+        }
+
+        // communicate to get the bounding box of the whole domain
+        if (gridView.comm().size() > 1)
+            for (int i = 0; i < dim; ++i) {
+                bboxMin_[i] = gridView.comm().min(bboxMin_[i]);
+                bboxMax_[i] = gridView.comm().max(bboxMax_[i]);
+            }
+
+        // set a default name for the problem
+        simName_ = "sim";
+
+        resultWriter_ = NULL;
+    }
+
+    ~CCProblem()
+    {
+        delete resultWriter_;
+    };
+
+
+    /*!
+     * \brief Called by the Dumux::TimeManager in order to
+     *        initialize the problem.
+     *
+     * If you overload this method don't forget to call
+     * ParentType::init()
+     */
+    void init()
+    {
+        // set the initial condition of the model
+        model().init(asImp_());
+    }
+
+    /*!
+     * \brief Specifies which kind of boundary condition should be
+     *        used for which equation on a given boundary segment.
+     *
+     * \param values The boundary types for the conservation equations
+     * \param intersection The intersection for which the boundary type is set
+     */
+    void boundaryTypes(BoundaryTypes &values,
+                       const Intersection &intersection) const
+    {
+        // forward it to the method which only takes the global coordinate
+        asImp_().boundaryTypesAtPos(values, intersection.geometry().center());
+    }
+
+    /*!
+     * \brief Specifies which kind of boundary condition should be
+     *        used for which equation on a given boundary segment.
+     *
+     * \param values The boundary types for the conservation equations
+     * \param pos The position of the finite volume in global coordinates
+     */
+    void boundaryTypesAtPos(BoundaryTypes &values,
+                            const GlobalPosition &pos) const
+    {
+        // Throw an exception (there is no reasonable default value
+        // for Dirichlet conditions)
+        DUNE_THROW(Dune::InvalidStateException,
+                   "The problem does not provide "
+                   "a boundaryTypes() method.");
+    }
+
+
+    /*!
+     * \brief Evaluate the boundary conditions for a dirichlet
+     *        control volume.
+     *
+     * \param values The dirichlet values for the primary variables
+     * \param intersection The intersection representing the "half volume on the boundary"
+     *
+     * For this method, the \a values parameter stores primary variables.
+     */
+    void dirichlet(PrimaryVariables &values,
+                   const Intersection &intersection) const
+    {
+        // forward it to the method which only takes the global coordinate
+        asImp_().dirichletAtPos(values, intersection.geometry().center());
+    }
+
+    /*!
+     * \brief Evaluate the boundary conditions for a dirichlet
+     *        control volume.
+     *
+     * \param values The dirichlet values for the primary variables
+     * \param pos The position of the center of the finite volume
+     *            for which the dirichlet condition ought to be
+     *            set in global coordinates
+     *
+     * For this method, the \a values parameter stores primary variables.
+     */
+    void dirichletAtPos(PrimaryVariables &values,
+                        const GlobalPosition &pos) const
+    {
+        // Throw an exception (there is no reasonable default value
+        // for Dirichlet conditions)
+        DUNE_THROW(Dune::InvalidStateException,
+                   "The problem specifies that some boundary "
+                   "segments are dirichlet, but does not provide "
+                   "a dirichlet() method.");
+    }
+
+    /*!
+     * \brief Evaluate the boundary conditions for a neumann
+     *        boundary segment.
+     *
+     * This is the method for the case where the Neumann condition is
+     * potentially solution dependent and requires some box method
+     * specific things.
+     *
+     * \param values The neumann values for the conservation equations [kg / (m^2 *s )]
+     * \param element The finite element
+     * \param fvElemGeom The finite-volume geometry in the box scheme
+     * \param is The intersection between element and boundary
+     * \param scvIdx The local vertex index
+     * \param boundaryFaceIdx The index of the boundary face
+     * \param elemVolVars All volume variables for the element
+     *
+     * For this method, the \a values parameter stores the mass flux
+     * in normal direction of each phase. Negative values mean influx.
+     */
+    void boxSDNeumann(PrimaryVariables &values,
+                      const Element &element,
+                      const FVElementGeometry &fvElemGeom,
+                      const Intersection &is,
+                      int scvIdx,
+                      int boundaryFaceIdx,
+                      const ElementVolumeVariables &elemVolVars) const
+    {
+        // forward it to the interface without the volume variables
+        asImp_().neumann(values,
+                         element,
+                         fvElemGeom,
+                         is,
+                         scvIdx,
+                         boundaryFaceIdx);
+    }
+
+    /*!
+     * \brief Evaluate the boundary conditions for a neumann
+     *        boundary segment.
+     *
+     * \param values The neumann values for the conservation equations [kg / (m^2 *s )]
+     * \param element The finite element
+     * \param fvElemGeom The finite-volume geometry in the box scheme
+     * \param is The intersection between element and boundary
+     * \param scvIdx The local vertex index
+     * \param boundaryFaceIdx The index of the boundary face
+     *
+     * For this method, the \a values parameter stores the mass flux
+     * in normal direction of each phase. Negative values mean influx.
+     */
+    void neumann(PrimaryVariables &values,
+                 const Element &element,
+                 const FVElementGeometry &fvElemGeom,
+                 const Intersection &is,
+                 int scvIdx,
+                 int boundaryFaceIdx) const
+    {
+        // forward it to the interface with only the global position
+        asImp_().neumannAtPos(values, fvElemGeom.boundaryFace[boundaryFaceIdx].ipGlobal);
+    }
+
+    /*!
+     * \brief Evaluate the boundary conditions for a neumann
+     *        boundary segment.
+     *
+     * \param values The neumann values for the conservation equations [kg / (m^2 *s )]
+     * \param pos The position of the boundary face's integration point in global coordinates
+     *
+     * For this method, the \a values parameter stores the mass flux
+     * in normal direction of each phase. Negative values mean influx.
+     */
+    void neumannAtPos(PrimaryVariables &values,
+                      const GlobalPosition &pos) const
+    {
+        // Throw an exception (there is no reasonable default value
+        // for Neumann conditions)
+        DUNE_THROW(Dune::InvalidStateException,
+                   "The problem specifies that some boundary "
+                   "segments are neumann, but does not provide "
+                   "a neumannAtPos() method.");
+    }
+
+    /*!
+     * \brief Evaluate the source term for all phases within a given
+     *        sub-control-volume.
+     *
+     * This is the method for the case where the source term is
+     * potentially solution dependent and requires some box method
+     * specific things.
+     *
+     * \param values The source and sink values for the conservation equations
+     * \param element The finite element
+     * \param fvElemGeom The finite-volume geometry in the box scheme
+     * \param scvIdx The local vertex index
+     * \param elemVolVars All volume variables for the element
+     *
+     * For this method, the \a values parameter stores the rate mass
+     * generated or annihilate per volume unit. Positive values mean
+     * that mass is created, negative ones mean that it vanishes.
+     */
+    void boxSDSource(PrimaryVariables &values,
+                     const Element &element,
+                     const FVElementGeometry &fvElemGeom,
+                     int scvIdx,
+                     const ElementVolumeVariables &elemVolVars) const
+    {
+        // forward to solution independent, box specific interface
+        asImp_().source(values, element, fvElemGeom, scvIdx);
+    }
+
+    /*!
+     * \brief Evaluate the source term for all phases within a given
+     *        sub-control-volume.
+     *
+     * \param values The source and sink values for the conservation equations
+     * \param element The finite element
+     * \param fvElemGeom The finite-volume geometry in the box scheme
+     * \param scvIdx The local vertex index
+     *
+     * For this method, the \a values parameter stores the rate mass
+     * generated or annihilate per volume unit. Positive values mean
+     * that mass is created, negative ones mean that it vanishes.
+     */
+    void source(PrimaryVariables &values,
+                const Element &element,
+                const FVElementGeometry &fvElemGeom,
+                int scvIdx) const
+    {
+        // forward to generic interface
+        asImp_().sourceAtPos(values, fvElemGeom.subContVol[scvIdx].global);
+    }
+
+    /*!
+     * \brief Evaluate the source term for all phases within a given
+     *        sub-control-volume.
+     *
+     * \param values The source and sink values for the conservation equations
+     * \param pos The position of the center of the finite volume
+     *            for which the source term ought to be
+     *            specified in global coordinates
+     *
+     * For this method, the \a values parameter stores the rate mass
+     * generated or annihilate per volume unit. Positive values mean
+     * that mass is created, negative ones mean that it vanishes.
+     */
+    void sourceAtPos(PrimaryVariables &values,
+                     const GlobalPosition &pos) const
+    {
+        DUNE_THROW(Dune::InvalidStateException,
+                   "The problem does not provide "
+                   "a sourceAtPos() method.");
+    }
+
+    /*!
+     * \brief Evaluate the initial value for a control volume.
+     *
+     * \param values The initial values for the primary variables
+     * \param element The finite element
+     * \param fvElemGeom The finite-volume geometry in the box scheme
+     * \param scvIdx The local vertex index
+     *
+     * For this method, the \a values parameter stores primary
+     * variables.
+     */
+    void initial(PrimaryVariables &values,
+                 const Element &element,
+                 const FVElementGeometry &fvElemGeom,
+                 int scvIdx) const
+    {
+        // forward to generic interface
+        asImp_().initialAtPos(values, fvElemGeom.subContVol[scvIdx].global);
+    }
+
+    /*!
+     * \brief Evaluate the initial value for a control volume.
+     *
+     * \param values The dirichlet values for the primary variables
+     * \param pos The position of the center of the finite volume
+     *            for which the initial values ought to be
+     *            set (in global coordinates)
+     *
+     * For this method, the \a values parameter stores primary variables.
+     */
+    void initialAtPos(PrimaryVariables &values,
+                      const GlobalPosition &pos) const
+    {
+        // Throw an exception (there is no reasonable default value
+        // for Dirichlet conditions)
+        DUNE_THROW(Dune::InvalidStateException,
+                   "The problem does not provide "
+                   "a initialAtPos() method.");
+    }
+
+    /*!
+     * \brief Return how much the domain is extruded at a given sub-control volume.
+     *
+     * This means the factor by which a lower-dimensional (1D or 2D)
+     * entity needs to be expanded to get a full dimensional cell. The
+     * default is 1.0 which means that 1D problems are actually
+     * thought as pipes with a cross section of 1 m^2 and 2D problems
+     * are assumed to extend 1 m to the back.
+     */
+    Scalar boxExtrusionFactor(const Element &element,
+                              const FVElementGeometry &fvElemGeom,
+                              int scvIdx) const
+    {
+        // forward to generic interface
+        return asImp_().extrusionFactorAtPos(fvElemGeom.subContVol[scvIdx].global);
+    }
+
+    /*!
+     * \brief Return how much the domain is extruded at a given position.
+     *
+     * This means the factor by which a lower-dimensional (1D or 2D)
+     * entity needs to be expanded to get a full dimensional cell. The
+     * default is 1.0 which means that 1D problems are actually
+     * thought as pipes with a cross section of 1 m^2 and 2D problems
+     * are assumed to extend 1 m to the back.
+     */
+    Scalar extrusionFactorAtPos(const GlobalPosition &pos) const
+    { return 1.0; }
+
+    /*!
+     * \brief If model coupling is used, this updates the parameters
+     *        required to calculate the coupling fluxes between the
+     *        sub-models.
+     *
+     * By default it does nothing
+     *
+     * \param element The DUNE Codim<0> entity for which the coupling
+     *                parameters should be computed.
+     */
+    void updateCouplingParams(const Element &element) const
+    {}
+
+    /*!
+     * \name Simulation steering
+     */
+    // \{
+
+    /*!
+     * \brief Called by the time manager before the time integration.
+     */
+    void preTimeStep()
+    {}
+
+    /*!
+     * \brief Called by Dumux::TimeManager in order to do a time
+     *        integration on the model.
+     */
+    void timeIntegration()
+    {
+        const int maxFails = 10;
+        for (int i = 0; i < maxFails; ++i) {
+            if (model_.update(newtonMethod_, newtonCtl_))
+                return;
+
+            Scalar dt = timeManager().timeStepSize();
+            Scalar nextDt = dt / 2;
+            timeManager().setTimeStepSize(nextDt);
+
+            // update failed
+            std::cout << "Newton solver did not converge with dt="<<dt<<" seconds. Retrying with time step of "
+                      << nextDt << " seconds\n";
+        }
+
+        DUNE_THROW(Dune::MathError,
+                   "Newton solver didn't converge after "
+                   << maxFails
+                   << " time-step divisions. dt="
+                   << timeManager().timeStepSize());
+    }
+
+    /*!
+     * \brief Returns the newton method object
+     */
+    NewtonMethod &newtonMethod()
+    { return newtonMethod_; }
+
+    /*!
+     * \copydoc newtonMethod()
+     */
+    const NewtonMethod &newtonMethod() const
+    { return newtonMethod_; }
+
+    /*!
+     * \brief Returns the newton contoller object
+     */
+    NewtonController &newtonController()
+    { return newtonCtl_; }
+
+    /*!
+     * \copydoc newtonController()
+     */
+    const NewtonController &newtonController() const
+    { return newtonCtl_; }
+
+    /*!
+     * \brief Called by Dumux::TimeManager whenever a solution for a
+     *        time step has been computed and the simulation time has
+     *        been updated.
+     *
+     * \param dt The current time-step size
+     */
+    Scalar nextTimeStepSize(Scalar dt)
+    {
+        return std::min(GET_PARAM_FROM_GROUP(TypeTag, Scalar, TimeManager, MaxTimeStepSize),
+                        newtonCtl_.suggestTimeStepSize(dt));
+    };
+
+    /*!
+     * \brief Returns true if a restart file should be written to
+     *        disk.
+     *
+     * The default behavior is to write one restart file every 5 time
+     * steps. This file is intended to be overwritten by the
+     * implementation.
+     */
+    bool shouldWriteRestartFile() const
+    {
+        return timeManager().timeStepIndex() > 0 &&
+            (timeManager().timeStepIndex() % 10 == 0);
+    }
+
+    /*!
+     * \brief Returns true if the current solution should be written to
+     *        disk (i.e. as a VTK file)
+     *
+     * The default behavior is to write out every the solution for
+     * very time step. This file is intended to be overwritten by the
+     * implementation.
+     */
+    bool shouldWriteOutput() const
+    { return true; }
+
+    /*!
+     * \brief Called by the time manager after the time integration to
+     *        do some post processing on the solution.
+     */
+    void postTimeStep()
+    { }
+
+    /*!
+     * \brief Called by the time manager after everything which can be
+     *        done about the current time step is finished and the
+     *        model should be prepared to do the next time integration.
+     */
+    void advanceTimeLevel()
+    {
+        model_.advanceTimeLevel();
+    }
+
+    /*!
+     * \brief Called when the end of an simulation episode is reached.
+     *
+     * Typically a new episode should be started in this method.
+     */
+    void episodeEnd()
+    {
+        std::cerr << "The end of an episode is reached, but the problem "
+                  << "does not override the episodeEnd() method. "
+                  << "Doing nothing!\n";
+    };
+    // \}
+
+    /*!
+     * \brief The problem name.
+     *
+     * This is used as a prefix for files generated by the simulation.
+     * It could be either overwritten by the problem files, or simply
+     * declared over the setName() function in the application file.
+     */
+    const char *name() const
+    {
+        return simName_.c_str();
+    }
+
+    /*!
+     * \brief Set the problem name.
+     *
+     * This static method sets the simulation name, which should be
+     * called before the application problem is declared! If not, the
+     * default name "sim" will be used.
+     *
+     * \param newName The problem's name
+     */
+    void setName(const char *newName)
+    {
+        simName_ = newName;
+    }
+
+
+    /*!
+     * \brief Returns the number of the current VTK file.
+     */
+    int currentVTKFileNumber()
+    {
+        createResultWriter_();
+        return resultWriter_->curWriterNum();
+    }
+
+    /*!
+     * \brief The GridView which used by the problem.
+     */
+    const GridView &gridView() const
+    { return gridView_; }
+
+    /*!
+     * \brief The coordinate of the corner of the GridView's bounding
+     *        box with the smallest values.
+     */
+    const GlobalPosition &bboxMin() const
+    { return bboxMin_; }
+
+    /*!
+     * \brief The coordinate of the corner of the GridView's bounding
+     *        box with the largest values.
+     */
+    const GlobalPosition &bboxMax() const
+    { return bboxMax_; }
+
+    /*!
+     * \brief Returns the mapper for vertices to indices.
+     */
+    const VertexMapper &vertexMapper() const
+    { return vertexMapper_; }
+
+    /*!
+     * \brief Returns the mapper for elements to indices.
+     */
+    const ElementMapper &elementMapper() const
+    { return elementMapper_; }
+
+    /*!
+     * \brief Returns TimeManager object used by the simulation
+     */
+    TimeManager &timeManager()
+    { return *timeManager_; }
+
+    /*!
+     * \copydoc timeManager()
+     */
+    const TimeManager &timeManager() const
+    { return *timeManager_; }
+
+    /*!
+     * \brief Returns numerical model used for the problem.
+     */
+    Model &model()
+    { return model_; }
+
+    /*!
+     * \copydoc model()
+     */
+    const Model &model() const
+    { return model_; }
+    // \}
+
+    /*!
+     * \name Restart mechanism
+     */
+    // \{
+
+    /*!
+     * \brief This method writes the complete state of the simulation
+     *        to the harddisk.
+     *
+     * The file will start with the prefix returned by the name()
+     * method, has the current time of the simulation clock in it's
+     * name and uses the extension <tt>.drs</tt>. (Dumux ReStart
+     * file.)  See Dumux::Restart for details.
+     */
+    void serialize()
+    {
+        typedef Dumux::Restart Restarter;
+        Restarter res;
+        res.serializeBegin(asImp_());
+        if (gridView().comm().rank() == 0)
+            std::cout << "Serialize to file '" << res.fileName() << "'\n";
+
+        timeManager().serialize(res);
+        asImp_().serialize(res);
+        res.serializeEnd();
+    }
+
+    /*!
+     * \brief This method writes the complete state of the problem
+     *        to the harddisk.
+     *
+     * The file will start with the prefix returned by the name()
+     * method, has the current time of the simulation clock in it's
+     * name and uses the extension <tt>.drs</tt>. (Dumux ReStart
+     * file.)  See Dumux::Restart for details.
+     *
+     * \tparam Restarter The serializer type
+     *
+     * \param res The serializer object
+     */
+    template <class Restarter>
+    void serialize(Restarter &res)
+    {
+        createResultWriter_();
+        resultWriter_->serialize(res);
+        model().serialize(res);
+    }
+
+    /*!
+     * \brief Load a previously saved state of the whole simulation
+     *        from disk.
+     *
+     * \param tRestart The simulation time on which the program was
+     *                 written to disk.
+     */
+    void restart(Scalar tRestart)
+    {
+        typedef Dumux::Restart Restarter;
+
+        Restarter res;
+
+        res.deserializeBegin(asImp_(), tRestart);
+        if (gridView().comm().rank() == 0)
+            std::cout << "Deserialize from file '" << res.fileName() << "'\n";
+        timeManager().deserialize(res);
+        asImp_().deserialize(res);
+        res.deserializeEnd();
+    }
+
+    /*!
+     * \brief This method restores the complete state of the problem
+     *        from disk.
+     *
+     * It is the inverse of the serialize() method.
+     *
+     * \tparam Restarter The deserializer type
+     *
+     * \param res The deserializer object
+     */
+    template <class Restarter>
+    void deserialize(Restarter &res)
+    {
+        createResultWriter_();
+        resultWriter_->deserialize(res);
+        model().deserialize(res);
+    }
+
+    // \}
+
+    /*!
+     * \brief Adds additional VTK output data to the VTKWriter. Function is called by writeOutput().
+     */
+    void addOutputVtkFields()
+    {}
+
+    /*!
+     * \brief Write the relevant secondary variables of the current
+     *        solution into an VTK output file.
+     */
+    void writeOutput(bool verbose = true)
+    {
+        // write the current result to disk
+        if (asImp_().shouldWriteOutput()) {
+            if (verbose && gridView().comm().rank() == 0)
+                std::cout << "Writing result file for \"" << asImp_().name() << "\"\n";
+
+            // calculate the time _after_ the time was updated
+            Scalar t = timeManager().time() + timeManager().timeStepSize();
+            createResultWriter_();
+            resultWriter_->beginWrite(t);
+            model().addOutputVtkFields(model().curSol(), *resultWriter_);
+            asImp_().addOutputVtkFields();
+            resultWriter_->endWrite();
+        }
+    }
+
+protected:
+    //! Returns the implementation of the problem (i.e. static polymorphism)
+    Implementation &asImp_()
+    { return *static_cast<Implementation *>(this); }
+
+    //! \copydoc asImp_()
+    const Implementation &asImp_() const
+    { return *static_cast<const Implementation *>(this); }
+
+    //! Returns the applied VTK-writer for the output
+    VtkMultiWriter& resultWriter()
+    {
+        createResultWriter_();
+        return *resultWriter_;
+    }
+    //! \copydoc Dumux::IMPETProblem::resultWriter()
+    VtkMultiWriter& resultWriter() const
+    {
+        createResultWriter_();
+        return *resultWriter_;
+    }
+
+
+private:
+    // makes sure that the result writer exists
+    void createResultWriter_()
+    { if (!resultWriter_) resultWriter_ = new VtkMultiWriter(gridView_, asImp_().name()); };
+
+    std::string simName_;
+    const GridView gridView_;
+
+    GlobalPosition bboxMin_;
+    GlobalPosition bboxMax_;
+
+    ElementMapper elementMapper_;
+    VertexMapper vertexMapper_;
+
+    TimeManager *timeManager_;
+
+    Model model_;
+
+    NewtonMethod newtonMethod_;
+    NewtonController newtonCtl_;
+
+    VtkMultiWriter *resultWriter_;
+};
+
+}
+
+#endif
diff --git a/dumux/implicit/cellcentered/ccproperties.hh b/dumux/implicit/cellcentered/ccproperties.hh
new file mode 100644
index 0000000000..7666f5d4c8
--- /dev/null
+++ b/dumux/implicit/cellcentered/ccproperties.hh
@@ -0,0 +1,142 @@
+// -*- mode: C++; tab-width: 4; indent-tabs-mode: nil; c-basic-offset: 4 -*-
+// vi: set et ts=4 sw=4 sts=4:
+/*****************************************************************************
+ *   Copyright (C) 2009 by Andreas Lauser                                    *
+ *   Copyright (C) 2008 by Bernd Flemisch                                    *
+ *   Institute for Modelling Hydraulic and Environmental Systems             *
+ *   University of Stuttgart, Germany                                        *
+ *   email: <givenname>.<name>@iws.uni-stuttgart.de                          *
+ *                                                                           *
+ *   This program is free software: you can redistribute it and/or modify    *
+ *   it under the terms of the GNU General Public License as published by    *
+ *   the Free Software Foundation, either version 2 of the License, or       *
+ *   (at your option) any later version.                                     *
+ *                                                                           *
+ *   This program is distributed in the hope that it will be useful,         *
+ *   but WITHOUT ANY WARRANTY; without even the implied warranty of          *
+ *   MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the           *
+ *   GNU General Public License for more details.                            *
+ *                                                                           *
+ *   You should have received a copy of the GNU General Public License       *
+ *   along with this program.  If not, see <http://www.gnu.org/licenses/>.   *
+ *****************************************************************************/
+#ifndef DUMUX_CC_PROPERTIES_HH
+#define DUMUX_CC_PROPERTIES_HH
+
+#include <dumux/common/propertysystem.hh>
+
+#include <dumux/common/basicproperties.hh>
+#include <dumux/linear/linearsolverproperties.hh>
+#include <dumux/nonlinear/newtonmethod.hh>
+
+/*!
+ * \ingroup Properties
+ * \ingroup CCProperties
+ * \ingroup CCModel
+ * \file
+ * \brief Specify the shape functions, operator assemblers, etc
+ *        used for the CCModel.
+ */
+namespace Dumux
+{
+
+namespace Properties
+{
+/*!
+ * \ingroup CCModel
+ */
+// \{
+
+//////////////////////////////////////////////////////////////////
+// Type tags
+//////////////////////////////////////////////////////////////////
+
+//! The type tag for models based on the box-scheme
+NEW_TYPE_TAG(CCModel, INHERITS_FROM(NewtonMethod, LinearSolverTypeTag, ImplicitModel));
+
+//////////////////////////////////////////////////////////////////
+// Property tags
+//////////////////////////////////////////////////////////////////
+
+NEW_PROP_TAG(Grid);     //!< The type of the DUNE grid
+NEW_PROP_TAG(GridView); //!< The type of the grid view
+
+NEW_PROP_TAG(FVElementGeometry); //! The type of the finite-volume geometry in the box scheme
+
+NEW_PROP_TAG(Problem); //!< The type of the problem
+NEW_PROP_TAG(BaseModel); //!< The type of the base class of the model
+NEW_PROP_TAG(Model); //!< The type of the model
+NEW_PROP_TAG(NumEq); //!< Number of equations in the system of PDEs
+NEW_PROP_TAG(BaseLocalResidual); //!< The type of the base class of the local residual
+NEW_PROP_TAG(LocalResidual); //!< The type of the local residual function
+NEW_PROP_TAG(LocalJacobian); //!< The type of the local jacobian operator
+
+NEW_PROP_TAG(JacobianAssembler); //!< Assembles the global jacobian matrix
+NEW_PROP_TAG(JacobianMatrix); //!< Type of the global jacobian matrix
+NEW_PROP_TAG(BoundaryTypes); //!< Stores the boundary types of a single degree of freedom
+NEW_PROP_TAG(ElementBoundaryTypes); //!< Stores the boundary types on an element
+
+NEW_PROP_TAG(PrimaryVariables); //!< A vector of primary variables within a sub-control volume
+NEW_PROP_TAG(SolutionVector); //!< Vector containing all primary variable vector of the grid
+NEW_PROP_TAG(ElementSolutionVector); //!< A vector of primary variables within a sub-control volume
+
+NEW_PROP_TAG(VolumeVariables);  //!< The secondary variables within a sub-control volume
+NEW_PROP_TAG(ElementVolumeVariables); //!< The secondary variables of all sub-control volumes in an element
+NEW_PROP_TAG(FluxVariables); //!< Data required to calculate a flux over a face
+NEW_PROP_TAG(BoundaryVariables); //!< Data required to calculate fluxes over boundary faces (outflow)
+
+// high level simulation control
+NEW_PROP_TAG(TimeManager);  //!< Manages the simulation time
+NEW_PROP_TAG(NewtonMethod);     //!< The type of the newton method
+NEW_PROP_TAG(NewtonController); //!< The type of the newton controller
+
+//! Specify whether the jacobian matrix of the last iteration of a
+//! time step should be re-used as the jacobian of the first iteration
+//! of the next time step.
+NEW_PROP_TAG(ImplicitEnableJacobianRecycling);
+
+//! Specify whether the jacobian matrix should be only reassembled for
+//! elements where at least one vertex is above the specified
+//! tolerance
+NEW_PROP_TAG(ImplicitEnablePartialReassemble);
+
+/*!
+ * \brief Specify the maximum size of a time integration [s].
+ *
+ * The default is to not limit the step size.
+ */
+NEW_PROP_TAG(TimeManagerMaxTimeStepSize);
+
+/*!
+ * \brief Specify which kind of method should be used to numerically
+ * calculate the partial derivatives of the residual.
+ *
+ * -1 means backward differences, 0 means central differences, 1 means
+ * forward differences. By default we use central differences.
+ */
+NEW_PROP_TAG(ImplicitNumericDifferenceMethod);
+
+/*!
+ * \brief Specify whether to use the already calculated solutions as
+ *        starting values of the volume variables.
+ *
+ * This only makes sense if the calculation of the volume variables is
+ * very expensive (e.g. for non-linear fugacity functions where the
+ * solver converges faster).
+ */
+NEW_PROP_TAG(ImplicitEnableHints);
+
+// mappers from local to global indices
+
+//! maper for vertices
+NEW_PROP_TAG(VertexMapper);
+//! maper for elements
+NEW_PROP_TAG(ElementMapper);
+//! maper for degrees of freedom
+NEW_PROP_TAG(DofMapper);
+}
+}
+
+// \}
+
+#endif
diff --git a/dumux/implicit/cellcentered/ccpropertydefaults.hh b/dumux/implicit/cellcentered/ccpropertydefaults.hh
new file mode 100644
index 0000000000..8affb6f501
--- /dev/null
+++ b/dumux/implicit/cellcentered/ccpropertydefaults.hh
@@ -0,0 +1,209 @@
+// -*- mode: C++; tab-width: 4; indent-tabs-mode: nil; c-basic-offset: 4 -*-
+// vi: set et ts=4 sw=4 sts=4:
+/*****************************************************************************
+ *   Copyright (C) 2008-2010 by Andreas Lauser                               *
+ *   Copyright (C) 2008-2010 by Bernd Flemisch                               *
+ *   Institute for Modelling Hydraulic and Environmental Systems             *
+ *   University of Stuttgart, Germany                                        *
+ *   email: <givenname>.<name>@iws.uni-stuttgart.de                          *
+ *                                                                           *
+ *   This program is free software: you can redistribute it and/or modify    *
+ *   it under the terms of the GNU General Public License as published by    *
+ *   the Free Software Foundation, either version 2 of the License, or       *
+ *   (at your option) any later version.                                     *
+ *                                                                           *
+ *   This program is distributed in the hope that it will be useful,         *
+ *   but WITHOUT ANY WARRANTY; without even the implied warranty of          *
+ *   MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the           *
+ *   GNU General Public License for more details.                            *
+ *                                                                           *
+ *   You should have received a copy of the GNU General Public License       *
+ *   along with this program.  If not, see <http://www.gnu.org/licenses/>.   *
+ *****************************************************************************/
+/*!
+ * \ingroup Properties
+ * \ingroup CCProperties
+ * \ingroup CCModel
+ * \file
+ *
+ * \brief Default properties for box models
+ */
+#ifndef DUMUX_CC_PROPERTY_DEFAULTS_HH
+#define DUMUX_CC_PROPERTY_DEFAULTS_HH
+
+#include <dumux/nonlinear/newtonmethod.hh>
+#include <dumux/nonlinear/newtoncontroller.hh>
+
+#include "ccassembler.hh"
+#include "ccmodel.hh"
+#include "ccfvelementgeometry.hh"
+#include "ccelementboundarytypes.hh"
+#include "cclocaljacobian.hh"
+#include "cclocalresidual.hh"
+#include "ccelementvolumevariables.hh"
+#include <dumux/boxmodels/common/boxvolumevariables.hh>
+
+#include <dumux/common/boundarytypes.hh>
+#include <dumux/common/timemanager.hh>
+
+#include "ccproperties.hh"
+
+#include <limits>
+
+namespace Dumux {
+
+// forward declaration
+template<class TypeTag>
+class CCModel;
+
+namespace Properties {
+//////////////////////////////////////////////////////////////////
+// Some defaults for very fundamental properties
+//////////////////////////////////////////////////////////////////
+
+//! Set the default type for the time manager
+SET_TYPE_PROP(CCModel, TimeManager, Dumux::TimeManager<TypeTag>);
+
+//////////////////////////////////////////////////////////////////
+// Properties
+//////////////////////////////////////////////////////////////////
+
+//! Use the leaf grid view if not defined otherwise
+SET_TYPE_PROP(CCModel,
+              GridView,
+              typename GET_PROP_TYPE(TypeTag, Grid)::LeafGridView);
+
+//! Set the default for the FVElementGeometry
+SET_TYPE_PROP(CCModel, FVElementGeometry, Dumux::CCFVElementGeometry<TypeTag>);
+
+//! Set the default for the ElementBoundaryTypes
+SET_TYPE_PROP(CCModel, ElementBoundaryTypes, Dumux::CCElementBoundaryTypes<TypeTag>);
+
+//! use the plain newton method for the box scheme by default
+SET_TYPE_PROP(CCModel, NewtonMethod, Dumux::NewtonMethod<TypeTag>);
+
+//! use the plain newton controller for the box scheme by default
+SET_TYPE_PROP(CCModel, NewtonController, Dumux::NewtonController<TypeTag>);
+
+//! Mapper for the grid view's vertices.
+SET_TYPE_PROP(CCModel,
+              VertexMapper,
+              Dune::MultipleCodimMultipleGeomTypeMapper<typename GET_PROP_TYPE(TypeTag, GridView),
+                                                        Dune::MCMGVertexLayout>);
+
+//! Mapper for the grid view's elements.
+SET_TYPE_PROP(CCModel,
+              ElementMapper,
+              Dune::MultipleCodimMultipleGeomTypeMapper<typename GET_PROP_TYPE(TypeTag, GridView),
+                                                        Dune::MCMGElementLayout>);
+
+//! Mapper for the degrees of freedoms.
+SET_TYPE_PROP(CCModel, DofMapper, typename GET_PROP_TYPE(TypeTag, ElementMapper));
+
+//! Set the BaseLocalResidual to CCLocalResidual
+SET_TYPE_PROP(CCModel, BaseLocalResidual, Dumux::CCLocalResidual<TypeTag>);
+
+//! Set the BaseModel to CCModel
+SET_TYPE_PROP(CCModel, BaseModel, Dumux::CCModel<TypeTag>);
+
+//! The local jacobian operator for the box scheme
+SET_TYPE_PROP(CCModel, LocalJacobian, Dumux::CCLocalJacobian<TypeTag>);
+
+/*!
+ * \brief The type of a solution for the whole grid at a fixed time.
+ */
+SET_TYPE_PROP(CCModel,
+              SolutionVector,
+              Dune::BlockVector<typename GET_PROP_TYPE(TypeTag, PrimaryVariables)>);
+
+/*!
+ * \brief The type of a solution for a whole element.
+ */
+SET_TYPE_PROP(CCModel,
+              ElementSolutionVector,
+              Dune::BlockVector<typename GET_PROP_TYPE(TypeTag, PrimaryVariables)>);
+
+/*!
+ * \brief A vector of primary variables.
+ */
+SET_TYPE_PROP(CCModel,
+              PrimaryVariables,
+              Dune::FieldVector<typename GET_PROP_TYPE(TypeTag, Scalar),
+                                GET_PROP_VALUE(TypeTag, NumEq)>);
+
+/*!
+ * \brief The volume variable class.
+ *
+ * This should almost certainly be overloaded by the model...
+ */
+SET_TYPE_PROP(CCModel, VolumeVariables, Dumux::BoxVolumeVariables<TypeTag>);
+
+/*!
+ * \brief An array of secondary variable containers.
+ */
+SET_TYPE_PROP(CCModel, ElementVolumeVariables, Dumux::CCElementVolumeVariables<TypeTag>);
+
+/*!
+ * \brief Boundary types at a single degree of freedom.
+ */
+SET_TYPE_PROP(CCModel,
+              BoundaryTypes,
+              Dumux::BoundaryTypes<GET_PROP_VALUE(TypeTag, NumEq)>);
+
+/*!
+ * \brief Assembler for the global jacobian matrix.
+ */
+SET_TYPE_PROP(CCModel, JacobianAssembler, Dumux::CCAssembler<TypeTag>);
+
+//! use an unlimited time step size by default
+#if 0
+// requires GCC 4.6 and above to call the constexpr function of
+// numeric_limits
+SET_SCALAR_PROP(CCModel, TimeManagerMaxTimeStepSize, std::numeric_limits<Scalar>::infinity());
+#else
+SET_SCALAR_PROP(CCModel, TimeManagerMaxTimeStepSize, 1e100);
+#endif
+
+//! use forward differences to calculate the jacobian by default
+SET_INT_PROP(CCModel, ImplicitNumericDifferenceMethod, +1);
+
+//! do not use hints by default
+SET_BOOL_PROP(CCModel, ImplicitEnableHints, false);
+
+// disable jacobian matrix recycling by default
+SET_BOOL_PROP(CCModel, ImplicitEnableJacobianRecycling, false);
+
+// disable partial reassembling by default
+SET_BOOL_PROP(CCModel, ImplicitEnablePartialReassemble, false);
+
+//! Set the type of a global jacobian matrix from the solution types
+SET_PROP(CCModel, JacobianMatrix)
+{
+private:
+    typedef typename GET_PROP_TYPE(TypeTag, Scalar) Scalar;
+    enum { numEq = GET_PROP_VALUE(TypeTag, NumEq) };
+    typedef typename Dune::FieldMatrix<Scalar, numEq, numEq> MatrixBlock;
+public:
+    typedef typename Dune::BCRSMatrix<MatrixBlock> type;
+};
+
+// use the stabilized BiCG solver preconditioned by the ILU-0 by default
+SET_TYPE_PROP(CCModel, LinearSolver, Dumux::BoxBiCGStabILU0Solver<TypeTag> );
+
+// if the deflection of the newton method is large, we do not
+// need to solve the linear approximation accurately. Assuming
+// that the initial value for the delta vector u is quite
+// close to the final value, a reduction of 6 orders of
+// magnitude in the defect should be sufficient...
+SET_SCALAR_PROP(CCModel, LinearSolverResidualReduction, 1e-6);
+
+//! set the default number of maximum iterations for the linear solver
+SET_INT_PROP(CCModel, LinearSolverMaxIterations, 250);
+
+//! set number of equations of the mathematical model as default
+SET_INT_PROP(CCModel, LinearSolverBlockSize, GET_PROP_VALUE(TypeTag, NumEq));
+
+} // namespace Properties
+} // namespace Dumux
+
+#endif
diff --git a/dumux/implicit/cellcentered/porousmediaccproblem.hh b/dumux/implicit/cellcentered/porousmediaccproblem.hh
new file mode 100644
index 0000000000..91dcd6352d
--- /dev/null
+++ b/dumux/implicit/cellcentered/porousmediaccproblem.hh
@@ -0,0 +1,192 @@
+// -*- mode: C++; tab-width: 4; indent-tabs-mode: nil; c-basic-offset: 4 -*-
+// vi: set et ts=4 sw=4 sts=4:
+/*****************************************************************************
+ *   Copyright (C) 2009 by Andreas Lauser                                    *
+ *   Institute for Modelling Hydraulic and Environmental Systems             *
+ *   University of Stuttgart, Germany                                        *
+ *   email: <givenname>.<name>@iws.uni-stuttgart.de                          *
+ *                                                                           *
+ *   This program is free software: you can redistribute it and/or modify    *
+ *   it under the terms of the GNU General Public License as published by    *
+ *   the Free Software Foundation, either version 2 of the License, or       *
+ *   (at your option) any later version.                                     *
+ *                                                                           *
+ *   This program is distributed in the hope that it will be useful,         *
+ *   but WITHOUT ANY WARRANTY; without even the implied warranty of          *
+ *   MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the           *
+ *   GNU General Public License for more details.                            *
+ *                                                                           *
+ *   You should have received a copy of the GNU General Public License       *
+ *   along with this program.  If not, see <http://www.gnu.org/licenses/>.   *
+ *****************************************************************************/
+/*!
+ * \file
+ * \brief Base class for all problems which use the two-phase box model
+ */
+#ifndef DUMUX_POROUS_MEDIA_CC_ROBLEM_HH
+#define DUMUX_POROUS_MEDIA_CC_PROBLEM_HH
+
+#include <dumux/ccmodels/common/ccproblem.hh>
+#include "ccproperties.hh"
+
+namespace Dumux
+{
+/*!
+ * \ingroup CCBaseProblems
+ * \brief Base class for all fully implicit cell centered porous media problems
+ */
+template<class TypeTag>
+class PorousMediaCCProblem : public CCProblem<TypeTag>
+{
+    typedef CCProblem<TypeTag> ParentType;
+
+    typedef typename GET_PROP_TYPE(TypeTag, Problem) Implementation;
+    typedef typename GET_PROP_TYPE(TypeTag, TimeManager) TimeManager;
+    typedef typename GET_PROP_TYPE(TypeTag, FVElementGeometry) FVElementGeometry;
+    typedef typename GET_PROP_TYPE(TypeTag, SpatialParams) SpatialParams;
+
+    typedef typename GET_PROP_TYPE(TypeTag, GridView) GridView;
+    typedef typename GridView::template Codim<0>::Entity Element;
+    enum {
+        dim = GridView::dimension,
+        dimWorld = GridView::dimensionworld
+    };
+
+    typedef typename GridView::ctype CoordScalar;
+    typedef Dune::FieldVector<CoordScalar, dimWorld> GlobalPosition;
+    typedef typename GET_PROP_TYPE(TypeTag, Scalar) Scalar;
+    typedef Dune::FieldVector<Scalar, dim> Vector;
+
+public:
+    /*!
+     * \brief The constructor
+     *
+     * \param timeManager The time manager
+     * \param gridView The grid view
+     * \param verbose Turn verbosity on or off
+     */
+    PorousMediaCCProblem(TimeManager &timeManager,
+                const GridView &gridView,
+                bool verbose = true)
+        : ParentType(timeManager, gridView),
+          gravity_(0)
+    {
+        newSpatialParams_ = true;
+        spatialParams_ = new SpatialParams(gridView);
+
+        if (GET_PARAM_FROM_GROUP(TypeTag, bool, Problem, EnableGravity))
+            gravity_[dim-1]  = -9.81;
+    }
+
+    ~PorousMediaCCProblem()
+    {
+        if (newSpatialParams_)
+            delete spatialParams_;
+    }
+
+    /*!
+     * \name Problem parameters
+     */
+    // \{
+
+    /*!
+     * \brief Returns the temperature \f$\mathrm{[K]}\f$ within a control volume.
+     *
+     * This is the discretization specific interface for the box
+     * method. By default it just calls temperature(pos).
+     *
+     * \param element The DUNE Codim<0> enitiy which intersects with
+     *                the finite volume.
+     * \param fvGeom The finite volume geometry of the element.
+     * \param scvIdx The local index of the sub control volume inside the element
+     */
+    Scalar boxTemperature(const Element &element,
+                          const FVElementGeometry fvGeom,
+                          int scvIdx) const
+    { return asImp_().temperatureAtPos(fvGeom.neighbors[scvIdx]->geometry().center()); }
+
+    /*!
+     * \brief Returns the temperature \f$\mathrm{[K]}\f$ at a given global position.
+     *
+     * This is not specific to the discretization. By default it just
+     * calls temperature().
+     *
+     * \param pos The position in global coordinates where the temperature should be specified.
+     */
+    Scalar temperatureAtPos(const GlobalPosition &pos) const
+    { return asImp_().temperature(); }
+
+    /*!
+     * \brief Returns the temperature \f$\mathrm{[K]}\f$ for an isothermal problem.
+     *
+     * This is not specific to the discretization. By default it just
+     * throws an exception so it must be overloaded by the problem if
+     * no energy equation is used.
+     */
+    Scalar temperature() const
+    { DUNE_THROW(Dune::NotImplemented, "temperature() method not implemented by the actual problem"); };
+
+    /*!
+     * \brief Returns the acceleration due to gravity \f$\mathrm{[m/s^2]}\f$.
+     *
+     * This is the box discretization specific interface. By default
+     * it just calls gravityAtPos().
+     */
+    const Vector &boxGravity(const Element &element,
+                                     const FVElementGeometry &fvGeom,
+                                     int scvIdx) const
+    { return asImp_().gravityAtPos(fvGeom.neighbors[scvIdx]->geometry().center()); }
+
+    /*!
+     * \brief Returns the acceleration due to gravity \f$\mathrm{[m/s^2]}\f$.
+     *
+     * This is discretization independent interface. By default it
+     * just calls gravity().
+     */
+    const Vector &gravityAtPos(const GlobalPosition &pos) const
+    { return asImp_().gravity(); }
+
+    /*!
+     * \brief Returns the acceleration due to gravity \f$\mathrm{[m/s^2]}\f$.
+     *
+     * This method is used for problems where the gravitational
+     * acceleration does not depend on the spatial position. The
+     * default behaviour is that if the <tt>ProblemEnableGravity</tt>
+     * property is true, \f$\boldsymbol{g} = ( 0,\dots,\ -9.81)^T \f$ holds,
+     * else \f$\boldsymbol{g} = ( 0,\dots, 0)^T \f$.
+     */
+    const Vector &gravity() const
+    { return gravity_; }
+
+    /*!
+     * \brief Returns the spatial parameters object.
+     */
+    SpatialParams &spatialParams()
+    { return *spatialParams_; }
+
+    /*!
+     * \brief Returns the spatial parameters object.
+     */
+    const SpatialParams &spatialParams() const
+    { return *spatialParams_; }
+
+    // \}
+
+private:
+    //! Returns the implementation of the problem (i.e. static polymorphism)
+    Implementation &asImp_()
+    { return *static_cast<Implementation *>(this); }
+    //! \copydoc asImp_()
+    const Implementation &asImp_() const
+    { return *static_cast<const Implementation *>(this); }
+
+    Vector gravity_;
+
+    // fluids and material properties
+    SpatialParams*  spatialParams_;
+    bool newSpatialParams_;
+};
+
+}
+
+#endif
diff --git a/dumux/implicit/co2/Makefile.am b/dumux/implicit/co2/Makefile.am
new file mode 100644
index 0000000000..52b76eb57e
--- /dev/null
+++ b/dumux/implicit/co2/Makefile.am
@@ -0,0 +1,4 @@
+co2dir = $(includedir)/dumux/boxmodels/co2
+co2_HEADERS = *.hh
+
+include $(top_srcdir)/am/global-rules
diff --git a/dumux/implicit/co2/co2model.hh b/dumux/implicit/co2/co2model.hh
new file mode 100644
index 0000000000..fcf6360603
--- /dev/null
+++ b/dumux/implicit/co2/co2model.hh
@@ -0,0 +1,283 @@
+// -*- mode: C++; tab-width: 4; indent-tabs-mode: nil; c-basic-offset: 4 -*-
+// vi: set et ts=4 sw=4 sts=4:
+/*****************************************************************************
+ *   Copyright (C) 2012 by                                                   *
+ *   Institute for Modelling Hydraulic and Environmental Systems             *
+ *   University of Stuttgart, Germany                                        *
+ *   email: <givenname>.<name>@iws.uni-stuttgart.de                          *
+ *                                                                           *
+ *   This program is free software: you can redistribute it and/or modify    *
+ *   it under the terms of the GNU General Public License as published by    *
+ *   the Free Software Foundation, either version 2 of the License, or       *
+ *   (at your option) any later version.                                     *
+ *                                                                           *
+ *   This program is distributed in the hope that it will be useful,         *
+ *   but WITHOUT ANY WARRANTY; without even the implied warranty of          *
+ *   MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the           *
+ *   GNU General Public License for more details.                            *
+ *                                                                           *
+ *   You should have received a copy of the GNU General Public License       *
+ *   along with this program.  If not, see <http://www.gnu.org/licenses/>.   *
+ *****************************************************************************/
+/*!
+ * \file
+ *
+ * \brief Adaption of the BOX scheme to the two-phase two-component flow model without constraint solver.
+ */
+#ifndef DUMUX_CO2_MODEL_HH
+#define DUMUX_CO2_MODEL_HH
+
+#include <dumux/boxmodels/2p2c/2p2cmodel.hh>
+
+namespace Dumux
+{
+/*!
+ * \ingroup CO2Model
+ * \brief Adaption of the BOX scheme to the non-isothermal two-phase two-component flow model.
+ *   See TwoPTwoCModel for reference to the equations used.
+ *   The CO2 model is derived from the 2p2c model. In the CO2 model the phase switch criterion
+ *   is different from the 2p2c model.
+ *   The phase switch occurs when the equilibrium concentration
+ *   of a component in a phase is exceeded, instead of the sum of the components in the virtual phase
+ *   (the phase which is not present) being greater that unity as done in the 2p2c model.
+ *   The CO2VolumeVariables do not use a constraint solver for calculating the mole fractions as is the
+ *   case in the 2p2c model. Instead mole fractions are calculated in the FluidSystem with a given
+ *   temperature, pressurem and salinity.
+ *
+ */
+
+template<class TypeTag>
+class CO2Model: public TwoPTwoCModel<TypeTag>
+{
+
+
+    typedef TwoPTwoCModel<TypeTag> ParentType;
+    typedef typename GET_PROP_TYPE(TypeTag, BaseModel) BaseType;
+
+     typedef typename GET_PROP_TYPE(TypeTag, Problem) Problem;
+     typedef typename GET_PROP_TYPE(TypeTag, FluidSystem) FluidSystem;
+     typedef typename GET_PROP_TYPE(TypeTag, FVElementGeometry) FVElementGeometry;
+     typedef typename GET_PROP_TYPE(TypeTag, PrimaryVariables) PrimaryVariables;
+     typedef typename GET_PROP_TYPE(TypeTag, VolumeVariables) VolumeVariables;
+     typedef typename GET_PROP_TYPE(TypeTag, ElementVolumeVariables) ElementVolumeVariables;
+     typedef typename GET_PROP_TYPE(TypeTag, FluxVariables) FluxVariables;
+     typedef typename GET_PROP_TYPE(TypeTag, SolutionVector) SolutionVector;
+     enum {
+         numPhases = GET_PROP_VALUE(TypeTag, NumPhases),
+         numComponents = GET_PROP_VALUE(TypeTag, NumComponents)
+     };
+
+     typedef typename GET_PROP_TYPE(TypeTag, Indices) Indices;
+     enum {
+         pressureIdx = Indices::pressureIdx,
+         switchIdx = Indices::switchIdx,
+
+         wPhaseIdx = Indices::wPhaseIdx,
+         nPhaseIdx = Indices::nPhaseIdx,
+         wCompIdx = Indices::wCompIdx,
+         nCompIdx = Indices::nCompIdx,
+
+         wPhaseOnly = Indices::wPhaseOnly,
+         nPhaseOnly = Indices::nPhaseOnly,
+         bothPhases = Indices::bothPhases,
+
+         pwSn = TwoPTwoCFormulation::pwSn,
+         pnSw = TwoPTwoCFormulation::pnSw,
+         formulation = GET_PROP_VALUE(TypeTag, Formulation)
+     };
+
+     typedef typename GET_PROP_TYPE(TypeTag, GridView) GridView;
+     typedef typename GridView::ctype CoordScalar;
+     typedef typename GridView::template Codim<0>::Entity Element;
+     typedef typename GridView::template Codim<0>::Iterator ElementIterator;
+     enum {
+         dim = GridView::dimension,
+         dimWorld = GridView::dimensionworld
+     };
+     typedef typename GridView::template Codim<dim>::Entity Vertex;
+     typedef typename GridView::template Codim<dim>::Iterator VertexIterator;
+
+     typedef typename GET_PROP_TYPE(TypeTag, Scalar) Scalar;
+     typedef Dune::FieldVector<Scalar, numPhases> PhasesVector;
+     typedef Dune::FieldVector<Scalar, dimWorld> GlobalPosition;
+
+ public:
+
+
+     /*!
+      * \brief Update the static data of all vertices in the grid.
+      *
+      * \param curGlobalSol The current global solution
+      * \param oldGlobalSol The previous global solution
+      */
+     void updateStaticData(SolutionVector &curGlobalSol,
+                           const SolutionVector &oldGlobalSol)
+     {
+         bool wasSwitched = false;
+
+         for (unsigned i = 0; i < ParentType::staticVertexDat_.size(); ++i)
+             ParentType::staticVertexDat_[i].visited = false;
+
+         unsigned numDofs = this->numDofs();
+         unsigned numVertices = this->problem_().gridView().size(dim);
+
+         FVElementGeometry fvGeometry;
+         static VolumeVariables volVars;
+         ElementIterator eIt = this->gridView_().template begin<0> ();
+         const ElementIterator &eEndIt = this->gridView_().template end<0> ();
+         for (; eIt != eEndIt; ++eIt)
+         {
+             fvGeometry.update(this->gridView_(), *eIt);
+             for (int scvIdx = 0; scvIdx < fvGeometry.numSCV; ++scvIdx)
+             {
+                 int globalIdx;
+
+                 if (numDofs != numVertices)
+                     globalIdx = this->elementMapper().map(*eIt);
+                 else
+                     globalIdx = this->vertexMapper().map(*eIt, scvIdx, dim);
+
+                 if (ParentType::staticVertexDat_[globalIdx].visited)
+                     continue;
+
+                 ParentType::staticVertexDat_[globalIdx].visited = true;
+                 volVars.update(curGlobalSol[globalIdx],
+                                this->problem_(),
+                                *eIt,
+                                fvGeometry,
+                                scvIdx,
+                                false);
+                 const GlobalPosition &globalPos = eIt->geometry().corner(scvIdx);
+                 if (primaryVarSwitch_(curGlobalSol,
+                                       volVars,
+                                       globalIdx,
+                                       globalPos))
+                 {
+                     this->jacobianAssembler().markVertexRed(globalIdx);
+                     wasSwitched = true;
+                 }
+             }
+         }
+
+         // make sure that if there was a variable switch in an
+         // other partition we will also set the switch flag
+         // for our partition.
+         if (this->gridView_().comm().size() > 1)
+             wasSwitched = this->gridView_().comm().max(wasSwitched);
+
+         ParentType::setSwitched_(wasSwitched);
+     }
+
+ protected:
+
+
+     /*!
+      * \brief Set the old phase of all verts state to the current one.
+      */
+     bool primaryVarSwitch_(SolutionVector &globalSol,
+                              const VolumeVariables &volVars, int globalIdx,
+                              const GlobalPosition &globalPos)
+       {
+         typename FluidSystem::ParameterCache paramCache;
+           // evaluate primary variable switch
+           bool wouldSwitch = false;
+           int phasePresence = ParentType::staticVertexDat_[globalIdx].phasePresence;
+           int newPhasePresence = phasePresence;
+
+           // check if a primary var switch is necessary
+           if (phasePresence == nPhaseOnly)
+           {
+
+               Scalar xnw = volVars.fluidState().moleFraction(nPhaseIdx, wCompIdx);
+               Scalar xnwMax = FluidSystem::equilibriumMoleFraction(volVars.fluidState(), paramCache, nPhaseIdx);
+
+               if(xnw > xnwMax)
+                   wouldSwitch = true;
+
+               if (ParentType::staticVertexDat_[globalIdx].wasSwitched)
+                   xnwMax *= 1.02;
+
+               //If mole fraction is higher than the equilibrium mole fraction make a phase switch
+               if(xnw > xnwMax)
+               {
+                   // wetting phase appears
+                   std::cout << "wetting phase appears at vertex " << globalIdx
+                             << ", coordinates: " << globalPos << ", xnw > xnwMax: "
+                             << xnw << " > "<< xnwMax << std::endl;
+                   newPhasePresence = bothPhases;
+                   if (formulation == pnSw)
+                       globalSol[globalIdx][switchIdx] = 0.0;
+                   else if (formulation == pwSn)
+                       globalSol[globalIdx][switchIdx] = 1.0;
+               }
+           }
+           else if (phasePresence == wPhaseOnly)
+           {
+
+               Scalar xwn = volVars.fluidState().moleFraction(wPhaseIdx, nCompIdx);
+               Scalar xwnMax = FluidSystem::equilibriumMoleFraction(volVars.fluidState(), paramCache, wPhaseIdx);
+
+               //If mole fraction is higher than the equilibrium mole fraction make a phase switch
+               if(xwn > xwnMax)
+                   wouldSwitch = true;
+               if (ParentType::staticVertexDat_[globalIdx].wasSwitched)
+                   xwnMax *= 1.02;
+
+
+               if(xwn > xwnMax)
+               {
+                   // non-wetting phase appears
+                   std::cout << "non-wetting phase appears at vertex " << globalIdx
+                             << ", coordinates: " << globalPos << ", xwn > xwnMax: "
+                             << xwn << " > "<< xwnMax << std::endl;
+
+                   newPhasePresence = bothPhases;
+                   if (formulation == pnSw)
+                       globalSol[globalIdx][switchIdx] = 0.999;
+                   else if (formulation == pwSn)
+                       globalSol[globalIdx][switchIdx] = 0.001;
+               }
+           }
+           else if (phasePresence == bothPhases)
+           {
+               Scalar Smin = 0.0;
+               if (ParentType::staticVertexDat_[globalIdx].wasSwitched)
+                   Smin = -0.01;
+
+               if (volVars.saturation(nPhaseIdx) <= Smin)
+               {
+                   wouldSwitch = true;
+                   // nonwetting phase disappears
+                   std::cout << "Nonwetting phase disappears at vertex " << globalIdx
+                             << ", coordinates: " << globalPos << ", Sn: "
+                             << volVars.saturation(nPhaseIdx) << std::endl;
+                   newPhasePresence = wPhaseOnly;
+
+                   globalSol[globalIdx][switchIdx]
+                       = volVars.fluidState().massFraction(wPhaseIdx, nCompIdx);
+               }
+               else if (volVars.saturation(wPhaseIdx) <= Smin)
+               {
+                   wouldSwitch = true;
+                   // wetting phase disappears
+                   std::cout << "Wetting phase disappears at vertex " << globalIdx
+                             << ", coordinates: " << globalPos << ", Sw: "
+                             << volVars.saturation(wPhaseIdx) << std::endl;
+                   newPhasePresence = nPhaseOnly;
+
+                   globalSol[globalIdx][switchIdx]
+                       = volVars.fluidState().massFraction(nPhaseIdx, wCompIdx);
+               }
+           }
+
+           ParentType::staticVertexDat_[globalIdx].phasePresence = newPhasePresence;
+           ParentType::staticVertexDat_[globalIdx].wasSwitched = wouldSwitch;
+           return phasePresence != newPhasePresence;
+       }
+
+
+};
+
+}
+
+#endif
diff --git a/dumux/implicit/co2/co2volumevariables.hh b/dumux/implicit/co2/co2volumevariables.hh
new file mode 100644
index 0000000000..0d0e41b3a1
--- /dev/null
+++ b/dumux/implicit/co2/co2volumevariables.hh
@@ -0,0 +1,404 @@
+// -*- mode: C++; tab-width: 4; indent-tabs-mode: nil; c-basic-offset: 4 -*-
+// vi: set et ts=4 sw=4 sts=4:
+/*****************************************************************************
+ *   Copyright (C) 2012 by                                                   *
+ *   Institute for Modelling Hydraulic and Environmental Systems             *
+ *   University of Stuttgart, Germany                                        *
+ *   email: <givenname>.<name>@iws.uni-stuttgart.de                          *
+ *                                                                           *
+ *   This program is free software: you can redistribute it and/or modify    *
+ *   it under the terms of the GNU General Public License as published by    *
+ *   the Free Software Foundation, either version 2 of the License, or       *
+ *   (at your option) any later version.                                     *
+ *                                                                           *
+ *   This program is distributed in the hope that it will be useful,         *
+ *   but WITHOUT ANY WARRANTY; without even the implied warranty of          *
+ *   MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the           *
+ *   GNU General Public License for more details.                            *
+ *                                                                           *
+ *   You should have received a copy of the GNU General Public License       *
+ *   along with this program.  If not, see <http://www.gnu.org/licenses/>.   *
+ *****************************************************************************/
+#ifndef DUMUX_CO2_VOLUME_VARIABLES_HH
+#define DUMUX_CO2_VOLUME_VARIABLES_HH
+
+#include <dumux/boxmodels/2p2c/2p2cvolumevariables.hh>
+
+namespace Dumux
+{
+/*!
+ * \ingroup CO2Model
+ * \ingroup BoxVolumeVariables
+ * \brief Contains the quantities which are are constant within a
+ *        finite volume in the non-isothermal two-phase, two-component
+ *        model.
+ */
+template <class TypeTag>
+class CO2VolumeVariables: public TwoPTwoCVolumeVariables<TypeTag>
+{
+    typedef TwoPTwoCVolumeVariables<TypeTag> ParentType;
+    typedef BoxVolumeVariables<TypeTag> BaseClassType;
+
+    typedef typename GET_PROP_TYPE(TypeTag, VolumeVariables) Implementation;
+
+    typedef typename GET_PROP_TYPE(TypeTag, Scalar) Scalar;
+//    typedef typename GET_PROP_TYPE(TypeTag, GridView) GridView;
+    typedef typename GET_PROP_TYPE(TypeTag, Problem) Problem;
+    typedef typename GET_PROP_TYPE(TypeTag, FVElementGeometry) FVElementGeometry;
+    typedef typename GET_PROP_TYPE(TypeTag, PrimaryVariables) PrimaryVariables;
+    typedef typename GET_PROP_TYPE(TypeTag, FluidSystem) FluidSystem;
+    typedef typename GET_PROP_TYPE(TypeTag, MaterialLaw) MaterialLaw;
+    typedef typename GET_PROP_TYPE(TypeTag, MaterialLawParams) MaterialLawParams;
+
+    typedef typename GET_PROP_TYPE(TypeTag, Indices) Indices;
+
+    enum {
+        numPhases = GET_PROP_VALUE(TypeTag, NumPhases),
+        numComponents = GET_PROP_VALUE(TypeTag, NumComponents)
+    };
+
+    enum {
+        wCompIdx = Indices::wCompIdx,
+        nCompIdx = Indices::nCompIdx,
+        wPhaseIdx = Indices::wPhaseIdx,
+        nPhaseIdx = Indices::nPhaseIdx
+    };
+
+    // present phases
+    enum {
+        wPhaseOnly = Indices::wPhaseOnly,
+        nPhaseOnly = Indices::nPhaseOnly,
+        bothPhases = Indices::bothPhases
+    };
+
+    // formulations
+    enum {
+        formulation = GET_PROP_VALUE(TypeTag, Formulation),
+        pwSn = TwoPTwoCFormulation::pwSn,
+        pnSw = TwoPTwoCFormulation::pnSw
+    };
+
+    // primary variable indices
+    enum {
+        switchIdx = Indices::switchIdx,
+        pressureIdx = Indices::pressureIdx
+    };
+
+    typedef typename GET_PROP_TYPE(TypeTag, GridView) GridView;
+    typedef typename GridView::template Codim<0>::Entity Element;
+    enum { dim = GridView::dimension};
+
+    static const Scalar R; // universial nonwetting constant
+
+public:
+    //! The type of the object returned by the fluidState() method
+    typedef Dumux::CompositionalFluidState<Scalar, FluidSystem> FluidState;
+
+
+    /*!
+     * \brief Update all quantities for a given control volume.
+     *
+     * \param priVars The primary variables
+     * \param problem The problem
+     * \param element The element
+     * \param fvGeometry The finite-volume geometry in the box scheme
+     * \param scvIdx The local index of the SCV (sub-control volume)
+     * \param isOldSol Evaluate function with solution of current or previous time step
+     */
+    void update(const PrimaryVariables &priVars,
+                const Problem &problem,
+                const Element &element,
+                const FVElementGeometry &fvGeometry,
+                const int scvIdx,
+                const bool isOldSol)
+    {
+    	// Update BoxVolVars but not 2p2cvolvars
+        // ToDo: Is BaseClassType the right name?
+        BaseClassType::update(priVars,
+                problem,
+                element,
+                fvGeometry,
+                scvIdx,
+                isOldSol);
+
+        unsigned numDofs = problem.model().numDofs();
+        unsigned numVertices = problem.gridView().size(dim);
+
+        int globalIdx;
+        if (numDofs != numVertices) // element data
+            globalIdx = problem.model().dofMapper().map(element);
+        else
+            globalIdx = problem.model().dofMapper().map(element, scvIdx, dim);
+
+        int phasePresence = problem.model().phasePresence(globalIdx, isOldSol);
+
+         Scalar temp = Implementation::temperature_(priVars, problem, element, fvGeometry, scvIdx);
+         ParentType::fluidState_.setTemperature(temp);
+
+         /////////////
+         // set the saturations
+         /////////////
+         Scalar Sn;
+         if (phasePresence == nPhaseOnly)
+             Sn = 1.0;
+         else if (phasePresence == wPhaseOnly) {
+             Sn = 0.0;
+         }
+         else if (phasePresence == bothPhases) {
+             if (formulation == pwSn)
+                 Sn = priVars[switchIdx];
+             else if (formulation == pnSw)
+                 Sn = 1.0 - priVars[switchIdx];
+             else DUNE_THROW(Dune::InvalidStateException, "Formulation: " << formulation << " is invalid.");
+         }
+         else DUNE_THROW(Dune::InvalidStateException, "phasePresence: " << phasePresence << " is invalid.");
+         ParentType::fluidState_.setSaturation(wPhaseIdx, 1 - Sn);
+         ParentType::fluidState_.setSaturation(nPhaseIdx, Sn);
+
+         // capillary pressure parameters
+          const MaterialLawParams &materialParams =
+              problem.spatialParams().materialLawParams(element, fvGeometry, scvIdx);
+
+
+          Scalar pC = MaterialLaw::pC(materialParams, 1 - Sn);
+
+          if (formulation == pwSn) {
+              ParentType::fluidState_.setPressure(wPhaseIdx, priVars[pressureIdx]);
+              ParentType::fluidState_.setPressure(nPhaseIdx, priVars[pressureIdx] + pC);
+          }
+          else if (formulation == pnSw) {
+              ParentType::fluidState_.setPressure(nPhaseIdx, priVars[pressureIdx]);
+              ParentType::fluidState_.setPressure(wPhaseIdx, priVars[pressureIdx] - pC);
+          }
+          else DUNE_THROW(Dune::InvalidStateException, "Formulation: " << formulation << " is invalid.");
+
+          /////////////
+          // calculate the phase compositions
+          /////////////
+          typename FluidSystem::ParameterCache paramCache;
+
+
+          // calculate phase composition
+          if (phasePresence == bothPhases) {
+
+              //Get the equilibrium mole fractions from the FluidSystem and set them in the fluidState
+              //xCO2 = equilibrium mole fraction of CO2 in the liquid phase
+              //yH2O = equilibrium mole fraction of H2O in the gas phase
+
+              Scalar xwCO2 = FluidSystem::equilibriumMoleFraction(ParentType::fluidState_, paramCache, wPhaseIdx);
+              Scalar xgH2O = FluidSystem::equilibriumMoleFraction(ParentType::fluidState_, paramCache, nPhaseIdx);
+              Scalar xwH2O = 1 - xwCO2;
+              Scalar xgCO2 = 1 - xgH2O;
+
+              ParentType::fluidState_.setMoleFraction(wPhaseIdx, wCompIdx, xwH2O);
+              ParentType::fluidState_.setMoleFraction(wPhaseIdx, nCompIdx, xwCO2);
+              ParentType::fluidState_.setMoleFraction(nPhaseIdx, wCompIdx, xgH2O);
+              ParentType::fluidState_.setMoleFraction(nPhaseIdx, nCompIdx, xgCO2);
+
+
+              //Get the phase densities from the FluidSystem and set them in the fluidState
+
+              Scalar rhoW = FluidSystem::density(ParentType::fluidState_, paramCache, wPhaseIdx);
+              Scalar rhoN = FluidSystem::density(ParentType::fluidState_, paramCache, nPhaseIdx);
+
+              ParentType::fluidState_.setDensity(wPhaseIdx, rhoW);
+              ParentType::fluidState_.setDensity(nPhaseIdx, rhoN);
+
+
+              //Get the phase viscosities from the FluidSystem and set them in the fluidState
+
+              Scalar muW = FluidSystem::viscosity(ParentType::fluidState_, paramCache, wPhaseIdx);
+              Scalar muN = FluidSystem::viscosity(ParentType::fluidState_, paramCache, nPhaseIdx);
+
+              ParentType::fluidState_.setViscosity(wPhaseIdx, muW);
+              ParentType::fluidState_.setViscosity(nPhaseIdx, muN);
+
+          }
+          else if (phasePresence == nPhaseOnly) {
+              // only the nonwetting phase is present, i.e. nonwetting phase
+              // composition is stored explicitly.
+
+              // extract _mass_ fractions in the nonwetting phase
+              Scalar massFractionN[numComponents];
+              massFractionN[wCompIdx] = priVars[switchIdx];
+              massFractionN[nCompIdx] = 1 - massFractionN[wCompIdx];
+
+              // calculate average molar mass of the nonwetting phase
+              Scalar M1 = FluidSystem::molarMass(wCompIdx);
+              Scalar M2 = FluidSystem::molarMass(nCompIdx);
+              Scalar X2 = massFractionN[nCompIdx];
+              Scalar avgMolarMass = M1*M2/(M2 + X2*(M1 - M2));
+
+              // convert mass to mole fractions and set the fluid state
+              ParentType::fluidState_.setMoleFraction(nPhaseIdx, wCompIdx, massFractionN[wCompIdx]*avgMolarMass/M1);
+              ParentType::fluidState_.setMoleFraction(nPhaseIdx, nCompIdx, massFractionN[nCompIdx]*avgMolarMass/M2);
+
+              // TODO give values for non-existing wetting phase
+              Scalar xwCO2 = FluidSystem::equilibriumMoleFraction(ParentType::fluidState_, paramCache, wPhaseIdx);
+              Scalar xwH2O = 1 - xwCO2;
+//              Scalar xwCO2 = FluidSystem::equilibriumMoleFraction(ParentType::fluidState_, paramCache, wPhaseIdx, nPhaseOnly);
+//              Scalar xwH2O = 1 - xwCO2;
+              ParentType::fluidState_.setMoleFraction(wPhaseIdx, nCompIdx, xwCO2);
+              ParentType::fluidState_.setMoleFraction(wPhaseIdx, wCompIdx, xwH2O);
+
+
+              //Get the phase densities from the FluidSystem and set them in the fluidState
+
+              Scalar rhoW = FluidSystem::density(ParentType::fluidState_, paramCache, wPhaseIdx);
+              Scalar rhoN = FluidSystem::density(ParentType::fluidState_, paramCache, nPhaseIdx);
+
+              ParentType::fluidState_.setDensity(wPhaseIdx, rhoW);
+              ParentType::fluidState_.setDensity(nPhaseIdx, rhoN);
+
+              //Get the phase viscosities from the FluidSystem and set them in the fluidState
+
+              Scalar muW = FluidSystem::viscosity(ParentType::fluidState_, paramCache, wPhaseIdx);
+              Scalar muN = FluidSystem::viscosity(ParentType::fluidState_, paramCache, nPhaseIdx);
+
+              ParentType::fluidState_.setViscosity(wPhaseIdx, muW);
+              ParentType::fluidState_.setViscosity(nPhaseIdx, muN);
+          }
+          else if (phasePresence == wPhaseOnly) {
+               // only the wetting phase is present, i.e. wetting phase
+               // composition is stored explicitly.
+
+               // extract _mass_ fractions in the nonwetting phase
+               Scalar massFractionW[numComponents];
+               massFractionW[nCompIdx] = priVars[switchIdx];
+               massFractionW[wCompIdx] = 1 - massFractionW[nCompIdx];
+
+               // calculate average molar mass of the nonwetting phase
+               Scalar M1 = FluidSystem::molarMass(wCompIdx);
+               Scalar M2 = FluidSystem::molarMass(nCompIdx);
+               Scalar X2 = massFractionW[nCompIdx];
+               Scalar avgMolarMass = M1*M2/(M2 + X2*(M1 - M2));
+
+               // convert mass to mole fractions and set the fluid state
+               ParentType::fluidState_.setMoleFraction(wPhaseIdx, wCompIdx, massFractionW[wCompIdx]*avgMolarMass/M1);
+               ParentType::fluidState_.setMoleFraction(wPhaseIdx, nCompIdx, massFractionW[nCompIdx]*avgMolarMass/M2);
+
+               //  TODO give values for non-existing nonwetting phase
+               Scalar xnH2O = FluidSystem::equilibriumMoleFraction(ParentType::fluidState_, paramCache, nPhaseIdx);
+               Scalar xnCO2 = 1 - xnH2O; //FluidSystem::equilibriumMoleFraction(ParentType::fluidState_, paramCache, nPhaseIdx);
+//               Scalar xnH2O = FluidSystem::equilibriumMoleFraction(ParentType::fluidState_, paramCache, nPhaseIdx, wPhaseOnly);
+//               Scalar xnCO2 = 1 - xnH2O;
+               ParentType::fluidState_.setMoleFraction(nPhaseIdx, nCompIdx, xnCO2);
+               ParentType::fluidState_.setMoleFraction(nPhaseIdx, wCompIdx, xnH2O);
+
+
+               Scalar rhoW = FluidSystem::density(ParentType::fluidState_, paramCache, wPhaseIdx);
+               Scalar rhoN = FluidSystem::density(ParentType::fluidState_, paramCache, nPhaseIdx);
+
+               ParentType::fluidState_.setDensity(wPhaseIdx, rhoW);
+               ParentType::fluidState_.setDensity(nPhaseIdx, rhoN);
+
+               //Get the phase viscosities from the FluidSystem and set them in the fluidState
+
+               Scalar muW = FluidSystem::viscosity(ParentType::fluidState_, paramCache, wPhaseIdx);
+               Scalar muN = FluidSystem::viscosity(ParentType::fluidState_, paramCache, nPhaseIdx);
+
+               ParentType::fluidState_.setViscosity(wPhaseIdx, muW);
+               ParentType::fluidState_.setViscosity(nPhaseIdx, muN);
+           }
+
+          for (int phaseIdx = 0; phaseIdx < numPhases; ++phaseIdx) {
+              // compute and set the enthalpy
+              Scalar h = Implementation::enthalpy_(ParentType::fluidState_, paramCache, phaseIdx);
+              ParentType::fluidState_.setEnthalpy(phaseIdx, h);
+          }
+
+          paramCache.updateAll(ParentType::fluidState_);
+
+          for (int phaseIdx = 0; phaseIdx < numPhases; ++phaseIdx) {
+              // relative permeabilities
+              Scalar kr;
+              if (phaseIdx == wPhaseIdx)
+                  kr = MaterialLaw::krw(materialParams, this->saturation(wPhaseIdx));
+              else // ATTENTION: krn requires the liquid saturation
+                  // as parameter!
+                  kr = MaterialLaw::krn(materialParams, this->saturation(wPhaseIdx));
+              ParentType::relativePermeability_[phaseIdx] = kr;
+              Valgrind::CheckDefined(ParentType::relativePermeability_[phaseIdx]);
+
+              // binary diffusion coefficents
+              ParentType::diffCoeff_[phaseIdx] =
+                  FluidSystem::binaryDiffusionCoefficient(ParentType::fluidState_,
+                                                          paramCache,
+                                                          phaseIdx,
+                                                          wCompIdx,
+                                                          nCompIdx);
+              Valgrind::CheckDefined(ParentType::diffCoeff_[phaseIdx]);
+          }
+
+          // porosity
+          ParentType::porosity_ = problem.spatialParams().porosity(element,
+                                                           fvGeometry,
+                                                           scvIdx);
+          Valgrind::CheckDefined(ParentType::porosity_);
+//          if(phasePresence == bothPhases)
+//          {
+//              std::cout<<"globalIdx = "<<globalIdx<<std::endl;
+//              std::cout<<"scvIdx = "<<globalIdx<<std::endl;
+//              std::cout<<"Sn = "<<ParentType::fluidState_.saturation(nPhaseIdx)<<std::endl;
+//              std::cout<<"Sw = "<<ParentType::fluidState_.saturation(wPhaseIdx)<<std::endl;
+//              std::cout<<"mobilityN = "<<ParentType::mobility(nPhaseIdx)<<std::endl;
+//              std::cout<<"xgH2O = "<<ParentType::fluidState_.moleFraction(nPhaseIdx, wCompIdx)<<std::endl;
+//              std::cout<<"xgCO2 = "<<ParentType::fluidState_.moleFraction(nPhaseIdx, nCompIdx)<<std::endl;
+//              std::cout<<"xwH2O = "<<ParentType::fluidState_.moleFraction(wPhaseIdx, wCompIdx)<<std::endl;
+//              std::cout<<"xwCO2 = "<<ParentType::fluidState_.moleFraction(wPhaseIdx, nCompIdx)<<std::endl;
+//              std::cout<<"XgH2O = "<<ParentType::fluidState_.massFraction(nPhaseIdx, wCompIdx)<<std::endl;
+//              std::cout<<"XgCO2 = "<<ParentType::fluidState_.massFraction(nPhaseIdx, nCompIdx)<<std::endl;
+//              std::cout<<"XwH2O = "<<ParentType::fluidState_.massFraction(wPhaseIdx, wCompIdx)<<std::endl;
+//              std::cout<<"XwCO2 = "<<ParentType::fluidState_.massFraction(wPhaseIdx, nCompIdx)<<std::endl;
+//          }
+
+          // energy related quantities not contained in the fluid state
+          asImp_().updateEnergy_(priVars, problem, element, fvGeometry, scvIdx, isOldSol);
+    }
+
+
+
+
+protected:
+
+    static Scalar temperature_(const PrimaryVariables &priVars,
+                               const Problem& problem,
+                               const Element &element,
+                               const FVElementGeometry &fvGeometry,
+                               int scvIdx)
+    {
+        return problem.boxTemperature(element, fvGeometry, scvIdx);
+    }
+
+    template<class ParameterCache>
+    static Scalar enthalpy_(const FluidState& fluidState,
+                            const ParameterCache& paramCache,
+                            const int phaseIdx)
+    {
+        return 0;
+    }
+
+    void updateEnergy_(const PrimaryVariables &sol,
+                       const Problem &problem,
+                       const Element &element,
+                       const FVElementGeometry &fvGeometry,
+                       const int vertIdx,
+                       bool isOldSol)
+    { }
+
+
+
+private:
+
+
+
+    Implementation &asImp_()
+    { return *static_cast<Implementation*>(this); }
+
+    const Implementation &asImp_() const
+    { return *static_cast<const Implementation*>(this); }
+};
+
+} // end namepace
+
+#endif
diff --git a/dumux/implicit/co2ni/Makefile.am b/dumux/implicit/co2ni/Makefile.am
new file mode 100644
index 0000000000..e1f4e38102
--- /dev/null
+++ b/dumux/implicit/co2ni/Makefile.am
@@ -0,0 +1,4 @@
+co2nidir = $(includedir)/dumux/boxmodels/co2ni
+co2ni_HEADERS = *.hh
+
+include $(top_srcdir)/am/global-rules
diff --git a/dumux/implicit/co2ni/co2nimodel.hh b/dumux/implicit/co2ni/co2nimodel.hh
new file mode 100644
index 0000000000..987f1b193c
--- /dev/null
+++ b/dumux/implicit/co2ni/co2nimodel.hh
@@ -0,0 +1,56 @@
+// -*- mode: C++; tab-width: 4; indent-tabs-mode: nil; c-basic-offset: 4 -*-
+// vi: set et ts=4 sw=4 sts=4:
+/*****************************************************************************
+ *   Copyright (C) 2012 by                                                   *
+ *   Institute for Modelling Hydraulic and Environmental Systems             *
+ *   University of Stuttgart, Germany                                        *
+ *   email: <givenname>.<name>@iws.uni-stuttgart.de                          *
+ *                                                                           *
+ *   This program is free software: you can redistribute it and/or modify    *
+ *   it under the terms of the GNU General Public License as published by    *
+ *   the Free Software Foundation, either version 2 of the License, or       *
+ *   (at your option) any later version.                                     *
+ *                                                                           *
+ *   This program is distributed in the hope that it will be useful,         *
+ *   but WITHOUT ANY WARRANTY; without even the implied warranty of          *
+ *   MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the           *
+ *   GNU General Public License for more details.                            *
+ *                                                                           *
+ *   You should have received a copy of the GNU General Public License       *
+ *   along with this program.  If not, see <http://www.gnu.org/licenses/>.   *
+ *****************************************************************************/
+/*!
+ * \file
+ *
+ * \brief Adaption of the BOX scheme to the non-isothermal two-phase two-component flow model without constraint solver.
+ */
+#ifndef DUMUX_CO2NI_MODEL_HH
+#define DUMUX_CO2NI_MODEL_HH
+
+#include <dumux/boxmodels/co2/co2model.hh>
+
+namespace Dumux {
+/*!
+ * \ingroup CO2NIModel
+ * \brief Adaption of the BOX scheme to the non-isothermal two-phase two-component flow model.
+ *   See TwoPTwoCNI model for reference to the equations.
+ *   The CO2NI model is derived from the CO2 model. In the CO2 model the phase switch criterion
+ *   is different from the 2p2c model.
+ *   The phase switch occurs when the equilibrium concentration
+ *   of a component in a phase is exceeded instead of the sum of the components in the virtual phase
+ *   (the phase which is not present) being greater that unity as done in the 2p2c model.
+ *   The CO2VolumeVariables do not use a constraint solver for calculating the mole fractions as is the
+ *   case in the 2p2c model. Instead mole fractions are calculated in the FluidSystem with a given
+ *   temperature, pressure and salinity.
+ *
+ */
+template<class TypeTag>
+class CO2NIModel : public CO2Model<TypeTag>
+{
+};
+
+}
+
+#include <dumux/boxmodels/2p2cni/2p2cnipropertydefaults.hh>
+
+#endif
diff --git a/dumux/implicit/co2ni/co2nivolumevariables.hh b/dumux/implicit/co2ni/co2nivolumevariables.hh
new file mode 100644
index 0000000000..9609d0095b
--- /dev/null
+++ b/dumux/implicit/co2ni/co2nivolumevariables.hh
@@ -0,0 +1,139 @@
+// -*- mode: C++; tab-width: 4; indent-tabs-mode: nil; c-basic-offset: 4 -*-
+// vi: set et ts=4 sw=4 sts=4:
+/*****************************************************************************
+ *   Copyright (C) 2012 by                                                   *
+ *   Institute for Modelling Hydraulic and Environmental Systems             *
+ *   University of Stuttgart, Germany                                        *
+ *   email: <givenname>.<name>@iws.uni-stuttgart.de                          *
+ *                                                                           *
+ *   This program is free software: you can redistribute it and/or modify    *
+ *   it under the terms of the GNU General Public License as published by    *
+ *   the Free Software Foundation, either version 2 of the License, or       *
+ *   (at your option) any later version.                                     *
+ *                                                                           *
+ *   This program is distributed in the hope that it will be useful,         *
+ *   but WITHOUT ANY WARRANTY; without even the implied warranty of          *
+ *   MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the           *
+ *   GNU General Public License for more details.                            *
+ *                                                                           *
+ *   You should have received a copy of the GNU General Public License       *
+ *   along with this program.  If not, see <http://www.gnu.org/licenses/>.   *
+ *****************************************************************************/
+/*!
+ * \file
+ *
+ * \brief Contains the quantities which are constant within a
+ *        finite volume in the non-isothermal two-phase, two-component
+ *        model.
+ */
+#ifndef DUMUX_CO2NI_VOLUME_VARIABLES_HH
+#define DUMUX_CO2NI_VOLUME_VARIABLES_HH
+
+#include <dumux/boxmodels/co2/co2volumevariables.hh>
+
+namespace Dumux
+{
+
+/*!
+ * \ingroup CO2NIModel
+ * \ingroup BoxVolumeVariables
+ * \brief Contains the quantities which are are constant within a
+ *        finite volume in the non-isothermal two-phase, two-component
+ *        model.
+ */
+template <class TypeTag>
+class CO2NIVolumeVariables : public CO2VolumeVariables<TypeTag>
+{
+    //! \cond 0
+    typedef CO2VolumeVariables<TypeTag> ParentType;
+    typedef typename ParentType::FluidState FluidState;
+
+    typedef typename GET_PROP_TYPE(TypeTag, Scalar) Scalar;
+    typedef typename GET_PROP_TYPE(TypeTag, FVElementGeometry) FVElementGeometry;
+    typedef typename GET_PROP_TYPE(TypeTag, Problem) Problem;
+    typedef typename GET_PROP_TYPE(TypeTag, PrimaryVariables) PrimaryVariables;
+    typedef typename GET_PROP_TYPE(TypeTag, FluidSystem) FluidSystem;
+
+    typedef typename GET_PROP_TYPE(TypeTag, Indices) Indices;
+    enum { temperatureIdx = Indices::temperatureIdx };
+
+    typedef typename GET_PROP_TYPE(TypeTag, GridView) GridView;
+    typedef typename GridView::template Codim<0>::Entity Element;
+    //! \endcond
+
+public:
+    /*!
+     * \brief Returns the total internal energy of a phase in the
+     *        sub-control volume.
+     *
+     * \param phaseIdx The phase index
+     */
+    Scalar internalEnergy(const int phaseIdx) const
+    { return this->fluidState_.internalEnergy(phaseIdx); };
+
+    /*!
+     * \brief Returns the total enthalpy of a phase in the sub-control
+     *        volume.
+     *
+     * \param phaseIdx The phase index
+     */
+    Scalar enthalpy(const int phaseIdx) const
+    { return this->fluidState_.enthalpy(phaseIdx); };
+
+    /*!
+     * \brief Returns the total heat capacity \f$\mathrm{[J/(K*m^3]}\f$ of the rock matrix in
+     *        the sub-control volume.
+     */
+    Scalar heatCapacity() const
+    { return heatCapacity_; };
+
+protected:
+    // this method gets called by the parent class. since this method
+    // is protected, we are friends with our parent..
+    friend class CO2VolumeVariables<TypeTag>;
+
+    static Scalar temperature_(const PrimaryVariables &priVars,
+                               const Problem& problem,
+                               const Element &element,
+                               const FVElementGeometry &fvGeometry,
+                               const int scvIdx)
+    {
+        return priVars[temperatureIdx];
+    }
+
+    template<class ParameterCache>
+    static Scalar enthalpy_(const FluidState& fluidState,
+                            const ParameterCache& paramCache,
+                            const int phaseIdx)
+    {
+        return FluidSystem::enthalpy(fluidState, paramCache, phaseIdx);
+    }
+
+    /*!
+     * \brief Update all quantities for a given control volume.
+     *
+     * \param sol The solution primary variables
+     * \param problem The problem
+     * \param element The element
+     * \param fvGeometry Evaluate function with solution of current or previous time step
+     * \param scvIdx The local index of the SCV (sub-control volume)
+     * \param isOldSol Evaluate function with solution of current or previous time step
+     */
+    void updateEnergy_(const PrimaryVariables &sol,
+                       const Problem &problem,
+                       const Element &element,
+                       const FVElementGeometry &fvGeometry,
+                       const int scvIdx,
+                       bool isOldSol)
+    {
+        // copmute and set the heat capacity of the solid phase
+        heatCapacity_ = problem.spatialParams().heatCapacity(element, fvGeometry, scvIdx);
+        Valgrind::CheckDefined(heatCapacity_);
+    };
+
+    Scalar heatCapacity_;
+};
+
+} // end namepace
+
+#endif
diff --git a/dumux/implicit/common/Makefile.am b/dumux/implicit/common/Makefile.am
new file mode 100644
index 0000000000..2fd0a582d6
--- /dev/null
+++ b/dumux/implicit/common/Makefile.am
@@ -0,0 +1,4 @@
+commondir = $(includedir)/dumux/boxmodels/common
+common_HEADERS = *.hh
+
+include $(top_srcdir)/am/global-rules
diff --git a/dumux/implicit/common/implicitassembler.hh b/dumux/implicit/common/implicitassembler.hh
new file mode 100644
index 0000000000..18e196c3e8
--- /dev/null
+++ b/dumux/implicit/common/implicitassembler.hh
@@ -0,0 +1,858 @@
+// -*- mode: C++; tab-width: 4; indent-tabs-mode: nil; c-basic-offset: 4 -*-
+// vi: set et ts=4 sw=4 sts=4:
+/*****************************************************************************
+ *   See the file COPYING for full copying permissions.                      *
+ *                                                                           *
+ *   This program is free software: you can redistribute it and/or modify    *
+ *   it under the terms of the GNU General Public License as published by    *
+ *   the Free Software Foundation, either version 2 of the License, or       *
+ *   (at your option) any later version.                                     *
+ *                                                                           *
+ *   This program is distributed in the hope that it will be useful,         *
+ *   but WITHOUT ANY WARRANTY; without even the implied warranty of          *
+ *   MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the            *
+ *   GNU General Public License for more details.                            *
+ *                                                                           *
+ *   You should have received a copy of the GNU General Public License       *
+ *   along with this program.  If not, see <http://www.gnu.org/licenses/>.   *
+ *****************************************************************************/
+/*!
+ * \file
+ *
+ * \brief An assembler for the global Jacobian matrix for models using the box discretization.
+ */
+#ifndef DUMUX_BOX_ASSEMBLER_HH
+#define DUMUX_BOX_ASSEMBLER_HH
+
+#include <dune/grid/common/gridenums.hh>
+
+#include <dumux/boxmodels/common/boxproperties.hh>
+#include <dumux/linear/vertexborderlistfromgrid.hh>
+#include <dumux/linear/foreignoverlapfrombcrsmatrix.hh>
+#include <dumux/parallel/vertexhandles.hh>
+
+namespace Dumux {
+
+/*!
+ * \brief An assembler for the global Jacobian matrix for models using the box discretization.
+ */
+template<class TypeTag>
+class BoxAssembler
+{
+    typedef typename GET_PROP_TYPE(TypeTag, Model) Model;
+    typedef typename GET_PROP_TYPE(TypeTag, Problem) Problem;
+    typedef typename GET_PROP_TYPE(TypeTag, GridView) GridView;
+    typedef typename GET_PROP_TYPE(TypeTag, Scalar) Scalar;
+    typedef typename GET_PROP_TYPE(TypeTag, VertexMapper) VertexMapper;
+    typedef typename GET_PROP_TYPE(TypeTag, ElementMapper) ElementMapper;
+
+    typedef typename GET_PROP_TYPE(TypeTag, SolutionVector) SolutionVector;
+    typedef typename GET_PROP_TYPE(TypeTag, JacobianMatrix) JacobianMatrix;
+    typedef typename GET_PROP_TYPE(TypeTag, PrimaryVariables) PrimaryVariables;
+
+    enum{ dim = GridView::dimension };
+    typedef typename GridView::template Codim<0>::Entity Element;
+    typedef typename GridView::template Codim<0>::Iterator ElementIterator;
+    typedef typename GridView::template Codim<dim>::EntityPointer VertexPointer;
+
+    enum { numEq = GET_PROP_VALUE(TypeTag, NumEq) };
+    typedef Dune::FieldMatrix<Scalar, numEq, numEq> MatrixBlock;
+    typedef Dune::FieldVector<Scalar, numEq> VectorBlock;
+
+    // copying the jacobian assembler is not a good idea
+    BoxAssembler(const BoxAssembler &);
+
+public:
+    /*!
+     * \brief The colors of elements and vertices required for partial
+     *        Jacobian reassembly.
+     */
+    enum EntityColor {
+        /*!
+         * Vertex/element that needs to be reassembled because some
+         * relative error is above the tolerance
+         */
+        Red = 0,
+
+        /*!
+         * Vertex/element that needs to be reassembled because a
+         * neighboring element/vertex is red
+         */
+        Yellow = 1,
+
+        /*!
+         * Yellow vertex has only non-green neighbor elements.
+         *
+         * This means that its relative error is below the tolerance,
+         * but its defect can be linearized without any additional
+         * cost. This is just an "internal" color which is not used
+         * ouside of the jacobian assembler.
+         */
+        Orange = 2,
+
+        /*!
+         * Vertex/element that does not need to be reassembled
+         */
+        Green = 3
+    };
+
+    BoxAssembler()
+    {
+        problemPtr_ = 0;
+        matrix_ = 0;
+
+        // set reassemble accuracy to 0, so that if partial reassembly
+        // of the jacobian matrix is disabled, the reassemble accuracy
+        // is always smaller than the current relative tolerance
+        reassembleAccuracy_ = 0.0;
+    }
+
+    ~BoxAssembler()
+    {
+        delete matrix_;
+    }
+
+    /*!
+     * \brief Initialize the jacobian assembler.
+     *
+     * At this point we can assume that all objects in the problem and
+     * the model have been allocated. We can not assume that they are
+     * fully initialized, though.
+     *
+     * \param problem The problem object
+     */
+    void init(Problem& problem)
+    {
+        problemPtr_ = &problem;
+
+        // initialize the BCRS matrix
+        createMatrix_();
+
+        // initialize the jacobian matrix and the right hand side
+        // vector
+        *matrix_ = 0;
+        reuseMatrix_ = false;
+
+        int numVerts = gridView_().size(dim);
+        int numElems = gridView_().size(0);
+
+        residual_.resize(numVerts);
+
+        // initialize the storage part of the Jacobian matrix. Since
+        // we only need this if Jacobian matrix recycling is enabled,
+        // we do not waste space if it is disabled
+        if (enableJacobianRecycling_()) {
+            storageJacobian_.resize(numVerts);
+            storageTerm_.resize(numVerts);
+        }
+
+        if (gridView_().comm().size() > 1)
+            totalElems_ = gridView_().comm().sum(numElems);
+        else
+            totalElems_ = numElems;
+
+        // initialize data needed for partial reassembly
+        if (enablePartialReassemble_()) {
+            vertexColor_.resize(numVerts);
+            vertexDelta_.resize(numVerts);
+            elementColor_.resize(numElems);
+        }
+        reassembleAll();
+    }
+
+    /*!
+     * \brief Assemble the global Jacobian of the residual and the residual for the current solution.
+     *
+     * The current state of affairs (esp. the previous and the current
+     * solutions) is represented by the model object.
+     */
+    void assemble()
+    {
+        bool printReassembleStatistics = enablePartialReassemble_() && !reuseMatrix_;
+        int succeeded;
+        try {
+            assemble_();
+            succeeded = 1;
+            if (gridView_().comm().size() > 1)
+                succeeded = gridView_().comm().min(succeeded);
+        }
+        catch (Dumux::NumericalProblem &e)
+        {
+            std::cout << "rank " << problem_().gridView().comm().rank()
+                      << " caught an exception while assembling:" << e.what()
+                      << "\n";
+            succeeded = 0;
+            if (gridView_().comm().size() > 1)
+                succeeded = gridView_().comm().min(succeeded);
+        }
+
+        if (!succeeded) {
+            DUNE_THROW(NumericalProblem,
+                       "A process did not succeed in linearizing the system");
+        }
+
+        if (printReassembleStatistics)
+        {
+            if (gridView_().comm().size() > 1)
+            {
+                greenElems_ = gridView_().comm().sum(greenElems_);
+                reassembleAccuracy_ = gridView_().comm().max(nextReassembleAccuracy_);
+            }
+            else
+            {
+                reassembleAccuracy_ = nextReassembleAccuracy_;
+            }
+
+            problem_().newtonController().endIterMsg()
+                << ", reassembled "
+                << totalElems_ - greenElems_ << "/" << totalElems_
+                << " (" << 100*Scalar(totalElems_ - greenElems_)/totalElems_ << "%) elems @accuracy="
+                << reassembleAccuracy_;
+        }
+
+        // reset all vertex colors to green
+        for (unsigned int i = 0; i < vertexColor_.size(); ++i) {
+            vertexColor_[i] = Green;
+        }
+    }
+
+    /*!
+     * \brief If Jacobian matrix recycling is enabled, this method
+     *        specifies whether the next call to assemble() just
+     *        rescales the storage term or does a full reassembly
+     *
+     * \param yesno If true, only rescale; else do full Jacobian assembly.
+     */
+    void setMatrixReuseable(const bool yesno = true)
+    {
+        if (enableJacobianRecycling_())
+            reuseMatrix_ = yesno;
+    }
+
+    /*!
+     * \brief If partial Jacobian matrix reassembly is enabled, this
+     *        method causes all elements to be reassembled in the next
+     *        assemble() call.
+     */
+    void reassembleAll()
+    {
+        // do not reuse the current linearization
+        reuseMatrix_ = false;
+
+        // do not use partial reassembly for the next iteration
+        nextReassembleAccuracy_ = 0.0;
+        if (enablePartialReassemble_()) {
+            std::fill(vertexColor_.begin(),
+                      vertexColor_.end(),
+                      Red);
+            std::fill(elementColor_.begin(),
+                      elementColor_.end(),
+                      Red);
+            std::fill(vertexDelta_.begin(),
+                      vertexDelta_.end(),
+                      0.0);
+        }
+    }
+
+    /*!
+     * \brief Returns the largest relative error of a "green" vertex
+     *        for the most recent call of the assemble() method.
+     *
+     * This only has an effect if partial Jacobian reassembly is
+     * enabled. If it is disabled, then this method always returns 0.
+     *
+     * This returns the _actual_ relative computed seen by
+     * computeColors(), not the tolerance which it was given.
+     */
+    Scalar reassembleAccuracy() const
+    { return reassembleAccuracy_; }
+
+    /*!
+     * \brief Update the distance where the non-linear system was
+     *        originally insistently linearized and the point where it
+     *        will be linerized the next time.
+     *
+     * This only has an effect if partial reassemble is enabled.
+     */
+    void updateDiscrepancy(const SolutionVector &u,
+                           const SolutionVector &uDelta)
+    {
+        if (!enablePartialReassemble_())
+            return;
+
+        // update the vector with the distances of the current
+        // evaluation point used for linearization from the original
+        // evaluation point
+        for (unsigned int i = 0; i < vertexDelta_.size(); ++i) {
+            PrimaryVariables currentPriVars(u[i]);
+            PrimaryVariables nextPriVars(currentPriVars);
+            nextPriVars -= uDelta[i];
+
+            // we need to add the distance the solution was moved for
+            // this vertex
+            Scalar dist = model_().relativeErrorVertex(i,
+                                                       currentPriVars,
+                                                       nextPriVars);
+            vertexDelta_[i] += std::abs(dist);
+        }
+
+    }
+
+    /*!
+     * \brief Force to reassemble a given vertex next time the
+     *        assemble() method is called.
+     *
+     * \param globalVertIdx The global index of the vertex which ought
+     *                      to be red.
+     */
+    void markVertexRed(const int globalVertIdx)
+    {
+        if (!enablePartialReassemble_())
+            return;
+
+        vertexColor_[globalVertIdx] = Red;
+    }
+
+    /*!
+     * \brief Determine the colors of vertices and elements for partial
+     *        reassembly given a relative tolerance.
+     *
+     * The following approach is used:
+     *
+     * - Set all vertices and elements to 'green'
+     * - Mark all vertices as 'red' which exhibit an relative error above
+     *   the tolerance
+     * - Mark all elements which feature a 'red' vetex as 'red'
+     * - Mark all vertices which are not 'red' and are part of a
+     *   'red' element as 'yellow'
+     * - Mark all elements which are not 'red' and contain a
+     *   'yellow' vertex as 'yellow'
+     *
+     * \param relTol The relative error below which a vertex won't be
+     *               reassembled. Note that this specifies the
+     *               worst-case relative error between the last
+     *               linearization point and the current solution and
+     *               _not_ the delta vector of the Newton iteration!
+     */
+    void computeColors(const Scalar relTol)
+    {
+        if (!enablePartialReassemble_())
+            return;
+
+        ElementIterator elemIt = gridView_().template begin<0>();
+        ElementIterator elemEndIt = gridView_().template end<0>();
+
+        // mark the red vertices and update the tolerance of the
+        // linearization which actually will get achieved
+        nextReassembleAccuracy_ = 0;
+        for (unsigned int i = 0; i < vertexColor_.size(); ++i) {
+            if (vertexDelta_[i] > relTol)
+                // mark vertex as red if discrepancy is larger than
+                // the relative tolerance
+                vertexColor_[i] = Red;
+            else
+                nextReassembleAccuracy_ =
+                    std::max(nextReassembleAccuracy_, vertexDelta_[i]);
+        }
+
+        // Mark all red elements
+        for (; elemIt != elemEndIt; ++elemIt) {
+            // find out whether the current element features a red
+            // vertex
+            bool isRed = false;
+            int numVerts = elemIt->template count<dim>();
+            for (int i=0; i < numVerts; ++i) {
+                int globalI = vertexMapper_().map(*elemIt, i, dim);
+                if (vertexColor_[globalI] == Red) {
+                    isRed = true;
+                    break;
+                }
+            }
+
+            // if yes, the element color is also red, else it is not
+            // red, i.e. green for the mean time
+            int globalElemIdx = elementMapper_().map(*elemIt);
+            if (isRed)
+                elementColor_[globalElemIdx] = Red;
+            else
+                elementColor_[globalElemIdx] = Green;
+        }
+
+        // Mark yellow vertices (as orange for the mean time)
+        elemIt = gridView_().template begin<0>();
+        for (; elemIt != elemEndIt; ++elemIt) {
+            int elemIdx = this->elementMapper_().map(*elemIt);
+            if (elementColor_[elemIdx] != Red)
+                continue; // non-red elements do not tint vertices
+                          // yellow!
+
+            int numVerts = elemIt->template count<dim>();
+            for (int i=0; i < numVerts; ++i) {
+                int globalI = vertexMapper_().map(*elemIt, i, dim);
+                // if a vertex is already red, don't recolor it to
+                // yellow!
+                if (vertexColor_[globalI] != Red) {
+                    vertexColor_[globalI] = Orange;
+                }
+            }
+        }
+
+        // at this point we communicate the yellow vertices to the
+        // neighboring processes because a neigbor process may not see
+        // the red vertex for yellow border vertices
+        VertexHandleMin<EntityColor, std::vector<EntityColor>,  VertexMapper>
+            minHandle(vertexColor_, vertexMapper_());
+        gridView_().communicate(minHandle,
+                                Dune::InteriorBorder_InteriorBorder_Interface,
+                                Dune::ForwardCommunication);
+
+        // Mark yellow elements
+        elemIt = gridView_().template begin<0>();
+        for (; elemIt != elemEndIt; ++elemIt) {
+            int elemIdx = this->elementMapper_().map(*elemIt);
+            if (elementColor_[elemIdx] == Red) {
+                continue; // element is red already!
+            }
+
+            // check whether the element features a yellow
+            // (resp. orange at this point) vertex
+            bool isYellow = false;
+            int numVerts = elemIt->template count<dim>();
+            for (int i=0; i < numVerts; ++i) {
+                int globalI = vertexMapper_().map(*elemIt, i, dim);
+                if (vertexColor_[globalI] == Orange) {
+                    isYellow = true;
+                    break;
+                }
+            }
+
+            if (isYellow)
+                elementColor_[elemIdx] = Yellow;
+        }
+
+        // Demote orange vertices to yellow ones if it has at least
+        // one green element as a neighbor.
+        elemIt = gridView_().template begin<0>();
+        for (; elemIt != elemEndIt; ++elemIt) {
+            int elemIdx = this->elementMapper_().map(*elemIt);
+            if (elementColor_[elemIdx] != Green)
+                continue; // yellow and red elements do not make
+                          // orange vertices yellow!
+
+            int numVerts = elemIt->template count<dim>();
+            for (int i=0; i < numVerts; ++i) {
+                int globalI = vertexMapper_().map(*elemIt, i, dim);
+                // if a vertex is orange, recolor it to yellow!
+                if (vertexColor_[globalI] == Orange)
+                    vertexColor_[globalI] = Yellow;
+            }
+        }
+
+        // demote the border orange vertices
+        VertexHandleMax<EntityColor, std::vector<EntityColor>,  VertexMapper>
+            maxHandle(vertexColor_,
+                      vertexMapper_());
+        gridView_().communicate(maxHandle,
+                                Dune::InteriorBorder_InteriorBorder_Interface,
+                                Dune::ForwardCommunication);
+
+        // promote the remaining orange vertices to red
+        for (unsigned int i=0; i < vertexColor_.size(); ++i) {
+            // if a vertex is green or yellow don't do anything!
+            if (vertexColor_[i] == Green || vertexColor_[i] == Yellow)
+                continue;
+
+            // make sure the vertex is red (this is a no-op vertices
+            // which are already red!)
+            vertexColor_[i] = Red;
+
+            // set the error of this vertex to 0 because the system
+            // will be consistently linearized at this vertex
+            vertexDelta_[i] = 0.0;
+        }
+    }
+
+    /*!
+     * \brief Returns the reassemble color of a vertex
+     *
+     * \param element An element which contains the vertex
+     * \param vertIdx The local index of the vertex in the element.
+     */
+    int vertexColor(const Element &element, const int vertIdx) const
+    {
+        if (!enablePartialReassemble_())
+            return Red; // reassemble unconditionally!
+
+        int globalIdx = vertexMapper_().map(element, vertIdx, dim);
+        return vertexColor_[globalIdx];
+    }
+
+    /*!
+     * \brief Returns the reassemble color of a vertex
+     *
+     * \param globalVertIdx The global index of the vertex.
+     */
+    int vertexColor(const int globalVertIdx) const
+    {
+        if (!enablePartialReassemble_())
+            return Red; // reassemble unconditionally!
+        return vertexColor_[globalVertIdx];
+    }
+
+    /*!
+     * \brief Returns the Jacobian reassemble color of an element
+     *
+     * \param element The Codim-0 DUNE entity
+     */
+    int elementColor(const Element &element) const
+    {
+        if (!enablePartialReassemble_())
+            return Red; // reassemble unconditionally!
+
+        int globalIdx = elementMapper_().map(element);
+        return elementColor_[globalIdx];
+    }
+
+    /*!
+     * \brief Returns the Jacobian reassemble color of an element
+     *
+     * \param globalElementIdx The global index of the element.
+     */
+    int elementColor(const int globalElementIdx) const
+    {
+        if (!enablePartialReassemble_())
+            return Red; // reassemble unconditionally!
+        return elementColor_[globalElementIdx];
+    }
+
+    /*!
+     * \brief Return constant reference to global Jacobian matrix.
+     */
+    const JacobianMatrix& matrix() const
+    { return *matrix_; }
+    JacobianMatrix& matrix()
+    { return *matrix_; }
+
+    /*!
+     * \brief Return constant reference to global residual vector.
+     */
+    const SolutionVector& residual() const
+    { return residual_; }
+    SolutionVector& residual() 
+    { return residual_; }
+
+private:
+    static bool enableJacobianRecycling_()
+    { return GET_PARAM_FROM_GROUP(TypeTag, bool, Implicit, EnableJacobianRecycling); }
+    static bool enablePartialReassemble_()
+    { return GET_PARAM_FROM_GROUP(TypeTag, bool, Implicit, EnablePartialReassemble); }
+
+    // Construct the BCRS matrix for the global jacobian
+    void createMatrix_()
+    {
+        int numVerticesGlobal = gridView_().size(dim);
+
+        // allocate raw matrix
+        matrix_ = new JacobianMatrix(numVerticesGlobal, numVerticesGlobal, JacobianMatrix::random);
+
+        // find out the global indices of the neighboring vertices of
+        // each vertex
+        typedef std::set<int> NeighborSet;
+        std::vector<NeighborSet> neighbors(numVerticesGlobal);
+        ElementIterator eIt = gridView_().template begin<0>();
+        const ElementIterator eEndIt = gridView_().template end<0>();
+        for (; eIt != eEndIt; ++eIt) {
+            const Element &elem = *eIt;
+            int numVerticesLocal = elem.template count<dim>();
+
+            // if the element is not in the interior or the process
+            // border, all dofs just contain main-diagonal entries
+            if (elem.partitionType() != Dune::InteriorEntity &&
+                elem.partitionType() != Dune::BorderEntity)
+            {
+                for (int i = 0; i < numVerticesLocal; ++i) {
+                    int globalI = vertexMapper_().map(*eIt, i, dim);
+                    neighbors[globalI].insert(globalI);
+                }
+            }
+            else
+            {
+                // loop over all element vertices
+                for (int i = 0; i < numVerticesLocal - 1; ++i) {
+                    int globalI = vertexMapper_().map(*eIt, i, dim);
+                    for (int j = i + 1; j < numVerticesLocal; ++j) {
+                        int globalJ = vertexMapper_().map(*eIt, j, dim);
+                        // make sure that vertex j is in the neighbor set
+                        // of vertex i and vice-versa
+                        neighbors[globalI].insert(globalJ);
+                        neighbors[globalJ].insert(globalI);
+                    }
+                }
+            }
+        }
+
+        // make vertices neighbors to themselfs
+        for (int i = 0; i < numVerticesGlobal; ++i) {
+            neighbors[i].insert(i);
+        }
+        
+        // allocate space for the rows of the matrix
+        for (int i = 0; i < numVerticesGlobal; ++i) {
+            matrix_->setrowsize(i, neighbors[i].size());
+        }
+        matrix_->endrowsizes();
+
+        // fill the rows with indices. each vertex talks to all of its
+        // neighbors. (it also talks to itself since vertices are
+        // sometimes quite egocentric.)
+        for (int i = 0; i < numVerticesGlobal; ++i) {
+            typename NeighborSet::iterator nIt = neighbors[i].begin();
+            typename NeighborSet::iterator nEndIt = neighbors[i].end();
+            for (; nIt != nEndIt; ++nIt) {
+                matrix_->addindex(i, *nIt);
+            }
+        }
+        matrix_->endindices();
+    }
+
+    // reset the global linear system of equations. if partial
+    // reassemble is enabled, this means that the jacobian matrix must
+    // only be erased partially!
+    void resetSystem_()
+    {
+        // do not do anything if we can re-use the current linearization
+        if (reuseMatrix_)
+            return;
+
+        // reset the right hand side.
+        residual_ = 0.0;
+
+        if (!enablePartialReassemble_()) {
+            // If partial reassembly of the jacobian is not enabled,
+            // we can just reset everything!
+            (*matrix_) = 0;
+
+            // reset the parts needed for Jacobian recycling
+            if (enableJacobianRecycling_()) {
+                int numVerticesGlobal = matrix_->N();
+                for (int i=0; i < numVerticesGlobal; ++ i) {
+                    storageJacobian_[i] = 0;
+                    storageTerm_[i] = 0;
+                }
+            }
+
+            return;
+        }
+
+        // reset all entries corrosponding to a red or yellow vertex
+        for (unsigned int rowIdx = 0; rowIdx < matrix_->N(); ++rowIdx) {
+            if (vertexColor_[rowIdx] == Green)
+                continue; // the equations for this control volume are
+                          // already below the treshold
+
+            // here we have yellow or red vertices...
+
+            // reset the parts needed for Jacobian recycling
+            if (enableJacobianRecycling_()) {
+                storageJacobian_[rowIdx] = 0;
+                storageTerm_[rowIdx] = 0;
+            }
+
+            // set all matrix entries in the row to 0
+            typedef typename JacobianMatrix::ColIterator ColIterator;
+            ColIterator colIt = (*matrix_)[rowIdx].begin();
+            const ColIterator &colEndIt = (*matrix_)[rowIdx].end();
+            for (; colIt != colEndIt; ++colIt) {
+                (*colIt) = 0.0;
+            }
+        }
+    }
+
+    // linearize the whole system
+    void assemble_()
+    {
+        resetSystem_();
+
+        // if we can "recycle" the current linearization, we do it
+        // here and be done with it...
+        Scalar curDt = problem_().timeManager().timeStepSize();
+        if (reuseMatrix_) {
+            int numVerticesGlobal = storageJacobian_.size();
+            for (int i = 0; i < numVerticesGlobal; ++i) {
+                // rescale the mass term of the jacobian matrix
+                MatrixBlock &J_i_i = (*matrix_)[i][i];
+
+                J_i_i -= storageJacobian_[i];
+                storageJacobian_[i] *= oldDt_/curDt;
+                J_i_i += storageJacobian_[i];
+
+                // use the flux term plus the source term as the new
+                // residual (since the delta in the d(storage)/dt is 0
+                // for the first iteration and the residual is
+                // approximately 0 in the last iteration, the flux
+                // term plus the source term must be equal to the
+                // negative change of the storage term of the last
+                // iteration of the last time step...)
+                residual_[i] = storageTerm_[i];
+                residual_[i] *= -1;
+            }
+
+            reuseMatrix_ = false;
+            oldDt_ = curDt;
+            return;
+        }
+
+        oldDt_ = curDt;
+        greenElems_ = 0;
+
+        // reassemble the elements...
+        ElementIterator elemIt = gridView_().template begin<0>();
+        ElementIterator elemEndIt = gridView_().template end<0>();
+        for (; elemIt != elemEndIt; ++elemIt) {
+            const Element &elem = *elemIt;
+            if (elem.partitionType() != Dune::InteriorEntity  &&
+                elem.partitionType() != Dune::BorderEntity)
+            {
+                assembleGhostElement_(elem);
+            }
+            else
+            {
+                assembleElement_(elem);
+            }
+        }
+    }
+
+    // assemble a non-ghost element
+    void assembleElement_(const Element &elem)
+    {
+        if (enablePartialReassemble_()) {
+            int globalElemIdx = model_().elementMapper().map(elem);
+            if (elementColor_[globalElemIdx] == Green) {
+                ++greenElems_;
+
+                assembleGreenElement_(elem);
+                return;
+            }
+        }
+
+        model_().localJacobian().assemble(elem);
+
+        int numVerticesLocal = elem.template count<dim>();
+        for (int i=0; i < numVerticesLocal; ++ i) {
+            int globI = vertexMapper_().map(elem, i, dim);
+
+            // update the right hand side
+            residual_[globI] += model_().localJacobian().residual(i);
+            for (int j = 0; j < residual_[globI].dimension; ++j)
+                assert(std::isfinite(residual_[globI][j]));
+            if (enableJacobianRecycling_()) {
+                storageTerm_[globI] +=
+                    model_().localJacobian().storageTerm(i);
+            }
+
+            // only update the jacobian matrix for non-green vertices
+            if (vertexColor(globI) != Green) {
+                if (enableJacobianRecycling_())
+                    storageJacobian_[globI] +=
+                        model_().localJacobian().storageJacobian(i);
+
+                // update the jacobian matrix
+                for (int j=0; j < numVerticesLocal; ++ j) {
+                    int globJ = vertexMapper_().map(elem, j, dim);
+                    (*matrix_)[globI][globJ] +=
+                        model_().localJacobian().mat(i,j);
+                }
+            }
+        }
+    }
+
+    // "assemble" a green element. green elements only get the
+    // residual updated, but the jacobian is left alone...
+    void assembleGreenElement_(const Element &elem)
+    {
+        model_().localResidual().eval(elem);
+
+        int numVerticesLocal = elem.template count<dim>();
+        for (int i=0; i < numVerticesLocal; ++ i) {
+            int globI = vertexMapper_().map(elem, i, dim);
+
+            // update the right hand side
+            residual_[globI] += model_().localResidual().residual(i);
+            if (enableJacobianRecycling_())
+                storageTerm_[globI] += model_().localResidual().storageTerm(i);
+        }
+    }
+
+    // "assemble" a ghost element
+    void assembleGhostElement_(const Element &elem)
+    {
+        int numVerticesLocal = elem.template count<dim>();
+        for (int i=0; i < numVerticesLocal; ++i) {
+            const VertexPointer vp = elem.template subEntity<dim>(i);
+
+            if (vp->partitionType() == Dune::InteriorEntity ||
+                vp->partitionType() == Dune::BorderEntity)
+            {
+                // do not change the non-ghost vertices
+                continue;
+            }
+
+            // set main diagonal entries for the vertex
+            int vIdx = vertexMapper_().map(*vp);
+            typedef typename JacobianMatrix::block_type BlockType;
+            BlockType &J = (*matrix_)[vIdx][vIdx];
+            for (int j = 0; j < BlockType::rows; ++j)
+                J[j][j] = 1.0;
+
+            // set residual for the vertex
+            residual_[vIdx] = 0;
+        }
+    }
+
+
+    Problem &problem_()
+    { return *problemPtr_; }
+    const Problem &problem_() const
+    { return *problemPtr_; }
+    const Model &model_() const
+    { return problem_().model(); }
+    Model &model_()
+    { return problem_().model(); }
+    const GridView &gridView_() const
+    { return problem_().gridView(); }
+    const VertexMapper &vertexMapper_() const
+    { return problem_().vertexMapper(); }
+    const ElementMapper &elementMapper_() const
+    { return problem_().elementMapper(); }
+
+    Problem *problemPtr_;
+
+    // the jacobian matrix
+    JacobianMatrix *matrix_;
+    // the right-hand side
+    SolutionVector residual_;
+
+    // attributes required for jacobian matrix recycling
+    bool reuseMatrix_;
+    // The storage part of the local Jacobian
+    std::vector<MatrixBlock> storageJacobian_;
+    std::vector<VectorBlock> storageTerm_;
+    // time step size of last assembly
+    Scalar oldDt_;
+
+
+    // attributes required for partial jacobian reassembly
+    std::vector<EntityColor> vertexColor_;
+    std::vector<EntityColor> elementColor_;
+    std::vector<Scalar> vertexDelta_;
+
+    int totalElems_;
+    int greenElems_;
+
+    Scalar nextReassembleAccuracy_;
+    Scalar reassembleAccuracy_;
+};
+
+} // namespace Dumux
+
+#endif
diff --git a/dumux/implicit/common/implicitdarcyfluxvariables.hh b/dumux/implicit/common/implicitdarcyfluxvariables.hh
new file mode 100644
index 0000000000..6e5d3df449
--- /dev/null
+++ b/dumux/implicit/common/implicitdarcyfluxvariables.hh
@@ -0,0 +1,313 @@
+// -*- mode: C++; tab-width: 4; indent-tabs-mode: nil; c-basic-offset: 4 -*-
+// vi: set et ts=4 sw=4 sts=4:
+/*****************************************************************************
+ *   See the file COPYING for full copying permissions.                      *
+ *                                                                           *
+ *   This program is free software: you can redistribute it and/or modify    *
+ *   it under the terms of the GNU General Public License as published by    *
+ *   the Free Software Foundation, either version 2 of the License, or       *
+ *   (at your option) any later version.                                     *
+ *                                                                           *
+ *   This program is distributed in the hope that it will be useful,         *
+ *   but WITHOUT ANY WARRANTY; without even the implied warranty of          *
+ *   MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the            *
+ *   GNU General Public License for more details.                            *
+ *                                                                           *
+ *   You should have received a copy of the GNU General Public License       *
+ *   along with this program.  If not, see <http://www.gnu.org/licenses/>.   *
+ *****************************************************************************/
+/*!
+ * \file
+ *
+ * \brief This file contains the data which is required to calculate
+ *        all fluxes of fluid phases over a face of a finite volume.
+ *
+ * This means pressure and temperature gradients, phase densities at
+ * the integration point, etc.
+ */
+#ifndef DUMUX_BOX_DARCY_FLUX_VARIABLES_HH
+#define DUMUX_BOX_DARCY_FLUX_VARIABLES_HH
+
+#include "boxproperties.hh"
+
+#include <dumux/common/parameters.hh>
+#include <dumux/common/math.hh>
+
+namespace Dumux
+{
+    
+namespace Properties
+{
+// forward declaration of properties 
+NEW_PROP_TAG(ImplicitMobilityUpwindWeight);
+NEW_PROP_TAG(SpatialParams);
+NEW_PROP_TAG(NumPhases);
+NEW_PROP_TAG(ProblemEnableGravity);
+}   
+
+/*!
+ * \ingroup BoxModel
+ * \ingroup BoxFluxVariables
+ * \brief Evaluates the normal component of the Darcy velocity 
+ * on a (sub)control volume face.
+ */
+template <class TypeTag>
+class BoxDarcyFluxVariables
+{
+    typedef typename GET_PROP_TYPE(TypeTag, Problem) Problem;
+    typedef typename GET_PROP_TYPE(TypeTag, SpatialParams) SpatialParams;
+    typedef typename GET_PROP_TYPE(TypeTag, ElementVolumeVariables) ElementVolumeVariables;
+    typedef typename GET_PROP_TYPE(TypeTag, VolumeVariables) VolumeVariables;
+    
+    typedef typename GET_PROP_TYPE(TypeTag, GridView) GridView;
+    typedef typename GridView::template Codim<0>::Entity Element;
+
+    enum { dim = GridView::dimension} ;
+    enum { dimWorld = GridView::dimensionworld} ;
+    enum { numPhases = GET_PROP_VALUE(TypeTag, NumPhases)} ;
+
+    typedef typename GET_PROP_TYPE(TypeTag, Scalar) Scalar;
+    typedef Dune::FieldMatrix<Scalar, dimWorld, dimWorld> Tensor;
+    typedef Dune::FieldVector<Scalar, dimWorld> DimVector;
+
+    typedef typename GET_PROP_TYPE(TypeTag, FVElementGeometry) FVElementGeometry;
+    typedef typename FVElementGeometry::SubControlVolumeFace SCVFace;
+
+public:
+    /*
+     * \brief The constructor
+     *
+     * \param problem The problem
+     * \param element The finite element
+     * \param fvGeometry The finite-volume geometry in the box scheme
+     * \param faceIdx The local index of the SCV (sub-control-volume) face
+     * \param elemVolVars The volume variables of the current element
+     * \param onBoundary A boolean variable to specify whether the flux variables
+     * are calculated for interior SCV faces or boundary faces, default=false
+     */
+    BoxDarcyFluxVariables(const Problem &problem,
+                 const Element &element,
+                 const FVElementGeometry &fvGeometry,
+                 const int faceIdx,
+                 const ElementVolumeVariables &elemVolVars,
+                 const bool onBoundary = false)
+        : fvGeometry_(fvGeometry), faceIdx_(faceIdx), onBoundary_(onBoundary)
+    {
+        mobilityUpwindWeight_ = GET_PARAM_FROM_GROUP(TypeTag, Scalar, Implicit, MobilityUpwindWeight);
+        calculateGradients_(problem, element, elemVolVars);
+        calculateNormalVelocity_(problem, element, elemVolVars);
+    }
+
+public:
+    /*!
+     * \brief Return the volumetric flux over a face of a given phase.
+     *
+     *        This is the calculated velocity multiplied by the unit normal
+     *        and the area of the face.
+     *        face().normal
+     *        has already the magnitude of the area.
+     *
+     * \param phaseIdx index of the phase
+     */
+    Scalar volumeFlux(const unsigned int phaseIdx) const
+    { return volumeFlux_[phaseIdx]; }
+    
+    /*!
+     * \brief Return the velocity of a given phase.
+     *
+     *        This is the full velocity vector on the
+     *        face (without being multiplied with normal).
+     *
+     * \param phaseIdx index of the phase
+     */
+    DimVector velocity(const unsigned int phaseIdx) const
+    { return velocity_[phaseIdx] ; }
+
+    /*!
+     * \brief Return intrinsic permeability multiplied with potential
+     *        gradient multiplied with normal.
+     *        I.e. everything that does not need upwind decisions.
+     *
+     * \param phaseIdx index of the phase
+     */
+    Scalar kGradPNormal(const unsigned int phaseIdx) const
+    { return kGradPNormal_[phaseIdx] ; }
+
+    /*!
+     * \brief Return the local index of the downstream control volume
+     *        for a given phase.
+     *
+     * \param phaseIdx index of the phase
+     */
+    const unsigned int downstreamIdx(const unsigned phaseIdx) const
+    { return downstreamIdx_[phaseIdx]; }
+    
+    /*!
+     * \brief Return the local index of the upstream control volume
+     *        for a given phase.
+     *
+     * \param phaseIdx index of the phase
+     */
+    const unsigned int upstreamIdx(const unsigned phaseIdx) const
+    { return upstreamIdx_[phaseIdx]; }
+
+    /*!
+     * \brief Return the SCV (sub-control-volume) face. This may be either
+     *        a face within the element or a face on the element boundary,
+     *        depending on the value of onBoundary_.
+     */
+    const SCVFace &face() const
+    {
+        if (onBoundary_)
+            return fvGeometry_.boundaryFace[faceIdx_];
+        else
+            return fvGeometry_.subContVolFace[faceIdx_];
+    }
+
+protected:
+    const FVElementGeometry &fvGeometry_;   //!< Information about the geometry of discretization
+    const unsigned int faceIdx_;            //!< The index of the sub control volume face
+    const bool      onBoundary_;                //!< Specifying whether we are currently on the boundary of the simulation domain
+    unsigned int    upstreamIdx_[numPhases] , downstreamIdx_[numPhases]; //!< local index of the upstream / downstream vertex
+    Scalar          volumeFlux_[numPhases] ;    //!< Velocity multiplied with normal (magnitude=area)
+    DimVector       velocity_[numPhases] ;      //!< The velocity as determined by Darcy's law or by the Forchheimer relation
+    Scalar          kGradPNormal_[numPhases] ;  //!< Permeability multiplied with gradient in potential, multiplied with normal (magnitude=area)
+    DimVector       kGradP_[numPhases] ; //!< Permeability multiplied with gradient in potential
+    DimVector       gradPotential_[numPhases] ; //!< Gradient of potential, which drives flow
+    Scalar          mobilityUpwindWeight_;      //!< Upwind weight for mobility. Set to one for full upstream weighting
+
+    /*
+     * \brief Calculation of the potential gradients
+     *
+     * \param problem The problem
+     * \param element The finite element
+     * \param elemVolVars The volume variables of the current element
+     * are calculated for interior SCV faces or boundary faces, default=false
+     */
+    void calculateGradients_(const Problem &problem,
+                             const Element &element,
+                             const ElementVolumeVariables &elemVolVars)
+    {
+        // loop over all phases
+        for (int phaseIdx = 0; phaseIdx < numPhases; phaseIdx++)
+        {
+            gradPotential_[phaseIdx]= 0.0 ;
+            for (int idx = 0;
+                 idx < fvGeometry_.numFAP;
+                 idx++) // loop over adjacent vertices
+            {
+                // FE gradient at vertex idx
+                const DimVector &feGrad = face().grad[idx];
+
+                // index for the element volume variables
+                int volVarsIdx = face().fapIndices[idx];
+
+                // the pressure gradient
+                DimVector tmp(feGrad);
+                tmp *= elemVolVars[volVarsIdx].fluidState().pressure(phaseIdx);
+                gradPotential_[phaseIdx] += tmp;
+            }
+
+            // correct the pressure gradient by the gravitational acceleration
+            if (GET_PARAM_FROM_GROUP(TypeTag, bool, Problem, EnableGravity))
+            {
+                // estimate the gravitational acceleration at a given SCV face
+                // using the arithmetic mean
+                DimVector g(problem.boxGravity(element, fvGeometry_, face().i));
+                g += problem.boxGravity(element, fvGeometry_, face().j);
+                g /= 2;
+
+                // calculate the phase density at the integration point. we
+                // only do this if the wetting phase is present in both cells
+                Scalar SI = elemVolVars[face().i].fluidState().saturation(phaseIdx);
+                Scalar SJ = elemVolVars[face().j].fluidState().saturation(phaseIdx);
+                Scalar rhoI = elemVolVars[face().i].fluidState().density(phaseIdx);
+                Scalar rhoJ = elemVolVars[face().j].fluidState().density(phaseIdx);
+                Scalar fI = std::max(0.0, std::min(SI/1e-5, 0.5));
+                Scalar fJ = std::max(0.0, std::min(SJ/1e-5, 0.5));
+                if (fI + fJ == 0)
+                    // doesn't matter because no wetting phase is present in
+                    // both cells!
+                    fI = fJ = 0.5;
+                const Scalar density = (fI*rhoI + fJ*rhoJ)/(fI + fJ);
+
+                // make gravity acceleration a force
+                DimVector f(g);
+                f *= density;
+
+                // calculate the final potential gradient
+                gradPotential_[phaseIdx] -= f;
+            } // gravity
+        } // loop over all phases
+     }
+
+    /*
+     * \brief Actual calculation of the normal Darcy velocities.
+     *
+     * \param problem The problem
+     * \param element The finite element
+     * \param elemVolVars The volume variables of the current element
+     */
+    void calculateNormalVelocity_(const Problem &problem,
+                                  const Element &element,
+                                  const ElementVolumeVariables &elemVolVars)
+    {
+        // calculate the mean intrinsic permeability
+        const SpatialParams &spatialParams = problem.spatialParams();
+        Tensor K;
+        spatialParams.meanK(K,
+                            spatialParams.intrinsicPermeability(element,
+                                                                fvGeometry_,
+                                                                face().i),
+                            spatialParams.intrinsicPermeability(element,
+                                                                fvGeometry_,
+                                                                face().j));
+        // loop over all phases
+        for (int phaseIdx = 0; phaseIdx < numPhases; phaseIdx++)
+        {
+            // calculate the flux in the normal direction of the
+            // current sub control volume face:
+            //
+            // v = - (K_f grad phi) * n
+            // with K_f = rho g / mu K
+            //
+            // Mind, that the normal has the length of it's area.
+            // This means that we are actually calculating
+            //  Q = - (K grad phi) dot n /|n| * A
+
+
+            K.mv(gradPotential_[phaseIdx], kGradP_[phaseIdx]);
+            kGradPNormal_[phaseIdx] = kGradP_[phaseIdx]*face().normal;
+
+            // determine the upwind direction
+            if (kGradPNormal_[phaseIdx] < 0)
+            {
+                upstreamIdx_[phaseIdx] = face().i;
+                downstreamIdx_[phaseIdx] = face().j;
+            }
+            else
+            {
+                upstreamIdx_[phaseIdx] = face().j;
+                downstreamIdx_[phaseIdx] = face().i;
+            }
+            
+            // obtain the upwind volume variables
+            const VolumeVariables& upVolVars = elemVolVars[ upstreamIdx(phaseIdx) ];
+            const VolumeVariables& downVolVars = elemVolVars[ downstreamIdx(phaseIdx) ];
+
+            // the minus comes from the Darcy relation which states that
+            // the flux is from high to low potentials.
+            // set the velocity
+            velocity_[phaseIdx] = kGradP_[phaseIdx];
+            velocity_[phaseIdx] *= - ( mobilityUpwindWeight_*upVolVars.mobility(phaseIdx)
+                    + (1.0 - mobilityUpwindWeight_)*downVolVars.mobility(phaseIdx)) ;
+
+            // set the volume flux
+            volumeFlux_[phaseIdx] = velocity_[phaseIdx] * face().normal ;
+        }// loop all phases
+    }
+};
+
+} // end namespace
+
+#endif
diff --git a/dumux/implicit/common/implicitelementboundarytypes.hh b/dumux/implicit/common/implicitelementboundarytypes.hh
new file mode 100644
index 0000000000..fe7e02a09c
--- /dev/null
+++ b/dumux/implicit/common/implicitelementboundarytypes.hh
@@ -0,0 +1,148 @@
+// -*- mode: C++; tab-width: 4; indent-tabs-mode: nil; c-basic-offset: 4 -*-
+// vi: set et ts=4 sw=4 sts=4:
+/*****************************************************************************
+ *   See the file COPYING for full copying permissions.                      *
+ *                                                                           *
+ *   This program is free software: you can redistribute it and/or modify    *
+ *   it under the terms of the GNU General Public License as published by    *
+ *   the Free Software Foundation, either version 2 of the License, or       *
+ *   (at your option) any later version.                                     *
+ *                                                                           *
+ *   This program is distributed in the hope that it will be useful,         *
+ *   but WITHOUT ANY WARRANTY; without even the implied warranty of          *
+ *   MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the            *
+ *   GNU General Public License for more details.                            *
+ *                                                                           *
+ *   You should have received a copy of the GNU General Public License       *
+ *   along with this program.  If not, see <http://www.gnu.org/licenses/>.   *
+ *****************************************************************************/
+/*!
+ * \file
+ *
+ * \brief Boundary types gathered on an element
+ */
+#ifndef DUMUX_BOX_ELEMENT_BOUNDARY_TYPES_HH
+#define DUMUX_BOX_ELEMENT_BOUNDARY_TYPES_HH
+
+#include "boxproperties.hh"
+
+#include <dumux/common/valgrind.hh>
+
+namespace Dumux
+{
+
+/*!
+ * \ingroup BoxModel
+ * \ingroup BoxBoundaryTypes
+ *
+ * \brief This class stores an array of BoundaryTypes objects
+ */
+template<class TypeTag>
+class BoxElementBoundaryTypes : public std::vector<typename GET_PROP_TYPE(TypeTag, BoundaryTypes) >
+{
+    typedef typename GET_PROP_TYPE(TypeTag, BoundaryTypes) BoundaryTypes;
+    typedef std::vector<BoundaryTypes> ParentType;
+
+    typedef typename GET_PROP_TYPE(TypeTag, Problem) Problem;
+    typedef typename GET_PROP_TYPE(TypeTag, GridView) GridView;
+    typedef typename GET_PROP_TYPE(TypeTag, FVElementGeometry) FVElementGeometry;
+
+    enum { dim = GridView::dimension };
+    typedef typename GridView::template Codim<0>::Entity Element;
+    typedef typename GridView::template Codim<dim>::EntityPointer VertexPointer;
+
+public:
+    /*!
+     * \brief Copy constructor.
+     *
+     * Copying a the boundary types of an element should be explicitly
+     * requested
+     */
+    explicit BoxElementBoundaryTypes(const BoxElementBoundaryTypes &v)
+        : ParentType(v)
+    {}
+
+    /*!
+     * \brief Default constructor.
+     */
+    BoxElementBoundaryTypes()
+    {
+        hasDirichlet_ = false;
+        hasNeumann_ = false;
+        hasOutflow_ = false;
+    }
+
+    /*!
+     * \brief Update the boundary types for all vertices of an element.
+     *
+     * \param problem The problem object which needs to be simulated
+     * \param element The DUNE Codim<0> entity for which the boundary
+     *                types should be collected
+     */
+    void update(const Problem &problem,
+                const Element &element)
+    {
+        int numVerts = element.template count<dim>();
+        this->resize(numVerts);
+
+        hasDirichlet_ = false;
+        hasNeumann_ = false;
+        hasOutflow_ = false;
+
+        for (int i = 0; i < numVerts; ++i) {
+            (*this)[i].reset();
+
+            if (problem.model().onBoundary(element, i)) {
+                const VertexPointer vptr = element.template subEntity<dim>(i);
+                problem.boundaryTypes((*this)[i], *vptr);
+
+                hasDirichlet_ = hasDirichlet_ || (*this)[i].hasDirichlet();
+                hasNeumann_ = hasNeumann_ || (*this)[i].hasNeumann();
+                hasOutflow_ = hasOutflow_ || (*this)[i].hasOutflow();
+            }
+        }
+    }
+
+    /*!
+     * \brief Update the boundary types for all vertices of an element.
+     *
+     * \param problem The problem object which needs to be simulated
+     * \param element The DUNE Codim<0> entity for which the boundary
+     *                types should be collected
+     * \param fvGeometry The element's finite volume geometry
+     */
+    void update(const Problem &problem,
+                const Element &element,
+                const FVElementGeometry &fvGeometry)
+    { update(problem, element); }
+    
+    /*!
+     * \brief Returns whether the element has a vertex which contains
+     *        a Dirichlet value.
+     */
+    bool hasDirichlet() const
+    { return hasDirichlet_; }
+
+    /*!
+     * \brief Returns whether the element potentially features a
+     *        Neumann boundary segment.
+     */
+    bool hasNeumann() const
+    { return hasNeumann_; }
+
+    /*!
+     * \brief Returns whether the element potentially features an
+     *        outflow boundary segment.
+     */
+    bool hasOutflow() const
+    { return hasOutflow_; }
+
+protected:
+    bool hasDirichlet_;
+    bool hasNeumann_;
+    bool hasOutflow_;
+};
+
+} // namespace Dumux
+
+#endif
diff --git a/dumux/implicit/common/implicitelementvolumevariables.hh b/dumux/implicit/common/implicitelementvolumevariables.hh
new file mode 100644
index 0000000000..c791bee09b
--- /dev/null
+++ b/dumux/implicit/common/implicitelementvolumevariables.hh
@@ -0,0 +1,138 @@
+// -*- mode: C++; tab-width: 4; indent-tabs-mode: nil; c-basic-offset: 4 -*-
+// vi: set et ts=4 sw=4 sts=4:
+/*****************************************************************************
+ *   See the file COPYING for full copying permissions.                      *
+ *                                                                           *
+ *   This program is free software: you can redistribute it and/or modify    *
+ *   it under the terms of the GNU General Public License as published by    *
+ *   the Free Software Foundation, either version 2 of the License, or       *
+ *   (at your option) any later version.                                     *
+ *                                                                           *
+ *   This program is distributed in the hope that it will be useful,         *
+ *   but WITHOUT ANY WARRANTY; without even the implied warranty of          *
+ *   MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the            *
+ *   GNU General Public License for more details.                            *
+ *                                                                           *
+ *   You should have received a copy of the GNU General Public License       *
+ *   along with this program.  If not, see <http://www.gnu.org/licenses/>.   *
+ *****************************************************************************/
+/*!
+ * \file
+ *
+ * \brief Volume variables gathered on an element
+ */
+#ifndef DUMUX_BOX_ELEMENT_VOLUME_VARIABLES_HH
+#define DUMUX_BOX_ELEMENT_VOLUME_VARIABLES_HH
+
+#include "boxproperties.hh"
+
+
+namespace Dumux
+{
+
+/*!
+ * \ingroup BoxModel
+ *
+ * \brief This class stores an array of VolumeVariables objects, one
+ *        volume variables object for each of the element's vertices
+ */
+template<class TypeTag>
+class BoxElementVolumeVariables : public std::vector<typename GET_PROP_TYPE(TypeTag, VolumeVariables) >
+{
+    typedef typename GET_PROP_TYPE(TypeTag, Problem) Problem;
+    typedef typename GET_PROP_TYPE(TypeTag, FVElementGeometry) FVElementGeometry;
+    typedef typename GET_PROP_TYPE(TypeTag, SolutionVector) SolutionVector;
+    typedef typename GET_PROP_TYPE(TypeTag, VertexMapper) VertexMapper;
+    typedef typename GET_PROP_TYPE(TypeTag, PrimaryVariables) PrimaryVariables;
+
+    typedef typename GET_PROP_TYPE(TypeTag, GridView) GridView;
+    typedef typename GridView::template Codim<0>::Entity Element;
+
+    enum { dim = GridView::dimension };
+    enum { numEq = GET_PROP_VALUE(TypeTag, NumEq) };
+
+public:
+    /*!
+     * \brief The constructor.
+     */
+    BoxElementVolumeVariables()
+    { }
+
+    /*!
+     * \brief Construct the volume variables for all of vertices of an element.
+     *
+     * \param problem The problem which needs to be simulated.
+     * \param element The DUNE Codim<0> entity for which the volume variables ought to be calculated
+     * \param fvGeometry The finite volume geometry of the element
+     * \param oldSol Tells whether the model's previous or current solution should be used.
+     */
+    void update(const Problem &problem,
+                const Element &element,
+                const FVElementGeometry &fvGeometry,
+                const bool oldSol)
+    {
+        const SolutionVector &globalSol =
+            oldSol?
+            problem.model().prevSol():
+            problem.model().curSol();
+        const VertexMapper &vertexMapper = problem.vertexMapper();
+        // we assert that the i-th shape function is
+        // associated to the i-th vert of the element.
+        int numVertices = element.template count<dim>();
+        this->resize(numVertices);
+        for (int scvIdx = 0; scvIdx < numVertices; scvIdx++) {
+            const PrimaryVariables &priVars
+                = globalSol[vertexMapper.map(element, scvIdx, dim)];
+
+            // reset evaluation point to zero
+            (*this)[scvIdx].setEvalPoint(0);
+
+            (*this)[scvIdx].update(priVars,
+                              problem,
+                              element,
+                              fvGeometry,
+                              scvIdx,
+                              oldSol);
+        }
+    }
+
+    /*!
+     * \brief Construct the volume variables for all of vertices of an
+     *        element given a solution vector computed by PDELab.
+     *
+     * \tparam ElementSolutionVector The container type which stores the
+     *                           primary variables of the element
+     *                           using _local_ indices
+     *
+     * \param problem The problem which needs to be simulated.
+     * \param element The DUNE Codim<0> entity for which the volume variables ought to be calculated
+     * \param fvGeometry The finite volume geometry of the element
+     * \param elementSolVector The local solution for the element using PDELab ordering
+     */
+    template<typename ElementSolutionVector>
+    void updatePDELab(const Problem &problem,
+                      const Element &element,
+                      const FVElementGeometry &fvGeometry,
+                      const ElementSolutionVector& elementSolVector)
+    {
+        int numVertices = element.template count<dim>();
+        this->resize(numVertices);
+        for (int scvIdx = 0; scvIdx < numVertices; scvIdx++)
+        {
+            PrimaryVariables priVars(0);
+            for (int eqnIdx = 0; eqnIdx < numEq; eqnIdx++)
+                priVars[eqnIdx] = elementSolVector[scvIdx + eqnIdx*numVertices];
+            (*this)[scvIdx].update(priVars,
+                                      problem,
+                                      element,
+                                      fvGeometry,
+                                      scvIdx,
+                                      false);
+
+        }
+    }
+};
+
+} // namespace Dumux
+
+#endif
diff --git a/dumux/implicit/common/implicitforchheimerfluxvariables.hh b/dumux/implicit/common/implicitforchheimerfluxvariables.hh
new file mode 100644
index 0000000000..e7f7e3bf32
--- /dev/null
+++ b/dumux/implicit/common/implicitforchheimerfluxvariables.hh
@@ -0,0 +1,358 @@
+// -*- mode: C++; tab-width: 4; indent-tabs-mode: nil; c-basic-offset: 4 -*-
+// vi: set et ts=4 sw=4 sts=4:
+/*****************************************************************************
+ *   See the file COPYING for full copying permissions.                      *
+ *                                                                           *
+ *   This program is free software: you can redistribute it and/or modify    *
+ *   it under the terms of the GNU General Public License as published by    *
+ *   the Free Software Foundation, either version 2 of the License, or       *
+ *   (at your option) any later version.                                     *
+ *                                                                           *
+ *   This program is distributed in the hope that it will be useful,         *
+ *   but WITHOUT ANY WARRANTY; without even the implied warranty of          *
+ *   MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the            *
+ *   GNU General Public License for more details.                            *
+ *                                                                           *
+ *   You should have received a copy of the GNU General Public License       *
+ *   along with this program.  If not, see <http://www.gnu.org/licenses/>.   *
+ *****************************************************************************/
+/*!
+ * \file
+ *
+ * \brief This file contains the data which is required to calculate
+ *        all fluxes of fluid phases over a face of a finite volume,
+ *        according to the Forchheimer-relation between velocity and pressure.
+ *
+ */
+#ifndef DUMUX_BOX_FORCHHEIMER_FLUX_VARIABLES_HH
+#define DUMUX_BOX_FORCHHEIMER_FLUX_VARIABLES_HH
+
+#include "boxproperties.hh"
+
+#include <dumux/common/parameters.hh>
+#include <dumux/common/math.hh>
+#include <dumux/boxmodels/common/boxdarcyfluxvariables.hh>
+
+namespace Dumux
+{
+    
+namespace Properties
+{
+// forward declaration of properties 
+NEW_PROP_TAG(MobilityUpwindWeight);
+NEW_PROP_TAG(SpatialParams);
+NEW_PROP_TAG(NumPhases);
+NEW_PROP_TAG(ProblemEnableGravity);
+}   
+
+/*!
+ * \ingroup BoxModel
+ * \ingroup BoxFluxVariables
+ * \brief Evaluates the normal component of the Forchheimer velocity
+ *        on a (sub)control volume face.
+ *
+ *        The commonly used Darcy relation looses it's validity for \f$ Re < 1\f$.
+ *        If one encounters flow velocities in porous media above this Reynolds number,
+ *        the Forchheimer relation can be used. Like the Darcy relation, it relates
+ *        the gradient in potential to velocity.
+ *        However, this relation is not linear (as in the Darcy case) any more.
+ *
+ *        Therefore, a Newton scheme is implemented in this class in order to calculate a
+ *        velocity from the current set of variables. This velocity can subsequently be used
+ *        e.g. by the localresidual.
+ *
+ *        For Reynolds numbers above \f$ 500\f$ the (Standard) forchheimer relation also
+ *        looses it's validity.
+ *
+ *        The Forchheimer equation looks as follows:
+ *         \f[ \nabla \left({p_\alpha + \rho_\alpha g z} \right)=  - \frac{\mu_\alpha}{k_{r \alpha} K} \underline{v_\alpha} - \frac{c_F}{\eta_{\alpha r} \sqrt{K}} \rho_\alpha |\underline{v_\alpha}| \underline{v_\alpha} \f]
+ *
+ *        For the formulation that is actually used in this class, see the documentation of the function calculating the residual.
+ *
+ *        - This algorithm does not find a solution if the fluid is incompressible and the
+ *          initial pressure distribution is uniform.
+ *        - This algorithm assumes the relative passabilities to have the same functional
+ *          form as the relative permeabilities.
+ */
+template <class TypeTag>
+class BoxForchheimerFluxVariables
+    : public BoxDarcyFluxVariables<TypeTag>
+{
+    typedef typename GET_PROP_TYPE(TypeTag, Problem) Problem;
+    typedef typename GET_PROP_TYPE(TypeTag, SpatialParams) SpatialParams;
+    typedef typename GET_PROP_TYPE(TypeTag, ElementVolumeVariables) ElementVolumeVariables;
+    typedef typename GET_PROP_TYPE(TypeTag, VolumeVariables) VolumeVariables;
+    typedef typename GET_PROP_TYPE(TypeTag, GridView) GridView;
+    typedef typename GridView::template Codim<0>::Entity Element;
+
+    enum { dim = GridView::dimension} ;
+    enum { dimWorld = GridView::dimensionworld} ;
+    enum { numPhases = GET_PROP_VALUE(TypeTag, NumPhases)} ;
+
+    typedef typename GET_PROP_TYPE(TypeTag, Scalar) Scalar;
+    typedef Dune::FieldMatrix<Scalar, dimWorld, dimWorld> Tensor;
+    typedef Dune::FieldVector<Scalar, dimWorld> DimVector;
+    typedef typename GET_PROP_TYPE(TypeTag, FVElementGeometry) FVElementGeometry;
+    typedef typename FVElementGeometry::SubControlVolumeFace SCVFace;
+
+public:
+    /*!
+     * \brief The constructor
+     *
+     * \param problem The problem
+     * \param element The finite element
+     * \param fvGeometry The finite-volume geometry in the box scheme
+     * \param faceIdx The local index of the SCV (sub-control-volume) face
+     * \param elemVolVars The volume variables of the current element
+     * \param onBoundary A boolean variable to specify whether the flux variables
+     * are calculated for interior SCV faces or boundary faces, default=false
+     */
+    BoxForchheimerFluxVariables(const Problem &problem,
+                 const Element &element,
+                 const FVElementGeometry &fvGeometry,
+                 const unsigned int faceIdx,
+                 const ElementVolumeVariables &elemVolVars,
+                 const bool onBoundary = false)
+        :   BoxDarcyFluxVariables<TypeTag>(problem, element, fvGeometry, faceIdx, elemVolVars, onBoundary)
+    {
+        calculateNormalVelocity_(problem, element, elemVolVars);
+    }
+
+protected:
+    /*!
+     * \brief Function for calculation of velocities.
+     *
+     * \param problem The problem
+     * \param element The finite element
+     * \param elemVolVars The volume variables of the current element
+     */
+    void calculateNormalVelocity_(const Problem &problem,
+                                  const Element &element,
+                                  const ElementVolumeVariables &elemVolVars)
+    {
+        // calculate the mean intrinsic permeability
+        const SpatialParams &spatialParams = problem.spatialParams();
+        Tensor K;
+        spatialParams.meanK(K,
+                            spatialParams.intrinsicPermeability(element,
+                                                                this->fvGeometry_,
+                                                                this->face().i),
+                            spatialParams.intrinsicPermeability(element,
+                                                                this->fvGeometry_,
+                                                                this->face().j));
+
+        // obtain the Forchheimer coefficient from the spatial parameters
+        const Scalar forchCoeff = spatialParams.forchCoeff(element,
+                                                          this->fvGeometry_,
+                                                          this->face().i);
+
+        // Make sure the permeability matrix does not have off-diagonal entries
+        assert( isDiagonal_(K) );
+
+        Tensor sqrtK(0.0);
+        for (int i = 0; i < dim; ++i)
+            sqrtK[i][i] = std::sqrt(K[i][i]);
+
+        // loop over all phases
+        for (int phaseIdx = 0; phaseIdx < numPhases; phaseIdx++)
+        {
+            // initial guess of velocity: Darcy relation
+            // first taken from base class, later overwritten in base class
+            DimVector velocity = this-> velocity(phaseIdx);
+
+            DimVector deltaV;           // the change in velocity between Newton iterations
+            DimVector residual(10e10);  // the residual (function value that is to be minimized ) of the equation that is to be fulfilled
+            DimVector tmp;              // temporary variable for numerical differentiation
+            Tensor    gradF;            // slope of equation that is to be solved
+
+            // search by means of the Newton method for a root of Forchheimer equation
+            for (int k = 0; residual.two_norm() > 1e-12 ; ++k) {
+
+                if (k >= 30)
+                    DUNE_THROW(NumericalProblem, "could not determine forchheimer velocity within "<< k <<" iterations");
+
+                // calculate current value of Forchheimer equation
+                forchheimerResidual_(residual,
+                                    forchCoeff,
+                                    sqrtK,
+                                    K,
+                                    velocity,
+                                    elemVolVars,
+                                    this->gradPotential_[phaseIdx],
+                                    phaseIdx);
+
+                // newton's method: slope (gradF) and current value (residual) of function is known,
+                forchheimerDerivative_(gradF,
+                                       forchCoeff,
+                                       sqrtK,
+                                       velocity,
+                                       elemVolVars,
+                                       phaseIdx);
+
+                // solve for change in velocity ("x-Axis intercept")
+                gradF.solve(deltaV, residual);
+                velocity -= deltaV;
+            }
+
+            this->velocity_[phaseIdx]     =  velocity ;                  // store the converged velocity solution
+            this->volumeFlux_[phaseIdx]   =  velocity * this->face().normal; // velocity dot normal times cross sectional area is volume flux
+        }// end loop over all phases
+    }
+
+    /*! \brief Function for calculation of Forchheimer relation.
+     *
+     *  The relative passability \f$ \eta_r\f$ is the "Forchheimer-equivalent" to the relative permeability \f$ k_r\f$.
+     *  We use the same function as for \f$ k_r \f$ (VG, BC, linear) other authors use a simple power law e.g.: \f$\eta_{rw} = S_w^3\f$
+     *
+     *  Some rearrangements have been made to the original Forchheimer relation:
+     *
+     * \f[  \underline{v_\alpha} + c_F \sqrt{K} \frac{\rho_\alpha}{\mu_\alpha } |\underline{v_\alpha}| \underline{v_\alpha} + \frac{k_{r \alpha}}{\mu_\alpha} K \nabla \left(p_\alpha + \rho_\alpha g z \right)=  0 \f]
+     *
+     * This already includes the assumption \f$ k_r(S_w) = \eta_r(S_w)\f$:
+     * - \f$\eta_{rw} = S_w^x\f$ looks very similar to e.g. Van Genuchten relative permeabilities
+     * - Fichot, et al. (2006), Nuclear Engineering and Design, state that several authors claim that \f$ k_r(S_w), \eta_r(S_w)\f$ can be chosen equal
+     * - It leads to the equation not degenerating for the case of \f$S_w=1\f$, because I do not need to multiply with two different functions, and therefore there are terms not being zero.
+     * - If this assumption is not to be made: Some regularization needs to be introduced ensuring that not all terms become zero for \f$S_w=1\f$.
+     *
+     *  As long as the correct velocity is not found yet, the above equation is not fulfilled, but
+     *  the left hand side yields some residual. This function calculates the left hand side of the
+     *  equation and returns the residual.
+     *
+     * \param residual The current function value for the given velocity
+     * \param forchCoeff The Forchheimer coefficient
+     * \param sqrtK A diagonal matrix whose entries are square roots of the permeability matrix entries
+     * \param K The permeability matrix
+     * \param velocity The current velocity approximation.
+     * \param elemVolVars The volume variables of the current element
+     * \param gradPotential The gradient in potential
+     * \param phaseIdx The index of the currently considered phase
+     */
+     void forchheimerResidual_(DimVector & residual,
+         const Scalar forchCoeff,
+         const Tensor & sqrtK,
+         const Tensor & K,
+         const DimVector & velocity,
+         const ElementVolumeVariables & elemVolVars,
+         const DimVector & gradPotential ,
+         const unsigned int phaseIdx) const
+     {
+         const VolumeVariables upVolVars    = elemVolVars[this->upstreamIdx(phaseIdx)];
+         const VolumeVariables downVolVars  = elemVolVars[this->downstreamIdx(phaseIdx)];
+
+         // Obtaining the physical quantities
+         const Scalar mobility = this->mobilityUpwindWeight_ * upVolVars.mobility(phaseIdx)
+                 + (1.-this->mobilityUpwindWeight_)*  downVolVars.mobility(phaseIdx) ;
+
+         const Scalar viscosity = this->mobilityUpwindWeight_ * upVolVars.fluidState().viscosity(phaseIdx)
+                 + (1.-this->mobilityUpwindWeight_)*  downVolVars.fluidState().viscosity(phaseIdx) ;
+
+         const Scalar density = this->mobilityUpwindWeight_ * upVolVars.fluidState().density(phaseIdx)
+                 + (1.-this->mobilityUpwindWeight_) * downVolVars.fluidState().density(phaseIdx) ;
+
+         // residual  = v
+         residual = velocity;
+
+         // residual += k_r/mu  K grad p
+         K.usmv(mobility, gradPotential, residual);
+
+         // residual += c_F rho / mu abs(v) sqrt(K) v
+         sqrtK.usmv(forchCoeff * density / viscosity * velocity.two_norm(), velocity, residual);
+     }
+
+
+     /*! \brief Function for calculation of the gradient of Forchheimer relation with respect to velocity.
+      *
+      *  This function already exploits that \f$ \sqrt{K}\f$ is a diagonal matrix. Therefore, we only have
+      *  to deal with the main entries.
+      *  The gradient of the Forchheimer relations looks as follows (mind that \f$ \sqrt{K}\f$ is a tensor):
+      *
+      * \f[  f\left(\underline{v_\alpha}\right) =
+      * \left(
+      * \begin{array}{ccc}
+      * 1 & 0 &0 \\
+      * 0 & 1 &0 \\
+      * 0 & 0 &1 \\
+      * \end{array}
+      * \right)
+      * +
+      * c_F \frac{\rho_\alpha}{\mu_\alpha} |\underline{v}_\alpha| \sqrt{K}
+      * +
+      * c_F \frac{\rho_\alpha}{\mu_\alpha}\frac{1}{|\underline{v}_\alpha|} \sqrt{K}
+      * \left(
+      * \begin{array}{ccc}
+      * v_x^2 & v_xv_y & v_xv_z \\
+      * v_yv_x & v_{y}^2 & v_yv_z \\
+      * v_zv_x & v_zv_y &v_{z}^2 \\
+      * \end{array}
+      * \right)
+      *  \f]
+      *
+      * \param derivative The gradient of the forchheimer equation
+      * \param forchCoeff Forchheimer coefficient
+      * \param sqrtK A diagonal matrix whose entries are square roots of the permeability matrix entries.
+      * \param velocity The current velocity approximation.
+      * \param elemVolVars The volume variables of the current element
+      * \param phaseIdx The index of the currently considered phase
+      */
+     void forchheimerDerivative_(Tensor & derivative,
+             const Scalar forchCoeff,
+             const Tensor & sqrtK,
+             const DimVector & velocity,
+             const ElementVolumeVariables & elemVolVars,
+             const unsigned int phaseIdx) const
+     {
+         const VolumeVariables upVolVars    = elemVolVars[this->upstreamIdx(phaseIdx)];
+         const VolumeVariables downVolVars  = elemVolVars[this->downstreamIdx(phaseIdx)];
+
+         // Obtaining the physical quantities
+         const Scalar viscosity = this->mobilityUpwindWeight_ * upVolVars.fluidState().viscosity(phaseIdx)
+                 + (1.-this->mobilityUpwindWeight_)*  downVolVars.fluidState().viscosity(phaseIdx) ;
+
+         const Scalar density = this->mobilityUpwindWeight_ * upVolVars.fluidState().density(phaseIdx)
+                 + (1.-this->mobilityUpwindWeight_) * downVolVars.fluidState().density(phaseIdx) ;
+
+         // Initialize because for low velocities, we add and do not set the entries.
+         derivative = 0.;
+
+         const Scalar absV = velocity.two_norm() ;
+         // This part of the derivative is only calculated if the velocity is sufficiently small: do not divide by zero!
+         // This should not be very bad because the derivative is only intended to give an approximation of the gradient of the
+         // function that goes into the Newton scheme.
+         // This is important in the case of a one-phase region in two-phase flow. The non-existing phase has a velocity of zero (kr=0).
+         // f = sqrtK * vTimesV (this is  a matrix)
+         // f *= forchCoeff density / |velocity| / viscosity (multiply all entries with scalars)
+         if(absV > 1e-20)
+             for (int i=0; i<dim; i++)
+                 for (int k=0; k<dim; k++)
+                     derivative[i][k]= sqrtK[i][i] * velocity[i] * velocity[k] * forchCoeff * density /  absV  / viscosity;
+
+         // add on the main diagonal:
+         // 1 + sqrtK_i forchCoeff density |v| / viscosity
+         for (int i=0; i<dim; i++)
+             derivative[i][i] += (1.0 + ( sqrtK[i][i]*forchCoeff * density * absV / viscosity ) ) ;
+     }
+
+     /*!
+      * \brief Check whether all off-diagonal entries of a tensor are zero.
+      *
+      * \param K the tensor that is to be checked.
+      *
+      * \return True iff all off-diagonals are zero.
+      *
+     */
+     const bool isDiagonal_(const Tensor & K) const
+     {
+         for (int i = 0; i < dim; i++) {
+             for (int k = 0; k < dim; k++) {
+                 if ((i != k) && (std::abs(K[i][k]) >= 1e-25)) {
+                   return false;
+                 }
+             }
+         }
+         return true;
+     }
+};
+
+} // end namespace
+
+#endif
diff --git a/dumux/implicit/common/implicitfvelementgeometry.hh b/dumux/implicit/common/implicitfvelementgeometry.hh
new file mode 100644
index 0000000000..fd0b5c89e2
--- /dev/null
+++ b/dumux/implicit/common/implicitfvelementgeometry.hh
@@ -0,0 +1,933 @@
+// -*- mode: C++; tab-width: 4; indent-tabs-mode: nil; c-basic-offset: 4 -*-
+// vi: set et ts=4 sw=4 sts=4:
+/*****************************************************************************
+ *   See the file COPYING for full copying permissions.                      *
+ *                                                                           *
+ *   This program is free software: you can redistribute it and/or modify    *
+ *   it under the terms of the GNU General Public License as published by    *
+ *   the Free Software Foundation, either version 2 of the License, or       *
+ *   (at your option) any later version.                                     *
+ *                                                                           *
+ *   This program is distributed in the hope that it will be useful,         *
+ *   but WITHOUT ANY WARRANTY; without even the implied warranty of          *
+ *   MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the            *
+ *   GNU General Public License for more details.                            *
+ *                                                                           *
+ *   You should have received a copy of the GNU General Public License       *
+ *   along with this program.  If not, see <http://www.gnu.org/licenses/>.   *
+ *****************************************************************************/
+/*!
+ * \file
+ *
+ * \brief Represents the finite volume geometry of a single element in
+ *        the box scheme.
+ */
+#ifndef DUMUX_BOX_FV_ELEMENTGEOMETRY_HH
+#define DUMUX_BOX_FV_ELEMENTGEOMETRY_HH
+
+#include <dune/common/version.hh>
+#include <dune/geometry/referenceelements.hh>
+#include <dune/grid/common/intersectioniterator.hh>
+#include <dune/localfunctions/lagrange/pqkfactory.hh>
+
+#include <dumux/common/parameters.hh>
+#include <dumux/common/propertysystem.hh>
+#include "boxproperties.hh"
+
+namespace Dumux
+{
+namespace Properties
+{
+NEW_PROP_TAG(GridView);
+NEW_PROP_TAG(Scalar);
+NEW_PROP_TAG(ImplicitUseTwoPointFlux);
+}
+
+/////////////////////
+// HACK: Functions to initialize the subcontrol volume data
+// structures of BoxFVElementGeomerty.
+//
+// this is a work around to be able to to use specialization for
+// doing this.  it is required since it is not possible to
+// specialize member functions of template classes because of some
+// weird reason I didn't really get...
+
+//! \cond INTERNAL
+
+template <typename BoxFVElementGeometry, int dim>
+class _BoxFVElemGeomHelper
+{
+public:
+    static void fillSubContVolData(BoxFVElementGeometry &eg, int numVertices)
+    {
+        DUNE_THROW(Dune::NotImplemented, "_BoxFVElemGeomHelper::fillSubContVolData dim = " << dim);
+    }
+};
+
+template <typename BoxFVElementGeometry>
+class _BoxFVElemGeomHelper<BoxFVElementGeometry, 1>
+{
+public:
+    enum { dim = 1 };
+    static void fillSubContVolData(BoxFVElementGeometry &eg, int numVertices)
+    {
+        // 1D
+        eg.subContVol[0].volume = 0.5*eg.elementVolume;
+        eg.subContVol[1].volume = 0.5*eg.elementVolume;
+    }
+};
+
+template <typename BoxFVElementGeometry>
+class _BoxFVElemGeomHelper<BoxFVElementGeometry, 2>
+{
+public:
+    enum { dim = 2 };
+
+    static void fillSubContVolData(BoxFVElementGeometry &eg, int numVertices)
+    {
+        switch (numVertices) {
+        case 3: // 2D, triangle
+            eg.subContVol[0].volume = eg.elementVolume/3;
+            eg.subContVol[1].volume = eg.elementVolume/3;
+            eg.subContVol[2].volume = eg.elementVolume/3;
+            break;
+        case 4: // 2D, quadrilinear
+            eg.subContVol[0].volume = eg.quadrilateralArea(eg.subContVol[0].global, eg.edgeCoord[2], eg.elementGlobal, eg.edgeCoord[0]);
+            eg.subContVol[1].volume = eg.quadrilateralArea(eg.subContVol[1].global, eg.edgeCoord[1], eg.elementGlobal, eg.edgeCoord[2]);
+            eg.subContVol[2].volume = eg.quadrilateralArea(eg.subContVol[2].global, eg.edgeCoord[0], eg.elementGlobal, eg.edgeCoord[3]);
+            eg.subContVol[3].volume = eg.quadrilateralArea(eg.subContVol[3].global, eg.edgeCoord[3], eg.elementGlobal, eg.edgeCoord[1]);
+            break;
+        default:
+            DUNE_THROW(Dune::NotImplemented, "_BoxFVElemGeomHelper::fillSubContVolData dim = " << dim << ", numVertices = " << numVertices);
+        }
+    }
+};
+
+template <typename BoxFVElementGeometry>
+class _BoxFVElemGeomHelper<BoxFVElementGeometry, 3>
+{
+public:
+    enum { dim = 3 };
+
+    static void fillSubContVolData(BoxFVElementGeometry &eg, int numVertices)
+    {
+        switch (numVertices) {
+        case 4: // 3D, tetrahedron
+            for (int k = 0; k < eg.numVertices; k++)
+                eg.subContVol[k].volume = eg.elementVolume / 4.0;
+            break;
+        case 5: // 3D, pyramid
+            eg.subContVol[0].volume = eg.hexahedronVolume(eg.subContVol[0].global,
+                                                          eg.edgeCoord[2],
+                                                          eg.faceCoord[0],
+                                                          eg.edgeCoord[0],
+                                                          eg.edgeCoord[4],
+                                                          eg.faceCoord[3],
+                                                          eg.elementGlobal,
+                                                          eg.faceCoord[1]);
+            eg.subContVol[1].volume = eg.hexahedronVolume(eg.subContVol[1].global,
+                                                          eg.edgeCoord[1],
+                                                          eg.faceCoord[0],
+                                                          eg.edgeCoord[2],
+                                                          eg.edgeCoord[5],
+                                                          eg.faceCoord[2],
+                                                          eg.elementGlobal,
+                                                          eg.faceCoord[3]);
+            eg.subContVol[2].volume = eg.hexahedronVolume(eg.subContVol[2].global,
+                                                          eg.edgeCoord[0],
+                                                          eg.faceCoord[0],
+                                                          eg.edgeCoord[3],
+                                                          eg.edgeCoord[6],
+                                                          eg.faceCoord[1],
+                                                          eg.elementGlobal,
+                                                          eg.faceCoord[4]);
+            eg.subContVol[3].volume = eg.hexahedronVolume(eg.subContVol[3].global,
+                                                          eg.edgeCoord[3],
+                                                          eg.faceCoord[0],
+                                                          eg.edgeCoord[1],
+                                                          eg.edgeCoord[7],
+                                                          eg.faceCoord[4],
+                                                          eg.elementGlobal,
+                                                          eg.faceCoord[2]);
+            eg.subContVol[4].volume = eg.elementVolume -
+                eg.subContVol[0].volume -
+                eg.subContVol[1].volume -
+                eg.subContVol[2].volume -
+                eg.subContVol[3].volume;
+            break;
+        case 6: // 3D, prism
+            eg.subContVol[0].volume = eg.hexahedronVolume(eg.subContVol[0].global,
+                                                          eg.edgeCoord[3],
+                                                          eg.faceCoord[3],
+                                                          eg.edgeCoord[4],
+                                                          eg.edgeCoord[0],
+                                                          eg.faceCoord[0],
+                                                          eg.elementGlobal,
+                                                          eg.faceCoord[1]);
+            eg.subContVol[1].volume = eg.hexahedronVolume(eg.subContVol[1].global,
+                                                          eg.edgeCoord[5],
+                                                          eg.faceCoord[3],
+                                                          eg.edgeCoord[3],
+                                                          eg.edgeCoord[1],
+                                                          eg.faceCoord[2],
+                                                          eg.elementGlobal,
+                                                          eg.faceCoord[0]);
+            eg.subContVol[2].volume = eg.hexahedronVolume(eg.subContVol[2].global,
+                                                          eg.edgeCoord[4],
+                                                          eg.faceCoord[3],
+                                                          eg.edgeCoord[5],
+                                                          eg.edgeCoord[2],
+                                                          eg.faceCoord[1],
+                                                          eg.elementGlobal,
+                                                          eg.faceCoord[2]);
+            eg.subContVol[3].volume = eg.hexahedronVolume(eg.edgeCoord[0],
+                                                          eg.faceCoord[0],
+                                                          eg.elementGlobal,
+                                                          eg.faceCoord[1],
+                                                          eg.subContVol[3].global,
+                                                          eg.edgeCoord[6],
+                                                          eg.faceCoord[4],
+                                                          eg.edgeCoord[7]);
+            eg.subContVol[4].volume = eg.hexahedronVolume(eg.edgeCoord[1],
+                                                          eg.faceCoord[2],
+                                                          eg.elementGlobal,
+                                                          eg.faceCoord[0],
+                                                          eg.subContVol[4].global,
+                                                          eg.edgeCoord[8],
+                                                          eg.faceCoord[4],
+                                                          eg.edgeCoord[6]);
+            eg.subContVol[5].volume = eg.hexahedronVolume(eg.edgeCoord[2],
+                                                          eg.faceCoord[1],
+                                                          eg.elementGlobal,
+                                                          eg.faceCoord[2],
+                                                          eg.subContVol[5].global,
+                                                          eg.edgeCoord[7],
+                                                          eg.faceCoord[4],
+                                                          eg.edgeCoord[8]);
+            break;
+        case 8: // 3D, hexahedron
+            eg.subContVol[0].volume = eg.hexahedronVolume(eg.subContVol[0].global,
+                                                          eg.edgeCoord[6],
+                                                          eg.faceCoord[4],
+                                                          eg.edgeCoord[4],
+                                                          eg.edgeCoord[0],
+                                                          eg.faceCoord[2],
+                                                          eg.elementGlobal,
+                                                          eg.faceCoord[0]);
+            eg.subContVol[1].volume = eg.hexahedronVolume(eg.subContVol[1].global,
+                                                          eg.edgeCoord[5],
+                                                          eg.faceCoord[4],
+                                                          eg.edgeCoord[6],
+                                                          eg.edgeCoord[1],
+                                                          eg.faceCoord[1],
+                                                          eg.elementGlobal,
+                                                          eg.faceCoord[2]);
+            eg.subContVol[2].volume = eg.hexahedronVolume(eg.subContVol[2].global,
+                                                          eg.edgeCoord[4],
+                                                          eg.faceCoord[4],
+                                                          eg.edgeCoord[7],
+                                                          eg.edgeCoord[2],
+                                                          eg.faceCoord[0],
+                                                          eg.elementGlobal,
+                                                          eg.faceCoord[3]);
+            eg.subContVol[3].volume = eg.hexahedronVolume(eg.subContVol[3].global,
+                                                          eg.edgeCoord[7],
+                                                          eg.faceCoord[4],
+                                                          eg.edgeCoord[5],
+                                                          eg.edgeCoord[3],
+                                                          eg.faceCoord[3],
+                                                          eg.elementGlobal,
+                                                          eg.faceCoord[1]);
+            eg.subContVol[4].volume = eg.hexahedronVolume(eg.edgeCoord[0],
+                                                          eg.faceCoord[2],
+                                                          eg.elementGlobal,
+                                                          eg.faceCoord[0],
+                                                          eg.subContVol[4].global,
+                                                          eg.edgeCoord[10],
+                                                          eg.faceCoord[5],
+                                                          eg.edgeCoord[8]);
+            eg.subContVol[5].volume = eg.hexahedronVolume(eg.edgeCoord[1],
+                                                          eg.faceCoord[1],
+                                                          eg.elementGlobal,
+                                                          eg.faceCoord[2],
+                                                          eg.subContVol[5].global,
+                                                          eg.edgeCoord[9],
+                                                          eg.faceCoord[5],
+                                                          eg.edgeCoord[10]);
+            eg.subContVol[6].volume = eg.hexahedronVolume(eg.edgeCoord[2],
+                                                          eg.faceCoord[0],
+                                                          eg.elementGlobal,
+                                                          eg.faceCoord[3],
+                                                          eg.subContVol[6].global,
+                                                          eg.edgeCoord[8],
+                                                          eg.faceCoord[5],
+                                                          eg.edgeCoord[11]);
+            eg.subContVol[7].volume = eg.hexahedronVolume(eg.edgeCoord[3],
+                                                          eg.faceCoord[3],
+                                                          eg.elementGlobal,
+                                                          eg.faceCoord[1],
+                                                          eg.subContVol[7].global,
+                                                          eg.edgeCoord[11],
+                                                          eg.faceCoord[5],
+                                                          eg.edgeCoord[9]);
+            break;
+        default:
+            DUNE_THROW(Dune::NotImplemented, "_BoxFVElemGeomHelper::fillSubContVolData dim = " << dim << ", numVertices = " << numVertices);
+        }
+    }
+};
+
+//! \endcond
+
+// END HACK
+/////////////////////
+
+/*!
+ * \brief Represents the finite volume geometry of a single element in
+ *        the box scheme.
+ *
+ * The box scheme is a vertex centered finite volume approach. This
+ * means that each vertex corrosponds to a control volume which
+ * intersects each of the vertex' neighboring elements. If only
+ * looking at a single element of the primary grid (which is what this
+ * class does), the element is subdivided into multiple fragments of
+ * control volumes called sub-control volumes. Each of the element's
+ * vertices corrosponds to exactly one sub-control volume in this
+ * scenario.
+ *
+ * For the box methods the sub-control volumes are constructed by
+ * connecting the element's center with each edge of the element.
+ */
+template<class TypeTag>
+class BoxFVElementGeometry
+{
+    typedef typename GET_PROP_TYPE(TypeTag, GridView) GridView;
+    enum{dim = GridView::dimension};
+    enum{dimWorld = GridView::dimensionworld};
+
+    typedef BoxFVElementGeometry<TypeTag>   ThisType;
+
+    /** \todo Please doc me! */
+    friend class _BoxFVElemGeomHelper<ThisType, dim>;
+
+    typedef _BoxFVElemGeomHelper<ThisType, dim> BoxFVElemGeomHelper;
+
+    enum{maxNC = (dim < 3 ? 4 : 8)};
+    enum{maxNE = (dim < 3 ? 4 : 12)};
+    enum{maxNF = (dim < 3 ? 1 : 6)};
+    enum{maxCOS = (dim < 3 ? 2 : 4)};
+    enum{maxBF = (dim < 3 ? 8 : 24)};
+    enum{maxNFAP = (dim < 3 ? 4 : 8)};
+    typedef typename GET_PROP_TYPE(TypeTag, Scalar) Scalar;
+    typedef typename GridView::ctype CoordScalar;
+    typedef typename GridView::Traits::template Codim<0>::Entity Element;
+    typedef typename Element::Geometry Geometry;
+    typedef Dune::FieldVector<Scalar,dimWorld> Vector;
+    typedef Dune::FieldVector<CoordScalar,dimWorld> GlobalPosition;
+    typedef Dune::FieldVector<CoordScalar,dim> LocalPosition;
+    typedef typename GridView::IntersectionIterator IntersectionIterator;
+#if DUNE_VERSION_NEWER_REV(DUNE_GRID, 2, 3, 0)
+    typedef typename Geometry::JacobianInverseTransposed JacobianInverseTransposed;
+#else
+    typedef typename Geometry::Jacobian JacobianInverseTransposed;    
+#endif
+
+    typedef Dune::PQkLocalFiniteElementCache<CoordScalar, Scalar, dim, 1> LocalFiniteElementCache;
+    typedef typename LocalFiniteElementCache::FiniteElementType LocalFiniteElement;
+    typedef typename LocalFiniteElement::Traits::LocalBasisType::Traits LocalBasisTraits;
+    typedef typename LocalBasisTraits::JacobianType ShapeJacobian;
+
+    Scalar quadrilateralArea(const GlobalPosition& p0, const GlobalPosition& p1, const GlobalPosition& p2, const GlobalPosition& p3)
+    {
+        return 0.5*fabs((p3[0] - p1[0])*(p2[1] - p0[1]) - (p3[1] - p1[1])*(p2[0] - p0[0]));
+    }
+
+    void crossProduct(Vector& c, const Vector& a, const Vector& b)
+    {
+        c[0] = a[1]*b[2] - a[2]*b[1];
+        c[1] = a[2]*b[0] - a[0]*b[2];
+        c[2] = a[0]*b[1] - a[1]*b[0];
+    }
+
+    Scalar pyramidVolume (const GlobalPosition& p0, const GlobalPosition& p1, const GlobalPosition& p2, const GlobalPosition& p3, const GlobalPosition& p4)
+    {
+        Vector a(p2); a -= p0;
+        Vector b(p3); b -= p1;
+
+        Vector n;
+        crossProduct(n, a, b);
+
+        a = p4; a -= p0;
+
+        return 1.0/6.0*(n*a);
+    }
+
+    Scalar prismVolume (const GlobalPosition& p0, const GlobalPosition& p1, const GlobalPosition& p2, const GlobalPosition& p3, const GlobalPosition& p4, const GlobalPosition& p5)
+    {
+        Vector a(p4);
+        for (int k = 0; k < dimWorld; ++k)
+            a[k] -= p0[k];
+        Vector b(p1);
+        for (int k = 0; k < dimWorld; ++k)
+            b[k] -= p3[k];
+        Vector m;
+        crossProduct(m, a, b);
+
+        a = p1;
+        for (int k = 0; k < dimWorld; ++k)
+            a[k] -= p0[k];
+        b = p2;
+        for (int k = 0; k < dimWorld; ++k)
+            b[k] -= p0[k];
+        Vector n;
+        crossProduct(n, a, b);
+        n += m;
+
+        a = p5;
+        for (int k = 0; k < dimWorld; ++k)
+            a[k] -= p0[k];
+
+        return fabs(1.0/6.0*(n*a));
+    }
+
+    Scalar hexahedronVolume (const GlobalPosition& p0, const GlobalPosition& p1, const GlobalPosition& p2, const GlobalPosition& p3,
+                             const GlobalPosition& p4, const GlobalPosition& p5, const GlobalPosition& p6, const GlobalPosition& p7)
+    {
+        return
+            prismVolume(p0,p1,p2,p4,p5,p6)
+            + prismVolume(p0,p2,p3,p4,p6,p7);
+    }
+
+    void normalOfQuadrilateral3D(Vector &normal, const GlobalPosition& p0, const GlobalPosition& p1, const GlobalPosition& p2, const GlobalPosition& p3)
+    {
+        Vector a(p2);
+        for (int k = 0; k < dimWorld; ++k)
+            a[k] -= p0[k];
+        Vector b(p3);
+        for (int k = 0; k < dimWorld; ++k)
+            b[k] -= p1[k];
+
+        crossProduct(normal, a, b);
+        normal *= 0.5;
+    }
+
+    Scalar quadrilateralArea3D(const GlobalPosition& p0, const GlobalPosition& p1, const GlobalPosition& p2, const GlobalPosition& p3)
+    {
+        Vector normal;
+        normalOfQuadrilateral3D(normal, p0, p1, p2, p3);
+        return normal.two_norm();
+    }
+
+    void getFaceIndices(int numVertices, int k, int& leftFace, int& rightFace)
+    {
+        static const int edgeToFaceTet[2][6] = {
+            {1, 0, 3, 2, 1, 3},
+            {0, 2, 0, 1, 3, 2}
+        };
+        static const int edgeToFacePyramid[2][8] = {
+            {1, 2, 3, 4, 1, 3, 4, 2},
+            {0, 0, 0, 0, 3, 2, 1, 4}
+        };
+        static const int edgeToFacePrism[2][9] = {
+            {1, 0, 2, 0, 1, 2, 4, 4, 4},
+            {0, 2, 1, 3, 3, 3, 0, 1, 2}
+        };
+        static const int edgeToFaceHex[2][12] = {
+            {0, 2, 3, 1, 4, 1, 2, 4, 0, 5, 5, 3},
+            {2, 1, 0, 3, 0, 4, 4, 3, 5, 1, 2, 5}
+        };
+
+        switch (numVertices) {
+        case 4:
+            leftFace = edgeToFaceTet[0][k];
+            rightFace = edgeToFaceTet[1][k];
+            break;
+        case 5:
+            leftFace = edgeToFacePyramid[0][k];
+            rightFace = edgeToFacePyramid[1][k];
+            break;
+        case 6:
+            leftFace = edgeToFacePrism[0][k];
+            rightFace = edgeToFacePrism[1][k];
+            break;
+        case 8:
+            leftFace = edgeToFaceHex[0][k];
+            rightFace = edgeToFaceHex[1][k];
+            break;
+        default:
+            DUNE_THROW(Dune::NotImplemented, "BoxFVElementGeometry :: getFaceIndices for numVertices = " << numVertices);
+            break;
+        }
+    }
+
+    void getEdgeIndices(int numVertices, int face, int vert, int& leftEdge, int& rightEdge)
+    {
+        static const int faceAndVertexToLeftEdgeTet[4][4] = {
+            { 0, 0, 2, -1},
+            { 0, 0, -1, 3},
+            { 1, -1, 1, 3},
+            {-1, 2, 2, 4}
+        };
+        static const int faceAndVertexToRightEdgeTet[4][4] = {
+            { 1, 2, 1, -1},
+            { 3, 4, -1, 4},
+            { 3, -1, 5, 5},
+            {-1, 4, 5, 5}
+        };
+        static const int faceAndVertexToLeftEdgePyramid[5][5] = {
+            { 0, 2, 3, 1, -1},
+            { 0, -1, 0, -1, 4},
+            {-1, 1, -1, 1, 5},
+            { 2, 2, -1, -1, 4},
+            {-1, -1, 3, 3, 7}
+        };
+        static const int faceAndVertexToRightEdgePyramid[5][5] = {
+            { 2, 1, 0, 3, -1},
+            { 4, -1, 6, -1, 6},
+            {-1, 5, -1, 7, 7},
+            { 4, 5, -1, -1, 5},
+            {-1, -1, 6, 7, 6}
+        };
+        static const int faceAndVertexToLeftEdgePrism[5][6] = {
+            { 3, 3, -1, 0, 1, -1},
+            { 4, -1, 4, 0, -1, 2},
+            {-1, 5, 5, -1, 1, 2},
+            { 3, 3, 5, -1, -1, -1},
+            {-1, -1, -1, 6, 6, 8}
+        };
+        static const int faceAndVertexToRightEdgePrism[5][6] = {
+            { 0, 1, -1, 6, 6, -1},
+            { 0, -1, 2, 7, -1, 7},
+            {-1, 1, 2, -1, 8, 8},
+            { 4, 5, 4, -1, -1, -1},
+            {-1, -1, -1, 7, 8, 7}
+        };
+        static const int faceAndVertexToLeftEdgeHex[6][8] = {
+            { 0, -1, 4, -1, 8, -1, 2, -1},
+            {-1, 5, -1, 3, -1, 1, -1, 9},
+            { 6, 1, -1, -1, 0, 10, -1, -1},
+            {-1, -1, 2, 7, -1, -1, 11, 3},
+            { 4, 6, 7, 5, -1, -1, -1, -1},
+            {-1, -1, -1, -1, 10, 9, 8, 11}
+        };
+        static const int faceAndVertexToRightEdgeHex[6][8] = {
+            { 4, -1, 2, -1, 0, -1, 8, -1},
+            {-1, 1, -1, 5, -1, 9, -1, 3},
+            { 0, 6, -1, -1, 10, 1, -1, -1},
+            {-1, -1, 7, 3, -1, -1, 2, 11},
+            { 6, 5, 4, 7, -1, -1, -1, -1},
+            {-1, -1, -1, -1, 8, 10, 11, 9}
+        };
+
+        switch (numVertices) {
+        case 4:
+            leftEdge = faceAndVertexToLeftEdgeTet[face][vert];
+            rightEdge = faceAndVertexToRightEdgeTet[face][vert];
+            break;
+        case 5:
+            leftEdge = faceAndVertexToLeftEdgePyramid[face][vert];
+            rightEdge = faceAndVertexToRightEdgePyramid[face][vert];
+            break;
+        case 6:
+            leftEdge = faceAndVertexToLeftEdgePrism[face][vert];
+            rightEdge = faceAndVertexToRightEdgePrism[face][vert];
+            break;
+        case 8:
+            leftEdge = faceAndVertexToLeftEdgeHex[face][vert];
+            rightEdge = faceAndVertexToRightEdgeHex[face][vert];
+            break;
+        default:
+            DUNE_THROW(Dune::NotImplemented, "BoxFVElementGeometry :: getFaceIndices for numVertices = " << numVertices);
+            break;
+        }
+    }
+
+public:
+    int boundaryFaceIndex(const int face, const int vertInFace) const
+    {
+        return (face*maxCOS + vertInFace);
+    }
+
+    struct SubControlVolume //! FV intersected with element
+    {
+        LocalPosition local; //!< local vert position
+        GlobalPosition global; //!< global vert position
+        LocalPosition localCenter; //!< local position of scv center
+        Scalar volume; //!< volume of scv
+        Dune::FieldVector<Vector, maxNC> grad; //! derivative of shape function associated with the sub control volume
+        Dune::FieldVector<Vector, maxNC> gradCenter; //! derivative of shape function at the center of the sub control volume
+        Dune::FieldVector<Scalar, maxNC> shapeValue; //! value of shape function associated with the sub control volume
+        bool inner;
+    };
+
+    struct SubControlVolumeFace //! interior face of a sub control volume
+    {
+        int i,j; //!< scvf seperates corner i and j of elem
+        LocalPosition ipLocal; //!< integration point in local coords
+        GlobalPosition ipGlobal; //!< integration point in global coords
+        Vector normal; //!< normal on face pointing to CV j or outward of the domain with length equal to |scvf|
+        Scalar area; //!< area of face
+        Dune::FieldVector<Vector, maxNC> grad; //!< derivatives of shape functions at ip
+        Dune::FieldVector<Scalar, maxNC> shapeValue; //!< value of shape functions at ip
+        Dune::FieldVector<int, maxNFAP> fapIndices; //!< indices w.r.t.neighbors of the flux approximation points
+    };
+
+    typedef SubControlVolumeFace BoundaryFace; //!< compatibility typedef
+
+    LocalPosition elementLocal; //!< local coordinate of element center
+    GlobalPosition elementGlobal; //!< global coordinate of element center
+    Scalar elementVolume; //!< element volume
+    SubControlVolume subContVol[maxNC]; //!< data of the sub control volumes
+    SubControlVolumeFace subContVolFace[maxNE]; //!< data of the sub control volume faces
+    BoundaryFace boundaryFace[maxBF]; //!< data of the boundary faces
+    GlobalPosition edgeCoord[maxNE]; //!< global coordinates of the edge centers
+    GlobalPosition faceCoord[maxNF]; //!< global coordinates of the face centers
+    int numVertices; //!< number of verts
+    int numEdges; //!< number of edges
+    int numFaces; //!< number of faces (0 in < 3D)
+    int numSCV; //!< number of subcontrol volumes
+    int numFAP; //!< number of flux approximation points
+
+    const LocalFiniteElementCache feCache_;
+
+    void update(const GridView& gridView, const Element& element)
+    {
+        const Geometry& geometry = element.geometry();
+        Dune::GeometryType gt = geometry.type();
+
+        const typename Dune::GenericReferenceElementContainer<CoordScalar,dim>::value_type&
+            referenceElement = Dune::GenericReferenceElements<CoordScalar,dim>::general(gt);
+
+        const LocalFiniteElement
+            &localFiniteElement = feCache_.get(gt);
+
+        elementVolume = geometry.volume();
+        elementLocal = referenceElement.position(0,0);
+        elementGlobal = geometry.global(elementLocal);
+
+        numVertices = referenceElement.size(dim);
+        numEdges = referenceElement.size(dim-1);
+        numFaces = (dim<3)?0:referenceElement.size(1);
+        numSCV = numVertices;
+
+        bool useTwoPointFlux
+            = GET_PARAM_FROM_GROUP(TypeTag, bool, Implicit, UseTwoPointFlux);
+        if (useTwoPointFlux)
+            numFAP = 2;
+        else
+            numFAP = numVertices;
+
+        // corners:
+        for (int vert = 0; vert < numVertices; vert++) {
+            subContVol[vert].local = referenceElement.position(vert, dim);
+            subContVol[vert].global = geometry.global(subContVol[vert].local);
+            subContVol[vert].inner = true;
+        }
+
+        // edges:
+        for (int edge = 0; edge < numEdges; edge++) {
+            edgeCoord[edge] = geometry.global(referenceElement.position(edge, dim-1));
+        }
+
+        // faces:
+        for (int face = 0; face < numFaces; face++) {
+            faceCoord[face] = geometry.global(referenceElement.position(face, 1));
+        }
+
+        // fill sub control volume data use specialization for this
+        // \todo maybe it would be a good idea to migrate everything
+        // which is dependend of the grid's dimension to
+        // _BoxFVElemGeomHelper in order to benefit from more aggressive
+        // compiler optimizations...
+        BoxFVElemGeomHelper::fillSubContVolData(*this, numVertices);
+
+        // fill sub control volume face data:
+        for (int k = 0; k < numEdges; k++) { // begin loop over edges / sub control volume faces
+            int i = referenceElement.subEntity(k, dim-1, 0, dim);
+            int j = referenceElement.subEntity(k, dim-1, 1, dim);
+            if (numEdges == 4 && (i == 2 || j == 2))
+                std::swap(i, j);
+            subContVolFace[k].i = i;
+            subContVolFace[k].j = j;
+
+            // calculate the local integration point and
+            // the face normal. note that since dim is a
+            // constant which is known at compile time
+            // the compiler can optimize away all if
+            // cases which don't apply.
+            LocalPosition ipLocal;
+            Vector diffVec;
+            if (dim==1) {
+                subContVolFace[k].ipLocal = 0.5;
+                subContVolFace[k].normal = 1.0;
+                ipLocal = subContVolFace[k].ipLocal;
+            }
+            else if (dim==2) {
+                ipLocal = referenceElement.position(k, dim-1) + elementLocal;
+                ipLocal *= 0.5;
+                subContVolFace[k].ipLocal = ipLocal;
+                diffVec = elementGlobal - edgeCoord[k];
+                subContVolFace[k].normal[0] = diffVec[1];
+                subContVolFace[k].normal[1] = -diffVec[0];
+
+                diffVec = subContVol[j].global;
+                for (int m = 0; m < dimWorld; ++m)
+                    diffVec[m] -= subContVol[i].global[m];
+                // make sure the normal points to the right direction
+                if (subContVolFace[k].normal * diffVec < 0)
+                    subContVolFace[k].normal *= -1;
+
+            }
+            else if (dim==3) {
+                int leftFace;
+                int rightFace;
+                getFaceIndices(numVertices, k, leftFace, rightFace);
+                ipLocal = referenceElement.position(k, dim-1) + elementLocal
+                    + referenceElement.position(leftFace, 1)
+                    + referenceElement.position(rightFace, 1);
+                ipLocal *= 0.25;
+                subContVolFace[k].ipLocal = ipLocal;
+                normalOfQuadrilateral3D(subContVolFace[k].normal,
+                                        edgeCoord[k], faceCoord[rightFace],
+                                        elementGlobal, faceCoord[leftFace]);
+            }
+
+            if (useTwoPointFlux)
+            {
+                GlobalPosition distVec = subContVol[i].global;
+                distVec -= subContVol[j].global;
+                distVec /= distVec.two_norm2();
+
+                // gradients using a two-point flux approximation
+                for (int idx = 0; idx < 2; idx++)
+                {
+                    subContVolFace[k].grad[idx] = distVec;
+                    subContVolFace[k].shapeValue[idx] = 0.5;
+                }
+                subContVolFace[k].grad[1] *= -1.0;
+
+                subContVolFace[k].fapIndices[0] = subContVolFace[k].i;
+                subContVolFace[k].fapIndices[1] = subContVolFace[k].j;
+            }
+            else
+            {
+                // get the global integration point and the Jacobian inverse
+                subContVolFace[k].ipGlobal = geometry.global(ipLocal);
+                JacobianInverseTransposed jacInvT = 
+                    geometry.jacobianInverseTransposed(ipLocal);
+
+                // calculate the shape function gradients
+                //typedef Dune::FieldVector< Dune::FieldVector< CoordScalar, dim >, 1 > ShapeJacobian;
+                typedef Dune::FieldVector< Scalar, 1 > ShapeValue;
+                std::vector<ShapeJacobian> localJac;
+                std::vector<ShapeValue>    shapeVal;
+                localFiniteElement.localBasis().evaluateJacobian(subContVolFace[k].ipLocal, localJac);
+                localFiniteElement.localBasis().evaluateFunction(subContVolFace[k].ipLocal, shapeVal);
+                for (int vert = 0; vert < numVertices; vert++) {
+                    jacInvT.mv(localJac[vert][0], subContVolFace[k].grad[vert]);
+                    subContVolFace[k].shapeValue[vert] = Scalar(shapeVal[vert]);
+                    subContVolFace[k].fapIndices[vert] = vert;
+                }
+            }
+        } // end loop over edges / sub control volume faces
+
+        // fill boundary face data:
+        IntersectionIterator endit = gridView.iend(element);
+        for (IntersectionIterator it = gridView.ibegin(element); it != endit; ++it)
+            if (it->boundary())
+            {
+                int face = it->indexInInside();
+                int numVerticesOfFace = referenceElement.size(face, 1, dim);
+                for (int vertInFace = 0; vertInFace < numVerticesOfFace; vertInFace++)
+                {
+                    int vertInElement = referenceElement.subEntity(face, 1, vertInFace, dim);
+                    int bfIdx = boundaryFaceIndex(face, vertInFace);
+                    subContVol[vertInElement].inner = false;
+                    switch ((short) dim) {
+                    case 1:
+                        boundaryFace[bfIdx].ipLocal = referenceElement.position(vertInElement, dim);
+                        boundaryFace[bfIdx].area = 1.0;
+                        break;
+                    case 2:
+                        boundaryFace[bfIdx].ipLocal = referenceElement.position(vertInElement, dim)
+                            + referenceElement.position(face, 1);
+                        boundaryFace[bfIdx].ipLocal *= 0.5;
+                        boundaryFace[bfIdx].area = 0.5*it->geometry().volume();
+                        break;
+                    case 3:
+                        int leftEdge;
+                        int rightEdge;
+                        getEdgeIndices(numVertices, face, vertInElement, leftEdge, rightEdge);
+                        boundaryFace[bfIdx].ipLocal = referenceElement.position(vertInElement, dim)
+                            + referenceElement.position(face, 1)
+                            + referenceElement.position(leftEdge, dim-1)
+                            + referenceElement.position(rightEdge, dim-1);
+                        boundaryFace[bfIdx].ipLocal *= 0.25;
+                        boundaryFace[bfIdx].area = quadrilateralArea3D(subContVol[vertInElement].global,
+                                                                       edgeCoord[rightEdge], faceCoord[face], edgeCoord[leftEdge]);
+                        break;
+                    default:
+                        DUNE_THROW(Dune::NotImplemented, "BoxFVElementGeometry for dim = " << dim);
+                    }
+                    boundaryFace[bfIdx].ipGlobal = geometry.global(boundaryFace[bfIdx].ipLocal);
+                    boundaryFace[bfIdx].i = vertInElement;
+                    boundaryFace[bfIdx].j = vertInElement;
+
+                    // ASSUME constant normal
+                    Dune::FieldVector<CoordScalar, dim-1> localDimM1(0);
+                    boundaryFace[bfIdx].normal = it->unitOuterNormal(localDimM1);
+                    boundaryFace[bfIdx].normal *= boundaryFace[bfIdx].area;
+
+                    typedef Dune::FieldVector< Scalar, 1 > ShapeValue;
+                    std::vector<ShapeJacobian> localJac;
+                    std::vector<ShapeValue>    shapeVal;
+                    localFiniteElement.localBasis().evaluateJacobian(boundaryFace[bfIdx].ipLocal, localJac);
+                    localFiniteElement.localBasis().evaluateFunction(boundaryFace[bfIdx].ipLocal, shapeVal);
+
+                    JacobianInverseTransposed jacInvT = 
+                        geometry.jacobianInverseTransposed(boundaryFace[bfIdx].ipLocal);
+                    for (int vert = 0; vert < numVertices; vert++)
+                    {
+                        jacInvT.mv(localJac[vert][0], boundaryFace[bfIdx].grad[vert]);
+                        boundaryFace[bfIdx].shapeValue[vert] = Scalar(shapeVal[vert]);
+                        boundaryFace[bfIdx].fapIndices[vert] = vert;
+                    }
+                }
+            }
+
+        bool evalGradientsAtSCVCenter = GET_PROP_VALUE(TypeTag, EvalGradientsAtSCVCenter);
+        if(evalGradientsAtSCVCenter)
+        {
+            // calculate gradients at the center of the scv
+            for (int scvIdx = 0; scvIdx < numVertices; scvIdx++){
+                if (dim == 2)
+                {
+                    switch (scvIdx)
+                    {
+                    case 0:
+                        if (numVertices == 4) {
+                            subContVol[scvIdx].localCenter[0] = 0.25;
+                            subContVol[scvIdx].localCenter[1] = 0.25;
+                        }
+                        else {
+                            subContVol[scvIdx].localCenter[0] = 1.0/6.0;
+                            subContVol[scvIdx].localCenter[1] = 1.0/6.0;
+                        }
+                        break;
+                    case 1:
+                        if (numVertices == 4) {
+                            subContVol[scvIdx].localCenter[0] = 0.75;
+                            subContVol[scvIdx].localCenter[1] = 0.25;
+                        }
+                        else {
+                            subContVol[scvIdx].localCenter[0] = 4.0/6.0;
+                            subContVol[scvIdx].localCenter[1] = 1.0/6.0;
+                        }
+                        break;
+                    case 2:
+                        if (numVertices == 4) {
+                            subContVol[scvIdx].localCenter[0] = 0.25;
+                            subContVol[scvIdx].localCenter[1] = 0.75;
+                        }
+                        else {
+                            subContVol[scvIdx].localCenter[0] = 1.0/6.0;
+                            subContVol[scvIdx].localCenter[1] = 4.0/6.0;
+                        }
+                        break;
+                    case 3:
+                        subContVol[scvIdx].localCenter[0] = 0.75;
+                        subContVol[scvIdx].localCenter[1] = 0.75;
+                        break;
+                    }
+                }
+
+                else if (dim == 3)
+                {
+                    switch (scvIdx)
+                    {
+                    case 0:
+                        if (numVertices == 8) {
+                            subContVol[scvIdx].localCenter[0] = 0.25;
+                            subContVol[scvIdx].localCenter[1] = 0.25;
+                            subContVol[scvIdx].localCenter[2] = 0.25;
+                        }
+                        else if (numVertices == 4) {
+                            subContVol[scvIdx].localCenter[0] = 3.0/16.0;
+                            subContVol[scvIdx].localCenter[1] = 3.0/16.0;
+                            subContVol[scvIdx].localCenter[2] = 3.0/16.0;
+                        }
+                        break;
+                    case 1:
+                        if (numVertices == 8) {
+                            subContVol[scvIdx].localCenter[0] = 0.75;
+                            subContVol[scvIdx].localCenter[1] = 0.25;
+                            subContVol[scvIdx].localCenter[2] = 0.25;
+                        }
+                        else if (numVertices == 4) {
+                            subContVol[scvIdx].localCenter[0] = 7.0/16.0;
+                            subContVol[scvIdx].localCenter[1] = 3.0/16.0;
+                            subContVol[scvIdx].localCenter[2] = 3.0/16.0;
+                        }
+                        break;
+                    case 2:
+                        if (numVertices == 8) {
+                            subContVol[scvIdx].localCenter[0] = 0.25;
+                            subContVol[scvIdx].localCenter[1] = 0.75;
+                            subContVol[scvIdx].localCenter[2] = 0.25;
+                        }
+                        else if (numVertices == 4) {
+                            subContVol[scvIdx].localCenter[0] = 3.0/16.0;
+                            subContVol[scvIdx].localCenter[1] = 7.0/16.0;
+                            subContVol[scvIdx].localCenter[2] = 3.0/16.0;
+                        }
+                        break;
+                    case 3:
+                        if (numVertices == 8) {
+                            subContVol[scvIdx].localCenter[0] = 0.75;
+                            subContVol[scvIdx].localCenter[1] = 0.75;
+                            subContVol[scvIdx].localCenter[2] = 0.25;
+                        }
+                        else if (numVertices == 4) {
+                            subContVol[scvIdx].localCenter[0] = 3.0/16.0;
+                            subContVol[scvIdx].localCenter[1] = 3.0/16.0;
+                            subContVol[scvIdx].localCenter[2] = 7.0/16.0;
+                        }
+                        break;
+                    case 4:
+                        subContVol[scvIdx].localCenter[0] = 0.25;
+                        subContVol[scvIdx].localCenter[1] = 0.25;
+                        subContVol[scvIdx].localCenter[2] = 0.75;
+                        break;
+                    case 5:
+                        subContVol[scvIdx].localCenter[0] = 0.75;
+                        subContVol[scvIdx].localCenter[1] = 0.25;
+                        subContVol[scvIdx].localCenter[2] = 0.75;
+                        break;
+                    case 6:
+                        subContVol[scvIdx].localCenter[0] = 0.25;
+                        subContVol[scvIdx].localCenter[1] = 0.75;
+                        subContVol[scvIdx].localCenter[2] = 0.75;
+                        break;
+                    case 7:
+                        subContVol[scvIdx].localCenter[0] = 0.75;
+                        subContVol[scvIdx].localCenter[1] = 0.75;
+                        subContVol[scvIdx].localCenter[2] = 0.75;
+                        break;
+                    }
+                }
+                std::vector<ShapeJacobian> localJac;
+                localFiniteElement.localBasis().evaluateJacobian(subContVol[scvIdx].localCenter, localJac);
+
+                JacobianInverseTransposed jacInvT =
+                    geometry.jacobianInverseTransposed(subContVol[scvIdx].localCenter);
+                for (int vert = 0; vert < numVertices; vert++)
+                    jacInvT.mv(localJac[vert][0], subContVol[scvIdx].gradCenter[vert]);
+            }
+        }
+    }
+};
+
+}
+
+#endif
+
diff --git a/dumux/implicit/common/implicitlocaljacobian.hh b/dumux/implicit/common/implicitlocaljacobian.hh
new file mode 100644
index 0000000000..7fc5140d25
--- /dev/null
+++ b/dumux/implicit/common/implicitlocaljacobian.hh
@@ -0,0 +1,534 @@
+// -*- mode: C++; tab-width: 4; indent-tabs-mode: nil; c-basic-offset: 4 -*-
+// vi: set et ts=4 sw=4 sts=4:
+/*****************************************************************************
+ *   See the file COPYING for full copying permissions.                      *
+ *                                                                           *
+ *   This program is free software: you can redistribute it and/or modify    *
+ *   it under the terms of the GNU General Public License as published by    *
+ *   the Free Software Foundation, either version 2 of the License, or       *
+ *   (at your option) any later version.                                     *
+ *                                                                           *
+ *   This program is distributed in the hope that it will be useful,         *
+ *   but WITHOUT ANY WARRANTY; without even the implied warranty of          *
+ *   MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the            *
+ *   GNU General Public License for more details.                            *
+ *                                                                           *
+ *   You should have received a copy of the GNU General Public License       *
+ *   along with this program.  If not, see <http://www.gnu.org/licenses/>.   *
+ *****************************************************************************/
+/*!
+ * \file
+ * \brief Caculates the Jacobian of the local residual for box models
+ */
+#ifndef DUMUX_BOX_LOCAL_JACOBIAN_HH
+#define DUMUX_BOX_LOCAL_JACOBIAN_HH
+
+#include <dune/istl/matrix.hh>
+
+#include <dumux/common/math.hh>
+#include "boxelementboundarytypes.hh"
+
+namespace Dumux
+{
+/*!
+ * \ingroup BoxModel
+ * \ingroup BoxLocalJacobian
+ * \brief Calculates the Jacobian of the local residual for box models
+ *
+ * The default behavior is to use numeric differentiation, i.e.
+ * forward or backward differences (2nd order), or central
+ * differences (3rd order). The method used is determined by the
+ * "NumericDifferenceMethod" property:
+ *
+ * - if the value of this property is smaller than 0, backward
+ *   differences are used, i.e.:
+ *   \f[
+ \frac{\partial f(x)}{\partial x} \approx \frac{f(x) - f(x - \epsilon)}{\epsilon}
+ *   \f]
+ *
+ * - if the value of this property is 0, central
+ *   differences are used, i.e.:
+ *   \f[
+ \frac{\partial f(x)}{\partial x} \approx \frac{f(x + \epsilon) - f(x - \epsilon)}{2 \epsilon}
+ *   \f]
+ *
+ * - if the value of this property is larger than 0, forward
+ *   differences are used, i.e.:
+ *   \f[
+ \frac{\partial f(x)}{\partial x} \approx \frac{f(x + \epsilon) - f(x)}{\epsilon}
+ *   \f]
+ *
+ * Here, \f$ f \f$ is the residual function for all equations, \f$x\f$
+ * is the value of a sub-control volume's primary variable at the
+ * evaluation point and \f$\epsilon\f$ is a small value larger than 0.
+ */
+template<class TypeTag>
+class BoxLocalJacobian
+{
+private:
+    typedef typename GET_PROP_TYPE(TypeTag, LocalJacobian) Implementation;
+    typedef typename GET_PROP_TYPE(TypeTag, LocalResidual) LocalResidual;
+    typedef typename GET_PROP_TYPE(TypeTag, Problem) Problem;
+    typedef typename GET_PROP_TYPE(TypeTag, Model) Model;
+    typedef typename GET_PROP_TYPE(TypeTag, GridView) GridView;
+    typedef typename GridView::template Codim<0>::Entity Element;
+    typedef typename GET_PROP_TYPE(TypeTag, JacobianAssembler) JacobianAssembler;
+
+    enum {
+        numEq = GET_PROP_VALUE(TypeTag, NumEq),
+        dim = GridView::dimension,
+
+        Green = JacobianAssembler::Green
+    };
+
+    typedef typename GET_PROP_TYPE(TypeTag, FVElementGeometry) FVElementGeometry;
+    typedef typename GET_PROP_TYPE(TypeTag, VertexMapper) VertexMapper;
+    typedef typename GET_PROP_TYPE(TypeTag, ElementSolutionVector) ElementSolutionVector;
+    typedef typename GET_PROP_TYPE(TypeTag, PrimaryVariables) PrimaryVariables;
+
+    typedef typename GET_PROP_TYPE(TypeTag, VolumeVariables) VolumeVariables;
+    typedef typename GET_PROP_TYPE(TypeTag, ElementVolumeVariables) ElementVolumeVariables;
+    typedef typename GET_PROP_TYPE(TypeTag, ElementBoundaryTypes) ElementBoundaryTypes;
+
+    typedef typename GET_PROP_TYPE(TypeTag, Scalar) Scalar;
+    typedef Dune::FieldMatrix<Scalar, numEq, numEq> MatrixBlock;
+    typedef Dune::Matrix<MatrixBlock> LocalBlockMatrix;
+
+    // copying a local jacobian is not a good idea
+    BoxLocalJacobian(const BoxLocalJacobian &);
+
+public:
+    BoxLocalJacobian()
+    {
+        numericDifferenceMethod_ = GET_PARAM_FROM_GROUP(TypeTag, int, Implicit, NumericDifferenceMethod);
+        Valgrind::SetUndefined(problemPtr_);
+    }
+
+
+    /*!
+     * \brief Initialize the local Jacobian object.
+     *
+     * At this point we can assume that everything has been allocated,
+     * although some objects may not yet be completely initialized.
+     *
+     * \param prob The problem which we want to simulate.
+     */
+    void init(Problem &prob)
+    {
+        problemPtr_ = &prob;
+        localResidual_.init(prob);
+
+        // assume quadrilinears as elements with most vertices
+        A_.setSize(2<<dim, 2<<dim);
+        storageJacobian_.resize(2<<dim);
+    }
+
+    /*!
+     * \brief Assemble an element's local Jacobian matrix of the
+     *        defect.
+     *
+     * \param element The DUNE Codim<0> entity which we look at.
+     */
+    void assemble(const Element &element)
+    {
+        // set the current grid element and update the element's
+        // finite volume geometry
+        elemPtr_ = &element;
+        fvElemGeom_.update(gridView_(), element);
+        reset_();
+
+        bcTypes_.update(problem_(), element_(), fvElemGeom_);
+
+        // this is pretty much a HACK because the internal state of
+        // the problem is not supposed to be changed during the
+        // evaluation of the residual. (Reasons: It is a violation of
+        // abstraction, makes everything more prone to errors and is
+        // not thread save.) The real solution are context objects!
+        problem_().updateCouplingParams(element_());
+
+        // set the hints for the volume variables
+        model_().setHints(element, prevVolVars_, curVolVars_);
+
+        // update the secondary variables for the element at the last
+        // and the current time levels
+        prevVolVars_.update(problem_(),
+                            element_(),
+                            fvElemGeom_,
+                            true /* isOldSol? */);
+
+        curVolVars_.update(problem_(),
+                           element_(),
+                           fvElemGeom_,
+                           false /* isOldSol? */);
+
+        // update the hints of the model
+        model_().updateCurHints(element, curVolVars_);
+
+        // calculate the local residual
+        localResidual().eval(element_(),
+                             fvElemGeom_,
+                             prevVolVars_,
+                             curVolVars_,
+                             bcTypes_);
+        residual_ = localResidual().residual();
+        storageTerm_ = localResidual().storageTerm();
+
+        model_().updatePVWeights(element_(), curVolVars_);
+
+        // calculate the local jacobian matrix
+        int numVertices = fvElemGeom_.numVertices;
+        ElementSolutionVector partialDeriv(numVertices);
+        PrimaryVariables storageDeriv;
+        for (int j = 0; j < numVertices; j++) {
+            for (int pvIdx = 0; pvIdx < numEq; pvIdx++) {
+                asImp_().evalPartialDerivative_(partialDeriv,
+                                                storageDeriv,
+                                                j,
+                                                pvIdx);
+
+                // update the local stiffness matrix with the current partial
+                // derivatives
+                updateLocalJacobian_(j,
+                                     pvIdx,
+                                     partialDeriv,
+                                     storageDeriv);
+            }
+        }
+    }
+
+    /*!
+     * \brief Returns a reference to the object which calculates the
+     *        local residual.
+     */
+    const LocalResidual &localResidual() const
+    { return localResidual_; }
+
+    /*!
+     * \brief Returns a reference to the object which calculates the
+     *        local residual.
+     */
+    LocalResidual &localResidual()
+    { return localResidual_; }
+
+    /*!
+     * \brief Returns the Jacobian of the equations at vertex i to the
+     *        primary variables at vertex j.
+     *
+     * \param i The local vertex (or sub-control volume) index on which
+     *          the equations are defined
+     * \param j The local vertex (or sub-control volume) index which holds
+     *          primary variables
+     */
+    const MatrixBlock &mat(const int i, const int j) const
+    { return A_[i][j]; }
+
+    /*!
+     * \brief Returns the Jacobian of the storage term at vertex i.
+     *
+     * \param i The local vertex (or sub-control volume) index
+     */
+    const MatrixBlock &storageJacobian(const int i) const
+    { return storageJacobian_[i]; }
+
+    /*!
+     * \brief Returns the residual of the equations at vertex i.
+     *
+     * \param i The local vertex (or sub-control volume) index on which
+     *          the equations are defined
+     */
+    const PrimaryVariables &residual(const int i) const
+    { return residual_[i]; }
+
+    /*!
+     * \brief Returns the storage term for vertex i.
+     *
+     * \param i The local vertex (or sub-control volume) index on which
+     *          the equations are defined
+     */
+    const PrimaryVariables &storageTerm(const int i) const
+    { return storageTerm_[i]; }
+
+    /*!
+     * \brief Returns the epsilon value which is added and removed
+     *        from the current solution.
+     *
+     * \param scvIdx     The local index of the element's vertex for
+     *                   which the local derivative ought to be calculated.
+     * \param pvIdx      The index of the primary variable which gets varied
+     */
+    Scalar numericEpsilon(const int scvIdx,
+                          const int pvIdx) const
+    {
+        // define the base epsilon as the geometric mean of 1 and the
+        // resolution of the scalar type. E.g. for standard 64 bit
+        // floating point values, the resolution is about 10^-16 and
+        // the base epsilon is thus approximately 10^-8.
+        /*
+        static const Scalar baseEps
+            = Dumux::geometricMean<Scalar>(std::numeric_limits<Scalar>::epsilon(), 1.0);
+        */
+        static const Scalar baseEps = 1e-10;
+        assert(std::numeric_limits<Scalar>::epsilon()*1e4 < baseEps);
+        // the epsilon value used for the numeric differentiation is
+        // now scaled by the absolute value of the primary variable...
+        Scalar priVar = this->curVolVars_[scvIdx].priVar(pvIdx);
+        return baseEps*(std::abs(priVar) + 1.0);
+    }
+
+protected:
+    Implementation &asImp_()
+    { return *static_cast<Implementation*>(this); }
+    const Implementation &asImp_() const
+    { return *static_cast<const Implementation*>(this); }
+
+    /*!
+     * \brief Returns a reference to the problem.
+     */
+    const Problem &problem_() const
+    {
+        Valgrind::CheckDefined(problemPtr_);
+        return *problemPtr_;
+    };
+
+    /*!
+     * \brief Returns a reference to the grid view.
+     */
+    const GridView &gridView_() const
+    { return problem_().gridView(); }
+
+    /*!
+     * \brief Returns a reference to the element.
+     */
+    const Element &element_() const
+    {
+        Valgrind::CheckDefined(elemPtr_);
+        return *elemPtr_;
+    };
+
+    /*!
+     * \brief Returns a reference to the model.
+     */
+    const Model &model_() const
+    { return problem_().model(); };
+
+    /*!
+     * \brief Returns a reference to the jacobian assembler.
+     */
+    const JacobianAssembler &jacAsm_() const
+    { return model_().jacobianAssembler(); }
+
+    /*!
+     * \brief Returns a reference to the vertex mapper.
+     */
+    const VertexMapper &vertexMapper_() const
+    { return problem_().vertexMapper(); };
+
+    /*!
+     * \brief Reset the local jacobian matrix to 0
+     */
+    void reset_()
+    {
+        int n = element_().template count<dim>();
+        for (int i = 0; i < n; ++ i) {
+            storageJacobian_[i] = 0.0;
+            for (int j = 0; j < n; ++ j) {
+                A_[i][j] = 0.0;
+            }
+        }
+    }
+
+    /*!
+     * \brief Compute the partial derivatives to a primary variable at
+     *        an degree of freedom.
+     *
+     * This method can be overwritten by the implementation if a
+     * better scheme than numerical differentiation is available.
+     *
+     * The default implementation of this method uses numeric
+     * differentiation, i.e. forward or backward differences (2nd
+     * order), or central differences (3rd order). The method used is
+     * determined by the "NumericDifferenceMethod" property:
+     *
+     * - if the value of this property is smaller than 0, backward
+     *   differences are used, i.e.:
+     *   \f[
+         \frac{\partial f(x)}{\partial x} \approx \frac{f(x) - f(x - \epsilon)}{\epsilon}
+     *   \f]
+     *
+     * - if the value of this property is 0, central
+     *   differences are used, i.e.:
+     *   \f[
+           \frac{\partial f(x)}{\partial x} \approx \frac{f(x + \epsilon) - f(x - \epsilon)}{2 \epsilon}
+     *   \f]
+     *
+     * - if the value of this property is larger than 0, forward
+     *   differences are used, i.e.:
+     *   \f[
+           \frac{\partial f(x)}{\partial x} \approx \frac{f(x + \epsilon) - f(x)}{\epsilon}
+     *   \f]
+     *
+     * Here, \f$ f \f$ is the residual function for all equations, \f$x\f$
+     * is the value of a sub-control volume's primary variable at the
+     * evaluation point and \f$\epsilon\f$ is a small value larger than 0.
+     *
+     * \param partialDeriv The vector storing the partial derivatives of all
+     *              equations
+     * \param storageDeriv the mass matrix contributions
+     * \param scvIdx The sub-control volume index of the current
+     *               finite element for which the partial derivative
+     *               ought to be calculated
+     * \param pvIdx The index of the primary variable at the scvIdx'
+     *              sub-control volume of the current finite element
+     *              for which the partial derivative ought to be
+     *              calculated
+     */
+    void evalPartialDerivative_(ElementSolutionVector &partialDeriv,
+                                PrimaryVariables &storageDeriv,
+                                const int scvIdx,
+                                const int pvIdx)
+    {
+        int globalIdx = vertexMapper_().map(element_(), scvIdx, dim);
+
+        PrimaryVariables priVars(model_().curSol()[globalIdx]);
+        VolumeVariables origVolVars(curVolVars_[scvIdx]);
+
+        curVolVars_[scvIdx].setEvalPoint(&origVolVars);
+        Scalar eps = asImp_().numericEpsilon(scvIdx, pvIdx);
+        Scalar delta = 0;
+
+        if (numericDifferenceMethod_ >= 0) {
+            // we are not using backward differences, i.e. we need to
+            // calculate f(x + \epsilon)
+
+            // deflect primary variables
+            priVars[pvIdx] += eps;
+            delta += eps;
+
+            // calculate the residual
+            curVolVars_[scvIdx].update(priVars,
+                                       problem_(),
+                                       element_(),
+                                       fvElemGeom_,
+                                       scvIdx,
+                                       false);
+            localResidual().eval(element_(),
+                                 fvElemGeom_,
+                                 prevVolVars_,
+                                 curVolVars_,
+                                 bcTypes_);
+
+            // store the residual and the storage term
+            partialDeriv = localResidual().residual();
+            storageDeriv = localResidual().storageTerm()[scvIdx];
+        }
+        else {
+            // we are using backward differences, i.e. we don't need
+            // to calculate f(x + \epsilon) and we can recycle the
+            // (already calculated) residual f(x)
+            partialDeriv = residual_;
+            storageDeriv = storageTerm_[scvIdx];
+        }
+
+
+        if (numericDifferenceMethod_ <= 0) {
+            // we are not using forward differences, i.e. we don't
+            // need to calculate f(x - \epsilon)
+
+            // deflect the primary variables
+            priVars[pvIdx] -= delta + eps;
+            delta += eps;
+
+            // calculate residual again
+            curVolVars_[scvIdx].update(priVars,
+                                       problem_(),
+                                       element_(),
+                                       fvElemGeom_,
+                                       scvIdx,
+                                       false);
+            localResidual().eval(element_(),
+                                 fvElemGeom_,
+                                 prevVolVars_,
+                                 curVolVars_,
+                                 bcTypes_);
+            partialDeriv -= localResidual().residual();
+            storageDeriv -= localResidual().storageTerm()[scvIdx];
+        }
+        else {
+            // we are using forward differences, i.e. we don't need to
+            // calculate f(x - \epsilon) and we can recycle the
+            // (already calculated) residual f(x)
+            partialDeriv -= residual_;
+            storageDeriv -= storageTerm_[scvIdx];
+        }
+
+        // divide difference in residuals by the magnitude of the
+        // deflections between the two function evaluation
+        partialDeriv /= delta;
+        storageDeriv /= delta;
+
+        // restore the original state of the element's volume variables
+        curVolVars_[scvIdx] = origVolVars;
+
+#if HAVE_VALGRIND
+        for (unsigned i = 0; i < partialDeriv.size(); ++i)
+            Valgrind::CheckDefined(partialDeriv[i]);
+#endif
+    }
+
+    /*!
+     * \brief Updates the current local Jacobian matrix with the
+     *        partial derivatives of all equations in regard to the
+     *        primary variable 'pvIdx' at vertex 'scvIdx' .
+     */
+    void updateLocalJacobian_(const int scvIdx,
+                              const int pvIdx,
+                              const ElementSolutionVector &partialDeriv,
+                              const PrimaryVariables &storageDeriv)
+    {
+        // store the derivative of the storage term
+        for (int eqIdx = 0; eqIdx < numEq; eqIdx++) {
+            storageJacobian_[scvIdx][eqIdx][pvIdx] = storageDeriv[eqIdx];
+        }
+
+        for (int i = 0; i < fvElemGeom_.numVertices; i++)
+        {
+            // Green vertices are not to be changed!
+            if (jacAsm_().vertexColor(element_(), i) != Green) {
+                for (int eqIdx = 0; eqIdx < numEq; eqIdx++) {
+                    // A[i][scvIdx][eqIdx][pvIdx] is the rate of change of
+                    // the residual of equation 'eqIdx' at vertex 'i'
+                    // depending on the primary variable 'pvIdx' at vertex
+                    // 'scvIdx'.
+                    this->A_[i][scvIdx][eqIdx][pvIdx] = partialDeriv[i][eqIdx];
+                    Valgrind::CheckDefined(this->A_[i][scvIdx][eqIdx][pvIdx]);
+                }
+            }
+        }
+    }
+
+    const Element *elemPtr_;
+    FVElementGeometry fvElemGeom_;
+
+    ElementBoundaryTypes bcTypes_;
+
+    // The problem we would like to solve
+    Problem *problemPtr_;
+
+    // secondary variables at the previous and at the current time
+    // levels
+    ElementVolumeVariables prevVolVars_;
+    ElementVolumeVariables curVolVars_;
+
+    LocalResidual localResidual_;
+
+    LocalBlockMatrix A_;
+    std::vector<MatrixBlock> storageJacobian_;
+
+    ElementSolutionVector residual_;
+    ElementSolutionVector storageTerm_;
+
+    int numericDifferenceMethod_;
+};
+}
+
+#endif
diff --git a/dumux/implicit/common/implicitlocalresidual.hh b/dumux/implicit/common/implicitlocalresidual.hh
new file mode 100644
index 0000000000..8c02754133
--- /dev/null
+++ b/dumux/implicit/common/implicitlocalresidual.hh
@@ -0,0 +1,742 @@
+// -*- mode: C++; tab-width: 4; indent-tabs-mode: nil; c-basic-offset: 4 -*-
+// vi: set et ts=4 sw=4 sts=4:
+/*****************************************************************************
+ *   See the file COPYING for full copying permissions.                      *
+ *                                                                           *
+ *   This program is free software: you can redistribute it and/or modify    *
+ *   it under the terms of the GNU General Public License as published by    *
+ *   the Free Software Foundation, either version 2 of the License, or       *
+ *   (at your option) any later version.                                     *
+ *                                                                           *
+ *   This program is distributed in the hope that it will be useful,         *
+ *   but WITHOUT ANY WARRANTY; without even the implied warranty of          *
+ *   MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the            *
+ *   GNU General Public License for more details.                            *
+ *                                                                           *
+ *   You should have received a copy of the GNU General Public License       *
+ *   along with this program.  If not, see <http://www.gnu.org/licenses/>.   *
+ *****************************************************************************/
+/*!
+ * \file
+ * \brief Calculates the residual of models based on the box scheme element-wise.
+ */
+#ifndef DUMUX_BOX_LOCAL_RESIDUAL_HH
+#define DUMUX_BOX_LOCAL_RESIDUAL_HH
+
+#include <dune/istl/matrix.hh>
+#include <dune/grid/common/geometry.hh>
+
+#include <dumux/common/valgrind.hh>
+
+#include "boxproperties.hh"
+
+namespace Dumux
+{
+/*!
+ * \ingroup BoxModel
+ * \ingroup BoxLocalResidual
+ * \brief Element-wise calculation of the residual matrix for models
+ *        based on the box scheme.
+ *
+ * \todo Please doc me more!
+ */
+template<class TypeTag>
+class BoxLocalResidual
+{
+private:
+    typedef typename GET_PROP_TYPE(TypeTag, LocalResidual) Implementation;
+    typedef typename GET_PROP_TYPE(TypeTag, Problem) Problem;
+    typedef typename GET_PROP_TYPE(TypeTag, Model) Model;
+    typedef typename GET_PROP_TYPE(TypeTag, Scalar) Scalar;
+    typedef typename GET_PROP_TYPE(TypeTag, GridView) GridView;
+
+    enum {
+        numEq = GET_PROP_VALUE(TypeTag, NumEq),
+        dim = GridView::dimension
+    };
+
+    typedef typename GridView::template Codim<0>::Entity Element;
+    typedef typename GridView::template Codim<dim>::EntityPointer VertexPointer;
+    typedef typename GridView::IntersectionIterator IntersectionIterator;
+
+    typedef typename GridView::Grid::ctype CoordScalar;
+    typedef typename Dune::GenericReferenceElements<CoordScalar, dim> ReferenceElements;
+    typedef typename Dune::GenericReferenceElement<CoordScalar, dim> ReferenceElement;
+
+    typedef typename GET_PROP_TYPE(TypeTag, FVElementGeometry) FVElementGeometry;
+    typedef typename GET_PROP_TYPE(TypeTag, VertexMapper) VertexMapper;
+    typedef typename GET_PROP_TYPE(TypeTag, ElementSolutionVector) ElementSolutionVector;
+    typedef typename GET_PROP_TYPE(TypeTag, PrimaryVariables) PrimaryVariables;
+    typedef typename GET_PROP_TYPE(TypeTag, BoundaryTypes) BoundaryTypes;
+    typedef typename GET_PROP_TYPE(TypeTag, ElementBoundaryTypes) ElementBoundaryTypes;
+    typedef typename GET_PROP_TYPE(TypeTag, VolumeVariables) VolumeVariables;
+    typedef typename GET_PROP_TYPE(TypeTag, ElementVolumeVariables) ElementVolumeVariables;
+
+    // copying the local residual class is not a good idea
+    BoxLocalResidual(const BoxLocalResidual &);
+
+public:
+    BoxLocalResidual()
+    { }
+
+    ~BoxLocalResidual()
+    { }
+
+    /*!
+     * \brief Initialize the local residual.
+     *
+     * This assumes that all objects of the simulation have been fully
+     * allocated but not necessarily initialized completely.
+     *
+     * \param problem The representation of the physical problem to be
+     *             solved.
+     */
+    void init(Problem &problem)
+    { problemPtr_ = &problem; }
+
+    /*!
+     * \brief Compute the local residual, i.e. the deviation of the
+     *        equations from zero.
+     *
+     * \param element The DUNE Codim<0> entity for which the residual
+     *                ought to be calculated
+     */
+    void eval(const Element &element)
+    {
+        FVElementGeometry fvGeometry;
+
+        fvGeometry.update(gridView_(), element);
+        fvElemGeomPtr_ = &fvGeometry;
+
+        ElementVolumeVariables volVarsPrev, volVarsCur;
+        // update the hints
+        model_().setHints(element, volVarsPrev, volVarsCur);
+
+        volVarsPrev.update(problem_(),
+                           element,
+                           fvGeometry_(),
+                           true /* oldSol? */);
+        volVarsCur.update(problem_(),
+                          element,
+                          fvGeometry_(),
+                          false /* oldSol? */);
+
+        ElementBoundaryTypes bcTypes;
+        bcTypes.update(problem_(), element, fvGeometry_());
+
+        // this is pretty much a HACK because the internal state of
+        // the problem is not supposed to be changed during the
+        // evaluation of the residual. (Reasons: It is a violation of
+        // abstraction, makes everything more prone to errors and is
+        // not thread save.) The real solution are context objects!
+        problem_().updateCouplingParams(element);
+
+        asImp_().eval(element, fvGeometry_(), volVarsPrev, volVarsCur, bcTypes);
+    }
+
+    /*!
+     * \brief Compute the storage term for the current solution.
+     *
+     * This can be used to figure out how much of each conservation
+     * quantity is inside the element.
+     *
+     * \param element The DUNE Codim<0> entity for which the storage
+     *                term ought to be calculated
+     */
+    void evalStorage(const Element &element)
+    {
+        elemPtr_ = &element;
+
+        FVElementGeometry fvGeometry;
+        fvGeometry.update(gridView_(), element);
+        fvElemGeomPtr_ = &fvGeometry;
+
+        ElementBoundaryTypes bcTypes;
+        bcTypes.update(problem_(), element, fvGeometry_());
+        bcTypesPtr_ = &bcTypes;
+
+        // no previous volume variables!
+        prevVolVarsPtr_ = 0;
+
+        ElementVolumeVariables volVars;
+
+        // update the hints
+        model_().setHints(element, volVars);
+
+        // calculate volume current variables
+        volVars.update(problem_(), element, fvGeometry_(), false);
+        curVolVarsPtr_ = &volVars;
+
+        asImp_().evalStorage_();
+    }
+
+    /*!
+     * \brief Compute the flux term for the current solution.
+     *
+     * \param element The DUNE Codim<0> entity for which the residual
+     *                ought to be calculated
+     * \param curVolVars The volume averaged variables for all
+     *                   sub-contol volumes of the element
+     */
+    void evalFluxes(const Element &element,
+                    const ElementVolumeVariables &curVolVars)
+    {
+        elemPtr_ = &element;
+
+        FVElementGeometry fvGeometry;
+        fvGeometry.update(gridView_(), element);
+        fvElemGeomPtr_ = &fvGeometry;
+
+        ElementBoundaryTypes bcTypes;
+        bcTypes.update(problem_(), element, fvGeometry_());
+
+        residual_.resize(fvGeometry_().numVertices);
+        residual_ = 0;
+
+        bcTypesPtr_ = &bcTypes;
+        prevVolVarsPtr_ = 0;
+        curVolVarsPtr_ = &curVolVars;
+        asImp_().evalFluxes_();
+    }
+
+    /*!
+     * \brief Compute the local residual, i.e. the deviation of the
+     *        equations from zero.
+     *
+     * \param element The DUNE Codim<0> entity for which the residual
+     *                ought to be calculated
+     * \param fvGeometry The finite-volume geometry of the element
+     * \param prevVolVars The volume averaged variables for all
+     *                   sub-control volumes of the element at the previous
+     *                   time level
+     * \param curVolVars The volume averaged variables for all
+     *                   sub-control volumes of the element at the current
+     *                   time level
+     * \param bcTypes The types of the boundary conditions for all
+     *                vertices of the element
+     */
+    void eval(const Element &element,
+              const FVElementGeometry &fvGeometry,
+              const ElementVolumeVariables &prevVolVars,
+              const ElementVolumeVariables &curVolVars,
+              const ElementBoundaryTypes &bcTypes)
+    {
+        Valgrind::CheckDefined(prevVolVars);
+        Valgrind::CheckDefined(curVolVars);
+
+#if !defined NDEBUG && HAVE_VALGRIND
+        for (int i=0; i < fvGeometry.numVertices; i++) {
+            prevVolVars[i].checkDefined();
+            curVolVars[i].checkDefined();
+        }
+#endif // HAVE_VALGRIND
+
+        elemPtr_ = &element;
+        fvElemGeomPtr_ = &fvGeometry;
+        bcTypesPtr_ = &bcTypes;
+        prevVolVarsPtr_ = &prevVolVars;
+        curVolVarsPtr_ = &curVolVars;
+
+        // resize the vectors for all terms
+        int numVerts = fvGeometry_().numVertices;
+        residual_.resize(numVerts);
+        storageTerm_.resize(numVerts);
+
+        residual_ = 0.0;
+        storageTerm_ = 0.0;
+
+        asImp_().evalFluxes_();
+
+#if !defined NDEBUG && HAVE_VALGRIND
+        for (int i=0; i < fvGeometry_().numVertices; i++)
+            Valgrind::CheckDefined(residual_[i]);
+#endif // HAVE_VALGRIND
+
+        asImp_().evalVolumeTerms_();
+
+#if !defined NDEBUG && HAVE_VALGRIND
+        for (int i=0; i < fvGeometry_().numVertices; i++) {
+            Valgrind::CheckDefined(residual_[i]);
+        }
+#endif // HAVE_VALGRIND
+
+        // evaluate the boundary conditions
+        asImp_().evalBoundary_();
+
+#if !defined NDEBUG && HAVE_VALGRIND
+        for (int i=0; i < fvGeometry_().numVertices; i++)
+            Valgrind::CheckDefined(residual_[i]);
+#endif // HAVE_VALGRIND
+    }
+
+    /*!
+     * \brief Returns the local residual for all sub-control
+     *        volumes of the element.
+     */
+    const ElementSolutionVector &residual() const
+    { return residual_; }
+
+    /*!
+     * \brief Returns the local residual for a given sub-control
+     *        volume of the element.
+     *
+     * \param scvIdx The local index of the sub-control volume
+     *               (i.e. the element's local vertex index)
+     */
+    const PrimaryVariables &residual(const int scvIdx) const
+    { return residual_[scvIdx]; }
+
+    /*!
+     * \brief Returns the storage term for all sub-control volumes of the
+     *        element.
+     */
+    const ElementSolutionVector &storageTerm() const
+    { return storageTerm_; }
+
+    /*!
+     * \brief Returns the storage term for a given sub-control volumes
+     *        of the element.
+     */
+    const PrimaryVariables &storageTerm(const int scvIdx) const
+    { return storageTerm_[scvIdx]; }
+
+protected:
+    Implementation &asImp_()
+    {
+        assert(static_cast<Implementation*>(this) != 0);
+        return *static_cast<Implementation*>(this);
+    }
+
+    const Implementation &asImp_() const
+    {
+        assert(static_cast<const Implementation*>(this) != 0);
+        return *static_cast<const Implementation*>(this);
+    }
+
+    /*!
+     * \brief Evaluate the boundary conditions
+     *        of the current element.
+     */
+    void evalBoundary_()
+    {
+        if (bcTypes_().hasNeumann() || bcTypes_().hasOutflow())
+            asImp_().evalBoundaryFluxes_();
+#if !defined NDEBUG && HAVE_VALGRIND
+        for (int i=0; i < fvGeometry_().numVertices; i++)
+            Valgrind::CheckDefined(residual_[i]);
+#endif // HAVE_VALGRIND
+
+        if (bcTypes_().hasDirichlet())
+            asImp_().evalDirichlet_();
+    }
+
+    /*!
+     * \brief Set the values of the Dirichlet boundary control volumes
+     *        of the current element.
+     */
+    void evalDirichlet_()
+    {
+        PrimaryVariables dirichletValues(0);
+        for (int scvIdx = 0; scvIdx < fvGeometry_().numVertices; ++scvIdx) {
+            const BoundaryTypes &bcTypes = bcTypes_(scvIdx);
+            
+            if (bcTypes.hasDirichlet()) {
+                // ask the problem for the dirichlet values
+                const VertexPointer vPtr = element_().template subEntity<dim>(scvIdx);
+                Valgrind::SetUndefined(dirichletValues);
+                asImp_().problem_().dirichlet(dirichletValues, *vPtr);
+
+                // set the dirichlet conditions
+                for (int eqIdx = 0; eqIdx < numEq; ++eqIdx) {
+                    if (bcTypes.isDirichlet(eqIdx)) {
+                        int pvIdx = bcTypes.eqToDirichletIndex(eqIdx);
+                        assert(0 <= pvIdx && pvIdx < numEq);
+                        Valgrind::CheckDefined(dirichletValues[pvIdx]);
+
+                        residual_[scvIdx][eqIdx] =
+                                curPriVar_(scvIdx, pvIdx) - dirichletValues[pvIdx];
+
+                        storageTerm_[scvIdx][eqIdx] = 0.0;
+                    }
+                }
+            }
+        }
+    }
+
+    /*!
+     * \brief Add all Neumann and outflow boundary conditions to the local
+     *        residual.
+     */
+    void evalBoundaryFluxes_()
+    {
+        Dune::GeometryType geoType = element_().geometry().type();
+        const ReferenceElement &refElement = ReferenceElements::general(geoType);
+
+        IntersectionIterator isIt = gridView_().ibegin(element_());
+        const IntersectionIterator &endIt = gridView_().iend(element_());
+        for (; isIt != endIt; ++isIt)
+        {
+            // handle only faces on the boundary
+            if (isIt->boundary()) {
+                // Assemble the boundary for all vertices of the current
+                // face
+                int faceIdx = isIt->indexInInside();
+                int numFaceVerts = refElement.size(faceIdx, 1, dim);
+                for (int faceVertIdx = 0;
+                    faceVertIdx < numFaceVerts;
+                    ++faceVertIdx)
+                {
+                    int scvIdx = refElement.subEntity(faceIdx,
+                                                        1,
+                                                        faceVertIdx,
+                                                        dim);
+
+                    int boundaryFaceIdx =
+                        fvGeometry_().boundaryFaceIndex(faceIdx, faceVertIdx);
+
+                    // add the residual of all vertices of the boundary
+                    // segment
+                    asImp_().evalNeumannSegment_(isIt,
+                                                scvIdx,
+                                                boundaryFaceIdx);
+                    // evaluate the outflow conditions at the boundary face
+                    // ATTENTION: This is so far a beta version that is only for the 2p2c and 2p2cni model
+                    //              available and not thoroughly tested.
+                    asImp_().evalOutflowSegment_(isIt,
+                                                scvIdx,
+                                                boundaryFaceIdx);
+                }
+            }
+        }
+    }
+
+    /*!
+     * \brief Add Neumann boundary conditions for a single sub-control
+     *        volume face to the local residual.
+     */
+    void evalNeumannSegment_(const IntersectionIterator &isIt,
+                             const int scvIdx,
+                             const int boundaryFaceIdx)
+    {
+        // temporary vector to store the neumann boundary fluxes
+        PrimaryVariables neumannFlux(0.0);
+        const BoundaryTypes &bcTypes = bcTypes_(scvIdx);
+
+        // deal with neumann boundaries
+        if (bcTypes.hasNeumann()) {
+            Valgrind::SetUndefined(neumannFlux);
+            problem_().boxSDNeumann(neumannFlux,
+                                    element_(),
+                                    fvGeometry_(),
+                                    *isIt,
+                                    scvIdx,
+                                    boundaryFaceIdx,
+                                    curVolVars_());
+            neumannFlux *=
+                fvGeometry_().boundaryFace[boundaryFaceIdx].area
+                * curVolVars_(scvIdx).extrusionFactor();
+            Valgrind::CheckDefined(neumannFlux);
+
+            // set the neumann conditions
+            for (int eqIdx = 0; eqIdx < numEq; ++eqIdx) {
+                if (!bcTypes.isNeumann(eqIdx))
+                    continue;
+                residual_[scvIdx][eqIdx] += neumannFlux[eqIdx];
+            }
+        }
+    }
+
+    /*!
+    * \brief Add outflow boundary conditions for a single sub-control
+    *        volume face to the local residual.
+    *
+    * \param isIt   The intersection iterator of current element
+    * \param scvIdx The index of the considered face of the sub-control volume
+    * \param boundaryFaceIdx The index of the considered boundary face of the sub control volume
+    */
+    void evalOutflowSegment_(const IntersectionIterator &isIt,
+                            const int scvIdx,
+                            const int boundaryFaceIdx)
+    {
+        const BoundaryTypes &bcTypes = this->bcTypes_(scvIdx);
+        // deal with outflow boundaries
+        if (bcTypes.hasOutflow())
+        {
+            //calculate outflow fluxes
+            PrimaryVariables values(0.0);
+            asImp_().computeFlux(values, boundaryFaceIdx, true);
+            Valgrind::CheckDefined(values);
+            
+            for (int equationIdx = 0; equationIdx < numEq; ++equationIdx)
+            {
+                if (!bcTypes.isOutflow(equationIdx) )
+                    continue;
+                // deduce outflow
+                this->residual_[scvIdx][equationIdx] += values[equationIdx];
+            }
+        }
+    }
+
+    /*!
+     * \brief Add the flux terms to the local residual of all
+     *        sub-control volumes of the current element.
+     */
+    void evalFluxes_()
+    {
+        // calculate the mass flux over the faces and subtract
+        // it from the local rates
+        for (int scvfIdx = 0; scvfIdx < fvGeometry_().numEdges; scvfIdx++)
+        {
+            int i = fvGeometry_().subContVolFace[scvfIdx].i;
+            int j = fvGeometry_().subContVolFace[scvfIdx].j;
+
+            PrimaryVariables flux;
+
+            Valgrind::SetUndefined(flux);
+            asImp_().computeFlux(flux, scvfIdx);
+            Valgrind::CheckDefined(flux);
+
+            Scalar extrusionFactor =
+                (curVolVars_(i).extrusionFactor()
+                 + curVolVars_(j).extrusionFactor())
+                / 2;
+            flux *= extrusionFactor;
+
+            // The balance equation for a finite volume is:
+            //
+            // dStorage/dt = Flux + Source
+            //
+            // where the 'Flux' and the 'Source' terms represent the
+            // mass per second which _ENTER_ the finite
+            // volume. Re-arranging this, we get
+            //
+            // dStorage/dt - Source - Flux = 0
+            //
+            // Since the flux calculated by computeFlux() goes _OUT_
+            // of sub-control volume i and _INTO_ sub-control volume
+            // j, we need to add the flux to finite volume i and
+            // subtract it from finite volume j
+            residual_[i] += flux;
+            residual_[j] -= flux;
+        }
+    }
+
+    /*!
+     * \brief Set the local residual to the storage terms of all
+     *        sub-control volumes of the current element.
+     */
+    void evalStorage_()
+    {
+        storageTerm_.resize(fvGeometry_().numVertices);
+        storageTerm_ = 0;
+
+        // calculate the amount of conservation each quantity inside
+        // all sub control volumes
+        for (int scvIdx = 0; scvIdx < fvGeometry_().numVertices; scvIdx++) {
+            Valgrind::SetUndefined(storageTerm_[scvIdx]);
+            asImp_().computeStorage(storageTerm_[scvIdx], scvIdx, /*isOldSol=*/false);
+            storageTerm_[scvIdx] *=
+                fvGeometry_().subContVol[scvIdx].volume
+                * curVolVars_(scvIdx).extrusionFactor();
+            Valgrind::CheckDefined(storageTerm_[scvIdx]);
+        }
+    }
+
+    /*!
+     * \brief Add the change in the storage terms and the source term
+     *        to the local residual of all sub-control volumes of the
+     *        current element.
+     */
+    void evalVolumeTerms_()
+    {
+        // evaluate the volume terms (storage + source terms)
+        for (int scvIdx = 0; scvIdx < fvGeometry_().numVertices; scvIdx++)
+        {
+            Scalar extrusionFactor =
+                curVolVars_(scvIdx).extrusionFactor();
+
+            PrimaryVariables values(0.0);
+
+            // mass balance within the element. this is the
+            // \f$\frac{m}{\partial t}\f$ term if using implicit
+            // euler as time discretization.
+            //
+            // TODO (?): we might need a more explicit way for
+            // doing the time discretization...
+            Valgrind::SetUndefined(storageTerm_[scvIdx]);
+            Valgrind::SetUndefined(values);
+            asImp_().computeStorage(storageTerm_[scvIdx], scvIdx, false);
+            asImp_().computeStorage(values, scvIdx, true);
+            Valgrind::CheckDefined(storageTerm_[scvIdx]);
+            Valgrind::CheckDefined(values);
+
+            storageTerm_[scvIdx] -= values;
+            storageTerm_[scvIdx] *=
+                fvGeometry_().subContVol[scvIdx].volume
+                / problem_().timeManager().timeStepSize()
+                * extrusionFactor;
+            residual_[scvIdx] += storageTerm_[scvIdx];
+
+            // subtract the source term from the local rate
+            Valgrind::SetUndefined(values);
+            asImp_().computeSource(values, scvIdx);
+            Valgrind::CheckDefined(values);
+            values *= fvGeometry_().subContVol[scvIdx].volume * extrusionFactor;
+            residual_[scvIdx] -= values;
+
+            // make sure that only defined quantities were used
+            // to calculate the residual.
+            Valgrind::CheckDefined(residual_[scvIdx]);
+        }
+    }
+
+    /*!
+     * \brief Returns a reference to the problem.
+     */
+    const Problem &problem_() const
+    { return *problemPtr_; };
+
+    /*!
+     * \brief Returns a reference to the model.
+     */
+    const Model &model_() const
+    { return problem_().model(); };
+
+    /*!
+     * \brief Returns a reference to the vertex mapper.
+     */
+    const VertexMapper &vertexMapper_() const
+    { return problem_().vertexMapper(); };
+
+    /*!
+     * \brief Returns a reference to the grid view.
+     */
+    const GridView &gridView_() const
+    { return problem_().gridView(); }
+
+    /*!
+     * \brief Returns a reference to the current element.
+     */
+    const Element &element_() const
+    {
+        Valgrind::CheckDefined(elemPtr_);
+        return *elemPtr_;
+    }
+    
+    /*!
+     * \brief Returns a reference to the current element's finite
+     *        volume geometry.
+     */
+    const FVElementGeometry &fvGeometry_() const
+    {
+        Valgrind::CheckDefined(fvElemGeomPtr_);
+        return *fvElemGeomPtr_;
+    }
+
+    /*!
+     * \brief Returns a reference to the primary variables of
+     *           the last time step of the i'th
+     *        sub-control volume of the current element.
+     */
+    const PrimaryVariables &prevPriVars_(const int i) const
+    {
+        return prevVolVars_(i).priVars();
+    }
+
+    /*!
+     * \brief Returns a reference to the primary variables of the i'th
+     *        sub-control volume of the current element.
+     */
+    const PrimaryVariables &curPriVars_(const int i) const
+    {
+        return curVolVars_(i).priVars();
+    }
+
+    /*!
+     * \brief Returns the j'th primary of the i'th sub-control volume
+     *        of the current element.
+     */
+    Scalar curPriVar_(const int i, const int j) const
+    {
+        return curVolVars_(i).priVar(j);
+    }
+
+    /*!
+     * \brief Returns a reference to the current volume variables of
+     *        all sub-control volumes of the current element.
+     */
+    const ElementVolumeVariables &curVolVars_() const
+    {
+        Valgrind::CheckDefined(curVolVarsPtr_);
+        return *curVolVarsPtr_;
+    }
+
+    /*!
+     * \brief Returns a reference to the volume variables of the i-th
+     *        sub-control volume of the current element.
+     */
+    const VolumeVariables &curVolVars_(const int i) const
+    {
+        return curVolVars_()[i];
+    }
+
+    /*!
+     * \brief Returns a reference to the previous time step's volume
+     *        variables of all sub-control volumes of the current
+     *        element.
+     */
+    const ElementVolumeVariables &prevVolVars_() const
+    {
+        Valgrind::CheckDefined(prevVolVarsPtr_);
+        return *prevVolVarsPtr_;
+    }
+
+    /*!
+     * \brief Returns a reference to the previous time step's volume
+     *        variables of the i-th sub-control volume of the current
+     *        element.
+     */
+    const VolumeVariables &prevVolVars_(const int i) const
+    {
+        return prevVolVars_()[i];
+    }
+
+    /*!
+     * \brief Returns a reference to the boundary types of all
+     *        sub-control volumes of the current element.
+     */
+    const ElementBoundaryTypes &bcTypes_() const
+    {
+        Valgrind::CheckDefined(bcTypesPtr_);
+        return *bcTypesPtr_;
+    }
+
+    /*!
+     * \brief Returns a reference to the boundary types of the i-th
+     *        sub-control volume of the current element.
+     */
+    const BoundaryTypes &bcTypes_(const int i) const
+    {
+        return bcTypes_()[i];
+    }
+
+protected:
+    ElementSolutionVector storageTerm_;
+    ElementSolutionVector residual_;
+
+    // The problem we would like to solve
+    Problem *problemPtr_;
+
+    const Element *elemPtr_;
+    const FVElementGeometry *fvElemGeomPtr_;
+
+    // current and previous secondary variables for the element
+    const ElementVolumeVariables *prevVolVarsPtr_;
+    const ElementVolumeVariables *curVolVarsPtr_;
+
+    const ElementBoundaryTypes *bcTypesPtr_;
+};
+
+}
+
+#endif
diff --git a/dumux/implicit/common/implicitmodel.hh b/dumux/implicit/common/implicitmodel.hh
new file mode 100644
index 0000000000..567d706dd7
--- /dev/null
+++ b/dumux/implicit/common/implicitmodel.hh
@@ -0,0 +1,927 @@
+// -*- mode: C++; tab-width: 4; indent-tabs-mode: nil; c-basic-offset: 4 -*-
+// vi: set et ts=4 sw=4 sts=4:
+/*****************************************************************************
+ *   See the file COPYING for full copying permissions.                      *
+ *                                                                           *
+ *   This program is free software: you can redistribute it and/or modify    *
+ *   it under the terms of the GNU General Public License as published by    *
+ *   the Free Software Foundation, either version 2 of the License, or       *
+ *   (at your option) any later version.                                     *
+ *                                                                           *
+ *   This program is distributed in the hope that it will be useful,         *
+ *   but WITHOUT ANY WARRANTY; without even the implied warranty of          *
+ *   MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the            *
+ *   GNU General Public License for more details.                            *
+ *                                                                           *
+ *   You should have received a copy of the GNU General Public License       *
+ *   along with this program.  If not, see <http://www.gnu.org/licenses/>.   *
+ *****************************************************************************/
+/*!
+ * \file
+ *
+ * \brief Base class for models using box discretization
+ */
+#ifndef DUMUX_BOX_MODEL_HH
+#define DUMUX_BOX_MODEL_HH
+
+#include "boxproperties.hh"
+#include "boxpropertydefaults.hh"
+
+#include "boxelementvolumevariables.hh"
+#include "boxlocaljacobian.hh"
+#include "boxlocalresidual.hh"
+
+#include <dumux/parallel/vertexhandles.hh>
+
+#include <dune/grid/common/geometry.hh>
+
+namespace Dumux
+{
+
+/*!
+ * \ingroup BoxModel
+ *
+ * \brief The base class for the vertex centered finite volume
+ *        discretization scheme.
+ */
+template<class TypeTag>
+class BoxModel
+{
+    typedef typename GET_PROP_TYPE(TypeTag, Model) Implementation;
+    typedef typename GET_PROP_TYPE(TypeTag, Problem) Problem;
+    typedef typename GET_PROP_TYPE(TypeTag, GridView) GridView;
+    typedef typename GET_PROP_TYPE(TypeTag, Scalar) Scalar;
+    typedef typename GET_PROP_TYPE(TypeTag, ElementMapper) ElementMapper;
+    typedef typename GET_PROP_TYPE(TypeTag, VertexMapper) VertexMapper;
+    typedef typename GET_PROP_TYPE(TypeTag, DofMapper) DofMapper;
+    typedef typename GET_PROP_TYPE(TypeTag, SolutionVector) SolutionVector;
+    typedef typename GET_PROP_TYPE(TypeTag, PrimaryVariables) PrimaryVariables;
+    typedef typename GET_PROP_TYPE(TypeTag, JacobianAssembler) JacobianAssembler;
+    typedef typename GET_PROP_TYPE(TypeTag, ElementVolumeVariables) ElementVolumeVariables;
+    typedef typename GET_PROP_TYPE(TypeTag, VolumeVariables) VolumeVariables;
+
+    enum {
+        numEq = GET_PROP_VALUE(TypeTag, NumEq),
+        dim = GridView::dimension
+    };
+
+    typedef typename GET_PROP_TYPE(TypeTag, FVElementGeometry) FVElementGeometry;
+    typedef typename GET_PROP_TYPE(TypeTag, LocalJacobian) LocalJacobian;
+    typedef typename GET_PROP_TYPE(TypeTag, LocalResidual) LocalResidual;
+    typedef typename GET_PROP_TYPE(TypeTag, NewtonMethod) NewtonMethod;
+    typedef typename GET_PROP_TYPE(TypeTag, NewtonController) NewtonController;
+
+    typedef typename GridView::ctype CoordScalar;
+    typedef typename GridView::template Codim<0>::Entity Element;
+    typedef typename GridView::template Codim<0>::Iterator ElementIterator;
+    typedef typename GridView::template Codim<dim>::Entity Vertex;
+    typedef typename GridView::template Codim<dim>::Iterator VertexIterator;
+    typedef typename GridView::IntersectionIterator IntersectionIterator;
+
+    typedef typename Dune::GenericReferenceElements<CoordScalar, dim> ReferenceElements;
+    typedef typename Dune::GenericReferenceElement<CoordScalar, dim> ReferenceElement;
+
+    // copying a model is not a good idea
+    BoxModel(const BoxModel &);
+
+public:
+    /*!
+     * \brief The constructor.
+     */
+    BoxModel()
+    {
+        enableHints_ = GET_PARAM_FROM_GROUP(TypeTag, bool, Implicit, EnableHints);
+    }
+
+    ~BoxModel()
+    { delete jacAsm_;  }
+
+    /*!
+     * \brief Apply the initial conditions to the model.
+     *
+     * \param problem The object representing the problem which needs to
+     *             be simulated.
+     */
+    void init(Problem &problem)
+    {
+        problemPtr_ = &problem;
+
+        updateBoundaryIndices_();
+
+        int nDofs = asImp_().numDofs();
+        uCur_.resize(nDofs);
+        uPrev_.resize(nDofs);
+        boxVolume_.resize(nDofs);
+
+        localJacobian_.init(problem_());
+        jacAsm_ = new JacobianAssembler();
+        jacAsm_->init(problem_());
+
+        asImp_().applyInitialSolution_();
+
+        // resize the hint vectors
+        if (enableHints_) {
+            int nVerts = gridView_().size(dim);
+            curHints_.resize(nVerts);
+            prevHints_.resize(nVerts);
+            hintsUsable_.resize(nVerts);
+            std::fill(hintsUsable_.begin(),
+                      hintsUsable_.end(),
+                      false);
+        }
+
+        // also set the solution of the "previous" time step to the
+        // initial solution.
+        uPrev_ = uCur_;
+    }
+
+    void setHints(const Element &element,
+                  ElementVolumeVariables &prevVolVars,
+                  ElementVolumeVariables &curVolVars) const
+    {
+        if (!enableHints_)
+            return;
+
+        int n = element.template count<dim>();
+        prevVolVars.resize(n);
+        curVolVars.resize(n);
+        for (int i = 0; i < n; ++i) {
+            int globalIdx = vertexMapper().map(element, i, dim);
+
+            if (!hintsUsable_[globalIdx]) {
+                curVolVars[i].setHint(NULL);
+                prevVolVars[i].setHint(NULL);
+            }
+            else {
+                curVolVars[i].setHint(&curHints_[globalIdx]);
+                prevVolVars[i].setHint(&prevHints_[globalIdx]);
+            }
+        }
+    }
+
+    void setHints(const Element &element,
+                  ElementVolumeVariables &curVolVars) const
+    {
+        if (!enableHints_)
+            return;
+
+        int n = element.template count<dim>();
+        curVolVars.resize(n);
+        for (int i = 0; i < n; ++i) {
+            int globalIdx = vertexMapper().map(element, i, dim);
+
+            if (!hintsUsable_[globalIdx])
+                curVolVars[i].setHint(NULL);
+            else
+                curVolVars[i].setHint(&curHints_[globalIdx]);
+        }
+    }
+
+    void updatePrevHints()
+    {
+        if (!enableHints_)
+            return;
+
+        prevHints_ = curHints_;
+    }
+
+    void updateCurHints(const Element &element,
+                        const ElementVolumeVariables &elemVolVars) const
+    {
+        if (!enableHints_)
+            return;
+
+        for (unsigned int i = 0; i < elemVolVars.size(); ++i) {
+            int globalIdx = vertexMapper().map(element, i, dim);
+            curHints_[globalIdx] = elemVolVars[i];
+            if (!hintsUsable_[globalIdx])
+                prevHints_[globalIdx] = elemVolVars[i];
+            hintsUsable_[globalIdx] = true;
+        }
+    }
+
+
+    /*!
+     * \brief Compute the global residual for an arbitrary solution
+     *        vector.
+     *
+     * \param residual Stores the result
+     * \param u The solution for which the residual ought to be calculated
+     */
+    Scalar globalResidual(SolutionVector &residual,
+                          const SolutionVector &u)
+    {
+        SolutionVector tmp(curSol());
+        curSol() = u;
+        Scalar res = globalResidual(residual);
+        curSol() = tmp;
+        return res;
+    }
+
+    /*!
+     * \brief Compute the global residual for the current solution
+     *        vector.
+     *
+     * \param residual Stores the result
+     */
+    Scalar globalResidual(SolutionVector &residual)
+    {
+        residual = 0;
+
+        ElementIterator elemIt = gridView_().template begin<0>();
+        const ElementIterator elemEndIt = gridView_().template end<0>();
+        for (; elemIt != elemEndIt; ++elemIt) {
+            localResidual().eval(*elemIt);
+
+            for (int i = 0; i < elemIt->template count<dim>(); ++i) {
+                int globalI = vertexMapper().map(*elemIt, i, dim);
+                residual[globalI] += localResidual().residual(i);
+            }
+        }
+
+        // calculate the square norm of the residual
+        Scalar result2 = residual.two_norm2();
+        if (gridView_().comm().size() > 1)
+            result2 = gridView_().comm().sum(result2);
+
+        // add up the residuals on the process borders
+        if (gridView_().comm().size() > 1) {
+            VertexHandleSum<PrimaryVariables, SolutionVector, VertexMapper>
+                sumHandle(residual, vertexMapper());
+            gridView_().communicate(sumHandle,
+                                    Dune::InteriorBorder_InteriorBorder_Interface,
+                                    Dune::ForwardCommunication);
+        }
+
+        return std::sqrt(result2);
+    }
+
+    /*!
+     * \brief Compute the integral over the domain of the storage
+     *        terms of all conservation quantities.
+     *
+     * \param storage Stores the result
+     */
+    void globalStorage(PrimaryVariables &storage)
+    {
+        storage = 0;
+
+        ElementIterator elemIt = gridView_().template begin<0>();
+        const ElementIterator elemEndIt = gridView_().template end<0>();
+        for (; elemIt != elemEndIt; ++elemIt) {
+            localResidual().evalStorage(*elemIt);
+
+            for (int i = 0; i < elemIt->template count<dim>(); ++i)
+                storage += localResidual().storageTerm()[i];
+        }
+
+        if (gridView_().comm().size() > 1)
+            storage = gridView_().comm().sum(storage);
+    }
+
+    /*!
+     * \brief Returns the volume \f$\mathrm{[m^3]}\f$ of a given control volume.
+     *
+     * \param globalIdx The global index of the control volume's
+     *                  associated vertex
+     */
+    Scalar boxVolume(const int globalIdx) const
+    { return boxVolume_[globalIdx][0]; }
+
+    /*!
+     * \brief Reference to the current solution as a block vector.
+     */
+    const SolutionVector &curSol() const
+    { return uCur_; }
+
+    /*!
+     * \brief Reference to the current solution as a block vector.
+     */
+    SolutionVector &curSol()
+    { return uCur_; }
+
+    /*!
+     * \brief Reference to the previous solution as a block vector.
+     */
+    const SolutionVector &prevSol() const
+    { return uPrev_; }
+
+    /*!
+     * \brief Reference to the previous solution as a block vector.
+     */
+    SolutionVector &prevSol()
+    { return uPrev_; }
+
+    /*!
+     * \brief Returns the operator assembler for the global jacobian of
+     *        the problem.
+     */
+    JacobianAssembler &jacobianAssembler()
+    { return *jacAsm_; }
+
+    /*!
+     * \copydoc jacobianAssembler()
+     */
+    const JacobianAssembler &jacobianAssembler() const
+    { return *jacAsm_; }
+
+    /*!
+     * \brief Returns the local jacobian which calculates the local
+     *        stiffness matrix for an arbitrary element.
+     *
+     * The local stiffness matrices of the element are used by
+     * the jacobian assembler to produce a global linerization of the
+     * problem.
+     */
+    LocalJacobian &localJacobian()
+    { return localJacobian_; }
+    /*!
+     * \copydoc localJacobian()
+     */
+    const LocalJacobian &localJacobian() const
+    { return localJacobian_; }
+
+    /*!
+     * \brief Returns the local residual function.
+     */
+    LocalResidual &localResidual()
+    { return localJacobian().localResidual(); }
+    /*!
+     * \copydoc localResidual()
+     */
+    const LocalResidual &localResidual() const
+    { return localJacobian().localResidual(); }
+
+    /*!
+     * \brief Returns the relative error between two vectors of
+     *        primary variables.
+     *
+     * \param vertexIdx The global index of the control volume's
+     *                  associated vertex
+     * \param priVars1 The first vector of primary variables
+     * \param priVars2 The second vector of primary variables
+     *
+     * \todo The vertexIdx argument is pretty hacky. it is required by
+     *       models with pseudo primary variables (i.e. the primary
+     *       variable switching models). the clean solution would be
+     *       to access the pseudo primary variables from the primary
+     *       variables.
+     */
+    Scalar relativeErrorVertex(const int vertexIdx,
+                               const PrimaryVariables &priVars1,
+                               const PrimaryVariables &priVars2)
+    {
+        Scalar result = 0.0;
+        for (int j = 0; j < numEq; ++j) {
+            Scalar eqErr = std::abs(priVars1[j] - priVars2[j]);
+            eqErr /= std::max<Scalar>(1.0, std::abs(priVars1[j] + priVars2[j])/2);
+
+            result = std::max(result, eqErr);
+        }
+        return result;
+    }
+
+    /*!
+     * \brief Try to progress the model to the next timestep.
+     *
+     * \param solver The non-linear solver
+     * \param controller The controller which specifies the behaviour
+     *                   of the non-linear solver
+     */
+    bool update(NewtonMethod &solver,
+                NewtonController &controller)
+    {
+#if HAVE_VALGRIND
+        for (size_t i = 0; i < curSol().size(); ++i)
+            Valgrind::CheckDefined(curSol()[i]);
+#endif // HAVE_VALGRIND
+
+        asImp_().updateBegin();
+
+        bool converged = solver.execute(controller);
+        if (converged) {
+            asImp_().updateSuccessful();
+        }
+        else
+            asImp_().updateFailed();
+
+#if HAVE_VALGRIND
+        for (size_t i = 0; i < curSol().size(); ++i) {
+            Valgrind::CheckDefined(curSol()[i]);
+        }
+#endif // HAVE_VALGRIND
+
+        return converged;
+    }
+
+
+    /*!
+     * \brief Called by the update() method before it tries to
+     *        apply the newton method. This is primary a hook
+     *        which the actual model can overload.
+     */
+    void updateBegin()
+    { }
+
+
+    /*!
+     * \brief Called by the update() method if it was
+     *        successful. This is primary a hook which the actual
+     *        model can overload.
+     */
+    void updateSuccessful()
+    { }
+
+    /*!
+     * \brief Called by the update() method if it was
+     *        unsuccessful. This is primary a hook which the actual
+     *        model can overload.
+     */
+    void updateFailed()
+    {
+        // Reset the current solution to the one of the
+        // previous time step so that we can start the next
+        // update at a physically meaningful solution.
+        uCur_ = uPrev_;
+        curHints_ = prevHints_;
+
+        jacAsm_->reassembleAll();
+    }
+
+    /*!
+     * \brief Called by the problem if a time integration was
+     *        successful, post processing of the solution is done and
+     *        the result has been written to disk.
+     *
+     * This should prepare the model for the next time integration.
+     */
+    void advanceTimeLevel()
+    {
+        // make the current solution the previous one.
+        uPrev_ = uCur_;
+        prevHints_ = curHints_;
+
+        updatePrevHints();
+    }
+
+    /*!
+     * \brief Serializes the current state of the model.
+     *
+     * \tparam Restarter The type of the serializer class
+     *
+     * \param res The serializer object
+     */
+    template <class Restarter>
+    void serialize(Restarter &res)
+    { res.template serializeEntities<dim>(asImp_(), this->gridView_()); }
+
+    /*!
+     * \brief Deserializes the state of the model.
+     *
+     * \tparam Restarter The type of the serializer class
+     *
+     * \param res The serializer object
+     */
+    template <class Restarter>
+    void deserialize(Restarter &res)
+    {
+        res.template deserializeEntities<dim>(asImp_(), this->gridView_());
+        prevSol() = curSol();
+    }
+
+    /*!
+     * \brief Write the current solution for a vertex to a restart
+     *        file.
+     *
+     * \param outstream The stream into which the vertex data should
+     *                  be serialized to
+     * \param vertex The DUNE Codim<dim> entity which's data should be
+     *             serialized
+     */
+    void serializeEntity(std::ostream &outstream,
+                         const Vertex &vertex)
+    {
+        int vertIdx = dofMapper().map(vertex);
+
+        // write phase state
+        if (!outstream.good()) {
+            DUNE_THROW(Dune::IOError,
+                       "Could not serialize vertex "
+                       << vertIdx);
+        }
+
+        for (int eqIdx = 0; eqIdx < numEq; ++eqIdx) {
+            outstream << curSol()[vertIdx][eqIdx] << " ";
+        }
+    }
+
+    /*!
+     * \brief Reads the current solution variables for a vertex from a
+     *        restart file.
+     *
+     * \param instream The stream from which the vertex data should
+     *                  be deserialized from
+     * \param vertex The DUNE Codim<dim> entity which's data should be
+     *             deserialized
+     */
+    void deserializeEntity(std::istream &instream,
+                           const Vertex &vertex)
+    {
+        int vertIdx = dofMapper().map(vertex);
+        for (int eqIdx = 0; eqIdx < numEq; ++eqIdx) {
+            if (!instream.good())
+                DUNE_THROW(Dune::IOError,
+                           "Could not deserialize vertex "
+                           << vertIdx);
+            instream >> curSol()[vertIdx][eqIdx];
+        }
+    }
+
+    /*!
+     * \brief Returns the number of global degrees of freedoms (DOFs)
+     */
+    size_t numDofs() const
+    { return gridView_().size(dim); }
+
+    /*!
+     * \brief Mapper for the entities where degrees of freedoms are
+     *        defined to indices.
+     *
+     * This usually means a mapper for vertices.
+     */
+    const DofMapper &dofMapper() const
+    { return problem_().vertexMapper(); }
+
+    /*!
+     * \brief Mapper for vertices to indices.
+     */
+    const VertexMapper &vertexMapper() const
+    { return problem_().vertexMapper(); }
+
+    /*!
+     * \brief Mapper for elements to indices.
+     */
+    const ElementMapper &elementMapper() const
+    { return problem_().elementMapper(); }
+
+    /*!
+     * \brief Resets the Jacobian matrix assembler, so that the
+     *        boundary types can be altered.
+     */
+    void resetJacobianAssembler ()
+    {
+        delete jacAsm_;
+        jacAsm_ = new JacobianAssembler;
+        jacAsm_->init(problem_());
+    }
+
+    /*!
+     * \brief Update the weights of all primary variables within an
+     *        element given the complete set of volume variables
+     *
+     * \param element The DUNE codim 0 entity
+     * \param volVars All volume variables for the element
+     */
+    void updatePVWeights(const Element &element,
+                         const ElementVolumeVariables &volVars) const
+    { }
+
+    /*!
+     * \brief Add the vector fields for analysing the convergence of
+     *        the newton method to the a VTK multi writer.
+     *
+     * \tparam MultiWriter The type of the VTK multi writer
+     *
+     * \param writer  The VTK multi writer object on which the fields should be added.
+     * \param u       The solution function
+     * \param deltaU  The delta of the solution function before and after the Newton update
+     */
+    template <class MultiWriter>
+    void addConvergenceVtkFields(MultiWriter &writer,
+                                 const SolutionVector &u,
+                                 const SolutionVector &deltaU)
+    {
+        typedef Dune::BlockVector<Dune::FieldVector<double, 1> > ScalarField;
+
+        SolutionVector residual(u);
+        asImp_().globalResidual(residual, u);
+
+        // create the required scalar fields
+        unsigned numVertices = this->gridView_().size(dim);
+
+        // global defect of the two auxiliary equations
+        ScalarField* def[numEq];
+        ScalarField* delta[numEq];
+        ScalarField* x[numEq];
+        for (int eqIdx = 0; eqIdx < numEq; ++eqIdx) {
+            x[eqIdx] = writer.allocateManagedBuffer(numVertices);
+            delta[eqIdx] = writer.allocateManagedBuffer(numVertices);
+            def[eqIdx] = writer.allocateManagedBuffer(numVertices);
+        }
+
+        VertexIterator vIt = this->gridView_().template begin<dim>();
+        VertexIterator vEndIt = this->gridView_().template end<dim>();
+        for (; vIt != vEndIt; ++ vIt)
+        {
+            int globalIdx = vertexMapper().map(*vIt);
+            for (int eqIdx = 0; eqIdx < numEq; ++eqIdx) {
+                (*x[eqIdx])[globalIdx] = u[globalIdx][eqIdx];
+                (*delta[eqIdx])[globalIdx] = - deltaU[globalIdx][eqIdx];
+                (*def[eqIdx])[globalIdx] = residual[globalIdx][eqIdx];
+            }
+        }
+
+        for (int eqIdx = 0; eqIdx < numEq; ++eqIdx) {
+            std::ostringstream oss;
+            oss.str(""); oss << "x_" << eqIdx;
+            writer.attachVertexData(*x[eqIdx], oss.str());
+            oss.str(""); oss << "delta_" << eqIdx;
+            writer.attachVertexData(*delta[eqIdx], oss.str());
+            oss.str(""); oss << "defect_" << eqIdx;
+            writer.attachVertexData(*def[eqIdx], oss.str());
+        }
+
+        asImp_().addOutputVtkFields(u, writer);
+    }
+
+    /*!
+     * \brief Add the quantities of a time step which ought to be written to disk.
+     *
+     * This should be overwritten by the actual model if any secondary
+     * variables should be written out. Read: This should _always_ be
+     * overwritten by well behaved models!
+     *
+     * \tparam MultiWriter The type of the VTK multi writer
+     *
+     * \param sol The global vector of primary variable values.
+     * \param writer The VTK multi writer where the fields should be added.
+     */
+    template <class MultiWriter>
+    void addOutputVtkFields(const SolutionVector &sol,
+                            MultiWriter &writer)
+    {
+        typedef Dune::BlockVector<Dune::FieldVector<Scalar, 1> > ScalarField;
+
+        // create the required scalar fields
+        unsigned numVertices = this->gridView_().size(dim);
+
+        // global defect of the two auxiliary equations
+        ScalarField* x[numEq];
+        for (int eqIdx = 0; eqIdx < numEq; ++eqIdx) {
+            x[eqIdx] = writer.allocateManagedBuffer(numVertices);
+        }
+
+        VertexIterator vIt = this->gridView_().template begin<dim>();
+        VertexIterator vEndIt = this->gridView_().template end<dim>();
+        for (; vIt != vEndIt; ++ vIt)
+        {
+            int globalIdx = vertexMapper().map(*vIt);
+            for (int eqIdx = 0; eqIdx < numEq; ++eqIdx) {
+                (*x[eqIdx])[globalIdx] = sol[globalIdx][eqIdx];
+            }
+        }
+
+        for (int eqIdx = 0; eqIdx < numEq; ++eqIdx) {
+            std::ostringstream oss;
+            oss << "primaryVar_" << eqIdx;
+            writer.attachVertexData(*x[eqIdx], oss.str());
+        }
+    }
+
+    /*!
+     * \brief Reference to the grid view of the spatial domain.
+     */
+    const GridView &gridView() const
+    { return problem_().gridView(); }
+
+    /*!
+     * \brief Returns true if the vertex with 'globalVertIdx' is
+     *        located on the grid's boundary.
+     *
+     * \param globalVertIdx The global index of the control volume's
+     *                      associated vertex
+     */
+    bool onBoundary(const int globalVertIdx) const
+    { return boundaryIndices_[globalVertIdx]; }
+
+    /*!
+     * \brief Returns true if a vertex is located on the grid's
+     *        boundary.
+     *
+     * \param element A DUNE Codim<0> entity which contains the control
+     *             volume's associated vertex.
+     * \param vIdx The local vertex index inside element
+     */
+    bool onBoundary(const Element &element, const int vIdx) const
+    { return onBoundary(vertexMapper().map(element, vIdx, dim)); }
+
+    /*!
+     * \brief Fill the fluid state according to the primary variables. 
+     * 
+     * Taking the information from the primary variables, 
+     * the fluid state is filled with every information that is 
+     * necessary to evaluate the model's local residual. 
+     * 
+     * \param priVars The primary variables of the model.
+     * \param problem The problem at hand. 
+     * \param element The current element. 
+     * \param fvGeometry The finite volume element geometry.
+     * \param scvIdx The index of the subcontrol volume. 
+     * \param fluidState The fluid state to fill. 
+     */
+    template <class FluidState>
+    static void completeFluidState(const PrimaryVariables& priVars,
+                                   const Problem& problem,
+                                   const Element& element,
+                                   const FVElementGeometry& fvGeometry,
+                                   const int scvIdx,
+                                   FluidState& fluidState)
+    {
+        VolumeVariables::completeFluidState(priVars, problem, element,
+                                            fvGeometry, scvIdx, fluidState);
+    }
+protected:
+    /*!
+     * \brief A reference to the problem on which the model is applied.
+     */
+    Problem &problem_()
+    { return *problemPtr_; }
+    /*!
+     * \copydoc problem_()
+     */
+    const Problem &problem_() const
+    { return *problemPtr_; }
+
+    /*!
+     * \brief Reference to the grid view of the spatial domain.
+     */
+    const GridView &gridView_() const
+    { return problem_().gridView(); }
+
+    /*!
+     * \brief Reference to the local residal object
+     */
+    LocalResidual &localResidual_()
+    { return localJacobian_.localResidual(); }
+
+    /*!
+     * \brief Applies the initial solution for all vertices of the grid.
+     */
+    void applyInitialSolution_()
+    {
+        // first set the whole domain to zero
+        uCur_ = Scalar(0.0);
+        boxVolume_ = Scalar(0.0);
+
+        FVElementGeometry fvGeometry;
+
+        // iterate through leaf grid and evaluate initial
+        // condition at the center of each sub control volume
+        //
+        // TODO: the initial condition needs to be unique for
+        // each vertex. we should think about the API...
+        ElementIterator eIt = gridView_().template begin<0>();
+        const ElementIterator &eEndIt = gridView_().template end<0>();
+        for (; eIt != eEndIt; ++eIt) {
+            // deal with the current element
+            fvGeometry.update(gridView_(), *eIt);
+
+            // loop over all element vertices, i.e. sub control volumes
+            for (int scvIdx = 0; scvIdx < fvGeometry.numVertices; scvIdx++)
+            {
+                // map the local vertex index to the global one
+                int globalIdx = vertexMapper().map(*eIt,
+                                                   scvIdx,
+                                                   dim);
+
+                // let the problem do the dirty work of nailing down
+                // the initial solution.
+                PrimaryVariables initPriVars;
+                Valgrind::SetUndefined(initPriVars);
+                problem_().initial(initPriVars,
+                                   *eIt,
+                                   fvGeometry,
+                                   scvIdx);
+                Valgrind::CheckDefined(initPriVars);
+
+                // add up the initial values of all sub-control
+                // volumes. If the initial values disagree for
+                // different sub control volumes, the initial value
+                // will be the arithmetic mean.
+                initPriVars *= fvGeometry.subContVol[scvIdx].volume;
+                boxVolume_[globalIdx] += fvGeometry.subContVol[scvIdx].volume;
+                uCur_[globalIdx] += initPriVars;
+                Valgrind::CheckDefined(uCur_[globalIdx]);
+            }
+        }
+
+        // add up the primary variables and the volumes of the boxes
+        // which cross process borders
+        if (gridView_().comm().size() > 1) {
+            VertexHandleSum<Dune::FieldVector<Scalar, 1>,
+                Dune::BlockVector<Dune::FieldVector<Scalar, 1> >,
+                VertexMapper> sumVolumeHandle(boxVolume_, vertexMapper());
+            gridView_().communicate(sumVolumeHandle,
+                                    Dune::InteriorBorder_InteriorBorder_Interface,
+                                    Dune::ForwardCommunication);
+
+            VertexHandleSum<PrimaryVariables, SolutionVector, VertexMapper>
+                sumPVHandle(uCur_, vertexMapper());
+            gridView_().communicate(sumPVHandle,
+                                    Dune::InteriorBorder_InteriorBorder_Interface,
+                                    Dune::ForwardCommunication);
+        }
+
+        // divide all primary variables by the volume of their boxes
+        int n = gridView_().size(dim);
+        for (int i = 0; i < n; ++i) {
+            uCur_[i] /= boxVolume(i);
+        }
+    }
+
+    /*!
+     * \brief Find all indices of boundary vertices.
+     *
+     * For this we need to loop over all intersections (which is slow
+     * in general). If the DUNE grid interface would provide a
+     * onBoundary() method for entities this could be done in a much
+     * nicer way (actually this would not be necessary)
+     */
+    void updateBoundaryIndices_()
+    {
+        boundaryIndices_.resize(numDofs());
+        std::fill(boundaryIndices_.begin(), boundaryIndices_.end(), false);
+
+        ElementIterator eIt = gridView_().template begin<0>();
+        ElementIterator eEndIt = gridView_().template end<0>();
+        for (; eIt != eEndIt; ++eIt) {
+            Dune::GeometryType geoType = eIt->geometry().type();
+            const ReferenceElement &refElement = ReferenceElements::general(geoType);
+
+            IntersectionIterator isIt = gridView_().ibegin(*eIt);
+            IntersectionIterator isEndIt = gridView_().iend(*eIt);
+            for (; isIt != isEndIt; ++isIt) {
+                if (isIt->boundary()) {
+                    // add all vertices on the intersection to the set of
+                    // boundary vertices
+                    int faceIdx = isIt->indexInInside();
+                    int numFaceVerts = refElement.size(faceIdx, 1, dim);
+                    for (int faceVertIdx = 0;
+                        faceVertIdx < numFaceVerts;
+                        ++faceVertIdx)
+                    {
+                        int elemVertIdx = refElement.subEntity(faceIdx,
+                                                            1,
+                                                            faceVertIdx,
+                                                            dim);
+                        int globalVertIdx = vertexMapper().map(*eIt, elemVertIdx, dim);
+                        boundaryIndices_[globalVertIdx] = true;
+                    }
+                }
+            }
+        }
+    }
+
+    // the hint cache for the previous and the current volume
+    // variables
+    mutable std::vector<bool> hintsUsable_;
+    mutable std::vector<VolumeVariables> curHints_;
+    mutable std::vector<VolumeVariables> prevHints_;
+
+    // the problem we want to solve. defines the constitutive
+    // relations, matxerial laws, etc.
+    Problem *problemPtr_;
+
+    // calculates the local jacobian matrix for a given element
+    LocalJacobian localJacobian_;
+    // Linearizes the problem at the current time step using the
+    // local jacobian
+    JacobianAssembler *jacAsm_;
+
+    // the set of all indices of vertices on the boundary
+    std::vector<bool> boundaryIndices_;
+
+    // cur is the current iterative solution, prev the converged
+    // solution of the previous time step
+    SolutionVector uCur_;
+    SolutionVector uPrev_;
+
+    Dune::BlockVector<Dune::FieldVector<Scalar, 1> > boxVolume_;
+
+private:
+    /*!
+     * \brief Returns whether messages should be printed
+     */
+    bool verbose_() const
+    { return gridView_().comm().rank() == 0; }
+
+    Implementation &asImp_()
+    { return *static_cast<Implementation*>(this); }
+    const Implementation &asImp_() const
+    { return *static_cast<const Implementation*>(this); }
+
+    bool enableHints_;
+};
+}
+
+#endif
diff --git a/dumux/implicit/common/implicitproblem.hh b/dumux/implicit/common/implicitproblem.hh
new file mode 100644
index 0000000000..c455443807
--- /dev/null
+++ b/dumux/implicit/common/implicitproblem.hh
@@ -0,0 +1,835 @@
+// -*- mode: C++; tab-width: 4; indent-tabs-mode: nil; c-basic-offset: 4 -*-
+// vi: set et ts=4 sw=4 sts=4:
+/*****************************************************************************
+ *   See the file COPYING for full copying permissions.                      *
+ *                                                                           *
+ *   This program is free software: you can redistribute it and/or modify    *
+ *   it under the terms of the GNU General Public License as published by    *
+ *   the Free Software Foundation, either version 2 of the License, or       *
+ *   (at your option) any later version.                                     *
+ *                                                                           *
+ *   This program is distributed in the hope that it will be useful,         *
+ *   but WITHOUT ANY WARRANTY; without even the implied warranty of          *
+ *   MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the            *
+ *   GNU General Public License for more details.                            *
+ *                                                                           *
+ *   You should have received a copy of the GNU General Public License       *
+ *   along with this program.  If not, see <http://www.gnu.org/licenses/>.   *
+ *****************************************************************************/
+/*!
+ * \file
+ * \brief Base class for all problems which use the box scheme
+ */
+#ifndef DUMUX_BOX_PROBLEM_HH
+#define DUMUX_BOX_PROBLEM_HH
+
+#include "boxproperties.hh"
+
+#include <dumux/io/vtkmultiwriter.hh>
+#include <dumux/io/restart.hh>
+
+namespace Dumux
+{
+/*!
+ * \ingroup BoxModel
+ * \ingroup BoxBaseProblems
+ * \brief Base class for all problems which use the box scheme.
+ *
+ * \note All quantities are specified assuming a threedimensional
+ *       world. Problems discretized using 2D grids are assumed to be
+ *       extruded by \f$1 m\f$ and 1D grids are assumed to have a
+ *       cross section of \f$1m \times 1m\f$.
+ */
+template<class TypeTag>
+class BoxProblem
+{
+private:
+    typedef typename GET_PROP_TYPE(TypeTag, Problem) Implementation;
+    typedef typename GET_PROP_TYPE(TypeTag, GridView) GridView;
+
+    typedef Dumux::VtkMultiWriter<GridView> VtkMultiWriter;
+
+    typedef typename GET_PROP_TYPE(TypeTag, NewtonMethod) NewtonMethod;
+    typedef typename GET_PROP_TYPE(TypeTag, NewtonController) NewtonController;
+
+    typedef typename GET_PROP_TYPE(TypeTag, Model) Model;
+    typedef typename GET_PROP_TYPE(TypeTag, Scalar) Scalar;
+    typedef typename GET_PROP_TYPE(TypeTag, TimeManager) TimeManager;
+
+    typedef typename GET_PROP_TYPE(TypeTag, VertexMapper) VertexMapper;
+    typedef typename GET_PROP_TYPE(TypeTag, ElementMapper) ElementMapper;
+
+    typedef typename GET_PROP_TYPE(TypeTag, PrimaryVariables) PrimaryVariables;
+    typedef typename GET_PROP_TYPE(TypeTag, ElementVolumeVariables) ElementVolumeVariables;
+    typedef typename GET_PROP_TYPE(TypeTag, FVElementGeometry) FVElementGeometry;
+    typedef typename GET_PROP_TYPE(TypeTag, BoundaryTypes) BoundaryTypes;
+
+    enum {
+        dim = GridView::dimension,
+        dimWorld = GridView::dimensionworld
+    };
+
+    typedef typename GridView::template Codim<0>::Entity Element;
+    typedef typename GridView::template Codim<dim>::Entity Vertex;
+    typedef typename GridView::template Codim<dim>::Iterator VertexIterator;
+    typedef typename GridView::Intersection Intersection;
+
+    typedef typename GridView::Grid::ctype CoordScalar;
+    typedef Dune::FieldVector<CoordScalar, dimWorld> GlobalPosition;
+
+    // copying a problem is not a good idea
+    BoxProblem(const BoxProblem &);
+
+public:
+    /*!
+     * \brief Constructor
+     *
+     * \param timeManager The TimeManager which is used by the simulation
+     * \param gridView The simulation's idea about physical space
+     */
+    BoxProblem(TimeManager &timeManager, const GridView &gridView)
+        : gridView_(gridView)
+        , bboxMin_(std::numeric_limits<double>::max())
+        , bboxMax_(-std::numeric_limits<double>::max())
+        , elementMapper_(gridView)
+        , vertexMapper_(gridView)
+        , timeManager_(&timeManager)
+        , newtonMethod_(asImp_())
+        , newtonCtl_(asImp_())
+    {
+        // calculate the bounding box of the local partition of the grid view
+        VertexIterator vIt = gridView.template begin<dim>();
+        const VertexIterator vEndIt = gridView.template end<dim>();
+        for (; vIt!=vEndIt; ++vIt) {
+            for (int i=0; i<dim; i++) {
+                bboxMin_[i] = std::min(bboxMin_[i], vIt->geometry().corner(0)[i]);
+                bboxMax_[i] = std::max(bboxMax_[i], vIt->geometry().corner(0)[i]);
+            }
+        }
+
+        // communicate to get the bounding box of the whole domain
+        if (gridView.comm().size() > 1)
+            for (int i = 0; i < dim; ++i) {
+                bboxMin_[i] = gridView.comm().min(bboxMin_[i]);
+                bboxMax_[i] = gridView.comm().max(bboxMax_[i]);
+            }
+
+        // set a default name for the problem
+        simName_ = "sim";
+
+        resultWriter_ = NULL;
+    }
+
+    ~BoxProblem()
+    {
+        delete resultWriter_;
+    };
+
+
+    /*!
+     * \brief Called by the Dumux::TimeManager in order to
+     *        initialize the problem.
+     *
+     * If you overload this method don't forget to call
+     * ParentType::init()
+     */
+    void init()
+    {
+        // set the initial condition of the model
+        model().init(asImp_());
+    }
+
+    /*!
+     * \brief Specifies which kind of boundary condition should be
+     *        used for which equation on a given boundary segment.
+     *
+     * \param values The boundary types for the conservation equations
+     * \param vertex The vertex for which the boundary type is set
+     */
+    void boundaryTypes(BoundaryTypes &values,
+                       const Vertex &vertex) const
+    {
+        // forward it to the method which only takes the global coordinate
+        asImp_().boundaryTypesAtPos(values, vertex.geometry().center());
+    }
+
+    /*!
+     * \brief Specifies which kind of boundary condition should be
+     *        used for which equation on a given boundary segment.
+     *
+     * \param values The boundary types for the conservation equations
+     * \param pos The position of the finite volume in global coordinates
+     */
+    void boundaryTypesAtPos(BoundaryTypes &values,
+                            const GlobalPosition &pos) const
+    {
+        // Throw an exception (there is no reasonable default value
+        // for Dirichlet conditions)
+        DUNE_THROW(Dune::InvalidStateException,
+                   "The problem does not provide "
+                   "a boundaryTypes() method.");
+    }
+
+
+    /*!
+     * \brief Evaluate the boundary conditions for a dirichlet
+     *        control volume.
+     *
+     * \param values The dirichlet values for the primary variables
+     * \param vertex The vertex representing the "half volume on the boundary"
+     *
+     * For this method, the \a values parameter stores primary variables.
+     */
+    void dirichlet(PrimaryVariables &values,
+                   const Vertex &vertex) const
+    {
+        // forward it to the method which only takes the global coordinate
+        asImp_().dirichletAtPos(values, vertex.geometry().center());
+    }
+
+    /*!
+     * \brief Evaluate the boundary conditions for a dirichlet
+     *        control volume.
+     *
+     * \param values The dirichlet values for the primary variables
+     * \param pos The position of the center of the finite volume
+     *            for which the dirichlet condition ought to be
+     *            set in global coordinates
+     *
+     * For this method, the \a values parameter stores primary variables.
+     */
+    void dirichletAtPos(PrimaryVariables &values,
+                        const GlobalPosition &pos) const
+    {
+        // Throw an exception (there is no reasonable default value
+        // for Dirichlet conditions)
+        DUNE_THROW(Dune::InvalidStateException,
+                   "The problem specifies that some boundary "
+                   "segments are dirichlet, but does not provide "
+                   "a dirichlet() method.");
+    }
+
+    /*!
+     * \brief Evaluate the boundary conditions for a neumann
+     *        boundary segment.
+     *
+     * This is the method for the case where the Neumann condition is
+     * potentially solution dependent and requires some box method
+     * specific things.
+     *
+     * \param values The neumann values for the conservation equations [kg / (m^2 *s )]
+     * \param element The finite element
+     * \param fvGeometry The finite-volume geometry in the box scheme
+     * \param is The intersection between element and boundary
+     * \param scvIdx The local vertex index
+     * \param boundaryFaceIdx The index of the boundary face
+     * \param elemVolVars All volume variables for the element
+     *
+     * For this method, the \a values parameter stores the mass flux
+     * in normal direction of each phase. Negative values mean influx.
+     */
+    void boxSDNeumann(PrimaryVariables &values,
+                      const Element &element,
+                      const FVElementGeometry &fvGeometry,
+                      const Intersection &is,
+                      const int scvIdx,
+                      const int boundaryFaceIdx,
+                      const ElementVolumeVariables &elemVolVars) const
+    {
+        // forward it to the interface without the volume variables
+        asImp_().neumann(values,
+                         element,
+                         fvGeometry,
+                         is,
+                         scvIdx,
+                         boundaryFaceIdx);
+    }
+
+    /*!
+     * \brief Evaluate the boundary conditions for a neumann
+     *        boundary segment.
+     *
+     * \param values The neumann values for the conservation equations [kg / (m^2 *s )]
+     * \param element The finite element
+     * \param fvGeometry The finite-volume geometry in the box scheme
+     * \param is The intersection between element and boundary
+     * \param scvIdx The local vertex index
+     * \param boundaryFaceIdx The index of the boundary face
+     *
+     * For this method, the \a values parameter stores the mass flux
+     * in normal direction of each phase. Negative values mean influx.
+     */
+    void neumann(PrimaryVariables &values,
+                 const Element &element,
+                 const FVElementGeometry &fvGeometry,
+                 const Intersection &is,
+                 const int scvIdx,
+                 const int boundaryFaceIdx) const
+    {
+        // forward it to the interface with only the global position
+        asImp_().neumannAtPos(values, fvGeometry.boundaryFace[boundaryFaceIdx].ipGlobal);
+    }
+
+    /*!
+     * \brief Evaluate the boundary conditions for a neumann
+     *        boundary segment.
+     *
+     * \param values The neumann values for the conservation equations [kg / (m^2 *s )]
+     * \param pos The position of the boundary face's integration point in global coordinates
+     *
+     * For this method, the \a values parameter stores the mass flux
+     * in normal direction of each phase. Negative values mean influx.
+     */
+    void neumannAtPos(PrimaryVariables &values,
+                      const GlobalPosition &pos) const
+    {
+        // Throw an exception (there is no reasonable default value
+        // for Neumann conditions)
+        DUNE_THROW(Dune::InvalidStateException,
+                   "The problem specifies that some boundary "
+                   "segments are neumann, but does not provide "
+                   "a neumannAtPos() method.");
+    }
+
+    /*!
+     * \brief Evaluate the source term for all phases within a given
+     *        sub-control-volume.
+     *
+     * This is the method for the case where the source term is
+     * potentially solution dependent and requires some box method
+     * specific things.
+     *
+     * \param values The source and sink values for the conservation equations
+     * \param element The finite element
+     * \param fvGeometry The finite-volume geometry in the box scheme
+     * \param scvIdx The local vertex index
+     * \param elemVolVars All volume variables for the element
+     *
+     * For this method, the \a values parameter stores the rate mass
+     * generated or annihilate per volume unit. Positive values mean
+     * that mass is created, negative ones mean that it vanishes.
+     */
+    void boxSDSource(PrimaryVariables &values,
+                     const Element &element,
+                     const FVElementGeometry &fvGeometry,
+                     const int scvIdx,
+                     const ElementVolumeVariables &elemVolVars) const
+    {
+        // forward to solution independent, box specific interface
+        asImp_().source(values, element, fvGeometry, scvIdx);
+    }
+
+    /*!
+     * \brief Evaluate the source term for all phases within a given
+     *        sub-control-volume.
+     *
+     * \param values The source and sink values for the conservation equations
+     * \param element The finite element
+     * \param fvGeometry The finite-volume geometry in the box scheme
+     * \param scvIdx The local vertex index
+     *
+     * For this method, the \a values parameter stores the rate mass
+     * generated or annihilate per volume unit. Positive values mean
+     * that mass is created, negative ones mean that it vanishes.
+     */
+    void source(PrimaryVariables &values,
+                const Element &element,
+                const FVElementGeometry &fvGeometry,
+                const int scvIdx) const
+    {
+        // forward to generic interface
+        asImp_().sourceAtPos(values, fvGeometry.subContVol[scvIdx].global);
+    }
+
+    /*!
+     * \brief Evaluate the source term for all phases within a given
+     *        sub-control-volume.
+     *
+     * \param values The source and sink values for the conservation equations
+     * \param pos The position of the center of the finite volume
+     *            for which the source term ought to be
+     *            specified in global coordinates
+     *
+     * For this method, the \a values parameter stores the rate mass
+     * generated or annihilate per volume unit. Positive values mean
+     * that mass is created, negative ones mean that it vanishes.
+     */
+    void sourceAtPos(PrimaryVariables &values,
+                     const GlobalPosition &pos) const
+    {
+        DUNE_THROW(Dune::InvalidStateException,
+                   "The problem does not provide "
+                   "a sourceAtPos() method.");
+    }
+
+    /*!
+     * \brief Evaluate the initial value for a control volume.
+     *
+     * \param values The initial values for the primary variables
+     * \param element The finite element
+     * \param fvGeometry The finite-volume geometry in the box scheme
+     * \param scvIdx The local vertex index
+     *
+     * For this method, the \a values parameter stores primary
+     * variables.
+     */
+    void initial(PrimaryVariables &values,
+                 const Element &element,
+                 const FVElementGeometry &fvGeometry,
+                 const int scvIdx) const
+    {
+        // forward to generic interface
+        asImp_().initialAtPos(values, fvGeometry.subContVol[scvIdx].global);
+    }
+
+    /*!
+     * \brief Evaluate the initial value for a control volume.
+     *
+     * \param values The dirichlet values for the primary variables
+     * \param pos The position of the center of the finite volume
+     *            for which the initial values ought to be
+     *            set (in global coordinates)
+     *
+     * For this method, the \a values parameter stores primary variables.
+     */
+    void initialAtPos(PrimaryVariables &values,
+                      const GlobalPosition &pos) const
+    {
+        // Throw an exception (there is no reasonable default value
+        // for Dirichlet conditions)
+        DUNE_THROW(Dune::InvalidStateException,
+                   "The problem does not provide "
+                   "a initialAtPos() method.");
+    }
+
+    /*!
+     * \brief Return how much the domain is extruded at a given sub-control volume.
+     *
+     * This means the factor by which a lower-dimensional (1D or 2D)
+     * entity needs to be expanded to get a full dimensional cell. The
+     * default is 1.0 which means that 1D problems are actually
+     * thought as pipes with a cross section of 1 m^2 and 2D problems
+     * are assumed to extend 1 m to the back.
+     */
+    Scalar boxExtrusionFactor(const Element &element,
+                              const FVElementGeometry &fvGeometry,
+                              const int scvIdx) const
+    {
+        // forward to generic interface
+        return asImp_().extrusionFactorAtPos(fvGeometry.subContVol[scvIdx].global);
+    }
+
+    /*!
+     * \brief Return how much the domain is extruded at a given position.
+     *
+     * This means the factor by which a lower-dimensional (1D or 2D)
+     * entity needs to be expanded to get a full dimensional cell. The
+     * default is 1.0 which means that 1D problems are actually
+     * thought as pipes with a cross section of 1 m^2 and 2D problems
+     * are assumed to extend 1 m to the back.
+     */
+    Scalar extrusionFactorAtPos(const GlobalPosition &pos) const
+    { return 1.0; }
+
+    /*!
+     * \brief If model coupling is used, this updates the parameters
+     *        required to calculate the coupling fluxes between the
+     *        sub-models.
+     *
+     * By default it does nothing
+     *
+     * \param element The DUNE Codim<0> entity for which the coupling
+     *                parameters should be computed.
+     */
+    void updateCouplingParams(const Element &element) const
+    {}
+
+    /*!
+     * \name Simulation steering
+     */
+    // \{
+
+    /*!
+     * \brief Called by the time manager before the time integration.
+     */
+    void preTimeStep()
+    {}
+
+    /*!
+     * \brief Called by Dumux::TimeManager in order to do a time
+     *        integration on the model.
+     */
+    void timeIntegration()
+    {
+        const int maxFails = 10;
+        for (int i = 0; i < maxFails; ++i) {
+            if (model_.update(newtonMethod_, newtonCtl_))
+                return;
+
+            Scalar dt = timeManager().timeStepSize();
+            Scalar nextDt = dt / 2;
+            timeManager().setTimeStepSize(nextDt);
+
+            // update failed
+            std::cout << "Newton solver did not converge with dt="<<dt<<" seconds. Retrying with time step of "
+                      << nextDt << " seconds\n";
+        }
+
+        DUNE_THROW(Dune::MathError,
+                   "Newton solver didn't converge after "
+                   << maxFails
+                   << " time-step divisions. dt="
+                   << timeManager().timeStepSize());
+    }
+
+    /*!
+     * \brief Returns the newton method object
+     */
+    NewtonMethod &newtonMethod()
+    { return newtonMethod_; }
+
+    /*!
+     * \copydoc newtonMethod()
+     */
+    const NewtonMethod &newtonMethod() const
+    { return newtonMethod_; }
+
+    /*!
+     * \brief Returns the newton contoller object
+     */
+    NewtonController &newtonController()
+    { return newtonCtl_; }
+
+    /*!
+     * \copydoc newtonController()
+     */
+    const NewtonController &newtonController() const
+    { return newtonCtl_; }
+
+    /*!
+     * \brief Called by Dumux::TimeManager whenever a solution for a
+     *        time step has been computed and the simulation time has
+     *        been updated.
+     *
+     * \param dt The current time-step size
+     */
+    Scalar nextTimeStepSize(const Scalar dt)
+    {
+        return std::min(GET_PARAM_FROM_GROUP(TypeTag, Scalar, TimeManager, MaxTimeStepSize),
+                        newtonCtl_.suggestTimeStepSize(dt));
+    };
+
+    /*!
+     * \brief Returns true if a restart file should be written to
+     *        disk.
+     *
+     * The default behavior is to write one restart file every 5 time
+     * steps. This file is intended to be overwritten by the
+     * implementation.
+     */
+    bool shouldWriteRestartFile() const
+    {
+        return timeManager().timeStepIndex() > 0 &&
+            (timeManager().timeStepIndex() % 10 == 0);
+    }
+
+    /*!
+     * \brief Returns true if the current solution should be written to
+     *        disk (i.e. as a VTK file)
+     *
+     * The default behavior is to write out every the solution for
+     * very time step. This file is intended to be overwritten by the
+     * implementation.
+     */
+    bool shouldWriteOutput() const
+    { return true; }
+
+    /*!
+     * \brief Called by the time manager after the time integration to
+     *        do some post processing on the solution.
+     */
+    void postTimeStep()
+    { }
+
+    /*!
+     * \brief Called by the time manager after everything which can be
+     *        done about the current time step is finished and the
+     *        model should be prepared to do the next time integration.
+     */
+    void advanceTimeLevel()
+    {
+        model_.advanceTimeLevel();
+    }
+
+    /*!
+     * \brief Called when the end of an simulation episode is reached.
+     *
+     * Typically a new episode should be started in this method.
+     */
+    void episodeEnd()
+    {
+        std::cerr << "The end of an episode is reached, but the problem "
+                  << "does not override the episodeEnd() method. "
+                  << "Doing nothing!\n";
+    };
+    // \}
+
+    /*!
+     * \brief The problem name.
+     *
+     * This is used as a prefix for files generated by the simulation.
+     * It could be either overwritten by the problem files, or simply
+     * declared over the setName() function in the application file.
+     */
+    const char *name() const
+    {
+        return simName_.c_str();
+    }
+
+    /*!
+     * \brief Set the problem name.
+     *
+     * This static method sets the simulation name, which should be
+     * called before the application problem is declared! If not, the
+     * default name "sim" will be used.
+     *
+     * \param newName The problem's name
+     */
+    void setName(const char *newName)
+    {
+        simName_ = newName;
+    }
+
+
+    /*!
+     * \brief Returns the number of the current VTK file.
+     */
+    int currentVTKFileNumber()
+    {
+        createResultWriter_();
+        return resultWriter_->curWriterNum();
+    }
+
+    /*!
+     * \brief The GridView which used by the problem.
+     */
+    const GridView &gridView() const
+    { return gridView_; }
+
+    /*!
+     * \brief The coordinate of the corner of the GridView's bounding
+     *        box with the smallest values.
+     */
+    const GlobalPosition &bboxMin() const
+    { return bboxMin_; }
+
+    /*!
+     * \brief The coordinate of the corner of the GridView's bounding
+     *        box with the largest values.
+     */
+    const GlobalPosition &bboxMax() const
+    { return bboxMax_; }
+
+    /*!
+     * \brief Returns the mapper for vertices to indices.
+     */
+    const VertexMapper &vertexMapper() const
+    { return vertexMapper_; }
+
+    /*!
+     * \brief Returns the mapper for elements to indices.
+     */
+    const ElementMapper &elementMapper() const
+    { return elementMapper_; }
+
+    /*!
+     * \brief Returns TimeManager object used by the simulation
+     */
+    TimeManager &timeManager()
+    { return *timeManager_; }
+
+    /*!
+     * \copydoc timeManager()
+     */
+    const TimeManager &timeManager() const
+    { return *timeManager_; }
+
+    /*!
+     * \brief Returns numerical model used for the problem.
+     */
+    Model &model()
+    { return model_; }
+
+    /*!
+     * \copydoc model()
+     */
+    const Model &model() const
+    { return model_; }
+    // \}
+
+    /*!
+     * \name Restart mechanism
+     */
+    // \{
+
+    /*!
+     * \brief This method writes the complete state of the simulation
+     *        to the harddisk.
+     *
+     * The file will start with the prefix returned by the name()
+     * method, has the current time of the simulation clock in it's
+     * name and uses the extension <tt>.drs</tt>. (Dumux ReStart
+     * file.)  See Dumux::Restart for details.
+     */
+    void serialize()
+    {
+        typedef Dumux::Restart Restarter;
+        Restarter res;
+        res.serializeBegin(asImp_());
+        if (gridView().comm().rank() == 0)
+            std::cout << "Serialize to file '" << res.fileName() << "'\n";
+
+        timeManager().serialize(res);
+        asImp_().serialize(res);
+        res.serializeEnd();
+    }
+
+    /*!
+     * \brief This method writes the complete state of the problem
+     *        to the harddisk.
+     *
+     * The file will start with the prefix returned by the name()
+     * method, has the current time of the simulation clock in it's
+     * name and uses the extension <tt>.drs</tt>. (Dumux ReStart
+     * file.)  See Dumux::Restart for details.
+     *
+     * \tparam Restarter The serializer type
+     *
+     * \param res The serializer object
+     */
+    template <class Restarter>
+    void serialize(Restarter &res)
+    {
+        createResultWriter_();
+        resultWriter_->serialize(res);
+        model().serialize(res);
+    }
+
+    /*!
+     * \brief Load a previously saved state of the whole simulation
+     *        from disk.
+     *
+     * \param tRestart The simulation time on which the program was
+     *                 written to disk.
+     */
+    void restart(const Scalar tRestart)
+    {
+        typedef Dumux::Restart Restarter;
+
+        Restarter res;
+
+        res.deserializeBegin(asImp_(), tRestart);
+        if (gridView().comm().rank() == 0)
+            std::cout << "Deserialize from file '" << res.fileName() << "'\n";
+        timeManager().deserialize(res);
+        asImp_().deserialize(res);
+        res.deserializeEnd();
+    }
+
+    /*!
+     * \brief This method restores the complete state of the problem
+     *        from disk.
+     *
+     * It is the inverse of the serialize() method.
+     *
+     * \tparam Restarter The deserializer type
+     *
+     * \param res The deserializer object
+     */
+    template <class Restarter>
+    void deserialize(Restarter &res)
+    {
+        createResultWriter_();
+        resultWriter_->deserialize(res);
+        model().deserialize(res);
+    }
+
+    // \}
+
+    /*!
+     * \brief Adds additional VTK output data to the VTKWriter. Function is called by writeOutput().
+     */
+    void addOutputVtkFields()
+    {}
+
+    /*!
+     * \brief Write the relevant secondary variables of the current
+     *        solution into an VTK output file.
+     */
+    void writeOutput(const bool verbose = true)
+    {
+        // write the current result to disk
+        if (asImp_().shouldWriteOutput()) {
+            if (verbose && gridView().comm().rank() == 0)
+                std::cout << "Writing result file for \"" << asImp_().name() << "\"\n";
+
+            // calculate the time _after_ the time was updated
+            Scalar t = timeManager().time() + timeManager().timeStepSize();
+            createResultWriter_();
+            resultWriter_->beginWrite(t);
+            model().addOutputVtkFields(model().curSol(), *resultWriter_);
+            asImp_().addOutputVtkFields();
+            resultWriter_->endWrite();
+        }
+    }
+
+protected:
+    //! Returns the implementation of the problem (i.e. static polymorphism)
+    Implementation &asImp_()
+    { return *static_cast<Implementation *>(this); }
+
+    //! \copydoc asImp_()
+    const Implementation &asImp_() const
+    { return *static_cast<const Implementation *>(this); }
+
+    //! Returns the applied VTK-writer for the output
+    VtkMultiWriter& resultWriter()
+    {
+        createResultWriter_();
+        return *resultWriter_;
+    }
+    //! \copydoc Dumux::IMPETProblem::resultWriter()
+    VtkMultiWriter& resultWriter() const
+    {
+        createResultWriter_();
+        return *resultWriter_;
+    }
+
+
+private:
+    // makes sure that the result writer exists
+    void createResultWriter_()
+    { if (!resultWriter_) resultWriter_ = new VtkMultiWriter(gridView_, asImp_().name()); };
+
+    std::string simName_;
+    const GridView gridView_;
+
+    GlobalPosition bboxMin_;
+    GlobalPosition bboxMax_;
+
+    ElementMapper elementMapper_;
+    VertexMapper vertexMapper_;
+
+    TimeManager *timeManager_;
+
+    Model model_;
+
+    NewtonMethod newtonMethod_;
+    NewtonController newtonCtl_;
+
+    VtkMultiWriter *resultWriter_;
+};
+
+}
+
+#endif
diff --git a/dumux/implicit/common/implicitproperties.hh b/dumux/implicit/common/implicitproperties.hh
new file mode 100644
index 0000000000..9fd7fffa05
--- /dev/null
+++ b/dumux/implicit/common/implicitproperties.hh
@@ -0,0 +1,142 @@
+// -*- mode: C++; tab-width: 4; indent-tabs-mode: nil; c-basic-offset: 4 -*-
+// vi: set et ts=4 sw=4 sts=4:
+/*****************************************************************************
+ *   See the file COPYING for full copying permissions.                      *
+ *                                                                           *
+ *   This program is free software: you can redistribute it and/or modify    *
+ *   it under the terms of the GNU General Public License as published by    *
+ *   the Free Software Foundation, either version 2 of the License, or       *
+ *   (at your option) any later version.                                     *
+ *                                                                           *
+ *   This program is distributed in the hope that it will be useful,         *
+ *   but WITHOUT ANY WARRANTY; without even the implied warranty of          *
+ *   MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the            *
+ *   GNU General Public License for more details.                            *
+ *                                                                           *
+ *   You should have received a copy of the GNU General Public License       *
+ *   along with this program.  If not, see <http://www.gnu.org/licenses/>.   *
+ *****************************************************************************/
+#ifndef DUMUX_BOX_PROPERTIES_HH
+#define DUMUX_BOX_PROPERTIES_HH
+
+#include <dumux/common/propertysystem.hh>
+
+#include <dumux/common/basicproperties.hh>
+#include <dumux/linear/linearsolverproperties.hh>
+#include <dumux/nonlinear/newtonmethod.hh>
+
+/*!
+ * \ingroup Properties
+ * \ingroup BoxProperties
+ * \ingroup BoxModel
+ * \file
+ * \brief Specify the shape functions, operator assemblers, etc
+ *        used for the BoxModel.
+ */
+namespace Dumux
+{
+
+namespace Properties
+{
+/*!
+ * \ingroup BoxModel
+ */
+// \{
+
+//////////////////////////////////////////////////////////////////
+// Type tags
+//////////////////////////////////////////////////////////////////
+
+//! The type tag for models based on the box-scheme
+NEW_TYPE_TAG(BoxModel, INHERITS_FROM(NewtonMethod, LinearSolverTypeTag, ImplicitModel));
+
+//////////////////////////////////////////////////////////////////
+// Property tags
+//////////////////////////////////////////////////////////////////
+
+NEW_PROP_TAG(Grid);     //!< The type of the DUNE grid
+NEW_PROP_TAG(GridView); //!< The type of the grid view
+
+NEW_PROP_TAG(FVElementGeometry); //! The type of the finite-volume geometry in the box scheme
+NEW_PROP_TAG(EvalGradientsAtSCVCenter); //! Evaluate shape function gradients additionally at the sub-control volume center
+
+NEW_PROP_TAG(Problem); //!< The type of the problem
+NEW_PROP_TAG(BaseModel); //!< The type of the base class of the model
+NEW_PROP_TAG(Model); //!< The type of the model
+NEW_PROP_TAG(NumEq); //!< Number of equations in the system of PDEs
+NEW_PROP_TAG(BaseLocalResidual); //!< The type of the base class of the local residual
+NEW_PROP_TAG(LocalResidual); //!< The type of the local residual function
+NEW_PROP_TAG(LocalJacobian); //!< The type of the local jacobian operator
+
+NEW_PROP_TAG(JacobianAssembler); //!< Assembles the global jacobian matrix
+NEW_PROP_TAG(JacobianMatrix); //!< Type of the global jacobian matrix
+NEW_PROP_TAG(BoundaryTypes); //!< Stores the boundary types of a single degree of freedom
+NEW_PROP_TAG(ElementBoundaryTypes); //!< Stores the boundary types on an element
+
+NEW_PROP_TAG(PrimaryVariables); //!< A vector of primary variables within a sub-control volume
+NEW_PROP_TAG(SolutionVector); //!< Vector containing all primary variable vector of the grid
+NEW_PROP_TAG(ElementSolutionVector); //!< A vector of primary variables within a sub-control volume
+
+NEW_PROP_TAG(VolumeVariables);  //!< The secondary variables within a sub-control volume
+NEW_PROP_TAG(ElementVolumeVariables); //!< The secondary variables of all sub-control volumes in an element
+NEW_PROP_TAG(FluxVariables); //!< Data required to calculate a flux over a face
+NEW_PROP_TAG(BoundaryVariables); //!< Data required to calculate fluxes over boundary faces (outflow)
+
+// high level simulation control
+NEW_PROP_TAG(TimeManager);  //!< Manages the simulation time
+NEW_PROP_TAG(NewtonMethod);     //!< The type of the newton method
+NEW_PROP_TAG(NewtonController); //!< The type of the newton controller
+
+//! Specify whether the jacobian matrix of the last iteration of a
+//! time step should be re-used as the jacobian of the first iteration
+//! of the next time step.
+NEW_PROP_TAG(ImplicitEnableJacobianRecycling);
+
+//! Specify whether the jacobian matrix should be only reassembled for
+//! elements where at least one vertex is above the specified
+//! tolerance
+NEW_PROP_TAG(ImplicitEnablePartialReassemble);
+/*!
+ * \brief Specify the maximum size of a time integration [s].
+ *
+ * The default is to not limit the step size.
+ */
+NEW_PROP_TAG(TimeManagerMaxTimeStepSize);
+
+/*!
+ * \brief Specify which kind of method should be used to numerically
+ * calculate the partial derivatives of the residual.
+ *
+ * -1 means backward differences, 0 means central differences, 1 means
+ * forward differences. By default we use central differences.
+ */
+NEW_PROP_TAG(ImplicitNumericDifferenceMethod);
+
+/*!
+ * \brief Specify whether to use the already calculated solutions as
+ *        starting values of the volume variables.
+ *
+ * This only makes sense if the calculation of the volume variables is
+ * very expensive (e.g. for non-linear fugacity functions where the
+ * solver converges faster).
+ */
+NEW_PROP_TAG(ImplicitEnableHints);
+
+//! indicates whether two-point flux should be used
+NEW_PROP_TAG(ImplicitUseTwoPointFlux); 
+
+// mappers from local to global indices
+
+//! maper for vertices
+NEW_PROP_TAG(VertexMapper);
+//! maper for elements
+NEW_PROP_TAG(ElementMapper);
+//! maper for degrees of freedom
+NEW_PROP_TAG(DofMapper);
+
+}
+}
+
+// \}
+
+#endif
diff --git a/dumux/implicit/common/implicitpropertydefaults.hh b/dumux/implicit/common/implicitpropertydefaults.hh
new file mode 100644
index 0000000000..50ec31e2c7
--- /dev/null
+++ b/dumux/implicit/common/implicitpropertydefaults.hh
@@ -0,0 +1,207 @@
+// -*- mode: C++; tab-width: 4; indent-tabs-mode: nil; c-basic-offset: 4 -*-
+// vi: set et ts=4 sw=4 sts=4:
+/*****************************************************************************
+ *   See the file COPYING for full copying permissions.                      *
+ *                                                                           *
+ *   This program is free software: you can redistribute it and/or modify    *
+ *   it under the terms of the GNU General Public License as published by    *
+ *   the Free Software Foundation, either version 2 of the License, or       *
+ *   (at your option) any later version.                                     *
+ *                                                                           *
+ *   This program is distributed in the hope that it will be useful,         *
+ *   but WITHOUT ANY WARRANTY; without even the implied warranty of          *
+ *   MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the            *
+ *   GNU General Public License for more details.                            *
+ *                                                                           *
+ *   You should have received a copy of the GNU General Public License       *
+ *   along with this program.  If not, see <http://www.gnu.org/licenses/>.   *
+ *****************************************************************************/
+/*!
+ * \ingroup Properties
+ * \ingroup BoxProperties
+ * \ingroup BoxModel
+ * \file
+ *
+ * \brief Default properties for box models
+ */
+#ifndef DUMUX_BOX_PROPERTY_DEFAULTS_HH
+#define DUMUX_BOX_PROPERTY_DEFAULTS_HH
+
+#include <dumux/nonlinear/newtonmethod.hh>
+#include <dumux/nonlinear/newtoncontroller.hh>
+
+#include "boxassembler.hh"
+#include "boxmodel.hh"
+#include "boxfvelementgeometry.hh"
+#include "boxelementboundarytypes.hh"
+#include "boxlocaljacobian.hh"
+#include "boxlocalresidual.hh"
+#include "boxelementvolumevariables.hh"
+#include "boxvolumevariables.hh"
+
+#include <dumux/common/boundarytypes.hh>
+#include <dumux/common/timemanager.hh>
+
+#include "boxproperties.hh"
+
+#include <limits>
+
+namespace Dumux {
+
+// forward declaration
+template<class TypeTag>
+class BoxModel;
+
+namespace Properties {
+//////////////////////////////////////////////////////////////////
+// Some defaults for very fundamental properties
+//////////////////////////////////////////////////////////////////
+
+//! Set the default type for the time manager
+SET_TYPE_PROP(BoxModel, TimeManager, Dumux::TimeManager<TypeTag>);
+
+//////////////////////////////////////////////////////////////////
+// Properties
+//////////////////////////////////////////////////////////////////
+
+//! Use the leaf grid view if not defined otherwise
+SET_TYPE_PROP(BoxModel,
+              GridView,
+              typename GET_PROP_TYPE(TypeTag, Grid)::LeafGridView);
+
+//! Set the default for the FVElementGeometry
+SET_TYPE_PROP(BoxModel, FVElementGeometry, Dumux::BoxFVElementGeometry<TypeTag>);
+
+//! Disable evaluation of shape function gradients at the sub-control volume center by default
+// The shape function gradients at the sub-control volume center are currently only
+// needed for the stokes and the linear elastic models
+SET_BOOL_PROP(BoxModel, EvalGradientsAtSCVCenter, false);
+
+//! Set the default for the ElementBoundaryTypes
+SET_TYPE_PROP(BoxModel, ElementBoundaryTypes, Dumux::BoxElementBoundaryTypes<TypeTag>);
+
+//! use the plain newton method for the box scheme by default
+SET_TYPE_PROP(BoxModel, NewtonMethod, Dumux::NewtonMethod<TypeTag>);
+
+//! use the plain newton controller for the box scheme by default
+SET_TYPE_PROP(BoxModel, NewtonController, Dumux::NewtonController<TypeTag>);
+
+//! Mapper for the grid view's vertices.
+SET_TYPE_PROP(BoxModel,
+              VertexMapper,
+              Dune::MultipleCodimMultipleGeomTypeMapper<typename GET_PROP_TYPE(TypeTag, GridView),
+                                                        Dune::MCMGVertexLayout>);
+
+//! Mapper for the grid view's elements.
+SET_TYPE_PROP(BoxModel,
+              ElementMapper,
+              Dune::MultipleCodimMultipleGeomTypeMapper<typename GET_PROP_TYPE(TypeTag, GridView),
+                                                        Dune::MCMGElementLayout>);
+
+//! Mapper for the degrees of freedoms.
+SET_TYPE_PROP(BoxModel, DofMapper, typename GET_PROP_TYPE(TypeTag, VertexMapper));
+
+//! Set the BaseLocalResidual to BoxLocalResidual
+SET_TYPE_PROP(BoxModel, BaseLocalResidual, Dumux::BoxLocalResidual<TypeTag>);
+
+//! Set the BaseModel to BoxModel
+SET_TYPE_PROP(BoxModel, BaseModel, Dumux::BoxModel<TypeTag>);
+
+//! The local jacobian operator for the box scheme
+SET_TYPE_PROP(BoxModel, LocalJacobian, Dumux::BoxLocalJacobian<TypeTag>);
+
+/*!
+ * \brief The type of a solution for the whole grid at a fixed time.
+ */
+SET_TYPE_PROP(BoxModel,
+              SolutionVector,
+              Dune::BlockVector<typename GET_PROP_TYPE(TypeTag, PrimaryVariables)>);
+
+/*!
+ * \brief The type of a solution for a whole element.
+ */
+SET_TYPE_PROP(BoxModel,
+              ElementSolutionVector,
+              Dune::BlockVector<typename GET_PROP_TYPE(TypeTag, PrimaryVariables)>);
+
+/*!
+ * \brief A vector of primary variables.
+ */
+SET_TYPE_PROP(BoxModel,
+              PrimaryVariables,
+              Dune::FieldVector<typename GET_PROP_TYPE(TypeTag, Scalar),
+                                GET_PROP_VALUE(TypeTag, NumEq)>);
+
+/*!
+ * \brief The volume variable class.
+ *
+ * This should almost certainly be overloaded by the model...
+ */
+SET_TYPE_PROP(BoxModel, VolumeVariables, Dumux::BoxVolumeVariables<TypeTag>);
+
+/*!
+ * \brief An array of secondary variable containers.
+ */
+SET_TYPE_PROP(BoxModel, ElementVolumeVariables, Dumux::BoxElementVolumeVariables<TypeTag>);
+
+/*!
+ * \brief Boundary types at a single degree of freedom.
+ */
+SET_TYPE_PROP(BoxModel,
+              BoundaryTypes,
+              Dumux::BoundaryTypes<GET_PROP_VALUE(TypeTag, NumEq)>);
+
+/*!
+ * \brief Assembler for the global jacobian matrix.
+ */
+SET_TYPE_PROP(BoxModel, JacobianAssembler, Dumux::BoxAssembler<TypeTag>);
+
+//! use an unlimited time step size by default
+SET_SCALAR_PROP(BoxModel, TimeManagerMaxTimeStepSize, 1e100);
+
+//! use forward differences to calculate the jacobian by default
+SET_INT_PROP(BoxModel, ImplicitNumericDifferenceMethod, +1);
+
+//! do not use hints by default
+SET_BOOL_PROP(BoxModel, ImplicitEnableHints, false);
+
+// disable jacobian matrix recycling by default
+SET_BOOL_PROP(BoxModel, ImplicitEnableJacobianRecycling, false);
+
+// disable partial reassembling by default
+SET_BOOL_PROP(BoxModel, ImplicitEnablePartialReassemble, false);
+
+// disable two-point-flux by default
+SET_BOOL_PROP(BoxModel, ImplicitUseTwoPointFlux, false);
+
+//! Set the type of a global jacobian matrix from the solution types
+SET_PROP(BoxModel, JacobianMatrix)
+{
+private:
+    typedef typename GET_PROP_TYPE(TypeTag, Scalar) Scalar;
+    enum { numEq = GET_PROP_VALUE(TypeTag, NumEq) };
+    typedef typename Dune::FieldMatrix<Scalar, numEq, numEq> MatrixBlock;
+public:
+    typedef typename Dune::BCRSMatrix<MatrixBlock> type;
+};
+
+// use the stabilized BiCG solver preconditioned by the ILU-0 by default
+SET_TYPE_PROP(BoxModel, LinearSolver, Dumux::BoxBiCGStabILU0Solver<TypeTag> );
+
+// if the deflection of the newton method is large, we do not
+// need to solve the linear approximation accurately. Assuming
+// that the initial value for the delta vector u is quite
+// close to the final value, a reduction of 6 orders of
+// magnitude in the defect should be sufficient...
+SET_SCALAR_PROP(BoxModel, LinearSolverResidualReduction, 1e-6);
+
+//! set the default number of maximum iterations for the linear solver
+SET_INT_PROP(BoxModel, LinearSolverMaxIterations, 250);
+
+//! set number of equations of the mathematical model as default
+SET_INT_PROP(BoxModel, LinearSolverBlockSize, GET_PROP_VALUE(TypeTag, NumEq));
+
+} // namespace Properties
+} // namespace Dumux
+
+#endif
diff --git a/dumux/implicit/common/implicitvolumevariables.hh b/dumux/implicit/common/implicitvolumevariables.hh
new file mode 100644
index 0000000000..0c0bb6d8f6
--- /dev/null
+++ b/dumux/implicit/common/implicitvolumevariables.hh
@@ -0,0 +1,190 @@
+// -*- mode: C++; tab-width: 4; indent-tabs-mode: nil; c-basic-offset: 4 -*-
+// vi: set et ts=4 sw=4 sts=4:
+/*****************************************************************************
+ *   See the file COPYING for full copying permissions.                      *
+ *                                                                           *
+ *   This program is free software: you can redistribute it and/or modify    *
+ *   it under the terms of the GNU General Public License as published by    *
+ *   the Free Software Foundation, either version 2 of the License, or       *
+ *   (at your option) any later version.                                     *
+ *                                                                           *
+ *   This program is distributed in the hope that it will be useful,         *
+ *   but WITHOUT ANY WARRANTY; without even the implied warranty of          *
+ *   MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the            *
+ *   GNU General Public License for more details.                            *
+ *                                                                           *
+ *   You should have received a copy of the GNU General Public License       *
+ *   along with this program.  If not, see <http://www.gnu.org/licenses/>.   *
+ *****************************************************************************/
+/*!
+ * \file
+ *
+ * \brief Base class for the model specific class which provides
+ *        access to all volume averaged quantities.
+ */
+#ifndef DUMUX_BOX_VOLUME_VARIABLES_HH
+#define DUMUX_BOX_VOLUME_VARIABLES_HH
+
+#include "boxproperties.hh"
+
+#include <dumux/common/valgrind.hh>
+
+namespace Dumux
+{
+
+/*!
+ * \ingroup BoxModel
+ * \ingroup BoxVolumeVariables
+ * \brief Base class for the model specific class which provides
+ *        access to all volume averaged quantities.
+ */
+template <class TypeTag>
+class BoxVolumeVariables
+{
+    typedef typename GET_PROP_TYPE(TypeTag, VolumeVariables) Implementation;
+
+    typedef typename GET_PROP_TYPE(TypeTag, Scalar) Scalar;
+    typedef typename GET_PROP_TYPE(TypeTag, Problem) Problem;
+    typedef typename GET_PROP_TYPE(TypeTag, GridView) GridView;
+    typedef typename GridView::template Codim<0>::Entity Element;
+    typedef typename GET_PROP_TYPE(TypeTag, FVElementGeometry) FVElementGeometry;
+
+    typedef typename GET_PROP_TYPE(TypeTag, PrimaryVariables) PrimaryVariables;
+
+public:
+    // default constructor
+    BoxVolumeVariables()
+    { evalPoint_ = 0; };
+
+    // copy constructor
+    BoxVolumeVariables(const BoxVolumeVariables &v)
+    {
+        evalPoint_ = 0;
+        priVars_ = v.priVars_;
+        extrusionFactor_ = v.extrusionFactor_;
+    };
+
+    /*!
+     * \brief Assignment operator
+     */
+    BoxVolumeVariables &operator=(const BoxVolumeVariables &v)
+    {
+        evalPoint_ = 0;
+        priVars_ = v.priVars_;
+        extrusionFactor_ = v.extrusionFactor_;
+
+        return *this;
+    };
+
+    /*!
+     * \brief Sets the evaluation point used by the local jacobian.
+     *
+     * The evaluation point is only used by semi-smooth models.
+     */
+    void setEvalPoint(const Implementation *ep)
+    {
+        evalPoint_ = ep;
+        Valgrind::CheckDefined(evalPoint_);
+    }
+
+    /*!
+     * \brief Returns the evaluation point used by the local jacobian.
+     *
+     * The evaluation point is only used by semi-smooth models.
+     */
+    const Implementation &evalPoint() const
+    { return (evalPoint_ == 0)?asImp_():*evalPoint_; }
+
+    /*!
+     * \brief Set the volume variables which should be used as initial
+     *        conditions for complex calculations.
+     */
+    void setHint(const Implementation *hint)
+    {};
+
+    /*!
+     * \brief Update all quantities for a given control volume
+     *
+     * \param priVars A vector containing the primary variables for the control volume
+     * \param problem The object specifying the problem which ought to
+     *                be simulated
+     * \param element An element which contains part of the control volume
+     * \param fvGeometry The finite volume geometry for the element
+     * \param scvIdx Local index of the sub control volume which is inside the element
+     * \param isOldSol Specifies whether this is the previous solution or the current one
+     *
+     * \todo Eliminate the 'isOldSol' parameter. This implies that the
+     *       'pseudo-primary variables' must be somehow be stored
+     *       inside the PrimaryVariables. (e.g. we need to know the
+     *       phase state in the 2p2c model)
+     */
+    void update(const PrimaryVariables &priVars,
+                const Problem &problem,
+                const Element &element,
+                const FVElementGeometry &fvGeometry,
+                const int scvIdx,
+                const bool isOldSol)
+    {
+        Valgrind::CheckDefined(priVars);
+        priVars_ = priVars;
+        extrusionFactor_ = problem.boxExtrusionFactor(element, fvGeometry, scvIdx);
+    }
+
+    /*!
+     * \brief Return the vector of primary variables
+     */
+    const PrimaryVariables &priVars() const
+    { return priVars_; }
+
+    /*!
+     * \brief Return a component of primary variable vector
+     *
+     * \param pvIdx The index of the primary variable of interest
+     */
+    Scalar priVar(const int pvIdx) const
+    {
+        return priVars_[pvIdx];
+    }
+
+    /*!
+     * \brief Return how much the sub-control volume is extruded.
+     *
+     * This means the factor by which a lower-dimensional (1D or 2D)
+     * entity needs to be expanded to get a full dimensional cell. The
+     * default is 1.0 which means that 1D problems are actually
+     * thought as pipes with a cross section of 1 m^2 and 2D problems
+     * are assumed to extend 1 m to the back.
+     */
+    Scalar extrusionFactor() const
+    { return extrusionFactor_; }
+
+    /*!
+     * \brief If running in valgrind this makes sure that all
+     *        quantities in the volume variables are defined.
+     */
+    void checkDefined() const
+    {
+#if !defined NDEBUG && HAVE_VALGRIND
+        Valgrind::CheckDefined(priVars_);
+        Valgrind::CheckDefined(evalPoint_);
+        if (evalPoint_ && evalPoint_ != this)
+            evalPoint_->checkDefined();
+#endif
+    };
+
+protected:
+    const Implementation &asImp_() const
+    { return *static_cast<const Implementation*>(this); }
+    Implementation &asImp_()
+    { return *static_cast<Implementation*>(this); }
+
+    // the evaluation point of the local jacobian
+    const Implementation *evalPoint_;
+
+    PrimaryVariables priVars_;
+    Scalar extrusionFactor_;
+};
+
+} // end namepace
+
+#endif
diff --git a/dumux/implicit/common/porousmediaimplicitproblem.hh b/dumux/implicit/common/porousmediaimplicitproblem.hh
new file mode 100644
index 0000000000..151f953703
--- /dev/null
+++ b/dumux/implicit/common/porousmediaimplicitproblem.hh
@@ -0,0 +1,197 @@
+// -*- mode: C++; tab-width: 4; indent-tabs-mode: nil; c-basic-offset: 4 -*-
+// vi: set et ts=4 sw=4 sts=4:
+/*****************************************************************************
+ *                 2012 by Bernd Flemisch                                    *
+ *   See the file COPYING for full copying permissions.                      *
+ *                                                                           *
+ *   This program is free software: you can redistribute it and/or modify    *
+ *   it under the terms of the GNU General Public License as published by    *
+ *   the Free Software Foundation, either version 2 of the License, or       *
+ *   (at your option) any later version.                                     *
+ *                                                                           *
+ *   This program is distributed in the hope that it will be useful,         *
+ *   but WITHOUT ANY WARRANTY; without even the implied warranty of          *
+ *   MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the            *
+ *   GNU General Public License for more details.                            *
+ *                                                                           *
+ *   You should have received a copy of the GNU General Public License       *
+ *   along with this program.  If not, see <http://www.gnu.org/licenses/>.   *
+ *****************************************************************************/
+/*!
+ * \file
+ * \brief Base class for all problems which use the two-phase box model
+ */
+#ifndef DUMUX_POROUS_MEDIA_BOX_PROBLEM_HH
+#define DUMUX_POROUS_MEDIA_BOX_PROBLEM_HH
+
+#include "boxproperties.hh"
+
+#include <dumux/boxmodels/common/boxproblem.hh>
+
+namespace Dumux
+{
+namespace Properties
+{
+NEW_PROP_TAG(SpatialParams); //!< The type of the spatial parameters object
+NEW_PROP_TAG(ProblemEnableGravity); //!< Returns whether gravity is considered in the problem
+}
+
+/*!
+ * \ingroup BoxBaseProblems
+ * \brief Base class for all porous media box problems
+ */
+template<class TypeTag>
+class PorousMediaBoxProblem : public BoxProblem<TypeTag>
+{
+    typedef BoxProblem<TypeTag> ParentType;
+
+    typedef typename GET_PROP_TYPE(TypeTag, Problem) Implementation;
+    typedef typename GET_PROP_TYPE(TypeTag, TimeManager) TimeManager;
+    typedef typename GET_PROP_TYPE(TypeTag, FVElementGeometry) FVElementGeometry;
+    typedef typename GET_PROP_TYPE(TypeTag, SpatialParams) SpatialParams;
+
+    typedef typename GET_PROP_TYPE(TypeTag, GridView) GridView;
+    typedef typename GridView::template Codim<0>::Entity Element;
+    enum {
+        dim = GridView::dimension,
+        dimWorld = GridView::dimensionworld
+    };
+
+    typedef typename GridView::ctype CoordScalar;
+    typedef Dune::FieldVector<CoordScalar, dimWorld> GlobalPosition;
+    typedef typename GET_PROP_TYPE(TypeTag, Scalar) Scalar;
+    typedef Dune::FieldVector<Scalar, dim> DimVector;
+
+public:
+    /*!
+     * \brief The constructor
+     *
+     * \param timeManager The time manager
+     * \param gridView The grid view
+     * \param verbose Turn verbosity on or off
+     */
+    PorousMediaBoxProblem(TimeManager &timeManager,
+                const GridView &gridView,
+                const bool verbose = true)
+        : ParentType(timeManager, gridView),
+          gravity_(0)
+    {
+        newSpatialParams_ = true;
+        spatialParams_ = new SpatialParams(gridView);
+
+        if (GET_PARAM_FROM_GROUP(TypeTag, bool, Problem, EnableGravity))
+            gravity_[dim-1]  = -9.81;
+    }
+
+    ~PorousMediaBoxProblem()
+    {
+        if (newSpatialParams_)
+            delete spatialParams_;
+    }
+
+    /*!
+     * \name Problem parameters
+     */
+    // \{
+
+    /*!
+     * \brief Returns the temperature \f$\mathrm{[K]}\f$ within a control volume.
+     *
+     * This is the discretization specific interface for the box
+     * method. By default it just calls temperature(pos).
+     *
+     * \param element The DUNE Codim<0> enitiy which intersects with
+     *                the finite volume.
+     * \param fvGeometry The finite volume geometry of the element.
+     * \param scvIdx The local index of the sub control volume inside the element
+     */
+    Scalar boxTemperature(const Element &element,
+                          const FVElementGeometry fvGeometry,
+                          const int scvIdx) const
+    { return asImp_().temperatureAtPos(fvGeometry.subContVol[scvIdx].global); }
+
+    /*!
+     * \brief Returns the temperature \f$\mathrm{[K]}\f$ at a given global position.
+     *
+     * This is not specific to the discretization. By default it just
+     * calls temperature().
+     *
+     * \param pos The position in global coordinates where the temperature should be specified.
+     */
+    Scalar temperatureAtPos(const GlobalPosition &pos) const
+    { return asImp_().temperature(); }
+
+    /*!
+     * \brief Returns the temperature \f$\mathrm{[K]}\f$ for an isothermal problem.
+     *
+     * This is not specific to the discretization. By default it just
+     * throws an exception so it must be overloaded by the problem if
+     * no energy equation is used.
+     */
+    Scalar temperature() const
+    { DUNE_THROW(Dune::NotImplemented, "temperature() method not implemented by the actual problem"); };
+
+    /*!
+     * \brief Returns the acceleration due to gravity \f$\mathrm{[m/s^2]}\f$.
+     *
+     * This is the box discretization specific interface. By default
+     * it just calls gravityAtPos().
+     */
+    const DimVector &boxGravity(const Element &element,
+                                const FVElementGeometry &fvGeometry,
+                                const int scvIdx) const
+    { return asImp_().gravityAtPos(fvGeometry.subContVol[scvIdx].global); }
+
+    /*!
+     * \brief Returns the acceleration due to gravity \f$\mathrm{[m/s^2]}\f$.
+     *
+     * This is discretization independent interface. By default it
+     * just calls gravity().
+     */
+    const DimVector &gravityAtPos(const GlobalPosition &pos) const
+    { return asImp_().gravity(); }
+
+    /*!
+     * \brief Returns the acceleration due to gravity \f$\mathrm{[m/s^2]}\f$.
+     *
+     * This method is used for problems where the gravitational
+     * acceleration does not depend on the spatial position. The
+     * default behaviour is that if the <tt>EnableGravity</tt>
+     * property is true, \f$\boldsymbol{g} = ( 0,\dots,\ -9.81)^T \f$ holds,
+     * else \f$\boldsymbol{g} = ( 0,\dots, 0)^T \f$.
+     */
+    const DimVector &gravity() const
+    { return gravity_; }
+
+    /*!
+     * \brief Returns the spatial parameters object.
+     */
+    SpatialParams &spatialParams()
+    { return *spatialParams_; }
+    
+    /*!
+     * \brief Returns the spatial parameters object.
+     */
+    const SpatialParams &spatialParams() const
+    { return *spatialParams_; }
+
+    // \}
+
+protected:
+    //! Returns the implementation of the problem (i.e. static polymorphism)
+    Implementation &asImp_()
+    { return *static_cast<Implementation *>(this); }
+    //! \copydoc asImp_()
+    const Implementation &asImp_() const
+    { return *static_cast<const Implementation *>(this); }
+
+    DimVector gravity_;
+
+    // fluids and material properties
+    SpatialParams*  spatialParams_;
+    bool newSpatialParams_;
+};
+
+}
+
+#endif
diff --git a/dumux/implicit/mpnc/Makefile.am b/dumux/implicit/mpnc/Makefile.am
new file mode 100644
index 0000000000..30f151f003
--- /dev/null
+++ b/dumux/implicit/mpnc/Makefile.am
@@ -0,0 +1,6 @@
+SUBDIRS = diffusion energy mass 
+
+mpncdir = $(includedir)/dumux/boxmodels/mpnc
+mpnc_HEADERS = *.hh
+
+include $(top_srcdir)/am/global-rules
diff --git a/dumux/implicit/mpnc/diffusion/Makefile.am b/dumux/implicit/mpnc/diffusion/Makefile.am
new file mode 100644
index 0000000000..53a44407d5
--- /dev/null
+++ b/dumux/implicit/mpnc/diffusion/Makefile.am
@@ -0,0 +1,4 @@
+diffusiondir = $(includedir)/dumux/boxmodels/mpnc/diffusion
+diffusion_HEADERS = *.hh
+
+include $(top_srcdir)/am/global-rules
diff --git a/dumux/implicit/mpnc/diffusion/diffusion.hh b/dumux/implicit/mpnc/diffusion/diffusion.hh
new file mode 100644
index 0000000000..1df1d41a50
--- /dev/null
+++ b/dumux/implicit/mpnc/diffusion/diffusion.hh
@@ -0,0 +1,150 @@
+// -*- mode: C++; tab-width: 4; indent-tabs-mode: nil; c-basic-offset: 4 -*-
+// vi: set et ts=4 sw=4 sts=4:
+/*****************************************************************************
+ *   See the file COPYING for full copying permissions.                      *
+ *                                                                           *
+ *   This program is free software: you can redistribute it and/or modify    *
+ *   it under the terms of the GNU General Public License as published by    *
+ *   the Free Software Foundation, either version 2 of the License, or       *
+ *   (at your option) any later version.                                     *
+ *                                                                           *
+ *   This program is distributed in the hope that it will be useful,         *
+ *   but WITHOUT ANY WARRANTY; without even the implied warranty of          *
+ *   MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the            *
+ *   GNU General Public License for more details.                            *
+ *                                                                           *
+ *   You should have received a copy of the GNU General Public License       *
+ *   along with this program.  If not, see <http://www.gnu.org/licenses/>.   *
+ *****************************************************************************/
+/*!
+ * \file
+ *
+ * \brief This file contains parts to calculate the diffusive flux in
+ *        the fully coupled two-phase N-component model
+ */
+#ifndef DUMUX_MPNC_DIFFUSION_HH
+#define DUMUX_MPNC_DIFFUSION_HH
+
+#include <dune/common/fmatrix.hh>
+#include <dune/common/fvector.hh>
+
+#include <dumux/boxmodels/mpnc/mpncproperties.hh>
+
+namespace Dumux {
+
+template <class TypeTag, bool enableDiffusion>
+class MPNCDiffusion
+{
+    typedef typename GET_PROP_TYPE(TypeTag, FluidSystem) FluidSystem;
+    typedef typename GET_PROP_TYPE(TypeTag, Scalar) Scalar;
+
+    enum { numComponents = GET_PROP_VALUE(TypeTag, NumComponents)};
+    enum { nPhaseIdx = FluidSystem::nPhaseIdx };
+    enum { wPhaseIdx = FluidSystem::wPhaseIdx };
+
+    typedef typename GET_PROP_TYPE(TypeTag, FluxVariables) FluxVariables;
+    typedef Dune::FieldMatrix<Scalar, numComponents, numComponents> ComponentMatrix;
+    typedef Dune::FieldVector<Scalar, numComponents> ComponentVector;
+
+public:
+    static void flux(ComponentVector &fluxes,
+                     const unsigned int phaseIdx,
+                     const FluxVariables &fluxVars,
+                     const Scalar molarDensity)
+    {
+        if (phaseIdx == nPhaseIdx)
+            gasFlux_(fluxes, fluxVars, molarDensity);
+        else if (phaseIdx == wPhaseIdx){
+            #if MACROSCALE_DIFFUSION_ONLY_GAS
+                    return ; // in the case that only the diffusion in the gas phase is considered, the liquidFlux should not be called
+            #endif
+            liquidFlux_(fluxes, fluxVars, molarDensity);
+        }
+        else
+            DUNE_THROW(Dune::InvalidStateException,
+                       "Invalid phase index: " << phaseIdx);
+    }
+
+protected:
+    static void liquidFlux_(ComponentVector &fluxes,
+                            const FluxVariables &fluxVars,
+                            const Scalar molarDensity)
+    {
+        for (int compIdx = 0; compIdx < numComponents; ++compIdx) {
+            // TODO: tensorial diffusion coefficients
+            const Scalar xGrad = fluxVars.moleFractionGrad(wPhaseIdx, compIdx)*fluxVars.face().normal;
+            fluxes[compIdx] =
+                - xGrad *
+                molarDensity *
+                fluxVars.face().normal.two_norm() * // because we want a mole flux and not an area specific flux
+                fluxVars.porousDiffCoeffL(compIdx) ;
+        }
+    }
+
+    static void gasFlux_(ComponentVector &fluxes,
+                         const FluxVariables &fluxVars,
+                         const Scalar molarDensity)
+    {
+        // Stefan-Maxwell equation
+        //
+        // See: R. Reid, et al.: "The Properties of Liquids and
+        // Gases", 4th edition, 1987, McGraw-Hill, p 596
+
+        // TODO: tensorial diffusion coefficients
+        ComponentMatrix M(0);
+
+        for (int compIIdx = 0; compIIdx < numComponents - 1; ++compIIdx) {
+            for (int compJIdx = 0; compJIdx < numComponents; ++compJIdx) {
+                Scalar Dij = fluxVars.porousDiffCoeffG(compIIdx, compJIdx);
+                if (Dij) {
+                    M[compIIdx][compJIdx] += fluxVars.moleFraction(nPhaseIdx, compIIdx) / Dij;
+                    M[compIIdx][compIIdx] -= fluxVars.moleFraction(nPhaseIdx, compJIdx) / Dij;
+                }
+            }
+        }
+
+        for (int compIIdx = 0; compIIdx < numComponents; ++compIIdx) {
+            M[numComponents - 1][compIIdx] = 1.0;
+        }
+
+        ComponentVector rightHandSide ; // see source cited above
+        for (int compIIdx = 0; compIIdx < numComponents - 1; ++compIIdx) {
+            rightHandSide[compIIdx] = molarDensity*(fluxVars.moleFractionGrad(nPhaseIdx, compIIdx)*fluxVars.face().normal);
+        }
+        rightHandSide[numComponents - 1] = 0.0;
+
+        M.solve(fluxes, rightHandSide);
+    }
+
+    // return whether a concentration can be assumed to be a trace
+    // component in the context of diffusion
+    static Scalar isTraceComp_(Scalar x)
+    { return x < 0.5/numComponents; }
+};
+
+/*!
+ * \brief Specialization of the diffusion module for the case where
+ *        diffusion is disabled.
+ *
+ * This class just does nothing.
+ */
+template <class TypeTag>
+class MPNCDiffusion<TypeTag, false>
+{
+    enum { numComponents = GET_PROP_VALUE(TypeTag, NumComponents) };
+
+    typedef typename GET_PROP_TYPE(TypeTag, Scalar) Scalar;
+    typedef typename GET_PROP_TYPE(TypeTag, FluxVariables) FluxVariables;
+    typedef Dune::FieldVector<Scalar, numComponents>        ComponentVector;
+
+public:
+    static void flux(ComponentVector &fluxes,
+                     const unsigned int phaseIdx,
+                     const FluxVariables &fluxVars,
+                     const Scalar molarDensity)
+    { fluxes = 0;  }
+};
+
+}
+
+#endif // DUMUX_MPNC_DIFFUSION_HH
diff --git a/dumux/implicit/mpnc/diffusion/fluxvariables.hh b/dumux/implicit/mpnc/diffusion/fluxvariables.hh
new file mode 100644
index 0000000000..7ed8570e08
--- /dev/null
+++ b/dumux/implicit/mpnc/diffusion/fluxvariables.hh
@@ -0,0 +1,221 @@
+// -*- mode: C++; tab-width: 4; indent-tabs-mode: nil; c-basic-offset: 4 -*-
+// vi: set et ts=4 sw=4 sts=4:
+/*****************************************************************************
+ *   See the file COPYING for full copying permissions.                      *
+ *                                                                           *
+ *   This program is free software: you can redistribute it and/or modify    *
+ *   it under the terms of the GNU General Public License as published by    *
+ *   the Free Software Foundation, either version 2 of the License, or       *
+ *   (at your option) any later version.                                     *
+ *                                                                           *
+ *   This program is distributed in the hope that it will be useful,         *
+ *   but WITHOUT ANY WARRANTY; without even the implied warranty of          *
+ *   MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the            *
+ *   GNU General Public License for more details.                            *
+ *                                                                           *
+ *   You should have received a copy of the GNU General Public License       *
+ *   along with this program.  If not, see <http://www.gnu.org/licenses/>.   *
+ *****************************************************************************/
+/*!
+ * \file
+ *
+ * \brief This file contains the diffusion module for the flux data of
+ *        the fully coupled two-phase N-component model
+ */
+#ifndef DUMUX_MPNC_DIFFUSION_FLUX_VARIABLES_HH
+#define DUMUX_MPNC_DIFFUSION_FLUX_VARIABLES_HH
+
+#include <dune/common/fvector.hh>
+
+#include "../mpncproperties.hh"
+
+namespace Dumux {
+
+template<class TypeTag, bool enableDiffusion>
+class MPNCFluxVariablesDiffusion
+{
+    typedef typename GET_PROP_TYPE(TypeTag, Scalar) Scalar;
+    typedef typename GET_PROP_TYPE(TypeTag, GridView) GridView;
+    typedef typename GET_PROP_TYPE(TypeTag, Problem) Problem;
+    typedef typename GET_PROP_TYPE(TypeTag, FluidSystem) FluidSystem;
+    typedef typename GET_PROP_TYPE(TypeTag, ElementVolumeVariables) ElementVolumeVariables;
+    typedef typename GridView::template Codim<0>::Entity Element;
+    typedef typename GET_PROP_TYPE(TypeTag, FVElementGeometry) FVElementGeometry;
+    typedef typename FVElementGeometry::SubControlVolumeFace SCVFace;
+
+    enum{dim = GridView::dimension};
+    enum{numPhases = GET_PROP_VALUE(TypeTag, NumPhases)};
+    enum{numComponents = GET_PROP_VALUE(TypeTag, NumComponents)};
+    enum{wPhaseIdx = FluidSystem::wPhaseIdx};
+    enum{nPhaseIdx = FluidSystem::nPhaseIdx};
+
+    typedef Dune::FieldVector<Scalar, dim>  DimVector;
+
+public:
+    MPNCFluxVariablesDiffusion()
+    {}
+
+    void update(const Problem & problem,
+                const Element & element,
+                const FVElementGeometry & fvGeometry,
+                const SCVFace & face,
+                const ElementVolumeVariables & elemVolVars)
+    {
+        const unsigned int i = face.i;
+        const unsigned int j = face.j;
+
+
+        for (int phaseIdx = 0; phaseIdx < numPhases; ++phaseIdx){
+            for (int compIdx = 0; compIdx < numComponents; ++compIdx){
+                moleFraction_[phaseIdx][compIdx] = 0. ;
+                moleFractionGrad_[phaseIdx][compIdx] = 0. ;
+            }
+        }
+
+
+        DimVector tmp ;
+        for (int idx = 0;
+             idx < fvGeometry.numFAP;
+             idx++) // loop over adjacent vertices
+        {
+            // FE gradient at vertex idx
+            const DimVector & feGrad = face.grad[idx];
+
+            // index for the element volume variables
+            int volVarsIdx = face.fapIndices[idx];
+
+            for (int phaseIdx = 0; phaseIdx < numPhases; phaseIdx++){
+                for (int compIdx = 0; compIdx < numComponents; ++compIdx){
+
+                    // calculate mole fractions at the integration points of the face
+                    moleFraction_[phaseIdx][compIdx] += elemVolVars[volVarsIdx].fluidState().moleFraction(phaseIdx, compIdx)*
+                    face.shapeValue[idx];
+
+                    // calculate mole fraction gradients
+                    tmp =  feGrad;
+                    tmp *= elemVolVars[volVarsIdx].fluidState().moleFraction(phaseIdx, compIdx);
+                    moleFractionGrad_[phaseIdx][compIdx] += tmp;
+                }
+            }
+        }
+
+        // initialize the diffusion coefficients to zero
+        for (int i = 0; i < numComponents; ++i) {
+            porousDiffCoeffL_[i] = 0.0;
+            for (int j = 0; j < numComponents; ++j)
+                porousDiffCoeffG_[i][j] = 0.0;
+        }
+
+        // calculate the diffusion coefficients at the integration
+        // point in the porous medium
+        for (int phaseIdx = 0; phaseIdx < numPhases; ++phaseIdx)
+        {
+            // make sure to only calculate diffusion coefficents
+            // for phases which exist in both finite volumes
+            if (elemVolVars[i].fluidState().saturation(phaseIdx) <= 1e-4 ||
+                elemVolVars[j].fluidState().saturation(phaseIdx) <= 1e-4)
+            {
+                continue;
+            }
+
+            // reduction factor for the diffusion coefficients in the
+            // porous medium in nodes i and j. this is the tortuosity
+            // times porosity times phase saturation at the nodes i
+            // and j
+            //
+            // TODO (?): move this calculation to the soil (possibly
+            // that's a bad idea, though)
+            Scalar red_i =
+                elemVolVars[i].fluidState().saturation(phaseIdx)/elemVolVars[i].porosity() *
+                pow(elemVolVars[i].porosity() * elemVolVars[i].fluidState().saturation(phaseIdx), 7.0/3);
+            Scalar red_j =
+                elemVolVars[j].fluidState().saturation(phaseIdx)/elemVolVars[j].porosity() *
+                pow(elemVolVars[j].porosity() * elemVolVars[j].fluidState().saturation(phaseIdx), 7.0/3);
+
+            if (phaseIdx == wPhaseIdx) {
+                // Liquid phase diffusion coefficients in the porous medium
+                for (int i = 0; i < numComponents; ++i) {
+                    // -> arithmetic mean
+                    porousDiffCoeffL_[i]
+                        = 1./2*(red_i * elemVolVars[i].diffCoeff(wPhaseIdx, 0, i) +
+                                red_j * elemVolVars[j].diffCoeff(wPhaseIdx, 0, i));
+                }
+            }
+            else {
+                // Gas phase diffusion coefficients in the porous medium
+                for (int i = 0; i < numComponents; ++i) {
+                    for (int j = 0; j < numComponents; ++j) {
+                        // -> arithmetic mean
+                        porousDiffCoeffG_[i][j]
+                            = 1./2*(red_i * elemVolVars[i].diffCoeff(nPhaseIdx, i, j) +
+                                    red_j * elemVolVars[j].diffCoeff(nPhaseIdx, i, j));
+                    }
+                }
+            }
+        }
+    }
+
+    Scalar porousDiffCoeffL(const unsigned int compIdx) const
+    {
+        // TODO: tensorial diffusion coefficients
+        return porousDiffCoeffL_[compIdx];
+    }
+
+    Scalar porousDiffCoeffG(const unsigned int compIIdx,
+                            const unsigned int compJIdx) const
+    {
+        // TODO: tensorial diffusion coefficients
+        return porousDiffCoeffG_[compIIdx][compJIdx];
+    }
+
+    Scalar moleFraction(const unsigned int phaseIdx,
+                        const unsigned int compIdx) const
+    { return moleFraction_[phaseIdx][compIdx]; }
+
+    const DimVector &moleFractionGrad(const unsigned int phaseIdx,
+                                  const unsigned int compIdx) const
+    { return moleFractionGrad_[phaseIdx][compIdx];}
+
+protected:
+    // the diffusion coefficients for the porous medium for the
+    // liquid phase
+    Scalar porousDiffCoeffL_[numComponents];
+
+    // the diffusion coefficients for the porous medium for the
+    // gas phase
+    Scalar porousDiffCoeffG_[numComponents][numComponents];
+
+    // the concentration gradients of all components in all phases
+    DimVector moleFractionGrad_[numPhases][numComponents];
+
+    // the mole fractions of each component at the integration point
+    Scalar moleFraction_[numPhases][numComponents];
+};
+
+
+template<class TypeTag>
+class MPNCFluxVariablesDiffusion<TypeTag, false>
+{
+    typedef typename GET_PROP_TYPE(TypeTag, Problem) Problem;
+    typedef typename GET_PROP_TYPE(TypeTag, GridView) GridView;
+    typedef typename GridView::template Codim<0>::Entity Element;
+    typedef typename GET_PROP_TYPE(TypeTag, ElementVolumeVariables) ElementVolumeVariables;
+    typedef typename GET_PROP_TYPE(TypeTag, FVElementGeometry) FVElementGeometry;
+    typedef typename FVElementGeometry::SubControlVolumeFace SCVFace;
+
+public:
+    MPNCFluxVariablesDiffusion()
+    {}
+
+    void update(const Problem & problem,
+                const Element & element,
+                const FVElementGeometry & fvGeometry,
+                const SCVFace & face,
+                const ElementVolumeVariables & elemVolVars)
+    {
+    }
+};
+
+}
+
+#endif // DUMUX_MPNC_DIFFUSION_FLUX_VARIABLES_HH
diff --git a/dumux/implicit/mpnc/diffusion/volumevariables.hh b/dumux/implicit/mpnc/diffusion/volumevariables.hh
new file mode 100644
index 0000000000..6c7e523467
--- /dev/null
+++ b/dumux/implicit/mpnc/diffusion/volumevariables.hh
@@ -0,0 +1,164 @@
+// -*- mode: C++; tab-width: 4; indent-tabs-mode: nil; c-basic-offset: 4 -*-
+// vi: set et ts=4 sw=4 sts=4:
+/*****************************************************************************
+ *   See the file COPYING for full copying permissions.                      *
+ *                                                                           *
+ *   This program is free software: you can redistribute it and/or modify    *
+ *   it under the terms of the GNU General Public License as published by    *
+ *   the Free Software Foundation, either version 2 of the License, or       *
+ *   (at your option) any later version.                                     *
+ *                                                                           *
+ *   This program is distributed in the hope that it will be useful,         *
+ *   but WITHOUT ANY WARRANTY; without even the implied warranty of          *
+ *   MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the            *
+ *   GNU General Public License for more details.                            *
+ *                                                                           *
+ *   You should have received a copy of the GNU General Public License       *
+ *   along with this program.  If not, see <http://www.gnu.org/licenses/>.   *
+ *****************************************************************************/
+/*!
+ * \file
+ *
+ * \brief This file contains the diffusion module for the vertex data
+ *        of the fully coupled two-phase N-component model
+ */
+#ifndef DUMUX_MPNC_DIFFUSION_VOLUME_VARIABLES_HH
+#define DUMUX_MPNC_DIFFUSION_VOLUME_VARIABLES_HH
+
+#include <dumux/common/valgrind.hh>
+#include <dumux/boxmodels/mpnc/mpncproperties.hh>
+
+namespace Dumux {
+
+template<class TypeTag, bool enableDiffusion>
+class MPNCVolumeVariablesDiffusion
+{
+    typedef typename GET_PROP_TYPE(TypeTag, Problem) Problem;
+    typedef typename GET_PROP_TYPE(TypeTag, VolumeVariables) VolumeVariables;
+    typedef typename GET_PROP_TYPE(TypeTag, FluidSystem) FluidSystem;
+    typedef typename GET_PROP_TYPE(TypeTag, Scalar) Scalar;
+    typedef typename GET_PROP_TYPE(TypeTag, FluidState) FluidState;
+    typedef typename FluidSystem::ParameterCache ParameterCache;
+
+    enum { numComponents = GET_PROP_VALUE(TypeTag, NumComponents) };
+    enum { wPhaseIdx = FluidSystem::wPhaseIdx };
+    enum { nPhaseIdx = FluidSystem::nPhaseIdx };
+
+public:
+
+    MPNCVolumeVariablesDiffusion()
+    {}
+
+    void update(FluidState &fluidState,
+                ParameterCache &paramCache,
+                const VolumeVariables &volVars,
+                const Problem &problem)
+    {
+        Valgrind::SetUndefined(*this);
+
+        // diffusion coefficents in liquid
+        diffCoeffL_[0] = 0.0;
+        for (int compIdx = 1; compIdx < numComponents; ++compIdx) {
+            diffCoeffL_[compIdx] =
+                FluidSystem::binaryDiffusionCoefficient(fluidState,
+                                                        paramCache,
+                                                        wPhaseIdx,
+                                                        0,
+                                                        compIdx);
+        }
+        Valgrind::CheckDefined(diffCoeffL_);
+
+        // diffusion coefficents in gas
+        for (int compIIdx = 0; compIIdx < numComponents; ++compIIdx) {
+            diffCoeffG_[compIIdx][compIIdx] = 0;
+            for (int compJIdx = compIIdx + 1; compJIdx < numComponents; ++compJIdx) {
+                diffCoeffG_[compIIdx][compJIdx] =
+                        FluidSystem::binaryDiffusionCoefficient(fluidState,
+                                                                paramCache,
+                                                                nPhaseIdx,
+                                                                compIIdx,
+                                                                compJIdx);
+
+                // fill the symmetric part of the diffusion coefficent
+                // matrix
+                diffCoeffG_[compJIdx][compIIdx] = diffCoeffG_[compIIdx][compJIdx];
+            }
+        }
+        Valgrind::CheckDefined(diffCoeffG_);
+    }
+
+
+    Scalar diffCoeff(const unsigned int phaseIdx,
+                     const unsigned int compIIdx,
+                     const unsigned int compJIdx) const
+    {
+        if (phaseIdx == nPhaseIdx)
+            // TODO: tensorial diffusion coefficients
+            return diffCoeffG_[compIIdx][compJIdx];
+
+        const unsigned int i = std::min(compIIdx, compJIdx);
+        const unsigned int j = std::max(compIIdx, compJIdx);
+        if (i != 0)
+            return 0;
+        return diffCoeffL_[j];
+    }
+
+    /*!
+     * \brief If running under valgrind this produces an error message
+     *        if some of the object's attributes is undefined.
+     */
+    void checkDefined() const
+    {
+        Valgrind::CheckDefined(diffCoeffL_);
+        Valgrind::CheckDefined(diffCoeffG_);
+    }
+
+
+protected:
+    // the diffusion coefficients for the porous medium for the
+    // liquid phase
+    Scalar diffCoeffL_[numComponents];
+
+    // the diffusion coefficients for the porous medium for the
+    // gas phase
+    Scalar diffCoeffG_[numComponents][numComponents];
+};
+
+// dummy class for the case where diffusion is disabled
+template<class TypeTag>
+class MPNCVolumeVariablesDiffusion<TypeTag, false>
+{
+    typedef typename GET_PROP_TYPE(TypeTag, Problem) Problem;
+    typedef typename GET_PROP_TYPE(TypeTag, VolumeVariables) VolumeVariables;
+    typedef typename GET_PROP_TYPE(TypeTag, Scalar) Scalar;
+    typedef typename GET_PROP_TYPE(TypeTag, FluidSystem) FluidSystem;
+    typedef typename GET_PROP_TYPE(TypeTag, FluidState) FluidState;
+    typedef typename FluidSystem::ParameterCache ParameterCache;
+
+public:
+    MPNCVolumeVariablesDiffusion()
+    {}
+
+    void update(FluidState &fluidState,
+                ParameterCache &paramCache,
+                const VolumeVariables &volVars,
+                const Problem &problem)
+    { }
+
+    Scalar diffCoeffL(const unsigned int compIdx) const
+    { return 0; }
+
+    Scalar diffCoeffG(const unsigned int compIIdx, const unsigned int compJIdx) const
+    { return 0; }
+
+    /*!
+     * \brief If running under valgrind this produces an error message
+     *        if some of the object's attributes is undefined.
+     */
+    void checkDefined() const
+    { }
+};
+
+}
+
+#endif // DUMUX_MPNC_DIFFUSION_VOLUME_VARIABLES_HH
diff --git a/dumux/implicit/mpnc/energy/Makefile.am b/dumux/implicit/mpnc/energy/Makefile.am
new file mode 100644
index 0000000000..0f5e064a86
--- /dev/null
+++ b/dumux/implicit/mpnc/energy/Makefile.am
@@ -0,0 +1,4 @@
+energydir = $(includedir)/dumux/boxmodels/mpnc/energy
+energy_HEADERS = *.hh
+
+include $(top_srcdir)/am/global-rules
diff --git a/dumux/implicit/mpnc/energy/mpncfluxvariablesenergy.hh b/dumux/implicit/mpnc/energy/mpncfluxvariablesenergy.hh
new file mode 100644
index 0000000000..a345453e15
--- /dev/null
+++ b/dumux/implicit/mpnc/energy/mpncfluxvariablesenergy.hh
@@ -0,0 +1,205 @@
+// -*- mode: C++; tab-width: 4; indent-tabs-mode: nil; c-basic-offset: 4 -*-
+// vi: set et ts=4 sw=4 sts=4:
+/*****************************************************************************
+ *   See the file COPYING for full copying permissions.                      *
+ *                                                                           *
+ *   This program is free software: you can redistribute it and/or modify    *
+ *   it under the terms of the GNU General Public License as published by    *
+ *   the Free Software Foundation, either version 2 of the License, or       *
+ *   (at your option) any later version.                                     *
+ *                                                                           *
+ *   This program is distributed in the hope that it will be useful,         *
+ *   but WITHOUT ANY WARRANTY; without even the implied warranty of          *
+ *   MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the            *
+ *   GNU General Public License for more details.                            *
+ *                                                                           *
+ *   You should have received a copy of the GNU General Public License       *
+ *   along with this program.  If not, see <http://www.gnu.org/licenses/>.   *
+ *****************************************************************************/
+/*!
+ * \file
+ *
+ * \brief Contains the quantities to calculate the energy flux in the
+ *        MpNc box model.
+ */
+#ifndef DUMUX_MPNC_ENERGY_FLUX_VARIABLES_HH
+#define DUMUX_MPNC_ENERGY_FLUX_VARIABLES_HH
+
+#include <dune/common/fmatrix.hh>
+#include <dune/common/fvector.hh>
+
+#include <dumux/boxmodels/mpnc/mpncproperties.hh>
+#include <dumux/common/spline.hh>
+
+namespace Dumux
+{
+
+template <class TypeTag, bool enableEnergy/*=false*/, bool kineticEnergyTransfer/*=false*/>
+class MPNCFluxVariablesEnergy
+{
+    static_assert(!(kineticEnergyTransfer && !enableEnergy),
+                  "No kinetic energy transfer may only be enabled "
+                  "if energy is enabled in general.");
+    static_assert(!kineticEnergyTransfer,
+                  "No kinetic energy transfer module included, "
+                  "but kinetic energy transfer enabled.");
+
+    typedef typename GET_PROP_TYPE(TypeTag, Problem) Problem;
+    typedef typename GET_PROP_TYPE(TypeTag, GridView) GridView;
+    typedef typename GridView::template Codim<0>::Entity Element;
+    typedef typename GET_PROP_TYPE(TypeTag, FVElementGeometry) FVElementGeometry;
+    typedef typename GET_PROP_TYPE(TypeTag, VolumeVariables) VolumeVariables;
+    typedef typename GET_PROP_TYPE(TypeTag, ElementVolumeVariables) ElementVolumeVariables;
+    typedef typename GET_PROP_TYPE(TypeTag, FluxVariables) FluxVariables;
+    typedef typename FVElementGeometry::SubControlVolumeFace SCVFace;
+
+public:
+    MPNCFluxVariablesEnergy()
+    {
+    }
+
+    void update(const Problem & problem,
+                const Element & element,
+                const FVElementGeometry & fvGeometry,
+                const SCVFace & face,
+                const FluxVariables & fluxVars,
+                const ElementVolumeVariables & elemVolVars)
+    {}
+};
+
+template <class TypeTag>
+class MPNCFluxVariablesEnergy<TypeTag, /*enableEnergy=*/true,  /*kineticEnergyTransfer=*/false>
+{
+    typedef typename GET_PROP_TYPE(TypeTag, Scalar) Scalar;
+    typedef typename GET_PROP_TYPE(TypeTag, GridView) GridView;
+    typedef typename GET_PROP_TYPE(TypeTag, Problem) Problem;
+    typedef typename GET_PROP_TYPE(TypeTag, VolumeVariables) VolumeVariables;
+    typedef typename GET_PROP_TYPE(TypeTag, ElementVolumeVariables) ElementVolumeVariables;
+    typedef typename GET_PROP_TYPE(TypeTag, FluxVariables) FluxVariables;
+    typedef typename GET_PROP_TYPE(TypeTag, FluidSystem) FluidSystem;
+    typedef typename GET_PROP_TYPE(TypeTag, FluidState) FluidState;
+    typedef typename FluidSystem::ParameterCache ParameterCache;
+    typedef typename GridView::ctype CoordScalar;
+    typedef typename GridView::template Codim<0>::Entity Element;
+
+    enum{dim = GridView::dimension};
+    enum{dimWorld = GridView::dimensionworld};
+    enum{nPhaseIdx = FluidSystem::nPhaseIdx};
+    enum{wPhaseIdx = FluidSystem::wPhaseIdx};
+    enum{numPhases = GET_PROP_VALUE(TypeTag, NumPhases)};
+
+    typedef Dune::FieldVector<CoordScalar, dimWorld>  DimVector;
+    typedef typename GET_PROP_TYPE(TypeTag, FVElementGeometry) FVElementGeometry;
+    typedef typename FVElementGeometry::SubControlVolumeFace SCVFace;
+
+public:
+    MPNCFluxVariablesEnergy()
+    {}
+
+    void update(const Problem & problem,
+                const Element & element,
+                const FVElementGeometry & fvGeometry,
+                const SCVFace & face,
+                const FluxVariables & fluxVars,
+                const ElementVolumeVariables & elemVolVars)
+    {
+        // calculate temperature gradient using finite element
+        // gradients
+        DimVector tmp(0.0);
+        DimVector temperatureGradient(0.);
+        for (int idx = 0; idx < fvGeometry.numFAP; idx++)
+        {
+            tmp = face.grad[idx];
+
+            // index for the element volume variables 
+            int volVarsIdx = face.fapIndices[idx];
+            
+            tmp *= elemVolVars[volVarsIdx].fluidState().temperature(/*phaseIdx=*/0);
+            temperatureGradient += tmp;
+        }
+
+        // project the heat flux vector on the face's normal vector
+        temperatureGradientNormal_ = temperatureGradient * face.normal;
+
+
+        lambdaPm_ = lumpedLambdaPm(problem,
+                                   element,
+                                   fvGeometry,
+                                   face,
+                                   elemVolVars) ;
+
+    }
+
+    Scalar lumpedLambdaPm(const Problem &problem,
+                          const Element &element,
+                          const FVElementGeometry & fvGeometry,
+                          const SCVFace & face,
+                          const ElementVolumeVariables & elemVolVars)
+    {
+         // arithmetic mean of the liquid saturation and the porosity
+         const unsigned int i = face.i;
+         const unsigned int j = face.j;
+
+         const FluidState &fsI = elemVolVars[i].fluidState();
+         const FluidState &fsJ = elemVolVars[j].fluidState();
+         const Scalar Swi = fsI.saturation(wPhaseIdx);
+         const Scalar Swj = fsJ.saturation(wPhaseIdx);
+
+         typename FluidSystem::ParameterCache paramCacheI, paramCacheJ;
+         paramCacheI.updateAll(fsI);
+         paramCacheJ.updateAll(fsJ);
+
+         const Scalar Sw = std::max<Scalar>(0.0, 0.5*(Swi + Swj));
+
+         //        const Scalar lambdaDry = 0.583; // W / (K m) // works, orig
+         //        const Scalar lambdaWet = 1.13; // W / (K m) // works, orig
+
+         const Scalar lambdaSoilI = problem.spatialParams().soilThermalConductivity(element, fvGeometry, i);
+         const Scalar lambdaSoilJ = problem.spatialParams().soilThermalConductivity(element, fvGeometry, i);
+         const Scalar lambdaDry = 0.5 * (lambdaSoilI + FluidSystem::thermalConductivity(fsI, paramCacheI, nPhaseIdx)); // W / (K m)
+         const Scalar lambdaWet = 0.5 * (lambdaSoilJ + FluidSystem::thermalConductivity(fsJ, paramCacheJ, wPhaseIdx)) ; // W / (K m)
+
+         // the heat conductivity of the matrix. in general this is a
+         // tensorial value, but we assume isotropic heat conductivity.
+         // This is the Sommerton approach with lambdaDry =
+         // lambdaSn100%.  Taken from: H. Class: "Theorie und
+         // numerische Modellierung nichtisothermer Mehrphasenprozesse
+         // in NAPL-kontaminierten poroesen Medien", PhD Thesis, University of
+         // Stuttgart, Institute of Hydraulic Engineering, p. 57
+
+         Scalar result;
+         if (Sw < 0.1) {
+             // regularization
+             Dumux::Spline<Scalar> sp(0, 0.1, // x1, x2
+                                      0, sqrt(0.1), // y1, y2
+                                      5*0.5/sqrt(0.1), 0.5/sqrt(0.1)); // m1, m2
+             result = lambdaDry + sp.eval(Sw)*(lambdaWet - lambdaDry);
+         }
+         else
+             result = lambdaDry + std::sqrt(Sw)*(lambdaWet - lambdaDry);
+
+         return result;
+    }
+
+    /*!
+     * \brief The lumped / average conductivity of solid plus phases \f$[W/mK]\f$.
+     */
+    Scalar lambdaPm() const
+    { return lambdaPm_; }
+
+    /*!
+     * \brief The normal of the gradient of temperature .
+     */
+    Scalar temperatureGradientNormal() const
+    {
+        return temperatureGradientNormal_;
+    }
+
+private:
+    Scalar lambdaPm_;
+    Scalar temperatureGradientNormal_;
+};
+
+} // end namepace
+
+#endif
diff --git a/dumux/implicit/mpnc/energy/mpncindicesenergy.hh b/dumux/implicit/mpnc/energy/mpncindicesenergy.hh
new file mode 100644
index 0000000000..05a8b33ce2
--- /dev/null
+++ b/dumux/implicit/mpnc/energy/mpncindicesenergy.hh
@@ -0,0 +1,75 @@
+// -*- mode: C++; tab-width: 4; indent-tabs-mode: nil; c-basic-offset: 4 -*-
+// vi: set et ts=4 sw=4 sts=4:
+/*****************************************************************************
+ *   See the file COPYING for full copying permissions.                      *
+ *                                                                           *
+ *   This program is free software: you can redistribute it and/or modify    *
+ *   it under the terms of the GNU General Public License as published by    *
+ *   the Free Software Foundation, either version 2 of the License, or       *
+ *   (at your option) any later version.                                     *
+ *                                                                           *
+ *   This program is distributed in the hope that it will be useful,         *
+ *   but WITHOUT ANY WARRANTY; without even the implied warranty of          *
+ *   MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the            *
+ *   GNU General Public License for more details.                            *
+ *                                                                           *
+ *   You should have received a copy of the GNU General Public License       *
+ *   along with this program.  If not, see <http://www.gnu.org/licenses/>.   *
+ *****************************************************************************/
+/*!
+ * \brief The indices for the non-isothermal part of the compositional
+ *        multi-phase model.
+ */
+#ifndef DUMUX_MPNC_INDICES_ENERGY_HH
+#define DUMUX_MPNC_INDICES_ENERGY_HH
+
+namespace Dumux
+{
+/*!
+ * \brief The indices for the energy equation.
+ *
+ * This is a dummy class for the isothermal case.
+ */
+template <int PVOffset, bool enableEnergy/*=false*/, bool kineticEnergyTransfer/*=false*/>
+struct MPNCEnergyIndices
+{
+    static_assert(!(kineticEnergyTransfer && !enableEnergy),
+                  "No kinetic energy transfer may only be enabled "
+                  "if energy is enabled in general.");
+    static_assert(!kineticEnergyTransfer,
+                  "No kinetic energy transfer module included, "
+                  "but kinetic energy transfer enabled.");
+public:
+    /*!
+     * \brief This module does not define any primary variables in the
+     *        isothermal case.
+     */
+    static const unsigned int NumPrimaryVars = 0;
+};
+
+/*!
+ * \brief The indices required for the energy equation.
+ */
+template <int PVOffset>
+struct MPNCEnergyIndices<PVOffset, /*isNonIsothermal=*/true, /*kineticEnergyTransfer*/false>
+{
+public:
+    /*!
+     * \brief This module defines one new primary variable.
+     */
+    static const unsigned int NumPrimaryVars = 1;
+
+    /*!
+     * \brief Index for the temperature in a vector of primary
+     *        variables.
+     */
+    static const unsigned int temperatureIdx = PVOffset + 0;
+    /*!
+     * \brief Equation index of the energy equation.
+     */
+    static const unsigned int energyEqIdx = PVOffset + 0;
+};
+
+}
+
+#endif
diff --git a/dumux/implicit/mpnc/energy/mpnclocalresidualenergy.hh b/dumux/implicit/mpnc/energy/mpnclocalresidualenergy.hh
new file mode 100644
index 0000000000..67c3b8b9ee
--- /dev/null
+++ b/dumux/implicit/mpnc/energy/mpnclocalresidualenergy.hh
@@ -0,0 +1,233 @@
+// -*- mode: C++; tab-width: 4; indent-tabs-mode: nil; c-basic-offset: 4 -*-
+// vi: set et ts=4 sw=4 sts=4:
+/*****************************************************************************
+ *   See the file COPYING for full copying permissions.                      *
+ *                                                                           *
+ *   This program is free software: you can redistribute it and/or modify    *
+ *   it under the terms of the GNU General Public License as published by    *
+ *   the Free Software Foundation, either version 2 of the License, or       *
+ *   (at your option) any later version.                                     *
+ *                                                                           *
+ *   This program is distributed in the hope that it will be useful,         *
+ *   but WITHOUT ANY WARRANTY; without even the implied warranty of          *
+ *   MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the            *
+ *   GNU General Public License for more details.                            *
+ *                                                                           *
+ *   You should have received a copy of the GNU General Public License       *
+ *   along with this program.  If not, see <http://www.gnu.org/licenses/>.   *
+ *****************************************************************************/
+/*!
+ * \file
+ *
+ * \brief This file contains the parts of the local residual to
+ *        calculate the heat flux in the fully coupled two-phase
+ *        N-component model
+ */
+#ifndef DUMUX_MPNC_LOCAL_RESIDUAL_ENERGY_HH
+#define DUMUX_MPNC_LOCAL_RESIDUAL_ENERGY_HH
+
+#include <dumux/boxmodels/mpnc/mpncproperties.hh>
+
+namespace Dumux {
+
+/*!
+ * \brief Specialization of the energy module for the isothermal case.
+ *
+ * This class just does nothing.
+ */
+template <class TypeTag, bool enableEnergy/*=false*/, bool kineticEnergyTransfer /*=false*/>
+class MPNCLocalResidualEnergy
+{
+    static_assert(!(kineticEnergyTransfer && !enableEnergy),
+                  "No kinetic energy transfer may only be enabled "
+                  "if energy is enabled in general.");
+    static_assert(!kineticEnergyTransfer,
+                  "No kinetic energy transfer module included, "
+                  "but kinetic energy transfer enabled.");
+
+    typedef typename GET_PROP_TYPE(TypeTag, PrimaryVariables) PrimaryVariables;
+    typedef typename GET_PROP_TYPE(TypeTag, VolumeVariables) VolumeVariables;
+    typedef typename GET_PROP_TYPE(TypeTag, FluxVariables) FluxVariables;
+    typedef typename GET_PROP_TYPE(TypeTag, ElementVolumeVariables) ElementVolumeVariables;
+    typedef typename GET_PROP_TYPE(TypeTag, Scalar) Scalar;
+
+    enum { numPhases        = GET_PROP_VALUE(TypeTag, NumPhases) };
+    enum { numComponents    = GET_PROP_VALUE(TypeTag, NumComponents) };
+
+    typedef typename Dune::FieldVector<Scalar, numComponents>  ComponentVector;
+
+public:
+    static void computeStorage(PrimaryVariables &storage,
+                               const VolumeVariables &volVars)
+    {
+        // do nothing, we're isothermal!
+    }
+
+
+    static void addPhaseStorage(PrimaryVariables &storage,
+                                const VolumeVariables &volVars,
+                                const unsigned int phaseIdx)
+    {
+        // do nothing, we're isothermal!
+    }
+
+    static void phaseEnthalpyFlux(PrimaryVariables &enthalpyFlux,
+                                  const unsigned int phaseIdx,
+                                  const PrimaryVariables &compMolFlux,
+                                  const ElementVolumeVariables &volVars,
+                                  const FluxVariables &fluxVars)
+    {
+        // do nothing, we're isothermal!
+    }
+
+    static void heatConduction(PrimaryVariables &heatConduction,
+                               const ElementVolumeVariables &volVars,
+                               const FluxVariables &fluxVars)
+    {
+        // do nothing, we're isothermal!
+    }
+
+
+    static void computeFlux(PrimaryVariables & flux,
+                                const FluxVariables & fluxVars,
+                                const ElementVolumeVariables & volVars,
+                                const ComponentVector molarPhaseComponentValuesMassTransport[numPhases])
+    {
+        // do nothing, we're isothermal!
+    }
+
+    static void computeSource(PrimaryVariables &source,
+                              const VolumeVariables &volVars,
+                              const ComponentVector componentIntoPhaseMassTransfer[numPhases])
+    {
+        // do nothing, we're isothermal!
+    }
+};
+
+
+template <class TypeTag>
+class MPNCLocalResidualEnergy<TypeTag, /*enableEnergy=*/true, /*kineticenergyTransfer=*/false>
+{
+    typedef typename GET_PROP_TYPE(TypeTag, FluidSystem) FluidSystem;
+    typedef typename GET_PROP_TYPE(TypeTag, FluidState) FluidState;
+    typedef typename FluidSystem::ParameterCache ParameterCache;
+    typedef typename GET_PROP_TYPE(TypeTag, Scalar) Scalar;
+    typedef typename GET_PROP_TYPE(TypeTag, GridView) GridView;
+    typedef typename GET_PROP_TYPE(TypeTag, PrimaryVariables) PrimaryVariables;
+    typedef typename GET_PROP_TYPE(TypeTag, FluxVariables) FluxVariables;
+    typedef typename GET_PROP_TYPE(TypeTag, VolumeVariables) VolumeVariables;
+    typedef typename GET_PROP_TYPE(TypeTag, ElementVolumeVariables) ElementVolumeVariables;
+    typedef typename GET_PROP_TYPE(TypeTag, Indices) Indices;
+
+    enum { dim = GridView::dimension };
+    enum { numPhases = GET_PROP_VALUE(TypeTag, NumPhases) };
+    enum { numComponents = GET_PROP_VALUE(TypeTag, NumComponents) };
+    enum { conti0EqIdx = Indices::conti0EqIdx };
+    enum { energyEqIdx = Indices::energyEqIdx };
+
+    typedef typename Dune::FieldVector<Scalar, numComponents> ComponentVector;
+
+public:
+    static void computeStorage(PrimaryVariables &storage,
+                               const VolumeVariables &volVars)
+    {
+        storage[energyEqIdx] = 0;
+
+        // energy of the fluids
+        for (int phaseIdx = 0; phaseIdx < numPhases; ++phaseIdx) {
+            addPhaseStorage(storage, volVars, phaseIdx);
+        }
+
+        // heat stored in the rock matrix
+        storage[energyEqIdx] +=
+            volVars.fluidState().temperature(/*phaseIdx=*/0)
+            * volVars.soilDensity()
+            * (1.0 - volVars.porosity())
+            * volVars.heatCapacity();
+    }
+
+    static void addPhaseStorage(PrimaryVariables &storage,
+                                const VolumeVariables &volVars,
+                                const unsigned int phaseIdx)
+    {
+        const FluidState &fs = volVars.fluidState();
+
+        // energy of the fluid
+        storage[energyEqIdx] +=
+            fs.density(phaseIdx)
+            * fs.internalEnergy(phaseIdx)
+            * fs.saturation(phaseIdx)
+            * volVars.porosity();
+    }
+
+    static void computeFlux(PrimaryVariables & flux,
+                            const FluxVariables & fluxVars,
+                            const ElementVolumeVariables & elemVolVars,
+                            const ComponentVector molarPhaseComponentValuesMassTransport[numPhases])
+    {
+        flux[energyEqIdx] = 0.0;
+
+        // fluid phases transport enthalpy individually
+        for(int phaseIdx=0; phaseIdx<numPhases; ++phaseIdx)
+            computePhaseEnthalpyFlux(flux,
+                                fluxVars,
+                                elemVolVars,
+                                phaseIdx,
+                                molarPhaseComponentValuesMassTransport[phaseIdx]);
+
+        //conduction is treated lumped in this model
+        computeHeatConduction(flux,
+                             fluxVars,
+                             elemVolVars);
+    }
+
+    static void computePhaseEnthalpyFlux(PrimaryVariables & flux,
+                                         const FluxVariables & fluxVars,
+                                         const ElementVolumeVariables & elemVolVars,
+                                         const unsigned int phaseIdx,
+                                         const ComponentVector & molarComponentValuesMassTransport)
+    {
+        Scalar massFlux = 0;
+
+        // calculate the mass flux in the phase i.e. make mass flux out of mole flux and add up the fluxes of a phase
+        for (int compIdx = 0; compIdx < numComponents; ++compIdx)
+            massFlux += molarComponentValuesMassTransport[compIdx]
+                                    * FluidSystem::molarMass(compIdx);
+
+        unsigned int upIdx = fluxVars.face().i;
+        if (massFlux < 0) upIdx = fluxVars.face().j;
+
+        // use the phase enthalpy of the upstream vertex to calculate
+        // the enthalpy transport
+        const VolumeVariables &up = elemVolVars[upIdx];
+        flux[energyEqIdx] += up.fluidState().enthalpy(phaseIdx) * massFlux;
+    }
+
+    static void computeHeatConduction(PrimaryVariables & flux,
+                                    const FluxVariables & fluxVars,
+                                    const ElementVolumeVariables & elemVolVars)
+    {
+        //lumped heat conduction of the rock matrix and the fluid phases
+        Scalar lumpedConductivity   = fluxVars.fluxVarsEnergy().lambdaPm() ;
+        Scalar temperatureGradientNormal  = fluxVars.fluxVarsEnergy().temperatureGradientNormal() ;
+        Scalar lumpedHeatConduction = - lumpedConductivity * temperatureGradientNormal ;
+        flux[energyEqIdx] += lumpedHeatConduction ;
+    }
+
+
+
+    static void computeSource(PrimaryVariables &source,
+                              const VolumeVariables &volVars,
+                              const ComponentVector componentIntoPhaseMassTransfer[numPhases])
+    {
+        source[energyEqIdx] = 0.0;
+    }
+};
+
+
+
+
+
+}
+
+#endif // DUMUX_MPNC_ENERGY_HH
diff --git a/dumux/implicit/mpnc/energy/mpncvolumevariablesenergy.hh b/dumux/implicit/mpnc/energy/mpncvolumevariablesenergy.hh
new file mode 100644
index 0000000000..185884fdc3
--- /dev/null
+++ b/dumux/implicit/mpnc/energy/mpncvolumevariablesenergy.hh
@@ -0,0 +1,207 @@
+// -*- mode: C++; tab-width: 4; indent-tabs-mode: nil; c-basic-offset: 4 -*-
+// vi: set et ts=4 sw=4 sts=4:
+/*****************************************************************************
+ *   See the file COPYING for full copying permissions.                      *
+ *                                                                           *
+ *   This program is free software: you can redistribute it and/or modify    *
+ *   it under the terms of the GNU General Public License as published by    *
+ *   the Free Software Foundation, either version 2 of the License, or       *
+ *   (at your option) any later version.                                     *
+ *                                                                           *
+ *   This program is distributed in the hope that it will be useful,         *
+ *   but WITHOUT ANY WARRANTY; without even the implied warranty of          *
+ *   MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the            *
+ *   GNU General Public License for more details.                            *
+ *                                                                           *
+ *   You should have received a copy of the GNU General Public License       *
+ *   along with this program.  If not, see <http://www.gnu.org/licenses/>.   *
+ *****************************************************************************/
+/*!
+ * \file
+ *
+ * \brief Contains the energy part of volume variables of the M-phase,
+ *        N-component model.
+ */
+#ifndef DUMUX_MPNC_ENERGY_VOLUME_VARIABLES_HH
+#define DUMUX_MPNC_ENERGY_VOLUME_VARIABLES_HH
+
+#include <dumux/boxmodels/mpnc/mpncproperties.hh>
+#include <dumux/material/fluidstates/compositionalfluidstate.hh>
+
+namespace Dumux
+{
+/*!
+ * \brief Contains the energy related quantities which are constant within a
+ *        finite volume in the two-phase, N-component model.
+ *
+ * This is the dummy class for the isothermal case. Note that we're
+ * only isothermal in the sense that the temperature at a location and
+ * a time is specified outside of the model!
+ */
+template <class TypeTag, bool enableEnergy/*=false*/, bool kineticEnergyTransfer /*=don't care*/>
+class MPNCVolumeVariablesEnergy
+{
+    static_assert(!(kineticEnergyTransfer && !enableEnergy),
+                  "No kinetic energy transfer may only be enabled "
+                  "if energy is enabled in general.");
+    static_assert(!kineticEnergyTransfer,
+                  "No kinetic energy transfer module included, "
+                  "but kinetic energy transfer enabled.");
+
+    typedef typename GET_PROP_TYPE(TypeTag, Scalar) Scalar;
+    typedef typename GET_PROP_TYPE(TypeTag, Problem) Problem;
+    typedef typename GET_PROP_TYPE(TypeTag, GridView) GridView;
+    typedef typename GridView::template Codim<0>::Entity Element;
+    typedef typename GET_PROP_TYPE(TypeTag, PrimaryVariables) PrimaryVariables;
+    typedef typename GET_PROP_TYPE(TypeTag, FVElementGeometry) FVElementGeometry;
+
+    enum { numPhases = GET_PROP_VALUE(TypeTag, NumPhases) };
+
+    typedef typename GET_PROP_TYPE(TypeTag, FluidSystem) FluidSystem;
+    typedef typename GET_PROP_TYPE(TypeTag, FluidState) FluidState;
+    typedef typename FluidSystem::ParameterCache ParameterCache;
+
+public:
+    /*!
+     * \brief Update the temperature of the sub-control volume.
+     */
+    void updateTemperatures(FluidState &fs,
+                            ParameterCache &paramCache,
+                            const PrimaryVariables &priVars,
+                            const Element &element,
+                            const FVElementGeometry &fvGeometry,
+                            const unsigned int scvIdx,
+                            const Problem &problem) const
+    {
+        Scalar T = problem.boxTemperature(element, fvGeometry, scvIdx);
+        fs.setTemperature(T);
+    }
+
+
+    /*!
+     * \brief Update the enthalpy and the internal energy for a given
+     *        control volume.
+     *
+     * Since we are isothermal, we don't need to do anything!
+     */
+    void update(FluidState &fs,
+                ParameterCache &paramCache,
+                const Element &element,
+                const FVElementGeometry &fvGeometry,
+                const unsigned int scvIdx,
+                const Problem &problem)
+    {
+    }
+
+    /*!
+     * \brief If running under valgrind this produces an error message
+     *        if some of the object's attributes is undefined.
+     */
+    void checkDefined() const
+    {
+    }
+};
+
+/*!
+ * \brief Contains the energy related quantities which are constant within a
+ *        finite volume in the two-phase, N-component model.
+ */
+template <class TypeTag>
+class MPNCVolumeVariablesEnergy<TypeTag, /*enableEnergy=*/true, /*kineticEnergyTransfer=*/false>
+{
+    typedef typename GET_PROP_TYPE(TypeTag, Problem) Problem;
+    typedef typename GET_PROP_TYPE(TypeTag, Scalar) Scalar;
+    typedef typename GET_PROP_TYPE(TypeTag, GridView) GridView;
+    typedef typename GridView::template Codim<0>::Entity Element;
+    typedef typename GET_PROP_TYPE(TypeTag, PrimaryVariables) PrimaryVariables;
+    typedef typename GET_PROP_TYPE(TypeTag, FVElementGeometry) FVElementGeometry;
+    typedef typename GET_PROP_TYPE(TypeTag, Indices) Indices;
+
+    enum { numPhases        = GET_PROP_VALUE(TypeTag, NumPhases) };
+    enum { numComponents    = GET_PROP_VALUE(TypeTag, NumComponents) };
+    enum { temperatureIdx   = Indices::temperatureIdx };
+    enum { numEnergyEqs     = Indices::NumPrimaryEnergyVars};
+    enum { temperature0Idx = Indices::temperatureIdx };
+
+    typedef typename GET_PROP_TYPE(TypeTag, FluidSystem) FluidSystem;
+    typedef typename GET_PROP_TYPE(TypeTag, FluidState)  FluidState;
+    typedef typename FluidSystem::ParameterCache ParameterCache;
+
+public:
+    /*!
+     * \brief Update the temperature of the sub-control volume.
+     */
+    void updateTemperatures(FluidState &fs,
+                            ParameterCache &paramCache,
+                            const PrimaryVariables &sol,
+                            const Element &element,
+                            const FVElementGeometry &fvGeometry,
+                            const unsigned int scvIdx,
+                            const Problem &problem) const
+    {
+        // retrieve temperature from solution vector
+        Scalar T = sol[temperatureIdx];
+        fs.setTemperature(T);
+    }
+
+    /*!
+     * \brief Update the enthalpy and the internal energy for a given
+     *        control volume.
+     */
+    void update(FluidState &fs,
+                ParameterCache &paramCache,
+                const Element &element,
+                const FVElementGeometry &fvGeometry,
+                const unsigned int scvIdx,
+                const Problem &problem)
+    {
+        Valgrind::SetUndefined(*this);
+
+        // heat capacities of the fluids plus the porous medium
+        heatCapacity_ =
+            problem.spatialParams().heatCapacity(element, fvGeometry, scvIdx);
+        Valgrind::CheckDefined(heatCapacity_);
+
+        soilDensity_ =
+            problem.spatialParams().soilDensity(element, fvGeometry, scvIdx);
+        Valgrind::CheckDefined(soilDensity_);
+
+        // set the enthalpies
+        for (int phaseIdx = 0; phaseIdx < numPhases; ++phaseIdx) {
+            Scalar h = FluidSystem::enthalpy(fs, paramCache, phaseIdx);
+            fs.setEnthalpy(phaseIdx, h);
+        }
+    }
+
+    /*!
+     * \brief Returns the total heat capacity [J/(K m^3)] of the rock matrix in
+     *        the sub-control volume.
+     */
+    Scalar heatCapacity() const
+    { return heatCapacity_; };
+
+    /*!
+     * \brief Returns the total density of the given soil [kg / m^3] in
+     *        the sub-control volume.
+     */
+    Scalar soilDensity() const
+    { return soilDensity_; };
+
+    /*!
+     * \brief If running under valgrind this produces an error message
+     *        if some of the object's attributes is undefined.
+     */
+    void checkDefined() const
+    {
+        Valgrind::CheckDefined(heatCapacity_);
+        Valgrind::CheckDefined(soilDensity_);
+    };
+
+protected:
+    Scalar heatCapacity_;
+    Scalar soilDensity_;
+};
+
+} // end namepace
+
+#endif
diff --git a/dumux/implicit/mpnc/energy/mpncvtkwriterenergy.hh b/dumux/implicit/mpnc/energy/mpncvtkwriterenergy.hh
new file mode 100644
index 0000000000..558d881b8d
--- /dev/null
+++ b/dumux/implicit/mpnc/energy/mpncvtkwriterenergy.hh
@@ -0,0 +1,218 @@
+// -*- mode: C++; tab-width: 4; indent-tabs-mode: nil; c-basic-offset: 4 -*-
+// vi: set et ts=4 sw=4 sts=4:
+/*****************************************************************************
+ *   See the file COPYING for full copying permissions.                      *
+ *                                                                           *
+ *   This program is free software: you can redistribute it and/or modify    *
+ *   it under the terms of the GNU General Public License as published by    *
+ *   the Free Software Foundation, either version 2 of the License, or       *
+ *   (at your option) any later version.                                     *
+ *                                                                           *
+ *   This program is distributed in the hope that it will be useful,         *
+ *   but WITHOUT ANY WARRANTY; without even the implied warranty of          *
+ *   MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the            *
+ *   GNU General Public License for more details.                            *
+ *                                                                           *
+ *   You should have received a copy of the GNU General Public License       *
+ *   along with this program.  If not, see <http://www.gnu.org/licenses/>.   *
+ *****************************************************************************/
+/*!
+ * \file
+ *
+ * \brief VTK writer module for the energy related quantities of the
+ *        MpNc model.
+ */
+#ifndef DUMUX_MPNC_VTK_WRITER_ENERGY_HH
+#define DUMUX_MPNC_VTK_WRITER_ENERGY_HH
+
+#include "../mpncvtkwritermodule.hh"
+
+namespace Dumux
+{
+/*!
+ * \ingroup MPNCModel
+ *
+ * \brief VTK writer module for the energy related quantities of the
+ *        MpNc model.
+ *
+ * This is the specialization for the case without energy.
+ */
+template<class TypeTag,
+         bool enableEnergy /* = false */,
+         bool enableKineticEnergy /* = false */>
+class MPNCVtkWriterEnergy : public MPNCVtkWriterModule<TypeTag>
+{
+    static_assert(enableKineticEnergy == false,
+                  "If you enable kinetic energy transfer between fluids, you"
+                  "also have to enable the energy in general!");
+
+    typedef MPNCVtkWriterModule<TypeTag> ParentType;
+
+    typedef typename GET_PROP_TYPE(TypeTag, Problem) Problem;
+    typedef typename GET_PROP_TYPE(TypeTag, Scalar) Scalar;
+    typedef typename GET_PROP_TYPE(TypeTag, FVElementGeometry) FVElementGeometry;
+    typedef typename GET_PROP_TYPE(TypeTag, ElementVolumeVariables) ElementVolumeVariables;
+    typedef typename GET_PROP_TYPE(TypeTag, ElementBoundaryTypes) ElementBoundaryTypes;
+    typedef typename GET_PROP_TYPE(TypeTag, VolumeVariables) VolumeVariables;
+    typedef typename GET_PROP_TYPE(TypeTag, GridView) GridView;
+    typedef typename GridView::template Codim<0>::Entity Element;
+
+    enum { dim = GridView::dimension };
+
+    typedef typename ParentType::ScalarVector ScalarVector;
+    typedef typename ParentType::PhaseVector PhaseVector;
+
+public:
+    MPNCVtkWriterEnergy(const Problem &problem)
+        : ParentType(problem)
+    {
+        temperatureOutput_ = GET_PARAM_FROM_GROUP(TypeTag, bool, Vtk, AddTemperatures);
+    }
+
+    /*!
+     * \brief Allocate memory for the scalar fields we would like to
+     *        write to the VTK file.
+     */
+    template <class MultiWriter>
+    void allocBuffers(MultiWriter &writer)
+    {
+        if (temperatureOutput_) this->resizeScalarBuffer_(temperature_);
+    }
+
+    /*!
+     * \brief Modify the internal buffers according to the volume
+     *        variables seen on an element
+     */
+    void processElement(const Element &elem,
+                        const FVElementGeometry &fvGeometry,
+                        const ElementVolumeVariables &elemVolVars,
+                        const ElementBoundaryTypes &elemBcTypes)
+    {
+        int numLocalVertices = elem.geometry().corners();
+        for (int localVertexIdx = 0; localVertexIdx < numLocalVertices; ++localVertexIdx) {
+            const unsigned int globalIdx = this->problem_.vertexMapper().map(elem, localVertexIdx, dim);
+            const VolumeVariables &volVars = elemVolVars[localVertexIdx];
+
+            if (temperatureOutput_)
+                temperature_[globalIdx] = volVars.fluidState().temperature(/*phaseIdx=*/0);
+        }
+    }
+
+    /*!
+     * \brief Add all buffers to the VTK output writer.
+     */
+    template <class MultiWriter>
+    void commitBuffers(MultiWriter &writer)
+    {
+        if (temperatureOutput_)
+            this->commitScalarBuffer_(writer, "T", temperature_);
+    }
+
+private:
+    bool temperatureOutput_;
+
+    ScalarVector temperature_;
+};
+
+/*!
+ * \ingroup MPNCModel
+ *
+ * \brief VTK writer module for the energy related quantities of the
+ *        MpNc model.
+ *
+ * This is the specialization for the case with an energy equation but
+ * local thermal equilibrium. (i.e. no kinetic energy transfer)
+ */
+template<class TypeTag>
+class MPNCVtkWriterEnergy<TypeTag, /* enableEnergy = */ true, /* enableKineticEnergy = */ false >
+    : public MPNCVtkWriterModule<TypeTag>
+{
+    typedef MPNCVtkWriterModule<TypeTag> ParentType;
+    typedef typename GET_PROP_TYPE(TypeTag, Problem) Problem;
+    typedef typename GET_PROP_TYPE(TypeTag, Scalar) Scalar;
+    typedef typename GET_PROP_TYPE(TypeTag, FVElementGeometry) FVElementGeometry;
+    typedef typename GET_PROP_TYPE(TypeTag, ElementVolumeVariables) ElementVolumeVariables;
+    typedef typename GET_PROP_TYPE(TypeTag, ElementBoundaryTypes) ElementBoundaryTypes;
+    typedef typename GET_PROP_TYPE(TypeTag, VolumeVariables) VolumeVariables;
+    typedef typename GET_PROP_TYPE(TypeTag, GridView) GridView;
+    typedef typename GridView::template Codim<0>::Entity Element;
+
+    enum { dim = GridView::dimension };
+    enum { numPhases = GET_PROP_VALUE(TypeTag, NumPhases) };
+
+    typedef typename ParentType::ScalarVector ScalarVector;
+    typedef typename ParentType::PhaseVector PhaseVector;
+
+
+public:
+    MPNCVtkWriterEnergy(const Problem &problem)
+        : ParentType(problem)
+    {
+        temperatureOutput_ = GET_PARAM_FROM_GROUP(TypeTag, bool, Vtk, AddTemperatures);
+        enthalpyOutput_ = GET_PARAM_FROM_GROUP(TypeTag, bool, Vtk, AddEnthalpies);
+        internalEnergyOutput_ = GET_PARAM_FROM_GROUP(TypeTag, bool, Vtk, AddInternalEnergies);
+    }
+
+    /*!
+     * \brief Allocate memory for the scalar fields we would like to
+     *        write to the VTK file.
+     */
+    template <class MultiWriter>
+    void allocBuffers(MultiWriter &writer)
+    {
+        if (temperatureOutput_) this->resizeScalarBuffer_(temperature_);
+        if (enthalpyOutput_) this->resizePhaseBuffer_(enthalpy_);
+        if (internalEnergyOutput_) this->resizePhaseBuffer_(internalEnergy_);
+    }
+
+    /*!
+     * \brief Modify the internal buffers according to the volume
+     *        variables seen on an element
+     */
+    void processElement(const Element &elem,
+                        const FVElementGeometry &fvGeometry,
+                        const ElementVolumeVariables &elemVolVars,
+                        const ElementBoundaryTypes &elemBcTypes)
+    {
+        const unsigned int numLocalVertices = elem.geometry().corners();
+        for (int localVertexIdx = 0; localVertexIdx < numLocalVertices; ++localVertexIdx) {
+            int gobalIdx = this->problem_.vertexMapper().map(elem, localVertexIdx, dim);
+            const VolumeVariables &volVars = elemVolVars[localVertexIdx];
+
+            if (temperatureOutput_) temperature_[gobalIdx] = volVars.fluidState().temperature(/*phaseIdx=*/0);
+            for (int phaseIdx = 0; phaseIdx < numPhases; ++ phaseIdx) {
+                if (enthalpyOutput_)
+                    enthalpy_[phaseIdx][gobalIdx] = volVars.fluidState().temperature(phaseIdx);
+                if (internalEnergyOutput_)
+                    internalEnergy_[phaseIdx][gobalIdx] = volVars.fluidState().internalEnergy(phaseIdx);
+            }
+        }
+    }
+
+    /*!
+     * \brief Add all buffers to the VTK output writer.
+     */
+    template <class MultiWriter>
+    void commitBuffers(MultiWriter &writer)
+    {
+        if (temperatureOutput_)
+            this->commitScalarBuffer_(writer, "T", temperature_);
+        if (enthalpyOutput_)
+            this->commitPhaseBuffer_(writer, "h_%s", enthalpy_);
+        if (internalEnergyOutput_)
+            this->commitPhaseBuffer_(writer, "u_%s", internalEnergy_);
+    }
+
+private:
+    bool temperatureOutput_;
+    bool enthalpyOutput_;
+    bool internalEnergyOutput_;
+
+    ScalarVector temperature_;
+    PhaseVector enthalpy_;
+    PhaseVector internalEnergy_;
+};
+
+}
+
+#endif
diff --git a/dumux/implicit/mpnc/mass/Makefile.am b/dumux/implicit/mpnc/mass/Makefile.am
new file mode 100644
index 0000000000..01a0fc6234
--- /dev/null
+++ b/dumux/implicit/mpnc/mass/Makefile.am
@@ -0,0 +1,4 @@
+massdir = $(includedir)/dumux/boxmodels/mpnc/mass
+mass_HEADERS = *.hh
+
+include $(top_srcdir)/am/global-rules
diff --git a/dumux/implicit/mpnc/mass/mpncindicesmass.hh b/dumux/implicit/mpnc/mass/mpncindicesmass.hh
new file mode 100644
index 0000000000..06c037fc68
--- /dev/null
+++ b/dumux/implicit/mpnc/mass/mpncindicesmass.hh
@@ -0,0 +1,84 @@
+// -*- mode: C++; tab-width: 4; indent-tabs-mode: nil; c-basic-offset: 4 -*-
+// vi: set et ts=4 sw=4 sts=4:
+/*****************************************************************************
+ *   See the file COPYING for full copying permissions.                      *
+ *                                                                           *
+ *   This program is free software: you can redistribute it and/or modify    *
+ *   it under the terms of the GNU General Public License as published by    *
+ *   the Free Software Foundation, either version 2 of the License, or       *
+ *   (at your option) any later version.                                     *
+ *                                                                           *
+ *   This program is distributed in the hope that it will be useful,         *
+ *   but WITHOUT ANY WARRANTY; without even the implied warranty of          *
+ *   MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the            *
+ *   GNU General Public License for more details.                            *
+ *                                                                           *
+ *   You should have received a copy of the GNU General Public License       *
+ *   along with this program.  If not, see <http://www.gnu.org/licenses/>.   *
+ *****************************************************************************/
+/*!
+ * \brief The indices for the mass flow part of the compositional
+ *        multi-phase model.
+ */
+#ifndef DUMUX_MPNC_MASS_INDICES_HH
+#define DUMUX_MPNC_MASS_INDICES_HH
+
+#include <dumux/boxmodels/mpnc/mpncproperties.hh>
+
+namespace Dumux
+{
+/*!
+ * \brief The indices required for conservation of mass.
+ *
+ * This is the specialization for the case without kinetic mass
+ * transfer (i.e. assuming chemical equilibrium)
+ */
+template <int PVOffset,
+          class TypeTag,
+          bool enableKinetic /*=false*/>
+class MPNCMassIndices
+{
+    static_assert(!enableKinetic,
+                  "No kinetic mass transfer module included, "
+                  "but kinetic mass transfer enabled.");
+
+    enum { numComponents = GET_PROP_VALUE(TypeTag, NumComponents) };
+
+public:
+    /*!
+     * \brief This module defines one new primary variable.
+     */
+    static const unsigned int NumPrimaryVars = numComponents;
+
+    /*!
+     * \brief Index for the fugacity of the first component in the
+     *        first phase in a vector of primary variables.
+     *
+     * The next numComponents indices represent the remaining
+     * fugacities:
+     *
+     *  fug0Idx + 0 = fugacity of component 0
+     *  fug0Idx + 1 = fugacity of component 1
+     *  ...
+     *  fug0Idx + N - 1 = fugacity of component N
+     */
+    static const unsigned int fug0Idx = PVOffset + 0;
+
+    /*!
+     * \brief Equation index of the mass conservation equation for the
+     *        first component.
+     *
+     * The next numComponents indices represent the equations of all
+     * components in all phases:
+     *
+     *  conti00EqIdx + 0 = continuity of component 0
+     *  conti00EqIdx + 1 = continuity of component 1
+     *  ...
+     *  conti00EqIdx + N - 1 = continuity of component N
+     */
+    static const unsigned int conti0EqIdx = PVOffset + 0;
+};
+
+}
+
+#endif
diff --git a/dumux/implicit/mpnc/mass/mpnclocalresidualmass.hh b/dumux/implicit/mpnc/mass/mpnclocalresidualmass.hh
new file mode 100644
index 0000000000..77adf69355
--- /dev/null
+++ b/dumux/implicit/mpnc/mass/mpnclocalresidualmass.hh
@@ -0,0 +1,369 @@
+// -*- mode: C++; tab-width: 4; indent-tabs-mode: nil; c-basic-offset: 4 -*-
+// vi: set et ts=4 sw=4 sts=4:
+/*****************************************************************************
+ *   See the file COPYING for full copying permissions.                      *
+ *                                                                           *
+ *   This program is free software: you can redistribute it and/or modify    *
+ *   it under the terms of the GNU General Public License as published by    *
+ *   the Free Software Foundation, either version 2 of the License, or       *
+ *   (at your option) any later version.                                     *
+ *                                                                           *
+ *   This program is distributed in the hope that it will be useful,         *
+ *   but WITHOUT ANY WARRANTY; without even the implied warranty of          *
+ *   MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the            *
+ *   GNU General Public License for more details.                            *
+ *                                                                           *
+ *   You should have received a copy of the GNU General Public License       *
+ *   along with this program.  If not, see <http://www.gnu.org/licenses/>.   *
+ *****************************************************************************/
+#ifndef DUMUX_MPNC_LOCAL_RESIDUAL_MASS_HH
+#define DUMUX_MPNC_LOCAL_RESIDUAL_MASS_HH
+
+#include <dune/common/fvector.hh>
+
+#include <dumux/boxmodels/mpnc/mpncproperties.hh>
+#include <dumux/material/constraintsolvers/compositionfromfugacities.hh>
+#include <dumux/common/math.hh>
+#include <dumux/common/spline.hh>
+
+#include "../diffusion/diffusion.hh"
+#include "../energy/mpnclocalresidualenergy.hh"
+
+namespace Dumux
+{
+/*!
+ * \brief The mass conservation part of the Mp-Nc model.
+ *
+ * This is the class represents methods which are shared amongst all
+ * mass conservation modules.
+ */
+template<class TypeTag>
+class MPNCLocalResidualMassCommon
+{
+protected:
+    typedef typename GET_PROP_TYPE(TypeTag, GridView) GridView;
+    typedef typename GET_PROP_TYPE(TypeTag, Scalar) Scalar;
+    typedef typename GET_PROP_TYPE(TypeTag, VolumeVariables) VolumeVariables;
+    typedef typename GET_PROP_TYPE(TypeTag, FluxVariables) FluxVariables;
+
+    enum { dim = GridView::dimension };
+    enum { numPhases        = GET_PROP_VALUE(TypeTag, NumPhases) };
+    enum { numComponents    = GET_PROP_VALUE(TypeTag, NumComponents) };
+    enum { enableDiffusion  = GET_PROP_VALUE(TypeTag, EnableDiffusion) };
+    enum { enableEnergy     = GET_PROP_VALUE(TypeTag, EnableEnergy) };
+    enum { enableKineticEnergy     = GET_PROP_VALUE(TypeTag, EnableKineticEnergy) };
+
+    typedef typename Dune::FieldVector<Scalar, dim> DimVector;
+    typedef typename Dune::FieldVector<Scalar, numComponents> ComponentVector;
+    typedef MPNCDiffusion<TypeTag, enableDiffusion> Diffusion;
+    typedef MPNCLocalResidualEnergy<TypeTag, enableEnergy, enableKineticEnergy> EnergyResid;
+
+public:
+    /*!
+     * \brief Evaluate the amount moles within a sub-control volume in
+     *        a phase.
+     *
+     * The result should be averaged over the volume.
+     */
+    static void computePhaseStorage(ComponentVector &storage,
+                                    const VolumeVariables &volVars,
+                                    const unsigned int phaseIdx)
+    {
+        // compute storage term of all components within all phases
+        storage = 0;
+        for (int compIdx = 0; compIdx < numComponents; ++ compIdx) {
+            storage[compIdx] +=
+                volVars.fluidState().saturation(phaseIdx)*
+                volVars.fluidState().molarity(phaseIdx, compIdx);
+        }
+
+        storage *= volVars.porosity();
+    }
+
+    /*!
+     * \brief Evaluates the advective flux of all conservation
+     *        quantities over a face of a subcontrol volume via a
+     *        fluid phase.
+     */
+    static void computeAdvectivePhaseFlux(ComponentVector &flux,
+                                          const FluxVariables &fluxVars,
+                                          const unsigned int phaseIdx)
+    {
+
+        const Scalar volumeFlux =  fluxVars.volumeFlux(phaseIdx) ;
+        #ifndef NDEBUG
+        if (!std::isfinite(volumeFlux))
+            DUNE_THROW(NumericalProblem, "Calculated non-finite normal flux");
+        #endif
+
+        // retrieve the upwind weight for the mass conservation equations. Use the value
+        // specified via the property system as default, and overwrite
+        // it by the run-time parameter from the Dune::ParameterTree
+        const Scalar massUpwindWeight = GET_PARAM_FROM_GROUP(TypeTag, Scalar, Implicit, MassUpwindWeight);
+
+        static bool enableSmoothUpwinding_ = GET_PARAM_FROM_GROUP(TypeTag, bool, Implicit, EnableSmoothUpwinding);
+
+        // data attached to upstream and the downstream vertices
+        // of the current phase
+        unsigned int upIdx = fluxVars.upstreamIdx(phaseIdx);
+        unsigned int dnIdx = fluxVars.downstreamIdx(phaseIdx);
+
+        const VolumeVariables &up = fluxVars.volVars(upIdx);
+        const VolumeVariables &dn = fluxVars.volVars(dnIdx);
+
+        ////////
+        // advective fluxes of all components in the phase
+        ////////
+        for (unsigned int compIdx = 0; compIdx < numComponents; ++compIdx) {
+            // add advective flux of current component in current
+            // phase. we use full upwinding.
+            if (enableSmoothUpwinding_) {
+                const Scalar kGradPNormal   = fluxVars.kGradPNormal(phaseIdx);
+                const Scalar mobUp          = up.mobility(phaseIdx);
+                const Scalar conUp          = up.fluidState().molarity(phaseIdx, compIdx);
+
+                const Scalar mobDn  = dn.mobility(phaseIdx);
+                const Scalar conDn  = dn.fluidState().molarity(phaseIdx, compIdx);
+
+                const Scalar mobConUp   = mobUp*conUp;
+                const Scalar mobConDn   = mobDn*conDn;
+                const Scalar meanMobCon = Dumux::harmonicMean(mobConUp, mobConDn);
+
+                const Scalar x      = std::abs(kGradPNormal);
+                const Scalar sign   = (kGradPNormal > 0)?-1:1;
+
+                // the direction from upstream to downstream
+                //GlobalPosition delta = this->curElement_().geometry().corner(upIdx);
+                //delta -= this->curElement_().geometry().corner(dnIdx);
+
+                // approximate the mean viscosity at the face
+                const Scalar meanVisc = (up.fluidState().viscosity(phaseIdx) +
+                                   dn.fluidState().viscosity(phaseIdx))/2;
+
+                // put the mean viscosity and permeanbility in
+                // relation to the viscosity of water at
+                // approximatly 20 degrees Celsius.
+                const Scalar pGradRef   = 10; // [Pa/m]
+                const Scalar muRef      = 1e-3; // [Ns/m^2]
+                const Scalar Kref       = 1e-12; // [m^2] = approx 1 Darcy
+
+                const Scalar faceArea   = fluxVars.face().normal.two_norm();
+                const Scalar eps        = pGradRef * Kref * faceArea * meanVisc/muRef; // * (1e3/18e-3)/meanC;
+
+                Scalar compFlux;
+                if (x >= eps) {
+                    // we only do tricks if x is below the epsilon
+                    // value
+                    compFlux = x*mobConUp;
+                }
+                else {
+                    const Scalar xPos[] = { 0, eps };
+                    const Scalar yPos[] = { 0, eps*mobConUp };
+                    const Spline<Scalar> sp2(xPos, yPos, meanMobCon, mobConUp);
+                    compFlux = sp2.eval(x);
+                }
+                #ifndef NDEBUG
+                if (!std::isfinite(compFlux))
+                    DUNE_THROW(NumericalProblem, "Calculated non-finite normal flux in smooth upwinding");
+                #endif
+
+                flux[compIdx] = sign*compFlux;
+            }
+            else
+            {// not use smooth upwinding
+                flux[compIdx] =
+                        volumeFlux *
+                        ((     massUpwindWeight)*up.fluidState().molarity(phaseIdx, compIdx)
+                                +
+                        (  1. - massUpwindWeight)*dn.fluidState().molarity(phaseIdx, compIdx) );
+
+
+            }
+        }
+    }
+
+
+    /*!
+     * \brief Evaluates the advective flux of all conservation
+     *        quantities over a face of a subcontrol volume via a
+     *        fluid phase.
+     */
+    static void computeDiffusivePhaseFlux(ComponentVector &flux,
+                                          const FluxVariables &fluxVars,
+                                          const unsigned int phaseIdx)
+    {
+        if (!enableDiffusion) {
+            flux = 0.0;
+            return;
+        }
+
+
+        const VolumeVariables &volVarsI = fluxVars.volVars(fluxVars.face().i);
+        const VolumeVariables &volVarsJ = fluxVars.volVars(fluxVars.face().j);
+        if (volVarsI.fluidState().saturation(phaseIdx) < 1e-4 ||
+            volVarsJ.fluidState().saturation(phaseIdx) < 1e-4)
+        {
+            return; // phase is not present in one of the finite volumes
+        }
+
+        // approximate the total concentration of the phase at the
+        // integration point by the arithmetic mean of the
+        // concentration of the sub-control volumes
+        Scalar molarDensityAtIP;
+        molarDensityAtIP = volVarsI.fluidState().molarDensity(phaseIdx);
+        molarDensityAtIP += volVarsJ.fluidState().molarDensity(phaseIdx);
+        molarDensityAtIP /= 2;
+
+        Diffusion::flux(flux, phaseIdx, fluxVars, molarDensityAtIP);
+    }
+};
+
+/*!
+ * \brief The mass conservation part of the Mp-Nc model.
+ *
+ * This is the specialization for the case where kinetic mass transfer
+ * is _not_ considered.
+ */
+template<class TypeTag, bool enableKinetic /*=false*/>
+class MPNCLocalResidualMass
+{
+    static_assert(!enableKinetic,
+                  "No kinetic mass transfer module included, "
+                  "but kinetic mass transfer enabled.");
+
+    typedef MPNCLocalResidualMassCommon<TypeTag> MassCommon;
+    typedef typename GET_PROP_TYPE(TypeTag, Scalar) Scalar;
+    typedef typename GET_PROP_TYPE(TypeTag, Indices) Indices;
+    typedef typename GET_PROP_TYPE(TypeTag, PrimaryVariables) PrimaryVariables;
+    typedef typename GET_PROP_TYPE(TypeTag, VolumeVariables) VolumeVariables;
+    typedef typename GET_PROP_TYPE(TypeTag, ElementVolumeVariables) ElementVolumeVariables;
+    typedef typename GET_PROP_TYPE(TypeTag, FluxVariables) FluxVariables;
+
+    enum { numPhases        = GET_PROP_VALUE(TypeTag, NumPhases) };
+    enum { numComponents    = GET_PROP_VALUE(TypeTag, NumComponents) };
+    enum { conti0EqIdx      = Indices::conti0EqIdx };
+    enum { enableEnergy     = GET_PROP_VALUE(TypeTag, EnableEnergy) };
+    enum { enableKineticEnergy     = GET_PROP_VALUE(TypeTag, EnableKineticEnergy) };
+
+    typedef typename Dune::FieldVector<Scalar, numComponents> ComponentVector;
+    typedef MPNCLocalResidualEnergy<TypeTag, enableEnergy, enableKineticEnergy> EnergyResid;
+
+public:
+    /*!
+     * \brief Calculate the storage for all mass balance equations
+     */
+    static void computeStorage(PrimaryVariables &storage,
+                               const VolumeVariables &volVars)
+    {
+        for (int compIdx = 0; compIdx < numComponents; ++compIdx)
+            storage[conti0EqIdx + compIdx] = 0.0;
+
+        for (int phaseIdx = 0; phaseIdx < numPhases; ++phaseIdx) {
+            addPhaseStorage(storage, volVars, phaseIdx);
+        }
+    }
+
+    /*!
+     * \brief Calculate the storage for all mass balance equations
+     *        within a single fluid phase
+     */
+    static void addPhaseStorage(PrimaryVariables &storage,
+                                const VolumeVariables &volVars,
+                                const unsigned int phaseIdx)
+    {
+        // calculate the component-wise mass storage
+        ComponentVector phaseComponentValues;
+        MassCommon::computePhaseStorage(phaseComponentValues,
+                                        volVars,
+                                        phaseIdx);
+
+        // copy to the primary variables
+        for (int compIdx = 0; compIdx < numComponents; ++compIdx)
+            storage[conti0EqIdx + compIdx] += phaseComponentValues[compIdx];
+    }
+
+    /*!
+     * \brief Calculate the storage for all mass balance equations
+     */
+    static void computeFlux(PrimaryVariables &flux,
+                            const FluxVariables &fluxVars,
+                            const ElementVolumeVariables & elemVolVars)
+    {
+        for (int compIdx = 0; compIdx < numComponents; ++compIdx)
+            flux[conti0EqIdx + compIdx] = 0.0;
+
+        ComponentVector phaseComponentValuesAdvection(0.);
+        ComponentVector phaseComponentValuesDiffusion(0.);
+        ComponentVector phaseComponentValuesMassTransport[numPhases]; // what goes into the energy module
+
+        for (int phaseIdx = 0; phaseIdx < numPhases; ++phaseIdx) {
+            MassCommon::computeAdvectivePhaseFlux(phaseComponentValuesAdvection, fluxVars, phaseIdx);
+            Valgrind::CheckDefined(phaseComponentValuesAdvection);
+            for (int compIdx = 0; compIdx < numComponents; ++compIdx)
+                flux[conti0EqIdx + compIdx] +=
+                        phaseComponentValuesAdvection[compIdx];
+
+            MassCommon::computeDiffusivePhaseFlux(phaseComponentValuesDiffusion, fluxVars, phaseIdx);
+            Valgrind::CheckDefined(phaseComponentValuesDiffusion);
+            for (int compIdx = 0; compIdx < numComponents; ++compIdx)
+                flux[conti0EqIdx + compIdx] +=
+                        phaseComponentValuesDiffusion[compIdx];
+
+            // Right now I think that adding the two contributions individually into the flux is best for debugging and understanding.
+            // The Energy module needs both contributions.
+            phaseComponentValuesMassTransport[phaseIdx] = phaseComponentValuesDiffusion + phaseComponentValuesAdvection ;
+            Valgrind::CheckDefined(flux);
+        }
+
+        // \todo
+        //
+        // The computeflux() of the Energy module needs a
+        // component-wise flux (for the diffusive enthalpy transport)
+        // It makes some sense calling energy from here, because energy
+        // is carried by mass. However, it is not really a clean
+        // solution.
+
+        // energy transport in fluid phases
+        EnergyResid::computeFlux(flux,
+                                 fluxVars,
+                                 elemVolVars,
+                                 phaseComponentValuesMassTransport);
+        Valgrind::CheckDefined(flux);
+    }
+
+
+
+    /*!
+     * \brief Calculate the source terms for all mass balance
+     *        equations
+     */
+    static void computeSource(PrimaryVariables &source,
+                              const VolumeVariables &volVars)
+    {
+    	static_assert(not enableKineticEnergy, // enableKinetic is disabled, in this specialization
+    			"In the case of kinetic energy transfer the advective energy transport between the phases has to be considered. "
+    			"It is hard (technically) to say how much mass got transfered in the case of chemical equilibrium. "
+    			"Therefore, kineticEnergy and no kinetic mass does not fit (yet).");
+
+        // mass transfer is not considered in this mass module
+        for (int compIdx = 0; compIdx < numComponents; ++compIdx)
+            source[conti0EqIdx + compIdx] = 0.0;
+
+
+        PrimaryVariables tmpPriVars(0);
+        // Similar to the compute Flux, the energy residual needs to be called from the
+        // mass residual.
+        ComponentVector dummy[numPhases];
+            for (int iDummy =0; iDummy <numPhases; ++iDummy)
+                dummy[iDummy] = 0.;
+        EnergyResid::computeSource(tmpPriVars,
+                                   volVars,
+                                   dummy);
+        source += tmpPriVars;
+        Valgrind::CheckDefined(source);
+    }
+};
+
+} // end namepace
+
+#endif
diff --git a/dumux/implicit/mpnc/mass/mpncvolumevariablesmass.hh b/dumux/implicit/mpnc/mass/mpncvolumevariablesmass.hh
new file mode 100644
index 0000000000..625b89ae58
--- /dev/null
+++ b/dumux/implicit/mpnc/mass/mpncvolumevariablesmass.hh
@@ -0,0 +1,131 @@
+// -*- mode: C++; tab-width: 4; indent-tabs-mode: nil; c-basic-offset: 4 -*-
+// vi: set et ts=4 sw=4 sts=4:
+/*****************************************************************************
+ *   See the file COPYING for full copying permissions.                      *
+ *                                                                           *
+ *   This program is free software: you can redistribute it and/or modify    *
+ *   it under the terms of the GNU General Public License as published by    *
+ *   the Free Software Foundation, either version 2 of the License, or       *
+ *   (at your option) any later version.                                     *
+ *                                                                           *
+ *   This program is distributed in the hope that it will be useful,         *
+ *   but WITHOUT ANY WARRANTY; without even the implied warranty of          *
+ *   MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the            *
+ *   GNU General Public License for more details.                            *
+ *                                                                           *
+ *   You should have received a copy of the GNU General Public License       *
+ *   along with this program.  If not, see <http://www.gnu.org/licenses/>.   *
+ *****************************************************************************/
+/*!
+ * \file
+ *
+ * \brief Contains the mass conservation part of the volume variables
+ */
+#ifndef DUMUX_MPNC_VOLUME_VARIABLES_MASS_HH
+#define DUMUX_MPNC_VOLUME_VARIABLES_MASS_HH
+
+#include <dumux/boxmodels/mpnc/mpncproperties.hh>
+
+#include <dumux/material/fluidstates/compositionalfluidstate.hh>
+
+namespace Dumux
+{
+/*!
+ * \brief The compositional part of the volume variables if chemical
+ *        equilibrium _is_ assumed
+ */
+template <class TypeTag, bool enableKinetic /* = false */>
+class MPNCVolumeVariablesMass
+{
+    static_assert(!enableKinetic,
+                  "No kinetic mass transfer module included, "
+                  "but kinetic mass transfer enabled.");
+
+    typedef typename GET_PROP_TYPE(TypeTag, PrimaryVariables) PrimaryVariables;
+    typedef typename GET_PROP_TYPE(TypeTag, Scalar) Scalar;
+    typedef typename GET_PROP_TYPE(TypeTag, FluidSystem) FluidSystem;
+    typedef typename GET_PROP_TYPE(TypeTag, FluidState) FluidState;
+    typedef typename FluidSystem::ParameterCache ParameterCache;
+    typedef typename GET_PROP_TYPE(TypeTag, Indices) Indices;
+    typedef typename GET_PROP_TYPE(TypeTag, Problem) Problem;
+    typedef typename GET_PROP_TYPE(TypeTag, VolumeVariables) VolumeVariables;
+    typedef typename GET_PROP_TYPE(TypeTag, FVElementGeometry) FVElementGeometry;
+    typedef typename GET_PROP_TYPE(TypeTag, GridView) GridView;
+    typedef typename GET_PROP_TYPE(TypeTag, ConstraintSolver) ConstraintSolver;
+    typedef typename GridView::template Codim<0>::Entity Element;
+
+    enum { numPhases = GET_PROP_VALUE(TypeTag, NumPhases) };
+    enum { numComponents = GET_PROP_VALUE(TypeTag, NumComponents) };
+    enum { fug0Idx = Indices::fug0Idx };
+
+    typedef Dune::FieldVector<Scalar, numComponents> ComponentVector;
+
+public:
+    /*!
+     * \brief Update composition of all phases in the mutable
+     *        parameters from the primary variables.
+     */
+    void update(FluidState &fs,
+                ParameterCache &paramCache,
+                const PrimaryVariables &priVars,
+                const VolumeVariables *hint,
+                const Problem &problem,
+                const Element &element,
+                const FVElementGeometry &fvGeometry,
+                const unsigned int scvIdx)
+    {
+        ComponentVector fug;
+        // retrieve component fugacities
+        for (int compIdx = 0; compIdx < numComponents; ++compIdx)
+            fug[compIdx] = priVars[fug0Idx + compIdx];
+
+        // calculate phase compositions
+        for (int phaseIdx = 0; phaseIdx < numPhases; ++phaseIdx) {
+            // initial guess
+            for (int compIdx = 0; compIdx < numComponents; ++compIdx) {
+                Scalar x_ij = 1.0/numComponents;
+                if (hint)
+                    // use the hint for the initial mole fraction!
+                    x_ij = hint->fluidState().moleFraction(phaseIdx, compIdx);
+
+                // set initial guess of the component's mole fraction
+                fs.setMoleFraction(phaseIdx,
+                                   compIdx,
+                                   x_ij);
+
+            }
+
+            // calculate the phase composition from the component
+            // fugacities
+            if (!hint)
+                // if no hint was given, we ask the constraint solver
+                // to make an initial guess
+                ConstraintSolver::guessInitial(fs, paramCache, phaseIdx, fug);
+            ConstraintSolver::solve(fs, paramCache, phaseIdx, fug);
+
+            /*
+              std::cout << "final composition: " << FluidSystem::phaseName(phaseIdx) << "="
+              << fs.moleFrac(phaseIdx, 0) << " "
+              << fs.moleFrac(phaseIdx, 1) << " "
+              << fs.moleFrac(phaseIdx, 2) << " "
+              << fs.moleFrac(phaseIdx, 3) << " "
+              << fs.moleFrac(phaseIdx, 4) << " "
+              << fs.moleFrac(phaseIdx, 5) << " "
+              << fs.moleFrac(phaseIdx, 6) << "\n";
+            */
+
+        }
+    }
+
+    /*!
+     * \brief If running in valgrind this makes sure that all
+     *        quantities in the volume variables are defined.
+     */
+    void checkDefined() const
+    {
+    }
+};
+
+} // end namepace
+
+#endif
diff --git a/dumux/implicit/mpnc/mass/mpncvtkwritermass.hh b/dumux/implicit/mpnc/mass/mpncvtkwritermass.hh
new file mode 100644
index 0000000000..23583d2482
--- /dev/null
+++ b/dumux/implicit/mpnc/mass/mpncvtkwritermass.hh
@@ -0,0 +1,118 @@
+// -*- mode: C++; tab-width: 4; indent-tabs-mode: nil; c-basic-offset: 4 -*-
+// vi: set et ts=4 sw=4 sts=4:
+/*****************************************************************************
+ *   See the file COPYING for full copying permissions.                      *
+ *                                                                           *
+ *   This program is free software: you can redistribute it and/or modify    *
+ *   it under the terms of the GNU General Public License as published by    *
+ *   the Free Software Foundation, either version 2 of the License, or       *
+ *   (at your option) any later version.                                     *
+ *                                                                           *
+ *   This program is distributed in the hope that it will be useful,         *
+ *   but WITHOUT ANY WARRANTY; without even the implied warranty of          *
+ *   MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the            *
+ *   GNU General Public License for more details.                            *
+ *                                                                           *
+ *   You should have received a copy of the GNU General Public License       *
+ *   along with this program.  If not, see <http://www.gnu.org/licenses/>.   *
+ *****************************************************************************/
+/*!
+ * \file
+ *
+ * \brief VTK writer module for the mass related quantities of the
+ *        MpNc model.
+ */
+#ifndef DUMUX_MPNC_VTK_WRITER_MASS_HH
+#define DUMUX_MPNC_VTK_WRITER_MASS_HH
+
+#include "../mpncvtkwritermodule.hh"
+
+namespace Dumux
+{
+/*!
+ * \ingroup MPNCModel
+ *
+ * \brief VTK writer module for the mass related quantities of the
+ *        MpNc model.
+ *
+ * This is the specialization for the case _without_ kinetic mass
+ * transfer between phases.
+ */
+template<class TypeTag, bool enableKinetic /* = false */>
+class MPNCVtkWriterMass : public MPNCVtkWriterModule<TypeTag>
+{
+    static_assert(!enableKinetic,
+                  "No kinetic mass transfer module included, "
+                  "but kinetic mass transfer enabled.");
+
+    typedef MPNCVtkWriterModule<TypeTag> ParentType;
+    typedef typename GET_PROP_TYPE(TypeTag, Problem) Problem;
+    typedef typename GET_PROP_TYPE(TypeTag, FVElementGeometry) FVElementGeometry;
+    typedef typename GET_PROP_TYPE(TypeTag, ElementVolumeVariables) ElementVolumeVariables;
+    typedef typename GET_PROP_TYPE(TypeTag, ElementBoundaryTypes) ElementBoundaryTypes;
+    typedef typename GET_PROP_TYPE(TypeTag, VolumeVariables) VolumeVariables;
+    typedef typename GET_PROP_TYPE(TypeTag, GridView) GridView;
+    typedef typename GridView::template Codim<0>::Entity Element;
+
+    enum { dim = GridView::dimension };
+    enum { numComponents = GET_PROP_VALUE(TypeTag, NumComponents) };
+
+    typedef typename ParentType::ComponentVector ComponentVector;
+    bool fugacityOutput_;
+
+public:
+    MPNCVtkWriterMass(const Problem &problem)
+        : ParentType(problem)
+    {
+        fugacityOutput_ = GET_PARAM_FROM_GROUP(TypeTag, bool, Vtk, AddFugacities);
+    }
+
+    /*!
+     * \brief Allocate memory for the scalar fields we would like to
+     *        write to the VTK file.
+     */
+    template <class MultiWriter>
+    void allocBuffers(MultiWriter &writer)
+    {
+        if (fugacityOutput_) this->resizeComponentBuffer_(fugacity_);
+    }
+
+    /*!
+     * \brief Modify the internal buffers according to the volume
+     *        variables seen on an element
+     */
+    void processElement(const Element &elem,
+                        const FVElementGeometry &fvElemGeom,
+                        const ElementVolumeVariables &elemVolVars,
+                        const ElementBoundaryTypes &elemBcTypes)
+    {
+        int numLocalVertices = elem.geometry().corners();
+        for (int localVertexIdx = 0; localVertexIdx < numLocalVertices; ++localVertexIdx) {
+            int globalIdx = this->problem_.vertexMapper().map(elem, localVertexIdx, dim);
+            const VolumeVariables &volVars = elemVolVars[localVertexIdx];
+
+            if (fugacityOutput_) {
+                for (int compIdx = 0; compIdx < numComponents; ++compIdx) {
+                    fugacity_[compIdx][globalIdx] = volVars.fluidState().fugacity(compIdx);
+                }
+            }
+        }
+    }
+
+    /*!
+     * \brief Add all buffers to the VTK output writer.
+     */
+    template <class MultiWriter>
+    void commitBuffers(MultiWriter &writer)
+    {
+        if (fugacityOutput_)
+            this->commitComponentBuffer_(writer, "f_%s", fugacity_);
+    }
+
+private:
+    ComponentVector fugacity_;
+};
+
+}
+
+#endif
diff --git a/dumux/implicit/mpnc/mpncfluxvariables.hh b/dumux/implicit/mpnc/mpncfluxvariables.hh
new file mode 100644
index 0000000000..2ef1640338
--- /dev/null
+++ b/dumux/implicit/mpnc/mpncfluxvariables.hh
@@ -0,0 +1,174 @@
+// -*- mode: C++; tab-width: 4; indent-tabs-mode: nil; c-basic-offset: 4 -*-
+// vi: set et ts=4 sw=4 sts=4:
+/*****************************************************************************
+ *   See the file COPYING for full copying permissions.                      *
+ *                                                                           *
+ *   This program is free software: you can redistribute it and/or modify    *
+ *   it under the terms of the GNU General Public License as published by    *
+ *   the Free Software Foundation, either version 2 of the License, or       *
+ *   (at your option) any later version.                                     *
+ *                                                                           *
+ *   This program is distributed in the hope that it will be useful,         *
+ *   but WITHOUT ANY WARRANTY; without even the implied warranty of          *
+ *   MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the            *
+ *   GNU General Public License for more details.                            *
+ *                                                                           *
+ *   You should have received a copy of the GNU General Public License       *
+ *   along with this program.  If not, see <http://www.gnu.org/licenses/>.   *
+ *****************************************************************************/
+/*!
+ * \file
+ *
+ * \brief This file contains the data which is required to calculate
+ *        all fluxes of components over a face of a finite volume.
+ *
+ * This means pressure, concentration and temperature gradients, phase
+ * densities at the integration point, etc.
+ */
+#ifndef DUMUX_MPNC_FLUX_VARIABLES_HH
+#define DUMUX_MPNC_FLUX_VARIABLES_HH
+
+#include <dumux/common/spline.hh>
+
+#include "diffusion/fluxvariables.hh"
+#include "energy/mpncfluxvariablesenergy.hh"
+#include <dumux/boxmodels/common/boxdarcyfluxvariables.hh>
+#include <dumux/boxmodels/common/boxforchheimerfluxvariables.hh>
+
+namespace Dumux
+{
+
+/*!
+ * \ingroup MPNCModel
+ * \ingroup BoxFluxVariables
+ * \brief This template class contains the data which is required to
+ *        calculate all fluxes of components over a face of a finite
+ *        volume for the two-phase, three-component model.
+ *
+ * This means pressure and concentration gradients, phase densities at
+ * the intergration point, etc.
+ */
+template <class TypeTag>
+class MPNCFluxVariables
+    : public GET_PROP_TYPE(TypeTag, BaseFluxVariables)
+{
+    typedef typename GET_PROP_TYPE(TypeTag, Problem) Problem;
+    typedef typename GET_PROP_TYPE(TypeTag, SpatialParams) SpatialParams;
+    typedef typename GET_PROP_TYPE(TypeTag, Scalar) Scalar;
+    typedef typename GET_PROP_TYPE(TypeTag, GridView) GridView;
+    typedef typename GridView::template Codim<0>::Entity Element;
+    typedef typename GET_PROP_TYPE(TypeTag, ElementVolumeVariables) ElementVolumeVariables;
+    typedef typename GET_PROP_TYPE(TypeTag, VolumeVariables) VolumeVariables;
+
+    typedef typename GET_PROP_TYPE(TypeTag, BaseFluxVariables) BaseFluxVariables;
+
+    enum {dim= GridView::dimension};
+    enum {numPhases = GET_PROP_VALUE(TypeTag, NumPhases)};
+    enum {enableDiffusion = GET_PROP_VALUE(TypeTag, EnableDiffusion)};
+    enum {enableEnergy = GET_PROP_VALUE(TypeTag, EnableEnergy)};
+    enum {enableKinetic = GET_PROP_VALUE(TypeTag, EnableKinetic)};
+    enum {enableKineticEnergy = GET_PROP_VALUE(TypeTag, EnableKineticEnergy)};
+
+    typedef Dune::FieldVector<Scalar, dim> DimVector;
+    typedef Dune::FieldMatrix<Scalar, dim, dim> DimMatrix;
+    typedef typename GET_PROP_TYPE(TypeTag, FVElementGeometry) FVElementGeometry;
+    typedef typename FVElementGeometry::SubControlVolumeFace SCVFace;
+    typedef MPNCFluxVariablesDiffusion<TypeTag, enableDiffusion> FluxVariablesDiffusion;
+    typedef MPNCFluxVariablesEnergy<TypeTag, enableEnergy, enableKineticEnergy> FluxVariablesEnergy;
+
+public:
+    /*
+     * \brief The constructor
+     *
+     * \param problem The problem
+     * \param element The finite element
+     * \param fvGeometry The finite-volume geometry in the box scheme
+     * \param faceIdx The local index of the SCV (sub-control-volume) face
+     * \param elemVolVars The volume variables of the current element
+     * \param onBoundary A boolean variable to specify whether the flux variables
+     * are calculated for interior SCV faces or boundary faces, default=false
+     */
+    MPNCFluxVariables(const Problem &problem,
+                      const Element &element,
+                      const FVElementGeometry &fvGeometry,
+                      const unsigned int faceIdx,
+                      const ElementVolumeVariables &elemVolVars,
+                      const bool onBoundary = false)
+        : BaseFluxVariables(problem, element, fvGeometry, faceIdx, elemVolVars, onBoundary),
+          fvGeometry_(fvGeometry), faceIdx_(faceIdx), elemVolVars_(elemVolVars), onBoundary_(onBoundary)
+    {
+        // velocities can be obtained from the Parent class.
+
+        // update the flux data of the energy module (i.e. isothermal
+        // or non-isothermal)
+        fluxVarsEnergy_.update(problem, element, fvGeometry, this->face(), *this, elemVolVars);
+
+        // update the flux data of the diffusion module (i.e. with or
+        // without diffusion)
+        fluxVarsDiffusion_.update(problem, element, fvGeometry, this->face(), elemVolVars);
+
+        extrusionFactor_ =
+            (elemVolVars[this->face().i].extrusionFactor()
+             + elemVolVars[this->face().j].extrusionFactor()) / 2;
+    }
+
+    /*!
+     * \brief Returns a reference to the volume
+     *        variables of the i-th sub-control volume of the current
+     *        element.
+     */
+    const VolumeVariables &volVars(const unsigned int idx) const
+    { return elemVolVars_[idx]; }
+
+    /*!
+     * \brief Returns th extrusion factor for the sub-control volume face
+     */
+    Scalar extrusionFactor() const
+    { return extrusionFactor_; }
+
+    ////////////////////////////////////////////////
+    // forward calls to the diffusion module
+    Scalar porousDiffCoeffL(const unsigned int compIdx) const
+    { return fluxVarsDiffusion_.porousDiffCoeffL(compIdx); }
+
+    Scalar porousDiffCoeffG(const unsigned int compIIdx,
+                            const unsigned int compJIdx) const
+    { return fluxVarsDiffusion_.porousDiffCoeffG(compIIdx, compJIdx); }
+
+    const Scalar moleFraction(const unsigned int phaseIdx,
+                              const unsigned int compIdx) const
+    { return fluxVarsDiffusion_.moleFraction(phaseIdx, compIdx); }
+
+    const DimVector &moleFractionGrad(const unsigned int phaseIdx,
+                                      const unsigned int compIdx) const
+    { return fluxVarsDiffusion_.moleFractionGrad(phaseIdx, compIdx); }
+
+    // end of forward calls to the diffusion module
+    ////////////////////////////////////////////////
+
+    ////////////////////////////////////////////////
+    // forward calls to the temperature module
+    const DimVector &temperatureGrad() const
+    { return fluxVarsEnergy_.temperatureGrad(); }
+
+    const FluxVariablesEnergy &fluxVarsEnergy() const
+    { return fluxVarsEnergy_; }
+    // end of forward calls to the temperature module
+    ////////////////////////////////////////////////
+
+private:
+    const FVElementGeometry &fvGeometry_;
+    const unsigned int faceIdx_;
+    const ElementVolumeVariables &elemVolVars_;
+    const bool onBoundary_;
+
+    // The extrusion factor for the sub-control volume face
+    Scalar extrusionFactor_;
+
+    FluxVariablesDiffusion  fluxVarsDiffusion_;
+    FluxVariablesEnergy     fluxVarsEnergy_;
+};
+
+} // end namepace
+
+#endif
diff --git a/dumux/implicit/mpnc/mpncindices.hh b/dumux/implicit/mpnc/mpncindices.hh
new file mode 100644
index 0000000000..eb1cc5b073
--- /dev/null
+++ b/dumux/implicit/mpnc/mpncindices.hh
@@ -0,0 +1,103 @@
+// -*- mode: C++; tab-width: 4; indent-tabs-mode: nil; c-basic-offset: 4 -*-
+// vi: set et ts=4 sw=4 sts=4:
+/*****************************************************************************
+ *   See the file COPYING for full copying permissions.                      *
+ *                                                                           *
+ *   This program is free software: you can redistribute it and/or modify    *
+ *   it under the terms of the GNU General Public License as published by    *
+ *   the Free Software Foundation, either version 2 of the License, or       *
+ *   (at your option) any later version.                                     *
+ *                                                                           *
+ *   This program is distributed in the hope that it will be useful,         *
+ *   but WITHOUT ANY WARRANTY; without even the implied warranty of          *
+ *   MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the            *
+ *   GNU General Public License for more details.                            *
+ *                                                                           *
+ *   You should have received a copy of the GNU General Public License       *
+ *   along with this program.  If not, see <http://www.gnu.org/licenses/>.   *
+ *****************************************************************************/
+#ifndef DUMUX_MPNC_INDICES_HH
+#define DUMUX_MPNC_INDICES_HH
+
+#include "mpncproperties.hh"
+
+#include "mass/mpncindicesmass.hh"
+#include "energy/mpncindicesenergy.hh"
+
+namespace Dumux
+{
+/*!
+ * \ingroup MPNCModel
+ * \ingroup BoxIndices
+ * \brief The primary variable and equation indices for the MpNc
+ *        model.
+ */
+template <class TypeTag, int BasePVOffset = 0>
+struct MPNCIndices :
+        public MPNCMassIndices<BasePVOffset,
+                               TypeTag,
+                               GET_PROP_VALUE(TypeTag, EnableKinetic) >,
+        public MPNCEnergyIndices<BasePVOffset +
+                                 MPNCMassIndices<0, TypeTag, GET_PROP_VALUE(TypeTag, EnableKinetic) >::NumPrimaryVars,
+                                 GET_PROP_VALUE(TypeTag, EnableEnergy),
+                                 GET_PROP_VALUE(TypeTag, EnableKineticEnergy)>
+{
+private:
+            typedef typename GET_PROP_TYPE(TypeTag, FluidSystem) FluidSystem;
+            enum { enableEnergy         = GET_PROP_VALUE(TypeTag, EnableEnergy) };
+            enum { enableKinetic        = GET_PROP_VALUE(TypeTag, EnableKinetic) }; //mass transfer
+            enum { enableKineticEnergy  = GET_PROP_VALUE(TypeTag, EnableKineticEnergy) }; // energy transfer
+            enum { numPhases = FluidSystem::numPhases };
+
+            typedef MPNCMassIndices<BasePVOffset, TypeTag, enableKinetic> MassIndices;
+            typedef MPNCEnergyIndices<BasePVOffset + MassIndices::NumPrimaryVars, enableEnergy, enableKineticEnergy> EnergyIndices;
+
+public:
+    /*!
+     * \brief The number of primary variables / equations.
+     */
+    // temperature + Mass Balance  + constraints for switch stuff
+    static const unsigned int NumPrimaryVars =
+        MassIndices::NumPrimaryVars +
+        EnergyIndices::NumPrimaryVars +
+        numPhases;
+
+    /*!
+     * \brief The number of primary variables / equations of the energy module.
+     */
+    static const unsigned int NumPrimaryEnergyVars =
+        EnergyIndices::NumPrimaryVars ;
+
+    /*!
+     * \brief Index of the saturation of the first phase in a vector
+     *        of primary variables.
+     *
+     * The following (numPhases - 1) primary variables represent the
+     * saturations for the phases [1, ..., numPhases - 1]
+     */
+    static const unsigned int S0Idx =
+        MassIndices::NumPrimaryVars +
+        EnergyIndices::NumPrimaryVars;
+
+    /*!
+     * \brief Index of the first phase' pressure in a vector of
+     *        primary variables.
+     */
+    static const unsigned int p0Idx =
+        MassIndices::NumPrimaryVars +
+        EnergyIndices::NumPrimaryVars +
+        numPhases - 1;
+
+    /*!
+     * \brief Index of the first phase NCP equation.
+     *
+     * The index for the remaining phases are consecutive.
+     */
+    static const unsigned int phase0NcpIdx =
+        MassIndices::NumPrimaryVars +
+        EnergyIndices::NumPrimaryVars;
+};
+
+}
+
+#endif
diff --git a/dumux/implicit/mpnc/mpnclocalresidual.hh b/dumux/implicit/mpnc/mpnclocalresidual.hh
new file mode 100644
index 0000000000..5513b44529
--- /dev/null
+++ b/dumux/implicit/mpnc/mpnclocalresidual.hh
@@ -0,0 +1,247 @@
+// -*- mode: C++; tab-width: 4; indent-tabs-mode: nil; c-basic-offset: 4 -*-
+// vi: set et ts=4 sw=4 sts=4:
+/*****************************************************************************
+ *   See the file COPYING for full copying permissions.                      *
+ *                                                                           *
+ *   This program is free software: you can redistribute it and/or modify    *
+ *   it under the terms of the GNU General Public License as published by    *
+ *   the Free Software Foundation, either version 2 of the License, or       *
+ *   (at your option) any later version.                                     *
+ *                                                                           *
+ *   This program is distributed in the hope that it will be useful,         *
+ *   but WITHOUT ANY WARRANTY; without even the implied warranty of          *
+ *   MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the            *
+ *   GNU General Public License for more details.                            *
+ *                                                                           *
+ *   You should have received a copy of the GNU General Public License       *
+ *   along with this program.  If not, see <http://www.gnu.org/licenses/>.   *
+ *****************************************************************************/
+#ifndef DUMUX_MPNC_LOCAL_RESIDUAL_HH
+#define DUMUX_MPNC_LOCAL_RESIDUAL_HH
+
+#include "mpncfluxvariables.hh"
+#include "diffusion/diffusion.hh"
+#include "energy/mpnclocalresidualenergy.hh"
+#include "mass/mpnclocalresidualmass.hh"
+
+#include <dumux/boxmodels/common/boxmodel.hh>
+#include <dumux/common/math.hh>
+
+namespace Dumux
+{
+/*!
+ * \ingroup MPNCModel
+ * \ingroup BoxLocalResidual
+ * \brief two-phase, N-component specific details needed to
+ *        approximately calculate the local defect in the BOX scheme.
+ *
+ * This class is used to fill the gaps in BoxLocalResidual for the
+ * two-phase, N-component twophase flow.
+ */
+template<class TypeTag>
+class MPNCLocalResidual : public GET_PROP_TYPE(TypeTag, BaseLocalResidual)
+{
+    typedef typename GET_PROP_TYPE(TypeTag, Indices) Indices;
+
+protected:
+    typedef typename GET_PROP_TYPE(TypeTag, LocalResidual) Implementation;
+    typedef typename GET_PROP_TYPE(TypeTag, BaseLocalResidual) ParentType;
+    typedef typename GET_PROP_TYPE(TypeTag, GridView) GridView;
+
+    enum {numPhases = GET_PROP_VALUE(TypeTag, NumPhases)};
+    enum {enableEnergy = GET_PROP_VALUE(TypeTag, EnableEnergy)};
+    enum {enableKineticEnergy = GET_PROP_VALUE(TypeTag, EnableKineticEnergy)};
+    enum {enableKinetic = GET_PROP_VALUE(TypeTag, EnableKinetic)};
+    enum {phase0NcpIdx = Indices::phase0NcpIdx};
+
+    typedef typename GridView::template Codim<0>::Entity Element;
+    typedef typename GET_PROP_TYPE(TypeTag, FVElementGeometry) FVElementGeometry;
+    typedef typename GET_PROP_TYPE(TypeTag, PrimaryVariables) PrimaryVariables;
+    typedef typename GET_PROP_TYPE(TypeTag, VolumeVariables) VolumeVariables;
+    typedef typename GET_PROP_TYPE(TypeTag, FluxVariables) FluxVariables;
+    typedef typename GET_PROP_TYPE(TypeTag, ElementVolumeVariables) ElementVolumeVariables;
+    typedef typename GET_PROP_TYPE(TypeTag, ElementBoundaryTypes) ElementBoundaryTypes;
+
+    typedef MPNCLocalResidualEnergy<TypeTag, enableEnergy, enableKineticEnergy> EnergyResid;
+    typedef MPNCLocalResidualMass<TypeTag, enableKinetic> MassResid;
+
+public:
+    /*!
+     * \brief Evaluate the amount all conservation quantites
+     *        (e.g. phase mass) within a sub-control volume.
+     *
+     * The result should be averaged over the volume (e.g. phase mass
+     * inside a sub control volume divided by the volume)
+     */
+    void computeStorage(PrimaryVariables &storage,
+                        const unsigned int scvIdx,
+                        const bool usePrevSol) const
+    {
+        // if flag usePrevSol is set, the solution from the previous
+        // time step is used, otherwise the current solution is
+        // used. The secondary variables are used accordingly.  This
+        // is required to compute the derivative of the storage term
+        // using the implicit euler method.
+        const ElementVolumeVariables &elemVolVars = usePrevSol ? this->prevVolVars_() : this->curVolVars_();
+        const VolumeVariables &volVars = elemVolVars[scvIdx];
+
+        storage =0;
+
+        // compute mass and energy storage terms
+        MassResid::computeStorage(storage, volVars);
+        Valgrind::CheckDefined(storage);
+        EnergyResid::computeStorage(storage, volVars);
+        Valgrind::CheckDefined(storage);
+    }
+
+    /*!
+     * \brief Evaluate the amount all conservation quantities
+     *        (e.g. phase mass) within all sub-control volumes of an
+     *        element.
+     */
+    void addPhaseStorage(PrimaryVariables &phaseStorage,
+                         const Element &element,
+                         const unsigned int phaseIdx) const
+    {
+        // create a finite volume element geometry
+        FVElementGeometry fvGeometry;
+        fvGeometry.update(this->gridView_(), element);
+
+        // calculate volume variables
+        ElementVolumeVariables elemVolVars;
+        this->model_().setHints(element, elemVolVars);
+        elemVolVars.update(this->problem_(),
+                           element,
+                           fvGeometry,
+                           /*useOldSolution=*/false);
+
+        // calculate the phase storage for all sub-control volumes
+        for (int scvIdx=0;
+             scvIdx < fvGeometry.numSCV;
+             scvIdx++)
+        {
+            PrimaryVariables tmpPriVars(0.0);
+
+            // compute mass and energy storage terms in terms of
+            // averaged quantities
+            MassResid::addPhaseStorage(tmpPriVars,
+                                       elemVolVars[scvIdx],
+                                       phaseIdx);
+            EnergyResid::addPhaseStorage(tmpPriVars,
+                                         elemVolVars[scvIdx],
+                                         phaseIdx);
+
+            // multiply with volume of sub-control volume
+            tmpPriVars *= fvGeometry.subContVol[scvIdx].volume;
+
+            // Add the storage of the current SCV to the total storage
+            phaseStorage += tmpPriVars;
+        }
+    }
+
+    /*!
+     * \brief Calculate the source term of the equation
+     */
+    void computeSource(PrimaryVariables &source,
+                       const unsigned int scvIdx)
+     {
+        Valgrind::SetUndefined(source);
+        this->problem_().boxSDSource(source,
+                                     this->element_(),
+                                     this->fvGeometry_(),
+                                     scvIdx,
+                                     this->curVolVars_() );
+        const VolumeVariables &volVars = this->curVolVars_(scvIdx);
+
+        PrimaryVariables tmp(0);
+        MassResid::computeSource(tmp, volVars);
+        source += tmp;
+        Valgrind::CheckDefined(source);
+
+        /*
+         *      EnergyResid also called in the MassResid
+         *      1) Makes some sense because energy is also carried by mass
+         *      2) The mass transfer between the phases is needed.
+         */
+//        tmp = 0.;
+//        EnergyResid::computeSource(tmp, volVars);
+//        source += tmp;
+//        Valgrind::CheckDefined(source);
+     };
+
+
+    /*!
+     * \brief Evaluates the total flux of all conservation quantities
+     *        over a face of a subcontrol volume.
+     *
+     * \param flux The flux over the SCV (sub-control-volume) face for each component
+     * \param faceIdx The index of the SCV face
+     * \param onBoundary A boolean variable to specify whether the flux variables
+     *        are calculated for interior SCV faces or boundary faces, default=false
+     */
+    void computeFlux(PrimaryVariables &flux,
+                     const unsigned int faceIdx, const bool onBoundary=false) const
+    {
+        FluxVariables fluxVars(this->problem_(),
+                               this->element_(),
+                               this->fvGeometry_(),
+                               faceIdx,
+                               this->curVolVars_(),
+                               onBoundary);
+
+        flux = 0.0;
+        MassResid::computeFlux(flux, fluxVars, this->curVolVars_() );
+        Valgrind::CheckDefined(flux);
+/*
+ *      EnergyResid also called in the MassResid
+ *      1) Makes some sense because energy is also carried by mass
+ *      2) The component-wise mass flux in each phase is needed.
+ */
+    }
+
+    /*!
+     * \brief Compute the local residual, i.e. the deviation of the
+     *        equations from zero.
+     */
+    void eval(const Element &element)
+    { ParentType::eval(element); }
+
+    /*!
+     * \brief Evaluate the local residual.
+     */
+    void eval(const Element &element,
+              const FVElementGeometry &fvGeometry,
+              const ElementVolumeVariables &prevVolVars,
+              const ElementVolumeVariables &curVolVars,
+              const ElementBoundaryTypes &bcType)
+    {
+        ParentType::eval(element,
+                         fvGeometry,
+                         prevVolVars,
+                         curVolVars,
+                         bcType);
+
+        for (int i = 0; i < this->fvGeometry_().numSCV; ++i) {
+            // add the two auxiliary equations, make sure that the
+            // dirichlet boundary condition is conserved
+            for (int phaseIdx = 0; phaseIdx < numPhases; ++phaseIdx)
+            {
+                if (!bcType[i].isDirichlet(phase0NcpIdx + phaseIdx))
+                {
+                    this->residual_[i][phase0NcpIdx + phaseIdx] =
+                        this->curVolVars_(i).phaseNcp(phaseIdx);
+                }
+            }
+        }
+    }
+
+protected:
+    Implementation &asImp_()
+    { return *static_cast<Implementation *>(this); }
+    const Implementation &asImp_() const
+    { return *static_cast<const Implementation *>(this); }
+};
+
+} // end namepace
+
+#endif
diff --git a/dumux/implicit/mpnc/mpncmodel.hh b/dumux/implicit/mpnc/mpncmodel.hh
new file mode 100644
index 0000000000..8d783cca51
--- /dev/null
+++ b/dumux/implicit/mpnc/mpncmodel.hh
@@ -0,0 +1,188 @@
+// -*- mode: C++; tab-width: 4; indent-tabs-mode: nil; c-basic-offset: 4 -*-
+// vi: set et ts=4 sw=4 sts=4:
+/*****************************************************************************
+ *   See the file COPYING for full copying permissions.                      *
+ *                                                                           *
+ *   This program is free software: you can redistribute it and/or modify    *
+ *   it under the terms of the GNU General Public License as published by    *
+ *   the Free Software Foundation, either version 2 of the License, or       *
+ *   (at your option) any later version.                                     *
+ *                                                                           *
+ *   This program is distributed in the hope that it will be useful,         *
+ *   but WITHOUT ANY WARRANTY; without even the implied warranty of          *
+ *   MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the            *
+ *   GNU General Public License for more details.                            *
+ *                                                                           *
+ *   You should have received a copy of the GNU General Public License       *
+ *   along with this program.  If not, see <http://www.gnu.org/licenses/>.   *
+ *****************************************************************************/
+#ifndef DUMUX_MPNC_MODEL_HH
+#define DUMUX_MPNC_MODEL_HH
+
+#include "mpncproperties.hh"
+#include "mpncvtkwriter.hh"
+
+#include <dumux/boxmodels/common/boxmodel.hh>
+
+namespace Dumux
+{
+/*!
+ * \ingroup MPNCModel
+ * \brief A fully implicit model for M-phase, N-component flow using
+ *        vertex centered finite volumes.
+ *
+ * This model implements a \f$M\f$-phase flow of a fluid mixture
+ * composed of \f$N\f$ chemical species. The phases are denoted by
+ * lower index \f$\alpha \in \{ 1, \dots, M \}\f$. All fluid phases
+ * are mixtures of \f$N \geq M - 1\f$ chemical species which are
+ * denoted by the upper index \f$\kappa \in \{ 1, \dots, N \} \f$.
+ *
+ * The momentum approximation can be selected via "BaseFluxVariables":
+ * Darcy (BoxDarcyFluxVariables) and Forchheimer (BoxForchheimerFluxVariables)
+ * relations are available for all Box models.
+ *
+ * By inserting this into the equations for the conservation of the
+ * mass of each component, one gets one mass-continuity equation for
+ * each component \f$\kappa\f$
+ * \f[
+ \sum_{\kappa} \left(
+    \phi \frac{\partial \left(\varrho_\alpha x_\alpha^\kappa S_\alpha\right)}{\partial t}
+    +
+    \mathrm{div}\;
+    \left\{
+        v_\alpha
+       \frac{\varrho_\alpha}{\overline M_\alpha} x_\alpha^\kappa
+    \right\}
+    \right)
+    = q^\kappa
+    \f]
+ * with \f$\overline M_\alpha\f$ being the average molar mass of the
+ * phase \f$\alpha\f$: \f[ \overline M_\alpha = \sum_\kappa M^\kappa
+ * \; x_\alpha^\kappa \f]
+ *
+ * For the missing \f$M\f$ model assumptions, the model assumes that
+ * if a fluid phase is not present, the sum of the mole fractions of
+ * this fluid phase is smaller than \f$1\f$, i.e.  
+ * \f[
+ * \forall \alpha: S_\alpha = 0 \implies \sum_\kappa x_\alpha^\kappa \leq 1
+ * \f]
+ *
+ * Also, if a fluid phase may be present at a given spatial location
+ * its saturation must be positive:
+ * \f[ \forall \alpha: \sum_\kappa x_\alpha^\kappa = 1 \implies S_\alpha \geq 0 \f]
+ *
+ * Since at any given spatial location, a phase is always either
+ * present or not present, one of the strict equalities on the
+ * right hand side is always true, i.e.
+ * \f[ \forall \alpha: S_\alpha \left( \sum_\kappa x_\alpha^\kappa - 1 \right) = 0 \f]
+ * always holds.
+ *
+ * These three equations constitute a non-linear complementarity
+ * problem, which can be solved using so-called non-linear
+ * complementarity functions \f$\Phi(a, b)\f$ which have the property
+ * \f[\Phi(a,b) = 0 \iff a \geq0 \land b \geq0  \land a \cdot b = 0 \f]
+ *
+ * Several non-linear complementarity functions have been suggested,
+ * e.g. the Fischer-Burmeister function
+ * \f[ \Phi(a,b) = a + b - \sqrt{a^2 + b^2} \;. \f]
+ * This model uses
+ * \f[ \Phi(a,b) = \min \{a,  b \}\;, \f]
+ * because of its piecewise linearity.
+ *
+ * These equations are then discretized using a fully-implicit vertex
+ * centered finite volume scheme (often known as 'box'-scheme) for
+ * spatial discretization and the implicit Euler method as temporal
+ * discretization.
+ *
+ * The model assumes local thermodynamic equilibrium and uses the
+ * following primary variables:
+ * - The component fugacities \f$f^1, \dots, f^{N}\f$
+ * - The pressure of the first phase \f$p_1\f$
+ * - The saturations of the first \f$M-1\f$ phases \f$S_1, \dots, S_{M-1}\f$
+ * - Temperature \f$T\f$ if the energy equation is enabled
+ */
+template<class TypeTag>
+class MPNCModel : public GET_PROP_TYPE(TypeTag, BaseModel)
+{
+    typedef typename GET_PROP_TYPE(TypeTag, BaseModel) ParentType;
+    typedef typename GET_PROP_TYPE(TypeTag, Problem) Problem;
+    typedef typename GET_PROP_TYPE(TypeTag, GridView) GridView;
+    typedef typename GridView::template Codim<0>::Entity Element;
+    typedef typename GridView::template Codim<0>::Iterator ElementIterator;
+    typedef typename GET_PROP_TYPE(TypeTag, PrimaryVariables) PrimaryVariables;
+    typedef typename GET_PROP_TYPE(TypeTag, SolutionVector) SolutionVector;
+    typedef Dumux::MPNCVtkWriter<TypeTag> MPNCVtkWriter;
+
+    enum {enableEnergy = GET_PROP_VALUE(TypeTag, EnableEnergy)};
+    enum {enableDiffusion = GET_PROP_VALUE(TypeTag, EnableDiffusion)};
+    enum {enableKinetic = GET_PROP_VALUE(TypeTag, EnableKinetic)};
+    enum {enableKineticEnergy = GET_PROP_VALUE(TypeTag, EnableKineticEnergy)};
+    enum {enableSmoothUpwinding = GET_PROP_VALUE(TypeTag, ImplicitEnableSmoothUpwinding)};
+    enum {enablePartialReassemble = GET_PROP_VALUE(TypeTag, ImplicitEnablePartialReassemble)};
+    enum {enableJacobianRecycling = GET_PROP_VALUE(TypeTag, ImplicitEnableJacobianRecycling)};
+    enum {numDiffMethod = GET_PROP_VALUE(TypeTag, ImplicitNumericDifferenceMethod)};
+    enum {numPhases = GET_PROP_VALUE(TypeTag, NumPhases)};
+    enum {numComponents = GET_PROP_VALUE(TypeTag, NumComponents)};
+    enum {numEq = GET_PROP_VALUE(TypeTag, NumEq)};
+
+public:
+    ~MPNCModel()
+    { delete vtkWriter_; };
+
+    void init(Problem &problem)
+    {
+        ParentType::init(problem);
+        vtkWriter_ = new MPNCVtkWriter(problem);
+
+        if (this->gridView_().comm().rank() == 0)
+            std::cout
+                << "Initializing M-phase N-component model: \n"
+                << "    phases: " << numPhases << "\n"
+                << "    components: " << numComponents << "\n"
+                << "    equations: " << numEq << "\n"
+                << "    kinetic mass transfer: " << enableKinetic<< "\n"
+                << "    kinetic energy transfer: " << enableKineticEnergy<< "\n"
+                << "    diffusion: " << enableDiffusion << "\n"
+                << "    energy equation: " << enableEnergy << "\n"
+                << "    smooth upwinding: " << enableSmoothUpwinding << "\n"
+                << "    partial jacobian reassembly: " << enablePartialReassemble << "\n"
+                << "    numeric differentiation method: " << numDiffMethod << " (-1: backward, 0: central, +1 forward)\n"
+                << "    jacobian recycling: " << enableJacobianRecycling << "\n";
+    }
+
+    /*!
+     * \brief Compute the total storage inside one phase of all
+     *        conservation quantities.
+     */
+    void globalPhaseStorage(PrimaryVariables &phaseStorage, const unsigned int phaseIdx)
+    {
+        phaseStorage = 0;
+
+        ElementIterator elemIt = this->gridView_().template begin<0>();
+        const ElementIterator elemEndIt = this->gridView_().template end<0>();
+        for (; elemIt != elemEndIt; ++elemIt) {
+            this->localResidual().addPhaseStorage(phaseStorage, *elemIt, phaseIdx);
+        }
+
+        if (this->gridView_().comm().size() > 1)
+            phaseStorage = this->gridView_().comm().sum(phaseStorage);
+    }
+
+    /*!
+     * \brief Add the result of the current timestep to the VTK output.
+     */
+    template <class MultiWriter>
+    void addOutputVtkFields(const SolutionVector &sol,
+                            MultiWriter &writer)
+    {
+        vtkWriter_->addCurrentSolution(writer);
+    }
+
+    MPNCVtkWriter *vtkWriter_;
+};
+
+}
+
+#include "mpncpropertydefaults.hh"
+
+#endif
diff --git a/dumux/implicit/mpnc/mpncnewtoncontroller.hh b/dumux/implicit/mpnc/mpncnewtoncontroller.hh
new file mode 100644
index 0000000000..005def2ce2
--- /dev/null
+++ b/dumux/implicit/mpnc/mpncnewtoncontroller.hh
@@ -0,0 +1,266 @@
+// -*- mode: C++; tab-width: 4; indent-tabs-mode: nil; c-basic-offset: 4 -*-
+// vi: set et ts=4 sw=4 sts=4:
+/*****************************************************************************
+ *   See the file COPYING for full copying permissions.                      *
+ *                                                                           *
+ *   This program is free software: you can redistribute it and/or modify    *
+ *   it under the terms of the GNU General Public License as published by    *
+ *   the Free Software Foundation, either version 2 of the License, or       *
+ *   (at your option) any later version.                                     *
+ *                                                                           *
+ *   This program is distributed in the hope that it will be useful,         *
+ *   but WITHOUT ANY WARRANTY; without even the implied warranty of          *
+ *   MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the            *
+ *   GNU General Public License for more details.                            *
+ *                                                                           *
+ *   You should have received a copy of the GNU General Public License       *
+ *   along with this program.  If not, see <http://www.gnu.org/licenses/>.   *
+ *****************************************************************************/
+/*!
+ * \file
+ * \brief A MpNc specific controller for the newton solver.
+ *
+ * This controller 'knows' what a 'physically meaningful' solution is
+ * which allows the newton method to abort quicker if the solution is
+ * way out of bounds.
+ */
+#ifndef DUMUX_MPNC_NEWTON_CONTROLLER_HH
+#define DUMUX_MPNC_NEWTON_CONTROLLER_HH
+
+#include "mpncproperties.hh"
+
+#include <dumux/nonlinear/newtoncontroller.hh>
+#include <algorithm>
+
+namespace Dumux {
+
+template <class TypeTag, bool enableKinetic /* = false */>
+class MpNcNewtonChop
+{
+    typedef typename GET_PROP_TYPE(TypeTag, Indices) Indices;
+    typedef typename GET_PROP_TYPE(TypeTag, Scalar) Scalar;
+    typedef typename GET_PROP_TYPE(TypeTag, SolutionVector) SolutionVector;
+
+    enum { numPhases =  GET_PROP_VALUE(TypeTag, NumPhases) };
+    enum { numComponents =  GET_PROP_VALUE(TypeTag, NumComponents) };
+    enum { fug0Idx = Indices::fug0Idx };
+    enum { S0Idx = Indices::S0Idx };
+    enum { p0Idx = Indices::p0Idx };
+
+public:
+    static void chop(SolutionVector &uCurrentIter,
+                     const SolutionVector &uLastIter)
+    {
+        for (unsigned int i = 0; i < uLastIter.size(); ++i) {
+            for (unsigned int phaseIdx = 0; phaseIdx < numPhases - 1; ++phaseIdx)
+                saturationChop_(uCurrentIter[i][S0Idx + phaseIdx],
+                                uLastIter[i][S0Idx + phaseIdx]);
+            pressureChop_(uCurrentIter[i][p0Idx], uLastIter[i][p0Idx]);
+            for (unsigned int comp = 0; comp < numComponents; ++comp) {
+                pressureChop_(uCurrentIter[i][fug0Idx + comp], uLastIter[i][fug0Idx + comp]);
+            }
+
+        }
+    };
+
+private:
+    static void clampValue_(Scalar &val,
+                            const Scalar minVal,
+                            const Scalar maxVal)
+    {
+        val = std::max(minVal, std::min(val, maxVal));
+    };
+
+    static void pressureChop_(Scalar &val,
+                              const Scalar oldVal)
+    {
+        const Scalar maxDelta = std::max(oldVal/4.0, 10e3);
+        clampValue_(val, oldVal - maxDelta, oldVal + maxDelta);
+        val = std::max(0.0, val); // don't allow negative pressures
+    }
+
+    static void saturationChop_(Scalar &val,
+                                const Scalar oldVal)
+    {
+        const Scalar maxDelta = 0.25;
+        clampValue_(val, oldVal - maxDelta, oldVal + maxDelta);
+        clampValue_(val, -0.001, 1.001);
+    }
+
+};
+
+template <class TypeTag>
+class MpNcNewtonChop<TypeTag, /*enableKinetic=*/true>
+{
+    typedef typename GET_PROP_TYPE(TypeTag, Indices) Indices;
+    typedef typename GET_PROP_TYPE(TypeTag, Scalar) Scalar;
+    typedef typename GET_PROP_TYPE(TypeTag, SolutionVector) SolutionVector;
+
+    enum { numPhases =  GET_PROP_VALUE(TypeTag, NumPhases) };
+    enum { numComponents =  GET_PROP_VALUE(TypeTag, NumComponents) };
+    enum { moleFrac00Idx = Indices::moleFrac00Idx };
+    enum { S0Idx = Indices::S0Idx };
+    enum { p0Idx = Indices::p0Idx };
+
+public:
+    static void chop(SolutionVector &uCurrentIter,
+                     const SolutionVector &uLastIter)
+    {
+        for (int i = 0; i < uLastIter.size(); ++i) {
+            for (int phaseIdx = 0; phaseIdx < numPhases - 1; ++phaseIdx)
+                saturationChop_(uCurrentIter[i][S0Idx + phaseIdx],
+                                uLastIter[i][S0Idx + phaseIdx]);
+            pressureChop_(uCurrentIter[i][p0Idx], uLastIter[i][p0Idx]);
+            for (int phaseIdx = 0; phaseIdx < numPhases; ++phaseIdx) {
+                for (int compIdx = 0; compIdx < numComponents; ++compIdx) {
+                    moleFracChop_(uCurrentIter[i][moleFrac00Idx + phaseIdx*numComponents + compIdx],
+                                  uLastIter[i][moleFrac00Idx + phaseIdx*numComponents + compIdx]);
+                }
+            }
+
+        }
+    }
+
+private:
+    static void clampValue_(Scalar &val,
+                            const Scalar minVal,
+                            const Scalar maxVal)
+    {
+        val = std::max(minVal, std::min(val, maxVal));
+    };
+
+    static void pressureChop_(Scalar &val,
+                              const Scalar oldVal)
+    {
+        const Scalar maxDelta = std::max(oldVal/4.0, 10e3);
+        clampValue_(val, oldVal - maxDelta, oldVal + maxDelta);
+        val = std::max(0.0, val); // don't allow negative pressures
+    }
+
+    static void saturationChop_(Scalar &val,
+                                const Scalar oldVal)
+    {
+        const Scalar maxDelta = 0.25;
+        clampValue_(val, oldVal - maxDelta, oldVal + maxDelta);
+        clampValue_(val, -0.001, 1.001);
+    }
+
+    static void moleFracChop_(Scalar &val,
+                              const Scalar oldVal)
+    {
+        // no component mole fraction can change by more than 20% per iteration
+        const Scalar maxDelta = 0.20;
+        clampValue_(val, oldVal - maxDelta, oldVal + maxDelta);
+        clampValue_(val, -0.001, 1.001);
+    }
+
+};
+
+/*!
+ * \ingroup Newton
+ * \brief A MpNc specific controller for the newton solver.
+ *
+ * This controller 'knows' what a 'physically meaningful' solution is
+ * which allows the newton method to abort quicker if the solution is
+ * way out of bounds.
+ */
+template <class TypeTag>
+class MPNCNewtonController : public NewtonController<TypeTag>
+{
+    typedef NewtonController<TypeTag> ParentType;
+    typedef typename GET_PROP_TYPE(TypeTag, SolutionVector) SolutionVector;
+    typedef typename GET_PROP_TYPE(TypeTag, Scalar) Scalar;
+    typedef typename GET_PROP_TYPE(TypeTag, Indices) Indices;
+    typedef typename GET_PROP_TYPE(TypeTag, Problem) Problem;
+
+    enum {numPhases = GET_PROP_VALUE(TypeTag, NumPhases)};
+    enum {    numComponents = GET_PROP_VALUE(TypeTag, NumComponents)};
+    enum {enableKinetic = GET_PROP_VALUE(TypeTag, EnableKinetic)};
+    enum {p0Idx = Indices::p0Idx};
+    enum {S0Idx = Indices::S0Idx};
+
+    typedef MpNcNewtonChop<TypeTag, enableKinetic> NewtonChop;
+
+public:
+    MPNCNewtonController(const Problem &problem)
+        : ParentType(problem)
+    {
+        enableChop_ = GET_PARAM_FROM_GROUP(TypeTag, bool, Newton, EnableChop);
+        Dune::FMatrixPrecision<>::set_singular_limit(1e-35);
+    };
+
+    void newtonUpdate(SolutionVector &uCurrentIter,
+                      const SolutionVector &uLastIter,
+                      const SolutionVector &deltaU)
+    {
+        if (this->enableRelativeCriterion_ || this->enablePartialReassemble_)
+            this->newtonUpdateRelError(uLastIter, deltaU);
+
+        // compute the vertex and element colors for partial
+        // reassembly
+        if (this->enablePartialReassemble_) {
+            const Scalar minReasmTol = 1e-2*this->tolerance_;
+            const Scalar maxReasmTol = 1e1*this->tolerance_;
+            Scalar reassembleTol = std::max(minReasmTol, std::min(maxReasmTol, this->error_/1e4));
+
+            this->model_().jacobianAssembler().updateDiscrepancy(uLastIter, deltaU);
+            this->model_().jacobianAssembler().computeColors(reassembleTol);
+        }
+
+        this->writeConvergence_(uLastIter, deltaU);
+
+        if (GET_PARAM_FROM_GROUP(TypeTag, bool, Newton, UseLineSearch)) {
+            lineSearchUpdate_(uCurrentIter, uLastIter, deltaU);
+        }
+        else {
+            for (unsigned int i = 0; i < uLastIter.size(); ++i) {
+                uCurrentIter[i] = uLastIter[i];
+                uCurrentIter[i] -= deltaU[i];
+            }
+
+            if (this->numSteps_ < 2 && enableChop_) {
+                // put crash barriers along the update path at the
+                // beginning...
+                NewtonChop::chop(uCurrentIter, uLastIter);
+            }
+
+            if (this->enableAbsoluteCriterion_)
+            {
+                SolutionVector tmp(uLastIter);
+                this->absoluteError_ = this->method().model().globalResidual(tmp, uCurrentIter);
+                this->absoluteError_ /= this->initialAbsoluteError_;
+            }
+        }
+    }
+
+private:
+    void lineSearchUpdate_(SolutionVector &uCurrentIter,
+                           const SolutionVector &uLastIter,
+                           const SolutionVector &deltaU)
+    {
+       Scalar lambda = 1.0;
+       Scalar globDef;
+
+       SolutionVector tmp(uLastIter);
+       Scalar oldGlobDef = this->model_().globalResidual(tmp, uLastIter);
+       while (true) {
+           uCurrentIter  = deltaU;
+           uCurrentIter *= -lambda;
+           uCurrentIter += uLastIter;
+
+           globDef = this->model_().globalResidual(tmp, uCurrentIter);
+           if (globDef < oldGlobDef || lambda <= 1.0/64) {
+               this->endIterMsg() << ", defect " << oldGlobDef << "->"  << globDef << "@lambda=1/" << 1/lambda;
+               return;
+           }
+
+           // try with a smaller update
+           lambda /= 2;
+       }
+    }
+
+    bool enableChop_;
+};
+}
+
+#endif
diff --git a/dumux/implicit/mpnc/mpncproperties.hh b/dumux/implicit/mpnc/mpncproperties.hh
new file mode 100644
index 0000000000..a8833bb7cd
--- /dev/null
+++ b/dumux/implicit/mpnc/mpncproperties.hh
@@ -0,0 +1,133 @@
+// -*- mode: C++; tab-width: 4; indent-tabs-mode: nil; c-basic-offset: 4 -*-
+// vi: set et ts=4 sw=4 sts=4:
+/*****************************************************************************
+ *   See the file COPYING for full copying permissions.                      *
+ *                                                                           *
+ *   This program is free software: you can redistribute it and/or modify    *
+ *   it under the terms of the GNU General Public License as published by    *
+ *   the Free Software Foundation, either version 2 of the License, or       *
+ *   (at your option) any later version.                                     *
+ *                                                                           *
+ *   This program is distributed in the hope that it will be useful,         *
+ *   but WITHOUT ANY WARRANTY; without even the implied warranty of          *
+ *   MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the            *
+ *   GNU General Public License for more details.                            *
+ *                                                                           *
+ *   You should have received a copy of the GNU General Public License       *
+ *   along with this program.  If not, see <http://www.gnu.org/licenses/>.   *
+ *****************************************************************************/
+#ifndef DUMUX_MPNC_PROPERTIES_HH
+#define DUMUX_MPNC_PROPERTIES_HH
+
+#include <dumux/boxmodels/common/boxproperties.hh>
+
+/*!
+ * \ingroup Properties
+ * \ingroup BoxProperties
+ * \ingroup BoxMpNcModel
+ * \file
+ * \brief  Defines the properties required for the Mp-Nc box model.
+ */
+namespace Dumux
+{
+namespace Properties
+{
+
+//////////////////////////////////////////////////////////////////
+// Type tags
+//////////////////////////////////////////////////////////////////
+
+/*!
+ * \brief Define the type tag for the compositional twophase box model.
+ */
+NEW_TYPE_TAG(BoxMPNC, INHERITS_FROM(BoxModel));
+
+//////////////////////////////////////////////////////////////////
+// Property tags
+//////////////////////////////////////////////////////////////////
+NEW_PROP_TAG(NumPhases);   //!< Number of fluid phases in the system
+NEW_PROP_TAG(NumComponents); //!< Number of fluid components in the system
+NEW_PROP_TAG(Indices); //!< Enumerations for the model
+
+NEW_PROP_TAG(BaseFluxVariables); //!< The type of velocity calculation that is to be used
+
+NEW_PROP_TAG(MPNCVtkCommonModule); //!< Vtk writer module for writing the common quantities into the VTK output file
+NEW_PROP_TAG(MPNCVtkMassModule); //!< Vtk writer module for writing the mass related quantities into the VTK output file
+NEW_PROP_TAG(MPNCVtkEnergyModule); //!< Vtk writer module for writing the energy related quantities into the VTK output file
+NEW_PROP_TAG(MPNCVtkCustomModule); //!< Vtk writer module for writing the user-specified quantities into the VTK output file
+
+NEW_PROP_TAG(VelocityAveragingInModel);//!< Should the averaging of velocities be done in the model?
+
+//! specify which quantities are written to the vtk output files
+NEW_PROP_TAG(VtkAddPorosity);
+NEW_PROP_TAG(VtkAddBoundaryTypes);
+NEW_PROP_TAG(VtkAddSaturations);
+NEW_PROP_TAG(VtkAddPressures);
+NEW_PROP_TAG(VtkAddVarPressures);
+NEW_PROP_TAG(VtkAddVelocities);
+NEW_PROP_TAG(VtkAddDensities);
+NEW_PROP_TAG(VtkAddMobilities);
+NEW_PROP_TAG(VtkAddAverageMolarMass);
+NEW_PROP_TAG(VtkAddMassFractions);
+NEW_PROP_TAG(VtkAddMoleFractions);
+NEW_PROP_TAG(VtkAddMolarities);
+NEW_PROP_TAG(VtkAddFugacities);
+NEW_PROP_TAG(VtkAddFugacityCoefficients);
+NEW_PROP_TAG(VtkAddTemperatures);
+NEW_PROP_TAG(VtkAddEnthalpies);
+NEW_PROP_TAG(VtkAddInternalEnergies);
+
+NEW_PROP_TAG(VtkAddxEquil);
+
+NEW_PROP_TAG(VtkAddReynolds);
+NEW_PROP_TAG(VtkAddPrandtl);
+NEW_PROP_TAG(VtkAddNusselt);
+NEW_PROP_TAG(VtkAddInterfacialArea);
+
+NEW_PROP_TAG(SpatialParams); //!< The type of the spatial parameters
+
+NEW_PROP_TAG(MaterialLaw);   //!< The material law which ought to be used (extracted from the soil)
+NEW_PROP_TAG(MaterialLawParams); //!< The context material law (extracted from the soil)
+
+//! The compositional twophase system of fluids which is considered
+NEW_PROP_TAG(FluidSystem);
+
+//! The thermodynamic constraint solver which calculates the
+//! composition of any phase given all component fugacities.
+NEW_PROP_TAG(CompositionFromFugacitiesSolver);
+NEW_PROP_TAG(ConstraintSolver);
+
+//! Enable the energy equation?
+NEW_PROP_TAG(EnableEnergy);
+
+//! Enable diffusive fluxes?
+NEW_PROP_TAG(EnableDiffusion);
+
+//! Enable kinetic resolution of mass transfer processes?
+NEW_PROP_TAG(EnableKinetic);
+
+//! Enable kinetic resolution of energy transfer processes?
+NEW_PROP_TAG(EnableKineticEnergy);
+
+//! Enable gravity?
+NEW_PROP_TAG(ProblemEnableGravity);
+
+//! Use the smooth upwinding method?
+NEW_PROP_TAG(ImplicitEnableSmoothUpwinding);
+
+NEW_PROP_TAG(ImplicitMassUpwindWeight); //!< The value of the weight of the upwind direction in the mass conservation equations
+
+NEW_PROP_TAG(ImplicitMobilityUpwindWeight); //!< Weight for the upwind mobility in the velocity calculation
+
+//! Chop the Newton update at the beginning of the non-linear solver?
+NEW_PROP_TAG(NewtonEnableChop);
+
+//! Which type of fluidstate should be used?
+NEW_PROP_TAG(FluidState);
+
+//! Property for the forchheimer coefficient
+NEW_PROP_TAG(SpatialParamsForchCoeff);
+}
+}
+
+#endif
diff --git a/dumux/implicit/mpnc/mpncpropertydefaults.hh b/dumux/implicit/mpnc/mpncpropertydefaults.hh
new file mode 100644
index 0000000000..0ead27ef49
--- /dev/null
+++ b/dumux/implicit/mpnc/mpncpropertydefaults.hh
@@ -0,0 +1,279 @@
+// -*- mode: C++; tab-width: 4; indent-tabs-mode: nil; c-basic-offset: 4 -*-
+// vi: set et ts=4 sw=4 sts=4:
+/*****************************************************************************
+ *   See the file COPYING for full copying permissions.                      *
+ *                                                                           *
+ *   This program is free software: you can redistribute it and/or modify    *
+ *   it under the terms of the GNU General Public License as published by    *
+ *   the Free Software Foundation, either version 2 of the License, or       *
+ *   (at your option) any later version.                                     *
+ *                                                                           *
+ *   This program is distributed in the hope that it will be useful,         *
+ *   but WITHOUT ANY WARRANTY; without even the implied warranty of          *
+ *   MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the            *
+ *   GNU General Public License for more details.                            *
+ *                                                                           *
+ *   You should have received a copy of the GNU General Public License       *
+ *   along with this program.  If not, see <http://www.gnu.org/licenses/>.   *
+ *****************************************************************************/
+#ifndef DUMUX_MPNC_PROPERTY_DEFAULTS_HH
+#define DUMUX_MPNC_PROPERTY_DEFAULTS_HH
+
+#include "mpncindices.hh"
+
+#include "mpncmodel.hh"
+#include "mpncindices.hh"
+#include "mpnclocalresidual.hh"
+#include "mpncfluxvariables.hh"
+#include "mpncvolumevariables.hh"
+#include "mpncproperties.hh"
+#include "mpncnewtoncontroller.hh"
+#include "mpncvtkwritermodule.hh"
+#include "mpncvtkwritercommon.hh"
+#include "mass/mpncvtkwritermass.hh"
+#include "energy/mpncvtkwriterenergy.hh"
+
+#include <dumux/material/constraintsolvers/compositionfromfugacities.hh>
+#include <dumux/material/spatialparams/boxspatialparams.hh>
+
+
+/*!
+ * \ingroup Properties
+ * \ingroup BoxProperties
+ * \ingroup BoxMpNcModel
+ * \file
+ * \brief  Default properties for the Mp-Nc box model.
+ */
+namespace Dumux
+{
+namespace Properties
+{
+//////////////////////////////////////////////////////////////////
+// default property values
+//////////////////////////////////////////////////////////////////
+
+/*!
+ * \brief Set the property for the number of components.
+ *
+ * We just forward the number from the fluid system.
+ */
+SET_PROP(BoxMPNC, NumComponents)
+{
+private:
+    typedef typename GET_PROP_TYPE(TypeTag, FluidSystem) FluidSystem;
+
+public:
+    static const unsigned int value = FluidSystem::numComponents;
+};
+
+/*!
+ * \brief Set the property for the number of fluid phases.
+ *
+ * We just forward the number from the fluid system and use an static
+ * assert to make sure it is 2.
+ */
+SET_PROP(BoxMPNC, NumPhases)
+{
+private:
+    typedef typename GET_PROP_TYPE(TypeTag, FluidSystem) FluidSystem;
+
+public:
+    static const unsigned int value = FluidSystem::numPhases;
+};
+
+/*!
+ * \brief Set the property for the number of equations and primary variables.
+ */
+SET_PROP(BoxMPNC, NumEq)
+{
+private:
+    typedef typename GET_PROP_TYPE(TypeTag, Indices) Indices;
+
+public:
+    static const unsigned int value = Indices::NumPrimaryVars;
+};
+
+/*!
+ * \brief Set the property for the material parameters by extracting
+ *        it from the material law.
+ */
+SET_PROP(BoxMPNC, MaterialLawParams)
+{
+private:
+    typedef typename GET_PROP_TYPE(TypeTag, MaterialLaw) MaterialLaw;
+
+public:
+    typedef typename MaterialLaw::Params type;
+};
+
+/*!
+ * \brief Set the thermodynamic constraint solver which calculates the
+ *        composition of any phase given all component fugacities.
+ *
+ *        \deprecated version. Use "ConstraintSolver" instead of "CompositionFromFugacitiesSolver"
+ */
+SET_PROP(BoxMPNC, CompositionFromFugacitiesSolver) // DEPRECATED version. Use "ConstraintSolver" instead of "CompositionFromFugacitiesSolver"
+{
+private:
+    typedef typename GET_PROP_TYPE(TypeTag, Scalar) Scalar;
+    typedef typename GET_PROP_TYPE(TypeTag, FluidSystem) FluidSystem;
+
+public:
+    typedef Dumux::CompositionFromFugacities<Scalar, FluidSystem> type; // DEPRECATED version. Use "ConstraintSolver" instead of "CompositionFromFugacitiesSolver"
+};
+
+/*!
+ * \brief Set the thermodynamic constraint solver which calculates the
+ *        composition of any phase given all component fugacities.
+ */
+SET_PROP(BoxMPNC, ConstraintSolver)
+{
+private:
+    typedef typename GET_PROP_TYPE(TypeTag, Scalar) Scalar;
+    typedef typename GET_PROP_TYPE(TypeTag, FluidSystem) FluidSystem;
+
+public:
+    typedef typename GET_PROP_TYPE(TypeTag, CompositionFromFugacitiesSolver)  type;
+};
+
+
+//! Use the MpNc local jacobian operator for the MpNc model
+SET_TYPE_PROP(BoxMPNC,
+              LocalResidual,
+              MPNCLocalResidual<TypeTag>);
+
+//! Use the MpNc specific newton controller for the MpNc model
+SET_PROP(BoxMPNC, NewtonController)
+{public:
+    typedef MPNCNewtonController<TypeTag> type;
+};
+
+//! the Model property
+SET_TYPE_PROP(BoxMPNC, Model, MPNCModel<TypeTag>);
+
+//! use an isothermal model by default
+SET_BOOL_PROP(BoxMPNC, EnableEnergy, false);
+
+//! disable diffusion by default
+SET_BOOL_PROP(BoxMPNC, EnableDiffusion, false);
+
+//! disable kinetic mass transfer by default
+SET_BOOL_PROP(BoxMPNC, EnableKinetic, false);
+
+//! disable kinetic energy transfer by default
+SET_BOOL_PROP(BoxMPNC, EnableKineticEnergy, false);
+
+//! enable smooth upwinding by default
+SET_BOOL_PROP(BoxMPNC, ImplicitEnableSmoothUpwinding, false);
+
+//! the VolumeVariables property
+SET_TYPE_PROP(BoxMPNC, VolumeVariables, MPNCVolumeVariables<TypeTag>);
+
+//! the FluxVariables property
+SET_TYPE_PROP(BoxMPNC, FluxVariables, MPNCFluxVariables<TypeTag>);
+
+//! the Base of the Fluxvariables property (Darcy / Forchheimer)
+SET_TYPE_PROP(BoxMPNC, BaseFluxVariables, BoxDarcyFluxVariables<TypeTag>);
+
+//! truncate the newton update for the first few Newton iterations of a time step
+SET_BOOL_PROP(BoxMPNC, NewtonEnableChop, true);
+
+//! The indices required by the mpnc model
+SET_TYPE_PROP(BoxMPNC, Indices, MPNCIndices<TypeTag, 0>);
+
+//! the upwind weight for the mass conservation equations.
+SET_SCALAR_PROP(BoxMPNC, ImplicitMassUpwindWeight, 1.0);
+
+//! weight for the upwind mobility in the velocity calculation
+SET_SCALAR_PROP(BoxMPNC, ImplicitMobilityUpwindWeight, 1.0);
+
+//! The spatial parameters to be employed. 
+//! Use BoxSpatialParams by default.
+SET_TYPE_PROP(BoxMPNC, SpatialParams, BoxSpatialParams<TypeTag>);
+
+//! The VTK writer module for common quantities
+SET_PROP(BoxMPNC, MPNCVtkCommonModule)
+{
+    typedef MPNCVtkWriterCommon<TypeTag> type;
+};
+
+//! The VTK writer module for quantities which are specific for each
+//! mass module
+SET_PROP(BoxMPNC, MPNCVtkMassModule)
+{
+private: enum { enableKinetic = GET_PROP_VALUE(TypeTag, EnableKinetic) };
+public: typedef MPNCVtkWriterMass<TypeTag, enableKinetic> type;
+};
+
+//! The VTK writer module for quantities which are specific for each
+//! energy module
+SET_PROP(BoxMPNC, MPNCVtkEnergyModule)
+{
+private:
+    enum { enableEnergy = GET_PROP_VALUE(TypeTag, EnableEnergy) };
+    enum { enableKineticEnergy = GET_PROP_VALUE(TypeTag, EnableKineticEnergy) };
+public:
+    typedef MPNCVtkWriterEnergy<TypeTag, enableEnergy, enableKineticEnergy> type;
+};
+
+//! The VTK writer for user specified data (does nothing by default)
+SET_PROP(BoxMPNC, MPNCVtkCustomModule)
+{ typedef MPNCVtkWriterModule<TypeTag> type; };
+
+/*!
+ * \brief The fluid state which is used by the volume variables to
+ *        store the thermodynamic state. This should be chosen
+ *        appropriately for the model ((non-)isothermal, equilibrium, ...).
+ *        This can be done in the problem.
+ */
+SET_PROP(BoxMPNC, FluidState){
+    private:
+        typedef typename GET_PROP_TYPE(TypeTag, Scalar) Scalar;
+        typedef typename GET_PROP_TYPE(TypeTag, FluidSystem) FluidSystem;
+    public:
+        typedef Dumux::CompositionalFluidState<Scalar, FluidSystem> type;
+};
+
+//! default value for the forchheimer coefficient
+// Source: Ward, J.C. 1964 Turbulent flow in porous media. ASCE J. Hydraul. Div 90.
+//        Actually the Forchheimer coefficient is also a function of the dimensions of the
+//        porous medium. Taking it as a constant is only a first approximation
+//        (Nield, Bejan, Convection in porous media, 2006, p. 10)
+SET_SCALAR_PROP(BoxModel, SpatialParamsForchCoeff, 0.55);
+
+
+//!< Should the averaging of velocities be done in the Model? (By default in the output)
+SET_BOOL_PROP(BoxMPNC, VelocityAveragingInModel, false);
+
+//! Specify what to add to the VTK output by default
+SET_BOOL_PROP(BoxMPNC, VtkAddPorosity, true);
+SET_BOOL_PROP(BoxMPNC, VtkAddBoundaryTypes, false);
+SET_BOOL_PROP(BoxMPNC, VtkAddSaturations, true);
+SET_BOOL_PROP(BoxMPNC, VtkAddPressures, true);
+SET_BOOL_PROP(BoxMPNC, VtkAddVarPressures, false);
+SET_BOOL_PROP(BoxMPNC, VtkAddVelocities, false);
+SET_BOOL_PROP(BoxMPNC, VtkAddDensities, true);
+SET_BOOL_PROP(BoxMPNC, VtkAddMobilities, true);
+SET_BOOL_PROP(BoxMPNC, VtkAddAverageMolarMass, false);
+SET_BOOL_PROP(BoxMPNC, VtkAddMassFractions, false);
+SET_BOOL_PROP(BoxMPNC, VtkAddMoleFractions, true);
+SET_BOOL_PROP(BoxMPNC, VtkAddMolarities, false);
+SET_BOOL_PROP(BoxMPNC, VtkAddFugacities, false);
+SET_BOOL_PROP(BoxMPNC, VtkAddFugacityCoefficients, false);
+SET_BOOL_PROP(BoxMPNC, VtkAddTemperatures, false);
+SET_BOOL_PROP(BoxMPNC, VtkAddEnthalpies, true);
+SET_BOOL_PROP(BoxMPNC, VtkAddInternalEnergies, false);
+SET_BOOL_PROP(BoxMPNC, VtkAddReynolds, false);
+SET_BOOL_PROP(BoxMPNC, VtkAddPrandtl, false);
+SET_BOOL_PROP(BoxMPNC, VtkAddNusselt, false);
+SET_BOOL_PROP(BoxMPNC, VtkAddInterfacialArea, false);
+SET_BOOL_PROP(BoxMPNC, VtkAddxEquil, false);
+
+// enable gravity by default
+SET_BOOL_PROP(BoxMPNC, ProblemEnableGravity, true);
+
+}
+
+}
+
+#endif
diff --git a/dumux/implicit/mpnc/mpncvolumevariables.hh b/dumux/implicit/mpnc/mpncvolumevariables.hh
new file mode 100644
index 0000000000..409218898f
--- /dev/null
+++ b/dumux/implicit/mpnc/mpncvolumevariables.hh
@@ -0,0 +1,340 @@
+// -*- mode: C++; tab-width: 4; indent-tabs-mode: nil; c-basic-offset: 4 -*-
+// vi: set et ts=4 sw=4 sts=4:
+/*****************************************************************************
+ *   See the file COPYING for full copying permissions.                      *
+ *                                                                           *
+ *   This program is free software: you can redistribute it and/or modify    *
+ *   it under the terms of the GNU General Public License as published by    *
+ *   the Free Software Foundation, either version 2 of the License, or       *
+ *   (at your option) any later version.                                     *
+ *                                                                           *
+ *   This program is distributed in the hope that it will be useful,         *
+ *   but WITHOUT ANY WARRANTY; without even the implied warranty of          *
+ *   MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the            *
+ *   GNU General Public License for more details.                            *
+ *                                                                           *
+ *   You should have received a copy of the GNU General Public License       *
+ *   along with this program.  If not, see <http://www.gnu.org/licenses/>.   *
+ *****************************************************************************/
+/*!
+ * \file
+ *
+ * \brief Contains the secondary variables (Quantities which are
+ *        constant within a finite volume) of the M-phase, N-component
+ *        model.
+ */
+#ifndef DUMUX_MPNC_VOLUME_VARIABLES_HH
+#define DUMUX_MPNC_VOLUME_VARIABLES_HH
+
+#include "diffusion/volumevariables.hh"
+#include "energy/mpncvolumevariablesenergy.hh"
+#include "mass/mpncvolumevariablesmass.hh"
+#include "mpncvolumevariablesia.hh"
+
+#include <dumux/boxmodels/common/boxvolumevariables.hh>
+#include <dumux/material/constraintsolvers/ncpflash.hh>
+
+namespace Dumux
+{
+/*!
+ * \ingroup MPNCModel
+ * \ingroup BoxVolumeVariables
+ * \brief Contains the quantities which are are constant within a
+ *        finite volume in the M-phase, N-component model.
+ */
+template <class TypeTag>
+class MPNCVolumeVariables
+    : public BoxVolumeVariables<TypeTag>
+    , public MPNCVolumeVariablesIA<TypeTag, GET_PROP_VALUE(TypeTag, EnableKinetic), GET_PROP_VALUE(TypeTag, EnableKineticEnergy)>
+    , public MPNCVolumeVariablesMass<TypeTag, GET_PROP_VALUE(TypeTag, EnableKinetic)>
+    , public MPNCVolumeVariablesDiffusion<TypeTag, GET_PROP_VALUE(TypeTag, EnableDiffusion) || GET_PROP_VALUE(TypeTag, EnableKinetic)>
+    , public MPNCVolumeVariablesEnergy<TypeTag, GET_PROP_VALUE(TypeTag, EnableEnergy), GET_PROP_VALUE(TypeTag, EnableKineticEnergy)>
+{
+    typedef BoxVolumeVariables<TypeTag> ParentType;
+    typedef typename GET_PROP_TYPE(TypeTag, VolumeVariables) Implementation;
+    typedef typename GET_PROP_TYPE(TypeTag, Problem) Problem;
+    typedef typename GET_PROP_TYPE(TypeTag, Scalar) Scalar;
+    typedef typename GET_PROP_TYPE(TypeTag, GridView) GridView;
+    typedef typename GET_PROP_TYPE(TypeTag, FVElementGeometry) FVElementGeometry;
+    typedef typename GET_PROP_TYPE(TypeTag, FluidSystem) FluidSystem;
+    typedef typename GET_PROP_TYPE(TypeTag, FluidState) FluidState;
+    typedef typename FluidSystem::ParameterCache ParameterCache;
+    typedef typename GET_PROP_TYPE(TypeTag, MaterialLaw) MaterialLaw;
+    typedef typename GET_PROP_TYPE(TypeTag, MaterialLawParams) MaterialLawParams;
+    typedef typename GET_PROP_TYPE(TypeTag, PrimaryVariables) PrimaryVariables;
+    typedef typename GET_PROP_TYPE(TypeTag, Indices) Indices;
+
+    enum {numPhases = GET_PROP_VALUE(TypeTag, NumPhases)};
+    enum {numComponents = GET_PROP_VALUE(TypeTag, NumComponents)};
+    enum {enableEnergy = GET_PROP_VALUE(TypeTag, EnableEnergy)};
+    enum {enableKinetic = GET_PROP_VALUE(TypeTag, EnableKinetic)};
+    enum {enableKineticEnergy = GET_PROP_VALUE(TypeTag, EnableKineticEnergy)};
+    enum {enableDiffusion = GET_PROP_VALUE(TypeTag, EnableDiffusion) || enableKinetic};
+    enum {S0Idx = Indices::S0Idx};
+    enum {p0Idx = Indices::p0Idx};
+
+    typedef typename GridView::template Codim<0>::Entity Element;
+    typedef MPNCVolumeVariablesMass<TypeTag, enableKinetic> MassVolumeVariables;
+    typedef MPNCVolumeVariablesEnergy<TypeTag, enableEnergy, enableKineticEnergy> EnergyVolumeVariables;
+    typedef MPNCVolumeVariablesIA<TypeTag, enableKinetic, enableKineticEnergy> IAVolumeVariables;
+    typedef MPNCVolumeVariablesDiffusion<TypeTag, enableDiffusion> DiffusionVolumeVariables;
+
+public:
+    MPNCVolumeVariables()
+    { hint_ = NULL; };
+
+    /*!
+     * \brief Set the volume variables which should be used as initial
+     *        conditions for complex calculations.
+     */
+    void setHint(const Implementation *hint)
+    {
+        hint_ = hint;
+    }
+
+    /*!
+     * \copydoc BoxVolumeVariables::update
+     */
+    void update(const PrimaryVariables &priVars,
+                const Problem &problem,
+                const Element &element,
+                const FVElementGeometry &fvGeometry,
+                const unsigned int scvIdx,
+                const bool isOldSol)
+    {
+        Valgrind::CheckDefined(priVars);
+        ParentType::update(priVars,
+                           problem,
+                           element,
+                           fvGeometry,
+                           scvIdx,
+                           isOldSol);
+        ParentType::checkDefined();
+
+        ParameterCache paramCache;
+
+        /////////////
+        // set the phase saturations
+        /////////////
+        Scalar sumSat = 0;
+        for (int phaseIdx = 0; phaseIdx < numPhases - 1; ++phaseIdx) {
+            sumSat += priVars[S0Idx + phaseIdx];
+            fluidState_.setSaturation(phaseIdx, priVars[S0Idx + phaseIdx]);
+        }
+        Valgrind::CheckDefined(sumSat);
+        fluidState_.setSaturation(numPhases - 1, 1.0 - sumSat);
+
+        /////////////
+        // set the fluid phase temperatures
+        /////////////
+        EnergyVolumeVariables::updateTemperatures(fluidState_,
+                                                  paramCache,
+                                                  priVars,
+                                                  element,
+                                                  fvGeometry,
+                                                  scvIdx,
+                                                  problem);
+
+        /////////////
+        // set the phase pressures
+        /////////////
+
+        // capillary pressure parameters
+        const MaterialLawParams &materialParams =
+            problem.spatialParams().materialLawParams(element, fvGeometry, scvIdx);
+        // capillary pressures
+        Scalar capPress[numPhases];
+        MaterialLaw::capillaryPressures(capPress, materialParams, fluidState_);
+        // add to the pressure of the first fluid phase
+        Scalar p0 = priVars[p0Idx];
+        for (int phaseIdx = 0; phaseIdx < numPhases; ++ phaseIdx)
+            fluidState_.setPressure(phaseIdx, p0 - capPress[0] + capPress[phaseIdx]);
+
+        /////////////
+        // set the fluid compositions
+        /////////////
+        MassVolumeVariables::update(fluidState_,
+                                    paramCache,
+                                    priVars,
+                                    hint_,
+                                    problem,
+                                    element,
+                                    fvGeometry,
+                                    scvIdx);
+        MassVolumeVariables::checkDefined();
+
+        /////////////
+        // Porosity
+        /////////////
+
+        // porosity
+        porosity_ = problem.spatialParams().porosity(element,
+                                                     fvGeometry,
+                                                     scvIdx);
+        Valgrind::CheckDefined(porosity_);
+
+        /////////////
+        // Phase mobilities
+        /////////////
+
+        // relative permeabilities
+        MaterialLaw::relativePermeabilities(relativePermeability_,
+                                            materialParams,
+                                            fluidState_);
+
+        // dynamic viscosities
+        for (int phaseIdx = 0; phaseIdx < numPhases; ++phaseIdx) {
+            // viscosities
+            Scalar mu = FluidSystem::viscosity(fluidState_, paramCache, phaseIdx);
+            fluidState_.setViscosity(phaseIdx, mu);
+        }
+
+        /////////////
+        // diffusion
+        /////////////
+
+        // update the diffusion part of the volume data
+        DiffusionVolumeVariables::update(fluidState_, paramCache, *this, problem);
+        DiffusionVolumeVariables::checkDefined();
+
+        /////////////
+        // energy
+        /////////////
+
+        // update the remaining parts of the energy module
+        EnergyVolumeVariables::update(fluidState_,
+                                      paramCache,
+                                      element,
+                                      fvGeometry,
+                                      scvIdx,
+                                      problem);
+        EnergyVolumeVariables::checkDefined();
+
+        // make sure the quantities in the fluid state are well-defined
+        fluidState_.checkDefined();
+
+        // specific interfacial area,
+        // well also all the dimensionless numbers :-)
+        // well, also the mass transfer rate
+        IAVolumeVariables::update(*this,
+                                  fluidState_,
+                                  paramCache,
+                                  priVars,
+                                  problem,
+                                  element,
+                                  fvGeometry,
+                                  scvIdx);
+        IAVolumeVariables::checkDefined();
+        checkDefined();
+    }
+
+    /*!
+     * \brief Return the fluid configuration at the given primary
+     *        variables
+     */
+    const FluidState &fluidState() const
+    { return fluidState_; }
+
+    /*!
+     * \brief Returns the effective mobility of a given phase within
+     *        the control volume.
+     */
+    Scalar mobility(const unsigned int phaseIdx) const
+    { return relativePermeability(phaseIdx)/fluidState_.viscosity(phaseIdx); }
+
+    /*!
+     * \brief Returns the viscosity of a given phase within
+     *        the control volume.
+     */
+    Scalar viscosity(const unsigned int phaseIdx) const
+    { return fluidState_.viscosity(phaseIdx); }
+
+    /*!
+     * \brief Returns the relative permeability of a given phase within
+     *        the control volume.
+     */
+    Scalar relativePermeability(const unsigned int phaseIdx) const
+    { return relativePermeability_[phaseIdx]; }
+
+    /*!
+     * \brief Returns the average porosity within the control volume.
+     */
+    Scalar porosity() const
+    { return porosity_; }
+
+    /*!
+     * \brief Returns true iff the fluid state is in the active set
+     *        for a phase,
+     */
+    bool isPhaseActive(const unsigned int phaseIdx) const
+    {
+        return
+            phasePresentIneq(fluidState(), phaseIdx) -
+            phaseNotPresentIneq(fluidState(), phaseIdx)
+            >= 0;
+    }
+
+    /*!
+     * \brief Returns the value of the NCP-function for a phase.
+     */
+    Scalar phaseNcp(const unsigned int phaseIdx) const
+    {
+        Scalar aEval = phaseNotPresentIneq(this->evalPoint().fluidState(), phaseIdx);
+        Scalar bEval = phasePresentIneq(this->evalPoint().fluidState(), phaseIdx);
+        if (aEval > bEval)
+            return phasePresentIneq(fluidState(), phaseIdx);
+        return phaseNotPresentIneq(fluidState(), phaseIdx);
+    };
+
+    /*!
+     * \brief Returns the value of the inequality where a phase is
+     *        present.
+     */
+    Scalar phasePresentIneq(const FluidState &fluidState,
+                            const unsigned int phaseIdx) const
+    { return fluidState.saturation(phaseIdx); }
+
+    /*!
+     * \brief Returns the value of the inequality where a phase is not
+     *        present.
+     */
+    Scalar phaseNotPresentIneq(const FluidState &fluidState,
+                               const unsigned int phaseIdx) const
+    {
+        // difference of sum of mole fractions in the phase from 100%
+        Scalar a = 1;
+        for (int compIdx = 0; compIdx < numComponents; ++compIdx)
+            a -= fluidState.moleFraction(phaseIdx, compIdx);
+        return a;
+    }
+
+    /*!
+     * \brief If running in valgrind this makes sure that all
+     *        quantities in the volume variables are defined.
+     */
+    void checkDefined() const
+    {
+#if !defined NDEBUG && HAVE_VALGRIND
+        ParentType::checkDefined();
+
+        Valgrind::CheckDefined(porosity_);
+        Valgrind::CheckDefined(hint_);
+        Valgrind::CheckDefined(relativePermeability_);
+
+        fluidState_.checkDefined();
+#endif
+    }
+
+protected:
+    Scalar porosity_; //!< Effective porosity within the control volume
+    Scalar relativePermeability_[numPhases]; //!< Effective relative permeability within the control volume
+
+    const Implementation *hint_;
+
+    //! Mass fractions of each component within each phase
+    FluidState fluidState_;
+};
+
+} // end namepace
+
+#endif
diff --git a/dumux/implicit/mpnc/mpncvolumevariablesia.hh b/dumux/implicit/mpnc/mpncvolumevariablesia.hh
new file mode 100644
index 0000000000..7e62cb7ed9
--- /dev/null
+++ b/dumux/implicit/mpnc/mpncvolumevariablesia.hh
@@ -0,0 +1,85 @@
+// -*- mode: C++; tab-width: 4; indent-tabs-mode: nil; c-basic-offset: 4 -*-
+// vi: set et ts=4 sw=4 sts=4:
+/*****************************************************************************
+ *   See the file COPYING for full copying permissions.                      *
+ *                                                                           *
+ *   This program is free software: you can redistribute it and/or modify    *
+ *   it under the terms of the GNU General Public License as published by    *
+ *   the Free Software Foundation, either version 2 of the License, or       *
+ *   (at your option) any later version.                                     *
+ *                                                                           *
+ *   This program is distributed in the hope that it will be useful,         *
+ *   but WITHOUT ANY WARRANTY; without even the implied warranty of          *
+ *   MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the            *
+ *   GNU General Public License for more details.                            *
+ *                                                                           *
+ *   You should have received a copy of the GNU General Public License       *
+ *   along with this program.  If not, see <http://www.gnu.org/licenses/>.   *
+ *****************************************************************************/
+/*!
+ * \file
+ *
+ * \brief This class contains the volume variables required for the
+ *        modules which require the specific interfacial area between
+ *        fluid phases.
+ */
+#ifndef DUMUX_MPNC_VOLUME_VARIABLES_IA_HH
+#define DUMUX_MPNC_VOLUME_VARIABLES_IA_HH
+
+#include <dumux/boxmodels/mpnc/mpncproperties.hh>
+
+namespace Dumux
+{
+
+/*!
+ * \brief This class contains the volume variables required for the
+ *        modules which require the specific interfacial area between
+ *        fluid phases.
+ *
+ * This is the specialization for the cases which do _not_ require
+ * specific interfacial area.
+ */
+template <class TypeTag, bool enableKinetic /* = false */, bool enableKineticEnergy /* = false */>
+class MPNCVolumeVariablesIA
+{
+    static_assert(not enableKinetic and not enableKineticEnergy,
+                  "The kinetic energy modules need specific interfacial area "
+                  "but no suitable specialization of the IA volume variables module "
+                  "has been included.");
+
+    typedef typename GET_PROP_TYPE(TypeTag, PrimaryVariables) PrimaryVariables;
+    typedef typename GET_PROP_TYPE(TypeTag, FVElementGeometry) FVElementGeometry;
+    typedef typename GET_PROP_TYPE(TypeTag, GridView) GridView;
+    typedef typename GET_PROP_TYPE(TypeTag, Problem) Problem;
+    typedef typename GET_PROP_TYPE(TypeTag, VolumeVariables) VolumeVariables;
+    typedef typename GET_PROP_TYPE(TypeTag, FluidSystem) FluidSystem;
+    typedef typename GET_PROP_TYPE(TypeTag, FluidState) FluidState;
+    typedef typename FluidSystem::ParameterCache ParameterCache;
+    typedef typename GridView::template Codim<0>::Entity Element;
+
+public:
+    /*!
+     * \brief Updates the volume specific interfacial area [m^2 / m^3] between the phases.
+     */
+    void update(const VolumeVariables & volVars,
+                const FluidState &fluidState,
+                const ParameterCache &paramCache,
+                const PrimaryVariables &priVars,
+                const Problem &problem,
+                const Element & element,
+                const FVElementGeometry & fvGeometry,
+                const unsigned int scvIdx)
+    {
+    }
+
+    /*!
+     * \brief If running in valgrind this makes sure that all
+     *        quantities in the volume variables are defined.
+     */
+    void checkDefined() const
+    { }
+};
+
+} // namespace Dumux
+
+#endif
diff --git a/dumux/implicit/mpnc/mpncvtkwriter.hh b/dumux/implicit/mpnc/mpncvtkwriter.hh
new file mode 100644
index 0000000000..afc912214e
--- /dev/null
+++ b/dumux/implicit/mpnc/mpncvtkwriter.hh
@@ -0,0 +1,126 @@
+// -*- mode: C++; tab-width: 4; indent-tabs-mode: nil; c-basic-offset: 4 -*-
+// vi: set et ts=4 sw=4 sts=4:
+/*****************************************************************************
+ *   See the file COPYING for full copying permissions.                      *
+ *                                                                           *
+ *   This program is free software: you can redistribute it and/or modify    *
+ *   it under the terms of the GNU General Public License as published by    *
+ *   the Free Software Foundation, either version 2 of the License, or       *
+ *   (at your option) any later version.                                     *
+ *                                                                           *
+ *   This program is distributed in the hope that it will be useful,         *
+ *   but WITHOUT ANY WARRANTY; without even the implied warranty of          *
+ *   MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the            *
+ *   GNU General Public License for more details.                            *
+ *                                                                           *
+ *   You should have received a copy of the GNU General Public License       *
+ *   along with this program.  If not, see <http://www.gnu.org/licenses/>.   *
+ *****************************************************************************/
+#ifndef DUMUX_MPNC_VTK_WRITER_HH
+#define DUMUX_MPNC_VTK_WRITER_HH
+
+#include "mpncproperties.hh"
+
+#include <dumux/io/vtkmultiwriter.hh>
+
+namespace Dumux
+{
+/*!
+ * \ingroup MPNCModel
+ * \brief Writes the VTK output files for a
+ * solution of the Mp-Nc model.
+ */
+template<class TypeTag>
+class MPNCVtkWriter
+{
+    typedef typename GET_PROP_TYPE(TypeTag, MPNCVtkCommonModule) MPNCVtkCommonModule;
+    typedef typename GET_PROP_TYPE(TypeTag, MPNCVtkMassModule) MPNCVtkMassModule;
+    typedef typename GET_PROP_TYPE(TypeTag, MPNCVtkEnergyModule) MPNCVtkEnergyModule;
+    typedef typename GET_PROP_TYPE(TypeTag, MPNCVtkCustomModule) MPNCVtkCustomModule;
+    typedef typename GET_PROP_TYPE(TypeTag, ElementVolumeVariables) ElementVolumeVariables;
+    typedef typename GET_PROP_TYPE(TypeTag, FVElementGeometry) FVElementGeometry;
+    typedef typename GET_PROP_TYPE(TypeTag, ElementBoundaryTypes) ElementBoundaryTypes;
+    typedef typename GET_PROP_TYPE(TypeTag, Problem) Problem;
+    typedef typename GET_PROP_TYPE(TypeTag, GridView) GridView;
+    typedef typename GridView::template Codim<0>::Entity Element;
+    typedef typename GridView::template Codim<0>::Iterator ElementIterator;
+
+public:
+    MPNCVtkWriter(const Problem &problem)
+        : problem_(problem)
+        , commonWriter_(problem)
+        , massWriter_(problem)
+        , energyWriter_(problem)
+        , customWriter_(problem)
+    {
+    }
+
+    /*!
+     * \brief Add  the current solution to the VtkMultiWriter.
+     */
+    template <class MultiWriter>
+    void addCurrentSolution(MultiWriter &writer)
+    {
+        // tell sub-writers to allocate their buffers
+        commonWriter_.allocBuffers(writer);
+        massWriter_.allocBuffers(writer);
+        energyWriter_.allocBuffers(writer);
+        customWriter_.allocBuffers(writer);
+
+        // iterate over grid
+        FVElementGeometry fvGeometry;
+        ElementVolumeVariables elemVolVars;
+        ElementBoundaryTypes elemBcTypes;
+
+        ElementIterator elemIt = problem_.gridView().template begin<0>();
+        ElementIterator elemEndIt = problem_.gridView().template end<0>();
+        for (; elemIt != elemEndIt; ++elemIt)
+        {
+            fvGeometry.update(problem_.gridView(), *elemIt);
+            elemBcTypes.update(problem_, *elemIt);
+            this->problem_.model().setHints(*elemIt, elemVolVars);
+            elemVolVars.update(problem_,
+                               *elemIt,
+                               fvGeometry,
+                               false);
+            this->problem_.model().updateCurHints(*elemIt, elemVolVars);
+
+            // tell the sub-writers to do what ever they need to with
+            // their internal buffers when a given element is seen.
+            commonWriter_.processElement(*elemIt,
+                                         fvGeometry,
+                                         elemVolVars,
+                                         elemBcTypes);
+            massWriter_.processElement(*elemIt,
+                                       fvGeometry,
+                                       elemVolVars,
+                                       elemBcTypes);
+            energyWriter_.processElement(*elemIt,
+                                         fvGeometry,
+                                         elemVolVars,
+                                         elemBcTypes);
+            customWriter_.processElement(*elemIt,
+                                         fvGeometry,
+                                         elemVolVars,
+                                         elemBcTypes);
+        }
+
+        // write everything to the output file
+        commonWriter_.commitBuffers(writer);
+        massWriter_.commitBuffers(writer);
+        energyWriter_.commitBuffers(writer);
+        customWriter_.commitBuffers(writer);
+    }
+
+private:
+    const Problem &problem_;
+
+    MPNCVtkCommonModule commonWriter_;
+    MPNCVtkMassModule massWriter_;
+    MPNCVtkEnergyModule energyWriter_;
+    MPNCVtkCustomModule customWriter_;
+};
+
+}
+
+#endif
diff --git a/dumux/implicit/mpnc/mpncvtkwritercommon.hh b/dumux/implicit/mpnc/mpncvtkwritercommon.hh
new file mode 100644
index 0000000000..c92536bf6d
--- /dev/null
+++ b/dumux/implicit/mpnc/mpncvtkwritercommon.hh
@@ -0,0 +1,275 @@
+// -*- mode: C++; tab-width: 4; indent-tabs-mode: nil; c-basic-offset: 4 -*-
+// vi: set et ts=4 sw=4 sts=4:
+/*****************************************************************************
+ *   See the file COPYING for full copying permissions.                      *
+ *                                                                           *
+ *   This program is free software: you can redistribute it and/or modify    *
+ *   it under the terms of the GNU General Public License as published by    *
+ *   the Free Software Foundation, either version 2 of the License, or       *
+ *   (at your option) any later version.                                     *
+ *                                                                           *
+ *   This program is distributed in the hope that it will be useful,         *
+ *   but WITHOUT ANY WARRANTY; without even the implied warranty of          *
+ *   MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the            *
+ *   GNU General Public License for more details.                            *
+ *                                                                           *
+ *   You should have received a copy of the GNU General Public License       *
+ *   along with this program.  If not, see <http://www.gnu.org/licenses/>.   *
+ *****************************************************************************/
+/*!
+ * \file
+ *
+ * \brief VTK writer module for the common quantities of the MpNc
+ *        model.
+ */
+#ifndef DUMUX_MPNC_VTK_WRITER_COMMON_HH
+#define DUMUX_MPNC_VTK_WRITER_COMMON_HH
+
+#include "mpncvtkwritermodule.hh"
+
+namespace Dumux
+{
+/*!
+ * \ingroup MPNCModel
+ *
+ * \brief VTK writer module for the common quantities of the MpNc
+ *        model.
+ */
+template<class TypeTag>
+class MPNCVtkWriterCommon : public MPNCVtkWriterModule<TypeTag>
+{
+    typedef MPNCVtkWriterModule<TypeTag> ParentType;
+    typedef typename GET_PROP_TYPE(TypeTag, Problem) Problem;
+    typedef typename GET_PROP_TYPE(TypeTag, Scalar) Scalar;
+    typedef typename GET_PROP_TYPE(TypeTag, FVElementGeometry) FVElementGeometry;
+    typedef typename GET_PROP_TYPE(TypeTag, ElementVolumeVariables) ElementVolumeVariables;
+    typedef typename GET_PROP_TYPE(TypeTag, ElementBoundaryTypes) ElementBoundaryTypes;
+    typedef typename GET_PROP_TYPE(TypeTag, VolumeVariables) VolumeVariables;
+    typedef typename GET_PROP_TYPE(TypeTag, FluxVariables) FluxVariables;
+    typedef typename GET_PROP_TYPE(TypeTag, FluidSystem) FluidSystem;
+    typedef typename GET_PROP_TYPE(TypeTag, GridView) GridView;
+    typedef typename GridView::template Codim<0>::Entity Element;
+    typedef typename ParentType::ScalarVector ScalarVector;
+    typedef typename ParentType::PhaseVector PhaseVector;
+    typedef typename ParentType::ComponentVector ComponentVector;
+    typedef typename ParentType::PhaseComponentMatrix PhaseComponentMatrix;
+
+    enum { dim = GridView::dimension };
+    enum { numPhases = GET_PROP_VALUE(TypeTag, NumPhases) };
+    enum { numComponents = GET_PROP_VALUE(TypeTag, NumComponents) };
+    enum { numEq = GET_PROP_VALUE(TypeTag, NumEq) };
+
+    typedef Dune::FieldVector<Scalar, dim> DimVector;
+    typedef Dune::BlockVector<DimVector> DimField;
+    typedef Dune::array<DimField, numPhases> PhaseDimField;
+
+public:
+    MPNCVtkWriterCommon(const Problem &problem)
+        : ParentType(problem)
+    {
+        porosityOutput_ = GET_PARAM_FROM_GROUP(TypeTag, bool, Vtk, AddPorosity);
+        boundaryTypesOutput_ = GET_PARAM_FROM_GROUP(TypeTag, bool, Vtk, AddBoundaryTypes);
+        saturationOutput_ = GET_PARAM_FROM_GROUP(TypeTag, bool, Vtk, AddSaturations);
+        pressureOutput_ = GET_PARAM_FROM_GROUP(TypeTag, bool, Vtk, AddPressures);
+        velocityOutput_ = GET_PARAM_FROM_GROUP(TypeTag, bool, Vtk, AddVelocities);
+        densityOutput_ = GET_PARAM_FROM_GROUP(TypeTag, bool, Vtk, AddDensities);
+        mobilityOutput_ = GET_PARAM_FROM_GROUP(TypeTag, bool, Vtk, AddMobilities);
+        averageMolarMassOutput_ = GET_PARAM_FROM_GROUP(TypeTag, bool, Vtk, AddAverageMolarMass);
+        massFracOutput_ = GET_PARAM_FROM_GROUP(TypeTag, bool, Vtk, AddMassFractions);
+        moleFracOutput_ = GET_PARAM_FROM_GROUP(TypeTag, bool, Vtk, AddMoleFractions);
+        molarityOutput_ = GET_PARAM_FROM_GROUP(TypeTag, bool, Vtk, AddMolarities);
+    }
+
+    /*!
+     * \brief Allocate memory for the scalar fields we would like to
+     *        write to the VTK file.
+     */
+    template <class MultiWriter>
+    void allocBuffers(MultiWriter &writer)
+    {
+        if (porosityOutput_)
+            this->resizeScalarBuffer_(porosity_);
+        if (boundaryTypesOutput_)
+            this->resizeScalarBuffer_(boundaryTypes_);
+
+        if (velocityOutput_) {
+            Scalar nVerts = this->problem_.gridView().size(dim);
+            for (int phaseIdx = 0; phaseIdx < numPhases; ++ phaseIdx) {
+                velocity_[phaseIdx].resize(nVerts);
+                velocity_[phaseIdx] = 0;
+            }
+            this->resizeScalarBuffer_(boxSurface_);
+        }
+
+        if (saturationOutput_) this->resizePhaseBuffer_(saturation_);
+        if (pressureOutput_) this->resizePhaseBuffer_(pressure_);
+        if (densityOutput_) this->resizePhaseBuffer_(density_);
+        if (mobilityOutput_) this->resizePhaseBuffer_(mobility_);
+        if (averageMolarMassOutput_) this->resizePhaseBuffer_(averageMolarMass_);
+        if (moleFracOutput_) this->resizePhaseComponentBuffer_(moleFrac_);
+        if (massFracOutput_) this->resizePhaseComponentBuffer_(massFrac_);
+        if (molarityOutput_) this->resizePhaseComponentBuffer_(molarity_);
+    }
+
+    /*!
+     * \brief Modify the internal buffers according to the volume
+     *        variables seen on an element
+     */
+    void processElement(const Element &elem,
+                        const FVElementGeometry &fvGeometry,
+                        const ElementVolumeVariables &elemVolVars,
+                        const ElementBoundaryTypes &elemBcTypes)
+    {
+        int numLocalVertices = elem.geometry().corners();
+        for (int localVertexIdx = 0; localVertexIdx < numLocalVertices; ++localVertexIdx) {
+            int globalIdx = this->problem_.vertexMapper().map(elem, localVertexIdx, dim);
+            const VolumeVariables &volVars = elemVolVars[localVertexIdx];
+
+            if (porosityOutput_) porosity_[globalIdx] = volVars.porosity();
+
+            // calculate a single value for the boundary type: use one
+            // bit for each equation and set it to 1 if the equation
+            // is used for a dirichlet condition
+            int tmp = 0;
+            for (int eqIdx = 0; eqIdx < numEq; ++eqIdx) {
+                if (elemBcTypes[localVertexIdx].isDirichlet(eqIdx))
+                    tmp += (1 << eqIdx);
+            }
+            if (boundaryTypesOutput_) boundaryTypes_[globalIdx] = tmp;
+
+            for (int phaseIdx = 0; phaseIdx < numPhases; ++phaseIdx) {
+                if (saturationOutput_) saturation_[phaseIdx][globalIdx] = volVars.fluidState().saturation(phaseIdx);
+                if (pressureOutput_) pressure_[phaseIdx][globalIdx] = volVars.fluidState().pressure(phaseIdx);
+                if (densityOutput_) density_[phaseIdx][globalIdx] = volVars.fluidState().density(phaseIdx);
+                if (mobilityOutput_) mobility_[phaseIdx][globalIdx] = volVars.mobility(phaseIdx);
+                if (averageMolarMassOutput_) averageMolarMass_[phaseIdx][globalIdx] = volVars.fluidState().averageMolarMass(phaseIdx);
+                for (int compIdx = 0; compIdx < numComponents; ++compIdx) {
+                    if (moleFracOutput_) moleFrac_[phaseIdx][compIdx][globalIdx] = volVars.fluidState().moleFraction(phaseIdx, compIdx);
+                    if (massFracOutput_) massFrac_[phaseIdx][compIdx][globalIdx] = volVars.fluidState().massFraction(phaseIdx, compIdx);
+                    if (molarityOutput_) molarity_[phaseIdx][compIdx][globalIdx] = volVars.fluidState().molarity(phaseIdx, compIdx);
+                }
+            }
+        }
+
+        // calculate velocities if requested by the problem
+        if (velocityOutput_) {
+            for (int faceIdx = 0; faceIdx < fvGeometry.numEdges; ++ faceIdx) {
+                int i = fvGeometry.subContVolFace[faceIdx].i;
+                int I = this->problem_.vertexMapper().map(elem, i, dim);
+
+                int j = fvGeometry.subContVolFace[faceIdx].j;
+                int J = this->problem_.vertexMapper().map(elem, j, dim);
+
+                FluxVariables fluxVars(this->problem_,
+                                       elem,
+                                       fvGeometry,
+                                       faceIdx,
+                                       elemVolVars);
+
+                Scalar scvfArea = fvGeometry.subContVolFace[faceIdx].normal.two_norm();
+                scvfArea *= fluxVars.extrusionFactor();
+
+                boxSurface_[I] += scvfArea;
+                boxSurface_[J] += scvfArea;
+
+                for (int phaseIdx = 0; phaseIdx < numPhases; ++phaseIdx) {
+                    Dune::FieldVector<Scalar, dim> velocity;
+                    velocity = fluxVars.velocity(phaseIdx);
+                    velocity *= scvfArea;
+                    velocity_[phaseIdx][I] += velocity;
+                    velocity_[phaseIdx][J] += velocity;
+
+                } // end for all phases
+            } // end for all faces
+        } // end if velocityOutput_
+    }
+
+    /*!
+     * \brief Add all buffers to the VTK output writer.
+     */
+    template <class MultiWriter>
+    void commitBuffers(MultiWriter &writer)
+    {
+        if (saturationOutput_)
+            this->commitPhaseBuffer_(writer, "S_%s", saturation_);
+
+        if (pressureOutput_)
+            this->commitPhaseBuffer_(writer, "p_%s", pressure_);
+
+        if (densityOutput_)
+            this->commitPhaseBuffer_(writer, "rho_%s", density_);
+
+        if (averageMolarMassOutput_)
+            this->commitPhaseBuffer_(writer, "M_%s", averageMolarMass_);
+
+        if (mobilityOutput_)
+            this->commitPhaseBuffer_(writer, "lambda_%s", mobility_);
+
+        if (porosityOutput_)
+            this->commitScalarBuffer_(writer, "porosity", porosity_);
+
+        if (boundaryTypesOutput_)
+            this->commitScalarBuffer_(writer, "boundary types", boundaryTypes_);
+
+        if (moleFracOutput_)
+            this->commitPhaseComponentBuffer_(writer, "x_%s^%s", moleFrac_);
+
+        if (massFracOutput_)
+            this->commitPhaseComponentBuffer_(writer, "X_%s^%s", massFrac_);
+
+        if(molarityOutput_)
+            this->commitPhaseComponentBuffer_(writer, "c_%s^%s", molarity_);
+
+        if (velocityOutput_) {
+            int nVerts = this->problem_.gridView().size(dim);
+            for (int phaseIdx = 0; phaseIdx < numPhases; ++phaseIdx) {
+                // first, divide the velocity field by the
+                // respective finite volume's surface area
+                for (int i = 0; i < nVerts; ++i)
+                    velocity_[phaseIdx][i] /= boxSurface_[i];
+                // commit the phase velocity
+                std::ostringstream oss;
+                oss << "velocity_" << FluidSystem::phaseName(phaseIdx);
+                writer.attachVertexData(velocity_[phaseIdx],
+                                        oss.str(),
+                                        dim);
+            }
+        }
+    }
+
+private:
+    bool porosityOutput_;
+    bool boundaryTypesOutput_;
+    bool saturationOutput_;
+    bool pressureOutput_;
+    bool velocityOutput_;
+    bool densityOutput_;
+    bool mobilityOutput_;
+    bool massFracOutput_;
+    bool moleFracOutput_;
+    bool molarityOutput_;
+    bool averageMolarMassOutput_;
+
+    PhaseVector saturation_;
+    PhaseVector pressure_;
+    PhaseVector density_;
+    PhaseVector mobility_;
+    PhaseVector averageMolarMass_;
+
+    PhaseDimField velocity_;
+    ScalarVector boxSurface_;
+
+    ScalarVector porosity_;
+    ScalarVector temperature_;
+    ScalarVector boundaryTypes_;
+
+    PhaseComponentMatrix moleFrac_;
+    PhaseComponentMatrix massFrac_;
+    PhaseComponentMatrix molarity_;
+
+    ComponentVector fugacity_;
+};
+
+}
+
+#endif
diff --git a/dumux/implicit/mpnc/mpncvtkwritermodule.hh b/dumux/implicit/mpnc/mpncvtkwritermodule.hh
new file mode 100644
index 0000000000..061903c030
--- /dev/null
+++ b/dumux/implicit/mpnc/mpncvtkwritermodule.hh
@@ -0,0 +1,256 @@
+// -*- mode: C++; tab-width: 4; indent-tabs-mode: nil; c-basic-offset: 4 -*-
+// vi: set et ts=4 sw=4 sts=4:
+/*****************************************************************************
+ *   See the file COPYING for full copying permissions.                      *
+ *                                                                           *
+ *   This program is free software: you can redistribute it and/or modify    *
+ *   it under the terms of the GNU General Public License as published by    *
+ *   the Free Software Foundation, either version 2 of the License, or       *
+ *   (at your option) any later version.                                     *
+ *                                                                           *
+ *   This program is distributed in the hope that it will be useful,         *
+ *   but WITHOUT ANY WARRANTY; without even the implied warranty of          *
+ *   MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the            *
+ *   GNU General Public License for more details.                            *
+ *                                                                           *
+ *   You should have received a copy of the GNU General Public License       *
+ *   along with this program.  If not, see <http://www.gnu.org/licenses/>.   *
+ *****************************************************************************/
+#ifndef DUMUX_MPNC_VTK_BASE_WRITER_HH
+#define DUMUX_MPNC_VTK_BASE_WRITER_HH
+
+#include <cstdio>
+
+#include <dune/common/array.hh>
+#include <dune/istl/bvector.hh>
+
+#include <dumux/io/vtkmultiwriter.hh>
+#include "mpncproperties.hh"
+
+namespace Dumux
+{
+/*!
+ * \ingroup MPNCModel
+ *
+ * \brief A VTK writer module which adheres to the required API but
+ *        does nothing.
+ *
+ * This class also provides some convenience methods for buffer
+ * management.
+ */
+template<class TypeTag>
+class MPNCVtkWriterModule
+{
+    typedef typename GET_PROP_TYPE(TypeTag, Problem) Problem;
+    typedef typename GET_PROP_TYPE(TypeTag, Scalar) Scalar;
+    typedef typename GET_PROP_TYPE(TypeTag, GridView) GridView;
+    typedef typename GET_PROP_TYPE(TypeTag, FVElementGeometry) FVElementGeometry;
+    typedef typename GET_PROP_TYPE(TypeTag, ElementVolumeVariables) ElementVolumeVariables;
+    typedef typename GET_PROP_TYPE(TypeTag, ElementBoundaryTypes) ElementBoundaryTypes;
+    typedef typename GET_PROP_TYPE(TypeTag, FluidSystem) FluidSystem;
+    typedef typename GridView::template Codim<0>::Entity Element;
+
+    enum { numPhases = GET_PROP_VALUE(TypeTag, NumPhases) };
+    enum { numComponents = GET_PROP_VALUE(TypeTag, NumComponents) };
+    enum { dim             = GridView::dimension };
+
+public:
+    typedef std::vector<Dune::FieldVector<Scalar, 1> > ScalarVector;
+    typedef Dune::array<ScalarVector, numPhases> PhaseVector;
+    typedef Dune::array<ScalarVector, numComponents> ComponentVector;
+    typedef Dune::array<ComponentVector,  numPhases> PhaseComponentMatrix;
+
+    MPNCVtkWriterModule(const Problem &problem)
+        : problem_(problem)
+    {
+    }
+
+    /*!
+     * \brief Allocate memory for the scalar fields we would like to
+     *        write to the VTK file.
+     */
+    template <class MultiWriter>
+    void allocBuffers(MultiWriter &writer)
+    {
+    }
+
+    /*!
+     * \brief Modify the internal buffers according to the volume
+     *        variables seen on an element
+     */
+    void processElement(const Element &elem,
+                        const FVElementGeometry &fvGeometry,
+                        const ElementVolumeVariables &elemCurVolVars,
+                        const ElementBoundaryTypes &elemBcTypes)
+    {
+    }
+
+    /*!
+     * \brief Add all buffers to the VTK output writer.
+     */
+    template <class MultiWriter>
+    void commitBuffers(MultiWriter &writer)
+    {
+    }
+
+protected:
+    /*!
+     * \brief Allocate the space for a buffer storing a scalar quantity
+     */
+    void resizeScalarBuffer_(ScalarVector &buffer,
+                             bool vertexCentered = true)
+    {
+        Scalar n; // numVertices for vertexCentereed, numVolumes for volume centered
+        if (vertexCentered)
+            n = problem_.gridView().size(dim);
+        else
+            n = problem_.gridView().size(0);
+
+        buffer.resize(n);
+        std::fill(buffer.begin(), buffer.end(), 0.0);
+    }
+
+    /*!
+     * \brief Allocate the space for a buffer storing a phase-specific
+     *        quantity
+     */
+    void resizePhaseBuffer_(PhaseVector &buffer,
+                            bool vertexCentered = true)
+    {
+        Scalar n; // numVertices for vertexCentereed, numVolumes for volume centered
+        if (vertexCentered)
+            n = problem_.gridView().size(dim);
+        else
+            n = problem_.gridView().size(0);
+
+        for (int phaseIdx = 0; phaseIdx < numPhases; ++phaseIdx) {
+            buffer[phaseIdx].resize(n);
+            std::fill(buffer[phaseIdx].begin(), buffer[phaseIdx].end(), 0.0);
+        }
+    }
+
+    /*!
+     * \brief Allocate the space for a buffer storing a component
+     *        specific quantity
+     */
+    void resizeComponentBuffer_(ComponentVector &buffer,
+                                bool vertexCentered = true)
+    {
+        Scalar n;// numVertices for vertexCentereed, numVolumes for volume centered
+        if (vertexCentered)
+            n = problem_.gridView().size(dim);
+        else
+            n = problem_.gridView().size(0);
+
+        for (int compIdx = 0; compIdx < numComponents; ++compIdx) {
+            buffer[compIdx].resize(n);
+            std::fill(buffer[compIdx].begin(), buffer[compIdx].end(), 0.0);
+        }
+    }
+
+    /*!
+     * \brief Allocate the space for a buffer storing a phase and
+     *        component specific buffer
+     */
+    void resizePhaseComponentBuffer_(PhaseComponentMatrix &buffer,
+                                     bool vertexCentered = true)
+    {
+        Scalar n;// numVertices for vertexCentereed, numVolumes for volume centered
+        if (vertexCentered)
+            n = problem_.gridView().size(dim);
+        else
+            n = problem_.gridView().size(0);
+
+        for (int phaseIdx = 0; phaseIdx < numPhases; ++phaseIdx) {
+            for (int compIdx = 0; compIdx < numComponents; ++compIdx) {
+                buffer[phaseIdx][compIdx].resize(n);
+                std::fill(buffer[phaseIdx][compIdx].begin(), buffer[phaseIdx][compIdx].end(), 0.0);
+            }
+        }
+    }
+
+    /*!
+     * \brief Add a phase-specific buffer to the VTK result file.
+     */
+    template <class MultiWriter>
+    void commitScalarBuffer_(MultiWriter &writer,
+                             const char *name,
+                             ScalarVector &buffer,
+                             bool vertexCentered = true)
+    {
+        if (vertexCentered)
+            writer.attachVertexData(buffer, name, 1);
+        else
+            writer.attachCellData(buffer, name, 1);
+    }
+
+    /*!
+     * \brief Add a phase-specific buffer to the VTK result file.
+     */
+    template <class MultiWriter>
+    void commitPhaseBuffer_(MultiWriter &writer,
+                            const char *pattern,
+                            PhaseVector &buffer,
+                            bool vertexCentered = true)
+    {
+        char name[512];
+        for (int phaseIdx = 0; phaseIdx < numPhases; ++phaseIdx) {
+            snprintf(name, 512, pattern, FluidSystem::phaseName(phaseIdx));
+
+            if (vertexCentered)
+                writer.attachVertexData(buffer[phaseIdx], name, 1);
+            else
+                writer.attachCellData(buffer[phaseIdx], name, 1);
+        }
+    }
+
+    /*!
+     * \brief Add a component-specific buffer to the VTK result file.
+     */
+    template <class MultiWriter>
+    void commitComponentBuffer_(MultiWriter &writer,
+                                const char *pattern,
+                                ComponentVector &buffer,
+                                bool vertexCentered = true)
+    {
+        char name[512];
+        for (int compIdx = 0; compIdx < numComponents; ++compIdx) {
+            snprintf(name, 512, pattern, FluidSystem::componentName(compIdx));
+
+            if (vertexCentered)
+                writer.attachVertexData(buffer[compIdx], name, 1);
+            else
+                writer.attachCellData(buffer[compIdx], name, 1);
+        }
+    }
+
+    /*!
+     * \brief Add a phase and component specific quantities to the output.
+     */
+    template <class MultiWriter>
+    void commitPhaseComponentBuffer_(MultiWriter &writer,
+                                     const char *pattern,
+                                     PhaseComponentMatrix &buffer,
+                                     bool vertexCentered = true)
+    {
+        char name[512];
+        for (int phaseIdx= 0; phaseIdx < numPhases; ++phaseIdx) {
+            for (int compIdx = 0; compIdx < numComponents; ++compIdx) {
+                snprintf(name, 512, pattern,
+                         FluidSystem::phaseName(phaseIdx),
+                         FluidSystem::componentName(compIdx));
+
+                if (vertexCentered)
+                    writer.attachVertexData(buffer[phaseIdx][compIdx], name, 1);
+                else
+                    writer.attachCellData(buffer[phaseIdx][compIdx], name, 1);
+            }
+        }
+    }
+
+    const Problem &problem_;
+};
+
+}
+
+#endif
diff --git a/dumux/implicit/richards/Makefile.am b/dumux/implicit/richards/Makefile.am
new file mode 100644
index 0000000000..26a58204fb
--- /dev/null
+++ b/dumux/implicit/richards/Makefile.am
@@ -0,0 +1,4 @@
+richardsdir = $(includedir)/dumux/boxmodels/richards
+richards_HEADERS = *.hh
+
+include $(top_srcdir)/am/global-rules
diff --git a/dumux/implicit/richards/richardsindices.hh b/dumux/implicit/richards/richardsindices.hh
new file mode 100644
index 0000000000..47e341a02a
--- /dev/null
+++ b/dumux/implicit/richards/richardsindices.hh
@@ -0,0 +1,67 @@
+// -*- mode: C++; tab-width: 4; indent-tabs-mode: nil; c-basic-offset: 4 -*-
+// vi: set et ts=4 sw=4 sts=4:
+/*****************************************************************************
+ *   See the file COPYING for full copying permissions.                      *
+ *                                                                           *
+ *   This program is free software: you can redistribute it and/or modify    *
+ *   it under the terms of the GNU General Public License as published by    *
+ *   the Free Software Foundation, either version 2 of the License, or       *
+ *   (at your option) any later version.                                     *
+ *                                                                           *
+ *   This program is distributed in the hope that it will be useful,         *
+ *   but WITHOUT ANY WARRANTY; without even the implied warranty of          *
+ *   MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the            *
+ *   GNU General Public License for more details.                            *
+ *                                                                           *
+ *   You should have received a copy of the GNU General Public License       *
+ *   along with this program.  If not, see <http://www.gnu.org/licenses/>.   *
+ *****************************************************************************/
+/*!
+ * \file
+ *
+ * \brief Index names for the Richards model.
+ */
+#ifndef DUMUX_RICHARDS_INDICES_HH
+#define DUMUX_RICHARDS_INDICES_HH
+
+#include "richardsproperties.hh"
+
+namespace Dumux
+{
+// \{
+
+/*!
+ * \ingroup RichardsModel
+ * \ingroup BoxIndices
+ * \brief Index names for the Richards model.
+ */
+
+template <class TypeTag>
+struct RichardsIndices
+{
+    typedef typename GET_PROP_TYPE(TypeTag, FluidSystem) FluidSystem;
+    
+    //////////
+    // primary variable indices
+    //////////
+    
+    //! Primary variable index for the wetting phase pressure
+    static const int pwIdx = 0;
+    
+    //////////
+    // equation indices
+    //////////
+    //! Equation index for the mass conservation of the wetting phase
+    static const int contiEqIdx = 0;
+    
+    //////////
+    // phase indices
+    //////////
+    static const int wPhaseIdx = FluidSystem::wPhaseIdx; //!< Index of the wetting phase;
+    static const int nPhaseIdx = FluidSystem::nPhaseIdx; //!< Index of the non-wetting phase;
+};
+// \}
+
+} // end namepace
+
+#endif
diff --git a/dumux/implicit/richards/richardslocalresidual.hh b/dumux/implicit/richards/richardslocalresidual.hh
new file mode 100644
index 0000000000..b1064f54c0
--- /dev/null
+++ b/dumux/implicit/richards/richardslocalresidual.hh
@@ -0,0 +1,158 @@
+// -*- mode: C++; tab-width: 4; indent-tabs-mode: nil; c-basic-offset: 4 -*-
+// vi: set et ts=4 sw=4 sts=4:
+/*****************************************************************************
+ *   See the file COPYING for full copying permissions.                      *
+ *                                                                           *
+ *   This program is free software: you can redistribute it and/or modify    *
+ *   it under the terms of the GNU General Public License as published by    *
+ *   the Free Software Foundation, either version 2 of the License, or       *
+ *   (at your option) any later version.                                     *
+ *                                                                           *
+ *   This program is distributed in the hope that it will be useful,         *
+ *   but WITHOUT ANY WARRANTY; without even the implied warranty of          *
+ *   MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the            *
+ *   GNU General Public License for more details.                            *
+ *                                                                           *
+ *   You should have received a copy of the GNU General Public License       *
+ *   along with this program.  If not, see <http://www.gnu.org/licenses/>.   *
+ *****************************************************************************/
+/*!
+ * \file
+ *
+ * \brief Element-wise calculation of the residual for the Richards box model.
+ */
+#ifndef DUMUX_RICHARDS_LOCAL_RESIDUAL_HH
+#define DUMUX_RICHARDS_LOCAL_RESIDUAL_HH
+
+#include <dumux/boxmodels/common/boxlocalresidual.hh>
+
+#include "richardsvolumevariables.hh"
+
+namespace Dumux
+{
+/*!
+ * \ingroup RichardsModel
+ * \ingroup BoxLocalResidual
+ * \brief Element-wise calculation of the residual for the Richards box model.
+ */
+template<class TypeTag>
+class RichardsLocalResidual : public GET_PROP_TYPE(TypeTag, BaseLocalResidual)
+{
+    typedef typename GET_PROP_TYPE(TypeTag, PrimaryVariables) PrimaryVariables;
+    typedef typename GET_PROP_TYPE(TypeTag, VolumeVariables) VolumeVariables;
+    typedef typename GET_PROP_TYPE(TypeTag, FluxVariables) FluxVariables;
+
+    typedef typename GET_PROP_TYPE(TypeTag, Indices) Indices;
+    enum {
+        contiEqIdx = Indices::contiEqIdx,
+        wPhaseIdx = Indices::wPhaseIdx
+    };
+
+    typedef typename GET_PROP_TYPE(TypeTag, GridView) GridView;
+    enum { dim = GridView::dimension};
+
+    typedef typename GET_PROP_TYPE(TypeTag, Scalar) Scalar;
+    typedef Dune::FieldVector<Scalar, dim> DimVector;
+
+public:
+    /*!
+     * \brief Constructor. Sets the upwind weight.
+     */
+    RichardsLocalResidual()
+    {
+        // retrieve the upwind weight for the mass conservation equations. Use the value
+        // specified via the property system as default, and overwrite
+        // it by the run-time parameter from the Dune::ParameterTree
+        massUpwindWeight_ = GET_PARAM_FROM_GROUP(TypeTag, Scalar, Implicit, MassUpwindWeight);
+    };
+
+    /*!
+     * \brief Evaluate the rate of change of all conservation
+     *        quantites (e.g. phase mass) within a sub control
+     *        volume of a finite volume element for the Richards
+     *        model.
+     *
+     * This function should not include the source and sink terms.
+     *
+     * \param storage Stores the average mass per unit volume for each phase \f$\mathrm{[kg/m^3]}\f$
+     * \param scvIdx The sub control volume index of the current element
+     * \param usePrevSol Calculate the storage term of the previous solution
+     *                   instead of the model's current solution.
+     */
+    void computeStorage(PrimaryVariables &storage, const int scvIdx, bool usePrevSol) const
+    {
+        // if flag usePrevSol is set, the solution from the previous
+        // time step is used, otherwise the current solution is
+        // used. The secondary variables are used accordingly.  This
+        // is required to compute the derivative of the storage term
+        // using the implicit euler method.
+        const VolumeVariables &volVars =
+            usePrevSol ?
+            this->prevVolVars_(scvIdx) :
+            this->curVolVars_(scvIdx);
+
+        // partial time derivative of the wetting phase mass
+        storage[contiEqIdx] =
+            volVars.density(wPhaseIdx)
+            * volVars.saturation(wPhaseIdx)
+            * volVars.porosity();
+    }
+
+
+    /*!
+     * \brief Evaluates the mass flux over a face of a subcontrol
+     *        volume.
+     *
+     * \param flux Stores the total mass fluxes over a sub-control volume face
+     *             of the current element \f$\mathrm{[kg/s]}\f$
+     * \param faceIdx The sub control volume face index inside the current
+     *                element
+     * \param onBoundary A boolean variable to specify whether the flux variables
+     *        are calculated for interior SCV faces or boundary faces, default=false
+     */
+    void computeFlux(PrimaryVariables &flux, const int faceIdx, bool onBoundary=false) const
+    {
+        FluxVariables fluxVars(this->problem_(),
+                               this->element_(),
+                               this->fvGeometry_(),
+                               faceIdx,
+                               this->curVolVars_(),
+                               onBoundary);
+
+        // data attached to upstream and the downstream vertices
+        // of the current phase
+        const VolumeVariables &up = this->curVolVars_(fluxVars.upstreamIdx(wPhaseIdx));
+        const VolumeVariables &dn = this->curVolVars_(fluxVars.downstreamIdx(wPhaseIdx));
+
+        flux[contiEqIdx] =
+            fluxVars.volumeFlux(wPhaseIdx)
+            *
+            ((    massUpwindWeight_)*up.density(wPhaseIdx)
+             +
+             (1 - massUpwindWeight_)*dn.density(wPhaseIdx));
+    }
+
+    /*!
+     * \brief Calculate the source term of the equation
+     *
+     * \param source Stores the average source term of all phases inside a
+     *          sub-control volume of the current element \f$\mathrm{[kg/(m^3 * s)]}\f$
+     * \param scvIdx The sub control volume index inside the current
+     *               element
+     */
+    void computeSource(PrimaryVariables &source, const int scvIdx)
+    {
+        this->problem_().boxSDSource(source,
+                                     this->element_(),
+                                     this->fvGeometry_(),
+                                     scvIdx,
+                                     this->curVolVars_());
+    }
+
+private:
+    Scalar massUpwindWeight_;
+};
+
+}
+
+#endif
diff --git a/dumux/implicit/richards/richardsmodel.hh b/dumux/implicit/richards/richardsmodel.hh
new file mode 100644
index 0000000000..ff71be4f6f
--- /dev/null
+++ b/dumux/implicit/richards/richardsmodel.hh
@@ -0,0 +1,208 @@
+// -*- mode: C++; tab-width: 4; indent-tabs-mode: nil; c-basic-offset: 4 -*-
+// vi: set et ts=4 sw=4 sts=4:
+/*****************************************************************************
+ *   See the file COPYING for full copying permissions.                      *
+ *                                                                           *
+ *   This program is free software: you can redistribute it and/or modify    *
+ *   it under the terms of the GNU General Public License as published by    *
+ *   the Free Software Foundation, either version 2 of the License, or       *
+ *   (at your option) any later version.                                     *
+ *                                                                           *
+ *   This program is distributed in the hope that it will be useful,         *
+ *   but WITHOUT ANY WARRANTY; without even the implied warranty of          *
+ *   MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the            *
+ *   GNU General Public License for more details.                            *
+ *                                                                           *
+ *   You should have received a copy of the GNU General Public License       *
+ *   along with this program.  If not, see <http://www.gnu.org/licenses/>.   *
+ *****************************************************************************/
+
+/*!
+* \file
+*
+* \brief Adaption of the box scheme to the Richards model.
+*/
+#ifndef DUMUX_RICHARDS_MODEL_HH
+#define DUMUX_RICHARDS_MODEL_HH
+
+#include <dumux/boxmodels/common/boxmodel.hh>
+
+#include "richardslocalresidual.hh"
+#include "richardsproblem.hh"
+
+namespace Dumux
+{
+/*!
+ * \ingroup RichardsModel
+ *
+ * \brief This model which implements a variant of the Richards'
+ *        equation for quasi-twophase flow.
+ *
+ * In the unsaturated zone, Richards' equation
+ \f[
+ \frac{\partial\;\phi S_w \rho_w}{\partial t}
+ -
+ \text{div} \left(
+ \rho_w \frac{k_{rw}}{\mu_w} \; \mathbf{K} \;
+ \text{\textbf{grad}}\left(
+ p_w - g\rho_w
+ \right)
+ \right)
+ =
+ q_w,
+ \f]
+ * is frequently used to
+ * approximate the water distribution above the groundwater level.
+ * 
+ * It can be derived from the two-phase equations, i.e.
+ \f[
+ \frac{\partial\;\phi S_\alpha \rho_\alpha}{\partial t}
+ -
+ \text{div} \left(
+ \rho_\alpha \frac{k_{r\alpha}}{\mu_\alpha}\; \mathbf{K} \;
+ \text{\textbf{grad}}\left(
+ p_\alpha - g\rho_\alpha
+ \right)
+ \right)
+ =
+ q_\alpha,
+ \f]
+ * where \f$\alpha \in \{w, n\}\f$ is the fluid phase,
+ * \f$\rho_\alpha\f$ is the fluid density, \f$S_\alpha\f$ is the fluid
+ * saturation, \f$\phi\f$ is the porosity of the soil,
+ * \f$k_{r\alpha}\f$ is the relative permeability for the fluid,
+ * \f$\mu_\alpha\f$ is the fluid's dynamic viscosity, \f$\mathbf{K}\f$ is the
+ * intrinsic permeability, \f$p_\alpha\f$ is the fluid pressure and
+ * \f$g\f$ is the potential of the gravity field.
+ *
+ * In contrast to the full two-phase model, the Richards model assumes
+ * gas as the non-wetting fluid and that it exhibits a much lower
+ * viscosity than the (liquid) wetting phase. (For example at
+ * atmospheric pressure and at room temperature, the viscosity of air
+ * is only about \f$1\%\f$ of the viscosity of liquid water.) As a
+ * consequence, the \f$\frac{k_{r\alpha}}{\mu_\alpha}\f$ term
+ * typically is much larger for the gas phase than for the wetting
+ * phase. For this reason, the Richards model assumes that
+ * \f$\frac{k_{rn}}{\mu_n}\f$ is infinitly large. This implies that
+ * the pressure of the gas phase is equivalent to the static pressure
+ * distribution and that therefore, mass conservation only needs to be
+ * considered for the wetting phase.
+ *
+ * The model thus choses the absolute pressure of the wetting phase
+ * \f$p_w\f$ as its only primary variable. The wetting phase
+ * saturation is calculated using the inverse of the capillary
+ * pressure, i.e.
+ \f[
+ S_w = p_c^{-1}(p_n - p_w)
+ \f]
+ * holds, where \f$p_n\f$ is a given reference pressure. Nota bene,
+ * that the last step is assumes that the capillary
+ * pressure-saturation curve can be uniquely inverted, so it is not
+ * possible to set the capillary pressure to zero when using the
+ * Richards model!
+ */
+template<class TypeTag >
+class RichardsModel : public GET_PROP_TYPE(TypeTag, BaseModel)
+{
+    typedef typename GET_PROP_TYPE(TypeTag, Scalar) Scalar;
+    typedef typename GET_PROP_TYPE(TypeTag, FVElementGeometry) FVElementGeometry;
+    typedef typename GET_PROP_TYPE(TypeTag, VolumeVariables) VolumeVariables;
+    typedef typename GET_PROP_TYPE(TypeTag, SolutionVector) SolutionVector;
+
+    typedef typename GET_PROP_TYPE(TypeTag, Indices) Indices;
+    enum {
+        nPhaseIdx = Indices::nPhaseIdx,
+        wPhaseIdx = Indices::wPhaseIdx
+    };
+
+    typedef typename GET_PROP_TYPE(TypeTag, GridView) GridView;
+    typedef typename GridView::template Codim<0>::Iterator ElementIterator;
+    enum { dim = GridView::dimension };
+
+public:
+    /*!
+     * \brief All relevant primary and secondary of a given
+     *        solution to an ouput writer.
+     *
+     * \param sol The current solution which ought to be written to disk
+     * \param writer The Dumux::VtkMultiWriter which is be used to write the data
+     */
+    template <class MultiWriter>
+    void addOutputVtkFields(const SolutionVector &sol, MultiWriter &writer)
+    {
+        typedef Dune::BlockVector<Dune::FieldVector<double, 1> > ScalarField;
+
+        // create the required scalar fields
+        unsigned numVertices = this->problem_().gridView().size(dim);
+        ScalarField *pW = writer.allocateManagedBuffer(numVertices);
+        ScalarField *pN = writer.allocateManagedBuffer(numVertices);
+        ScalarField *pC = writer.allocateManagedBuffer(numVertices);
+        ScalarField *Sw = writer.allocateManagedBuffer(numVertices);
+        ScalarField *Sn = writer.allocateManagedBuffer(numVertices);
+        ScalarField *rhoW = writer.allocateManagedBuffer(numVertices);
+        ScalarField *rhoN = writer.allocateManagedBuffer(numVertices);
+        ScalarField *mobW = writer.allocateManagedBuffer(numVertices);
+        ScalarField *mobN = writer.allocateManagedBuffer(numVertices);
+        ScalarField *poro = writer.allocateManagedBuffer(numVertices);
+        ScalarField *Te = writer.allocateManagedBuffer(numVertices);
+
+        unsigned numElements = this->gridView_().size(0);
+        ScalarField *rank =
+                writer.allocateManagedBuffer (numElements);
+
+        FVElementGeometry fvElemGeom;
+        VolumeVariables volVars;
+
+        ElementIterator elemIt = this->gridView_().template begin<0>();
+        ElementIterator elemEndIt = this->gridView_().template end<0>();
+        for (; elemIt != elemEndIt; ++elemIt)
+        {
+            int idx = this->problem_().model().elementMapper().map(*elemIt);
+            (*rank)[idx] = this->gridView_().comm().rank();
+
+            fvElemGeom.update(this->gridView_(), *elemIt);
+
+            int numVerts = elemIt->template count<dim> ();
+            for (int i = 0; i < numVerts; ++i)
+            {
+                int globalIdx = this->vertexMapper().map(*elemIt, i, dim);
+                volVars.update(sol[globalIdx],
+                               this->problem_(),
+                               *elemIt,
+                               fvElemGeom,
+                               i,
+                               false);
+
+                (*pW)[globalIdx] = volVars.pressure(wPhaseIdx);
+                (*pN)[globalIdx] = volVars.pressure(nPhaseIdx);
+                (*pC)[globalIdx] = volVars.capillaryPressure();
+                (*Sw)[globalIdx] = volVars.saturation(wPhaseIdx);
+                (*Sn)[globalIdx] = volVars.saturation(nPhaseIdx);
+                (*rhoW)[globalIdx] = volVars.density(wPhaseIdx);
+                (*rhoN)[globalIdx] = volVars.density(nPhaseIdx);
+                (*mobW)[globalIdx] = volVars.mobility(wPhaseIdx);
+                (*mobN)[globalIdx] = volVars.mobility(nPhaseIdx);
+                (*poro)[globalIdx] = volVars.porosity();
+                (*Te)[globalIdx] = volVars.temperature();
+            }
+        }
+
+        writer.attachVertexData(*Sn, "Sn");
+        writer.attachVertexData(*Sw, "Sw");
+        writer.attachVertexData(*pN, "pn");
+        writer.attachVertexData(*pW, "pw");
+        writer.attachVertexData(*pC, "pc");
+        writer.attachVertexData(*rhoW, "rhoW");
+        writer.attachVertexData(*rhoN, "rhoN");
+        writer.attachVertexData(*mobW, "mobW");
+        writer.attachVertexData(*mobN, "mobN");
+        writer.attachVertexData(*poro, "porosity");
+        writer.attachVertexData(*Te, "temperature");
+        writer.attachCellData(*rank, "process rank");
+    }
+};
+}
+
+#include "richardspropertydefaults.hh"
+
+#endif
diff --git a/dumux/implicit/richards/richardsnewtoncontroller.hh b/dumux/implicit/richards/richardsnewtoncontroller.hh
new file mode 100644
index 0000000000..635f6a6288
--- /dev/null
+++ b/dumux/implicit/richards/richardsnewtoncontroller.hh
@@ -0,0 +1,125 @@
+// -*- mode: C++; tab-width: 4; indent-tabs-mode: nil; c-basic-offset: 4 -*-
+// vi: set et ts=4 sw=4 sts=4:
+/*****************************************************************************
+ *   See the file COPYING for full copying permissions.                      *
+ *                                                                           *
+ *   This program is free software: you can redistribute it and/or modify    *
+ *   it under the terms of the GNU General Public License as published by    *
+ *   the Free Software Foundation, either version 2 of the License, or       *
+ *   (at your option) any later version.                                     *
+ *                                                                           *
+ *   This program is distributed in the hope that it will be useful,         *
+ *   but WITHOUT ANY WARRANTY; without even the implied warranty of          *
+ *   MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the            *
+ *   GNU General Public License for more details.                            *
+ *                                                                           *
+ *   You should have received a copy of the GNU General Public License       *
+ *   along with this program.  If not, see <http://www.gnu.org/licenses/>.   *
+ *****************************************************************************/
+/*!
+ * \file
+ * \brief A newton solver specific to the Richards problem.
+ */
+#ifndef DUMUX_RICHARDS_NEWTON_CONTROLLER_HH
+#define DUMUX_RICHARDS_NEWTON_CONTROLLER_HH
+
+#include "richardsproperties.hh"
+
+#include <dumux/nonlinear/newtoncontroller.hh>
+
+namespace Dumux {
+/*!
+ * \ingroup Newton
+ * \brief A Richards model specific controller for the newton solver.
+ *
+ * This controller 'knows' what a 'physically meaningful' solution is
+ * and can thus do update smarter than the plain Newton controller.
+ */
+template <class TypeTag>
+class RichardsNewtonController : public NewtonController<TypeTag>
+{
+    typedef NewtonController<TypeTag> ParentType;
+
+    typedef typename GET_PROP_TYPE(TypeTag, Scalar) Scalar;
+    typedef typename GET_PROP_TYPE(TypeTag, SolutionVector) SolutionVector;
+    typedef typename GET_PROP_TYPE(TypeTag, SpatialParams) SpatialParams;
+    typedef typename GET_PROP_TYPE(TypeTag, FVElementGeometry) FVElementGeometry;
+    typedef typename GET_PROP_TYPE(TypeTag, MaterialLaw) MaterialLaw;
+    typedef typename GET_PROP_TYPE(TypeTag, MaterialLawParams) MaterialLawParams;
+    typedef typename GET_PROP_TYPE(TypeTag, Problem) Problem;
+
+    typedef typename GET_PROP_TYPE(TypeTag, Indices) Indices;
+    enum { pwIdx = Indices::pwIdx };
+
+    typedef typename GET_PROP_TYPE(TypeTag, GridView) GridView;
+    typedef typename GridView::template Codim<0>::Iterator ElementIterator;
+    enum { dim = GridView::dimension };
+public:
+    /*!
+     * \brief Constructor
+     */
+    RichardsNewtonController(const Problem &problem)
+        : ParentType(problem)
+    {}
+
+    /*!
+     * \brief Update the current solution of the newton method
+     *
+     * This is basically the step
+     * \f[ u^{k+1} = u^k - \Delta u^k \f]
+     *
+     * \param uCurrentIter The solution after the current Newton iteration \f$ u^{k+1} \f$
+     * \param uLastIter The solution after the last Newton iteration \f$ u^k \f$
+     * \param deltaU The vector of differences between the last
+     *               iterative solution and the next one \f$ \Delta u^k \f$
+     */
+    void newtonUpdate(SolutionVector &uCurrentIter,
+                      const SolutionVector &uLastIter,
+                      const SolutionVector &deltaU)
+    {
+        ParentType::newtonUpdate(uCurrentIter, uLastIter, deltaU);
+
+        if (!GET_PARAM_FROM_GROUP(TypeTag, bool, Newton, UseLineSearch))
+        {
+            // do not clamp anything after 5 iterations
+            if (this->numSteps_ > 4)
+                return;
+
+            // clamp saturation change to at most 20% per iteration
+            FVElementGeometry fvGeometry;
+            const GridView &gridView = this->problem_().gridView();
+            ElementIterator elemIt = gridView.template begin<0>();
+            const ElementIterator elemEndIt = gridView.template end<0>();
+            for (; elemIt != elemEndIt; ++elemIt) {
+                fvGeometry.update(gridView, *elemIt);
+                for (int i = 0; i < fvGeometry.numSCV; ++i) {
+                    int globI = this->problem_().vertexMapper().map(*elemIt, i, dim);
+
+                    // calculate the old wetting phase saturation
+                    const SpatialParams &spatialParams = this->problem_().spatialParams();
+                    const MaterialLawParams &mp = spatialParams.materialLawParams(*elemIt, fvGeometry, i);
+                    Scalar pcMin = MaterialLaw::pC(mp, 1.0);
+                    Scalar pW = uLastIter[globI][pwIdx];
+                    Scalar pN = std::max(this->problem_().referencePressure(*elemIt, fvGeometry, i),
+                                         pW + pcMin);
+                    Scalar pcOld = pN - pW;
+                    Scalar SwOld = std::max<Scalar>(0.0, MaterialLaw::Sw(mp, pcOld));
+
+                    // convert into minimum and maximum wetting phase
+                    // pressures
+                    Scalar pwMin = pN - MaterialLaw::pC(mp, SwOld - 0.2);
+                    Scalar pwMax = pN - MaterialLaw::pC(mp, SwOld + 0.2);
+
+                    // clamp the result
+                    pW = uCurrentIter[globI][pwIdx];
+                    pW = std::max(pwMin, std::min(pW, pwMax));
+                    uCurrentIter[globI][pwIdx] = pW;
+
+                }
+            }
+        }
+    }
+};
+}
+
+#endif
diff --git a/dumux/implicit/richards/richardsproblem.hh b/dumux/implicit/richards/richardsproblem.hh
new file mode 100644
index 0000000000..99fcf05746
--- /dev/null
+++ b/dumux/implicit/richards/richardsproblem.hh
@@ -0,0 +1,92 @@
+// -*- mode: C++; tab-width: 4; indent-tabs-mode: nil; c-basic-offset: 4 -*-
+// vi: set et ts=4 sw=4 sts=4:
+/*****************************************************************************
+ *   See the file COPYING for full copying permissions.                      *
+ *                                                                           *
+ *   This program is free software: you can redistribute it and/or modify    *
+ *   it under the terms of the GNU General Public License as published by    *
+ *   the Free Software Foundation, either version 2 of the License, or       *
+ *   (at your option) any later version.                                     *
+ *                                                                           *
+ *   This program is distributed in the hope that it will be useful,         *
+ *   but WITHOUT ANY WARRANTY; without even the implied warranty of          *
+ *   MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the            *
+ *   GNU General Public License for more details.                            *
+ *                                                                           *
+ *   You should have received a copy of the GNU General Public License       *
+ *   along with this program.  If not, see <http://www.gnu.org/licenses/>.   *
+ *****************************************************************************/
+/*!
+ * \file
+ * \brief Base class for all problems which use the box scheme
+ */
+#ifndef DUMUX_RICHARDS_PROBLEM_HH
+#define DUMUX_RICHARDS_PROBLEM_HH
+
+#include <dumux/boxmodels/common/porousmediaboxproblem.hh>
+
+#include "richardsproperties.hh"
+
+namespace Dumux
+{
+/*!
+ * \ingroup RichardsModel
+ * \ingroup BoxBaseProblems
+ * \brief Base class for all problems which use the two-phase box model
+ *
+ * For a description of the Richards model, see Dumux::RichardsModel
+ */
+template<class TypeTag>
+class RichardsBoxProblem : public PorousMediaBoxProblem<TypeTag>
+{
+    typedef PorousMediaBoxProblem<TypeTag> ParentType;
+
+    typedef typename GET_PROP_TYPE(TypeTag, TimeManager) TimeManager;
+    typedef typename GET_PROP_TYPE(TypeTag, FVElementGeometry) FVElementGeometry;
+    typedef typename GET_PROP_TYPE(TypeTag, Scalar) Scalar;
+    typedef typename GET_PROP_TYPE(TypeTag, GridView) GridView;
+    typedef typename GridView::template Codim<0>::Entity Element;
+
+public:
+    /*!
+     * \brief The constructor.
+     *
+     * The overloaded class must allocate all data structures
+     * required, but _must not_ do any calls to the model, the
+     * jacobian assembler, etc inside the constructor.
+     *
+     * If the problem requires information from these, the
+     * BoxProblem::init() method be overloaded.
+     *
+     * \param timeManager The TimeManager which keeps track of time
+     * \param gridView The GridView used by the problem.
+     */
+    RichardsBoxProblem(TimeManager &timeManager, const GridView &gridView)
+    : ParentType(timeManager, gridView)
+    {}
+
+    /*!
+     * \name Problem parameters
+     */
+    // \{
+    /*!
+     * \brief Returns the reference pressure \f$\mathrm{[Pa]}\f$ of the non-wetting
+     *        phase within a control volume.
+     *
+     * This method MUST be overwritten by the actual problem.
+     *
+     * \param element The DUNE Codim<0> enitiy which intersects with
+     *                the finite volume.
+     * \param fvGeometry The finite volume geometry of the element.
+     * \param scvIdx     The local index of the sub control volume inside the element
+     */
+    Scalar referencePressure(const Element &element,
+                             const FVElementGeometry fvGeometry,
+                             const int scvIdx) const
+    { DUNE_THROW(Dune::NotImplemented, "referencePressure() method not implemented by the actual problem"); };
+    // \}
+};
+
+}
+
+#endif
diff --git a/dumux/implicit/richards/richardsproperties.hh b/dumux/implicit/richards/richardsproperties.hh
new file mode 100644
index 0000000000..fb1f3bd65b
--- /dev/null
+++ b/dumux/implicit/richards/richardsproperties.hh
@@ -0,0 +1,70 @@
+// -*- mode: C++; tab-width: 4; indent-tabs-mode: nil; c-basic-offset: 4 -*-
+// vi: set et ts=4 sw=4 sts=4:
+/*****************************************************************************
+ *   See the file COPYING for full copying permissions.                      *
+ *                                                                           *
+ *   This program is free software: you can redistribute it and/or modify    *
+ *   it under the terms of the GNU General Public License as published by    *
+ *   the Free Software Foundation, either version 2 of the License, or       *
+ *   (at your option) any later version.                                     *
+ *                                                                           *
+ *   This program is distributed in the hope that it will be useful,         *
+ *   but WITHOUT ANY WARRANTY; without even the implied warranty of          *
+ *   MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the            *
+ *   GNU General Public License for more details.                            *
+ *                                                                           *
+ *   You should have received a copy of the GNU General Public License       *
+ *   along with this program.  If not, see <http://www.gnu.org/licenses/>.   *
+ *****************************************************************************/
+/*!
+ * \ingroup Properties
+ * \ingroup BoxProperties
+ * \ingroup RichardsModel
+ * \file
+ *
+ * \brief Contains the property declarations for the Richards box
+ *        model.
+ */
+#ifndef DUMUX_RICHARDS_PROPERTIES_HH
+#define DUMUX_RICHARDS_PROPERTIES_HH
+
+#include <dumux/boxmodels/common/boxproperties.hh>
+
+namespace Dumux
+{
+// \{
+///////////////////////////////////////////////////////////////////////////
+// properties for the isothermal richards model
+///////////////////////////////////////////////////////////////////////////
+namespace Properties {
+
+//////////////////////////////////////////////////////////////////
+// Type tags
+//////////////////////////////////////////////////////////////////
+
+//! The type tag for problems discretized using the Richards model
+NEW_TYPE_TAG(BoxRichards, INHERITS_FROM(BoxModel));
+
+//////////////////////////////////////////////////////////////////
+// Property tags
+//////////////////////////////////////////////////////////////////
+
+NEW_PROP_TAG(NumPhases);   //!< Number of fluid phases in the system
+NEW_PROP_TAG(Indices); //!< Enumerations used by the model
+NEW_PROP_TAG(SpatialParams); //!< The type of the spatial parameters
+NEW_PROP_TAG(MaterialLaw);   //!< The material law which ought to be used (by default extracted from the spatial parameters)
+NEW_PROP_TAG(MaterialLawParams); //!< The type of the parameter object for the material law (by default extracted from the spatial parameters)
+NEW_PROP_TAG(FluidSystem); //!< The fluid system to be used for the Richards model
+NEW_PROP_TAG(WettingPhase); //!< Fluid which represents the wetting phase
+NEW_PROP_TAG(NonwettingPhase); //!< Fluid which represents the non-wetting phase
+NEW_PROP_TAG(ProblemEnableGravity); //!< Returns whether gravity is considered in the problem
+NEW_PROP_TAG(ImplicitMassUpwindWeight); //!< The value of the weight of the upwind direction in the mass conservation equations
+NEW_PROP_TAG(ImplicitMobilityUpwindWeight); //!< The value of the weight for the upwind mobility in the velocity calculation
+NEW_PROP_TAG(SpatialParamsForchCoeff); //!< Property for the forchheimer coefficient
+
+// \}
+}
+
+} // end namepace
+
+#endif
diff --git a/dumux/implicit/richards/richardspropertydefaults.hh b/dumux/implicit/richards/richardspropertydefaults.hh
new file mode 100644
index 0000000000..e7b6df30d4
--- /dev/null
+++ b/dumux/implicit/richards/richardspropertydefaults.hh
@@ -0,0 +1,168 @@
+// -*- mode: C++; tab-width: 4; indent-tabs-mode: nil; c-basic-offset: 4 -*-
+// vi: set et ts=4 sw=4 sts=4:
+/*****************************************************************************
+ *   See the file COPYING for full copying permissions.                      *
+ *                                                                           *
+ *   This program is free software: you can redistribute it and/or modify    *
+ *   it under the terms of the GNU General Public License as published by    *
+ *   the Free Software Foundation, either version 2 of the License, or       *
+ *   (at your option) any later version.                                     *
+ *                                                                           *
+ *   This program is distributed in the hope that it will be useful,         *
+ *   but WITHOUT ANY WARRANTY; without even the implied warranty of          *
+ *   MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the            *
+ *   GNU General Public License for more details.                            *
+ *                                                                           *
+ *   You should have received a copy of the GNU General Public License       *
+ *   along with this program.  If not, see <http://www.gnu.org/licenses/>.   *
+ *****************************************************************************/
+/*!
+ * \ingroup Properties
+ * \ingroup BoxProperties
+ * \ingroup RichardsModel
+ * \file
+ *
+ * \brief Contains the default definitions for the properties required
+ *        by the Richards box model.
+ */
+#ifndef DUMUX_RICHARDS_PROPERTY_DEFAULTS_HH
+#define DUMUX_RICHARDS_PROPERTY_DEFAULTS_HH
+
+#include "richardsmodel.hh"
+#include "richardsproblem.hh"
+#include "richardsindices.hh"
+#include <dumux/boxmodels/common/boxdarcyfluxvariables.hh>
+#include "richardsvolumevariables.hh"
+#include "richardsproperties.hh"
+#include "richardsnewtoncontroller.hh"
+
+#include <dumux/material/components/nullcomponent.hh>
+#include <dumux/material/fluidsystems/2pimmisciblefluidsystem.hh>
+#include <dumux/material/spatialparams/boxspatialparams.hh>
+
+namespace Dumux
+{
+// \{
+
+namespace Properties {
+//////////////////////////////////////////////////////////////////
+// Properties values
+//////////////////////////////////////////////////////////////////
+//! Number of equations required by the model
+SET_INT_PROP(BoxRichards, NumEq, 1);
+//! Number of fluid phases considered
+SET_INT_PROP(BoxRichards, NumPhases, 2);
+
+//! The local residual operator
+SET_TYPE_PROP(BoxRichards,
+              LocalResidual,
+              RichardsLocalResidual<TypeTag>);
+
+//! The global model used
+SET_TYPE_PROP(BoxRichards, Model, RichardsModel<TypeTag>);
+
+//! The class for the volume averaged quantities
+SET_TYPE_PROP(BoxRichards, VolumeVariables, RichardsVolumeVariables<TypeTag>);
+
+//! The class for the quantities required for the flux calculation
+SET_TYPE_PROP(BoxRichards, FluxVariables, BoxDarcyFluxVariables<TypeTag>);
+
+//! The class of the newton controller
+SET_TYPE_PROP(BoxRichards, NewtonController, RichardsNewtonController<TypeTag>);
+
+//! The upwind weight for the mass conservation equations
+SET_SCALAR_PROP(BoxRichards, ImplicitMassUpwindWeight, 1.0);
+
+//! weight for the upwind mobility in the velocity calculation
+SET_SCALAR_PROP(BoxRichards, ImplicitMobilityUpwindWeight, 1.0);
+
+//! The class with all index definitions for the model
+SET_TYPE_PROP(BoxRichards, Indices, RichardsIndices<TypeTag>);
+
+//! The spatial parameters to be employed. 
+//! Use BoxSpatialParams by default.
+SET_TYPE_PROP(BoxRichards, SpatialParams, BoxSpatialParams<TypeTag>);
+
+/*!
+ * \brief Set type of the parameter objects for the material law
+ *
+ * By default this is just retrieved from the material law.
+ */
+SET_PROP(BoxRichards, MaterialLawParams)
+{
+private:
+    typedef typename GET_PROP_TYPE(TypeTag, MaterialLaw) MaterialLaw;
+
+public:
+    typedef typename MaterialLaw::Params type;
+};
+
+/*!
+ * \brief The wetting phase used.
+ *
+ * By default we use the null-phase, i.e. this has to be defined by
+ * the problem for the program to work. Please be aware that you
+ * should be careful to use the Richards model in conjunction with
+ * liquid non-wetting phases. This is only meaningful if the viscosity
+ * of the liquid phase is _much_ lower than the viscosity of the
+ * wetting phase.
+ */
+SET_PROP(BoxRichards, WettingPhase)
+{ private:
+    typedef typename GET_PROP_TYPE(TypeTag, Scalar) Scalar;
+public:
+    typedef Dumux::LiquidPhase<Scalar, Dumux::NullComponent<Scalar> > type;
+};
+
+/*!
+ * \brief The wetting phase used.
+ *
+ * By default we use the null-phase, i.e. this has to be defined by
+ * the problem for the program to work. This doed not need to be
+ * specified by the problem for the Richards model to work because the
+ * Richards model does not conserve the non-wetting phase.
+ */
+SET_PROP(BoxRichards, NonwettingPhase)
+{ private:
+    typedef typename GET_PROP_TYPE(TypeTag, Scalar) Scalar;
+public:
+    typedef Dumux::GasPhase<Scalar, Dumux::NullComponent<Scalar> > type;
+};
+
+/*!
+ *\brief The fluid system used by the model.
+ *
+ * By default this uses the immiscible twophase fluid system. The
+ * actual fluids used are specified using in the problem definition by
+ * the WettingPhase and NonwettingPhase properties. Be aware that
+ * using different fluid systems in conjunction with the Richards
+ * model only makes very limited sense.
+ */
+SET_PROP(BoxRichards, FluidSystem)
+{ private:
+    typedef typename GET_PROP_TYPE(TypeTag, Scalar) Scalar;
+    typedef typename GET_PROP_TYPE(TypeTag, WettingPhase) WettingPhase;
+    typedef typename GET_PROP_TYPE(TypeTag, NonwettingPhase) NonwettingPhase;
+
+public:
+    typedef Dumux::FluidSystems::TwoPImmiscible<Scalar,
+                                                WettingPhase,
+                                                NonwettingPhase> type;
+};
+
+// enable gravity by default
+SET_BOOL_PROP(BoxRichards, ProblemEnableGravity, true);
+
+//! default value for the forchheimer coefficient
+// Source: Ward, J.C. 1964 Turbulent flow in porous media. ASCE J. Hydraul. Div 90.
+//        Actually the Forchheimer coefficient is also a function of the dimensions of the
+//        porous medium. Taking it as a constant is only a first approximation
+//        (Nield, Bejan, Convection in porous media, 2006, p. 10)
+SET_SCALAR_PROP(BoxModel, SpatialParamsForchCoeff, 0.55);
+
+// \}
+}
+
+} // end namepace
+
+#endif
diff --git a/dumux/implicit/richards/richardsvolumevariables.hh b/dumux/implicit/richards/richardsvolumevariables.hh
new file mode 100644
index 0000000000..d32e107dad
--- /dev/null
+++ b/dumux/implicit/richards/richardsvolumevariables.hh
@@ -0,0 +1,280 @@
+// -*- mode: C++; tab-width: 4; indent-tabs-mode: nil; c-basic-offset: 4 -*-
+// vi: set et ts=4 sw=4 sts=4:
+/*****************************************************************************
+ *   See the file COPYING for full copying permissions.                      *
+ *                                                                           *
+ *   This program is free software: you can redistribute it and/or modify    *
+ *   it under the terms of the GNU General Public License as published by    *
+ *   the Free Software Foundation, either version 2 of the License, or       *
+ *   (at your option) any later version.                                     *
+ *                                                                           *
+ *   This program is distributed in the hope that it will be useful,         *
+ *   but WITHOUT ANY WARRANTY; without even the implied warranty of          *
+ *   MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the            *
+ *   GNU General Public License for more details.                            *
+ *                                                                           *
+ *   You should have received a copy of the GNU General Public License       *
+ *   along with this program.  If not, see <http://www.gnu.org/licenses/>.   *
+ *****************************************************************************/
+/*!
+ * \file
+ *
+ * \brief Volume averaged quantities required by the Richards model.
+ */
+#ifndef DUMUX_RICHARDS_VOLUME_VARIABLES_HH
+#define DUMUX_RICHARDS_VOLUME_VARIABLES_HH
+
+#include "richardsproperties.hh"
+
+#include <dumux/material/fluidstates/immisciblefluidstate.hh>
+#include <dumux/boxmodels/common/boxvolumevariables.hh>
+
+namespace Dumux
+{
+
+/*!
+ * \ingroup RichardsModel
+ * \ingroup BoxVolumeVariables
+ * \brief Volume averaged quantities required by the Richards model.
+ *
+ * This contains the quantities which are are constant within a finite
+ * volume in the Richards model
+ */
+template <class TypeTag>
+class RichardsVolumeVariables : public BoxVolumeVariables<TypeTag>
+{
+    typedef BoxVolumeVariables<TypeTag> ParentType;
+
+    typedef typename GET_PROP_TYPE(TypeTag, VolumeVariables) Implementation;
+    typedef typename GET_PROP_TYPE(TypeTag, Scalar) Scalar;
+    typedef typename GET_PROP_TYPE(TypeTag, Problem) Problem;
+    typedef typename GET_PROP_TYPE(TypeTag, FluidSystem) FluidSystem;
+    typedef typename GET_PROP_TYPE(TypeTag, MaterialLaw) MaterialLaw;
+    typedef typename GET_PROP_TYPE(TypeTag, MaterialLawParams) MaterialLawParams;
+    typedef typename GET_PROP_TYPE(TypeTag, FVElementGeometry) FVElementGeometry;
+    typedef typename GET_PROP_TYPE(TypeTag, PrimaryVariables) PrimaryVariables;
+
+    typedef typename GET_PROP_TYPE(TypeTag, Indices) Indices;
+    enum {
+        pwIdx = Indices::pwIdx,
+        wPhaseIdx = Indices::wPhaseIdx,
+        nPhaseIdx = Indices::nPhaseIdx
+    };
+
+    typedef typename GET_PROP_TYPE(TypeTag, GridView) GridView;
+    typedef typename GridView::template Codim<0>::Entity Element;
+
+public:
+    //! The type returned by the fluidState() method
+    typedef Dumux::ImmiscibleFluidState<Scalar, FluidSystem> FluidState;
+
+    /*!
+     * \copydoc BoxVolumeVariables::update
+     */
+    void update(const PrimaryVariables &priVars,
+                const Problem &problem,
+                const Element &element,
+                const FVElementGeometry &fvGeometry,
+                const int scvIdx,
+                const bool isOldSol)
+    {
+        assert(!FluidSystem::isLiquid(nPhaseIdx));
+
+        ParentType::update(priVars,
+                           problem,
+                           element,
+                           fvGeometry,
+                           scvIdx,
+                           isOldSol);
+
+        completeFluidState(priVars, problem, element, fvGeometry, scvIdx, fluidState_);
+
+        //////////
+        // specify the other parameters
+        //////////
+        const MaterialLawParams &matParams =
+            problem.spatialParams().materialLawParams(element, fvGeometry, scvIdx);
+        relativePermeabilityWetting_ =
+            MaterialLaw::krw(matParams,
+                             fluidState_.saturation(wPhaseIdx));
+
+        porosity_ = problem.spatialParams().porosity(element, fvGeometry, scvIdx);
+
+        // energy related quantities not contained in the fluid state
+        asImp_().updateEnergy_(priVars, problem, element, fvGeometry, scvIdx, isOldSol);
+    }
+
+    /*!
+     * \copydoc BoxModel::completeFluidState
+     */
+    static void completeFluidState(const PrimaryVariables& priVars,
+                                   const Problem& problem,
+                                   const Element& element,
+                                   const FVElementGeometry& fvGeometry,
+                                   const int scvIdx,
+                                   FluidState& fluidState)
+    {
+        // temperature
+        Scalar t = Implementation::temperature_(priVars, problem, element,
+                                                fvGeometry, scvIdx);
+        fluidState.setTemperature(t);
+
+        // pressures
+        Scalar pnRef = problem.referencePressure(element, fvGeometry, scvIdx);
+        const MaterialLawParams &matParams =
+            problem.spatialParams().materialLawParams(element, fvGeometry, scvIdx);
+        Scalar minPc = MaterialLaw::pC(matParams, 1.0);
+        fluidState.setPressure(wPhaseIdx, priVars[pwIdx]);
+        fluidState.setPressure(nPhaseIdx, std::max(pnRef, priVars[pwIdx] + minPc));
+
+        // saturations
+        Scalar Sw = MaterialLaw::Sw(matParams, fluidState.pressure(nPhaseIdx) - fluidState.pressure(wPhaseIdx));
+        fluidState.setSaturation(wPhaseIdx, Sw);
+        fluidState.setSaturation(nPhaseIdx, 1 - Sw);
+
+        // density and viscosity
+        typename FluidSystem::ParameterCache paramCache;
+        paramCache.updateAll(fluidState);
+        fluidState.setDensity(wPhaseIdx, FluidSystem::density(fluidState, paramCache, wPhaseIdx));
+        fluidState.setDensity(nPhaseIdx, 1e-10);
+
+        fluidState.setViscosity(wPhaseIdx, FluidSystem::viscosity(fluidState, paramCache, wPhaseIdx));
+        fluidState.setViscosity(nPhaseIdx, 1e-10);
+    }
+
+    /*!
+     * \brief Return the fluid configuration at the given primary
+     *        variables
+     */
+    const FluidState &fluidState() const
+    { return fluidState_; }
+
+    /*!
+     * \brief Returns the average porosity [] within the control volume.
+     *
+     * The porosity is defined as the ratio of the pore space to the
+     * total volume, i.e. \f[ \Phi := \frac{V_{pore}}{V_{pore} + V_{rock}} \f]
+     */
+    Scalar porosity() const
+    { return porosity_; }
+
+    /*!
+     * \brief Returns the average absolute saturation [] of a given
+     *        fluid phase within the finite volume.
+     *
+     * The saturation of a fluid phase is defined as the fraction of
+     * the pore volume filled by it, i.e.
+     * \f[ S_\alpha := \frac{V_\alpha}{V_{pore}} = \phi \frac{V_\alpha}{V} \f]
+     *
+     * \param phaseIdx The index of the fluid phase
+     */
+    Scalar saturation(const int phaseIdx) const
+    { return fluidState_.saturation(phaseIdx); }
+
+    /*!
+     * \brief Returns the average mass density \f$\mathrm{[kg/m^3]}\f$ of a given
+     *        fluid phase within the control volume.
+     *
+     * \param phaseIdx The index of the fluid phase
+     */
+    Scalar density(const int phaseIdx) const
+    { return fluidState_.density(phaseIdx); }
+
+    /*!
+     * \brief Returns the effective pressure \f$\mathrm{[Pa]}\f$ of a given phase within
+     *        the control volume.
+     *
+     * For the non-wetting phase (i.e. the gas phase), we assume
+     * infinite mobility, which implies that the non-wetting phase
+     * pressure is equal to the finite volume's reference pressure
+     * defined by the problem.
+     *
+     * \param phaseIdx The index of the fluid phase
+     */
+    Scalar pressure(const int phaseIdx) const
+    { return fluidState_.pressure(phaseIdx); }
+
+    /*!
+     * \brief Returns average temperature \f$\mathrm{[K]}\f$ inside the control volume.
+     *
+     * Note that we assume thermodynamic equilibrium, i.e. the
+     * temperature of the rock matrix and of all fluid phases are
+     * identical.
+     */
+    Scalar temperature() const
+    { return fluidState_.temperature(); }
+
+    /*!
+     * \brief Returns the effective mobility \f$\mathrm{[1/(Pa*s)]}\f$ of a given phase within
+     *        the control volume.
+     *
+     * The mobility of a fluid phase is defined as the relative
+     * permeability of the phase (given by the chosen material law)
+     * divided by the dynamic viscosity of the fluid, i.e.
+     * \f[ \lambda_\alpha := \frac{k_{r\alpha}}{\mu_\alpha} \f]
+     *
+     * \param phaseIdx The index of the fluid phase
+     */
+    Scalar mobility(const int phaseIdx) const
+    { return relativePermeability(phaseIdx)/fluidState_.viscosity(phaseIdx); }
+
+    /*!
+     * \brief Returns relative permeability [-] of a given phase within
+     *        the control volume.
+     *
+     * \param phaseIdx The index of the fluid phase
+     */
+    Scalar relativePermeability(const int phaseIdx) const
+    {
+        if (phaseIdx == wPhaseIdx)
+            return relativePermeabilityWetting_;
+        return 1;
+    }
+
+    /*!
+     * \brief Returns the effective capillary pressure \f$\mathrm{[Pa]}\f$ within the
+     *        control volume.
+     *
+     * The capillary pressure is defined as the difference in
+     * pressures of the non-wetting and the wetting phase, i.e.
+     * \f[ p_c = p_n - p_w \f]
+     */
+    Scalar capillaryPressure() const
+    { return fluidState_.pressure(nPhaseIdx) - fluidState_.pressure(wPhaseIdx); }
+
+protected:
+    static Scalar temperature_(const PrimaryVariables &primaryVariables,
+                            const Problem& problem,
+                            const Element &element,
+                            const FVElementGeometry &fvGeometry,
+                            const int scvIdx)
+    {
+        return problem.boxTemperature(element, fvGeometry, scvIdx);
+    }
+
+    /*!
+     * \brief Called by update() to compute the energy related quantities
+     */
+    void updateEnergy_(const PrimaryVariables &priVars,
+                       const Problem &problem,
+                       const Element &element,
+                       const FVElementGeometry &fvGeometry,
+                       const int scvIdx,
+                       const bool isOldSol)
+    { }
+
+    FluidState fluidState_;
+    Scalar relativePermeabilityWetting_;
+    Scalar porosity_;
+
+private:
+    Implementation &asImp_()
+    { return *static_cast<Implementation*>(this); }
+
+    const Implementation &asImp_() const
+    { return *static_cast<const Implementation*>(this); }
+};
+
+}
+
+#endif
diff --git a/dumux/io/artmeshreader.hh b/dumux/io/artgridcreator.hh
similarity index 51%
rename from dumux/io/artmeshreader.hh
rename to dumux/io/artgridcreator.hh
index be77711f96..a8a76a518b 100644
--- a/dumux/io/artmeshreader.hh
+++ b/dumux/io/artgridcreator.hh
@@ -21,8 +21,8 @@
  *  for modeling lower dimensional discrete fracture-matrix problems.
  */
 
-#ifndef DUMUX_IO_ARTMESH_READER_HH
-#define DUMUX_IO_ARTMESH_READER_HH
+#ifndef DUMUX_ARTGRIDCREATOR_HH
+#define DUMUX_ARTGRIDCREATOR_HH
 
 #include <algorithm>
 #include <iostream>
@@ -31,9 +31,11 @@
 #include <iomanip>
 
 #include <dune/grid/common/mcmgmapper.hh>
-#include <dune/grid/uggrid.hh>
+#include <dune/grid/common/gridfactory.hh>
 
 #include <dumux/common/math.hh>
+#include <dumux/common/propertysystem.hh>
+#include <dumux/common/parameters.hh>
 #include <dumux/common/valgrind.hh>
 
 // plot the vertices, edges, elements
@@ -42,66 +44,42 @@
 
 namespace Dumux
 {
-#ifdef HAVE_UG
-typedef Dune::UGGrid<2> GridType; // Currently implemented for 2D fractured systems
-#else
-typedef Dune::YaspGrid<2> GridType;
-#endif
 
-typedef Dune::FieldVector<double, 3> Coordinates;
-typedef std::vector<Coordinates> VerticesVector;
-typedef Dune::FieldVector<int, 3> EdgePoints;
-typedef std::vector<EdgePoints> EdgesVector;
-typedef Dune::FieldVector<int, 4> Faces;
-typedef std::vector<Faces> FacesVector;
-
-typedef double NumberType; // TODO: from parameter system?
-
-/*
-The number of
-    boundary vertices,
-    boundary edges (connecting two boundary vertices),
-    boundary faces (connecting n boundary edges) and
-    boundary elements (should be 0)
-are read from the boundarty description file and stored here.
-*/
-int bVertices, bEdges, bFaces, bElements;
-
-// Store the vertex coordinates, edge infos, face infos.
-Dune::FieldVector<double, 2> vertexPosition;
-
-template<int dim>
-struct P1Layout
+namespace Properties
 {
-    bool contains (Dune::GeometryType gt)
-    {
-        return (gt.dim() == 0);
-    }
-};
-
+NEW_PROP_TAG(Scalar);
+NEW_PROP_TAG(Grid);
+NEW_PROP_TAG(GridCreator);
+}
+    
 /*!
  * \brief Reads in Artmesh files.
  */
-template <class GridType>
-class ArtReader {
+template <class TypeTag>
+class ArtGridCreator
+{
+    typedef typename GET_PROP_TYPE(TypeTag, Scalar) Scalar;
+    typedef typename GET_PROP_TYPE(TypeTag, Grid)  Grid;
+    typedef Grid* GridPointer;
+    typedef Dune::FieldVector<double, 3> Coordinates;
+    typedef std::vector<Coordinates> VerticesVector;
+    typedef Dune::FieldVector<int, 3> EdgePoints;
+    typedef std::vector<EdgePoints> EdgesVector;
+    typedef Dune::FieldVector<int, 4> Faces;
+    typedef std::vector<Faces> FacesVector;
 
 public:
     /*!
-     * \brief Reads the file formats obtained with the Artmesh generator
-     * 
-     * \param artFileName Path to the Artmesh file.
+     * \brief Create the Grid
      */
-    void read_art_file(const char *artFileName)
+    static void makeGrid()
     {
+        const std::string artFileName = GET_RUNTIME_PARAM_FROM_GROUP(TypeTag, std::string, Grid, File);
+
         std::cout << "Opening " << artFileName << std::endl;
         std::ifstream inFile(artFileName);
 
-        //intialize
-        Coordinates coordinate_;
-        EdgePoints edge_points_;
-        Faces faces_;
         std::string jump;
-
         while (inFile >> jump)
         {
             //do nothing with the first lines in the code
@@ -110,7 +88,7 @@ public:
             {
                 inFile >> jump;
                 double dummy = atof(jump.c_str());
-                vertexNumber = dummy;
+                vertexNumber_ = dummy;
                 break;
             }
         }
@@ -120,7 +98,7 @@ public:
             {
                 inFile >> jump;
                 double dummy = atof(jump.c_str());
-                edgeNumber = dummy;
+                edgeNumber_ = dummy;
                 break;
             }
         }
@@ -130,7 +108,7 @@ public:
             {
                 inFile >> jump;
                 double dummy = atof(jump.c_str());
-                faceNumber = dummy;
+                faceNumber_ = dummy;
                 break;
             }
         }
@@ -140,7 +118,7 @@ public:
             {
                 inFile >> jump;
                 double dummy = atof(jump.c_str());
-                elementNumber = dummy;
+                elementNumber_ = dummy;
                 break;
             }
         }
@@ -172,14 +150,15 @@ public:
                 break;
             }
             double dummy = atof(jump.c_str());
-            coordinate_[0] = dummy;
-            for (int k=1; k<3; k++)
+            Coordinates coordinate;
+            coordinate[0] = dummy;
+            for (int k = 1; k < 3; k++)
             {
                 inFile >> jump;
                 dummy = atof(jump.c_str());
-                coordinate_[k] = dummy;
+                coordinate[k] = dummy;
             }
-            vertices_.push_back(coordinate_);
+            vertices_.push_back(coordinate);
         }
     /////Reading Edges
         while (inFile >> jump)
@@ -199,14 +178,15 @@ public:
                 break;
             }
             double dummy = atof(jump.c_str());
-            edge_points_[0] = dummy;
-            for (int k=1; k<3; k++)
+            EdgePoints edgePoints;
+            edgePoints[0] = dummy;
+            for (int k = 1; k < 3; k++)
             {
                 inFile >> jump;
                 dummy = atof(jump.c_str());
-                edge_points_[k] = dummy;
+                edgePoints[k] = dummy;
             }
-            edges_vector_.push_back(edge_points_);
+            edges_.push_back(edgePoints);
         }
 
     /////Reading Faces
@@ -227,171 +207,90 @@ public:
                 break;
             }
             double dummy = atof(jump.c_str());
-            faces_[0] = dummy;
-            for (int k=1; k<4; k++)
+            Faces facePoints;
+            facePoints[0] = dummy;
+            for (int k = 1; k < 4; k++)
             {
                 inFile >> jump;
                 dummy = atof(jump.c_str());
-                faces_[k] = dummy;
+                facePoints[k] = dummy;
             }
-            faces_vector_.push_back(faces_);
+            faces_.push_back(facePoints);
         }
-    }
-    void outputARTtoScreen()
-    {
-    ////////OUTPUT for verification
-    //////////////////////////////////////////////////////////////////
-            std::cout << std::endl << "printing VERTICES" << std::endl;
-            for (int i = 0; i < vertices_.size(); i++)
-            {
-                for (int j=0; j < 3; j++)
-                std::cout << vertices_[i][j]<<"\t";
-                std::cout << std::endl;
-            }
-
-            std::cout << std::endl << "printing EDGES" << std::endl;
-            for (int i = 0; i < edges_vector_.size(); i++)
-            {
-                for (int j=0; j < 3; j++)
-                std::cout<<edges_vector_[i][j]<<"\t";
-                std::cout<<std::endl;
-            }
-            ////Printing Faces
-            std::cout << std::endl << "printing FACES" << std::endl;
-            for (int i = 0; i < faces_vector_.size(); i++)
-            {
-                for (int j=0; j < 4; j++)
-                {
-                    std::cout<<faces_vector_[i][j]<<" ";
-                }
-                std::cout<<std::endl;
-            }
-
-            std::cout << std::endl << "Total number of vertices "<<vertexNumber<<std::endl;
-            std::cout << "Total number of edges: "<<edgeNumber<<std::endl;
-            std::cout << "Total number of faces: "<<faceNumber<<std::endl;
-            std::cout << "Total number of elements: "<<elementNumber<<std::endl;
-
-            if (vertices_.size() != vertexNumber )
-            {
-                std::cout << "The total given number of vertices: "<<vertexNumber
-                        <<" is not the same with the read number of entries: "
-                        <<vertices_.size()<<"" << std::endl;
-            }
-            if (edges_vector_.size() != edgeNumber )
-            {
-                std::cout << "The total given number of edges: "<<edgeNumber
-                        <<" is not the same with the read number of entries: "
-                        <<edges_vector_.size()<<"" << std::endl;
-            }
-            if (faces_vector_.size() != faceNumber )
-            {
-                std::cout << "The total given number of faces: "<<faceNumber
-                        <<" is not the same with the read number of entries: "
-                        <<faces_vector_.size()<<"" << std::endl;
-            }
-    }
-
-    /*!
-     * \brief Create the UG grid from the read in data
-     */
-    GridType* createGrid()
-    {
-        // set up the grid factory
+        
+                // set up the grid factory
         Dune::FieldVector<double,2> position;
-        Dune::GridFactory<GridType> factory;
-        bVertices = vertexNumber;
-        bEdges = edgeNumber;
-        bFaces = faceNumber;
-        VerticesVector verts(bVertices);
-        EdgesVector edges(bEdges);
-        FacesVector elems(bFaces);
+        Dune::GridFactory<Grid> factory;
 
+#if PLOT
         // Plot the vertices
-    #if PLOT
-        std::cout << "*================*"<<std::endl;
-        std::cout << "* Vertices"<<std::endl;
-        std::cout << "*================*"<<std::endl;
-    #endif
-        for (int k=0; k<bVertices; k++)
+        std::cout << "*================*" << std::endl;
+        std::cout << "* Vertices" << std::endl;
+        std::cout << "*================*" << std::endl;
+#endif
+        for (int k = 0; k < vertexNumber_; k++)
         {
-            verts[k][0] = vertices_[k][0];
-            verts[k][1] = vertices_[k][1];
-            verts[k][2] = vertices_[k][2];
-
-            //Printing the vertices vector
-    #if PLOT
-            std::cout << verts[k][0]<<"\t\t";
-            std::cout << verts[k][1]<<"\t\t";
-            std::cout << verts[k][2]<<std::endl;
-    #endif
-            for (int i=0; i<2; i++)
+#if PLOT
+            // Printing the vertices vector
+            std::cout << vertices_[k][0] << "\t\t";
+            std::cout << vertices_[k][1] << "\t\t";
+            std::cout << vertices_[k][2] << std::endl;
+#endif
+            for (int i = 0; i < 2; i++)
             {
-                position[i]=verts[k][i];
+                position[i] = vertices_[k][i];
             }
             factory.insertVertex(position);
         }
-    #if PLOT
-        std::cout << "*================*"<<std::endl;
-        std::cout << "* Edges"<<std::endl;
-        std::cout << "*================*"<<std::endl;
-    #endif
-        for (int k=0; k<bEdges; k++)
+
+#if PLOT
+        std::cout << "*================*" << std::endl;
+        std::cout << "* Edges" << std::endl;
+        std::cout << "*================*" << std::endl;
+        for (int k = 0; k < edgeNumber_; k++)
         {
-            edges[k][0]=edges_vector_[k][0];
-            edges[k][1]=edges_vector_[k][1];
-            edges[k][2]=edges_vector_[k][2];
-    #if PLOT
-            //Printing the Edge vector
-            std::cout<<edges[k][0]<<"\t\t";
-            std::cout<<edges[k][1]<<"\t";
-            std::cout<<edges[k][2]<<std::endl;
-    #endif
+            // Printing the Edge vector
+            std::cout << edges_[k][0] << "\t\t";
+            std::cout << edges_[k][1] << "\t";
+            std::cout << edges_[k][2] << std::endl;
         }
 
         // Plot the Elements (Faces)
-    #if PLOT
-        std::cout << "*================*"<<std::endl;
-        std::cout << "* Faces"<<std::endl;
-        std::cout << "*================*"<<std::endl;
-    #endif
-
-        for (int k=0; k<faceNumber; k++)
+        std::cout << "*================*" << std::endl;
+        std::cout << "* Faces" << std::endl;
+        std::cout << "*================*" << std::endl;
+        for (int k = 0; k < faceNumber_; k++)
         {
-            elems[k][0]=faces_vector_[k][1];
-            elems[k][1]=faces_vector_[k][2];
-            elems[k][2]=faces_vector_[k][3];
-    #if PLOT
-            std::cout<<elems[k][0]<<"\t";
-            std::cout<<elems[k][1]<<"\t";
-            std::cout<<elems[k][2]<<std::endl;
-    #endif
+            std::cout << faces_[k][1] << "\t";
+            std::cout << faces_[k][2] << "\t";
+            std::cout << faces_[k][3] << std::endl;
         }
-
+#endif
+        
         //***********************************************************************//
         //Create the Elements in Dune::GridFactory //
         //***********************************************************************//
 
-        for (int i=0; i<bFaces; i++)
+        for (int i=0; i<faceNumber_; i++)
         {
             std::vector<unsigned int> nodeIdx(3);
             Dune::FieldVector<double,3> point(0);
-    #if PLOT
-            std::cout << "====================================="<<std::endl;
-            std::cout << "globalElemIdx "<<i<<std::endl;
-            std::cout << "====================================="<<std::endl;
-    #endif
+#if PLOT
+            std::cout << "=====================================" << std::endl;
+            std::cout << "globalElemIdx " << i << std::endl;
+            std::cout << "=====================================" << std::endl;
+#endif
             int edgeIdx = 0;
             //first node of the element - from first edge Node 1
-            nodeIdx[0] = edges[elems[i][edgeIdx]][1];
+            nodeIdx[0] = edges_[faces_[i][edgeIdx+1]][1];
             //second node of the element- from first edge Node 2
-            nodeIdx[1] = edges[elems[i][edgeIdx]][2];
+            nodeIdx[1] = edges_[faces_[i][edgeIdx+1]][2];
             //third node of the element - from the second edge
-            nodeIdx[2] = edges[elems[i][edgeIdx+1]][1];
+            nodeIdx[2] = edges_[faces_[i][edgeIdx+2]][1];
             // if the nodes of the edges are identical swap
             if (nodeIdx[1] == nodeIdx[2] || nodeIdx[0] == nodeIdx[2])
             {
-                nodeIdx[2] = edges[elems[i][edgeIdx+1]][2];
+                nodeIdx[2] = edges_[faces_[i][edgeIdx+2]][2];
             }
 
             /* Check if the order of the nodes is trigonometric
@@ -400,63 +299,181 @@ public:
             Dune::FieldVector<double, 2> v(0);
             Dune::FieldVector<double, 2> w(0);
             double cross1;
-            v[0] = verts[nodeIdx[0]][0] - verts[nodeIdx[1]][0];
-            v[1] = verts[nodeIdx[0]][1] - verts[nodeIdx[1]][1];
-            w[0] = verts[nodeIdx[0]][0] - verts[nodeIdx[2]][0];
-            w[1] = verts[nodeIdx[0]][1] - verts[nodeIdx[2]][1];
+            v[0] = vertices_[nodeIdx[0]][0] - vertices_[nodeIdx[1]][0];
+            v[1] = vertices_[nodeIdx[0]][1] - vertices_[nodeIdx[1]][1];
+            w[0] = vertices_[nodeIdx[0]][0] - vertices_[nodeIdx[2]][0];
+            w[1] = vertices_[nodeIdx[0]][1] - vertices_[nodeIdx[2]][1];
             cross1 = v[0]*w[1]-v[1]*w[0];
             //If the cross product is negative switch the order of the vertices
             if (cross1 < 0)
             {
-                nodeIdx[0] = edges[elems[i][edgeIdx]][2]; //node 0 is node 1
-                nodeIdx[1] = edges[elems[i][edgeIdx]][1]; //node 1 is node 0
+                nodeIdx[0] = edges_[faces_[i][edgeIdx+1]][2]; //node 0 is node 1
+                nodeIdx[1] = edges_[faces_[i][edgeIdx+1]][1]; //node 1 is node 0
             }
-            v[0] = verts[nodeIdx[0]][0] - verts[nodeIdx[1]][0];
-            v[1] = verts[nodeIdx[0]][1] - verts[nodeIdx[1]][1];
-            w[0] = verts[nodeIdx[0]][0] - verts[nodeIdx[2]][0];
-            w[1] = verts[nodeIdx[0]][1] - verts[nodeIdx[2]][1];
+            v[0] = vertices_[nodeIdx[0]][0] - vertices_[nodeIdx[1]][0];
+            v[1] = vertices_[nodeIdx[0]][1] - vertices_[nodeIdx[1]][1];
+            w[0] = vertices_[nodeIdx[0]][0] - vertices_[nodeIdx[2]][0];
+            w[1] = vertices_[nodeIdx[0]][1] - vertices_[nodeIdx[2]][1];
 
             factory.insertElement(Dune::GeometryType(Dune::GeometryType::simplex,2),
                     nodeIdx);
-    #if PLOT
-            std::cout << "edges of the element "<< elems[i] << std::endl;
+#if PLOT
+            std::cout << "edges of the element "<< faces_[i] << std::endl;
             std::cout << "nodes of the element " << nodeIdx[0]
                       << ", " << nodeIdx[1] << ", "
                       << nodeIdx[2] << std::endl;
-            std::cout << "1st "<<nodeIdx[0]<<"\t"<<"2nd "<<nodeIdx[1]
-                      << "\t"<<"3rd "<<nodeIdx[2]
+            std::cout << "1st " << nodeIdx[0] 
+                      << "\t" << "2nd " << nodeIdx[1]
+                      << "\t" << "3rd " << nodeIdx[2]
                       << std::endl;
-    #endif
-            if (nodeIdx[0] == nodeIdx[1]||nodeIdx[1] == nodeIdx[2]
-                                        ||nodeIdx[0] == nodeIdx[2] )
+#endif
+            if (nodeIdx[0] == nodeIdx[1] || nodeIdx[1] == nodeIdx[2]
+                                         || nodeIdx[0] == nodeIdx[2])
             {
                 std::cout << "Error. The node index is identical in the element"
                           << std::endl;
             }
-
         }
 
-        Valgrind::CheckDefined(verts);
+        grid_ = factory.createGrid();
+    }
+    
+    static void outputARTtoScreen()
+    {
+    ////////OUTPUT for verification
+    //////////////////////////////////////////////////////////////////
+            std::cout << std::endl << "printing VERTICES" << std::endl;
+            for (int i = 0; i < vertices_.size(); i++)
+            {
+                for (int j = 0; j < 3; j++)
+                    std::cout << vertices_[i][j] << "\t";
+                std::cout << std::endl;
+            }
 
-        return factory.createGrid();
+            std::cout << std::endl << "printing EDGES" << std::endl;
+            for (int i = 0; i < edges_.size(); i++)
+            {
+                for (int j = 0; j < 3; j++)
+                    std::cout << edges_[i][j] << "\t";
+                std::cout << std::endl;
+            }
+            ////Printing Faces
+            std::cout << std::endl << "printing FACES" << std::endl;
+            for (int i = 0; i < faces_.size(); i++)
+            {
+                for (int j = 0; j < 4; j++)
+                    std::cout << faces_[i][j] << " ";
+                std::cout << std::endl;
+            }
+
+            std::cout << std::endl << "Total number of vertices " << vertexNumber_ << std::endl;
+            std::cout << "Total number of edges: " << edgeNumber_ << std::endl;
+            std::cout << "Total number of faces: " << faceNumber_ << std::endl;
+            std::cout << "Total number of elements: " << elementNumber_ << std::endl;
+
+            if (vertices_.size() != vertexNumber_ )
+            {
+                std::cout << "The total given number of vertices: " << vertexNumber_
+                        << " is not the same with the read number of entries: "
+                        << vertices_.size() << "" << std::endl;
+            }
+            if (edges_.size() != edgeNumber_ )
+            {
+                std::cout << "The total given number of edges: " << edgeNumber_
+                        << " is not the same with the read number of entries: "
+                        << edges_.size() << "" << std::endl;
+            }
+            if (faces_.size() != faceNumber_ )
+            {
+                std::cout << "The total given number of faces: " << faceNumber_
+                        << " is not the same with the read number of entries: "
+                        << faces_.size() << "" << std::endl;
+            }
     }
 
-public:
-    VerticesVector vertices_;
-    EdgesVector edges_vector_;
-    FacesVector faces_vector_ ;
-    int vertexNumber;
-    int edgeNumber;
-    int faceNumber; //in 2D
-    int elementNumber; //in 3D
+    /*!
+     * \brief Returns a reference to the grid.
+     */
+    static Grid &grid()
+    {
+        return *grid_;
+    };
+
+    /*!
+     * \brief Distributes the grid on all processes of a parallel
+     *        computation.
+     */
+    static void loadBalance()
+    {
+        grid_->loadBalance();
+    };
+
+    static int vertexNumber()
+    {
+        return vertexNumber_;
+    }
+    
+    static int edgeNumber()
+    {
+        return edgeNumber_;
+    }
+    
+    static int faceNumber()
+    {
+        return faceNumber_;
+    }
+
+    static VerticesVector& vertices()
+    {
+        return vertices_;
+    }
+    
+    static EdgesVector& edges()
+    {
+        return edges_;
+    }
+    
+    static FacesVector& faces()
+    {
+        return faces_;
+    }
+    
+private:
+    static VerticesVector vertices_;
+    static EdgesVector edges_;
+    static FacesVector faces_ ;
+    static int vertexNumber_;
+    static int edgeNumber_;
+    static int faceNumber_; //in 2D
+    static int elementNumber_; //in 3D
+    static GridPointer grid_;
 };
 
+template <class TypeTag>
+typename Dumux::ArtGridCreator<TypeTag>::GridPointer ArtGridCreator<TypeTag>::grid_;
+template <class TypeTag>
+typename Dumux::ArtGridCreator<TypeTag>::VerticesVector ArtGridCreator<TypeTag>::vertices_;
+template <class TypeTag>
+typename Dumux::ArtGridCreator<TypeTag>::EdgesVector ArtGridCreator<TypeTag>::edges_;
+template <class TypeTag>
+typename Dumux::ArtGridCreator<TypeTag>::FacesVector ArtGridCreator<TypeTag>::faces_;
+template <class TypeTag>
+int ArtGridCreator<TypeTag>::vertexNumber_;
+template <class TypeTag>
+int ArtGridCreator<TypeTag>::edgeNumber_;
+template <class TypeTag>
+int ArtGridCreator<TypeTag>::faceNumber_;
+template <class TypeTag>
+int ArtGridCreator<TypeTag>::elementNumber_;
+
 /*!
  * \brief Maps the fractures from the Artmesh to the UG grid ones
  */
-template<class GridType>
+template<class TypeTag>
 class FractureMapper
 {
+    typedef typename GET_PROP_TYPE(TypeTag, GridView)  GridView;
+    typedef typename GET_PROP_TYPE(TypeTag, GridCreator)  GridCreator;
 public:
     // mapper: one data element in every entity
     template<int dim>
@@ -467,62 +484,33 @@ public:
             return gt.dim() == dim-1;
         }
     };
-    template<int dim>
-    struct VertexLayout
-    {
-        bool contains (Dune::GeometryType gt)
-        {
-            return gt.dim() == 0;
-        }
-    };
-    typedef typename GridType::LeafGridView GV;
-    typedef typename GridType::ctype DT;
-    enum {dim=GridType::dimension};
-    typedef typename GV::IndexSet IS;
-    typedef typename GridType::template Codim<0>::Entity Entity;
-    typedef typename GV::template Codim<dim>::Iterator VertexLeafIterator;
-    typedef typename GV::template Codim<0>::Iterator ElementLeafIterator;
-    typedef typename GridType::template Codim<0>::EntityPointer EEntityPointer;
-    typedef typename GridType::Traits::GlobalIdSet IDS;
-    typedef typename IDS::IdType IdType;
-    typedef std::set<IdType> GIDSet;
-    typedef Dune::MultipleCodimMultipleGeomTypeMapper<GV,FaceLayout> FaceMapper;
-    typedef Dune::MultipleCodimMultipleGeomTypeMapper<GV,VertexLayout> VertexMapper;
-    typedef Dumux::ArtReader<GridType> ArtReader;
+    typedef typename GridView::ctype DT;
+    enum {dim = GridView::dimension};
+    typedef typename GridView::template Codim<dim>::Iterator VertexIterator;
+    typedef typename GridView::template Codim<0>::Iterator ElementIterator;
+    typedef Dune::MultipleCodimMultipleGeomTypeMapper<GridView, FaceLayout> FaceMapper;
+    typedef Dune::MultipleCodimMultipleGeomTypeMapper<GridView, Dune::MCMGVertexLayout> VertexMapper;
 
 public:
-    /*!
-     * \brief Constructor
-     * 
-     * \param grid The grid
-     * \param geomArt Artmesh reader
-     */
-    FractureMapper (const GridType& grid, ArtReader geomArt)
-        : grid_(grid),
-        facemapper(grid.leafView()),
-        vertexmapper(grid.leafView()),
-        artgeom_(geomArt)
-    {}
-    
     /*!
      * \brief Constructor
      * 
      * \param grid The grid
      */
-    FractureMapper (const GridType& grid)
-        : grid_(grid),
-        facemapper(grid.leafView()),
-        vertexmapper(grid.leafView())
+    FractureMapper (const GridView& gridView)
+    : gridView_(gridView),
+      faceMapper_(gridView),
+      vertexMapper_(gridView)
     {}
 
     /*!
      * 
      */
-    void fractureMapper()
+    void map()
     {
         //call the new_read art
-        int nVertices = artgeom_.vertexNumber;
-        int nEdges = artgeom_.edgeNumber;
+        int nVertices = GridCreator::vertexNumber();
+        int nEdges = GridCreator::edgeNumber();
         //The vertexes which are located on fractures
         isDuneFractureVertex_.resize(nVertices);
         std::fill(isDuneFractureVertex_.begin(), isDuneFractureVertex_.end(), false);
@@ -532,10 +520,8 @@ public:
         fractureEdgesIdx_.resize(nEdges);
         std::fill(isDuneFractureEdge_.begin(), isDuneFractureEdge_.end(), false);
 
-        GV leafView = grid_.leafView();
-
-        ElementLeafIterator eendit = leafView. template end<0>();
-        for (ElementLeafIterator it = leafView .template begin<0>(); it != eendit; ++it)
+        ElementIterator eendit = gridView_.template end<0>();
+        for (ElementIterator it = gridView_.template begin<0>(); it != eendit; ++it)
         {
              Dune::GeometryType gt = it->geometry().type();
              const typename Dune::GenericReferenceElementContainer<DT,dim>::value_type&
@@ -544,7 +530,7 @@ public:
               // Loop over element faces
               for (int i = 0; i < refElem.size(1); i++)
               {
-                  int indexFace = facemapper.map(*it, i, 1);
+                  int indexFace = faceMapper_.map(*it, i, 1);
                   /*
                   * it maps the local element vertices "localV1Idx" -> indexVertex1
                   * then it gets the coordinates of the nodes in the ART file and
@@ -552,47 +538,44 @@ public:
                   */
                   int localV1Idx = refElem.subEntity(i, 1, 0, dim);
                   int localV2Idx = refElem.subEntity(i, 1, 1, dim);
-                  int indexVertex1 = vertexmapper.map(*it, localV1Idx, dim);
-                  int indexVertex2 = vertexmapper.map(*it, localV2Idx, dim);
+                  int indexVertex1 = vertexMapper_.map(*it, localV1Idx, dim);
+                  int indexVertex2 = vertexMapper_.map(*it, localV2Idx, dim);
                   Dune::FieldVector<DT, dim> nodeART_from;
                   Dune::FieldVector<DT, dim> nodeART_to;
                   Dune::FieldVector<DT, dim> nodeDune_from;
                   Dune::FieldVector<DT, dim> nodeDune_to;
 
-                  nodeDune_from = it-> geometry(). corner (localV1Idx);
-                  nodeDune_to = it-> geometry(). corner (localV2Idx);
+                  nodeDune_from = it->geometry().corner(localV1Idx);
+                  nodeDune_to = it->geometry().corner(localV2Idx);
 
                   for (int j=0; j < nEdges; j++)
                   {
-                      nodeART_from[0] = artgeom_.vertices_[artgeom_.edges_vector_[j][1]][0];
-                      nodeART_from[1] = artgeom_.vertices_[artgeom_.edges_vector_[j][1]][1];
-                      nodeART_to[0] = artgeom_.vertices_[artgeom_.edges_vector_[j][2]][0];
-                      nodeART_to[1] = artgeom_.vertices_[artgeom_.edges_vector_[j][2]][1];
+                      nodeART_from[0] = GridCreator::vertices()[GridCreator::edges()[j][1]][0];
+                      nodeART_from[1] = GridCreator::vertices()[GridCreator::edges()[j][1]][1];
+                      nodeART_to[0] = GridCreator::vertices()[GridCreator::edges()[j][2]][0];
+                      nodeART_to[1] = GridCreator::vertices()[GridCreator::edges()[j][2]][1];
             
                       if ((nodeART_from == nodeDune_from && nodeART_to == nodeDune_to)
                           || (nodeART_from == nodeDune_to && nodeART_to == nodeDune_from))
                       {
 #if PLOT
-                        std::cout << " ART edge index is "<< j;
-//                            std::cout << " Node ART_from: "
-//                            << nodeART_from<<std::endl;
-                        std::cout << " Dune edge is " << indexFace
-                        <<std::endl;
+                        std::cout << " ART edge index is "<< j
+                                  << ", Dune edge is " << indexFace << std::endl;
 #endif
                         /* assigns a value 1 for the edges
                         * which are fractures */
-                        if (artgeom_.edges_vector_[j][0] < 0)
+                        if (GridCreator::edges()[j][0] < 0)
                         {
                             isDuneFractureEdge_[indexFace] = true;
-                            fractureEdgesIdx_[indexFace]   = artgeom_.edges_vector_[j][0];
+                            fractureEdgesIdx_[indexFace]   = GridCreator::edges()[j][0];
                             isDuneFractureVertex_[indexVertex1]=true;
                             isDuneFractureVertex_[indexVertex2]=true;
 
 #if PLOT
-                            std::cout << "isDuneFractureEdge_ "<<
-                            isDuneFractureEdge_[indexFace]<<"\t";
-                            std::cout << "vertex1 "<<indexVertex1<<"\t";
-                            std::cout << "vertex2 "<<indexVertex2<<"" << std::endl;
+                            std::cout << "isDuneFractureEdge_ "
+                                      << isDuneFractureEdge_[indexFace] << "\t"
+                                      << "vertex1 " << indexVertex1 << "\t"
+                                      << "vertex2 " << indexVertex2 << "" << std::endl;
 #endif
                         }
                     }
@@ -602,8 +585,8 @@ public:
 
 #if PLOT
         int i=0;
-        for (VertexLeafIterator vIt=leafView. template begin<dim> (); 
-             vIt != leafView. template end<dim> (); ++vIt)
+        for (VertexIterator vIt=gridView_.template begin<dim>(); 
+             vIt != gridView_.template end<dim>(); ++vIt)
         {
             Dune::GeometryType gt = vIt->type();
             std::cout << "visiting " << gt
@@ -615,18 +598,31 @@ public:
 #endif
 
     }
+    
+    bool isDuneFractureVertex(unsigned int i) const
+    {
+        return isDuneFractureVertex_[i];
+    }
+    
+    bool isDuneFractureEdge(unsigned int i) const
+    {
+        return isDuneFractureEdge_[i];
+    }
+    
+    int fractureEdgesIdx(unsigned int i) const
+    {
+        return fractureEdgesIdx_[i];
+    }
 
 private:
-   const GridType& grid_;
-   FaceMapper facemapper;
-   VertexMapper vertexmapper;
-   ArtReader artgeom_;
-public:
-   std::vector<bool> isDuneFractureVertex_;
-   std::vector<bool> isDuneFractureEdge_;
-   std::vector<int>  fractureEdgesIdx_;
+    const GridView gridView_;
+    FaceMapper faceMapper_;
+    VertexMapper vertexMapper_;
+    std::vector<bool> isDuneFractureVertex_;
+    std::vector<bool> isDuneFractureEdge_;
+    std::vector<int>  fractureEdgesIdx_;
 };
 
 } // end namespace
 
-#endif // DUMUX_IO_ARTMESH_READER_HH
+#endif // DUMUX_ARTGRIDCREATOR_HH
diff --git a/test/Makefile.am b/test/Makefile.am
index 745926a41a..b8f8ea0a80 100644
--- a/test/Makefile.am
+++ b/test/Makefile.am
@@ -1,4 +1,4 @@
-SUBDIRS = boxmodels common decoupled freeflow material
+SUBDIRS = common decoupled freeflow implicit material
 
 EXTRA_DIST = CMakeLists.txt
 
diff --git a/test/boxmodels/2pdfm/test_2pdfm.cc b/test/boxmodels/2pdfm/test_2pdfm.cc
deleted file mode 100644
index f51fbce54c..0000000000
--- a/test/boxmodels/2pdfm/test_2pdfm.cc
+++ /dev/null
@@ -1,136 +0,0 @@
-/*****************************************************************************
- *   See the file COPYING for full copying permissions.                      *
- *                                                                           *
- *   This program is free software: you can redistribute it and/or modify    *
- *   it under the terms of the GNU General Public License as published by    *
- *   the Free Software Foundation, either version 2 of the License, or       *
- *   (at your option) any later version.                                     *
- *                                                                           *
- *   This program is distributed in the hope that it will be useful,         *
- *   but WITHOUT ANY WARRANTY; without even the implied warranty of          *
- *   MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the            *
- *   GNU General Public License for more details.                            *
- *                                                                           *
- *   You should have received a copy of the GNU General Public License       *
- *   along with this program. If not, see <http://www.gnu.org/licenses/>.    *
- *****************************************************************************/
-/*!
- * \file
- *
- * \brief Test for the two-phase flow with discrete fracture-matrix (discrete
- *        fracture model) and box model scheme.
- */
-#include "config.h"
-
-#include "2pdfmtestproblem.hh"
-#include <dumux/common/start.hh>
-
-/*!
- * \brief Provides an interface for customizing error messages associated with
- *        reading in parameters.
- *
- * \param progName  The name of the program, that was tried to be started.
- */
-void usage(const char *progName)
-{
-    std::string errorMessageOut = "\nUsage: ";
-                errorMessageOut += progName;
-                errorMessageOut += " [--restart restartTime] grid tEnd dt\n";
-    std::cout << errorMessageOut << std::endl;
-    exit(1);
-}
-
-////////////////////////
-// the main function
-////////////////////////
-int main(int argc, char** argv)
-{
-    try {
-        FILE *file;
-        typedef TTAG(TwoPDFMTestProblem) TypeTag;
-        typedef GET_PROP_TYPE(TypeTag, Scalar) Scalar;
-        typedef GET_PROP_TYPE(TypeTag, TimeManager) TimeManager;
-        typedef GET_PROP_TYPE(TypeTag, Grid) Grid;
-        typedef GET_PROP_TYPE(TypeTag, Problem) Problem;
-        typedef Dune::FieldVector<Scalar, Grid::dimensionworld> GlobalPosition;
-
-        // initialize MPI, finalize is done automatically on exit
-        Dune::MPIHelper::instance(argc, argv);
-
-        ////////////////////////////////////////////////////////////
-        // parse the command line arguments
-        ////////////////////////////////////////////////////////////
-        if (argc < 4)
-        {
-            usage(argv[0]);
-        }
-
-        // deal with the restart stuff
-        int argPos = 1;
-        bool restart = false;
-        double restartTime = 0;
-        if (std::string("--restart") == argv[argPos])
-        {
-            restart = true;
-            ++argPos;
-
-            std::istringstream(argv[argPos++]) >> restartTime;
-        }
-
-        if (argc - argPos != 3)
-        {
-            usage(argv[0]);
-        }
-
-        // read the initial time step and the end time
-        double tEnd, dt;
-        const char *artFileName = argv[argPos++];
-        std::istringstream(argv[argPos++]) >> tEnd;
-        std::istringstream(argv[argPos++]) >> dt;
-        file = fopen(artFileName,"r");
-        if (file == NULL)
-        {
-            std::cout << "Could not open artmesh file '" 
-                      << artFileName << "'" << std::endl;
-            exit(1);
-        }
-
-        ////////////////////////////////////////////////////////////
-        // create the grid from ART Reader
-        ////////////////////////////////////////////////////////////
-
-        Dumux::ArtReader<Grid> dfmArtmeshGeometry; // instantiate ArtReader
-        Grid *gridT;
-        dfmArtmeshGeometry.read_art_file(artFileName);
-        gridT = dfmArtmeshGeometry.createGrid();
-        gridT->loadBalance();
-        Dumux::FractureMapper<Grid> ModelARTReader(*gridT, dfmArtmeshGeometry); // map fractures to grid
-        ModelARTReader.fractureMapper();
-
-        ////////////////////////////////////////////////////////////
-        // instantiate and run the concrete problem
-        ////////////////////////////////////////////////////////////
-        // instantiate and run the concrete problem
-        TimeManager timeManager;
-        Problem problem(timeManager,
-                            gridT->leafView(),
-                            ModelARTReader.isDuneFractureVertex_,
-                            ModelARTReader.isDuneFractureEdge_,
-                            ModelARTReader.fractureEdgesIdx_);
-        timeManager.init(problem, 0, dt, tEnd, restart);
-        if (restart)
-        {
-            problem.restart(restartTime);
-        }
-        timeManager.run();
-        return 0;
-    }
-    catch (Dune::Exception &e) {
-        std::cerr << "Dune reported error: " << e << std::endl;
-    }
-    catch (...) {
-        std::cerr << "Unknown exception thrown!\n";
-        throw;
-    }
-    return EXIT_SUCCESS;
-}
diff --git a/test/boxmodels/1p/1ptest-reference.vtu b/test/implicit/1p/1ptest-reference.vtu
similarity index 100%
rename from test/boxmodels/1p/1ptest-reference.vtu
rename to test/implicit/1p/1ptest-reference.vtu
diff --git a/test/boxmodels/1p/1ptestproblem.hh b/test/implicit/1p/1ptestproblem.hh
similarity index 100%
rename from test/boxmodels/1p/1ptestproblem.hh
rename to test/implicit/1p/1ptestproblem.hh
diff --git a/test/boxmodels/1p/1ptestspatialparams.hh b/test/implicit/1p/1ptestspatialparams.hh
similarity index 100%
rename from test/boxmodels/1p/1ptestspatialparams.hh
rename to test/implicit/1p/1ptestspatialparams.hh
diff --git a/test/boxmodels/1p/CMakeLists.txt b/test/implicit/1p/CMakeLists.txt
similarity index 100%
rename from test/boxmodels/1p/CMakeLists.txt
rename to test/implicit/1p/CMakeLists.txt
diff --git a/test/boxmodels/1p/Makefile.am b/test/implicit/1p/Makefile.am
similarity index 100%
rename from test/boxmodels/1p/Makefile.am
rename to test/implicit/1p/Makefile.am
diff --git a/test/boxmodels/1p/grids/test_1p_1d.dgf b/test/implicit/1p/grids/test_1p_1d.dgf
similarity index 100%
rename from test/boxmodels/1p/grids/test_1p_1d.dgf
rename to test/implicit/1p/grids/test_1p_1d.dgf
diff --git a/test/boxmodels/1p/grids/test_1p_2d.dgf b/test/implicit/1p/grids/test_1p_2d.dgf
similarity index 100%
rename from test/boxmodels/1p/grids/test_1p_2d.dgf
rename to test/implicit/1p/grids/test_1p_2d.dgf
diff --git a/test/boxmodels/1p/grids/test_1p_3d.dgf b/test/implicit/1p/grids/test_1p_3d.dgf
similarity index 100%
rename from test/boxmodels/1p/grids/test_1p_3d.dgf
rename to test/implicit/1p/grids/test_1p_3d.dgf
diff --git a/test/boxmodels/1p/test_1p.cc b/test/implicit/1p/test_1p.cc
similarity index 100%
rename from test/boxmodels/1p/test_1p.cc
rename to test/implicit/1p/test_1p.cc
diff --git a/test/boxmodels/1p/test_1p.input b/test/implicit/1p/test_1p.input
similarity index 100%
rename from test/boxmodels/1p/test_1p.input
rename to test/implicit/1p/test_1p.input
diff --git a/test/boxmodels/1p2c/1p2coutflowproblem.hh b/test/implicit/1p2c/1p2coutflowproblem.hh
similarity index 100%
rename from test/boxmodels/1p2c/1p2coutflowproblem.hh
rename to test/implicit/1p2c/1p2coutflowproblem.hh
diff --git a/test/boxmodels/1p2c/1p2coutflowspatialparams.hh b/test/implicit/1p2c/1p2coutflowspatialparams.hh
similarity index 100%
rename from test/boxmodels/1p2c/1p2coutflowspatialparams.hh
rename to test/implicit/1p2c/1p2coutflowspatialparams.hh
diff --git a/test/boxmodels/1p2c/CMakeLists.txt b/test/implicit/1p2c/CMakeLists.txt
similarity index 100%
rename from test/boxmodels/1p2c/CMakeLists.txt
rename to test/implicit/1p2c/CMakeLists.txt
diff --git a/test/boxmodels/1p2c/Makefile.am b/test/implicit/1p2c/Makefile.am
similarity index 100%
rename from test/boxmodels/1p2c/Makefile.am
rename to test/implicit/1p2c/Makefile.am
diff --git a/test/boxmodels/1p2c/grids/test_1p2c.dgf b/test/implicit/1p2c/grids/test_1p2c.dgf
similarity index 100%
rename from test/boxmodels/1p2c/grids/test_1p2c.dgf
rename to test/implicit/1p2c/grids/test_1p2c.dgf
diff --git a/test/boxmodels/1p2c/outflow-reference.vtu b/test/implicit/1p2c/outflow-reference.vtu
similarity index 100%
rename from test/boxmodels/1p2c/outflow-reference.vtu
rename to test/implicit/1p2c/outflow-reference.vtu
diff --git a/test/boxmodels/1p2c/test_1p2c.cc b/test/implicit/1p2c/test_1p2c.cc
similarity index 100%
rename from test/boxmodels/1p2c/test_1p2c.cc
rename to test/implicit/1p2c/test_1p2c.cc
diff --git a/test/boxmodels/1p2c/test_1p2c.input b/test/implicit/1p2c/test_1p2c.input
similarity index 100%
rename from test/boxmodels/1p2c/test_1p2c.input
rename to test/implicit/1p2c/test_1p2c.input
diff --git a/test/boxmodels/2p/CMakeLists.txt b/test/implicit/2p/CMakeLists.txt
similarity index 100%
rename from test/boxmodels/2p/CMakeLists.txt
rename to test/implicit/2p/CMakeLists.txt
diff --git a/test/boxmodels/2p/Makefile.am b/test/implicit/2p/Makefile.am
similarity index 100%
rename from test/boxmodels/2p/Makefile.am
rename to test/implicit/2p/Makefile.am
diff --git a/test/boxmodels/2p/grids/test_2p.dgf b/test/implicit/2p/grids/test_2p.dgf
similarity index 100%
rename from test/boxmodels/2p/grids/test_2p.dgf
rename to test/implicit/2p/grids/test_2p.dgf
diff --git a/test/boxmodels/2p/lens-reference.vtu b/test/implicit/2p/lens-reference.vtu
similarity index 100%
rename from test/boxmodels/2p/lens-reference.vtu
rename to test/implicit/2p/lens-reference.vtu
diff --git a/test/boxmodels/2p/lensproblem.hh b/test/implicit/2p/lensproblem.hh
similarity index 100%
rename from test/boxmodels/2p/lensproblem.hh
rename to test/implicit/2p/lensproblem.hh
diff --git a/test/boxmodels/2p/lensspatialparams.hh b/test/implicit/2p/lensspatialparams.hh
similarity index 100%
rename from test/boxmodels/2p/lensspatialparams.hh
rename to test/implicit/2p/lensspatialparams.hh
diff --git a/test/boxmodels/2p/test_2p.cc b/test/implicit/2p/test_2p.cc
similarity index 100%
rename from test/boxmodels/2p/test_2p.cc
rename to test/implicit/2p/test_2p.cc
diff --git a/test/boxmodels/2p/test_2p.input b/test/implicit/2p/test_2p.input
similarity index 100%
rename from test/boxmodels/2p/test_2p.input
rename to test/implicit/2p/test_2p.input
diff --git a/test/boxmodels/2p2c/CMakeLists.txt b/test/implicit/2p2c/CMakeLists.txt
similarity index 100%
rename from test/boxmodels/2p2c/CMakeLists.txt
rename to test/implicit/2p2c/CMakeLists.txt
diff --git a/test/boxmodels/2p2c/Makefile.am b/test/implicit/2p2c/Makefile.am
similarity index 100%
rename from test/boxmodels/2p2c/Makefile.am
rename to test/implicit/2p2c/Makefile.am
diff --git a/test/boxmodels/2p2c/grids/test_2p2c.dgf b/test/implicit/2p2c/grids/test_2p2c.dgf
similarity index 100%
rename from test/boxmodels/2p2c/grids/test_2p2c.dgf
rename to test/implicit/2p2c/grids/test_2p2c.dgf
diff --git a/test/boxmodels/2p2c/injection-reference.vtu b/test/implicit/2p2c/injection-reference.vtu
similarity index 100%
rename from test/boxmodels/2p2c/injection-reference.vtu
rename to test/implicit/2p2c/injection-reference.vtu
diff --git a/test/boxmodels/2p2c/injectionproblem.hh b/test/implicit/2p2c/injectionproblem.hh
similarity index 100%
rename from test/boxmodels/2p2c/injectionproblem.hh
rename to test/implicit/2p2c/injectionproblem.hh
diff --git a/test/boxmodels/2p2c/injectionspatialparams.hh b/test/implicit/2p2c/injectionspatialparams.hh
similarity index 100%
rename from test/boxmodels/2p2c/injectionspatialparams.hh
rename to test/implicit/2p2c/injectionspatialparams.hh
diff --git a/test/boxmodels/2p2c/test_2p2c.cc b/test/implicit/2p2c/test_2p2c.cc
similarity index 100%
rename from test/boxmodels/2p2c/test_2p2c.cc
rename to test/implicit/2p2c/test_2p2c.cc
diff --git a/test/boxmodels/2p2c/test_2p2c.input b/test/implicit/2p2c/test_2p2c.input
similarity index 100%
rename from test/boxmodels/2p2c/test_2p2c.input
rename to test/implicit/2p2c/test_2p2c.input
diff --git a/test/boxmodels/2p2cni/CMakeLists.txt b/test/implicit/2p2cni/CMakeLists.txt
similarity index 100%
rename from test/boxmodels/2p2cni/CMakeLists.txt
rename to test/implicit/2p2cni/CMakeLists.txt
diff --git a/test/boxmodels/2p2cni/Makefile.am b/test/implicit/2p2cni/Makefile.am
similarity index 100%
rename from test/boxmodels/2p2cni/Makefile.am
rename to test/implicit/2p2cni/Makefile.am
diff --git a/test/boxmodels/2p2cni/grids/test_2p2cni.dgf b/test/implicit/2p2cni/grids/test_2p2cni.dgf
similarity index 100%
rename from test/boxmodels/2p2cni/grids/test_2p2cni.dgf
rename to test/implicit/2p2cni/grids/test_2p2cni.dgf
diff --git a/test/boxmodels/2p2cni/test_2p2cni.cc b/test/implicit/2p2cni/test_2p2cni.cc
similarity index 100%
rename from test/boxmodels/2p2cni/test_2p2cni.cc
rename to test/implicit/2p2cni/test_2p2cni.cc
diff --git a/test/boxmodels/2p2cni/test_2p2cni.input b/test/implicit/2p2cni/test_2p2cni.input
similarity index 100%
rename from test/boxmodels/2p2cni/test_2p2cni.input
rename to test/implicit/2p2cni/test_2p2cni.input
diff --git a/test/boxmodels/2p2cni/waterair-reference.vtu b/test/implicit/2p2cni/waterair-reference.vtu
similarity index 100%
rename from test/boxmodels/2p2cni/waterair-reference.vtu
rename to test/implicit/2p2cni/waterair-reference.vtu
diff --git a/test/boxmodels/2p2cni/waterairproblem.hh b/test/implicit/2p2cni/waterairproblem.hh
similarity index 100%
rename from test/boxmodels/2p2cni/waterairproblem.hh
rename to test/implicit/2p2cni/waterairproblem.hh
diff --git a/test/boxmodels/2p2cni/waterairspatialparams.hh b/test/implicit/2p2cni/waterairspatialparams.hh
similarity index 100%
rename from test/boxmodels/2p2cni/waterairspatialparams.hh
rename to test/implicit/2p2cni/waterairspatialparams.hh
diff --git a/test/boxmodels/2pdfm/2pdfmspatialparams.hh b/test/implicit/2pdfm/2pdfmspatialparams.hh
similarity index 74%
rename from test/boxmodels/2pdfm/2pdfmspatialparams.hh
rename to test/implicit/2pdfm/2pdfmspatialparams.hh
index 425476ece7..bda6131572 100644
--- a/test/boxmodels/2pdfm/2pdfmspatialparams.hh
+++ b/test/implicit/2pdfm/2pdfmspatialparams.hh
@@ -24,7 +24,6 @@
 #define DUMUX_TEST_2PDFM_SPATIAL_PARAMETERS_HH
 
 #include <dumux/boxmodels/2pdfm/2pdfmmodel.hh>
-#include <dumux/io/artmeshreader.hh>
 #include <dumux/material/fluidmatrixinteractions/2p/efftoabslaw.hh>
 #include <dumux/material/fluidmatrixinteractions/2p/regularizedbrookscorey.hh>
 #include <dumux/material/spatialparams/boxspatialparams.hh>
@@ -34,18 +33,18 @@ namespace Dumux
 
 //forward declaration
 template<class TypeTag>
-class TwoPDFMSpatialParameters;
+class TwoPDFMSpatialParams;
 
 namespace Properties
 {
 // The spatial parameters TypeTag
-NEW_TYPE_TAG(TwoPDFMSpatialParameters);
+NEW_TYPE_TAG(TwoPDFMSpatialParams);
 
 // Set the spatial parameters
-SET_TYPE_PROP(TwoPDFMSpatialParameters, SpatialParams, Dumux::TwoPDFMSpatialParameters<TypeTag>);
+SET_TYPE_PROP(TwoPDFMSpatialParams, SpatialParams, Dumux::TwoPDFMSpatialParams<TypeTag>);
 
 // Set the material Law
-SET_PROP(TwoPDFMSpatialParameters, MaterialLaw)
+SET_PROP(TwoPDFMSpatialParams, MaterialLaw)
 {
 private:
     // define the material law which is parameterized by effective
@@ -64,7 +63,7 @@ public:
  *        twophase box model
  */
 template<class TypeTag>
-class TwoPDFMSpatialParameters : public BoxSpatialParams<TypeTag>
+class TwoPDFMSpatialParams : public BoxSpatialParams<TypeTag>
 {
 
     template<int dim>
@@ -75,14 +74,6 @@ class TwoPDFMSpatialParameters : public BoxSpatialParams<TypeTag>
             return gt.dim() == dim - 1;
         }
     };
-    template<int dim>
-    struct VertexLayout
-    {
-        bool contains (Dune::GeometryType gt)
-        {
-            return gt.dim() == 0;
-        }
-    };
 
     typedef BoxSpatialParams<TypeTag> ParentType;
     typedef typename GET_PROP_TYPE(TypeTag, Grid) Grid;
@@ -90,8 +81,8 @@ class TwoPDFMSpatialParameters : public BoxSpatialParams<TypeTag>
     typedef typename GET_PROP_TYPE(TypeTag, Scalar) Scalar;
     typedef typename Grid::ctype CoordScalar;
 
-    typedef Dune::MultipleCodimMultipleGeomTypeMapper<GridView,VertexLayout> VertexMapper;
-    typedef Dune::MultipleCodimMultipleGeomTypeMapper<GridView,FaceLayout> FaceMapper;
+    typedef Dune::MultipleCodimMultipleGeomTypeMapper<GridView, Dune::MCMGVertexLayout> VertexMapper;
+    typedef Dune::MultipleCodimMultipleGeomTypeMapper<GridView, FaceLayout> FaceMapper;
 
     enum {
         dim = GridView::dimension,
@@ -108,21 +99,13 @@ public:
     typedef typename GET_PROP_TYPE(TypeTag, MaterialLaw) MaterialLaw;
     typedef typename MaterialLaw::Params MaterialLawParams;
 
-    TwoPDFMSpatialParameters(const GridView& gridView)
-        : ParentType(gridView)
+    TwoPDFMSpatialParams(const GridView& gridView)
+        : ParentType(gridView), gridView_(gridView),
+        faceMapper_(gridView), vertexMapper_(gridView),
+        fractureMapper_(gridView)
     {
-        gridView_     = 0;
-        facemapper_   = 0;
-        vertexmapper_ = 0;
-
-        setupFractureMatrixSoilParameters();
-    }
+        inactivateFractures_ = false;
 
-    /**
-     * Set the soil properties of fractures and domain.
-     */
-    void setupFractureMatrixSoilParameters()
-    {
         Scalar mD = 1e-12 * 1e-3; //miliDarcy
 
         SwrF_    = 0.00;
@@ -150,6 +133,8 @@ public:
         porosityMatrix_   =    0.25;
         porosityFracture_ = 0.10;
         fractureWidth_    = 1e-2;
+
+        fractureMapper_.map();
     }
 
     /*!
@@ -234,7 +219,7 @@ public:
                                                     const FVElementGeometry &fvGeometry,
                                                     int scvIdx) const
     {
-        int globalIdx = vertexmapper().map(element, scvIdx, dim);
+        DUNE_UNUSED int globalIdx = vertexMapper_.map(element, scvIdx, dim);
 
         // be picky if called for non-fracture vertices
         assert(isVertexFracture(globalIdx));
@@ -254,8 +239,8 @@ public:
         {
             return false;
         }
-        int globalIdx = vertexmapper().map(element, localVertexIdx, dim);
-        return isDuneFractureVertex_[globalIdx];
+        int globalIdx = vertexMapper_.map(element, localVertexIdx, dim);
+        return fractureMapper_.isDuneFractureVertex(globalIdx);
     }
 
     /*!
@@ -269,7 +254,7 @@ public:
         {
             return false;
         }
-        return isDuneFractureVertex_[globalIdx];
+        return fractureMapper_.isDuneFractureVertex(globalIdx);
     }
 
     /*!
@@ -280,22 +265,10 @@ public:
      */
     bool isEdgeFracture(const Element &element, int localFaceIdx) const
     {
-        int globalIdx = facemapper().map(element, localFaceIdx, 1);
-        return isDuneFractureEdge_[globalIdx];
+        int globalIdx = faceMapper_.map(element, localFaceIdx, 1);
+        return fractureMapper_.isDuneFractureEdge(globalIdx);
     }
 
-    /*!
-     * \brief Returns the vertex mapper.
-     */
-    const VertexMapper &vertexmapper() const
-    { return *vertexmapper_; }
-
-    /*!
-     * \brief Returns the face mapper.
-     */
-    const FaceMapper &facemapper() const
-    { return *facemapper_; }
-
     /*!
      * \brief Returns the width of the fracture.
      * 
@@ -317,41 +290,6 @@ public:
         return fractureWidth_;
     }
 
-    /*!
-     * \brief Set the grid view.
-     * 
-     * \param gv The new grid view to be set.
-     */
-    void setGridView(const GridView &gv)
-     {
-        delete gridView_;
-        delete facemapper_;
-        delete vertexmapper_;
-
-        gridView_ = new GridView(gv);
-        facemapper_ = new FaceMapper(gv);
-        vertexmapper_ = new VertexMapper(gv);
-     }
-
-    /*!
-     * \brief Set which vertices and edges are fractures.
-     * 
-     * \param isDuneFractureVertex Vector of bools which indicates fracture vertices
-     * \param isDuneFractureEdge Vector of bools which indicates fracture edges
-     * \param fractureEdgesIdx Vector of edge indices which are fractures
-     * \param inactivateFractures Deactivates fractures
-     */
-    const void setFractureBoolVectors(const std::vector<bool>& isDuneFractureVertex,
-                                      const std::vector<bool>& isDuneFractureEdge,
-                                      const std::vector<int>& fractureEdgesIdx,
-                                      bool inactivateFractures)
-    {
-        isDuneFractureVertex_ = isDuneFractureVertex;
-        isDuneFractureEdge_   = isDuneFractureEdge;
-        inactivateFractures_  = inactivateFractures;
-        fractureEdgesIdx_     = fractureEdgesIdx;
-    }
-    
     Scalar SwrF_;
     Scalar SwrM_;
     Scalar SnrF_;
@@ -362,8 +300,6 @@ public:
     Scalar pdM_;
 
 private:
-    MaterialLawParams materialParams_;
-
     Scalar KMatrix_;
     Scalar KFracture_;
     Scalar porosityMatrix_;
@@ -375,14 +311,11 @@ private:
     MaterialLawParams rockMatrixMaterialParams_;
     bool inactivateFractures_;
 
-    std::vector<bool> isFracture_;
-    std::vector<bool> isDuneFractureVertex_;
-    std::vector<bool> isDuneFractureEdge_;
-    std::vector<int>  fractureEdgesIdx_;
-
-    VertexMapper *vertexmapper_;
-    FaceMapper *facemapper_;
-    GridView *gridView_;
+    const GridView gridView_;
+    const FaceMapper faceMapper_;
+    const VertexMapper vertexMapper_;
+    
+    Dumux::FractureMapper<TypeTag> fractureMapper_;
 };
 
 } // end namespace
diff --git a/test/boxmodels/2pdfm/2pdfmtestproblem.hh b/test/implicit/2pdfm/2pdfmtestproblem.hh
similarity index 83%
rename from test/boxmodels/2pdfm/2pdfmtestproblem.hh
rename to test/implicit/2pdfm/2pdfmtestproblem.hh
index e36bf1159f..a887e6c65c 100644
--- a/test/boxmodels/2pdfm/2pdfmtestproblem.hh
+++ b/test/implicit/2pdfm/2pdfmtestproblem.hh
@@ -36,6 +36,7 @@
 #include <dumux/material/components/simpleh2o.hh>
 #include <dumux/material/components/dnapl.hh>
 #include <dumux/material/fluidsystems/h2on2fluidsystem.hh>
+#include <dumux/io/artgridcreator.hh>
 
 #include "2pdfmspatialparams.hh"
 
@@ -47,7 +48,7 @@ class TwoPDFMTestProblem;
 
 namespace Properties
 {
-NEW_TYPE_TAG(TwoPDFMTestProblem, INHERITS_FROM(BoxTwoPDFM, TwoPDFMSpatialParameters));
+NEW_TYPE_TAG(TwoPDFMTestProblem, INHERITS_FROM(BoxTwoPDFM, TwoPDFMSpatialParams));
 
 // Set the grid type
 #if HAVE_UG
@@ -56,6 +57,9 @@ SET_TYPE_PROP(TwoPDFMTestProblem, Grid, Dune::UGGrid<2>);
 SET_TYPE_PROP(TwoPDFMTestProblem, Grid, Dune::YaspGrid<2>);
 #endif
 
+// set the GridCreator property
+SET_TYPE_PROP(TwoPDFMTestProblem, GridCreator, Dumux::ArtGridCreator<TypeTag>);
+
 // Set the problem property
 SET_TYPE_PROP(TwoPDFMTestProblem, Problem, Dumux::TwoPDFMTestProblem<TypeTag>);
 
@@ -145,13 +149,10 @@ class TwoPDFMTestProblem : public PorousMediaBoxProblem<TypeTag>
 
     typedef typename GridView::template Codim<0>::Entity Element;
     typedef typename GridView::template Codim<dim>::Entity Vertex;
-    typedef typename GridView::Intersection Intersection;
-    typedef typename GridView::template Codim<0>::Iterator ElementIterator;
 
     typedef typename GET_PROP_TYPE(TypeTag, PrimaryVariables) PrimaryVariables;
     typedef typename GET_PROP_TYPE(TypeTag, BoundaryTypes) BoundaryTypes;
     typedef typename GET_PROP_TYPE(TypeTag, TimeManager) TimeManager;
-    typedef typename GridType::ctype DT;
 
     typedef typename GET_PROP_TYPE(TypeTag, Scalar) Scalar;
     typedef Dune::FieldVector<Scalar, dimWorld> GlobalPosition;
@@ -167,25 +168,12 @@ public:
      * \param fractureEdgesIdx Vector of edge indices which are fractures
      */
     TwoPDFMTestProblem(TimeManager &timeManager,
-                       const GridView &gridView,
-                       std::vector<bool>& isDuneFractureVertex,
-                       std::vector<bool>& isDuneFractureEdge,
-                       std::vector<int>& fractureEdgesIdx)
+                       const GridView &gridView)
         : ParentType(timeManager, gridView),
-          isDuneFractureVertex_(isDuneFractureVertex),
-          isDuneFractureEdge_(isDuneFractureEdge),
-          fractureEdgesIdx_(fractureEdgesIdx),
           useInterfaceCondition_(true)
     {
         eps_ = 3e-6;
         temperature_ = 273.15 + 20; // -> 20°C
-
-        inactivateFractures_ = false;
-        this->spatialParams().setGridView(gridView);
-        this->spatialParams().setFractureBoolVectors(isDuneFractureVertex_,
-                isDuneFractureEdge_, fractureEdgesIdx_, inactivateFractures_);
-        bboxMin_ = this->bboxMin();
-        bboxMax_ = this->bboxMax();
     }
 
     /*!
@@ -385,51 +373,10 @@ private:
         return globalPos[1] > this->bboxMax()[1] - eps_;
     }
 
-    bool onInlet_(const GlobalPosition &globalPos) const
-    {
-        Scalar width = this->bboxMax()[0] - this->bboxMin()[0];
-        Scalar lambda = (this->bboxMax()[0] - globalPos[0])/width;
-        return onUpperBoundary_(globalPos) && 0.5 < lambda && lambda < 2.0/3.0;
-    }
-
-    bool upperRightCorner(const GlobalPosition &globalPos) const
-    {
-        return ((globalPos[0]>bboxMax_[0] - eps_)
-                &&(globalPos[1]>bboxMax_[1] - eps_));
-    }
-    
-    /*!
-     * \brief Checks whether the fracture intersects the boundary.
-     * 
-     * \param element The current element
-     * \param scvIdx Index of the sub-control volume to be checked
-     */
-    bool isFractureVertexOnBoundary_(const Element &element, int scvIdx) const
-    {
-        const GlobalPosition &globalPos = element.geometry().corner(scvIdx);
-        int globalIdx = this->soil().vertexmapper().map(element, scvIdx, dim);
-
-        int isVF = this->soil().isVertexFracture(globalIdx);
-        return ((isVF && onUpperBoundary_(globalPos))
-                 || (isVF && onLowerBoundary_(globalPos))
-                 || (isVF && onLeftBoundary_(globalPos))
-                 || (isVF && onRightBoundary_(globalPos)));
-    }
-
     Scalar temperature_;
     Scalar eps_;
 
-    GlobalPosition bboxMin_;
-    GlobalPosition bboxMax_;
-    std::vector<bool> isDuneFractureVertex_;
-    std::vector<bool> isDuneFractureEdge_;
-    std::vector<bool> fractureVolFractionVector;
-    std::vector<int> fractureEdgesIdx_;
-    std::vector<Scalar> distNodesOnBoundary;
-
     bool useInterfaceCondition_;
-    bool inactivateFractures_;
-
 };
 } //end namespace
 
diff --git a/test/boxmodels/2pdfm/Makefile.am b/test/implicit/2pdfm/Makefile.am
similarity index 100%
rename from test/boxmodels/2pdfm/Makefile.am
rename to test/implicit/2pdfm/Makefile.am
diff --git a/test/boxmodels/2pdfm/grids/2pdfmartmesh.net b/test/implicit/2pdfm/grids/2pdfmartmesh.net
similarity index 100%
rename from test/boxmodels/2pdfm/grids/2pdfmartmesh.net
rename to test/implicit/2pdfm/grids/2pdfmartmesh.net
diff --git a/test/implicit/2pdfm/test_2pdfm.cc b/test/implicit/2pdfm/test_2pdfm.cc
new file mode 100644
index 0000000000..39e61e87e9
--- /dev/null
+++ b/test/implicit/2pdfm/test_2pdfm.cc
@@ -0,0 +1,62 @@
+/*****************************************************************************
+ *   See the file COPYING for full copying permissions.                      *
+ *                                                                           *
+ *   This program is free software: you can redistribute it and/or modify    *
+ *   it under the terms of the GNU General Public License as published by    *
+ *   the Free Software Foundation, either version 2 of the License, or       *
+ *   (at your option) any later version.                                     *
+ *                                                                           *
+ *   This program is distributed in the hope that it will be useful,         *
+ *   but WITHOUT ANY WARRANTY; without even the implied warranty of          *
+ *   MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the            *
+ *   GNU General Public License for more details.                            *
+ *                                                                           *
+ *   You should have received a copy of the GNU General Public License       *
+ *   along with this program. If not, see <http://www.gnu.org/licenses/>.    *
+ *****************************************************************************/
+/*!
+ * \file
+ *
+ * \brief Test for the two-phase flow with discrete fracture-matrix (discrete
+ *        fracture model) and box model scheme.
+ */
+#include "config.h"
+
+#include "2pdfmtestproblem.hh"
+#include <dumux/common/start.hh>
+
+/*!
+ * \brief Provides an interface for customizing error messages associated with
+ *        reading in parameters.
+ *
+ * \param progName  The name of the program, that was tried to be started.
+ * \param errorMsg  The error message that was issued by the start function.
+ *                  Comprises the thing that went wrong and a general help message.
+ */
+void usage(const char *progName, const std::string &errorMsg)
+{
+    if (errorMsg.size() > 0) {
+        std::string errorMessageOut = "\nUsage: ";
+        errorMessageOut += progName;
+        errorMessageOut += " [options]\n";
+        errorMessageOut += errorMsg;
+        errorMessageOut += "\n\nThe list of mandatory options for this program is:\n"
+        "\t-TimeManager.TEnd              End of the simulation [s] \n"
+        "\t-TimeManager.DtInitial         Initial timestep size [s] \n"
+        "\t-Grid.File                     Name of the file containing the grid \n"
+        "\t                               definition in ART format\n"
+        "\n";
+        
+        std::cout << errorMessageOut
+        << "\n";
+    }
+}
+
+////////////////////////
+// the main function
+////////////////////////
+int main(int argc, char** argv)
+{
+    typedef TTAG(TwoPDFMTestProblem) ProblemTypeTag;
+    return Dumux::start<ProblemTypeTag>(argc, argv, usage);
+}
diff --git a/test/implicit/2pdfm/test_2pdfm.input b/test/implicit/2pdfm/test_2pdfm.input
new file mode 100644
index 0000000000..538324350a
--- /dev/null
+++ b/test/implicit/2pdfm/test_2pdfm.input
@@ -0,0 +1,28 @@
+###############################################################
+# Parameter file for test_2pdfm.
+# Everything behind a '#' is a comment.
+# Type "./test_2pdfm --help" for more information.
+###############################################################
+
+###############################################################
+# Mandatory arguments
+###############################################################
+
+[TimeManager]
+DtInitial = 1 # [s]
+TEnd = 20 # [s]
+
+[Grid]
+File = ./grids/2pdfmartmesh.net 
+
+###############################################################
+# Simulation restart
+#
+# DuMux simulations can be restarted from *.drs files
+# Set Restart to the value of a specific file, 
+# e.g.:  'Restart = 27184.1' for the restart file
+# name_time=27184.1_rank=0.drs
+# Please comment in the two lines below, if restart is desired.
+###############################################################
+# [TimeManager]
+# Restart = ... 
diff --git a/test/boxmodels/2pni/CMakeLists.txt b/test/implicit/2pni/CMakeLists.txt
similarity index 100%
rename from test/boxmodels/2pni/CMakeLists.txt
rename to test/implicit/2pni/CMakeLists.txt
diff --git a/test/boxmodels/2pni/Makefile.am b/test/implicit/2pni/Makefile.am
similarity index 100%
rename from test/boxmodels/2pni/Makefile.am
rename to test/implicit/2pni/Makefile.am
diff --git a/test/boxmodels/2pni/grids/test_2pni.dgf b/test/implicit/2pni/grids/test_2pni.dgf
similarity index 100%
rename from test/boxmodels/2pni/grids/test_2pni.dgf
rename to test/implicit/2pni/grids/test_2pni.dgf
diff --git a/test/boxmodels/2pni/injection2pni-reference.vtu b/test/implicit/2pni/injection2pni-reference.vtu
similarity index 100%
rename from test/boxmodels/2pni/injection2pni-reference.vtu
rename to test/implicit/2pni/injection2pni-reference.vtu
diff --git a/test/boxmodels/2pni/injectionproblem2pni.hh b/test/implicit/2pni/injectionproblem2pni.hh
similarity index 100%
rename from test/boxmodels/2pni/injectionproblem2pni.hh
rename to test/implicit/2pni/injectionproblem2pni.hh
diff --git a/test/boxmodels/2pni/test_2pni.cc b/test/implicit/2pni/test_2pni.cc
similarity index 100%
rename from test/boxmodels/2pni/test_2pni.cc
rename to test/implicit/2pni/test_2pni.cc
diff --git a/test/boxmodels/2pni/test_2pni.input b/test/implicit/2pni/test_2pni.input
similarity index 100%
rename from test/boxmodels/2pni/test_2pni.input
rename to test/implicit/2pni/test_2pni.input
diff --git a/test/boxmodels/3p3c/CMakeLists.txt b/test/implicit/3p3c/CMakeLists.txt
similarity index 100%
rename from test/boxmodels/3p3c/CMakeLists.txt
rename to test/implicit/3p3c/CMakeLists.txt
diff --git a/test/boxmodels/3p3c/Makefile.am b/test/implicit/3p3c/Makefile.am
similarity index 100%
rename from test/boxmodels/3p3c/Makefile.am
rename to test/implicit/3p3c/Makefile.am
diff --git a/test/boxmodels/3p3c/grids/test_3p3c.dgf b/test/implicit/3p3c/grids/test_3p3c.dgf
similarity index 100%
rename from test/boxmodels/3p3c/grids/test_3p3c.dgf
rename to test/implicit/3p3c/grids/test_3p3c.dgf
diff --git a/test/boxmodels/3p3c/grids/test_3p3c_coarse.dgf b/test/implicit/3p3c/grids/test_3p3c_coarse.dgf
similarity index 100%
rename from test/boxmodels/3p3c/grids/test_3p3c_coarse.dgf
rename to test/implicit/3p3c/grids/test_3p3c_coarse.dgf
diff --git a/test/boxmodels/3p3c/infiltration-reference.vtu b/test/implicit/3p3c/infiltration-reference.vtu
similarity index 100%
rename from test/boxmodels/3p3c/infiltration-reference.vtu
rename to test/implicit/3p3c/infiltration-reference.vtu
diff --git a/test/boxmodels/3p3c/infiltrationproblem.hh b/test/implicit/3p3c/infiltrationproblem.hh
similarity index 100%
rename from test/boxmodels/3p3c/infiltrationproblem.hh
rename to test/implicit/3p3c/infiltrationproblem.hh
diff --git a/test/boxmodels/3p3c/infiltrationspatialparameters.hh b/test/implicit/3p3c/infiltrationspatialparameters.hh
similarity index 100%
rename from test/boxmodels/3p3c/infiltrationspatialparameters.hh
rename to test/implicit/3p3c/infiltrationspatialparameters.hh
diff --git a/test/boxmodels/3p3c/test_3p3c.cc b/test/implicit/3p3c/test_3p3c.cc
similarity index 100%
rename from test/boxmodels/3p3c/test_3p3c.cc
rename to test/implicit/3p3c/test_3p3c.cc
diff --git a/test/boxmodels/3p3c/test_3p3c.input b/test/implicit/3p3c/test_3p3c.input
similarity index 100%
rename from test/boxmodels/3p3c/test_3p3c.input
rename to test/implicit/3p3c/test_3p3c.input
diff --git a/test/boxmodels/3p3cni/CMakeLists.txt b/test/implicit/3p3cni/CMakeLists.txt
similarity index 100%
rename from test/boxmodels/3p3cni/CMakeLists.txt
rename to test/implicit/3p3cni/CMakeLists.txt
diff --git a/test/boxmodels/3p3cni/Makefile.am b/test/implicit/3p3cni/Makefile.am
similarity index 100%
rename from test/boxmodels/3p3cni/Makefile.am
rename to test/implicit/3p3cni/Makefile.am
diff --git a/test/boxmodels/3p3cni/column3p3cni-reference.vtu b/test/implicit/3p3cni/column3p3cni-reference.vtu
similarity index 100%
rename from test/boxmodels/3p3cni/column3p3cni-reference.vtu
rename to test/implicit/3p3cni/column3p3cni-reference.vtu
diff --git a/test/boxmodels/3p3cni/columnxylolproblem.hh b/test/implicit/3p3cni/columnxylolproblem.hh
similarity index 100%
rename from test/boxmodels/3p3cni/columnxylolproblem.hh
rename to test/implicit/3p3cni/columnxylolproblem.hh
diff --git a/test/boxmodels/3p3cni/columnxylolspatialparams.hh b/test/implicit/3p3cni/columnxylolspatialparams.hh
similarity index 100%
rename from test/boxmodels/3p3cni/columnxylolspatialparams.hh
rename to test/implicit/3p3cni/columnxylolspatialparams.hh
diff --git a/test/boxmodels/3p3cni/grids/column.dgf b/test/implicit/3p3cni/grids/column.dgf
similarity index 100%
rename from test/boxmodels/3p3cni/grids/column.dgf
rename to test/implicit/3p3cni/grids/column.dgf
diff --git a/test/boxmodels/3p3cni/grids/kuev_3p3cni.dgf b/test/implicit/3p3cni/grids/kuev_3p3cni.dgf
similarity index 100%
rename from test/boxmodels/3p3cni/grids/kuev_3p3cni.dgf
rename to test/implicit/3p3cni/grids/kuev_3p3cni.dgf
diff --git a/test/boxmodels/3p3cni/grids/kuev_3p3cni_coarse.dgf b/test/implicit/3p3cni/grids/kuev_3p3cni_coarse.dgf
similarity index 100%
rename from test/boxmodels/3p3cni/grids/kuev_3p3cni_coarse.dgf
rename to test/implicit/3p3cni/grids/kuev_3p3cni_coarse.dgf
diff --git a/test/boxmodels/3p3cni/kuevetteproblem.hh b/test/implicit/3p3cni/kuevetteproblem.hh
similarity index 100%
rename from test/boxmodels/3p3cni/kuevetteproblem.hh
rename to test/implicit/3p3cni/kuevetteproblem.hh
diff --git a/test/boxmodels/3p3cni/kuevettespatialparams.hh b/test/implicit/3p3cni/kuevettespatialparams.hh
similarity index 100%
rename from test/boxmodels/3p3cni/kuevettespatialparams.hh
rename to test/implicit/3p3cni/kuevettespatialparams.hh
diff --git a/test/boxmodels/3p3cni/test_3p3cni.cc b/test/implicit/3p3cni/test_3p3cni.cc
similarity index 100%
rename from test/boxmodels/3p3cni/test_3p3cni.cc
rename to test/implicit/3p3cni/test_3p3cni.cc
diff --git a/test/boxmodels/3p3cni/test_3p3cni.input b/test/implicit/3p3cni/test_3p3cni.input
similarity index 100%
rename from test/boxmodels/3p3cni/test_3p3cni.input
rename to test/implicit/3p3cni/test_3p3cni.input
diff --git a/test/boxmodels/CMakeLists.txt b/test/implicit/CMakeLists.txt
similarity index 100%
rename from test/boxmodels/CMakeLists.txt
rename to test/implicit/CMakeLists.txt
diff --git a/test/boxmodels/Makefile.am b/test/implicit/Makefile.am
similarity index 100%
rename from test/boxmodels/Makefile.am
rename to test/implicit/Makefile.am
diff --git a/test/boxmodels/co2/CMakeLists.txt b/test/implicit/co2/CMakeLists.txt
similarity index 100%
rename from test/boxmodels/co2/CMakeLists.txt
rename to test/implicit/co2/CMakeLists.txt
diff --git a/test/boxmodels/co2/Makefile.am b/test/implicit/co2/Makefile.am
similarity index 100%
rename from test/boxmodels/co2/Makefile.am
rename to test/implicit/co2/Makefile.am
diff --git a/test/boxmodels/co2/co2-reference.vtu b/test/implicit/co2/co2-reference.vtu
similarity index 100%
rename from test/boxmodels/co2/co2-reference.vtu
rename to test/implicit/co2/co2-reference.vtu
diff --git a/test/boxmodels/co2/co2values.inc b/test/implicit/co2/co2values.inc
similarity index 100%
rename from test/boxmodels/co2/co2values.inc
rename to test/implicit/co2/co2values.inc
diff --git a/test/boxmodels/co2/grids/heterogeneousSmall.dgf b/test/implicit/co2/grids/heterogeneousSmall.dgf
similarity index 100%
rename from test/boxmodels/co2/grids/heterogeneousSmall.dgf
rename to test/implicit/co2/grids/heterogeneousSmall.dgf
diff --git a/test/boxmodels/co2/heterogeneousco2tables.hh b/test/implicit/co2/heterogeneousco2tables.hh
similarity index 100%
rename from test/boxmodels/co2/heterogeneousco2tables.hh
rename to test/implicit/co2/heterogeneousco2tables.hh
diff --git a/test/boxmodels/co2/heterogeneousproblem.hh b/test/implicit/co2/heterogeneousproblem.hh
similarity index 100%
rename from test/boxmodels/co2/heterogeneousproblem.hh
rename to test/implicit/co2/heterogeneousproblem.hh
diff --git a/test/boxmodels/co2/heterogeneousspatialparameters.hh b/test/implicit/co2/heterogeneousspatialparameters.hh
similarity index 100%
rename from test/boxmodels/co2/heterogeneousspatialparameters.hh
rename to test/implicit/co2/heterogeneousspatialparameters.hh
diff --git a/test/boxmodels/co2/test_co2.cc b/test/implicit/co2/test_co2.cc
similarity index 100%
rename from test/boxmodels/co2/test_co2.cc
rename to test/implicit/co2/test_co2.cc
diff --git a/test/boxmodels/co2/test_co2.input b/test/implicit/co2/test_co2.input
similarity index 100%
rename from test/boxmodels/co2/test_co2.input
rename to test/implicit/co2/test_co2.input
diff --git a/test/boxmodels/co2ni/CMakeLists.txt b/test/implicit/co2ni/CMakeLists.txt
similarity index 100%
rename from test/boxmodels/co2ni/CMakeLists.txt
rename to test/implicit/co2ni/CMakeLists.txt
diff --git a/test/boxmodels/co2ni/Makefile.am b/test/implicit/co2ni/Makefile.am
similarity index 100%
rename from test/boxmodels/co2ni/Makefile.am
rename to test/implicit/co2ni/Makefile.am
diff --git a/test/boxmodels/co2ni/co2ni-reference.vtu b/test/implicit/co2ni/co2ni-reference.vtu
similarity index 100%
rename from test/boxmodels/co2ni/co2ni-reference.vtu
rename to test/implicit/co2ni/co2ni-reference.vtu
diff --git a/test/boxmodels/co2ni/co2values.inc b/test/implicit/co2ni/co2values.inc
similarity index 100%
rename from test/boxmodels/co2ni/co2values.inc
rename to test/implicit/co2ni/co2values.inc
diff --git a/test/boxmodels/co2ni/grids/heterogeneousSmall.dgf b/test/implicit/co2ni/grids/heterogeneousSmall.dgf
similarity index 100%
rename from test/boxmodels/co2ni/grids/heterogeneousSmall.dgf
rename to test/implicit/co2ni/grids/heterogeneousSmall.dgf
diff --git a/test/boxmodels/co2ni/heterogeneousco2tables.hh b/test/implicit/co2ni/heterogeneousco2tables.hh
similarity index 100%
rename from test/boxmodels/co2ni/heterogeneousco2tables.hh
rename to test/implicit/co2ni/heterogeneousco2tables.hh
diff --git a/test/boxmodels/co2ni/heterogeneousproblemni.hh b/test/implicit/co2ni/heterogeneousproblemni.hh
similarity index 100%
rename from test/boxmodels/co2ni/heterogeneousproblemni.hh
rename to test/implicit/co2ni/heterogeneousproblemni.hh
diff --git a/test/boxmodels/co2ni/heterogeneousspatialparametersni.hh b/test/implicit/co2ni/heterogeneousspatialparametersni.hh
similarity index 100%
rename from test/boxmodels/co2ni/heterogeneousspatialparametersni.hh
rename to test/implicit/co2ni/heterogeneousspatialparametersni.hh
diff --git a/test/boxmodels/co2ni/test_co2ni.cc b/test/implicit/co2ni/test_co2ni.cc
similarity index 100%
rename from test/boxmodels/co2ni/test_co2ni.cc
rename to test/implicit/co2ni/test_co2ni.cc
diff --git a/test/boxmodels/co2ni/test_co2ni.input b/test/implicit/co2ni/test_co2ni.input
similarity index 100%
rename from test/boxmodels/co2ni/test_co2ni.input
rename to test/implicit/co2ni/test_co2ni.input
diff --git a/test/boxmodels/mpnc/CMakeLists.txt b/test/implicit/mpnc/CMakeLists.txt
similarity index 100%
rename from test/boxmodels/mpnc/CMakeLists.txt
rename to test/implicit/mpnc/CMakeLists.txt
diff --git a/test/boxmodels/mpnc/Makefile.am b/test/implicit/mpnc/Makefile.am
similarity index 100%
rename from test/boxmodels/mpnc/Makefile.am
rename to test/implicit/mpnc/Makefile.am
diff --git a/test/boxmodels/mpnc/forchheimer1p-reference.vtp b/test/implicit/mpnc/forchheimer1p-reference.vtp
similarity index 100%
rename from test/boxmodels/mpnc/forchheimer1p-reference.vtp
rename to test/implicit/mpnc/forchheimer1p-reference.vtp
diff --git a/test/boxmodels/mpnc/forchheimer1pproblem.hh b/test/implicit/mpnc/forchheimer1pproblem.hh
similarity index 100%
rename from test/boxmodels/mpnc/forchheimer1pproblem.hh
rename to test/implicit/mpnc/forchheimer1pproblem.hh
diff --git a/test/boxmodels/mpnc/forchheimer2p-reference.vtu b/test/implicit/mpnc/forchheimer2p-reference.vtu
similarity index 100%
rename from test/boxmodels/mpnc/forchheimer2p-reference.vtu
rename to test/implicit/mpnc/forchheimer2p-reference.vtu
diff --git a/test/boxmodels/mpnc/forchheimer2pproblem.hh b/test/implicit/mpnc/forchheimer2pproblem.hh
similarity index 100%
rename from test/boxmodels/mpnc/forchheimer2pproblem.hh
rename to test/implicit/mpnc/forchheimer2pproblem.hh
diff --git a/test/boxmodels/mpnc/forchheimerspatialparams.hh b/test/implicit/mpnc/forchheimerspatialparams.hh
similarity index 100%
rename from test/boxmodels/mpnc/forchheimerspatialparams.hh
rename to test/implicit/mpnc/forchheimerspatialparams.hh
diff --git a/test/boxmodels/mpnc/grids/forchheimer1d.dgf b/test/implicit/mpnc/grids/forchheimer1d.dgf
similarity index 100%
rename from test/boxmodels/mpnc/grids/forchheimer1d.dgf
rename to test/implicit/mpnc/grids/forchheimer1d.dgf
diff --git a/test/boxmodels/mpnc/grids/obstacle_24x16.dgf b/test/implicit/mpnc/grids/obstacle_24x16.dgf
similarity index 100%
rename from test/boxmodels/mpnc/grids/obstacle_24x16.dgf
rename to test/implicit/mpnc/grids/obstacle_24x16.dgf
diff --git a/test/boxmodels/mpnc/grids/obstacle_48x32.dgf b/test/implicit/mpnc/grids/obstacle_48x32.dgf
similarity index 100%
rename from test/boxmodels/mpnc/grids/obstacle_48x32.dgf
rename to test/implicit/mpnc/grids/obstacle_48x32.dgf
diff --git a/test/boxmodels/mpnc/obstacle-reference.vtu b/test/implicit/mpnc/obstacle-reference.vtu
similarity index 100%
rename from test/boxmodels/mpnc/obstacle-reference.vtu
rename to test/implicit/mpnc/obstacle-reference.vtu
diff --git a/test/boxmodels/mpnc/obstacleproblem.hh b/test/implicit/mpnc/obstacleproblem.hh
similarity index 100%
rename from test/boxmodels/mpnc/obstacleproblem.hh
rename to test/implicit/mpnc/obstacleproblem.hh
diff --git a/test/boxmodels/mpnc/obstaclespatialparams.hh b/test/implicit/mpnc/obstaclespatialparams.hh
similarity index 100%
rename from test/boxmodels/mpnc/obstaclespatialparams.hh
rename to test/implicit/mpnc/obstaclespatialparams.hh
diff --git a/test/boxmodels/mpnc/test_forchheimer1p.cc b/test/implicit/mpnc/test_forchheimer1p.cc
similarity index 100%
rename from test/boxmodels/mpnc/test_forchheimer1p.cc
rename to test/implicit/mpnc/test_forchheimer1p.cc
diff --git a/test/boxmodels/mpnc/test_forchheimer1p.input b/test/implicit/mpnc/test_forchheimer1p.input
similarity index 100%
rename from test/boxmodels/mpnc/test_forchheimer1p.input
rename to test/implicit/mpnc/test_forchheimer1p.input
diff --git a/test/boxmodels/mpnc/test_forchheimer2p.cc b/test/implicit/mpnc/test_forchheimer2p.cc
similarity index 100%
rename from test/boxmodels/mpnc/test_forchheimer2p.cc
rename to test/implicit/mpnc/test_forchheimer2p.cc
diff --git a/test/boxmodels/mpnc/test_forchheimer2p.input b/test/implicit/mpnc/test_forchheimer2p.input
similarity index 100%
rename from test/boxmodels/mpnc/test_forchheimer2p.input
rename to test/implicit/mpnc/test_forchheimer2p.input
diff --git a/test/boxmodels/mpnc/test_mpnc.cc b/test/implicit/mpnc/test_mpnc.cc
similarity index 100%
rename from test/boxmodels/mpnc/test_mpnc.cc
rename to test/implicit/mpnc/test_mpnc.cc
diff --git a/test/boxmodels/mpnc/test_mpnc.input b/test/implicit/mpnc/test_mpnc.input
similarity index 100%
rename from test/boxmodels/mpnc/test_mpnc.input
rename to test/implicit/mpnc/test_mpnc.input
diff --git a/test/boxmodels/richards/CMakeLists.txt b/test/implicit/richards/CMakeLists.txt
similarity index 100%
rename from test/boxmodels/richards/CMakeLists.txt
rename to test/implicit/richards/CMakeLists.txt
diff --git a/test/boxmodels/richards/Makefile.am b/test/implicit/richards/Makefile.am
similarity index 100%
rename from test/boxmodels/richards/Makefile.am
rename to test/implicit/richards/Makefile.am
diff --git a/test/boxmodels/richards/grids/richardslens-24x16.dgf b/test/implicit/richards/grids/richardslens-24x16.dgf
similarity index 100%
rename from test/boxmodels/richards/grids/richardslens-24x16.dgf
rename to test/implicit/richards/grids/richardslens-24x16.dgf
diff --git a/test/boxmodels/richards/grids/richardslens-48x32.dgf b/test/implicit/richards/grids/richardslens-48x32.dgf
similarity index 100%
rename from test/boxmodels/richards/grids/richardslens-48x32.dgf
rename to test/implicit/richards/grids/richardslens-48x32.dgf
diff --git a/test/boxmodels/richards/grids/richardslens-96x64.dgf b/test/implicit/richards/grids/richardslens-96x64.dgf
similarity index 100%
rename from test/boxmodels/richards/grids/richardslens-96x64.dgf
rename to test/implicit/richards/grids/richardslens-96x64.dgf
diff --git a/test/boxmodels/richards/richardslens-reference-parallel.vtu b/test/implicit/richards/richardslens-reference-parallel.vtu
similarity index 100%
rename from test/boxmodels/richards/richardslens-reference-parallel.vtu
rename to test/implicit/richards/richardslens-reference-parallel.vtu
diff --git a/test/boxmodels/richards/richardslens-reference.vtu b/test/implicit/richards/richardslens-reference.vtu
similarity index 100%
rename from test/boxmodels/richards/richardslens-reference.vtu
rename to test/implicit/richards/richardslens-reference.vtu
diff --git a/test/boxmodels/richards/richardslensproblem.hh b/test/implicit/richards/richardslensproblem.hh
similarity index 100%
rename from test/boxmodels/richards/richardslensproblem.hh
rename to test/implicit/richards/richardslensproblem.hh
diff --git a/test/boxmodels/richards/richardslensspatialparams.hh b/test/implicit/richards/richardslensspatialparams.hh
similarity index 100%
rename from test/boxmodels/richards/richardslensspatialparams.hh
rename to test/implicit/richards/richardslensspatialparams.hh
diff --git a/test/boxmodels/richards/test_richards.cc b/test/implicit/richards/test_richards.cc
similarity index 100%
rename from test/boxmodels/richards/test_richards.cc
rename to test/implicit/richards/test_richards.cc
diff --git a/test/boxmodels/richards/test_richards.input b/test/implicit/richards/test_richards.input
similarity index 100%
rename from test/boxmodels/richards/test_richards.input
rename to test/implicit/richards/test_richards.input
-- 
GitLab