From 86502f1843c6a2f2249441a6bfbf72c790a88d09 Mon Sep 17 00:00:00 2001
From: Bernd Flemisch <bernd@iws.uni-stuttgart.de>
Date: Fri, 7 Sep 2018 13:40:12 +0200
Subject: [PATCH] [io] improve template parameters for the IOFields

Restore the template parameters for the `IOField`s to the state
when they where `VtkOutputField`s. Add a uniform template parameter
`ModelTraits` to the `primaryVariableName` functions inside the
`IOField`s.
---
 dumux/common/properties.hh                    |  1 +
 dumux/porousmediumflow/1p/iofields.hh         |  2 +-
 dumux/porousmediumflow/1p/model.hh            |  9 ++---
 dumux/porousmediumflow/1pnc/iofields.hh       |  5 +--
 dumux/porousmediumflow/1pnc/model.hh          | 17 +++------
 dumux/porousmediumflow/1pncmin/model.hh       | 20 +++-------
 dumux/porousmediumflow/2p/iofields.hh         |  5 +--
 dumux/porousmediumflow/2p/model.hh            | 19 ++++------
 dumux/porousmediumflow/2p1c/iofields.hh       |  9 +++--
 dumux/porousmediumflow/2p1c/model.hh          |  7 +---
 dumux/porousmediumflow/2p2c/model.hh          | 22 ++---------
 dumux/porousmediumflow/2pnc/iofields.hh       | 31 +++++++--------
 dumux/porousmediumflow/2pnc/model.hh          | 34 +++--------------
 dumux/porousmediumflow/2pncmin/model.hh       | 38 +++----------------
 dumux/porousmediumflow/3p/iofields.hh         |  2 +-
 dumux/porousmediumflow/3p/model.hh            | 18 +--------
 dumux/porousmediumflow/3p3c/iofields.hh       |  5 ++-
 dumux/porousmediumflow/3p3c/model.hh          | 17 +++------
 dumux/porousmediumflow/3pwateroil/iofields.hh |  5 ++-
 dumux/porousmediumflow/3pwateroil/model.hh    |  7 +---
 .../mineralization/iofields.hh                | 10 +++--
 .../nonisothermal/iofields.hh                 |  8 ++--
 dumux/porousmediumflow/nonisothermal/model.hh |  7 +++-
 dumux/porousmediumflow/richards/iofields.hh   |  6 ++-
 dumux/porousmediumflow/richards/model.hh      |  7 ++--
 dumux/porousmediumflow/richardsnc/iofields.hh |  7 ++--
 dumux/porousmediumflow/richardsnc/model.hh    |  8 ++--
 dumux/porousmediumflow/tracer/iofields.hh     |  5 +--
 dumux/porousmediumflow/tracer/model.hh        |  2 +-
 29 files changed, 112 insertions(+), 221 deletions(-)

diff --git a/dumux/common/properties.hh b/dumux/common/properties.hh
index 32e2967186..dafc61396f 100644
--- a/dumux/common/properties.hh
+++ b/dumux/common/properties.hh
@@ -45,6 +45,7 @@ NEW_PROP_TAG(PrimaryVariables);       //!< A vector of primary variables
 NEW_PROP_TAG(NumEqVector);            //!< A vector of size number equations that can be used for Neumann fluxes, sources, residuals, ...
 NEW_PROP_TAG(GridView);               //!< The type of the grid view according to the grid type
 NEW_PROP_TAG(ModelTraits);            //!< Traits class encapsulating model specifications
+NEW_PROP_TAG(BaseModelTraits);        //!< Model traits to be used as a base for nonisothermal, mineralization ... models
 NEW_PROP_TAG(Problem);                //!< Property to specify the type of a problem which has to be solved
 NEW_PROP_TAG(PointSource);            //!< Property defining the type of point source used
 NEW_PROP_TAG(PointSourceHelper);      //!< Property defining the class that computes which sub control volume point sources belong to
diff --git a/dumux/porousmediumflow/1p/iofields.hh b/dumux/porousmediumflow/1p/iofields.hh
index 7b59c37ca2..932dab2912 100644
--- a/dumux/porousmediumflow/1p/iofields.hh
+++ b/dumux/porousmediumflow/1p/iofields.hh
@@ -51,7 +51,7 @@ public:
         initOutputModule(out);
     }
 
-    template <class FluidSystem = void, class SolidSystem = void>
+    template <class ModelTraits = void, class FluidSystem = void, class SolidSystem = void>
     static std::string primaryVariableName(int pvIdx = 0, int state = 0)
     {
         return IOName::pressure();
diff --git a/dumux/porousmediumflow/1p/model.hh b/dumux/porousmediumflow/1p/model.hh
index e8d2982a42..e79ed569d4 100644
--- a/dumux/porousmediumflow/1p/model.hh
+++ b/dumux/porousmediumflow/1p/model.hh
@@ -121,7 +121,8 @@ NEW_TYPE_TAG(OnePNI, INHERITS_FROM(OneP));
 ///////////////////////////////////////////////////////////////////////////
 SET_TYPE_PROP(OneP, IOFields, OnePIOFields);                          //!< default I/O fields specific to this model
 SET_TYPE_PROP(OneP, LocalResidual, ImmiscibleLocalResidual<TypeTag>); //!< the local residual function
-SET_TYPE_PROP(OneP, ModelTraits, OnePModelTraits);                    //!< states some specifics of the one-phase model
+SET_TYPE_PROP(OneP, BaseModelTraits, OnePModelTraits);                //!< states some specifics of the one-phase model
+SET_TYPE_PROP(OneP, ModelTraits, typename GET_PROP_TYPE(TypeTag, BaseModelTraits)); //!< default the actually used traits to the base traits
 
 //! Set the volume variables property
 SET_PROP(OneP, VolumeVariables)
@@ -160,11 +161,7 @@ public:
 ///////////////////////////////////////////////////////////////////////////
 
 //! Add temperature to the output
-SET_PROP(OnePNI, IOFields)
-{
-    using ModelTraits = typename GET_PROP_TYPE(TypeTag, ModelTraits);
-    using type = EnergyIOFields<OnePIOFields, ModelTraits>;
-};
+SET_TYPE_PROP(OnePNI, IOFields, EnergyIOFields<OnePIOFields>);
 
 //! The model traits of the non-isothermal model
 SET_TYPE_PROP(OnePNI, ModelTraits, PorousMediumFlowNIModelTraits<OnePModelTraits>);
diff --git a/dumux/porousmediumflow/1pnc/iofields.hh b/dumux/porousmediumflow/1pnc/iofields.hh
index 0b4bf08259..c48ba433c8 100644
--- a/dumux/porousmediumflow/1pnc/iofields.hh
+++ b/dumux/porousmediumflow/1pnc/iofields.hh
@@ -34,7 +34,6 @@ namespace Dumux {
  * \ingroup OnePNCModel
  * \brief Adds I/O fields specific to the OnePNC model
  */
-template <bool useMoles>
 class OnePNCIOFields
 {
 public:
@@ -69,12 +68,12 @@ public:
         initOutputModule(out);
     }
 
-    template <class FluidSystem, class SolidSystem = void>
+    template <class ModelTraits, class FluidSystem, class SolidSystem = void>
     static std::string primaryVariableName(int pvIdx, int state = 0)
     {
         if (pvIdx == 0)
             return IOName::pressure();
-        else if (useMoles)
+        else if (ModelTraits::useMoles())
             return IOName::moleFraction<FluidSystem>(0, pvIdx);
         else
             return IOName::massFraction<FluidSystem>(0, pvIdx);
diff --git a/dumux/porousmediumflow/1pnc/model.hh b/dumux/porousmediumflow/1pnc/model.hh
index d293d6330f..7b9fd97c35 100644
--- a/dumux/porousmediumflow/1pnc/model.hh
+++ b/dumux/porousmediumflow/1pnc/model.hh
@@ -149,14 +149,15 @@ NEW_TYPE_TAG(OnePNCNI, INHERITS_FROM(OnePNC));
 //! Set as default that no component mass balance is replaced by the total mass balance
 SET_INT_PROP(OnePNC, ReplaceCompEqIdx, GET_PROP_TYPE(TypeTag, FluidSystem)::numComponents);
 
-//! The model traits. Per default, we use the number of components of the fluid system.
-SET_PROP(OnePNC, ModelTraits)
+//! The base model traits. Per default, we use the number of components of the fluid system.
+SET_PROP(OnePNC, BaseModelTraits)
 {
 private:
     using FluidSystem = typename GET_PROP_TYPE(TypeTag, FluidSystem);
 public:
     using type = OnePNCModelTraits<FluidSystem::numComponents, GET_PROP_VALUE(TypeTag, UseMoles), GET_PROP_VALUE(TypeTag, ReplaceCompEqIdx)>;
 };
+SET_TYPE_PROP(OnePNC, ModelTraits, typename GET_PROP_TYPE(TypeTag, BaseModelTraits)); //!< default the actually used traits to the base traits
 
 
 /*!
@@ -207,19 +208,14 @@ public:
 };
 
 //! Set the vtk output fields specific to this model
-SET_TYPE_PROP(OnePNC, IOFields, OnePNCIOFields<GET_PROP_VALUE(TypeTag, UseMoles)>);
+SET_TYPE_PROP(OnePNC, IOFields, OnePNCIOFields);
 
 ///////////////////////////////////////////////////////////////////////////
 // properties for the non-isothermal single phase model
 ///////////////////////////////////////////////////////////////////////////
 
 //! the non-isothermal vtk output fields
-SET_PROP(OnePNCNI, IOFields)
-{
-    using OnePNCIOF = OnePNCIOFields<GET_PROP_VALUE(TypeTag, UseMoles)>;
-    using ModelTraits = typename GET_PROP_TYPE(TypeTag, ModelTraits);
-    using type = EnergyIOFields<OnePNCIOF, ModelTraits>;
-};
+SET_TYPE_PROP(OnePNCNI, IOFields, EnergyIOFields<OnePNCIOFields>);
 
 //! Use the average for effective conductivities
 SET_TYPE_PROP(OnePNCNI,
@@ -230,8 +226,7 @@ SET_TYPE_PROP(OnePNCNI,
 SET_PROP(OnePNCNI, ModelTraits)
 {
 private:
-    using FluidSystem = typename GET_PROP_TYPE(TypeTag, FluidSystem);
-    using IsothermalTraits = OnePNCModelTraits<FluidSystem::numComponents, GET_PROP_VALUE(TypeTag, UseMoles), GET_PROP_VALUE(TypeTag, ReplaceCompEqIdx)>;
+    using IsothermalTraits = typename GET_PROP_TYPE(TypeTag, BaseModelTraits);
 public:
     using type = PorousMediumFlowNIModelTraits<IsothermalTraits>;
 };
diff --git a/dumux/porousmediumflow/1pncmin/model.hh b/dumux/porousmediumflow/1pncmin/model.hh
index 90fc5c57bb..d03f678254 100644
--- a/dumux/porousmediumflow/1pncmin/model.hh
+++ b/dumux/porousmediumflow/1pncmin/model.hh
@@ -124,9 +124,8 @@ SET_TYPE_PROP(OnePNCMin, LocalResidual, MineralizationLocalResidual<TypeTag>);
 SET_PROP(OnePNCMin, ModelTraits)
 {
 private:
-    using FluidSystem = typename GET_PROP_TYPE(TypeTag, FluidSystem);
     using SolidSystem = typename GET_PROP_TYPE(TypeTag, SolidSystem);
-    using NonMinTraits = OnePNCModelTraits<FluidSystem::numComponents, GET_PROP_VALUE(TypeTag, UseMoles), GET_PROP_VALUE(TypeTag, ReplaceCompEqIdx)>;
+    using NonMinTraits = typename GET_PROP_TYPE(TypeTag, BaseModelTraits);
 public:
     using type = MineralizationModelTraits<NonMinTraits, SolidSystem::numComponents, SolidSystem::numInertComponents>;
 };
@@ -142,12 +141,7 @@ public:
 };
 
 //! Use the mineralization vtk output fields
-SET_PROP(OnePNCMin, IOFields)
-{
-    using OnePNCIOF = OnePNCIOFields<GET_PROP_VALUE(TypeTag, UseMoles)>;
-    using FluidSystem = typename GET_PROP_TYPE(TypeTag, FluidSystem);
-    using type = MineralizationIOFields<OnePNCIOF, FluidSystem::numComponents>;
-};
+SET_TYPE_PROP(OnePNCMin, IOFields, MineralizationIOFields<OnePNCIOFields>);
 
 //////////////////////////////////////////////////////////////////
 // Properties for the non-isothermal 2pncmin model
@@ -156,20 +150,16 @@ SET_PROP(OnePNCMin, IOFields)
 //! non-isothermal vtk output
 SET_PROP(OnePNCMinNI, IOFields)
 {
-    using OnePNCIOF = OnePNCIOFields<GET_PROP_VALUE(TypeTag, UseMoles)>;
-    using FluidSystem = typename GET_PROP_TYPE(TypeTag, FluidSystem);
-    using MineralizationIOF = MineralizationIOFields<OnePNCIOF, FluidSystem::numComponents>;
-    using ModelTraits = typename GET_PROP_TYPE(TypeTag, ModelTraits);
-    using type = EnergyIOFields<MineralizationIOF, ModelTraits>;
+    using MineralizationIOF = MineralizationIOFields<OnePNCIOFields>;
+    using type = EnergyIOFields<MineralizationIOF>;
 };
 
 //! The non-isothermal model traits
 SET_PROP(OnePNCMinNI, ModelTraits)
 {
 private:
-    using FluidSystem = typename GET_PROP_TYPE(TypeTag, FluidSystem);
     using SolidSystem = typename GET_PROP_TYPE(TypeTag, SolidSystem);
-    using OnePNCTraits = OnePNCModelTraits<FluidSystem::numComponents, GET_PROP_VALUE(TypeTag, UseMoles), GET_PROP_VALUE(TypeTag, ReplaceCompEqIdx)>;
+    using OnePNCTraits = typename GET_PROP_TYPE(TypeTag, BaseModelTraits);
     using IsothermalTraits = MineralizationModelTraits<OnePNCTraits, SolidSystem::numComponents, SolidSystem::numInertComponents>;
 public:
     using type = PorousMediumFlowNIModelTraits<IsothermalTraits>;
diff --git a/dumux/porousmediumflow/2p/iofields.hh b/dumux/porousmediumflow/2p/iofields.hh
index a12e9f4ba5..48a97cf540 100644
--- a/dumux/porousmediumflow/2p/iofields.hh
+++ b/dumux/porousmediumflow/2p/iofields.hh
@@ -36,7 +36,6 @@ namespace Dumux {
  * \ingroup TwoPModel
  * \brief Adds I/O fields specific to the two-phase model
  */
-template <TwoPFormulation priVarFormulation>
 class TwoPIOFields
 {
 public:
@@ -71,10 +70,10 @@ public:
         initOutputModule(out);
     }
 
-    template <class FluidSystem, class SolidSystem = void>
+    template <class ModelTraits, class FluidSystem, class SolidSystem = void>
     static std::string primaryVariableName(int pvIdx, int state = 0)
     {
-        if (priVarFormulation == TwoPFormulation::p0s1)
+        if (ModelTraits::priVarFormulation() == TwoPFormulation::p0s1)
             return pvIdx == 0 ? IOName::pressure<FluidSystem>(FluidSystem::phase0Idx)
                               : IOName::saturation<FluidSystem>(FluidSystem::phase1Idx);
         else
diff --git a/dumux/porousmediumflow/2p/model.hh b/dumux/porousmediumflow/2p/model.hh
index 311d498643..91765814df 100644
--- a/dumux/porousmediumflow/2p/model.hh
+++ b/dumux/porousmediumflow/2p/model.hh
@@ -138,8 +138,7 @@ struct TwoPVolumeVariablesTraits
     using SaturationReconstruction = SR;
 };
 
-// forward declaration
-template <TwoPFormulation priVarFormulation>
+// necessary for models derived from 2p
 class TwoPIOFields;
 
 ////////////////////////////////
@@ -166,11 +165,12 @@ SET_PROP(TwoP, Formulation)
 
 SET_TYPE_PROP(TwoP, LocalResidual, ImmiscibleLocalResidual<TypeTag>);         //!< Use the immiscible local residual operator for the 2p model
 
-//! The model traits class
-SET_TYPE_PROP(TwoP, ModelTraits, TwoPModelTraits<GET_PROP_VALUE(TypeTag, Formulation)>);
+//! The base model traits class
+SET_TYPE_PROP(TwoP, BaseModelTraits, TwoPModelTraits<GET_PROP_VALUE(TypeTag, Formulation)>);
+SET_TYPE_PROP(TwoP, ModelTraits, typename GET_PROP_TYPE(TypeTag, BaseModelTraits)); //!< default the actually used traits to the base traits
 
 //! Set the vtk output fields specific to the twop model
-SET_TYPE_PROP(TwoP, IOFields, TwoPIOFields<GET_PROP_VALUE(TypeTag, Formulation)>);
+SET_TYPE_PROP(TwoP, IOFields, TwoPIOFields);
 
 //! Set the volume variables property
 SET_PROP(TwoP, VolumeVariables)
@@ -209,15 +209,10 @@ public:
 ////////////////////////////////////////////////////////
 
 //! The non-isothermal model traits class
-SET_TYPE_PROP(TwoPNI, ModelTraits, PorousMediumFlowNIModelTraits<TwoPModelTraits<GET_PROP_VALUE(TypeTag, Formulation)>>);
+SET_TYPE_PROP(TwoPNI, ModelTraits, PorousMediumFlowNIModelTraits<typename GET_PROP_TYPE(TypeTag, BaseModelTraits)>);
 
 //! Set the vtk output fields specific to the non-isothermal twop model
-SET_PROP(TwoPNI, IOFields)
-{
-    using TwoPIOF = TwoPIOFields<GET_PROP_VALUE(TypeTag, Formulation)>;
-    using ModelTraits = typename GET_PROP_TYPE(TypeTag, ModelTraits);
-    using type = EnergyIOFields<TwoPIOF, ModelTraits>;
-};
+SET_TYPE_PROP(TwoPNI, IOFields, EnergyIOFields<TwoPIOFields>);
 
 //! Somerton is used as default model to compute the effective thermal heat conductivity
 SET_PROP(TwoPNI, ThermalConductivityModel)
diff --git a/dumux/porousmediumflow/2p1c/iofields.hh b/dumux/porousmediumflow/2p1c/iofields.hh
index d2cfe34041..7b43bac9c8 100644
--- a/dumux/porousmediumflow/2p1c/iofields.hh
+++ b/dumux/porousmediumflow/2p1c/iofields.hh
@@ -33,7 +33,6 @@ namespace Dumux {
  * \ingroup TwoPOneCModel
  * \brief Adds I/O fields specific to two-phase one-component model.
  */
-template <TwoPFormulation priVarFormulation, class Indices>
 class TwoPOneCIOFields
 {
 public:
@@ -41,7 +40,7 @@ public:
     static void initOutputModule(OutputModule& out)
     {
         // use default fields from the 2p model
-        TwoPIOFields<priVarFormulation>::initOutputModule(out);
+        TwoPIOFields::initOutputModule(out);
 
         // output additional to TwoP output:
         out.addVolumeVariable([](const auto& v){ return v.priVars().state(); },
@@ -55,10 +54,12 @@ public:
         initOutputModule(out);
     }
 
-    template <class FluidSystem, class SolidSystem = void>
+    template <class ModelTraits, class FluidSystem, class SolidSystem = void>
     static std::string primaryVariableName(int pvIdx, int state)
     {
-        if (priVarFormulation == TwoPFormulation::p0s1)
+        using Indices = typename ModelTraits::Indices;
+
+        if (ModelTraits::priVarFormulation() == TwoPFormulation::p0s1)
             return (pvIdx == 0) ? IOName::pressure<FluidSystem>(FluidSystem::phase0Idx) :
                                   (state == Indices::twoPhases)
                                   ? IOName::saturation<FluidSystem>(FluidSystem::phase1Idx)
diff --git a/dumux/porousmediumflow/2p1c/model.hh b/dumux/porousmediumflow/2p1c/model.hh
index 55ec945241..1d3a3990e9 100644
--- a/dumux/porousmediumflow/2p1c/model.hh
+++ b/dumux/porousmediumflow/2p1c/model.hh
@@ -217,12 +217,7 @@ SET_TYPE_PROP(TwoPOneCNI, ThermalConductivityModel, ThermalConductivitySomerton<
 SET_TYPE_PROP(TwoPOneCNI, ModelTraits, TwoPOneCNIModelTraits<GET_PROP_VALUE(TypeTag, Formulation)>);
 
 //! The non-isothermal vtk output fields.
-SET_PROP(TwoPOneCNI, IOFields)
-{
-    using TwoPOneCIOF = TwoPOneCIOFields<GET_PROP_VALUE(TypeTag, Formulation), TwoPOneCIndices>;
-    using ModelTraits = typename GET_PROP_TYPE(TypeTag, ModelTraits);
-    using type = EnergyIOFields<TwoPOneCIOF, ModelTraits>;
-};
+SET_TYPE_PROP(TwoPOneCNI, IOFields, EnergyIOFields<TwoPOneCIOFields>);
 
 } // end namespace Properties
 } // end namespace Dumux
diff --git a/dumux/porousmediumflow/2p2c/model.hh b/dumux/porousmediumflow/2p2c/model.hh
index a17a3ec7ed..b99b2a7e66 100644
--- a/dumux/porousmediumflow/2p2c/model.hh
+++ b/dumux/porousmediumflow/2p2c/model.hh
@@ -141,7 +141,7 @@ NEW_TYPE_TAG(TwoPTwoCNI, INHERITS_FROM(TwoPTwoC));
 /*!
  * \brief Set the model traits property.
  */
-SET_PROP(TwoPTwoC, ModelTraits)
+SET_PROP(TwoPTwoC, BaseModelTraits)
 {
 private:
     using FluidSystem = typename GET_PROP_TYPE(TypeTag, FluidSystem);
@@ -153,6 +153,7 @@ public:
                                       GET_PROP_VALUE(TypeTag, UseMoles),
                                       GET_PROP_VALUE(TypeTag, ReplaceCompEqIdx) >;
 };
+SET_TYPE_PROP(TwoPTwoC, ModelTraits, typename GET_PROP_TYPE(TypeTag, BaseModelTraits));
 
 //! Use the 2p2c VolumeVariables
 SET_PROP(TwoPTwoC, VolumeVariables)
@@ -187,28 +188,13 @@ SET_BOOL_PROP(TwoPTwoC, UseConstraintSolver, true);
 SET_PROP(TwoPTwoCNI, ModelTraits)
 {
 private:
-    //! we use the number of components specified by the fluid system here
-    using FluidSystem = typename GET_PROP_TYPE(TypeTag, FluidSystem);
-    static_assert(FluidSystem::numComponents == 2, "Only fluid systems with 2 components are supported by the 2p2c model!");
-    static_assert(FluidSystem::numPhases == 2, "Only fluid systems with 2 phases are supported by the 2p2c model!");
-    using IsothermalTraits = TwoPTwoCModelTraits<GET_PROP_VALUE(TypeTag, Formulation),
-                                                 GET_PROP_VALUE(TypeTag, UseMoles),
-                                                 GET_PROP_VALUE(TypeTag, ReplaceCompEqIdx)>;
+    using IsothermalTraits = typename GET_PROP_TYPE(TypeTag, BaseModelTraits);
 public:
     using type = PorousMediumFlowNIModelTraits<IsothermalTraits>;
 };
 
 //! Set non-isothermal output fields
-SET_PROP(TwoPTwoCNI, IOFields)
-{
-    static constexpr auto formulation = GET_PROP_VALUE(TypeTag, Formulation);
-    using Indices = TwoPNCIndices;
-    static constexpr auto useMoles = GET_PROP_VALUE(TypeTag, UseMoles);
-    using ModelTraits = typename GET_PROP_TYPE(TypeTag, ModelTraits);
-    static constexpr auto setMoleFractionsForFirstPhase = true;
-    using TwoPNCIOF = TwoPNCIOFields<formulation, Indices, useMoles, setMoleFractionsForFirstPhase>;
-    using type = EnergyIOFields<TwoPNCIOF, ModelTraits>;
-};
+SET_TYPE_PROP(TwoPTwoCNI, IOFields, EnergyIOFields<TwoPNCIOFields>);
 
 //! Somerton is used as default model to compute the effective thermal heat conductivity
 SET_TYPE_PROP(TwoPTwoCNI, ThermalConductivityModel, ThermalConductivitySomerton<typename GET_PROP_TYPE(TypeTag, Scalar)>);
diff --git a/dumux/porousmediumflow/2pnc/iofields.hh b/dumux/porousmediumflow/2pnc/iofields.hh
index 58ee425377..1f1ef53cd6 100644
--- a/dumux/porousmediumflow/2pnc/iofields.hh
+++ b/dumux/porousmediumflow/2pnc/iofields.hh
@@ -34,7 +34,6 @@ namespace Dumux
  * \ingroup TwoPNCModel
  * \brief Adds I/O fields specific to the TwoPNC model
  */
-template <TwoPFormulation priVarFormulation, class Indices, bool useMoles, bool setMoleFractionsForFirstPhase>
 class TwoPNCIOFields
 {
 public:
@@ -45,7 +44,7 @@ public:
         using FluidSystem = typename VolumeVariables::FluidSystem;
 
         // use default fields from the 2p model
-        TwoPIOFields<priVarFormulation>::initOutputModule(out);
+        TwoPIOFields::initOutputModule(out);
 
         // output additional to TwoP output:
         for (int phaseIdx = 0; phaseIdx < VolumeVariables::numPhases(); ++phaseIdx)
@@ -74,35 +73,37 @@ public:
         initOutputModule(out);
     }
 
-    template <class FluidSystem, class SolidSystem = void>
+    template <class ModelTraits, class FluidSystem, class SolidSystem = void>
     static std::string primaryVariableName(int pvIdx, int state)
     {
+        using Indices = typename ModelTraits::Indices;
+
         int idxSecComps;
         if (state == Indices::firstPhaseOnly
-            || (state == Indices::bothPhases && setMoleFractionsForFirstPhase))
+            || (state == Indices::bothPhases && ModelTraits::setMoleFractionsForFirstPhase()))
             idxSecComps = FluidSystem::phase0Idx;
         else
             idxSecComps = FluidSystem::phase1Idx;
 
         if (pvIdx > 1)
-            return useMoles ? IOName::moleFraction<FluidSystem>(idxSecComps, pvIdx)
-                            : IOName::massFraction<FluidSystem>(idxSecComps, pvIdx);
+            return ModelTraits::useMoles() ? IOName::moleFraction<FluidSystem>(idxSecComps, pvIdx)
+                                           : IOName::massFraction<FluidSystem>(idxSecComps, pvIdx);
 
         const std::vector<std::string> p0s1SwitchedPvNames = {
-            useMoles ? IOName::moleFraction<FluidSystem>(FluidSystem::phase0Idx, FluidSystem::comp1Idx)
-                     : IOName::massFraction<FluidSystem>(FluidSystem::phase0Idx, FluidSystem::comp1Idx),
-            useMoles ? IOName::moleFraction<FluidSystem>(FluidSystem::phase1Idx, FluidSystem::comp0Idx)
-                     : IOName::massFraction<FluidSystem>(FluidSystem::phase1Idx, FluidSystem::comp0Idx),
+            ModelTraits::useMoles() ? IOName::moleFraction<FluidSystem>(FluidSystem::phase0Idx, FluidSystem::comp1Idx)
+                                    : IOName::massFraction<FluidSystem>(FluidSystem::phase0Idx, FluidSystem::comp1Idx),
+            ModelTraits::useMoles() ? IOName::moleFraction<FluidSystem>(FluidSystem::phase1Idx, FluidSystem::comp0Idx)
+                                    : IOName::massFraction<FluidSystem>(FluidSystem::phase1Idx, FluidSystem::comp0Idx),
             IOName::saturation<FluidSystem>(FluidSystem::phase1Idx)};
 
         const std::vector<std::string> p1s0SwitchedPvNames = {
-            useMoles ? IOName::moleFraction<FluidSystem>(FluidSystem::phase0Idx, FluidSystem::comp1Idx)
-                     : IOName::massFraction<FluidSystem>(FluidSystem::phase0Idx, FluidSystem::comp1Idx),
-            useMoles ? IOName::moleFraction<FluidSystem>(FluidSystem::phase1Idx, FluidSystem::comp0Idx)
-                     : IOName::massFraction<FluidSystem>(FluidSystem::phase1Idx, FluidSystem::comp0Idx),
+            ModelTraits::useMoles() ? IOName::moleFraction<FluidSystem>(FluidSystem::phase0Idx, FluidSystem::comp1Idx)
+                                    : IOName::massFraction<FluidSystem>(FluidSystem::phase0Idx, FluidSystem::comp1Idx),
+            ModelTraits::useMoles() ? IOName::moleFraction<FluidSystem>(FluidSystem::phase1Idx, FluidSystem::comp0Idx)
+                                    : IOName::massFraction<FluidSystem>(FluidSystem::phase1Idx, FluidSystem::comp0Idx),
             IOName::saturation<FluidSystem>(FluidSystem::phase0Idx)};
 
-        switch (priVarFormulation)
+        switch (ModelTraits::priVarFormulation())
         {
         case TwoPFormulation::p0s1:
             return pvIdx == 0 ? IOName::pressure<FluidSystem>(FluidSystem::wPhaseIdx)
diff --git a/dumux/porousmediumflow/2pnc/model.hh b/dumux/porousmediumflow/2pnc/model.hh
index c5cfa177db..7deeeefc33 100644
--- a/dumux/porousmediumflow/2pnc/model.hh
+++ b/dumux/porousmediumflow/2pnc/model.hh
@@ -194,7 +194,6 @@ struct TwoPNCVolumeVariablesTraits
     using ModelTraits = MT;
 };
 
-
 namespace Properties {
 //////////////////////////////////////////////////////////////////
 // Type tags
@@ -234,8 +233,8 @@ public:
     using type = TwoPNCVolumeVariables<Traits>;
 };
 
-//! Set the model traits
-SET_PROP(TwoPNC, ModelTraits)
+//! Set the base model traits
+SET_PROP(TwoPNC, BaseModelTraits)
 {
 private:
     //! we use the number of components specified by the fluid system here
@@ -247,16 +246,10 @@ public:
                                    GET_PROP_VALUE(TypeTag, SetMoleFractionsForFirstPhase),
                                    GET_PROP_VALUE(TypeTag, Formulation), GET_PROP_VALUE(TypeTag, ReplaceCompEqIdx)>;
 };
+SET_TYPE_PROP(TwoPNC, ModelTraits, typename GET_PROP_TYPE(TypeTag, BaseModelTraits)); //!< default the actually used traits to the base traits
 
 //! Set the vtk output fields specific to this model
-SET_PROP(TwoPNC, IOFields)
-{
-    static constexpr auto formulation = GET_PROP_VALUE(TypeTag, Formulation);
-    using Indices = TwoPNCIndices;
-    static constexpr auto useMoles = GET_PROP_VALUE(TypeTag, UseMoles);
-    static constexpr auto setMoleFractionsForFirstPhase = GET_PROP_VALUE(TypeTag, SetMoleFractionsForFirstPhase);
-    using type = TwoPNCIOFields<formulation, Indices, useMoles, setMoleFractionsForFirstPhase>;
-};
+SET_TYPE_PROP(TwoPNC, IOFields, TwoPNCIOFields);
 
 SET_TYPE_PROP(TwoPNC, LocalResidual, CompositionalLocalResidual<TypeTag>);                  //!< Use the compositional local residual
 
@@ -290,28 +283,13 @@ public:
 SET_PROP(TwoPNCNI, ModelTraits)
 {
 private:
-    //! we use the number of components specified by the fluid system here
-    using FluidSystem = typename GET_PROP_TYPE(TypeTag, FluidSystem);
-    static_assert(FluidSystem::numPhases == 2, "Only fluid systems with 2 fluid phases are supported by the 2p-nc model!");
-    using IsothermalTraits = TwoPNCModelTraits<FluidSystem::numComponents,
-                                               GET_PROP_VALUE(TypeTag, UseMoles),
-                                               GET_PROP_VALUE(TypeTag, SetMoleFractionsForFirstPhase),
-                                               GET_PROP_VALUE(TypeTag, Formulation), GET_PROP_VALUE(TypeTag, ReplaceCompEqIdx)>;
+    using IsothermalTraits = typename GET_PROP_TYPE(TypeTag, BaseModelTraits);
 public:
     using type = PorousMediumFlowNIModelTraits<IsothermalTraits>;
 };
 
 //! Set non-isothermal output fields
-SET_PROP(TwoPNCNI, IOFields)
-{
-    static constexpr auto formulation = GET_PROP_VALUE(TypeTag, Formulation);
-    using Indices = TwoPNCIndices;
-    static constexpr auto useMoles = GET_PROP_VALUE(TypeTag, UseMoles);
-    using ModelTraits = typename GET_PROP_TYPE(TypeTag, ModelTraits);
-    static constexpr auto setMoleFractionsForFirstPhase = ModelTraits::setMoleFractionsForFirstPhase();
-    using TwoPNCIOF = TwoPNCIOFields<formulation, Indices, useMoles, setMoleFractionsForFirstPhase>;
-    using type = EnergyIOFields<TwoPNCIOF, ModelTraits>;
-};
+SET_TYPE_PROP(TwoPNCNI, IOFields, EnergyIOFields<TwoPNCIOFields>);
 
 //! Somerton is used as default model to compute the effective thermal heat conductivity
 SET_PROP(TwoPNCNI, ThermalConductivityModel)
diff --git a/dumux/porousmediumflow/2pncmin/model.hh b/dumux/porousmediumflow/2pncmin/model.hh
index 84b63f3a1f..ebb7782c09 100644
--- a/dumux/porousmediumflow/2pncmin/model.hh
+++ b/dumux/porousmediumflow/2pncmin/model.hh
@@ -139,29 +139,14 @@ public:
 };
 
 //! Set the vtk output fields specific to this model
-SET_PROP(TwoPNCMin, IOFields)
-{
-    static constexpr auto formulation = GET_PROP_VALUE(TypeTag, Formulation);
-    using Indices = TwoPNCIndices;
-    static constexpr auto useMoles = GET_PROP_VALUE(TypeTag, UseMoles);
-    static constexpr auto setMoleFractionsForFirstPhase = GET_PROP_VALUE(TypeTag, SetMoleFractionsForFirstPhase);
-    using TwoPNCIOF = TwoPNCIOFields<formulation, Indices, useMoles, setMoleFractionsForFirstPhase>;
-    using FluidSystem = typename GET_PROP_TYPE(TypeTag, FluidSystem);
-    using type = MineralizationIOFields<TwoPNCIOF, FluidSystem::numComponents>;
-};
+SET_TYPE_PROP(TwoPNCMin, IOFields, MineralizationIOFields<TwoPNCIOFields>);
 
 //! The 2pnc model traits define the non-mineralization part
 SET_PROP(TwoPNCMin, ModelTraits)
 {
 private:
-    //! we use the number of components specified by the fluid system here
-    using FluidSystem = typename GET_PROP_TYPE(TypeTag, FluidSystem);
-    static_assert(FluidSystem::numPhases == 2, "Only fluid systems with 2 fluid phases are supported by the 2p-nc model!");
     using SolidSystem = typename GET_PROP_TYPE(TypeTag, SolidSystem);
-    using NonMineralizationTraits = TwoPNCModelTraits<FluidSystem::numComponents,
-                                                      GET_PROP_VALUE(TypeTag, UseMoles),
-                                                      GET_PROP_VALUE(TypeTag, SetMoleFractionsForFirstPhase),
-                                                      GET_PROP_VALUE(TypeTag, Formulation), GET_PROP_VALUE(TypeTag, ReplaceCompEqIdx)>;
+    using NonMineralizationTraits = typename GET_PROP_TYPE(TypeTag, BaseModelTraits);
 public:
     using type = MineralizationModelTraits<NonMineralizationTraits, SolidSystem::numComponents, SolidSystem::numInertComponents>;
 };
@@ -184,14 +169,8 @@ public:
 SET_PROP(TwoPNCMinNI, ModelTraits)
 {
 private:
-    //! we use the number of components specified by the fluid system here
-    using FluidSystem = typename GET_PROP_TYPE(TypeTag, FluidSystem);
-    static_assert(FluidSystem::numPhases == 2, "Only fluid systems with 2 fluid phases are supported by the 2p-nc model!");
     using SolidSystem = typename GET_PROP_TYPE(TypeTag, SolidSystem);
-    using TwoPNCTraits = TwoPNCModelTraits<FluidSystem::numComponents,
-                                           GET_PROP_VALUE(TypeTag, UseMoles),
-                                           GET_PROP_VALUE(TypeTag, SetMoleFractionsForFirstPhase),
-                                           GET_PROP_VALUE(TypeTag, Formulation), GET_PROP_VALUE(TypeTag, ReplaceCompEqIdx)>;
+    using TwoPNCTraits = typename GET_PROP_TYPE(TypeTag, BaseModelTraits);
     using IsothermalTraits = MineralizationModelTraits<TwoPNCTraits, SolidSystem::numComponents, SolidSystem::numInertComponents>;
 public:
     // the mineralization traits, based on 2pnc traits, are the isothermal traits
@@ -201,15 +180,8 @@ public:
 //! non-isothermal vtkoutput
 SET_PROP(TwoPNCMinNI, IOFields)
 {
-    static constexpr auto formulation = GET_PROP_VALUE(TypeTag, Formulation);
-    using Indices = TwoPNCIndices;
-    static constexpr auto useMoles = GET_PROP_VALUE(TypeTag, UseMoles);
-    static constexpr auto setMoleFractionsForFirstPhase = GET_PROP_VALUE(TypeTag, SetMoleFractionsForFirstPhase);
-    using TwoPNCIOF = TwoPNCIOFields<formulation, Indices, useMoles, setMoleFractionsForFirstPhase>;
-    using FluidSystem = typename GET_PROP_TYPE(TypeTag, FluidSystem);
-    using MineralizationIOF = MineralizationIOFields<TwoPNCIOF, FluidSystem::numComponents>;
-    using ModelTraits = typename GET_PROP_TYPE(TypeTag, ModelTraits);
-    using type = EnergyIOFields<MineralizationIOF, ModelTraits>;
+    using MineralizationIOF = MineralizationIOFields<TwoPNCIOFields>;
+    using type = EnergyIOFields<MineralizationIOF>;
 };
 
 } // end namespace Properties
diff --git a/dumux/porousmediumflow/3p/iofields.hh b/dumux/porousmediumflow/3p/iofields.hh
index a33a68111b..3b8138622a 100644
--- a/dumux/porousmediumflow/3p/iofields.hh
+++ b/dumux/porousmediumflow/3p/iofields.hh
@@ -65,7 +65,7 @@ public:
         initOutputModule(out);
     }
 
-    template <class FluidSystem, class SolidSystem = void>
+    template <class ModelTraits, class FluidSystem, class SolidSystem = void>
     static std::string primaryVariableName(int pvIdx, int state = 0)
     {
         switch (pvIdx)
diff --git a/dumux/porousmediumflow/3p/model.hh b/dumux/porousmediumflow/3p/model.hh
index d6f9e405e6..bd6b39126d 100644
--- a/dumux/porousmediumflow/3p/model.hh
+++ b/dumux/porousmediumflow/3p/model.hh
@@ -186,14 +186,7 @@ public:
 };
 
 //! Set the vtk output fields specific to this model
-SET_PROP(ThreeP, IOFields)
-{
-private:
-   using Indices = typename GET_PROP_TYPE(TypeTag, ModelTraits)::Indices;
-
-public:
-    using type = ThreePIOFields;
-};
+SET_TYPE_PROP(ThreeP, IOFields, ThreePIOFields);
 
 /////////////////////////////////////////////////
 // Properties for the non-isothermal 3p model
@@ -209,14 +202,7 @@ public:
 };
 
 //! Set non-isothermal output fields
-SET_PROP(ThreePNI, IOFields)
-{
-private:
-    using ModelTraits = typename GET_PROP_TYPE(TypeTag, ModelTraits);
-    using IsothermalFields = ThreePIOFields;
-public:
-    using type = EnergyIOFields<IsothermalFields, ModelTraits>;
-};
+SET_TYPE_PROP(ThreePNI, IOFields, EnergyIOFields<ThreePIOFields>);
 
 //! Set non-isothermal model traits
 SET_PROP(ThreePNI, ModelTraits)
diff --git a/dumux/porousmediumflow/3p3c/iofields.hh b/dumux/porousmediumflow/3p3c/iofields.hh
index 25d31deb2f..5f0b3206ac 100644
--- a/dumux/porousmediumflow/3p3c/iofields.hh
+++ b/dumux/porousmediumflow/3p3c/iofields.hh
@@ -32,7 +32,6 @@ namespace Dumux {
  * \ingroup ThreePThreeCModel
  * \brief Adds I/O fields specific to the three-phase three-component model
  */
-template <class Indices>
 class ThreePThreeCIOFields
 {
 public:
@@ -72,9 +71,11 @@ public:
         initOutputModule(out);
     }
 
-    template <class FluidSystem, class SolidSystem = void>
+    template <class ModelTraits, class FluidSystem, class SolidSystem = void>
     static std::string primaryVariableName(int pvIdx, int state)
     {
+        using Indices = typename ModelTraits::Indices;
+
         switch (state)
         {
             case Indices::threePhases:
diff --git a/dumux/porousmediumflow/3p3c/model.hh b/dumux/porousmediumflow/3p3c/model.hh
index e777112c22..be5d31c175 100644
--- a/dumux/porousmediumflow/3p3c/model.hh
+++ b/dumux/porousmediumflow/3p3c/model.hh
@@ -206,7 +206,7 @@ NEW_TYPE_TAG(ThreePThreeCNI, INHERITS_FROM(ThreePThreeC));
 //////////////////////////////////////////////////////////////////
 
 //! Set the model traits
-SET_PROP(ThreePThreeC, ModelTraits)
+SET_PROP(ThreePThreeC, BaseModelTraits)
 {
 private:
     using FluidSystem = typename GET_PROP_TYPE(TypeTag, FluidSystem);
@@ -215,6 +215,7 @@ private:
 public:
     using type = ThreePThreeCModelTraits<GET_PROP_VALUE(TypeTag, UseConstraintSolver), GET_PROP_VALUE(TypeTag, UseMoles)>;
 };
+SET_TYPE_PROP(ThreePThreeC, ModelTraits, typename GET_PROP_TYPE(TypeTag, BaseModelTraits));
 
 //! Determines whether a constraint solver should be used explicitly
 SET_BOOL_PROP(ThreePThreeC, UseConstraintSolver, false);
@@ -272,7 +273,7 @@ public:
 SET_TYPE_PROP(ThreePThreeC, EffectiveDiffusivityModel, DiffusivityMillingtonQuirk<typename GET_PROP_TYPE(TypeTag, Scalar)>);
 
 //! Set the vtk output fields specific to this model
-SET_TYPE_PROP(ThreePThreeC, IOFields, ThreePThreeCIOFields<ThreePThreeCIndices>);
+SET_TYPE_PROP(ThreePThreeC, IOFields, ThreePThreeCIOFields);
 
 //! Use mole fractions in the balance equations by default
 SET_BOOL_PROP(ThreePThreeC, UseMoles, true);
@@ -288,21 +289,13 @@ SET_TYPE_PROP(ThreePThreeCNI, ThermalConductivityModel, ThermalConductivitySomer
 SET_PROP(ThreePThreeCNI, ModelTraits)
 {
 private:
-    using FluidSystem = typename GET_PROP_TYPE(TypeTag, FluidSystem);
-    static_assert(FluidSystem::numComponents == 3, "Only fluid systems with 3 components are supported by the 3p3c model!");
-    static_assert(FluidSystem::numPhases == 3, "Only fluid systems with 3 phases are supported by the 3p3c model!");
-    using IsothermalModelTraits = ThreePThreeCModelTraits<GET_PROP_VALUE(TypeTag, UseConstraintSolver), GET_PROP_VALUE(TypeTag, UseMoles)>;
+    using IsothermalModelTraits = typename GET_PROP_TYPE(TypeTag, BaseModelTraits);
 public:
     using type = PorousMediumFlowNIModelTraits<IsothermalModelTraits>;
 };
 
 //! Set the non-isothermal vktoutputfields
-SET_PROP(ThreePThreeCNI, IOFields)
-{
-    using ThreePThreeCIOF = ThreePThreeCIOFields<ThreePThreeCIndices>;
-    using ModelTraits = typename GET_PROP_TYPE(TypeTag, ModelTraits);
-    using type = EnergyIOFields<ThreePThreeCIOF, ModelTraits>;
-};
+SET_TYPE_PROP(ThreePThreeCNI, IOFields, EnergyIOFields<ThreePThreeCIOFields>);
 
 } // end namespace Properties
 } // end namespace Dumux
diff --git a/dumux/porousmediumflow/3pwateroil/iofields.hh b/dumux/porousmediumflow/3pwateroil/iofields.hh
index 4d33cae0f7..90ed23fe99 100644
--- a/dumux/porousmediumflow/3pwateroil/iofields.hh
+++ b/dumux/porousmediumflow/3pwateroil/iofields.hh
@@ -33,7 +33,6 @@ namespace Dumux {
  * \ingroup ThreePWaterOilModel
  * \brief Adds I/O fields specific to the three-phase three-component model
  */
-template <class Indices>
 class ThreePWaterOilIOFields
 {
 
@@ -78,9 +77,11 @@ public:
         initOutputModule(out);
     }
 
-    template <class FluidSystem, class SolidSystem = void>
+    template <class ModelTraits, class FluidSystem, class SolidSystem = void>
     static std::string primaryVariableName(int pvIdx, int state)
     {
+        using Indices = typename ModelTraits::Indices;
+
         switch (state)
         {
             case Indices::threePhases:
diff --git a/dumux/porousmediumflow/3pwateroil/model.hh b/dumux/porousmediumflow/3pwateroil/model.hh
index 6e18d90b42..ecb22d7d78 100644
--- a/dumux/porousmediumflow/3pwateroil/model.hh
+++ b/dumux/porousmediumflow/3pwateroil/model.hh
@@ -274,12 +274,7 @@ public:
 };
 
 //! Set the non-isothermal vkt output fields
-SET_PROP(ThreePWaterOilNI, IOFields)
-{
-    using ThreePWaterOilIOF = ThreePWaterOilIOFields<ThreePWaterOilIndices>;
-    using ModelTraits = typename GET_PROP_TYPE(TypeTag, ModelTraits);
-    using type = EnergyIOFields<ThreePWaterOilIOF, ModelTraits>;
-};
+SET_TYPE_PROP(ThreePWaterOilNI, IOFields, EnergyIOFields<ThreePWaterOilIOFields>);
 
 } // end namespace Properties
 } // end namespace Dumux
diff --git a/dumux/porousmediumflow/mineralization/iofields.hh b/dumux/porousmediumflow/mineralization/iofields.hh
index 529e64c8c5..0ca489e4d4 100644
--- a/dumux/porousmediumflow/mineralization/iofields.hh
+++ b/dumux/porousmediumflow/mineralization/iofields.hh
@@ -33,7 +33,7 @@ namespace Dumux {
  * \ingroup MineralizationModel
  * \brief Adds I/O fields specific to a NCMin model
  */
-template<class NonMineralizationIOFields, int nonMineralizationNumEq>
+template<class NonMineralizationIOFields>
 class MineralizationIOFields
 {
 public:
@@ -60,13 +60,15 @@ public:
         initOutputModule(out);
     }
 
-    template <class FluidSystem, class SolidSystem>
+    template <class ModelTraits, class FluidSystem, class SolidSystem>
     static std::string primaryVariableName(int pvIdx, int state = 0)
     {
-        if (pvIdx < nonMineralizationNumEq)
+        static constexpr int nonMinNumEq = ModelTraits::numEq() - ModelTraits::numSolidComp() + ModelTraits::numInertSolidComp();
+
+        if (pvIdx < nonMinNumEq)
             return NonMineralizationIOFields::template primaryVariableName<FluidSystem, SolidSystem>(pvIdx, state);
         else
-            return IOName::solidVolumeFraction<SolidSystem>(pvIdx - nonMineralizationNumEq);
+            return IOName::solidVolumeFraction<SolidSystem>(pvIdx - nonMinNumEq);
     }
 };
 
diff --git a/dumux/porousmediumflow/nonisothermal/iofields.hh b/dumux/porousmediumflow/nonisothermal/iofields.hh
index 3ef98a1259..ed979301a3 100644
--- a/dumux/porousmediumflow/nonisothermal/iofields.hh
+++ b/dumux/porousmediumflow/nonisothermal/iofields.hh
@@ -32,7 +32,7 @@ namespace Dumux {
  * \ingroup NIModel
  * \brief Adds I/O fields specific to non-isothermal models
  */
-template<class IsothermalIOFields, class ModelTraits>
+template<class IsothermalIOFields>
 class EnergyIOFields
 {
 
@@ -52,11 +52,13 @@ public:
         initOutputModule(out);
     }
 
-    template <class FluidSystem = void, class SolidSystem = void>
+    template <class ModelTraits, class FluidSystem = void, class SolidSystem = void>
     static std::string primaryVariableName(int pvIdx, int state = 0)
     {
+        using IsothermalTraits = typename ModelTraits::IsothermalTraits;
+
         if (pvIdx < ModelTraits::numEq() - 1)
-            return IsothermalIOFields::template primaryVariableName<FluidSystem, SolidSystem>(pvIdx, state);
+            return IsothermalIOFields::template primaryVariableName<IsothermalTraits, FluidSystem, SolidSystem>(pvIdx, state);
         else
             return IOName::temperature();
     }
diff --git a/dumux/porousmediumflow/nonisothermal/model.hh b/dumux/porousmediumflow/nonisothermal/model.hh
index edf37038be..12d5cfdf0e 100644
--- a/dumux/porousmediumflow/nonisothermal/model.hh
+++ b/dumux/porousmediumflow/nonisothermal/model.hh
@@ -63,9 +63,12 @@ namespace Dumux {
  *        flow models based on the specifics of a given isothermal model.
  * \tparam IsothermalTraits Model traits of the isothermal model
  */
-template<class IsothermalTraits>
-struct PorousMediumFlowNIModelTraits : public IsothermalTraits
+template<class IsothermalT>
+struct PorousMediumFlowNIModelTraits : public IsothermalT
 {
+    //! Export the isothermal model traits
+    using IsothermalTraits = IsothermalT;
+
     //! We solve for one more equation, i.e. the energy balance
     static constexpr int numEq() { return IsothermalTraits::numEq()+1; }
     //! only one energy equation is needed when assuming thermal equilibrium
diff --git a/dumux/porousmediumflow/richards/iofields.hh b/dumux/porousmediumflow/richards/iofields.hh
index cd2b4a05b2..c2df1959b1 100644
--- a/dumux/porousmediumflow/richards/iofields.hh
+++ b/dumux/porousmediumflow/richards/iofields.hh
@@ -33,7 +33,7 @@ namespace Dumux {
  * \ingroup RichardsModel
  * \brief Adds I/O fields specific to the Richards model.
  */
-template<bool enableWaterDiffusionInAir, class Indices>
+template <bool enableWaterDiffusionInAir>
 class RichardsIOFields
 {
 public:
@@ -84,9 +84,11 @@ public:
         initOutputModule(out);
     }
 
-    template<class FluidSystem, class SolidSystem = void>
+    template<class ModelTraits, class FluidSystem, class SolidSystem = void>
     static std::string primaryVariableName(int pvIdx, int state)
     {
+        using Indices = typename ModelTraits::Indices;
+
         if (state == Indices::gasPhaseOnly)
             return IOName::moleFraction<FluidSystem>(FluidSystem::gasPhaseIdx,
                                                      FluidSystem::liquidCompIdx);
diff --git a/dumux/porousmediumflow/richards/model.hh b/dumux/porousmediumflow/richards/model.hh
index f1958f5691..992be84a6f 100644
--- a/dumux/porousmediumflow/richards/model.hh
+++ b/dumux/porousmediumflow/richards/model.hh
@@ -198,7 +198,7 @@ private:
         = GET_PROP_VALUE(TypeTag, EnableWaterDiffusionInAir);
 
 public:
-    using type = RichardsIOFields<enableWaterDiffusionInAir, RichardsIndices>;
+    using type = RichardsIOFields<enableWaterDiffusionInAir>;
 };
 
 //! The model traits
@@ -300,9 +300,8 @@ SET_PROP(RichardsNI, IOFields)
 {
     static constexpr bool enableWaterDiffusionInAir
         = GET_PROP_VALUE(TypeTag, EnableWaterDiffusionInAir);
-    using RichardsIOF = RichardsIOFields<enableWaterDiffusionInAir, RichardsIndices>;
-    using ModelTraits = typename GET_PROP_TYPE(TypeTag, ModelTraits);
-    using type = EnergyIOFields<RichardsIOF, ModelTraits>;
+    using RichardsIOF = RichardsIOFields<enableWaterDiffusionInAir>;
+    using type = EnergyIOFields<RichardsIOF>;
 };
 
 // \}
diff --git a/dumux/porousmediumflow/richardsnc/iofields.hh b/dumux/porousmediumflow/richardsnc/iofields.hh
index 1dd65fbe04..99c20395d6 100644
--- a/dumux/porousmediumflow/richardsnc/iofields.hh
+++ b/dumux/porousmediumflow/richardsnc/iofields.hh
@@ -33,7 +33,6 @@ namespace Dumux {
  * \ingroup RichardsNCModel
  * \brief Adds I/O fields specific to the Richards model.
  */
-template <bool useMoles>
 class RichardsNCIOFields
 {
 public:
@@ -84,14 +83,14 @@ public:
         initOutputModule(out);
     }
 
-    template <class FluidSystem, class SolidSystem = void>
+    template <class ModelTraits, class FluidSystem, class SolidSystem = void>
     static std::string primaryVariableName(int pvIdx, int state = 0)
     {
         if (pvIdx == 0)
             return IOName::pressure<FluidSystem>(0);
         else
-            return useMoles ? IOName::moleFraction<FluidSystem>(0, pvIdx)
-                            : IOName::massFraction<FluidSystem>(0, pvIdx);
+            return ModelTraits::useMoles() ? IOName::moleFraction<FluidSystem>(0, pvIdx)
+                                           : IOName::massFraction<FluidSystem>(0, pvIdx);
     }
 };
 
diff --git a/dumux/porousmediumflow/richardsnc/model.hh b/dumux/porousmediumflow/richardsnc/model.hh
index 3e2a11e980..3937e5a568 100644
--- a/dumux/porousmediumflow/richardsnc/model.hh
+++ b/dumux/porousmediumflow/richardsnc/model.hh
@@ -144,13 +144,14 @@ NEW_TYPE_TAG(RichardsNCNI, INHERITS_FROM(RichardsNC));
 //////////////////////////////////////////////////////////////////
 
 //! Set the model traits class
-SET_PROP(RichardsNC, ModelTraits)
+SET_PROP(RichardsNC, BaseModelTraits)
 {
 private:
     using FluidSystem = typename GET_PROP_TYPE(TypeTag, FluidSystem);
 public:
     using type = RichardsNCModelTraits<FluidSystem::numComponents, GET_PROP_VALUE(TypeTag, UseMoles), GET_PROP_VALUE(TypeTag, ReplaceCompEqIdx)>;
 };
+SET_TYPE_PROP(RichardsNC, ModelTraits, typename GET_PROP_TYPE(TypeTag, BaseModelTraits));
 
 //! Define that per default mole fractions are used in the balance equations
 SET_BOOL_PROP(RichardsNC, UseMoles, true);
@@ -213,7 +214,7 @@ SET_PROP(RichardsNC, FluidState)
 };
 
 //! Set the vtk output fields specific to this model
-SET_TYPE_PROP(RichardsNC, IOFields, RichardsNCIOFields<GET_PROP_VALUE(TypeTag, UseMoles)>);
+SET_TYPE_PROP(RichardsNC, IOFields, RichardsNCIOFields);
 
 //! The model after Millington (1961) is used for the effective diffusivity
 SET_TYPE_PROP(RichardsNC, EffectiveDiffusivityModel, DiffusivityMillingtonQuirk<typename GET_PROP_TYPE(TypeTag, Scalar)>);
@@ -229,8 +230,7 @@ SET_TYPE_PROP(RichardsNCNI, ThermalConductivityModel, ThermalConductivityAverage
 SET_PROP(RichardsNCNI, ModelTraits)
 {
 private:
-    using FluidSystem = typename GET_PROP_TYPE(TypeTag, FluidSystem);
-    using IsothermalTraits = RichardsNCModelTraits<FluidSystem::numComponents, GET_PROP_VALUE(TypeTag, UseMoles), GET_PROP_VALUE(TypeTag, ReplaceCompEqIdx)>;
+    using IsothermalTraits = typename GET_PROP_TYPE(TypeTag, BaseModelTraits);
 public:
     using type = PorousMediumFlowNIModelTraits<IsothermalTraits>;
 };
diff --git a/dumux/porousmediumflow/tracer/iofields.hh b/dumux/porousmediumflow/tracer/iofields.hh
index bebeae2307..94cae16f18 100644
--- a/dumux/porousmediumflow/tracer/iofields.hh
+++ b/dumux/porousmediumflow/tracer/iofields.hh
@@ -34,7 +34,6 @@ namespace Dumux {
  * \ingroup TracerModel
  * \brief Adds I/O fields specific to the tracer model
  */
-template <bool useMoles>
 class TracerIOFields
 {
 public:
@@ -62,10 +61,10 @@ public:
         initOutputModule(out);
     }
 
-    template <class FluidSystem, class SolidSystem = void>
+    template <class ModelTraits, class FluidSystem, class SolidSystem = void>
     static std::string primaryVariableName(int pvIdx, int state = 0)
     {
-        const std::string xString = useMoles ? "x" : "X";
+        const std::string xString = ModelTraits::useMoles() ? "x" : "X";
         return xString + "^" + FluidSystem::componentName(pvIdx);
     }
 };
diff --git a/dumux/porousmediumflow/tracer/model.hh b/dumux/porousmediumflow/tracer/model.hh
index b909797476..cccbb3bc10 100644
--- a/dumux/porousmediumflow/tracer/model.hh
+++ b/dumux/porousmediumflow/tracer/model.hh
@@ -142,7 +142,7 @@ public:
 SET_TYPE_PROP(Tracer, LocalResidual, TracerLocalResidual<TypeTag>);
 
 //! Set the vtk output fields specific to this model
-SET_TYPE_PROP(Tracer, IOFields, TracerIOFields<GET_PROP_VALUE(TypeTag, UseMoles)>);
+SET_TYPE_PROP(Tracer, IOFields, TracerIOFields);
 
 //! Set the volume variables property
 SET_PROP(Tracer, VolumeVariables)
-- 
GitLab