From 56ec173c73402543a2ac7c6504430a52abc84af0 Mon Sep 17 00:00:00 2001 From: Theresa Kurz Date: Wed, 28 Nov 2018 13:40:36 +0100 Subject: [PATCH 01/25] [execise-basic] update exercise and readme to dumux 3.0 --- exercises/exercise-basic/README.md | 2 +- exercises/exercise-basic/exercise_basic_2p.cc | 49 +++++++++++---- .../exercise-basic/exercise_basic_2p2c.cc | 59 +++++++++++++------ .../exercise-basic/injection2p2cproblem.hh | 41 +++++++------ .../exercise-basic/injection2pniproblem.hh | 38 +++++++----- .../exercise-basic/injection2pproblem.hh | 38 +++++++----- .../exercise-basic/exercise_basic_2pni.cc | 45 ++++++++++---- .../exercise-basic/injection2pniproblem.hh | 37 +++++++----- 8 files changed, 200 insertions(+), 109 deletions(-) diff --git a/exercises/exercise-basic/README.md b/exercises/exercise-basic/README.md index 8aee329..cc81fd4 100644 --- a/exercises/exercise-basic/README.md +++ b/exercises/exercise-basic/README.md @@ -60,7 +60,7 @@ paraview injection-2p2c.pvd * Copy the main file `exercise_basic_2p.cc` and rename it to `exercise_basic_2pni.cc` * In `exercise_basic_2pni.cc`, include the header `injection2pniproblem.hh` instead of `injection2pproblem.hh`. -* In `exercise_basic_2pni.cc`, change `Injection2pCCTypeTag` to `Injection2pNICCTypeTag` in the line `using TypeTag = TTAG(Injection2pCCTypeTag);` +* In `exercise_basic_2pni.cc`, change `Injection2pCCTypeTag` to `Injection2pNICCTypeTag` in the line `using TypeTag = Properties::TTag::Injection2pNICCTypeTag;` * Add a new executable in `CMakeLists.txt` by adding the lines ```cmake diff --git a/exercises/exercise-basic/exercise_basic_2p.cc b/exercises/exercise-basic/exercise_basic_2p.cc index 88f18f8..babdd67 100644 --- a/exercises/exercise-basic/exercise_basic_2p.cc +++ b/exercises/exercise-basic/exercise_basic_2p.cc @@ -41,10 +41,11 @@ #include #include -#include +#include #include #include +#include // The problem file, where setup-specific boundary and initial conditions are defined. #include "injection2pproblem.hh" @@ -57,7 +58,7 @@ int main(int argc, char** argv) try using namespace Dumux; // define the type tag for this problem - using TypeTag = TTAG(Injection2pCCTypeTag); + using TypeTag = Properties::TTag::Injection2pCCTypeTag; // initialize MPI, finalize is done automatically on exit const auto& mpiHelper = Dune::MPIHelper::instance(argc, argv); @@ -70,7 +71,7 @@ int main(int argc, char** argv) try Parameters::init(argc, argv); // try to create a grid (from the given grid file or the input file) - GridManager gridManager; + GridManager> gridManager; gridManager.init(); //////////////////////////////////////////////////////////// @@ -81,35 +82,57 @@ int main(int argc, char** argv) try const auto& leafGridView = gridManager.grid().leafGridView(); // create the finite volume grid geometry - using FVGridGeometry = typename GET_PROP_TYPE(TypeTag, FVGridGeometry); + using FVGridGeometry = GetPropType; auto fvGridGeometry = std::make_shared(leafGridView); fvGridGeometry->update(); // the problem (initial and boundary conditions) - using Problem = typename GET_PROP_TYPE(TypeTag, Problem); + using Problem = GetPropType; auto problem = std::make_shared(fvGridGeometry); + // check if we are about to restart a previously interrupted simulation + using Scalar = GetPropType; + Scalar restartTime = getParam("Restart.Time", 0); + // the solution vector - using SolutionVector = typename GET_PROP_TYPE(TypeTag, SolutionVector); + using SolutionVector = GetPropType; SolutionVector x(fvGridGeometry->numDofs()); - problem->applyInitialSolution(x); + if (restartTime > 0) + { + using IOFields = GetPropType; + using PrimaryVariables = GetPropType; + using ModelTraits = GetPropType; + using FluidSystem = GetPropType; + const auto fileName = getParam("Restart.File"); + const auto pvName = createPVNameFunction(); + loadSolution(x, fileName, pvName, *fvGridGeometry); + } + else + problem->applyInitialSolution(x); auto xOld = x; // the grid variables - using GridVariables = typename GET_PROP_TYPE(TypeTag, GridVariables); + using GridVariables = GetPropType; auto gridVariables = std::make_shared(problem, fvGridGeometry); - gridVariables->init(x, xOld); + gridVariables->init(x); // get some time loop parameters - using Scalar = typename GET_PROP_TYPE(TypeTag, Scalar); + using Scalar = GetPropType; const auto tEnd = getParam("TimeLoop.TEnd"); const auto maxDt = getParam("TimeLoop.MaxTimeStepSize"); auto dt = getParam("TimeLoop.DtInitial"); // intialize the vtk output module - using VtkOutputFields = typename GET_PROP_TYPE(TypeTag, VtkOutputFields); - VtkOutputModule vtkWriter(*problem, *fvGridGeometry, *gridVariables, x, problem->name()); - VtkOutputFields::init(vtkWriter); //! Add model specific output fields + using IOFields = GetPropType; + + // use non-conforming output for the test with interface solver + const auto ncOutput = getParam("Problem.UseNonConformingOutput", false); + VtkOutputModule vtkWriter(*gridVariables, x, problem->name(), "", + ncOutput ? Dune::VTK::nonconforming : Dune::VTK::conforming); + using VelocityOutput = GetPropType; + vtkWriter.addVelocityOutput(std::make_shared(*gridVariables)); + IOFields::initOutputModule(vtkWriter); //!< Add model specific output fields + vtkWriter.write(restartTime); // instantiate time loop auto timeLoop = std::make_shared>(0.0, dt, tEnd); diff --git a/exercises/exercise-basic/exercise_basic_2p2c.cc b/exercises/exercise-basic/exercise_basic_2p2c.cc index b4359b9..68c91ea 100644 --- a/exercises/exercise-basic/exercise_basic_2p2c.cc +++ b/exercises/exercise-basic/exercise_basic_2p2c.cc @@ -36,15 +36,16 @@ #include #include -#include +#include #include #include -#include +#include #include #include +#include // The problem file, where setup-specific boundary and initial conditions are defined. #include "injection2p2cproblem.hh" @@ -57,7 +58,7 @@ int main(int argc, char** argv) try using namespace Dumux; // define the type tag for this problem - using TypeTag = TTAG(Injection2p2cCCTypeTag); + using TypeTag = Properties::TTag::Injection2p2cCCTypeTag; // initialize MPI, finalize is done automatically on exit const auto& mpiHelper = Dune::MPIHelper::instance(argc, argv); @@ -70,7 +71,7 @@ int main(int argc, char** argv) try Parameters::init(argc, argv); // try to create a grid (from the given grid file or the input file) - GridManager gridManager; + GridManager> gridManager; gridManager.init(); //////////////////////////////////////////////////////////// @@ -81,38 +82,62 @@ int main(int argc, char** argv) try const auto& leafGridView = gridManager.grid().leafGridView(); // create the finite volume grid geometry - using FVGridGeometry = typename GET_PROP_TYPE(TypeTag, FVGridGeometry); + using FVGridGeometry = GetPropType; auto fvGridGeometry = std::make_shared(leafGridView); fvGridGeometry->update(); // the problem (initial and boundary conditions) - using Problem = typename GET_PROP_TYPE(TypeTag, Problem); + using Problem = GetPropType; auto problem = std::make_shared(fvGridGeometry); + // check if we are about to restart a previously interrupted simulation + using Scalar = GetPropType; + Scalar restartTime = getParam("Restart.Time", 0); + // the solution vector - using SolutionVector = typename GET_PROP_TYPE(TypeTag, SolutionVector); + using SolutionVector = GetPropType; SolutionVector x(fvGridGeometry->numDofs()); - problem->applyInitialSolution(x); +// problem->applyInitialSolution(x); + if (restartTime > 0) + { + using IOFields = GetPropType; + using PrimaryVariables = GetPropType; + using ModelTraits = GetPropType; + using FluidSystem = GetPropType; + const auto fileName = getParam("Restart.File"); + const auto pvName = createPVNameFunction(); + loadSolution(x, fileName, pvName, *fvGridGeometry); + } + else + problem->applyInitialSolution(x); auto xOld = x; // the grid variables - using GridVariables = typename GET_PROP_TYPE(TypeTag, GridVariables); + using GridVariables = GetPropType; auto gridVariables = std::make_shared(problem, fvGridGeometry); - gridVariables->init(x, xOld); + gridVariables->init(x); // get some time loop parameters - using Scalar = typename GET_PROP_TYPE(TypeTag, Scalar); + using Scalar = GetPropType; const auto tEnd = getParam("TimeLoop.TEnd"); const auto maxDt = getParam("TimeLoop.MaxTimeStepSize"); auto dt = getParam("TimeLoop.DtInitial"); // intialize the vtk output module - using VtkOutputFields = typename GET_PROP_TYPE(TypeTag, VtkOutputFields); - VtkOutputModule vtkWriter(*problem, *fvGridGeometry, *gridVariables, x, problem->name()); - VtkOutputFields::init(vtkWriter); //! Add model specific output fields +// using VtkOutputFields = GetPropType; +// VtkOutputModule vtkWriter(*problem, *fvGridGeometry, *gridVariables, x, problem->name()); +// VtkOutputFields::init(vtkWriter); //! Add model specific output fields + + // intialize the vtk output module + using VtkOutputFields = GetPropType; + VtkOutputModule vtkWriter(*gridVariables, x, problem->name()); + using VelocityOutput = GetPropType; + vtkWriter.addVelocityOutput(std::make_shared(*gridVariables)); + VtkOutputFields::initOutputModule(vtkWriter); //!< Add model specific output fields + vtkWriter.write(restartTime); // instantiate time loop - auto timeLoop = std::make_shared>(0.0, dt, tEnd); + auto timeLoop = std::make_shared>(restartTime, dt, tEnd); timeLoop->setMaxTimeStepSize(maxDt); // the assembler with time loop for instationary problem @@ -124,8 +149,8 @@ int main(int argc, char** argv) try auto linearSolver = std::make_shared(leafGridView, fvGridGeometry->dofMapper()); // the non-linear solver - using PrimaryVariableSwitch = typename GET_PROP_TYPE(TypeTag, PrimaryVariableSwitch); - using NewtonSolver = Dumux::PriVarSwitchNewtonSolver; +// using PrimaryVariableSwitch = GetPropType; + using NewtonSolver = NewtonSolver; NewtonSolver nonLinearSolver(assembler, linearSolver); // time loop diff --git a/exercises/exercise-basic/injection2p2cproblem.hh b/exercises/exercise-basic/injection2p2cproblem.hh index 39b0ab5..276f3cc 100644 --- a/exercises/exercise-basic/injection2p2cproblem.hh +++ b/exercises/exercise-basic/injection2p2cproblem.hh @@ -38,25 +38,32 @@ template class Injection2p2cProblem; namespace Properties { -NEW_TYPE_TAG(Injection2p2cTypeTag, INHERITS_FROM(TwoPTwoC)); -NEW_TYPE_TAG(Injection2p2cCCTypeTag, INHERITS_FROM(CCTpfaModel, Injection2p2cTypeTag)); +// Create new type tags +namespace TTag { +struct Injection2p2cTypeTag { using InheritsFrom = std::tuple; }; +struct Injection2p2cCCTypeTag { using InheritsFrom = std::tuple; }; +} // end namespace TTag // Set the grid type -SET_TYPE_PROP(Injection2p2cTypeTag, Grid, Dune::YaspGrid<2>); +template +struct Grid { using type = Dune::YaspGrid<2>; }; // Set the problem property -SET_TYPE_PROP(Injection2p2cTypeTag, Problem, Injection2p2cProblem); +template +struct Problem { using type = Injection2p2cProblem; }; // Set the spatial parameters SET_TYPE_PROP(Injection2p2cTypeTag, SpatialParams, - InjectionSpatialParams); + InjectionSpatialParams, + GetPropType>); // Set fluid configuration -SET_TYPE_PROP(Injection2p2cTypeTag, FluidSystem, FluidSystems::H2ON2>); +template +struct FluidSystem { using type = FluidSystems::H2ON2, FluidSystems::H2ON2DefaultPolicy>; }; // Define whether mole(true) or mass (false) fractions are used -SET_BOOL_PROP(Injection2p2cTypeTag, UseMoles, true); +template +struct UseMoles { static constexpr bool value = true; }; } // end namespace Properties /*! @@ -84,15 +91,15 @@ template class Injection2p2cProblem : public PorousMediumFlowProblem { using ParentType = PorousMediumFlowProblem; - using GridView = typename GET_PROP_TYPE(TypeTag, GridView); - using Scalar = typename GET_PROP_TYPE(TypeTag, Scalar); - using Indices = typename GET_PROP_TYPE(TypeTag, ModelTraits)::Indices; - using PrimaryVariables = typename GET_PROP_TYPE(TypeTag, PrimaryVariables); - using BoundaryTypes = typename GET_PROP_TYPE(TypeTag, BoundaryTypes); - using FVGridGeometry = typename GET_PROP_TYPE(TypeTag, FVGridGeometry); - using FVElementGeometry = typename GET_PROP_TYPE(TypeTag, FVGridGeometry)::LocalView; - using FluidSystem = typename GET_PROP_TYPE(TypeTag, FluidSystem); - using NumEqVector = typename GET_PROP_TYPE(TypeTag, NumEqVector); + using GridView = GetPropType; + using Scalar = GetPropType; + using Indices = typename GetPropType::Indices; + using PrimaryVariables = GetPropType; + using BoundaryTypes = GetPropType; + using FVGridGeometry = GetPropType; + using FVElementGeometry = typename GetPropType::LocalView; + using FluidSystem = GetPropType; + using NumEqVector = GetPropType; enum { dimWorld = GridView::dimensionworld }; using Element = typename GridView::template Codim<0>::Entity; diff --git a/exercises/exercise-basic/injection2pniproblem.hh b/exercises/exercise-basic/injection2pniproblem.hh index 5d03855..4a1e960 100644 --- a/exercises/exercise-basic/injection2pniproblem.hh +++ b/exercises/exercise-basic/injection2pniproblem.hh @@ -44,22 +44,28 @@ namespace Properties * TODO:dumux-course-task: * inherit from the TwoPNI model instead of TwoP here */ -NEW_TYPE_TAG(Injection2pNITypeTag, INHERITS_FROM(TwoP)); -NEW_TYPE_TAG(Injection2pNICCTypeTag, INHERITS_FROM(CCTpfaModel, Injection2pNITypeTag)); +// Create new type tags +namespace TTag { +struct Injection2pNITypeTag { using InheritsFrom = std::tuple; }; +struct Injection2pNICCTypeTag { using InheritsFrom = std::tuple; }; +} // end namespace TTag // Set the grid type -SET_TYPE_PROP(Injection2pNITypeTag, Grid, Dune::YaspGrid<2>); +template +struct Grid { using type = Dune::YaspGrid<2>; }; // Set the problem property -SET_TYPE_PROP(Injection2pNITypeTag, Problem, InjectionProblem2PNI); +template +struct Problem { using type = InjectionProblem2PNI; }; // Set the spatial parameters SET_TYPE_PROP(Injection2pNITypeTag, SpatialParams, - InjectionSpatialParams); + InjectionSpatialParams, + GetPropType>); // Set fluid configuration -SET_TYPE_PROP(Injection2pNITypeTag, FluidSystem, FluidSystems::H2ON2>); +template +struct FluidSystem { using type = FluidSystems::H2ON2, FluidSystems::H2ON2DefaultPolicy>; }; } // end namespace Properties /*! @@ -87,15 +93,15 @@ template class InjectionProblem2PNI : public PorousMediumFlowProblem { using ParentType = PorousMediumFlowProblem; - using GridView = typename GET_PROP_TYPE(TypeTag, GridView); - using Scalar = typename GET_PROP_TYPE(TypeTag, Scalar); - using Indices = typename GET_PROP_TYPE(TypeTag, ModelTraits)::Indices; - using PrimaryVariables = typename GET_PROP_TYPE(TypeTag, PrimaryVariables); - using BoundaryTypes = typename GET_PROP_TYPE(TypeTag, BoundaryTypes); - using FVGridGeometry = typename GET_PROP_TYPE(TypeTag, FVGridGeometry); - using FVElementGeometry = typename GET_PROP_TYPE(TypeTag, FVGridGeometry)::LocalView; - using FluidSystem = typename GET_PROP_TYPE(TypeTag, FluidSystem); - using NumEqVector = typename GET_PROP_TYPE(TypeTag, NumEqVector); + using GridView = GetPropType; + using Scalar = GetPropType; + using Indices = typename GetPropType::Indices; + using PrimaryVariables = GetPropType; + using BoundaryTypes = GetPropType; + using FVGridGeometry = GetPropType; + using FVElementGeometry = typename GetPropType::LocalView; + using FluidSystem = GetPropType; + using NumEqVector = GetPropType; enum { dimWorld = GridView::dimensionworld }; using Element = typename GridView::template Codim<0>::Entity; diff --git a/exercises/exercise-basic/injection2pproblem.hh b/exercises/exercise-basic/injection2pproblem.hh index aae8751..0f05faf 100644 --- a/exercises/exercise-basic/injection2pproblem.hh +++ b/exercises/exercise-basic/injection2pproblem.hh @@ -40,22 +40,28 @@ class InjectionProblem2P; namespace Properties { // define the TypeTag for this problem with a cell-centered two-point flux approximation spatial discretization. -NEW_TYPE_TAG(Injection2pTypeTag, INHERITS_FROM(TwoP)); -NEW_TYPE_TAG(Injection2pCCTypeTag, INHERITS_FROM(CCTpfaModel, Injection2pTypeTag)); +// Create new type tags +namespace TTag { +struct Injection2pTypeTag { using InheritsFrom = std::tuple; }; +struct Injection2pCCTypeTag { using InheritsFrom = std::tuple; }; +} // end namespace TTag // Set the grid type -SET_TYPE_PROP(Injection2pTypeTag, Grid, Dune::YaspGrid<2>); +template +struct Grid { using type = Dune::YaspGrid<2>; }; // Set the problem property -SET_TYPE_PROP(Injection2pTypeTag, Problem, InjectionProblem2P); +template +struct Problem { using type = InjectionProblem2P; }; // Set the spatial parameters SET_TYPE_PROP(Injection2pTypeTag, SpatialParams, - InjectionSpatialParams); + InjectionSpatialParams, + GetPropType>); // Set fluid configuration -SET_TYPE_PROP(Injection2pTypeTag, FluidSystem, FluidSystems::H2ON2>); +template +struct FluidSystem { using type = FluidSystems::H2ON2, FluidSystems::H2ON2DefaultPolicy>; }; } // end namespace Properties /*! @@ -83,15 +89,15 @@ template class InjectionProblem2P : public PorousMediumFlowProblem { using ParentType = PorousMediumFlowProblem; - using GridView = typename GET_PROP_TYPE(TypeTag, GridView); - using Scalar = typename GET_PROP_TYPE(TypeTag, Scalar); - using Indices = typename GET_PROP_TYPE(TypeTag, ModelTraits)::Indices; - using PrimaryVariables = typename GET_PROP_TYPE(TypeTag, PrimaryVariables); - using BoundaryTypes = typename GET_PROP_TYPE(TypeTag, BoundaryTypes); - using FVGridGeometry = typename GET_PROP_TYPE(TypeTag, FVGridGeometry); - using FVElementGeometry = typename GET_PROP_TYPE(TypeTag, FVGridGeometry)::LocalView; - using FluidSystem = typename GET_PROP_TYPE(TypeTag, FluidSystem); - using NumEqVector = typename GET_PROP_TYPE(TypeTag, NumEqVector); + using GridView = GetPropType; + using Scalar = GetPropType; + using Indices = typename GetPropType::Indices; + using PrimaryVariables = GetPropType; + using BoundaryTypes = GetPropType; + using FVGridGeometry = GetPropType; + using FVElementGeometry = typename GetPropType::LocalView; + using FluidSystem = GetPropType; + using NumEqVector = GetPropType; enum { dimWorld = GridView::dimensionworld }; using Element = typename GridView::template Codim<0>::Entity; diff --git a/exercises/solution/exercise-basic/exercise_basic_2pni.cc b/exercises/solution/exercise-basic/exercise_basic_2pni.cc index c772513..3a9037d 100644 --- a/exercises/solution/exercise-basic/exercise_basic_2pni.cc +++ b/exercises/solution/exercise-basic/exercise_basic_2pni.cc @@ -41,10 +41,11 @@ #include #include -#include +#include #include #include +#include // The problem file, where setup-specific boundary and initial conditions are defined. #include "injection2pniproblem.hh" @@ -57,7 +58,7 @@ int main(int argc, char** argv) try using namespace Dumux; // define the type tag for this problem - using TypeTag = TTAG(Injection2pNICCTypeTag); + using TypeTag = Properties::TTag::Injection2pNICCTypeTag; // initialize MPI, finalize is done automatically on exit const auto& mpiHelper = Dune::MPIHelper::instance(argc, argv); @@ -70,7 +71,7 @@ int main(int argc, char** argv) try Parameters::init(argc, argv); // try to create a grid (from the given grid file or the input file) - GridManager gridManager; + GridManager> gridManager; gridManager.init(); //////////////////////////////////////////////////////////// @@ -81,35 +82,53 @@ int main(int argc, char** argv) try const auto& leafGridView = gridManager.grid().leafGridView(); // create the finite volume grid geometry - using FVGridGeometry = typename GET_PROP_TYPE(TypeTag, FVGridGeometry); + using FVGridGeometry = GetPropType; auto fvGridGeometry = std::make_shared(leafGridView); fvGridGeometry->update(); // the problem (initial and boundary conditions) - using Problem = typename GET_PROP_TYPE(TypeTag, Problem); + using Problem = GetPropType; auto problem = std::make_shared(fvGridGeometry); + // check if we are about to restart a previously interrupted simulation + using Scalar = GetPropType; + Scalar restartTime = getParam("Restart.Time", 0); + // the solution vector - using SolutionVector = typename GET_PROP_TYPE(TypeTag, SolutionVector); + using SolutionVector = GetPropType; SolutionVector x(fvGridGeometry->numDofs()); - problem->applyInitialSolution(x); + if (restartTime > 0) + { + using IOFields = GetPropType; + using PrimaryVariables = GetPropType; + using ModelTraits = GetPropType; + using FluidSystem = GetPropType; + const auto fileName = getParam("Restart.File"); + const auto pvName = createPVNameFunction(); + loadSolution(x, fileName, pvName, *fvGridGeometry); + } + else + problem->applyInitialSolution(x); auto xOld = x; // the grid variables - using GridVariables = typename GET_PROP_TYPE(TypeTag, GridVariables); + using GridVariables = GetPropType; auto gridVariables = std::make_shared(problem, fvGridGeometry); - gridVariables->init(x, xOld); + gridVariables->init(x); // get some time loop parameters - using Scalar = typename GET_PROP_TYPE(TypeTag, Scalar); + using Scalar = GetPropType; const auto tEnd = getParam("TimeLoop.TEnd"); const auto maxDt = getParam("TimeLoop.MaxTimeStepSize"); auto dt = getParam("TimeLoop.DtInitial"); // intialize the vtk output module - using VtkOutputFields = typename GET_PROP_TYPE(TypeTag, VtkOutputFields); - VtkOutputModule vtkWriter(*problem, *fvGridGeometry, *gridVariables, x, problem->name()); - VtkOutputFields::init(vtkWriter); //! Add model specific output fields + using VtkOutputFields = GetPropType; + VtkOutputModule vtkWriter(*gridVariables, x, problem->name()); + using VelocityOutput = GetPropType; + vtkWriter.addVelocityOutput(std::make_shared(*gridVariables)); + VtkOutputFields::initOutputModule(vtkWriter); //!< Add model specific output fields + vtkWriter.write(restartTime); // instantiate time loop auto timeLoop = std::make_shared>(0.0, dt, tEnd); diff --git a/exercises/solution/exercise-basic/injection2pniproblem.hh b/exercises/solution/exercise-basic/injection2pniproblem.hh index f886863..6625627 100644 --- a/exercises/solution/exercise-basic/injection2pniproblem.hh +++ b/exercises/solution/exercise-basic/injection2pniproblem.hh @@ -39,23 +39,28 @@ template class InjectionProblem2PNI; namespace Properties { -NEW_TYPE_TAG(Injection2pNITypeTag, INHERITS_FROM(TwoPNI)); -NEW_TYPE_TAG(Injection2pNICCTypeTag, INHERITS_FROM(CCTpfaModel, Injection2pNITypeTag)); +// Create new type tags +namespace TTag { +struct Injection2pNITypeTag { using InheritsFrom = std::tuple; }; +struct Injection2pNICCTypeTag { using InheritsFrom = std::tuple; }; +} // end namespace TTag // Set the grid type -SET_TYPE_PROP(Injection2pNITypeTag, Grid, Dune::YaspGrid<2>); +template +struct Grid { using type = Dune::YaspGrid<2>; }; // Set the problem property -SET_TYPE_PROP(Injection2pNITypeTag, Problem, InjectionProblem2PNI); +template +struct Problem { using type = InjectionProblem2PNI; }; // Set the spatial parameters SET_TYPE_PROP(Injection2pNITypeTag, SpatialParams, - InjectionSpatialParams); + InjectionSpatialParams, + GetPropType>); // Set fluid configuration SET_TYPE_PROP(Injection2pNITypeTag, FluidSystem, - FluidSystems::H2ON2>); + FluidSystems::H2ON2, FluidSystems::H2ON2DefaultPolicy>); } // end namespace Properties /*! @@ -83,15 +88,15 @@ template class InjectionProblem2PNI : public PorousMediumFlowProblem { using ParentType = PorousMediumFlowProblem; - using GridView = typename GET_PROP_TYPE(TypeTag, GridView); - using Scalar = typename GET_PROP_TYPE(TypeTag, Scalar); - using Indices = typename GET_PROP_TYPE(TypeTag, ModelTraits)::Indices; - using PrimaryVariables = typename GET_PROP_TYPE(TypeTag, PrimaryVariables); - using BoundaryTypes = typename GET_PROP_TYPE(TypeTag, BoundaryTypes); - using FVGridGeometry = typename GET_PROP_TYPE(TypeTag, FVGridGeometry); - using FVElementGeometry = typename GET_PROP_TYPE(TypeTag, FVGridGeometry)::LocalView; - using FluidSystem = typename GET_PROP_TYPE(TypeTag, FluidSystem); - using NumEqVector = typename GET_PROP_TYPE(TypeTag, NumEqVector); + using GridView = GetPropType; + using Scalar = GetPropType; + using Indices = typename GetPropType::Indices; + using PrimaryVariables = GetPropType; + using BoundaryTypes = GetPropType; + using FVGridGeometry = GetPropType; + using FVElementGeometry = typename GetPropType::LocalView; + using FluidSystem = GetPropType; + using NumEqVector = GetPropType; enum { dimWorld = GridView::dimensionworld }; using Element = typename GridView::template Codim<0>::Entity; -- GitLab From c2330116d202e8ab2d25f4e615ba732ac63e6083 Mon Sep 17 00:00:00 2001 From: Theresa Kurz Date: Wed, 28 Nov 2018 14:56:59 +0100 Subject: [PATCH 02/25] [exercise-runtimeparams] update to dumux 3.0 --- .../exercise_runtimeparams.cc | 45 +++++++++++++------ .../injection2pproblem.hh | 36 ++++++++------- .../exercise_runtimeparams_solution.cc | 45 +++++++++++++------ .../injection2pproblem.hh | 36 ++++++++------- 4 files changed, 106 insertions(+), 56 deletions(-) diff --git a/exercises/exercise-runtimeparams/exercise_runtimeparams.cc b/exercises/exercise-runtimeparams/exercise_runtimeparams.cc index 5356a47..315fb6f 100644 --- a/exercises/exercise-runtimeparams/exercise_runtimeparams.cc +++ b/exercises/exercise-runtimeparams/exercise_runtimeparams.cc @@ -41,10 +41,11 @@ #include #include -#include +#include #include #include +#include // The problem file, where setup-specific boundary and initial conditions are defined. #include "injection2pproblem.hh" @@ -57,7 +58,7 @@ int main(int argc, char** argv) try using namespace Dumux; // define the type tag for this problem - using TypeTag = TTAG(Injection2pCCTypeTag); + using TypeTag = Properties::TTag::Injection2pCCTypeTag; // initialize MPI, finalize is done automatically on exit const auto& mpiHelper = Dune::MPIHelper::instance(argc, argv); @@ -70,7 +71,7 @@ int main(int argc, char** argv) try Parameters::init(argc, argv); // try to create a grid (from the given grid file or the input file) - GridManager gridManager; + GridManager> gridManager; gridManager.init(); //////////////////////////////////////////////////////////// @@ -81,37 +82,55 @@ int main(int argc, char** argv) try const auto& leafGridView = gridManager.grid().leafGridView(); // create the finite volume grid geometry - using FVGridGeometry = typename GET_PROP_TYPE(TypeTag, FVGridGeometry); + using FVGridGeometry = GetPropType; auto fvGridGeometry = std::make_shared(leafGridView); fvGridGeometry->update(); // the problem (initial and boundary conditions) - using Problem = typename GET_PROP_TYPE(TypeTag, Problem); + using Problem = GetPropType; auto problem = std::make_shared(fvGridGeometry); + // check if we are about to restart a previously interrupted simulation + using Scalar = GetPropType; + Scalar restartTime = getParam("Restart.Time", 0); + // the solution vector - using SolutionVector = typename GET_PROP_TYPE(TypeTag, SolutionVector); + using SolutionVector = GetPropType; SolutionVector x(fvGridGeometry->numDofs()); - problem->applyInitialSolution(x); + if (restartTime > 0) + { + using IOFields = GetPropType; + using PrimaryVariables = GetPropType; + using ModelTraits = GetPropType; + using FluidSystem = GetPropType; + const auto fileName = getParam("Restart.File"); + const auto pvName = createPVNameFunction(); + loadSolution(x, fileName, pvName, *fvGridGeometry); + } + else + problem->applyInitialSolution(x); auto xOld = x; // the grid variables - using GridVariables = typename GET_PROP_TYPE(TypeTag, GridVariables); + using GridVariables = GetPropType; auto gridVariables = std::make_shared(problem, fvGridGeometry); - gridVariables->init(x, xOld); + gridVariables->init(x); // get some time loop parameters // getParam("GROUPNAME.PARAMNAME") reads and sets parameter PARAMNAME // of type TYPE given in the group GROUPNAME from the input file - using Scalar = typename GET_PROP_TYPE(TypeTag, Scalar); + using Scalar = GetPropType; const auto tEnd = getParam("TimeLoop.TEnd"); const auto maxDt = getParam("TimeLoop.MaxTimeStepSize"); auto dt = getParam("TimeLoop.DtInitial"); // intialize the vtk output module - using VtkOutputFields = typename GET_PROP_TYPE(TypeTag, VtkOutputFields); - VtkOutputModule vtkWriter(*problem, *fvGridGeometry, *gridVariables, x, problem->name()); - VtkOutputFields::init(vtkWriter); //! Add model specific output fields + using VtkOutputFields = GetPropType; + VtkOutputModule vtkWriter(*gridVariables, x, problem->name()); + using VelocityOutput = GetPropType; + vtkWriter.addVelocityOutput(std::make_shared(*gridVariables)); + VtkOutputFields::initOutputModule(vtkWriter); //!< Add model specific output fields + vtkWriter.write(restartTime); // instantiate time loop auto timeLoop = std::make_shared>(0.0, dt, tEnd); diff --git a/exercises/exercise-runtimeparams/injection2pproblem.hh b/exercises/exercise-runtimeparams/injection2pproblem.hh index cdc33ec..edb5d86 100644 --- a/exercises/exercise-runtimeparams/injection2pproblem.hh +++ b/exercises/exercise-runtimeparams/injection2pproblem.hh @@ -40,22 +40,28 @@ class InjectionProblem2P; namespace Properties { // define the TypeTag for this problem with a cell-centered two-point flux approximation spatial discretization. -NEW_TYPE_TAG(Injection2pTypeTag, INHERITS_FROM(TwoP)); -NEW_TYPE_TAG(Injection2pCCTypeTag, INHERITS_FROM(CCTpfaModel, Injection2pTypeTag)); +// Create new type tags +namespace TTag { +struct Injection2pTypeTag { using InheritsFrom = std::tuple; }; +struct Injection2pCCTypeTag { using InheritsFrom = std::tuple; }; +} // end namespace TTag // Set the grid type -SET_TYPE_PROP(Injection2pTypeTag, Grid, Dune::YaspGrid<2>); +template +struct Grid { using type = Dune::YaspGrid<2>; }; // Set the problem property -SET_TYPE_PROP(Injection2pTypeTag, Problem, InjectionProblem2P); +template +struct Problem { using type = InjectionProblem2P; }; // Set the spatial parameters SET_TYPE_PROP(Injection2pTypeTag, SpatialParams, - InjectionSpatialParams); + InjectionSpatialParams, + GetPropType>); // Set fluid configuration -SET_TYPE_PROP(Injection2pTypeTag, FluidSystem, FluidSystems::H2ON2 >); +template +struct FluidSystem { using type = FluidSystems::H2ON2, FluidSystems::H2ON2DefaultPolicy >; }; } // end namespace Properties /*! @@ -83,14 +89,14 @@ template class InjectionProblem2P : public PorousMediumFlowProblem { using ParentType = PorousMediumFlowProblem; - using GridView = typename GET_PROP_TYPE(TypeTag, GridView); - using Scalar = typename GET_PROP_TYPE(TypeTag, Scalar); - using Indices = typename GET_PROP_TYPE(TypeTag, ModelTraits)::Indices; - using PrimaryVariables = typename GET_PROP_TYPE(TypeTag, PrimaryVariables); - using BoundaryTypes = typename GET_PROP_TYPE(TypeTag, BoundaryTypes); - using FVGridGeometry = typename GET_PROP_TYPE(TypeTag, FVGridGeometry); - using FVElementGeometry = typename GET_PROP_TYPE(TypeTag, FVGridGeometry)::LocalView; - using FluidSystem = typename GET_PROP_TYPE(TypeTag, FluidSystem); + using GridView = GetPropType; + using Scalar = GetPropType; + using Indices = typename GetPropType::Indices; + using PrimaryVariables = GetPropType; + using BoundaryTypes = GetPropType; + using FVGridGeometry = GetPropType; + using FVElementGeometry = typename GetPropType::LocalView; + using FluidSystem = GetPropType; enum { dimWorld = GridView::dimensionworld }; using Element = typename GridView::template Codim<0>::Entity; diff --git a/exercises/solution/exercise-runtimeparams/exercise_runtimeparams_solution.cc b/exercises/solution/exercise-runtimeparams/exercise_runtimeparams_solution.cc index 5356a47..315fb6f 100644 --- a/exercises/solution/exercise-runtimeparams/exercise_runtimeparams_solution.cc +++ b/exercises/solution/exercise-runtimeparams/exercise_runtimeparams_solution.cc @@ -41,10 +41,11 @@ #include #include -#include +#include #include #include +#include // The problem file, where setup-specific boundary and initial conditions are defined. #include "injection2pproblem.hh" @@ -57,7 +58,7 @@ int main(int argc, char** argv) try using namespace Dumux; // define the type tag for this problem - using TypeTag = TTAG(Injection2pCCTypeTag); + using TypeTag = Properties::TTag::Injection2pCCTypeTag; // initialize MPI, finalize is done automatically on exit const auto& mpiHelper = Dune::MPIHelper::instance(argc, argv); @@ -70,7 +71,7 @@ int main(int argc, char** argv) try Parameters::init(argc, argv); // try to create a grid (from the given grid file or the input file) - GridManager gridManager; + GridManager> gridManager; gridManager.init(); //////////////////////////////////////////////////////////// @@ -81,37 +82,55 @@ int main(int argc, char** argv) try const auto& leafGridView = gridManager.grid().leafGridView(); // create the finite volume grid geometry - using FVGridGeometry = typename GET_PROP_TYPE(TypeTag, FVGridGeometry); + using FVGridGeometry = GetPropType; auto fvGridGeometry = std::make_shared(leafGridView); fvGridGeometry->update(); // the problem (initial and boundary conditions) - using Problem = typename GET_PROP_TYPE(TypeTag, Problem); + using Problem = GetPropType; auto problem = std::make_shared(fvGridGeometry); + // check if we are about to restart a previously interrupted simulation + using Scalar = GetPropType; + Scalar restartTime = getParam("Restart.Time", 0); + // the solution vector - using SolutionVector = typename GET_PROP_TYPE(TypeTag, SolutionVector); + using SolutionVector = GetPropType; SolutionVector x(fvGridGeometry->numDofs()); - problem->applyInitialSolution(x); + if (restartTime > 0) + { + using IOFields = GetPropType; + using PrimaryVariables = GetPropType; + using ModelTraits = GetPropType; + using FluidSystem = GetPropType; + const auto fileName = getParam("Restart.File"); + const auto pvName = createPVNameFunction(); + loadSolution(x, fileName, pvName, *fvGridGeometry); + } + else + problem->applyInitialSolution(x); auto xOld = x; // the grid variables - using GridVariables = typename GET_PROP_TYPE(TypeTag, GridVariables); + using GridVariables = GetPropType; auto gridVariables = std::make_shared(problem, fvGridGeometry); - gridVariables->init(x, xOld); + gridVariables->init(x); // get some time loop parameters // getParam("GROUPNAME.PARAMNAME") reads and sets parameter PARAMNAME // of type TYPE given in the group GROUPNAME from the input file - using Scalar = typename GET_PROP_TYPE(TypeTag, Scalar); + using Scalar = GetPropType; const auto tEnd = getParam("TimeLoop.TEnd"); const auto maxDt = getParam("TimeLoop.MaxTimeStepSize"); auto dt = getParam("TimeLoop.DtInitial"); // intialize the vtk output module - using VtkOutputFields = typename GET_PROP_TYPE(TypeTag, VtkOutputFields); - VtkOutputModule vtkWriter(*problem, *fvGridGeometry, *gridVariables, x, problem->name()); - VtkOutputFields::init(vtkWriter); //! Add model specific output fields + using VtkOutputFields = GetPropType; + VtkOutputModule vtkWriter(*gridVariables, x, problem->name()); + using VelocityOutput = GetPropType; + vtkWriter.addVelocityOutput(std::make_shared(*gridVariables)); + VtkOutputFields::initOutputModule(vtkWriter); //!< Add model specific output fields + vtkWriter.write(restartTime); // instantiate time loop auto timeLoop = std::make_shared>(0.0, dt, tEnd); diff --git a/exercises/solution/exercise-runtimeparams/injection2pproblem.hh b/exercises/solution/exercise-runtimeparams/injection2pproblem.hh index 953e36e..2d10eb6 100644 --- a/exercises/solution/exercise-runtimeparams/injection2pproblem.hh +++ b/exercises/solution/exercise-runtimeparams/injection2pproblem.hh @@ -40,22 +40,28 @@ class InjectionProblem2P; namespace Properties { // define the TypeTag for this problem with a cell-centered two-point flux approximation spatial discretization. -NEW_TYPE_TAG(Injection2pTypeTag, INHERITS_FROM(TwoP)); -NEW_TYPE_TAG(Injection2pCCTypeTag, INHERITS_FROM(CCTpfaModel, Injection2pTypeTag)); +// Create new type tags +namespace TTag { +struct Injection2pTypeTag { using InheritsFrom = std::tuple; }; +struct Injection2pCCTypeTag { using InheritsFrom = std::tuple; }; +} // end namespace TTag // Set the grid type -SET_TYPE_PROP(Injection2pTypeTag, Grid, Dune::YaspGrid<2>); +template +struct Grid { using type = Dune::YaspGrid<2>; }; // Set the problem property -SET_TYPE_PROP(Injection2pTypeTag, Problem, InjectionProblem2P); +template +struct Problem { using type = InjectionProblem2P; }; // Set the spatial parameters SET_TYPE_PROP(Injection2pTypeTag, SpatialParams, - InjectionSpatialParams); + InjectionSpatialParams, + GetPropType>); // Set fluid configuration -SET_TYPE_PROP(Injection2pTypeTag, FluidSystem, FluidSystems::H2ON2>); +template +struct FluidSystem { using type = FluidSystems::H2ON2, FluidSystems::H2ON2DefaultPolicy>; }; } // end namespace Properties /*! @@ -83,14 +89,14 @@ template class InjectionProblem2P : public PorousMediumFlowProblem { using ParentType = PorousMediumFlowProblem; - using GridView = typename GET_PROP_TYPE(TypeTag, GridView); - using Scalar = typename GET_PROP_TYPE(TypeTag, Scalar); - using Indices = typename GET_PROP_TYPE(TypeTag, ModelTraits)::Indices; - using PrimaryVariables = typename GET_PROP_TYPE(TypeTag, PrimaryVariables); - using BoundaryTypes = typename GET_PROP_TYPE(TypeTag, BoundaryTypes); - using FVGridGeometry = typename GET_PROP_TYPE(TypeTag, FVGridGeometry); - using FVElementGeometry = typename GET_PROP_TYPE(TypeTag, FVGridGeometry)::LocalView; - using FluidSystem = typename GET_PROP_TYPE(TypeTag, FluidSystem); + using GridView = GetPropType; + using Scalar = GetPropType; + using Indices = typename GetPropType::Indices; + using PrimaryVariables = GetPropType; + using BoundaryTypes = GetPropType; + using FVGridGeometry = GetPropType; + using FVElementGeometry = typename GetPropType::LocalView; + using FluidSystem = GetPropType; enum { dimWorld = GridView::dimensionworld }; using Element = typename GridView::template Codim<0>::Entity; -- GitLab From e7431e64d9a101fbb9c174f8a5633f774ee1127a Mon Sep 17 00:00:00 2001 From: Felix Weinhardt Date: Wed, 28 Nov 2018 15:23:43 +0100 Subject: [PATCH 03/25] [exercise-mainfile] update code main file and problem file --- exercises/exercise-mainfile/1pproblem.hh | 54 +++++++++++-------- exercises/exercise-mainfile/exercise_1p_a.cc | 24 +++++---- exercises/exercise-mainfile/exercise_1p_b.cc | 22 ++++---- exercises/exercise-mainfile/exercise_1p_c.cc | 24 +++++---- .../solution/exercise-mainfile/1pproblem.hh | 52 +++++++++++------- .../exercise_1p_a_solution.cc | 24 +++++---- 6 files changed, 116 insertions(+), 84 deletions(-) diff --git a/exercises/exercise-mainfile/1pproblem.hh b/exercises/exercise-mainfile/1pproblem.hh index 3a8f3ae..7deacc4 100644 --- a/exercises/exercise-mainfile/1pproblem.hh +++ b/exercises/exercise-mainfile/1pproblem.hh @@ -38,7 +38,7 @@ // TODO: dumux-course-task // uncomment the incompressiblelocalresidual which is a specialization of the standard immisible localresidual for one phase incompressible cases and provides an analytic jacobian. -//#include +#include #include #include @@ -53,46 +53,58 @@ template class OnePTestProblem; namespace Properties { // create the type tag nodes. Here we define the incompressible type tag as well as the compressible type tag. The incompressible uses a different fluidsystem than the compressible -NEW_TYPE_TAG(OnePBase, INHERITS_FROM(OneP)); -NEW_TYPE_TAG(OnePIncompressible, INHERITS_FROM(CCTpfaModel, OnePBase)); -NEW_TYPE_TAG(OnePCompressible, INHERITS_FROM(CCTpfaModel, OnePBase)); +// Create new type tags +namespace TTag { +struct OnePBase { using InheritsFrom = std::tuple; }; +struct OnePIncompressible { using InheritsFrom = std::tuple; }; +struct OnePCompressible { using InheritsFrom = std::tuple; }; +} // end namespace TTag // Set the grid type -SET_TYPE_PROP(OnePBase, Grid, Dune::YaspGrid<2>); +template +struct Grid { using type = Dune::YaspGrid<2>; }; // Set the problem type -SET_TYPE_PROP(OnePBase, Problem, OnePTestProblem); +template +struct Problem { using type = OnePTestProblem; }; // set the spatial params -SET_TYPE_PROP(OnePBase, SpatialParams, OnePTestSpatialParams); +template +struct SpatialParams { using type = OnePTestSpatialParams; }; // the fluid system for incompressible tests -SET_PROP(OnePIncompressible, FluidSystem) +template +struct FluidSystem { private: - using Scalar = typename GET_PROP_TYPE(TypeTag, Scalar); + using Scalar = GetPropType; public: using type = FluidSystems::OnePLiquid >; }; // TODO: dumux-course-task // set the OneP Incompressible local residual for the OnePIncompressible type tag. This provides an analytic jacobian to be used for the analytic solution. Change that by setting: -//SET_TYPE_PROP(OnePIncompressible, LocalResidual, OnePIncompressibleLocalResidual); +template +struct LocalResidual { using type = OnePIncompressibleLocalResidual; }; // the fluid system for compressible tests -SET_PROP(OnePCompressible, FluidSystem) +template +struct FluidSystem { private: - using Scalar = typename GET_PROP_TYPE(TypeTag, Scalar); + using Scalar = GetPropType; public: using type = FluidSystems::OnePLiquid>>; }; // Disable caching (for testing purposes) -SET_BOOL_PROP(OnePBase, EnableGridVolumeVariablesCache, false); -SET_BOOL_PROP(OnePBase, EnableGridFluxVariablesCache, false); -SET_BOOL_PROP(OnePBase, EnableFVGridGeometryCache, false); +template +struct EnableGridVolumeVariablesCache { static constexpr bool value = false; }; +template +struct EnableGridFluxVariablesCache { static constexpr bool value = false; }; +template +struct EnableFVGridGeometryCache { static constexpr bool value = false; }; } // end namespace Properties /*! @@ -106,15 +118,15 @@ template class OnePTestProblem : public PorousMediumFlowProblem { using ParentType = PorousMediumFlowProblem; - using GridView = typename GET_PROP_TYPE(TypeTag, GridView); + using GridView = GetPropType; using Element = typename GridView::template Codim<0>::Entity; - using Scalar = typename GET_PROP_TYPE(TypeTag, Scalar); - using PrimaryVariables = typename GET_PROP_TYPE(TypeTag, PrimaryVariables); - using FVGridGeometry = typename GET_PROP_TYPE(TypeTag, FVGridGeometry); - using BoundaryTypes = typename GET_PROP_TYPE(TypeTag, BoundaryTypes); + using Scalar = GetPropType; + using PrimaryVariables = GetPropType; + using FVGridGeometry = GetPropType; + using BoundaryTypes = GetPropType; static constexpr int dimWorld = GridView::dimensionworld; using GlobalPosition = typename Element::Geometry::GlobalCoordinate; - using FluidSystem = typename GET_PROP_TYPE(TypeTag, FluidSystem); + using FluidSystem = GetPropType; public: OnePTestProblem(std::shared_ptr fvGridGeometry) diff --git a/exercises/exercise-mainfile/exercise_1p_a.cc b/exercises/exercise-mainfile/exercise_1p_a.cc index 5ce59ce..0c62419 100644 --- a/exercises/exercise-mainfile/exercise_1p_a.cc +++ b/exercises/exercise-mainfile/exercise_1p_a.cc @@ -51,7 +51,7 @@ int main(int argc, char** argv) try using namespace Dumux; // define the type tag for this problem - using TypeTag = TTAG(OnePIncompressible); + using TypeTag = Properties::TTag::OnePIncompressible; //////////////////////////////////////////////////////////// //////////////////////////////////////////////////////////// @@ -70,7 +70,7 @@ int main(int argc, char** argv) try // try to create a grid (from the given grid file or the input file) ///////////////////////////////////////////////////////////////////// - GridManager gridManager; + GridManager> gridManager; gridManager.init(); //////////////////////////////////////////////////////////// @@ -81,27 +81,29 @@ int main(int argc, char** argv) try const auto& leafGridView = gridManager.grid().leafGridView(); // create the finite volume grid geometry - using FVGridGeometry = typename GET_PROP_TYPE(TypeTag, FVGridGeometry); + using FVGridGeometry = GetPropType; auto fvGridGeometry = std::make_shared(leafGridView); fvGridGeometry->update(); // the problem (initial and boundary conditions) - using Problem = typename GET_PROP_TYPE(TypeTag, Problem); + using Problem = GetPropType; auto problem = std::make_shared(fvGridGeometry); // the solution vector - using SolutionVector = typename GET_PROP_TYPE(TypeTag, SolutionVector); + using SolutionVector = GetPropType; SolutionVector x(fvGridGeometry->numDofs()); // the grid variables - using GridVariables = typename GET_PROP_TYPE(TypeTag, GridVariables); + using GridVariables = GetPropType; auto gridVariables = std::make_shared(problem, fvGridGeometry); gridVariables->init(x); - // initialize the vtk output module - using VtkOutputFields = typename GET_PROP_TYPE(TypeTag, VtkOutputFields); - VtkOutputModule vtkWriter(*problem, *fvGridGeometry, *gridVariables, x, problem->name()); - VtkOutputFields::init(vtkWriter); //!< Add model specific output fields + // intialize the vtk output module + VtkOutputModule vtkWriter(*gridVariables, x, problem->name()); + using VelocityOutput = GetPropType; + vtkWriter.addVelocityOutput(std::make_shared(*gridVariables)); + using IOFields = GetPropType; + IOFields::initOutputModule(vtkWriter); //!< Add model specific output fields vtkWriter.write(0.0); Dune::Timer timer; @@ -118,7 +120,7 @@ int main(int argc, char** argv) try auto linearSolver = std::make_shared(); // the discretization matrices for stationary linear problems - using JacobianMatrix = typename GET_PROP_TYPE(TypeTag, JacobianMatrix); + using JacobianMatrix = GetPropType; auto A = std::make_shared(); auto r = std::make_shared(); assembler->setLinearSystem(A, r); diff --git a/exercises/exercise-mainfile/exercise_1p_b.cc b/exercises/exercise-mainfile/exercise_1p_b.cc index 4fdde99..9c4af7d 100644 --- a/exercises/exercise-mainfile/exercise_1p_b.cc +++ b/exercises/exercise-mainfile/exercise_1p_b.cc @@ -52,7 +52,7 @@ int main(int argc, char** argv) try using namespace Dumux; // define the type tag for this problem - using TypeTag = TTAG(OnePCompressible); + using TypeTag = Properties::TTag::OnePCompressible; //////////////////////////////////////////////////////////// //////////////////////////////////////////////////////////// @@ -71,7 +71,7 @@ int main(int argc, char** argv) try // try to create a grid (from the given grid file or the input file) ///////////////////////////////////////////////////////////////////// - GridManager gridManager; + GridManager> gridManager; gridManager.init(); //////////////////////////////////////////////////////////// @@ -82,27 +82,29 @@ int main(int argc, char** argv) try const auto& leafGridView = gridManager.grid().leafGridView(); // create the finite volume grid geometry - using FVGridGeometry = typename GET_PROP_TYPE(TypeTag, FVGridGeometry); + using FVGridGeometry = GetPropType; auto fvGridGeometry = std::make_shared(leafGridView); fvGridGeometry->update(); // the problem (initial and boundary conditions) - using Problem = typename GET_PROP_TYPE(TypeTag, Problem); + using Problem = GetPropType; auto problem = std::make_shared(fvGridGeometry); // the solution vector - using SolutionVector = typename GET_PROP_TYPE(TypeTag, SolutionVector); + using SolutionVector = GetPropType; SolutionVector x(fvGridGeometry->numDofs()); // the grid variables - using GridVariables = typename GET_PROP_TYPE(TypeTag, GridVariables); + using GridVariables = GetPropType; auto gridVariables = std::make_shared(problem, fvGridGeometry); gridVariables->init(x); - // initialize the vtk output module - using VtkOutputFields = typename GET_PROP_TYPE(TypeTag, VtkOutputFields); - VtkOutputModule vtkWriter(*problem, *fvGridGeometry, *gridVariables, x, problem->name()); - VtkOutputFields::init(vtkWriter); //!< Add model specific output fields + // intialize the vtk output module + VtkOutputModule vtkWriter(*gridVariables, x, problem->name()); + using VelocityOutput = GetPropType; + vtkWriter.addVelocityOutput(std::make_shared(*gridVariables)); + using IOFields = GetPropType; + IOFields::initOutputModule(vtkWriter); //!< Add model specific output fields vtkWriter.write(0.0); Dune::Timer timer; diff --git a/exercises/exercise-mainfile/exercise_1p_c.cc b/exercises/exercise-mainfile/exercise_1p_c.cc index aaa2209..11f31b1 100644 --- a/exercises/exercise-mainfile/exercise_1p_c.cc +++ b/exercises/exercise-mainfile/exercise_1p_c.cc @@ -52,7 +52,7 @@ int main(int argc, char** argv) try using namespace Dumux; // define the type tag for this problem - using TypeTag = TTAG(OnePCompressible); + using TypeTag = Properties::TTag::OnePCompressible; //////////////////////////////////////////////////////////// //////////////////////////////////////////////////////////// @@ -71,7 +71,7 @@ int main(int argc, char** argv) try // try to create a grid (from the given grid file or the input file) ///////////////////////////////////////////////////////////////////// - GridManager gridManager; + GridManager> gridManager; gridManager.init(); //////////////////////////////////////////////////////////// @@ -82,33 +82,35 @@ int main(int argc, char** argv) try const auto& leafGridView = gridManager.grid().leafGridView(); // create the finite volume grid geometry - using FVGridGeometry = typename GET_PROP_TYPE(TypeTag, FVGridGeometry); + using FVGridGeometry = GetPropType; auto fvGridGeometry = std::make_shared(leafGridView); fvGridGeometry->update(); // the problem (initial and boundary conditions) - using Problem = typename GET_PROP_TYPE(TypeTag, Problem); + using Problem = GetPropType; auto problem = std::make_shared(fvGridGeometry); // the solution vector - using SolutionVector = typename GET_PROP_TYPE(TypeTag, SolutionVector); + using SolutionVector = GetPropType; SolutionVector x(fvGridGeometry->numDofs()); problem->applyInitialSolution(x); auto xOld = x; // the grid variables - using GridVariables = typename GET_PROP_TYPE(TypeTag, GridVariables); + using GridVariables = GetPropType; auto gridVariables = std::make_shared(problem, fvGridGeometry); gridVariables->init(x, xOld); - // initialize the vtk output module - using VtkOutputFields = typename GET_PROP_TYPE(TypeTag, VtkOutputFields); - VtkOutputModule vtkWriter(*problem, *fvGridGeometry, *gridVariables, x, problem->name()); - VtkOutputFields::init(vtkWriter); //!< Add model specific output fields + // intialize the vtk output module + VtkOutputModule vtkWriter(*gridVariables, x, problem->name()); + using VelocityOutput = GetPropType; + vtkWriter.addVelocityOutput(std::make_shared(*gridVariables)); + using IOFields = GetPropType; + IOFields::initOutputModule(vtkWriter); //!< Add model specific output fields vtkWriter.write(0.0); // get some time loop parameters - using Scalar = typename GET_PROP_TYPE(TypeTag, Scalar); + using Scalar = GetPropType; auto tEnd = getParam("TimeLoop.TEnd"); auto dt = getParam("TimeLoop.DtInitial"); auto maxDt = getParam("TimeLoop.MaxTimeStepSize"); diff --git a/exercises/solution/exercise-mainfile/1pproblem.hh b/exercises/solution/exercise-mainfile/1pproblem.hh index b484f75..7deacc4 100644 --- a/exercises/solution/exercise-mainfile/1pproblem.hh +++ b/exercises/solution/exercise-mainfile/1pproblem.hh @@ -53,46 +53,58 @@ template class OnePTestProblem; namespace Properties { // create the type tag nodes. Here we define the incompressible type tag as well as the compressible type tag. The incompressible uses a different fluidsystem than the compressible -NEW_TYPE_TAG(OnePBase, INHERITS_FROM(OneP)); -NEW_TYPE_TAG(OnePIncompressible, INHERITS_FROM(CCTpfaModel, OnePBase)); -NEW_TYPE_TAG(OnePCompressible, INHERITS_FROM(CCTpfaModel, OnePBase)); +// Create new type tags +namespace TTag { +struct OnePBase { using InheritsFrom = std::tuple; }; +struct OnePIncompressible { using InheritsFrom = std::tuple; }; +struct OnePCompressible { using InheritsFrom = std::tuple; }; +} // end namespace TTag // Set the grid type -SET_TYPE_PROP(OnePBase, Grid, Dune::YaspGrid<2>); +template +struct Grid { using type = Dune::YaspGrid<2>; }; // Set the problem type -SET_TYPE_PROP(OnePBase, Problem, OnePTestProblem); +template +struct Problem { using type = OnePTestProblem; }; // set the spatial params -SET_TYPE_PROP(OnePBase, SpatialParams, OnePTestSpatialParams); +template +struct SpatialParams { using type = OnePTestSpatialParams; }; // the fluid system for incompressible tests -SET_PROP(OnePIncompressible, FluidSystem) +template +struct FluidSystem { private: - using Scalar = typename GET_PROP_TYPE(TypeTag, Scalar); + using Scalar = GetPropType; public: using type = FluidSystems::OnePLiquid >; }; // TODO: dumux-course-task // set the OneP Incompressible local residual for the OnePIncompressible type tag. This provides an analytic jacobian to be used for the analytic solution. Change that by setting: -SET_TYPE_PROP(OnePIncompressible, LocalResidual, OnePIncompressibleLocalResidual); +template +struct LocalResidual { using type = OnePIncompressibleLocalResidual; }; // the fluid system for compressible tests -SET_PROP(OnePCompressible, FluidSystem) +template +struct FluidSystem { private: - using Scalar = typename GET_PROP_TYPE(TypeTag, Scalar); + using Scalar = GetPropType; public: using type = FluidSystems::OnePLiquid>>; }; // Disable caching (for testing purposes) -SET_BOOL_PROP(OnePBase, EnableGridVolumeVariablesCache, false); -SET_BOOL_PROP(OnePBase, EnableGridFluxVariablesCache, false); -SET_BOOL_PROP(OnePBase, EnableFVGridGeometryCache, false); +template +struct EnableGridVolumeVariablesCache { static constexpr bool value = false; }; +template +struct EnableGridFluxVariablesCache { static constexpr bool value = false; }; +template +struct EnableFVGridGeometryCache { static constexpr bool value = false; }; } // end namespace Properties /*! @@ -106,15 +118,15 @@ template class OnePTestProblem : public PorousMediumFlowProblem { using ParentType = PorousMediumFlowProblem; - using GridView = typename GET_PROP_TYPE(TypeTag, GridView); + using GridView = GetPropType; using Element = typename GridView::template Codim<0>::Entity; - using Scalar = typename GET_PROP_TYPE(TypeTag, Scalar); - using PrimaryVariables = typename GET_PROP_TYPE(TypeTag, PrimaryVariables); - using FVGridGeometry = typename GET_PROP_TYPE(TypeTag, FVGridGeometry); - using BoundaryTypes = typename GET_PROP_TYPE(TypeTag, BoundaryTypes); + using Scalar = GetPropType; + using PrimaryVariables = GetPropType; + using FVGridGeometry = GetPropType; + using BoundaryTypes = GetPropType; static constexpr int dimWorld = GridView::dimensionworld; using GlobalPosition = typename Element::Geometry::GlobalCoordinate; - using FluidSystem = typename GET_PROP_TYPE(TypeTag, FluidSystem); + using FluidSystem = GetPropType; public: OnePTestProblem(std::shared_ptr fvGridGeometry) diff --git a/exercises/solution/exercise-mainfile/exercise_1p_a_solution.cc b/exercises/solution/exercise-mainfile/exercise_1p_a_solution.cc index e78a822..55137bf 100644 --- a/exercises/solution/exercise-mainfile/exercise_1p_a_solution.cc +++ b/exercises/solution/exercise-mainfile/exercise_1p_a_solution.cc @@ -51,7 +51,7 @@ int main(int argc, char** argv) try using namespace Dumux; // define the type tag for this problem - using TypeTag = TTAG(TYPETAG); + using TypeTag = Properties::TTag::TYPETAG; //////////////////////////////////////////////////////////// //////////////////////////////////////////////////////////// @@ -70,7 +70,7 @@ int main(int argc, char** argv) try // try to create a grid (from the given grid file or the input file) ///////////////////////////////////////////////////////////////////// - GridManager gridManager; + GridManager> gridManager; gridManager.init(); //////////////////////////////////////////////////////////// @@ -81,29 +81,31 @@ int main(int argc, char** argv) try const auto& leafGridView = gridManager.grid().leafGridView(); // create the finite volume grid geometry - using FVGridGeometry = typename GET_PROP_TYPE(TypeTag, FVGridGeometry); + using FVGridGeometry = GetPropType; auto fvGridGeometry = std::make_shared(leafGridView); fvGridGeometry->update(); // the problem (initial and boundary conditions) - using Problem = typename GET_PROP_TYPE(TypeTag, Problem); + using Problem = GetPropType; auto problem = std::make_shared(fvGridGeometry); // the solution vector - using SolutionVector = typename GET_PROP_TYPE(TypeTag, SolutionVector); + using SolutionVector = GetPropType; SolutionVector x(fvGridGeometry->numDofs()); // the grid variables - using GridVariables = typename GET_PROP_TYPE(TypeTag, GridVariables); + using GridVariables = GetPropType; auto gridVariables = std::make_shared(problem, fvGridGeometry); gridVariables->init(x); // intialize the vtk output module - using VtkOutputFields = typename GET_PROP_TYPE(TypeTag, VtkOutputFields); - VtkOutputModule vtkWriter(*problem, *fvGridGeometry, *gridVariables, x, problem->name()); - VtkOutputFields::init(vtkWriter); //!< Add model specific output fields + VtkOutputModule vtkWriter(*gridVariables, x, problem->name()); + using VelocityOutput = GetPropType; + vtkWriter.addVelocityOutput(std::make_shared(*gridVariables)); + using IOFields = GetPropType; + IOFields::initOutputModule(vtkWriter); //!< Add model specific output fields vtkWriter.write(0.0); - + Dune::Timer timer; // TODO: dumux-course-task @@ -118,7 +120,7 @@ int main(int argc, char** argv) try auto linearSolver = std::make_shared(); // the discretization matrices for stationary linear problems - using JacobianMatrix = typename GET_PROP_TYPE(TypeTag, JacobianMatrix); + using JacobianMatrix = GetPropType; auto A = std::make_shared(); auto r = std::make_shared(); assembler->setLinearSystem(A, r); -- GitLab From b9d6ef9457beddfdfa75489ac5fe499e5493d368 Mon Sep 17 00:00:00 2001 From: Felix Weinhardt Date: Wed, 28 Nov 2018 16:04:28 +0100 Subject: [PATCH 04/25] [exercise-mainfile] updated README --- exercises/exercise-mainfile/README.md | 22 ++++++++++++---------- 1 file changed, 12 insertions(+), 10 deletions(-) diff --git a/exercises/exercise-mainfile/README.md b/exercises/exercise-mainfile/README.md index a4028be..5be7515 100644 --- a/exercises/exercise-mainfile/README.md +++ b/exercises/exercise-mainfile/README.md @@ -45,41 +45,43 @@ The general structure of any main file in DuMux is: ```c++ // define the type tag for this problem -using TypeTag = TTAG(OnePCompressible); +using TypeTag = Properties::TTag::OnePCompressible; ``` The TypeTag is created in the `1pproblem.hh`. There you can see that it inherits from the __OneP__ and additionally from the __CCTpfaModel__ which defines the discretization method, which is in this case the cell-centered tpfa method. * a gridmanager tries to create the grid either from a grid file or the input file ```c++ -GridManager gridManager; +GridManager> gridManager; gridManager.init(); ``` * we create the finite volume grid geometry, the problem, solutionvector and the gridvariables and initialize them. Additionally we initialize the vtkoutput. Each model has a predefined model specific output with relevant parameters for that model. ```c++ // create the finite volume grid geometry -using FVGridGeometry = typename GET_PROP_TYPE(TypeTag, FVGridGeometry); +using FVGridGeometry = GetPropType; auto fvGridGeometry = std::make_shared(leafGridView); fvGridGeometry->update(); // the problem (initial and boundary conditions) -using Problem = typename GET_PROP_TYPE(TypeTag, Problem); +using Problem = GetPropType; auto problem = std::make_shared(fvGridGeometry); // the solution vector -using SolutionVector = typename GET_PROP_TYPE(TypeTag, SolutionVector); +using SolutionVector = GetPropType; SolutionVector x(fvGridGeometry->numDofs()); // the grid variables -using GridVariables = typename GET_PROP_TYPE(TypeTag, GridVariables); +using GridVariables = GetPropType; auto gridVariables = std::make_shared(problem, fvGridGeometry); gridVariables->init(x); // initialize the vtk output module -using VtkOutputFields = typename GET_PROP_TYPE(TypeTag, VtkOutputFields); -VtkOutputModule vtkWriter(*problem, *fvGridGeometry, *gridVariables, x, problem->name()); -VtkOutputFields::init(vtkWriter); //!< Add model specific output fields +VtkOutputModule vtkWriter(*gridVariables, x, problem->name()); +using VelocityOutput = GetPropType; +vtkWriter.addVelocityOutput(std::make_shared(*gridVariables)); +using IOFields = GetPropType; +IOFields::initOutputModule(vtkWriter); //!< Add model specific output fields vtkWriter.write(0.0); ``` @@ -87,7 +89,7 @@ vtkWriter.write(0.0); ```c++ // get some time loop parameters -using Scalar = typename GET_PROP_TYPE(TypeTag, Scalar); +using Scalar = GetPropType; auto tEnd = getParam("TimeLoop.TEnd"); auto dt = getParam("TimeLoop.DtInitial"); auto maxDt = getParam("TimeLoop.MaxTimeStepSize"); -- GitLab From 693a7970fed24035bf8b400647ec10a56b221230 Mon Sep 17 00:00:00 2001 From: Theresa Kurz Date: Wed, 28 Nov 2018 16:20:22 +0100 Subject: [PATCH 05/25] [exercise-grid] update --- exercises/exercise-grids/README.md | 3 +- exercises/exercise-grids/exercise_grids.cc | 45 +++++++++++++----- .../exercise-grids/injection2pproblem.hh | 36 ++++++++------ .../exercise-grids/exercise_grids_solution.cc | 45 +++++++++++++----- .../exercise-grids/injection2pproblem.hh | 47 +++++++++++-------- 5 files changed, 115 insertions(+), 61 deletions(-) diff --git a/exercises/exercise-grids/README.md b/exercises/exercise-grids/README.md index aeffdc2..08b2a50 100644 --- a/exercises/exercise-grids/README.md +++ b/exercises/exercise-grids/README.md @@ -44,7 +44,8 @@ In the Problem file, the grid properties are defined using the following command ```c++ // Set the grid type -SET_TYPE_PROP(Injection2pTypeTag, Grid, Dune::YaspGrid<2>); +template +struct Grid { using type = Dune::YaspGrid<2>; }; ``` This sets the Grid, which belongs to the Injection2pTypeTag type tag, and calls the manager with a basic YaspGrid in the second dimension. diff --git a/exercises/exercise-grids/exercise_grids.cc b/exercises/exercise-grids/exercise_grids.cc index 5e56eb4..4c5a065 100644 --- a/exercises/exercise-grids/exercise_grids.cc +++ b/exercises/exercise-grids/exercise_grids.cc @@ -41,10 +41,11 @@ #include #include -#include +#include #include #include +#include // The problem file, where setup-specific boundary and initial conditions are defined. #include "injection2pproblem.hh" @@ -57,7 +58,7 @@ int main(int argc, char** argv) try using namespace Dumux; // define the type tag for this problem - using TypeTag = TTAG(Injection2pCCTypeTag); + using TypeTag = Properties::TTag::Injection2pCCTypeTag; // initialize MPI, finalize is done automatically on exit const auto& mpiHelper = Dune::MPIHelper::instance(argc, argv); @@ -70,7 +71,7 @@ int main(int argc, char** argv) try Parameters::init(argc, argv); // try to create a grid (from the given grid file or the input file) - GridManager gridManager; + GridManager> gridManager; gridManager.init(); //////////////////////////////////////////////////////////// @@ -81,37 +82,55 @@ int main(int argc, char** argv) try const auto& leafGridView = gridManager.grid().leafGridView(); // create the finite volume grid geometry - using FVGridGeometry = typename GET_PROP_TYPE(TypeTag, FVGridGeometry); + using FVGridGeometry = GetPropType; auto fvGridGeometry = std::make_shared(leafGridView); fvGridGeometry->update(); // the problem (initial and boundary conditions) - using Problem = typename GET_PROP_TYPE(TypeTag, Problem); + using Problem = GetPropType; auto problem = std::make_shared(fvGridGeometry); + // check if we are about to restart a previously interrupted simulation + using Scalar = GetPropType; + Scalar restartTime = getParam("Restart.Time", 0); + // the solution vector - using SolutionVector = typename GET_PROP_TYPE(TypeTag, SolutionVector); + using SolutionVector = GetPropType; SolutionVector x(fvGridGeometry->numDofs()); - problem->applyInitialSolution(x); + if (restartTime > 0) + { + using IOFields = GetPropType; + using PrimaryVariables = GetPropType; + using ModelTraits = GetPropType; + using FluidSystem = GetPropType; + const auto fileName = getParam("Restart.File"); + const auto pvName = createPVNameFunction(); + loadSolution(x, fileName, pvName, *fvGridGeometry); + } + else + problem->applyInitialSolution(x); auto xOld = x; // the grid variables - using GridVariables = typename GET_PROP_TYPE(TypeTag, GridVariables); + using GridVariables = GetPropType; auto gridVariables = std::make_shared(problem, fvGridGeometry); - gridVariables->init(x, xOld); + gridVariables->init(x); // get some time loop parameters // getParam("GROUPNAME.PARAMNAME") reads and sets parameter PARAMNAME // of type TYPE given in the group GROUPNAME from the input file - using Scalar = typename GET_PROP_TYPE(TypeTag, Scalar); + using Scalar = GetPropType; const auto tEnd = getParam("TimeLoop.TEnd"); const auto maxDt = getParam("TimeLoop.MaxTimeStepSize"); auto dt = getParam("TimeLoop.DtInitial"); // intialize the vtk output module - using VtkOutputFields = typename GET_PROP_TYPE(TypeTag, VtkOutputFields); - VtkOutputModule vtkWriter(*problem, *fvGridGeometry, *gridVariables, x, problem->name()); - VtkOutputFields::init(vtkWriter); //! Add model specific output fields + using VtkOutputFields = GetPropType; + VtkOutputModule vtkWriter(*gridVariables, x, problem->name()); + using VelocityOutput = GetPropType; + vtkWriter.addVelocityOutput(std::make_shared(*gridVariables)); + VtkOutputFields::initOutputModule(vtkWriter); //!< Add model specific output fields + vtkWriter.write(restartTime); // instantiate time loop auto timeLoop = std::make_shared>(0.0, dt, tEnd); diff --git a/exercises/exercise-grids/injection2pproblem.hh b/exercises/exercise-grids/injection2pproblem.hh index ab11ae9..0b9e430 100644 --- a/exercises/exercise-grids/injection2pproblem.hh +++ b/exercises/exercise-grids/injection2pproblem.hh @@ -40,25 +40,31 @@ class InjectionProblem2P; namespace Properties { // define the TypeTag for this problem with a cell-centered two-point flux approximation spatial discretization. -NEW_TYPE_TAG(Injection2pTypeTag, INHERITS_FROM(TwoP)); -NEW_TYPE_TAG(Injection2pCCTypeTag, INHERITS_FROM(CCTpfaModel, Injection2pTypeTag)); +// Create new type tags +namespace TTag { +struct Injection2pTypeTag { using InheritsFrom = std::tuple; }; +struct Injection2pCCTypeTag { using InheritsFrom = std::tuple; }; +} // end namespace TTag // Set the grid type -SET_TYPE_PROP(Injection2pTypeTag, Grid, Dune::YaspGrid<2>); +template +struct Grid { using type = Dune::YaspGrid<2>; }; // TODO: Task 2: Replace the above Grid Property definition with a more flexible grid (Use Dune::TensorProductCoordinates) // TODO: Task 4: Replace the above Grid Property definition to read in a external structured grid via a .msh file (Use Dune::ALUGrid and Dune:cube) // TODO: Task 5: Replace the above Grid Property definition to read in a external unstructured grid via a .msh file (Use Dune::ALUGrid and Dune::simplex) // Set the problem property -SET_TYPE_PROP(Injection2pTypeTag, Problem, InjectionProblem2P); +template +struct Problem { using type = InjectionProblem2P; }; // Set the spatial parameters SET_TYPE_PROP(Injection2pTypeTag, SpatialParams, - InjectionSpatialParams); + InjectionSpatialParams, + GetPropType>); // Set fluid configuration -SET_TYPE_PROP(Injection2pTypeTag, FluidSystem, FluidSystems::H2ON2>); +template +struct FluidSystem { using type = FluidSystems::H2ON2, FluidSystems::H2ON2DefaultPolicy>; }; } // end namespace Properties /*! @@ -86,14 +92,14 @@ template class InjectionProblem2P : public PorousMediumFlowProblem { using ParentType = PorousMediumFlowProblem; - using GridView = typename GET_PROP_TYPE(TypeTag, GridView); - using Scalar = typename GET_PROP_TYPE(TypeTag, Scalar); - using Indices = typename GET_PROP_TYPE(TypeTag, ModelTraits)::Indices; - using PrimaryVariables = typename GET_PROP_TYPE(TypeTag, PrimaryVariables); - using BoundaryTypes = typename GET_PROP_TYPE(TypeTag, BoundaryTypes); - using FVGridGeometry = typename GET_PROP_TYPE(TypeTag, FVGridGeometry); - using FVElementGeometry = typename GET_PROP_TYPE(TypeTag, FVGridGeometry)::LocalView; - using FluidSystem = typename GET_PROP_TYPE(TypeTag, FluidSystem); + using GridView = GetPropType; + using Scalar = GetPropType; + using Indices = typename GetPropType::Indices; + using PrimaryVariables = GetPropType; + using BoundaryTypes = GetPropType; + using FVGridGeometry = GetPropType; + using FVElementGeometry = typename GetPropType::LocalView; + using FluidSystem = GetPropType; enum { dimWorld = GridView::dimensionworld }; using Element = typename GridView::template Codim<0>::Entity; diff --git a/exercises/solution/exercise-grids/exercise_grids_solution.cc b/exercises/solution/exercise-grids/exercise_grids_solution.cc index 9da491d..6a90753 100644 --- a/exercises/solution/exercise-grids/exercise_grids_solution.cc +++ b/exercises/solution/exercise-grids/exercise_grids_solution.cc @@ -41,10 +41,11 @@ #include #include -#include +#include #include #include +#include // The problem file, where setup-specific boundary and initial conditions are defined. #include "injection2pproblem.hh" @@ -57,7 +58,7 @@ int main(int argc, char** argv) try using namespace Dumux; // define the type tag for this problem - using TypeTag = TTAG(Injection2pCCTypeTag); + using TypeTag = Properties::TTag::Injection2pCCTypeTag; // initialize MPI, finalize is done automatically on exit const auto& mpiHelper = Dune::MPIHelper::instance(argc, argv); @@ -70,7 +71,7 @@ int main(int argc, char** argv) try Parameters::init(argc, argv); // try to create a grid (from the given grid file or the input file) - GridManager gridManager; + GridManager> gridManager; gridManager.init(); //////////////////////////////////////////////////////////// @@ -81,37 +82,55 @@ int main(int argc, char** argv) try const auto& leafGridView = gridManager.grid().leafGridView(); // create the finite volume grid geometry - using FVGridGeometry = typename GET_PROP_TYPE(TypeTag, FVGridGeometry); + using FVGridGeometry = GetPropType; auto fvGridGeometry = std::make_shared(leafGridView); fvGridGeometry->update(); // the problem (initial and boundary conditions) - using Problem = typename GET_PROP_TYPE(TypeTag, Problem); + using Problem = GetPropType; auto problem = std::make_shared(fvGridGeometry); + // check if we are about to restart a previously interrupted simulation + using Scalar = GetPropType; + Scalar restartTime = getParam("Restart.Time", 0); + // the solution vector - using SolutionVector = typename GET_PROP_TYPE(TypeTag, SolutionVector); + using SolutionVector = GetPropType; SolutionVector x(fvGridGeometry->numDofs()); - problem->applyInitialSolution(x); + if (restartTime > 0) + { + using IOFields = GetPropType; + using PrimaryVariables = GetPropType; + using ModelTraits = GetPropType; + using FluidSystem = GetPropType; + const auto fileName = getParam("Restart.File"); + const auto pvName = createPVNameFunction(); + loadSolution(x, fileName, pvName, *fvGridGeometry); + } + else + problem->applyInitialSolution(x); auto xOld = x; // the grid variables - using GridVariables = typename GET_PROP_TYPE(TypeTag, GridVariables); + using GridVariables = GetPropType; auto gridVariables = std::make_shared(problem, fvGridGeometry); - gridVariables->init(x, xOld); + gridVariables->init(x); // get some time loop parameters // getParam("GROUPNAME.PARAMNAME") reads and sets parameter PARAMNAME // of type TYPE given in the group GROUPNAME from the input file - using Scalar = typename GET_PROP_TYPE(TypeTag, Scalar); + using Scalar = GetPropType; const auto tEnd = getParam("TimeLoop.TEnd"); const auto maxDt = getParam("TimeLoop.MaxTimeStepSize"); auto dt = getParam("TimeLoop.DtInitial"); // intialize the vtk output module - using VtkOutputFields = typename GET_PROP_TYPE(TypeTag, VtkOutputFields); - VtkOutputModule vtkWriter(*problem, *fvGridGeometry, *gridVariables, x, problem->name()); - VtkOutputFields::init(vtkWriter); //! Add model specific output fields + using VtkOutputFields = GetPropType; + VtkOutputModule vtkWriter(*gridVariables, x, problem->name()); + using VelocityOutput = GetPropType; + vtkWriter.addVelocityOutput(std::make_shared(*gridVariables)); + VtkOutputFields::initOutputModule(vtkWriter); //!< Add model specific output fields + vtkWriter.write(restartTime); // instantiate time loop auto timeLoop = std::make_shared>(0.0, dt, tEnd); diff --git a/exercises/solution/exercise-grids/injection2pproblem.hh b/exercises/solution/exercise-grids/injection2pproblem.hh index 0ac137c..616105a 100644 --- a/exercises/solution/exercise-grids/injection2pproblem.hh +++ b/exercises/solution/exercise-grids/injection2pproblem.hh @@ -40,30 +40,39 @@ class InjectionProblem2P; namespace Properties { // define the TypeTag for this problem with a cell-centered two-point flux approximation spatial discretization. -NEW_TYPE_TAG(Injection2pTypeTag, INHERITS_FROM(TwoP)); -NEW_TYPE_TAG(Injection2pCCTypeTag, INHERITS_FROM(CCTpfaModel, Injection2pTypeTag)); +// Create new type tags +namespace TTag { +struct Injection2pTypeTag { using InheritsFrom = std::tuple; }; +struct Injection2pCCTypeTag { using InheritsFrom = std::tuple; }; +} // end namespace TTag -// Set the grid type -SET_TYPE_PROP(Injection2pTypeTag, Grid, Dune::YaspGrid<2>); +//Set the grid type +template +struct Grid { using type = Dune::YaspGrid<2>; }; // TODO: Task 2: Replace the above Grid Property definition with a more flexible grid (Use Dune::TensorProductCoordinates) -//SET_TYPE_PROP(Injection2pTypeTag, Grid, Dune::YaspGrid<2, Dune::TensorProductCoordinates >); +template +struct Grid { using type = Dune::YaspGrid<2, Dune::TensorProductCoordinates >; }; // TODO: Task 4: Replace the above Grid Property definition to read in a external structured grid via a .msh file (Use Dune::ALUGrid and Dune:cube) -//SET_TYPE_PROP(Injection2pTypeTag, Grid, Dune::ALUGrid<2, 2, Dune::cube, Dune::nonconforming>); +template +struct Grid { using type = Dune::ALUGrid<2, 2, Dune::cube, Dune::nonconforming>; }; // TODO: Task 5: Replace the above Grid Property definition to read in a external unstructured grid via a .msh file (Use Dune::ALUGrid and Dune::simplex) -// SET_TYPE_PROP(Injection2pTypeTag, Grid, Dune::ALUGrid<2, 2, Dune::simplex, Dune::nonconforming>); +template +struct Grid { using type = Dune::ALUGrid<2, 2, Dune::simplex, Dune::nonconforming>; }; // Set the problem property -SET_TYPE_PROP(Injection2pTypeTag, Problem, InjectionProblem2P); +template +struct Problem { using type = InjectionProblem2P; }; // Set the spatial parameters SET_TYPE_PROP(Injection2pTypeTag, SpatialParams, - InjectionSpatialParams); + InjectionSpatialParams, + GetPropType>); // Set fluid configuration -SET_TYPE_PROP(Injection2pTypeTag, FluidSystem, FluidSystems::H2ON2>); +template +struct FluidSystem { using type = FluidSystems::H2ON2, FluidSystems::H2ON2DefaultPolicy>; }; } // end namespace Properties /*! @@ -91,14 +100,14 @@ template class InjectionProblem2P : public PorousMediumFlowProblem { using ParentType = PorousMediumFlowProblem; - using GridView = typename GET_PROP_TYPE(TypeTag, GridView); - using Scalar = typename GET_PROP_TYPE(TypeTag, Scalar); - using Indices = typename GET_PROP_TYPE(TypeTag, ModelTraits)::Indices; - using PrimaryVariables = typename GET_PROP_TYPE(TypeTag, PrimaryVariables); - using BoundaryTypes = typename GET_PROP_TYPE(TypeTag, BoundaryTypes); - using FVGridGeometry = typename GET_PROP_TYPE(TypeTag, FVGridGeometry); - using FVElementGeometry = typename GET_PROP_TYPE(TypeTag, FVGridGeometry)::LocalView; - using FluidSystem = typename GET_PROP_TYPE(TypeTag, FluidSystem); + using GridView = GetPropType; + using Scalar = GetPropType; + using Indices = typename GetPropType::Indices; + using PrimaryVariables = GetPropType; + using BoundaryTypes = GetPropType; + using FVGridGeometry = GetPropType; + using FVElementGeometry = typename GetPropType::LocalView; + using FluidSystem = GetPropType; enum { dimWorld = GridView::dimensionworld }; using Element = typename GridView::template Codim<0>::Entity; -- GitLab From 3f0ede686c563a858da594c1ec1c76628d49af14 Mon Sep 17 00:00:00 2001 From: Theresa Kurz Date: Wed, 28 Nov 2018 16:50:22 +0100 Subject: [PATCH 06/25] [exercise-properties] update --- exercises/exercise-properties/README.md | 3 +- .../exercise_properties.cc | 53 ++++++++++++------- exercises/exercise-properties/problem.hh | 45 +++++++++------- .../exercise_properties_solution.cc | 38 +++++++++---- 4 files changed, 90 insertions(+), 49 deletions(-) diff --git a/exercises/exercise-properties/README.md b/exercises/exercise-properties/README.md index 92a890a..ff2d42b 100644 --- a/exercises/exercise-properties/README.md +++ b/exercises/exercise-properties/README.md @@ -69,7 +69,8 @@ Types that are properties can be changed on the problem level by using the prope ```c++ // note that every property struct knows about TypeTag -SET_PROP(TwoPIncompressible, LocalResidual) +template +struct LocalResidual { using type = MyLocalResidual; }; diff --git a/exercises/exercise-properties/exercise_properties.cc b/exercises/exercise-properties/exercise_properties.cc index 3583260..558a13a 100644 --- a/exercises/exercise-properties/exercise_properties.cc +++ b/exercises/exercise-properties/exercise_properties.cc @@ -46,10 +46,11 @@ #include #include -#include +#include #include #include +#include /*! * \brief Provides an interface for customizing error messages associated with @@ -88,7 +89,7 @@ int main(int argc, char** argv) try using namespace Dumux; // define the type tag for this problem - using TypeTag = TTAG(TwoPIncompressibleTpfa); + using TypeTag = Properties::TTag::TwoPIncompressibleTpfa; // initialize MPI, finalize is done automatically on exit const auto& mpiHelper = Dune::MPIHelper::instance(argc, argv); @@ -101,7 +102,7 @@ int main(int argc, char** argv) try Parameters::init(argc, argv, usage); // try to create a grid (from the given grid file or the input file) - GridManager gridManager; + GridManager> gridManager; gridManager.init(); //////////////////////////////////////////////////////////// @@ -112,41 +113,57 @@ int main(int argc, char** argv) try const auto& leafGridView = gridManager.grid().leafGridView(); // create the finite volume grid geometry - using FVGridGeometry = typename GET_PROP_TYPE(TypeTag, FVGridGeometry); + using FVGridGeometry = GetPropType; auto fvGridGeometry = std::make_shared(leafGridView); fvGridGeometry->update(); // the problem (initial and boundary conditions) - using Problem = typename GET_PROP_TYPE(TypeTag, Problem); + using Problem = GetPropType; auto problem = std::make_shared(fvGridGeometry); + // check if we are about to restart a previously interrupted simulation + using Scalar = GetPropType; + Scalar restartTime = getParam("Restart.Time", 0); + // the solution vector - using SolutionVector = typename GET_PROP_TYPE(TypeTag, SolutionVector); + using Scalar = GetPropType; + using SolutionVector = GetPropType; SolutionVector x(fvGridGeometry->numDofs()); - problem->applyInitialSolution(x); + if (restartTime > 0) + { + using IOFields = GetPropType; + using PrimaryVariables = GetPropType; + using ModelTraits = GetPropType; + using FluidSystem = GetPropType; + const auto fileName = getParam("Restart.File"); + const auto pvName = createPVNameFunction(); + loadSolution(x, fileName, pvName, *fvGridGeometry); + } + else + problem->applyInitialSolution(x); auto xOld = x; // the grid variables - using GridVariables = typename GET_PROP_TYPE(TypeTag, GridVariables); + using GridVariables = GetPropType; auto gridVariables = std::make_shared(problem, fvGridGeometry); - gridVariables->init(x, xOld); + gridVariables->init(x); // get some time loop parameters - using Scalar = typename GET_PROP_TYPE(TypeTag, Scalar); + using Scalar = GetPropType; const auto tEnd = getParam("TimeLoop.TEnd"); const auto maxDt = getParam("TimeLoop.MaxTimeStepSize"); auto dt = getParam("TimeLoop.DtInitial"); // intialize the vtk output module - using VtkOutputFields = typename GET_PROP_TYPE(TypeTag, VtkOutputFields); + using VtkOutputFields = GetPropType; - // use non-conforming output for the test with interface solver - const auto ncOutput = getParam("Problem.UseNonConformingOutput", false); - VtkOutputModule vtkWriter(*problem, *fvGridGeometry, *gridVariables, x, problem->name(), "", - (ncOutput ? Dune::VTK::nonconforming : Dune::VTK::conforming)); - - VtkOutputFields::init(vtkWriter); //!< Add model specific output fields - vtkWriter.write(0.0); + // intialize the vtk output module + using VtkOutputFields = GetPropType; + VtkOutputModule vtkWriter(*gridVariables, x, problem->name()); + using VelocityOutput = GetPropType; + vtkWriter.addVelocityOutput(std::make_shared(*gridVariables)); + VtkOutputFields::initOutputModule(vtkWriter); //!< Add model specific output fields + vtkWriter.write(restartTime); // instantiate time loop auto timeLoop = std::make_shared>(0.0, dt, tEnd); diff --git a/exercises/exercise-properties/problem.hh b/exercises/exercise-properties/problem.hh index 020272c..6405549 100644 --- a/exercises/exercise-properties/problem.hh +++ b/exercises/exercise-properties/problem.hh @@ -47,32 +47,39 @@ namespace Dumux { template class TwoPTestProblem; namespace Properties { -NEW_TYPE_TAG(TwoPIncompressible, INHERITS_FROM(TwoP)); -NEW_TYPE_TAG(TwoPIncompressibleTpfa, INHERITS_FROM(CCTpfaModel, TwoPIncompressible)); +// Create new type tags +namespace TTag { +struct TwoPIncompressible { using InheritsFrom = std::tuple; }; +struct TwoPIncompressibleTpfa { using InheritsFrom = std::tuple; }; +} // end namespace TTag // Set the grid type -SET_TYPE_PROP(TwoPIncompressible, Grid, Dune::YaspGrid<2>); +template +struct Grid { using type = Dune::YaspGrid<2>; }; // Set the problem type -SET_TYPE_PROP(TwoPIncompressible, Problem, TwoPTestProblem); +template +struct Problem { using type = TwoPTestProblem; }; // TODO: use MyLocalResidual as LocalResidual // Set the fluid system -SET_PROP(TwoPIncompressible, FluidSystem) +template +struct FluidSystem { - using Scalar = typename GET_PROP_TYPE(TypeTag, Scalar); + using Scalar = GetPropType; using WettingPhase = FluidSystems::OnePLiquid >; using NonwettingPhase = FluidSystems::OnePLiquid >; using type = FluidSystems::TwoPImmiscible; }; // Set the spatial parameters -SET_PROP(TwoPIncompressible, SpatialParams) +template +struct SpatialParams { private: - using FVGridGeometry = typename GET_PROP_TYPE(TypeTag, FVGridGeometry); - using Scalar = typename GET_PROP_TYPE(TypeTag, Scalar); + using FVGridGeometry = GetPropType; + using Scalar = GetPropType; public: using type = TwoPTestSpatialParams; }; @@ -86,16 +93,16 @@ template class TwoPTestProblem : public PorousMediumFlowProblem { using ParentType = PorousMediumFlowProblem; - using GridView = typename GET_PROP_TYPE(TypeTag, GridView); + using GridView = GetPropType; using Element = typename GridView::template Codim<0>::Entity; - using Scalar = typename GET_PROP_TYPE(TypeTag, Scalar); - using FluidSystem = typename GET_PROP_TYPE(TypeTag, FluidSystem); - using PrimaryVariables = typename GET_PROP_TYPE(TypeTag, PrimaryVariables); - using FVGridGeometry = typename GET_PROP_TYPE(TypeTag, FVGridGeometry); - using BoundaryTypes = typename GET_PROP_TYPE(TypeTag, BoundaryTypes); + using Scalar = GetPropType; + using FluidSystem = GetPropType; + using PrimaryVariables = GetPropType; + using FVGridGeometry = GetPropType; + using BoundaryTypes = GetPropType; using GlobalPosition = typename Element::Geometry::GlobalCoordinate; - using NumEqVector = typename GET_PROP_TYPE(TypeTag, NumEqVector); - using Indices = typename GET_PROP_TYPE(TypeTag, ModelTraits)::Indices; + using NumEqVector = GetPropType; + using Indices = typename GetPropType::Indices; enum { pressureH2OIdx = Indices::pressureIdx, saturationDNAPLIdx = Indices::saturationIdx, @@ -136,7 +143,7 @@ public: PrimaryVariables dirichletAtPos(const GlobalPosition &globalPos) const { PrimaryVariables values; - typename GET_PROP_TYPE(TypeTag, FluidState) fluidState; + GetPropType fluidState; fluidState.setTemperature(temperature()); fluidState.setPressure(waterPhaseIdx, /*pressure=*/1e5); fluidState.setPressure(dnaplPhaseIdx, /*pressure=*/1e5); @@ -186,7 +193,7 @@ public: PrimaryVariables initialAtPos(const GlobalPosition &globalPos) const { PrimaryVariables values; - typename GET_PROP_TYPE(TypeTag, FluidState) fluidState; + GetPropType fluidState; fluidState.setTemperature(temperature()); fluidState.setPressure(waterPhaseIdx, /*pressure=*/1e5); fluidState.setPressure(dnaplPhaseIdx, /*pressure=*/1e5); diff --git a/exercises/solution/exercise-properties/exercise_properties_solution.cc b/exercises/solution/exercise-properties/exercise_properties_solution.cc index 3583260..01bcae0 100644 --- a/exercises/solution/exercise-properties/exercise_properties_solution.cc +++ b/exercises/solution/exercise-properties/exercise_properties_solution.cc @@ -46,10 +46,11 @@ #include #include -#include +#include #include #include +#include /*! * \brief Provides an interface for customizing error messages associated with @@ -120,16 +121,31 @@ int main(int argc, char** argv) try using Problem = typename GET_PROP_TYPE(TypeTag, Problem); auto problem = std::make_shared(fvGridGeometry); + // check if we are about to restart a previously interrupted simulation + using Scalar = GetPropType; + Scalar restartTime = getParam("Restart.Time", 0); + // the solution vector - using SolutionVector = typename GET_PROP_TYPE(TypeTag, SolutionVector); + using SolutionVector = GetPropType; SolutionVector x(fvGridGeometry->numDofs()); - problem->applyInitialSolution(x); + if (restartTime > 0) + { + using IOFields = GetPropType; + using PrimaryVariables = GetPropType; + using ModelTraits = GetPropType; + using FluidSystem = GetPropType; + const auto fileName = getParam("Restart.File"); + const auto pvName = createPVNameFunction(); + loadSolution(x, fileName, pvName, *fvGridGeometry); + } + else + problem->applyInitialSolution(x); auto xOld = x; // the grid variables using GridVariables = typename GET_PROP_TYPE(TypeTag, GridVariables); auto gridVariables = std::make_shared(problem, fvGridGeometry); - gridVariables->init(x, xOld); + gridVariables->init(x); // get some time loop parameters using Scalar = typename GET_PROP_TYPE(TypeTag, Scalar); @@ -140,13 +156,13 @@ int main(int argc, char** argv) try // intialize the vtk output module using VtkOutputFields = typename GET_PROP_TYPE(TypeTag, VtkOutputFields); - // use non-conforming output for the test with interface solver - const auto ncOutput = getParam("Problem.UseNonConformingOutput", false); - VtkOutputModule vtkWriter(*problem, *fvGridGeometry, *gridVariables, x, problem->name(), "", - (ncOutput ? Dune::VTK::nonconforming : Dune::VTK::conforming)); - - VtkOutputFields::init(vtkWriter); //!< Add model specific output fields - vtkWriter.write(0.0); + // intialize the vtk output module + using VtkOutputFields = GetPropType; + VtkOutputModule vtkWriter(*gridVariables, x, problem->name()); + using VelocityOutput = GetPropType; + vtkWriter.addVelocityOutput(std::make_shared(*gridVariables)); + VtkOutputFields::initOutputModule(vtkWriter); //!< Add model specific output fields + vtkWriter.write(restartTime); // instantiate time loop auto timeLoop = std::make_shared>(0.0, dt, tEnd); -- GitLab From d3df3e9aabd3da0c5d28c70f11fe4ff1b83f0468 Mon Sep 17 00:00:00 2001 From: Theresa Kurz Date: Wed, 28 Nov 2018 17:10:00 +0100 Subject: [PATCH 07/25] [exercise-problem] update properties in solution --- exercises/exercise-properties/README.md | 6 +-- .../exercise_properties_solution.cc | 14 +++--- .../solution/exercise-properties/problem.hh | 48 +++++++++++-------- 3 files changed, 36 insertions(+), 32 deletions(-) diff --git a/exercises/exercise-properties/README.md b/exercises/exercise-properties/README.md index ff2d42b..d04afc4 100644 --- a/exercises/exercise-properties/README.md +++ b/exercises/exercise-properties/README.md @@ -68,16 +68,12 @@ Types that are properties can be changed on the problem level by using the prope * Make DuMux use this new local residual by including the header `mylocalresidual.hh` and setting the corresponding property in the `Property` namespace in the file `problem.hh` ```c++ -// note that every property struct knows about TypeTag + template struct LocalResidual { using type = MyLocalResidual; }; - -// or using the convenience macro -SET_TYPE_PROP(TwoPIncompressible, LocalResidual, - MyLocalResidual); ``` Observe the difference in the output of the type tag tree. diff --git a/exercises/solution/exercise-properties/exercise_properties_solution.cc b/exercises/solution/exercise-properties/exercise_properties_solution.cc index 01bcae0..2b4e03a 100644 --- a/exercises/solution/exercise-properties/exercise_properties_solution.cc +++ b/exercises/solution/exercise-properties/exercise_properties_solution.cc @@ -89,7 +89,7 @@ int main(int argc, char** argv) try using namespace Dumux; // define the type tag for this problem - using TypeTag = TTAG(TwoPIncompressibleTpfa); + using TypeTag = Properties::TTag::TwoPIncompressibleTpfa; // initialize MPI, finalize is done automatically on exit const auto& mpiHelper = Dune::MPIHelper::instance(argc, argv); @@ -102,7 +102,7 @@ int main(int argc, char** argv) try Parameters::init(argc, argv, usage); // try to create a grid (from the given grid file or the input file) - GridManager gridManager; + GridManager> gridManager; gridManager.init(); //////////////////////////////////////////////////////////// @@ -113,12 +113,12 @@ int main(int argc, char** argv) try const auto& leafGridView = gridManager.grid().leafGridView(); // create the finite volume grid geometry - using FVGridGeometry = typename GET_PROP_TYPE(TypeTag, FVGridGeometry); + using FVGridGeometry = GetPropType; auto fvGridGeometry = std::make_shared(leafGridView); fvGridGeometry->update(); // the problem (initial and boundary conditions) - using Problem = typename GET_PROP_TYPE(TypeTag, Problem); + using Problem = GetPropType; auto problem = std::make_shared(fvGridGeometry); // check if we are about to restart a previously interrupted simulation @@ -143,18 +143,18 @@ int main(int argc, char** argv) try auto xOld = x; // the grid variables - using GridVariables = typename GET_PROP_TYPE(TypeTag, GridVariables); + using GridVariables = GetPropType; auto gridVariables = std::make_shared(problem, fvGridGeometry); gridVariables->init(x); // get some time loop parameters - using Scalar = typename GET_PROP_TYPE(TypeTag, Scalar); + using Scalar = GetPropType; const auto tEnd = getParam("TimeLoop.TEnd"); const auto maxDt = getParam("TimeLoop.MaxTimeStepSize"); auto dt = getParam("TimeLoop.DtInitial"); // intialize the vtk output module - using VtkOutputFields = typename GET_PROP_TYPE(TypeTag, VtkOutputFields); + using VtkOutputFields = GetPropType; // intialize the vtk output module using VtkOutputFields = GetPropType; diff --git a/exercises/solution/exercise-properties/problem.hh b/exercises/solution/exercise-properties/problem.hh index 4e1a3b4..d8a18ef 100644 --- a/exercises/solution/exercise-properties/problem.hh +++ b/exercises/solution/exercise-properties/problem.hh @@ -46,32 +46,40 @@ namespace Dumux { template class TwoPTestProblem; namespace Properties { -NEW_TYPE_TAG(TwoPIncompressible, INHERITS_FROM(TwoP)); -NEW_TYPE_TAG(TwoPIncompressibleTpfa, INHERITS_FROM(CCTpfaModel, TwoPIncompressible)); +// Create new type tags +namespace TTag { +struct TwoPIncompressible { using InheritsFrom = std::tuple; }; +struct TwoPIncompressibleTpfa { using InheritsFrom = std::tuple; }; +} // end namespace TTag // Set the grid type -SET_TYPE_PROP(TwoPIncompressible, Grid, Dune::YaspGrid<2>); +template +struct Grid { using type = Dune::YaspGrid<2>; }; // Set the problem type -SET_TYPE_PROP(TwoPIncompressible, Problem, TwoPTestProblem); +template +struct Problem { using type = TwoPTestProblem; }; -SET_TYPE_PROP(TwoPIncompressible, LocalResidual, MyLocalResidual); +template +struct LocalResidual { using type = MyLocalResidual; }; // Set the fluid system -SET_PROP(TwoPIncompressible, FluidSystem) +template +struct FluidSystem { - using Scalar = typename GET_PROP_TYPE(TypeTag, Scalar); + using Scalar = GetPropType; using WettingPhase = FluidSystems::OnePLiquid >; using NonwettingPhase = FluidSystems::OnePLiquid >; using type = FluidSystems::TwoPImmiscible; }; // Set the spatial parameters -SET_PROP(TwoPIncompressible, SpatialParams) +template +struct SpatialParams { private: - using FVGridGeometry = typename GET_PROP_TYPE(TypeTag, FVGridGeometry); - using Scalar = typename GET_PROP_TYPE(TypeTag, Scalar); + using FVGridGeometry = GetPropType; + using Scalar = GetPropType; public: using type = TwoPTestSpatialParams; }; @@ -85,16 +93,16 @@ template class TwoPTestProblem : public PorousMediumFlowProblem { using ParentType = PorousMediumFlowProblem; - using GridView = typename GET_PROP_TYPE(TypeTag, GridView); + using GridView = GetPropType; using Element = typename GridView::template Codim<0>::Entity; - using Scalar = typename GET_PROP_TYPE(TypeTag, Scalar); - using FluidSystem = typename GET_PROP_TYPE(TypeTag, FluidSystem); - using PrimaryVariables = typename GET_PROP_TYPE(TypeTag, PrimaryVariables); - using FVGridGeometry = typename GET_PROP_TYPE(TypeTag, FVGridGeometry); - using BoundaryTypes = typename GET_PROP_TYPE(TypeTag, BoundaryTypes); + using Scalar = GetPropType; + using FluidSystem = GetPropType; + using PrimaryVariables = GetPropType; + using FVGridGeometry = GetPropType; + using BoundaryTypes = GetPropType; using GlobalPosition = typename Element::Geometry::GlobalCoordinate; - using NumEqVector = typename GET_PROP_TYPE(TypeTag, NumEqVector); - using Indices = typename GET_PROP_TYPE(TypeTag, ModelTraits)::Indices; + using NumEqVector = GetPropType; + using Indices = typename GetPropType::Indices; enum { pressureH2OIdx = Indices::pressureIdx, saturationDNAPLIdx = Indices::saturationIdx, @@ -135,7 +143,7 @@ public: PrimaryVariables dirichletAtPos(const GlobalPosition &globalPos) const { PrimaryVariables values; - typename GET_PROP_TYPE(TypeTag, FluidState) fluidState; + GetPropType fluidState; fluidState.setTemperature(temperature()); fluidState.setPressure(waterPhaseIdx, /*pressure=*/1e5); fluidState.setPressure(dnaplPhaseIdx, /*pressure=*/1e5); @@ -188,7 +196,7 @@ public: PrimaryVariables initialAtPos(const GlobalPosition &globalPos) const { PrimaryVariables values; - typename GET_PROP_TYPE(TypeTag, FluidState) fluidState; + GetPropType fluidState; fluidState.setTemperature(temperature()); fluidState.setPressure(waterPhaseIdx, /*pressure=*/1e5); fluidState.setPressure(dnaplPhaseIdx, /*pressure=*/1e5); -- GitLab From c57faba1128eb5b8deaaada977eb4ae2ba0a90c6 Mon Sep 17 00:00:00 2001 From: Felix Weinhardt Date: Thu, 29 Nov 2018 14:16:44 +0100 Subject: [PATCH 08/25] [update exercise-fluidsystem] updated code and readme --- exercises/exercise-fluidsystem/2p2cproblem.hh | 42 +++++++++++------- exercises/exercise-fluidsystem/2pproblem.hh | 44 +++++++++++-------- exercises/exercise-fluidsystem/README.md | 18 +++++--- .../exercise-fluidsystem.cc | 38 +++++++++------- .../h2omycompressiblecomponent.hh | 18 +++++--- .../exercise-fluidsystem/2p2cproblem.hh | 42 +++++++++++------- .../exercise-fluidsystem/2pproblem.hh | 44 +++++++++++-------- .../exercise-fluidsystem.cc | 37 ++++++++-------- .../h2omycompressiblecomponent.hh | 14 +++--- 9 files changed, 172 insertions(+), 125 deletions(-) diff --git a/exercises/exercise-fluidsystem/2p2cproblem.hh b/exercises/exercise-fluidsystem/2p2cproblem.hh index 8cff7cc..4886824 100644 --- a/exercises/exercise-fluidsystem/2p2cproblem.hh +++ b/exercises/exercise-fluidsystem/2p2cproblem.hh @@ -45,30 +45,38 @@ template class ExerciseFluidsystemProblemTwoPTwoC; namespace Properties { // Create a new type tag for the problem -NEW_TYPE_TAG(ExerciseFluidsystemTwoPTwoCTypeTag, INHERITS_FROM(TwoPTwoC, BoxModel)); +// Create new type tags +namespace TTag { +struct ExerciseFluidsystemTwoPTwoCTypeTag { using InheritsFrom = std::tuple; }; +} // end namespace TTag // Set the "Problem" property -SET_TYPE_PROP(ExerciseFluidsystemTwoPTwoCTypeTag, Problem, ExerciseFluidsystemProblemTwoPTwoC); +template +struct Problem { using type = ExerciseFluidsystemProblemTwoPTwoC; }; // Set the spatial parameters SET_TYPE_PROP(ExerciseFluidsystemTwoPTwoCTypeTag, SpatialParams, - ExerciseFluidsystemSpatialParams); + ExerciseFluidsystemSpatialParams, + GetPropType>); // Set grid and the grid creator to be used #if HAVE_DUNE_ALUGRID -SET_TYPE_PROP(ExerciseFluidsystemTwoPTwoCTypeTag, Grid, Dune::ALUGrid); +template +struct Grid { using type = Dune::ALUGrid; }; #elif HAVE_UG -SET_TYPE_PROP(ExerciseFluidsystemTwoPTwoCTypeTag, Grid, Dune::UGGrid<2>); +template +struct Grid { using type = Dune::UGGrid<2>; }; #else -SET_TYPE_PROP(ExerciseFluidsystemTwoPTwoCTypeTag, Grid, Dune::YaspGrid<2>); +template +struct Grid { using type = Dune::YaspGrid<2>; }; #endif // HAVE_DUNE_ALUGRID // The fluid system property -SET_PROP(ExerciseFluidsystemTwoPTwoCTypeTag, FluidSystem) +template +struct FluidSystem { private: - using Scalar = typename GET_PROP_TYPE(TypeTag, Scalar); + using Scalar = GetPropType; public: using type = FluidSystems::H2OMyCompressibleComponent; }; @@ -84,8 +92,8 @@ template class ExerciseFluidsystemProblemTwoPTwoC : public PorousMediumFlowProblem { using ParentType = PorousMediumFlowProblem; - using GridView = typename GET_PROP_TYPE(TypeTag, GridView); - using Scalar = typename GET_PROP_TYPE(TypeTag, Scalar); + using GridView = GetPropType; + using Scalar = GetPropType; // Grid dimension enum { dim = GridView::dimension, @@ -95,12 +103,12 @@ class ExerciseFluidsystemProblemTwoPTwoC : public PorousMediumFlowProblem::Indices; + using PrimaryVariables = GetPropType; + using BoundaryTypes = GetPropType; + using FVGridGeometry = GetPropType; + using FVElementGeometry = typename GetPropType::LocalView; + using FluidSystem = GetPropType; public: ExerciseFluidsystemProblemTwoPTwoC(std::shared_ptr fvGridGeometry) diff --git a/exercises/exercise-fluidsystem/2pproblem.hh b/exercises/exercise-fluidsystem/2pproblem.hh index c5decbf..8fa4668 100644 --- a/exercises/exercise-fluidsystem/2pproblem.hh +++ b/exercises/exercise-fluidsystem/2pproblem.hh @@ -68,30 +68,38 @@ template class ExerciseFluidsystemProblemTwoP; namespace Properties { // Create a new type tag for the problem -NEW_TYPE_TAG(ExerciseFluidsystemTwoPTypeTag, INHERITS_FROM(TwoP, BoxModel)); +// Create new type tags +namespace TTag { +struct ExerciseFluidsystemTwoPTypeTag { using InheritsFrom = std::tuple; }; +} // end namespace TTag // Set the "Problem" property -SET_TYPE_PROP(ExerciseFluidsystemTwoPTypeTag, Problem, ExerciseFluidsystemProblemTwoP); +template +struct Problem { using type = ExerciseFluidsystemProblemTwoP; }; // Set the spatial parameters SET_TYPE_PROP(ExerciseFluidsystemTwoPTypeTag, SpatialParams, - ExerciseFluidsystemSpatialParams); + ExerciseFluidsystemSpatialParams, + GetPropType>); // Set grid to be used #if HAVE_DUNE_ALUGRID -SET_TYPE_PROP(ExerciseFluidsystemTwoPTypeTag, Grid, Dune::ALUGrid); +template +struct Grid { using type = Dune::ALUGrid; }; #elif HAVE_UG -SET_TYPE_PROP(ExerciseFluidsystemTwoPTypeTag, Grid, Dune::UGGrid<2>); +template +struct Grid { using type = Dune::UGGrid<2>; }; #else -SET_TYPE_PROP(ExerciseFluidsystemTwoPTypeTag, Grid, Dune::YaspGrid<2>); +template +struct Grid { using type = Dune::YaspGrid<2>; }; #endif // HAVE_DUNE_ALUGRID // we use the immiscible fluid system here -SET_PROP(ExerciseFluidsystemTwoPTypeTag, FluidSystem) +template +struct FluidSystem { private: - using Scalar = typename GET_PROP_TYPE(TypeTag, Scalar); + using Scalar = GetPropType; using TabulatedH2O = Components::TabulatedComponent>; using LiquidWaterPhase = typename FluidSystems::OnePLiquid; /*! @@ -115,8 +123,8 @@ template class ExerciseFluidsystemProblemTwoP : public PorousMediumFlowProblem { using ParentType = PorousMediumFlowProblem; - using GridView = typename GET_PROP_TYPE(TypeTag, GridView); - using Scalar = typename GET_PROP_TYPE(TypeTag, Scalar); + using GridView = GetPropType; + using Scalar = GetPropType; // Grid dimension enum { dim = GridView::dimension, @@ -126,13 +134,13 @@ class ExerciseFluidsystemProblemTwoP : public PorousMediumFlowProblem using GlobalPosition = typename Element::Geometry::GlobalCoordinate; // Dumux specific types - using Indices = typename GET_PROP_TYPE(TypeTag, ModelTraits)::Indices; - using PrimaryVariables = typename GET_PROP_TYPE(TypeTag, PrimaryVariables); - using BoundaryTypes = typename GET_PROP_TYPE(TypeTag, BoundaryTypes); - using FVGridGeometry = typename GET_PROP_TYPE(TypeTag, FVGridGeometry); - using FVElementGeometry = typename GET_PROP_TYPE(TypeTag, FVGridGeometry)::LocalView; - using FluidSystem = typename GET_PROP_TYPE(TypeTag, FluidSystem); - using FluidState = typename GET_PROP_TYPE(TypeTag, FluidState); + using Indices = typename GetPropType::Indices; + using PrimaryVariables = GetPropType; + using BoundaryTypes = GetPropType; + using FVGridGeometry = GetPropType; + using FVElementGeometry = typename GetPropType::LocalView; + using FluidSystem = GetPropType; + using FluidState = GetPropType; enum { waterPressureIdx = Indices::pressureIdx, diff --git a/exercises/exercise-fluidsystem/README.md b/exercises/exercise-fluidsystem/README.md index c9db143..da369d7 100644 --- a/exercises/exercise-fluidsystem/README.md +++ b/exercises/exercise-fluidsystem/README.md @@ -39,7 +39,10 @@ In this part of the exercise we will consider a system consisting of two immisci the `TwoP` _TypeTag_ (immiscible two-phase model properties) and the `BoxModel` _TypeTag_ (specifies properties of the discretization scheme). ```c++ -NEW_TYPE_TAG(ExerciseFluidsystemTwoPTypeTag, INHERITS_FROM(TwoP, BoxModel)); +// Create new type tags +namespace TTag { +struct ExerciseFluidsystemTwoPTypeTag { using InheritsFrom = std::tuple; }; +} // end namespace TTag ``` In order to be able to derive from these _TypeTags_, the declarations of the `TwoP` _TypeTag_ and `BoxModel` _TypeTag_ have to be included. @@ -95,10 +98,11 @@ the other phase is liquid as well and consists of the incompressible fictitious ```c++ // we use the immiscible fluid system here -SET_PROP(ExerciseFluidsystemTwoPTypeTag, FluidSystem) +template +struct FluidSystem { private: - using Scalar = typename GET_PROP_TYPE(TypeTag, Scalar); + using Scalar = GetPropType; using TabulatedH2O = Components::TabulatedComponent>; using LiquidWaterPhase = typename FluidSystems::OnePLiquid; /*! @@ -181,7 +185,8 @@ two-component model properties: ```c++ // Create a new type tag for the problem -NEW_TYPE_TAG(ExerciseFluidsystemTwoPTwoCTypeTag, INHERITS_FROM(TwoPTwoC, BoxModel)); +struct ExerciseFluidsystemTwoPTwoCTypeTag { using InheritsFrom = std::tuple; }; +} // end namespace TTag ``` The new fluid system is to be implemented in the file `fluidsystems/h2omycompressiblecomponent.hh`. This is already included in the problem and the fluid system property is set accordingly. @@ -193,10 +198,11 @@ The new fluid system is to be implemented in the file `fluidsystems/h2omycompres ```c++ // The fluid system property -SET_PROP(ExerciseFluidsystemTwoPTwoCTypeTag, FluidSystem) +template +struct FluidSystem { private: - using Scalar = typename GET_PROP_TYPE(TypeTag, Scalar); + using Scalar = GetPropType; public: using type = FluidSystems::H2OMyCompressibleComponent; }; diff --git a/exercises/exercise-fluidsystem/exercise-fluidsystem.cc b/exercises/exercise-fluidsystem/exercise-fluidsystem.cc index 90a44e1..61f3df1 100644 --- a/exercises/exercise-fluidsystem/exercise-fluidsystem.cc +++ b/exercises/exercise-fluidsystem/exercise-fluidsystem.cc @@ -42,16 +42,17 @@ #include #include -#include +#include #include #include -#include +#include #include #include + //////////////////////// // the main function //////////////////////// @@ -61,10 +62,10 @@ int main(int argc, char** argv) try // define the type tag for this problem // TYPETAG is set in CMakeLists.txt as compile time definition - // alternatively you could write `using TypeTag = TTAG(ExerciseFluidsystemBoxTwoPTypeTag);` - // then, for the 2p2c problem you have to change this line to `using TypeTag = TTAG(ExerciseFluidsystemBoxTwoPTypeTag);` + // alternatively you could write `using TypeTag = Properties::TTag::ExerciseFluidsystemBoxTwoPTypeTag;` + // then, for the 2p2c problem you have to change this line to `using TypeTag = Properties::TTag::ExerciseFluidsystemBoxTwoPTypeTag;` // and recompile the executable - using TypeTag = TTAG(TYPETAG); + using TypeTag = Properties::TTag::TYPETAG; // initialize MPI, finalize is done automatically on exit const auto& mpiHelper = Dune::MPIHelper::instance(argc, argv); @@ -77,7 +78,7 @@ int main(int argc, char** argv) try Parameters::init(argc, argv); // try to create a grid (from the given grid file or the input file) - GridManager gridManager; + GridManager> gridManager; gridManager.init(); //////////////////////////////////////////////////////////// @@ -88,35 +89,38 @@ int main(int argc, char** argv) try const auto& leafGridView = gridManager.grid().leafGridView(); // create the finite volume grid geometry - using FVGridGeometry = typename GET_PROP_TYPE(TypeTag, FVGridGeometry); + using FVGridGeometry = GetPropType; auto fvGridGeometry = std::make_shared(leafGridView); fvGridGeometry->update(); // the problem (initial and boundary conditions) - using Problem = typename GET_PROP_TYPE(TypeTag, Problem); + using Problem = GetPropType; auto problem = std::make_shared(fvGridGeometry); // the solution vector - using SolutionVector = typename GET_PROP_TYPE(TypeTag, SolutionVector); + using SolutionVector = GetPropType; SolutionVector x(fvGridGeometry->numDofs()); problem->applyInitialSolution(x); auto xOld = x; // the grid variables - using GridVariables = typename GET_PROP_TYPE(TypeTag, GridVariables); + using GridVariables = GetPropType; auto gridVariables = std::make_shared(problem, fvGridGeometry); - gridVariables->init(x, xOld); + gridVariables->init(x); + // get some time loop parameters - using Scalar = typename GET_PROP_TYPE(TypeTag, Scalar); + using Scalar = GetPropType; const auto tEnd = getParam("TimeLoop.TEnd"); const auto maxDt = getParam("TimeLoop.MaxTimeStepSize"); auto dt = getParam("TimeLoop.DtInitial"); // intialize the vtk output module - using VtkOutputFields = typename GET_PROP_TYPE(TypeTag, VtkOutputFields); - VtkOutputModule vtkWriter(*problem, *fvGridGeometry, *gridVariables, x, problem->name()); - VtkOutputFields::init(vtkWriter); //! Add model specific output fields + using VtkOutputFields = GetPropType; + VtkOutputModule vtkWriter(*gridVariables, x, problem->name()); + using VelocityOutput = GetPropType; + vtkWriter.addVelocityOutput(std::make_shared(*gridVariables)); + VtkOutputFields::initOutputModule(vtkWriter); //!< Add model specific output fields // instantiate time loop auto timeLoop = std::make_shared>(/*start time*/0.0, dt, tEnd); @@ -130,8 +134,8 @@ int main(int argc, char** argv) try using LinearSolver = AMGBackend; auto linearSolver = std::make_shared(leafGridView, fvGridGeometry->dofMapper()); - // the non-linear solver (primary variable switch needed for the 2p2c test in exercise b) - using NewtonSolver = Dumux::PriVarSwitchNewtonSolver; + // the non-linear solver + using NewtonSolver = NewtonSolver; NewtonSolver nonLinearSolver(assembler, linearSolver); // time loop diff --git a/exercises/exercise-fluidsystem/fluidsystems/h2omycompressiblecomponent.hh b/exercises/exercise-fluidsystem/fluidsystems/h2omycompressiblecomponent.hh index b2446b7..62965b2 100644 --- a/exercises/exercise-fluidsystem/fluidsystems/h2omycompressiblecomponent.hh +++ b/exercises/exercise-fluidsystem/fluidsystems/h2omycompressiblecomponent.hh @@ -47,14 +47,14 @@ namespace FluidSystems { template > > class H2OMyCompressibleComponent - : public BaseFluidSystem< Scalar, H2OMyCompressibleComponent > + : public Base< Scalar, H2OMyCompressibleComponent > { - typedef H2OMyCompressibleComponent ThisType; - typedef BaseFluidSystem Base; - + using ThisType = H2OMyCompressibleComponent; + using Base = Dumux::FluidSystems::Base; + public: - typedef Dumux::MyCompressibleComponent MyCompressibleComponent; - typedef H2OType H2O; + using H2O = H2OType; + using MyCompressibleComponent = Dumux::MyCompressibleComponent; static constexpr int numPhases = 2; static constexpr int numComponents = 2; @@ -121,7 +121,11 @@ public: assert(0 <= phaseIdx && phaseIdx < numPhases); return true; } - + static constexpr bool isGas(int phaseIdx) + { + assert(0 <= phaseIdx && phaseIdx < numPhases); + return phaseIdx == phase1Idx; + } static constexpr bool isIdealGas(int phaseIdx) { return H2O::gasIsIdeal() && MyCompressibleComponent::gasIsIdeal(); } diff --git a/exercises/solution/exercise-fluidsystem/2p2cproblem.hh b/exercises/solution/exercise-fluidsystem/2p2cproblem.hh index 13eb748..b46b9f0 100644 --- a/exercises/solution/exercise-fluidsystem/2p2cproblem.hh +++ b/exercises/solution/exercise-fluidsystem/2p2cproblem.hh @@ -45,30 +45,38 @@ template class ExerciseFluidsystemProblemTwoPTwoC; namespace Properties { // Create a new type tag for the problem -NEW_TYPE_TAG(ExerciseFluidsystemTwoPTwoCTypeTag, INHERITS_FROM(TwoPTwoC, BoxModel)); +// Create new type tags +namespace TTag { +struct ExerciseFluidsystemTwoPTwoCTypeTag { using InheritsFrom = std::tuple; }; +} // end namespace TTag // Set the "Problem" property -SET_TYPE_PROP(ExerciseFluidsystemTwoPTwoCTypeTag, Problem, ExerciseFluidsystemProblemTwoPTwoC); +template +struct Problem { using type = ExerciseFluidsystemProblemTwoPTwoC; }; // Set the spatial parameters SET_TYPE_PROP(ExerciseFluidsystemTwoPTwoCTypeTag, SpatialParams, - ExerciseFluidsystemSpatialParams); + ExerciseFluidsystemSpatialParams, + GetPropType>); // Set grid and the grid creator to be used #if HAVE_DUNE_ALUGRID -SET_TYPE_PROP(ExerciseFluidsystemTwoPTwoCTypeTag, Grid, Dune::ALUGrid); +template +struct Grid { using type = Dune::ALUGrid; }; #elif HAVE_UG -SET_TYPE_PROP(ExerciseFluidsystemTwoPTwoCTypeTag, Grid, Dune::UGGrid<2>); +template +struct Grid { using type = Dune::UGGrid<2>; }; #else -SET_TYPE_PROP(ExerciseFluidsystemTwoPTwoCTypeTag, Grid, Dune::YaspGrid<2>); +template +struct Grid { using type = Dune::YaspGrid<2>; }; #endif // HAVE_DUNE_ALUGRID // The fluid system property -SET_PROP(ExerciseFluidsystemTwoPTwoCTypeTag, FluidSystem) +template +struct FluidSystem { private: - using Scalar = typename GET_PROP_TYPE(TypeTag, Scalar); + using Scalar = GetPropType; public: using type = FluidSystems::H2OMyCompressibleComponent; }; @@ -84,8 +92,8 @@ template class ExerciseFluidsystemProblemTwoPTwoC : public PorousMediumFlowProblem { using ParentType = PorousMediumFlowProblem; - using GridView = typename GET_PROP_TYPE(TypeTag, GridView); - using Scalar = typename GET_PROP_TYPE(TypeTag, Scalar); + using GridView = GetPropType; + using Scalar = GetPropType; // Grid dimension enum { dim = GridView::dimension, @@ -95,12 +103,12 @@ class ExerciseFluidsystemProblemTwoPTwoC : public PorousMediumFlowProblem::Indices; + using PrimaryVariables = GetPropType; + using BoundaryTypes = GetPropType; + using FVGridGeometry = GetPropType; + using FVElementGeometry = typename GetPropType::LocalView; + using FluidSystem = GetPropType; public: ExerciseFluidsystemProblemTwoPTwoC(std::shared_ptr fvGridGeometry) diff --git a/exercises/solution/exercise-fluidsystem/2pproblem.hh b/exercises/solution/exercise-fluidsystem/2pproblem.hh index c228046..f27c36b 100644 --- a/exercises/solution/exercise-fluidsystem/2pproblem.hh +++ b/exercises/solution/exercise-fluidsystem/2pproblem.hh @@ -68,30 +68,38 @@ template class ExerciseFluidsystemProblemTwoP; namespace Properties { // Create a new type tag for the problem -NEW_TYPE_TAG(ExerciseFluidsystemTwoPTypeTag, INHERITS_FROM(TwoP, BoxModel)); +// Create new type tags +namespace TTag { +struct ExerciseFluidsystemTwoPTypeTag { using InheritsFrom = std::tuple; }; +} // end namespace TTag // Set the "Problem" property -SET_TYPE_PROP(ExerciseFluidsystemTwoPTypeTag, Problem, ExerciseFluidsystemProblemTwoP); +template +struct Problem { using type = ExerciseFluidsystemProblemTwoP; }; // Set the spatial parameters SET_TYPE_PROP(ExerciseFluidsystemTwoPTypeTag, SpatialParams, - ExerciseFluidsystemSpatialParams); + ExerciseFluidsystemSpatialParams, + GetPropType>); // Set grid to be used #if HAVE_DUNE_ALUGRID -SET_TYPE_PROP(ExerciseFluidsystemTwoPTypeTag, Grid, Dune::ALUGrid); +template +struct Grid { using type = Dune::ALUGrid; }; #elif HAVE_UG -SET_TYPE_PROP(ExerciseFluidsystemTwoPTypeTag, Grid, Dune::UGGrid<2>); +template +struct Grid { using type = Dune::UGGrid<2>; }; #else -SET_TYPE_PROP(ExerciseFluidsystemTwoPTypeTag, Grid, Dune::YaspGrid<2>); +template +struct Grid { using type = Dune::YaspGrid<2>; }; #endif // HAVE_DUNE_ALUGRID // we use the immiscible fluid system here -SET_PROP(ExerciseFluidsystemTwoPTypeTag, FluidSystem) +template +struct FluidSystem { private: - using Scalar = typename GET_PROP_TYPE(TypeTag, Scalar); + using Scalar = GetPropType; using TabulatedH2O = Components::TabulatedComponent>; using LiquidWater = typename FluidSystems::OnePLiquid; /*! @@ -115,8 +123,8 @@ template class ExerciseFluidsystemProblemTwoP : public PorousMediumFlowProblem { using ParentType = PorousMediumFlowProblem; - using GridView = typename GET_PROP_TYPE(TypeTag, GridView); - using Scalar = typename GET_PROP_TYPE(TypeTag, Scalar); + using GridView = GetPropType; + using Scalar = GetPropType; // Grid dimension enum { dim = GridView::dimension, @@ -126,13 +134,13 @@ class ExerciseFluidsystemProblemTwoP : public PorousMediumFlowProblem using GlobalPosition = typename Element::Geometry::GlobalCoordinate; // Dumux specific types - using Indices = typename GET_PROP_TYPE(TypeTag, ModelTraits)::Indices; - using PrimaryVariables = typename GET_PROP_TYPE(TypeTag, PrimaryVariables); - using BoundaryTypes = typename GET_PROP_TYPE(TypeTag, BoundaryTypes); - using FVGridGeometry = typename GET_PROP_TYPE(TypeTag, FVGridGeometry); - using FVElementGeometry = typename GET_PROP_TYPE(TypeTag, FVGridGeometry)::LocalView; - using FluidSystem = typename GET_PROP_TYPE(TypeTag, FluidSystem); - using FluidState = typename GET_PROP_TYPE(TypeTag, FluidState); + using Indices = typename GetPropType::Indices; + using PrimaryVariables = GetPropType; + using BoundaryTypes = GetPropType; + using FVGridGeometry = GetPropType; + using FVElementGeometry = typename GetPropType::LocalView; + using FluidSystem = GetPropType; + using FluidState = GetPropType; enum { waterPressureIdx = Indices::pressureIdx, diff --git a/exercises/solution/exercise-fluidsystem/exercise-fluidsystem.cc b/exercises/solution/exercise-fluidsystem/exercise-fluidsystem.cc index de88249..ce136ff 100644 --- a/exercises/solution/exercise-fluidsystem/exercise-fluidsystem.cc +++ b/exercises/solution/exercise-fluidsystem/exercise-fluidsystem.cc @@ -42,12 +42,12 @@ #include #include -#include +#include #include #include -#include +#include #include #include @@ -61,10 +61,10 @@ int main(int argc, char** argv) try // define the type tag for this problem // TYPETAG is set in CMakeLists.txt as compile time definition - // alternatively you could write `using TypeTag = TTAG(ExerciseFluidsystemTwoPTypeTag);` - // then, for the 2p2c problem you have to change this line to `using TypeTag = TTAG(ExerciseFluidsystemTwoPTwoCTypeTag);` + // alternatively you could write `using TypeTag = Properties::TTag::ExerciseFluidsystemTwoPTypeTag;` + // then, for the 2p2c problem you have to change this line to `using TypeTag = Properties::TTag::ExerciseFluidsystemTwoPTwoCTypeTag;` // and recompile the executable - using TypeTag = TTAG(TYPETAG); + using TypeTag = Properties::TTag::TYPETAG; // initialize MPI, finalize is done automatically on exit const auto& mpiHelper = Dune::MPIHelper::instance(argc, argv); @@ -77,7 +77,7 @@ int main(int argc, char** argv) try Parameters::init(argc, argv); // try to create a grid (from the given grid file or the input file) - GridManager gridManager; + GridManager> gridManager; gridManager.init(); //////////////////////////////////////////////////////////// @@ -88,35 +88,36 @@ int main(int argc, char** argv) try const auto& leafGridView = gridManager.grid().leafGridView(); // create the finite volume grid geometry - using FVGridGeometry = typename GET_PROP_TYPE(TypeTag, FVGridGeometry); + using FVGridGeometry = GetPropType; auto fvGridGeometry = std::make_shared(leafGridView); fvGridGeometry->update(); // the problem (initial and boundary conditions) - using Problem = typename GET_PROP_TYPE(TypeTag, Problem); + using Problem = GetPropType; auto problem = std::make_shared(fvGridGeometry); // the solution vector - using SolutionVector = typename GET_PROP_TYPE(TypeTag, SolutionVector); + using SolutionVector = GetPropType; SolutionVector x(fvGridGeometry->numDofs()); problem->applyInitialSolution(x); auto xOld = x; // the grid variables - using GridVariables = typename GET_PROP_TYPE(TypeTag, GridVariables); + using GridVariables = GetPropType; auto gridVariables = std::make_shared(problem, fvGridGeometry); gridVariables->init(x, xOld); // get some time loop parameters - using Scalar = typename GET_PROP_TYPE(TypeTag, Scalar); + using Scalar = GetPropType; const auto tEnd = getParam("TimeLoop.TEnd"); const auto maxDt = getParam("TimeLoop.MaxTimeStepSize"); auto dt = getParam("TimeLoop.DtInitial"); - // intialize the vtk output module - using VtkOutputFields = typename GET_PROP_TYPE(TypeTag, VtkOutputFields); - VtkOutputModule vtkWriter(*problem, *fvGridGeometry, *gridVariables, x, problem->name()); - VtkOutputFields::init(vtkWriter); //! Add model specific output fields + using VtkOutputFields = GetPropType; + VtkOutputModule vtkWriter(*gridVariables, x, problem->name()); + using VelocityOutput = GetPropType; + vtkWriter.addVelocityOutput(std::make_shared(*gridVariables)); + VtkOutputFields::initOutputModule(vtkWriter); //!< Add model specific output fields // instantiate time loop auto timeLoop = std::make_shared>(/*start time*/0.0, dt, tEnd); @@ -129,9 +130,9 @@ int main(int argc, char** argv) try // the linear solver using LinearSolver = AMGBackend; auto linearSolver = std::make_shared(leafGridView, fvGridGeometry->dofMapper()); - - // the non-linear solver (primary variable switch needed for the 2p2c test in exercise b) - using NewtonSolver = Dumux::PriVarSwitchNewtonSolver; + + // the non-linear solver + using NewtonSolver = NewtonSolver; NewtonSolver nonLinearSolver(assembler, linearSolver); // time loop diff --git a/exercises/solution/exercise-fluidsystem/fluidsystems/h2omycompressiblecomponent.hh b/exercises/solution/exercise-fluidsystem/fluidsystems/h2omycompressiblecomponent.hh index 212c0fe..6f4d9be 100644 --- a/exercises/solution/exercise-fluidsystem/fluidsystems/h2omycompressiblecomponent.hh +++ b/exercises/solution/exercise-fluidsystem/fluidsystems/h2omycompressiblecomponent.hh @@ -39,7 +39,7 @@ namespace Dumux { namespace FluidSystems { - + /*! * \brief A compositional fluid consisting of two liquid phases, * which are water and a fictitious component from exercise-fluidsystem a. @@ -47,14 +47,14 @@ namespace FluidSystems { template > > class H2OMyCompressibleComponent - : public BaseFluidSystem< Scalar, H2OMyCompressibleComponent > + : public Base< Scalar, H2OMyCompressibleComponent > { - typedef H2OMyCompressibleComponent ThisType; - typedef BaseFluidSystem Base; - + using ThisType = H2OMyCompressibleComponent; + using Base = Dumux::FluidSystems::Base; + public: - typedef Dumux::MyCompressibleComponent MyCompressibleComponent; - typedef H2OType H2O; + using H2O = H2OType; + using MyCompressibleComponent = Dumux::MyCompressibleComponent; static constexpr int numPhases = 2; static constexpr int numComponents = 2; -- GitLab From f91301563908ab4297662db02e2cf25a4d18e3e6 Mon Sep 17 00:00:00 2001 From: Felix Weinhardt Date: Fri, 30 Nov 2018 17:10:28 +0100 Subject: [PATCH 09/25] [exercise-sunemodule / exercise-fluidsystem] adjusted readme of exercise-sunemodule and exercise-fluidsystem --- exercises/exercise-dunemodule/README.md | 10 +++++----- exercises/exercise-fluidsystem/README.md | 4 ++-- 2 files changed, 7 insertions(+), 7 deletions(-) diff --git a/exercises/exercise-dunemodule/README.md b/exercises/exercise-dunemodule/README.md index 53b4ba9..dafdf9d 100644 --- a/exercises/exercise-dunemodule/README.md +++ b/exercises/exercise-dunemodule/README.md @@ -43,7 +43,7 @@ You need to run this command in the folder with content dumux, dumux-course, dun mkdir appl ``` -* Copy some test case from the dumux module, e.g. test_1p from test/porousmediumflow/1p/implicit/compressible +* Copy some test case from the dumux module, e.g. test_1p from test/porousmediumflow/1p/implicit/compressible/stationary * Copy the problem, spatialparams, cc source file, input file * Adjust the CMakeLists.txt file within the dumux-example (or your module name)-folder to include your new subdirectory @@ -52,13 +52,13 @@ mkdir appl ```cmake # add a new finite volume 1p test -dune_add_test(NAME test_1p_compressible_tpfa - SOURCES test_1p.cc +dune_add_test(NAME test_1p_compressible_stationary_tpfa + SOURCES main.cc COMPILE_DEFINITIONS TYPETAG=OnePCompressibleTpfa - CMD_ARGS test_1p.input) + CMD_ARGS params.input) # add a symlink for the input file -dune_symlink_to_source_files(FILES "test_1p.input") +dune_symlink_to_source_files(FILES "params.input") ``` diff --git a/exercises/exercise-fluidsystem/README.md b/exercises/exercise-fluidsystem/README.md index da369d7..d12f4bf 100644 --- a/exercises/exercise-fluidsystem/README.md +++ b/exercises/exercise-fluidsystem/README.md @@ -56,7 +56,7 @@ The `TwoP` _TypeTag_ can be found in the `2p/model.hh` header: while the `BoxModel` _TypeTag_ can be found in the `box/properties.hh` header: ```c++ -// The discretization +// The box discretization #include ``` @@ -164,7 +164,7 @@ We now want to implement a pressure-dependent density for our component. Open th $`\displaystyle \rho_{MyComp} = \rho_{min} + \frac{ \rho_{max} - \rho_{min} }{ 1 + \rho_{min}*e^{-1.0*k*(\rho_{max} - \rho_{min})*p} } `$ -where $`p`$ is the pressure and $`\rho_{min} = 1440 `$, $`\rho_{max} = 1480 `$ and $`k = 5 \cdot 10^{-7} `$. Also, make sure the header is included in the `2pproblem.hh` file by uncommenting line 54. Furthermore, the new component has to be set as a liquid phase in the fluid system, i.e. comment line 101 and uncomment line 102. The density distribution of this phase (rhoN) at the final simulation time should look like this: +where $`p`$ is the pressure and $`\rho_{min} = 1440 `$, $`\rho_{max} = 1480 `$ and $`k = 5 \cdot 10^{-7} `$. Also, make sure the header is included in the `2pproblem.hh` file by uncommenting line 54. Furthermore, the new component has to be set as a liquid phase in the fluid system, i.e. comment line 109 and uncomment line 110. The density distribution of this phase (rhoN) at the final simulation time should look like this: ![](../extradoc/exercise-fluidsystem_a_solution2.png) -- GitLab From 8f4ca1ebf1fffee559cbef86ead7d71e66e09d23 Mon Sep 17 00:00:00 2001 From: Felix Weinhardt Date: Mon, 3 Dec 2018 17:27:14 +0100 Subject: [PATCH 10/25] [exercise-properties] removed Task 3; Properties::print(); doesn't exist anymore --- exercises/exercise-properties/README.md | 14 +------------- 1 file changed, 1 insertion(+), 13 deletions(-) diff --git a/exercises/exercise-properties/README.md b/exercises/exercise-properties/README.md index d04afc4..1e80194 100644 --- a/exercises/exercise-properties/README.md +++ b/exercises/exercise-properties/README.md @@ -47,20 +47,9 @@ make exercise_properties Note: Because the input file has the same name as the executable, DuMux will find it automatically. -


-### Task 3: Inspect the type tag tree -
- -Many types in DuMux are properties that are attached to property tags which themselves are attached to type tags. -To view the complete type tag tree, add the line -``` -Properties::print(); -``` -directly above the `return 0;` statement of the main function. -Inspect the result.


-### Task 4: Implement a custom local residual +### Task 3: Implement a custom local residual
Types that are properties can be changed on the problem level by using the property system. In the following task we implement our own 2p local residual, i.e. the class that computes the element residual in every Newton iteration. The file `mylocalresidual.hh` contains a copy of the original local residual class used for all immiscible models renamed to `template class MyLocalResidual`. @@ -75,7 +64,6 @@ struct LocalResidual using type = MyLocalResidual; }; ``` -Observe the difference in the output of the type tag tree. Simplify the original local residual by using the assumption that only incompressible fluid phases are present. As a consequence, one can balance phase volume instead of phase mass: -- GitLab From 2e3a23c6e900b10ad81c1bf080a68a62d9537fce Mon Sep 17 00:00:00 2001 From: Felix Weinhardt Date: Wed, 5 Dec 2018 15:29:50 +0100 Subject: [PATCH 11/25] [updated include discretization file names] changed to box.hh cctpfa.hh ccmpfa.hh --- exercises/exercise-basic/injection2p2cproblem.hh | 2 +- exercises/exercise-basic/injection2pniproblem.hh | 2 +- exercises/exercise-basic/injection2pproblem.hh | 2 +- exercises/exercise-biomineralization/biominproblem.hh | 2 +- .../interface/ex_interface_pmproblem.hh | 2 +- .../exercise-coupling-ff-pm/models/ex_models_pmproblem.hh | 2 +- .../turbulence/ex_turbulence_pmproblem.hh | 2 +- exercises/exercise-fluidsystem/2p2cproblem.hh | 2 +- exercises/exercise-fluidsystem/2pproblem.hh | 2 +- exercises/exercise-fluidsystem/README.md | 2 +- exercises/exercise-fractures/fractureproblem.hh | 2 +- exercises/exercise-grids/injection2pproblem.hh | 2 +- exercises/exercise-mainfile/1pproblem.hh | 6 +++--- exercises/exercise-properties/problem.hh | 6 +++--- exercises/exercise-runtimeparams/injection2pproblem.hh | 2 +- exercises/solution/exercise-basic/injection2pniproblem.hh | 2 +- .../solution/exercise-biomineralization/biominproblem.hh | 2 +- .../interface/ex_interface_pmproblem.hh | 2 +- .../exercise-coupling-ff-pm/models/ex_models_pmproblem.hh | 2 +- .../turbulence/ex_turbulence_pmproblem.hh | 2 +- exercises/solution/exercise-fluidsystem/2p2cproblem.hh | 2 +- exercises/solution/exercise-fluidsystem/2pproblem.hh | 2 +- exercises/solution/exercise-fractures/fractureproblem.hh | 2 +- exercises/solution/exercise-grids/injection2pproblem.hh | 2 +- exercises/solution/exercise-mainfile/1pproblem.hh | 6 +++--- exercises/solution/exercise-properties/problem.hh | 6 +++--- .../solution/exercise-runtimeparams/injection2pproblem.hh | 2 +- 27 files changed, 35 insertions(+), 35 deletions(-) diff --git a/exercises/exercise-basic/injection2p2cproblem.hh b/exercises/exercise-basic/injection2p2cproblem.hh index 276f3cc..9e48382 100644 --- a/exercises/exercise-basic/injection2p2cproblem.hh +++ b/exercises/exercise-basic/injection2p2cproblem.hh @@ -24,7 +24,7 @@ #ifndef DUMUX_EX_BASIC_PROBLEM_2P2C_HH #define DUMUX_EX_BASIC_PROBLEM_2P2C_HH -#include +#include #include #include #include diff --git a/exercises/exercise-basic/injection2pniproblem.hh b/exercises/exercise-basic/injection2pniproblem.hh index 4a1e960..eb5c5a4 100644 --- a/exercises/exercise-basic/injection2pniproblem.hh +++ b/exercises/exercise-basic/injection2pniproblem.hh @@ -25,7 +25,7 @@ #ifndef DUMUX_EX_BASIC_PROBLEM_2PNI_HH #define DUMUX_EX_BASIC_PROBLEM_2PNI_HH -#include +#include #include #include #include diff --git a/exercises/exercise-basic/injection2pproblem.hh b/exercises/exercise-basic/injection2pproblem.hh index 0f05faf..414b412 100644 --- a/exercises/exercise-basic/injection2pproblem.hh +++ b/exercises/exercise-basic/injection2pproblem.hh @@ -25,7 +25,7 @@ #ifndef DUMUX_EX_BASIC_PROBLEM_2P_HH #define DUMUX_EX_BASIC_PROBLEM_2P_HH -#include +#include #include #include #include diff --git a/exercises/exercise-biomineralization/biominproblem.hh b/exercises/exercise-biomineralization/biominproblem.hh index aa2c8a2..23ef532 100644 --- a/exercises/exercise-biomineralization/biominproblem.hh +++ b/exercises/exercise-biomineralization/biominproblem.hh @@ -24,7 +24,7 @@ #ifndef DUMUX_EXERCISE_FOUR_PROBLEM_HH #define DUMUX_EXERCISE_FOUR_PROBLEM_HH -#include +#include #include #include #include "solidsystems/biominsolidphase.hh" // The biomineralization solid system diff --git a/exercises/exercise-coupling-ff-pm/interface/ex_interface_pmproblem.hh b/exercises/exercise-coupling-ff-pm/interface/ex_interface_pmproblem.hh index 6c60375..8b9f749 100644 --- a/exercises/exercise-coupling-ff-pm/interface/ex_interface_pmproblem.hh +++ b/exercises/exercise-coupling-ff-pm/interface/ex_interface_pmproblem.hh @@ -29,7 +29,7 @@ //****** uncomment for the last exercise *****// // #include -#include +#include #include #include diff --git a/exercises/exercise-coupling-ff-pm/models/ex_models_pmproblem.hh b/exercises/exercise-coupling-ff-pm/models/ex_models_pmproblem.hh index 0e48d23..c20e9e4 100644 --- a/exercises/exercise-coupling-ff-pm/models/ex_models_pmproblem.hh +++ b/exercises/exercise-coupling-ff-pm/models/ex_models_pmproblem.hh @@ -26,7 +26,7 @@ #include -#include +#include #include #include #include diff --git a/exercises/exercise-coupling-ff-pm/turbulence/ex_turbulence_pmproblem.hh b/exercises/exercise-coupling-ff-pm/turbulence/ex_turbulence_pmproblem.hh index 2d3a84d..0a9cd5f 100644 --- a/exercises/exercise-coupling-ff-pm/turbulence/ex_turbulence_pmproblem.hh +++ b/exercises/exercise-coupling-ff-pm/turbulence/ex_turbulence_pmproblem.hh @@ -26,7 +26,7 @@ #include -#include +#include #include #include diff --git a/exercises/exercise-fluidsystem/2p2cproblem.hh b/exercises/exercise-fluidsystem/2p2cproblem.hh index 4886824..a89f4da 100644 --- a/exercises/exercise-fluidsystem/2p2cproblem.hh +++ b/exercises/exercise-fluidsystem/2p2cproblem.hh @@ -28,7 +28,7 @@ #include // The box discretization -#include +#include // The base porous media box problem #include diff --git a/exercises/exercise-fluidsystem/2pproblem.hh b/exercises/exercise-fluidsystem/2pproblem.hh index 8fa4668..33950b2 100644 --- a/exercises/exercise-fluidsystem/2pproblem.hh +++ b/exercises/exercise-fluidsystem/2pproblem.hh @@ -28,7 +28,7 @@ #include // The box discretization -#include +#include // The grid managers #if HAVE_DUNE_ALUGRID diff --git a/exercises/exercise-fluidsystem/README.md b/exercises/exercise-fluidsystem/README.md index d12f4bf..3cfe4ba 100644 --- a/exercises/exercise-fluidsystem/README.md +++ b/exercises/exercise-fluidsystem/README.md @@ -57,7 +57,7 @@ while the `BoxModel` _TypeTag_ can be found in the `box/properties.hh` header: ```c++ // The box discretization -#include +#include ``` For a cell-centered scheme, you could derive from `CCTpfaModel` or `CCMpfaModel` instead (and, of course, include the right headers). diff --git a/exercises/exercise-fractures/fractureproblem.hh b/exercises/exercise-fractures/fractureproblem.hh index 2df7b24..297aa34 100644 --- a/exercises/exercise-fractures/fractureproblem.hh +++ b/exercises/exercise-fractures/fractureproblem.hh @@ -34,7 +34,7 @@ #include // we use a cell-centered finite volume scheme with tpfa here -#include +#include // include the base problem and the model we inherit from #include diff --git a/exercises/exercise-grids/injection2pproblem.hh b/exercises/exercise-grids/injection2pproblem.hh index 0b9e430..209e9f5 100644 --- a/exercises/exercise-grids/injection2pproblem.hh +++ b/exercises/exercise-grids/injection2pproblem.hh @@ -25,7 +25,7 @@ #ifndef DUMUX_EXGRIDS_INJECTION_PROBLEM_2P_HH #define DUMUX_EXGRIDS_INJECTION_PROBLEM_2P_HH -#include +#include #include #include #include diff --git a/exercises/exercise-mainfile/1pproblem.hh b/exercises/exercise-mainfile/1pproblem.hh index 7deacc4..7f1d69c 100644 --- a/exercises/exercise-mainfile/1pproblem.hh +++ b/exercises/exercise-mainfile/1pproblem.hh @@ -31,9 +31,9 @@ #include #include -#include -#include -#include +#include +#include +#include // TODO: dumux-course-task diff --git a/exercises/exercise-properties/problem.hh b/exercises/exercise-properties/problem.hh index 6405549..f336029 100644 --- a/exercises/exercise-properties/problem.hh +++ b/exercises/exercise-properties/problem.hh @@ -25,9 +25,9 @@ #include -#include -#include -#include +#include +#include +#include #include #include diff --git a/exercises/exercise-runtimeparams/injection2pproblem.hh b/exercises/exercise-runtimeparams/injection2pproblem.hh index edb5d86..7ac8abb 100644 --- a/exercises/exercise-runtimeparams/injection2pproblem.hh +++ b/exercises/exercise-runtimeparams/injection2pproblem.hh @@ -25,7 +25,7 @@ #ifndef DUMUX_EXRUNTIMEPARAMS_INJECTION_PROBLEM_2P_HH #define DUMUX_EXRUNTIMEPARAMS_INJECTION_PROBLEM_2P_HH -#include +#include #include #include #include diff --git a/exercises/solution/exercise-basic/injection2pniproblem.hh b/exercises/solution/exercise-basic/injection2pniproblem.hh index 6625627..4e20b2b 100644 --- a/exercises/solution/exercise-basic/injection2pniproblem.hh +++ b/exercises/solution/exercise-basic/injection2pniproblem.hh @@ -25,7 +25,7 @@ #ifndef DUMUX_EX_BASIC_PROBLEM_2PNI_HH #define DUMUX_EX_BASIC_PROBLEM_2PNI_HH -#include +#include #include #include #include diff --git a/exercises/solution/exercise-biomineralization/biominproblem.hh b/exercises/solution/exercise-biomineralization/biominproblem.hh index 3c24e6d..d7e6093 100644 --- a/exercises/solution/exercise-biomineralization/biominproblem.hh +++ b/exercises/solution/exercise-biomineralization/biominproblem.hh @@ -24,7 +24,7 @@ #ifndef DUMUX_EXERCISE_FOUR_PROBLEM_HH #define DUMUX_EXERCISE_FOUR_PROBLEM_HH -#include +#include #include #include #include "solidsystems/biominsolidphase.hh" // The biomineralization solid system diff --git a/exercises/solution/exercise-coupling-ff-pm/interface/ex_interface_pmproblem.hh b/exercises/solution/exercise-coupling-ff-pm/interface/ex_interface_pmproblem.hh index 7a5c4ba..d78c76f 100644 --- a/exercises/solution/exercise-coupling-ff-pm/interface/ex_interface_pmproblem.hh +++ b/exercises/solution/exercise-coupling-ff-pm/interface/ex_interface_pmproblem.hh @@ -30,7 +30,7 @@ #include #endif -#include +#include #include #include diff --git a/exercises/solution/exercise-coupling-ff-pm/models/ex_models_pmproblem.hh b/exercises/solution/exercise-coupling-ff-pm/models/ex_models_pmproblem.hh index 18ad042..b2d951b 100644 --- a/exercises/solution/exercise-coupling-ff-pm/models/ex_models_pmproblem.hh +++ b/exercises/solution/exercise-coupling-ff-pm/models/ex_models_pmproblem.hh @@ -27,7 +27,7 @@ #include #include -#include +#include #include #include #include diff --git a/exercises/solution/exercise-coupling-ff-pm/turbulence/ex_turbulence_pmproblem.hh b/exercises/solution/exercise-coupling-ff-pm/turbulence/ex_turbulence_pmproblem.hh index bd589d6..1b46ce7 100644 --- a/exercises/solution/exercise-coupling-ff-pm/turbulence/ex_turbulence_pmproblem.hh +++ b/exercises/solution/exercise-coupling-ff-pm/turbulence/ex_turbulence_pmproblem.hh @@ -26,7 +26,7 @@ #include -#include +#include #include #include diff --git a/exercises/solution/exercise-fluidsystem/2p2cproblem.hh b/exercises/solution/exercise-fluidsystem/2p2cproblem.hh index b46b9f0..35eca35 100644 --- a/exercises/solution/exercise-fluidsystem/2p2cproblem.hh +++ b/exercises/solution/exercise-fluidsystem/2p2cproblem.hh @@ -28,7 +28,7 @@ #include // The box discretization -#include +#include // The base porous media box problem #include diff --git a/exercises/solution/exercise-fluidsystem/2pproblem.hh b/exercises/solution/exercise-fluidsystem/2pproblem.hh index f27c36b..d97bba8 100644 --- a/exercises/solution/exercise-fluidsystem/2pproblem.hh +++ b/exercises/solution/exercise-fluidsystem/2pproblem.hh @@ -28,7 +28,7 @@ #include // The box discretization -#include +#include // The grid managers #if HAVE_DUNE_ALUGRID diff --git a/exercises/solution/exercise-fractures/fractureproblem.hh b/exercises/solution/exercise-fractures/fractureproblem.hh index 02c89ce..b3300c8 100644 --- a/exercises/solution/exercise-fractures/fractureproblem.hh +++ b/exercises/solution/exercise-fractures/fractureproblem.hh @@ -34,7 +34,7 @@ #include // we use a cell-centered finite volume scheme with tpfa here -#include +#include // include the base problem and the model we inherit from #include diff --git a/exercises/solution/exercise-grids/injection2pproblem.hh b/exercises/solution/exercise-grids/injection2pproblem.hh index 616105a..325d555 100644 --- a/exercises/solution/exercise-grids/injection2pproblem.hh +++ b/exercises/solution/exercise-grids/injection2pproblem.hh @@ -25,7 +25,7 @@ #ifndef DUMUX_EXGRIDS_INJECTION_PROBLEM_2P_HH #define DUMUX_EXGRIDS_INJECTION_PROBLEM_2P_HH -#include +#include #include #include #include diff --git a/exercises/solution/exercise-mainfile/1pproblem.hh b/exercises/solution/exercise-mainfile/1pproblem.hh index 7deacc4..7f1d69c 100644 --- a/exercises/solution/exercise-mainfile/1pproblem.hh +++ b/exercises/solution/exercise-mainfile/1pproblem.hh @@ -31,9 +31,9 @@ #include #include -#include -#include -#include +#include +#include +#include // TODO: dumux-course-task diff --git a/exercises/solution/exercise-properties/problem.hh b/exercises/solution/exercise-properties/problem.hh index d8a18ef..1aae5fc 100644 --- a/exercises/solution/exercise-properties/problem.hh +++ b/exercises/solution/exercise-properties/problem.hh @@ -25,9 +25,9 @@ #include -#include -#include -#include +#include +#include +#include #include #include diff --git a/exercises/solution/exercise-runtimeparams/injection2pproblem.hh b/exercises/solution/exercise-runtimeparams/injection2pproblem.hh index 2d10eb6..f553316 100644 --- a/exercises/solution/exercise-runtimeparams/injection2pproblem.hh +++ b/exercises/solution/exercise-runtimeparams/injection2pproblem.hh @@ -25,7 +25,7 @@ #ifndef DUMUX_EXRUNTIMEPARAMS_INJECTION_PROBLEM_2P_HH #define DUMUX_EXRUNTIMEPARAMS_INJECTION_PROBLEM_2P_HH -#include +#include #include #include #include -- GitLab From 92b54e432140b334f95395130102b290374cb376 Mon Sep 17 00:00:00 2001 From: Felix Weinhardt Date: Wed, 5 Dec 2018 16:52:33 +0100 Subject: [PATCH 12/25] [update exercise-biomineralization] -updated to dumux 3.0 -added a build-directory for the solution --- .../exercise-biomineralization/README.md | 12 +- .../biominproblem.hh | 66 +- .../biominspatialparams.hh | 21 +- .../chemistry/simplebiominreactions.hh | 13 +- .../exercisebiomin.cc | 25 +- .../exercisebiomin.input | 3 + .../fluidsystems/biomin.hh | 14 +- .../exercisebiomin_injectionFinal.png | Bin 17765 -> 29636 bytes .../extradoc/exercisebiomin_porosityFinal.png | Bin 14498 -> 25045 bytes exercises/solution/CMakeLists.txt | 1 + .../exercise-biomineralization/CMakeLists.txt | 10 + .../biominproblem.hh | 79 ++- .../biominspatialparams.hh | 354 +++++++++++ .../{ => chemistry}/simplebiominreactions.hh | 25 +- .../components/biofilm.hh | 77 +++ .../components/urea.hh | 58 ++ .../exercisebiomin.cc | 219 +++++++ ...in.input => exercisebiomin_solution.input} | 3 + .../fluidsystems/biomin.hh | 583 ++++++++++++++++++ .../solidsystems/biominsolidphase.hh | 201 ++++++ 20 files changed, 1655 insertions(+), 109 deletions(-) create mode 100644 exercises/solution/exercise-biomineralization/CMakeLists.txt create mode 100644 exercises/solution/exercise-biomineralization/biominspatialparams.hh rename exercises/solution/exercise-biomineralization/{ => chemistry}/simplebiominreactions.hh (88%) create mode 100644 exercises/solution/exercise-biomineralization/components/biofilm.hh create mode 100644 exercises/solution/exercise-biomineralization/components/urea.hh create mode 100644 exercises/solution/exercise-biomineralization/exercisebiomin.cc rename exercises/solution/exercise-biomineralization/{exercisebiomin.input => exercisebiomin_solution.input} (97%) create mode 100644 exercises/solution/exercise-biomineralization/fluidsystems/biomin.hh create mode 100644 exercises/solution/exercise-biomineralization/solidsystems/biominsolidphase.hh diff --git a/exercises/exercise-biomineralization/README.md b/exercises/exercise-biomineralization/README.md index f7348b0..dfd4c1b 100644 --- a/exercises/exercise-biomineralization/README.md +++ b/exercises/exercise-biomineralization/README.md @@ -124,7 +124,7 @@ Run two simulations and compare them side by side by creating two input files, o ```bash ./exercisebiomin -Problem.Name biominNoUrea -Injection.ConcUrea 0 ``` -The result for the biomineralization process after the CO2 injection should look like this: +The result for the biomineralization process during the CO2 injection should look like this: ![](../extradoc/exercisebiomin_injectionFinal.png) @@ -133,13 +133,13 @@ The result for the biomineralization process after the CO2 injection should look In the last step, the manual comparison of the results can be quite difficult. Paraview offers the option to use programmable python filters. To use them, make sure two result files with __different names__ are loaded. Mark both of them and click on `Filters --> Alphabetical --> Programmable Filter`. Now a new field opens on the left side. Copy the following lines there: ```python -Sn_0 = inputs[0].CellData['S_n']; -Sn_1 = inputs[1].CellData['S_n']; -output.CellData.append(abs(Sn_0-Sn_1),'diffSn'); +S_gas_0 = inputs[0].CellData['S_gas']; +S_gas_1 = inputs[1].CellData['S_gas']; +output.CellData.append(abs(S_gas_0-S_gas_1),'diffS_gas'); ``` -Click `Apply` and select `diffSn` as new output. You should now see the difference between the two result files. You can also change the output to a not absolute value by changing the last line to: +Click `Apply` and select `diffS_gas` as new output. You should now see the difference between the two result files. You can also change the output to a not absolute value by changing the last line to: ```python -output.CellData.append((Sn_0-Sn_1),'diffSn'); +output.CellData.append((S_gas_0-S_gas_1),'diffS_gas'); ``` diff --git a/exercises/exercise-biomineralization/biominproblem.hh b/exercises/exercise-biomineralization/biominproblem.hh index 23ef532..f015d7e 100644 --- a/exercises/exercise-biomineralization/biominproblem.hh +++ b/exercises/exercise-biomineralization/biominproblem.hh @@ -51,42 +51,54 @@ class ExerciseFourBioMinProblem; namespace Properties { //! Create new type tag for the problem -NEW_TYPE_TAG(ExerciseFourBioMinTypeTag, INHERITS_FROM(TwoPNCMin, BioMinSpatialparams)); -NEW_TYPE_TAG(ExerciseFourBioMinCCTpfaTypeTag, INHERITS_FROM(CCTpfaModel, ExerciseFourBioMinTypeTag)); +// Create new type tags +namespace TTag { +struct ExerciseFourBioMinTypeTag { using InheritsFrom = std::tuple; }; +struct ExerciseFourBioMinCCTpfaTypeTag { using InheritsFrom = std::tuple; }; +} // end namespace TTag //! Set the problem property -SET_TYPE_PROP(ExerciseFourBioMinTypeTag, Problem, ExerciseFourBioMinProblem); +template +struct Problem { using type = ExerciseFourBioMinProblem; }; //! Set grid and the grid creator to be used #if HAVE_DUNE_ALUGRID -SET_TYPE_PROP(ExerciseFourBioMinTypeTag, Grid, Dune::ALUGrid); +template +struct Grid { using type = Dune::ALUGrid; }; #elif HAVE_UG -SET_TYPE_PROP(ExerciseFourBioMinTypeTag, Grid, Dune::UGGrid<2>); +template +struct Grid { using type = Dune::UGGrid<2>; }; #else -SET_TYPE_PROP(ExerciseFourBioMinTypeTag, Grid, Dune::YaspGrid<2>); +template +struct Grid { using type = Dune::YaspGrid<2>; }; #endif // HAVE_DUNE_ALUGRID //! Set the fluid system type -SET_PROP(ExerciseFourBioMinTypeTag, FluidSystem) +template +struct FluidSystem { private: - using Scalar = typename GET_PROP_TYPE(TypeTag, Scalar); + using Scalar = GetPropType; using CO2Tables = Dumux::CO2Tables; using H2OType = Components::TabulatedComponent>; public: using type = FluidSystems::BioMin; }; -SET_PROP(ExerciseFourBioMinTypeTag, SolidSystem) +template +struct SolidSystem { - using Scalar = typename GET_PROP_TYPE(TypeTag, Scalar); + using Scalar = GetPropType; using type = SolidSystems::BiominSolidPhase; }; -SET_BOOL_PROP(ExerciseFourBioMinTypeTag, EnableFVGridGeometryCache, false); -SET_BOOL_PROP(ExerciseFourBioMinTypeTag, EnableGridVolumeVariablesCache, false); -SET_BOOL_PROP(ExerciseFourBioMinTypeTag, EnableGridFluxVariablesCache, false); +template +struct EnableFVGridGeometryCache { static constexpr bool value = false; }; +template +struct EnableGridVolumeVariablesCache { static constexpr bool value = false; }; +template +struct EnableGridFluxVariablesCache { static constexpr bool value = false; }; } // end namespace properties /*! @@ -98,16 +110,16 @@ class ExerciseFourBioMinProblem : public PorousMediumFlowProblem { using ParentType = PorousMediumFlowProblem; - using GridView = typename GET_PROP_TYPE(TypeTag, GridView); - using Scalar = typename GET_PROP_TYPE(TypeTag, Scalar); - using FluidSystem = typename GET_PROP_TYPE(TypeTag, FluidSystem); - using SolidSystem = typename GET_PROP_TYPE(TypeTag, SolidSystem); - using Indices = typename GET_PROP_TYPE(TypeTag, ModelTraits)::Indices; - using PrimaryVariables = typename GET_PROP_TYPE(TypeTag, PrimaryVariables); - using BoundaryTypes = typename GET_PROP_TYPE(TypeTag, BoundaryTypes); - using VolumeVariables = typename GET_PROP_TYPE(TypeTag, VolumeVariables); - using FVGridGeometry = typename GET_PROP_TYPE(TypeTag, FVGridGeometry); - using FVElementGeometry = typename GET_PROP_TYPE(TypeTag, FVGridGeometry)::LocalView; + using GridView = GetPropType; + using Scalar = GetPropType; + using FluidSystem = GetPropType; + using SolidSystem = GetPropType; + using Indices = typename GetPropType::Indices; + using PrimaryVariables = GetPropType; + using BoundaryTypes = GetPropType; + using VolumeVariables = GetPropType; + using FVGridGeometry = GetPropType; + using FVElementGeometry = typename GetPropType::LocalView; // Grid dimension enum @@ -117,10 +129,10 @@ class ExerciseFourBioMinProblem : public PorousMediumFlowProblem }; using GlobalPosition = Dune::FieldVector; - using NumEqVector = typename GET_PROP_TYPE(TypeTag, NumEqVector); - using ElementVolumeVariables = typename GET_PROP_TYPE(TypeTag, GridVolumeVariables)::LocalView; + using NumEqVector = GetPropType; + using ElementVolumeVariables = typename GetPropType::LocalView; using Element = typename GridView::template Codim<0>::Entity; - using SolutionVector = typename GET_PROP_TYPE(TypeTag, SolutionVector); + using SolutionVector = GetPropType; using SubControlVolume = typename FVElementGeometry::SubControlVolume; // TODO: dumux-course-task // set the chemistry TypeTag @@ -173,7 +185,7 @@ public: concCa_ = getParam("Injection.ConcCa"); concUrea_ = getParam("Injection.ConcUrea"); - unsigned int codim = GET_PROP_TYPE(TypeTag, FVGridGeometry)::discMethod == DiscretizationMethod::box ? dim : 0; + unsigned int codim = GetPropType::discMethod == DiscretizationMethod::box ? dim : 0; Kxx_.resize(fvGridGeometry->gridView().size(codim)); Kyy_.resize(fvGridGeometry->gridView().size(codim)); diff --git a/exercises/exercise-biomineralization/biominspatialparams.hh b/exercises/exercise-biomineralization/biominspatialparams.hh index c8d01ef..12be491 100644 --- a/exercises/exercise-biomineralization/biominspatialparams.hh +++ b/exercises/exercise-biomineralization/biominspatialparams.hh @@ -31,7 +31,7 @@ #include #include -#include +#include namespace Dumux { @@ -45,7 +45,8 @@ namespace Properties NEW_TYPE_TAG(BioMinSpatialparams); // Set the spatial parameters -SET_TYPE_PROP(BioMinSpatialparams, SpatialParams, BioMinSpatialparams); +template +struct SpatialParams { using type = BioMinSpatialparams; }; } // end namespace Properties /*! @@ -54,17 +55,17 @@ SET_TYPE_PROP(BioMinSpatialparams, SpatialParams, BioMinSpatialparams); */ template class BioMinSpatialparams -: public FVSpatialParams, + GetPropType, BioMinSpatialparams> { - using Scalar = typename GET_PROP_TYPE(TypeTag, Scalar); - using FVGridGeometry = typename GET_PROP_TYPE(TypeTag, FVGridGeometry); + using Scalar = GetPropType; + using FVGridGeometry = GetPropType; using FVElementGeometry = typename FVGridGeometry::LocalView; using SubControlVolume = typename FVElementGeometry::SubControlVolume; using ParentType = FVSpatialParams>; using EffectiveLaw = RegularizedBrooksCorey; - using SolutionVector = typename GET_PROP_TYPE(TypeTag, SolutionVector); + using SolutionVector = GetPropType; using GridView = typename FVGridGeometry::GridView; using CoordScalar = typename GridView::ctype; @@ -75,7 +76,7 @@ class BioMinSpatialparams using Tensor = Dune::FieldMatrix; public: - using SolidSystem = typename GET_PROP_TYPE(TypeTag, SolidSystem); + using SolidSystem = GetPropType; using PermeabilityType = Tensor; using MaterialLaw = EffToAbsLaw; using MaterialLawParams = typename MaterialLaw::Params; @@ -331,8 +332,8 @@ private: bool isFaultZone_(const GlobalPosition &globalPos) const { return globalPos[dimWorld-2] > 2 - eps_ && globalPos[dimWorld-2] < 3 + eps_;} - using ModelTraits = typename GET_PROP_TYPE(TypeTag, ModelTraits); - PorosityPrecipitation poroLaw_; + using ModelTraits = GetPropType; + PorosityPrecipitation poroLaw_; PermeabilityKozenyCarman permLaw_; diff --git a/exercises/exercise-biomineralization/chemistry/simplebiominreactions.hh b/exercises/exercise-biomineralization/chemistry/simplebiominreactions.hh index fff7201..bc0e0f0 100644 --- a/exercises/exercise-biomineralization/chemistry/simplebiominreactions.hh +++ b/exercises/exercise-biomineralization/chemistry/simplebiominreactions.hh @@ -33,12 +33,12 @@ namespace Dumux { template class SimpleBiominReactions { - using Scalar = typename GET_PROP_TYPE(TypeTag, Scalar); - using FluidSystem = typename GET_PROP_TYPE(TypeTag, FluidSystem); - using SolidSystem = typename GET_PROP_TYPE(TypeTag, SolidSystem); - using VolumeVariables = typename GET_PROP_TYPE(TypeTag, VolumeVariables); + using Scalar = GetPropType; + using FluidSystem = GetPropType; + using SolidSystem = GetPropType; + using VolumeVariables = GetPropType; using ThisType = SimpleBiominReactions; - using Sources = typename GET_PROP_TYPE(TypeTag, NumEqVector); + using Sources = GetPropType; public: @@ -100,7 +100,6 @@ public: if (molalityUrea < 0) molalityUrea = 0; - // compute rate of ureolysis: // TODO: dumux-course-task // compute rate of ureolysis by implementing Z_urease,biofilm and r_urea @@ -121,7 +120,7 @@ public: q[BiofilmIdx] += 0; q[CalciteIdx] += 0; } - + private: // urease parameters Scalar kub_; diff --git a/exercises/exercise-biomineralization/exercisebiomin.cc b/exercises/exercise-biomineralization/exercisebiomin.cc index dc84ce8..a4cbddf 100644 --- a/exercises/exercise-biomineralization/exercisebiomin.cc +++ b/exercises/exercise-biomineralization/exercisebiomin.cc @@ -39,12 +39,12 @@ #include #include -#include +#include #include #include -#include +#include #include #include @@ -59,7 +59,7 @@ int main(int argc, char** argv) try using namespace Dumux; // define the type tag for this problem - using TypeTag = TTAG(ExerciseFourBioMinCCTpfaTypeTag); + using TypeTag = Properties::TTag::ExerciseFourBioMinCCTpfaTypeTag; // initialize MPI, finalize is done automatically on exit const auto& mpiHelper = Dune::MPIHelper::instance(argc, argv); @@ -72,7 +72,7 @@ int main(int argc, char** argv) try Parameters::init(argc, argv); // try to create a grid (from the given grid file or the input file) - GridManager gridManager; + GridManager> gridManager; gridManager.init(); //////////////////////////////////////////////////////////// @@ -83,16 +83,16 @@ int main(int argc, char** argv) try const auto& leafGridView = gridManager.grid().leafGridView(); // create the finite volume grid geometry - using FVGridGeometry = typename GET_PROP_TYPE(TypeTag, FVGridGeometry); + using FVGridGeometry = GetPropType; auto fvGridGeometry = std::make_shared(leafGridView); fvGridGeometry->update(); // the problem (initial and boundary conditions) - using Problem = typename GET_PROP_TYPE(TypeTag, Problem); + using Problem = GetPropType; auto problem = std::make_shared(fvGridGeometry); // the solution vector - using SolutionVector = typename GET_PROP_TYPE(TypeTag, SolutionVector); + using SolutionVector = GetPropType; SolutionVector x(fvGridGeometry->numDofs()); problem->applyInitialSolution(x); auto xOld = x; @@ -102,19 +102,19 @@ int main(int argc, char** argv) try problem->spatialParams().computeReferencePermeability(*fvGridGeometry, x); // the grid variables - using GridVariables = typename GET_PROP_TYPE(TypeTag, GridVariables); + using GridVariables = GetPropType; auto gridVariables = std::make_shared(problem, fvGridGeometry); gridVariables->init(x, xOld); // get some time loop parameters - using Scalar = typename GET_PROP_TYPE(TypeTag, Scalar); + using Scalar = GetPropType; const auto tEnd = getParam("TimeLoop.TEnd"); const auto maxDt = getParam("TimeLoop.MaxTimeStepSize"); auto dt = getParam("TimeLoop.DtInitial"); // initialize the vtk output module - using VtkOutputFields = typename GET_PROP_TYPE(TypeTag, VtkOutputFields); - VtkOutputModule vtkWriter(*problem, *fvGridGeometry, *gridVariables, x, problem->name()); + using VtkOutputFields = GetPropType; + VtkOutputModule vtkWriter(*gridVariables, x, problem->name()); VtkOutputFields::init(vtkWriter); //!< Add model specific output fields //add specific output vtkWriter.addField(problem->getKxx(), "Kxx"); @@ -137,8 +137,7 @@ int main(int argc, char** argv) try auto linearSolver = std::make_shared(leafGridView, fvGridGeometry->dofMapper()); // the non-linear solver - using NewtonSolver = PriVarSwitchNewtonSolver; + using NewtonSolver = NewtonSolver; NewtonSolver nonLinearSolver(assembler, linearSolver); // time loop diff --git a/exercises/exercise-biomineralization/exercisebiomin.input b/exercises/exercise-biomineralization/exercisebiomin.input index 6d57216..0f3d3e4 100644 --- a/exercises/exercise-biomineralization/exercisebiomin.input +++ b/exercises/exercise-biomineralization/exercisebiomin.input @@ -37,3 +37,6 @@ RhoBiofilm = 6.9 # [kg/m³] density of biofilm Kub = 8.81e-3 # [kg_urease/kg_bio] (max: 0.01) Kurease = 1000 # [mol_urea/(kg_urease s)] Ku = 0.355 # [mol/kgH2O] Lauchnor et al. 2014 + +[Brine] +Salinity = 0.1 diff --git a/exercises/exercise-biomineralization/fluidsystems/biomin.hh b/exercises/exercise-biomineralization/fluidsystems/biomin.hh index 6f4be1e..617bf8b 100644 --- a/exercises/exercise-biomineralization/fluidsystems/biomin.hh +++ b/exercises/exercise-biomineralization/fluidsystems/biomin.hh @@ -61,13 +61,13 @@ namespace FluidSystems { */ template > > + class H2OType = Dumux::Components::TabulatedComponent> > class BioMin -: public BaseFluidSystem > +: public Base > { using ThisType = BioMin; - using Base = BaseFluidSystem ; + using Base = Dumux::FluidSystems::Base; using Brine_CO2 = BinaryCoeff::Brine_CO2; using IdealGas = Dumux::IdealGas; @@ -333,8 +333,8 @@ public: if (phaseIdx == liquidPhaseIdx) { // assume brine with viscosity effect of Ca for the liquid phase. - Scalar salinity = fluidState.massFraction(liquidPhaseIdx, CaIdx); - Scalar result = Brine::liquidViscosity(temperature, pressure, salinity); + //F Scalar salinity = fluidState.massFraction(liquidPhaseIdx, CaIdx); + Scalar result = Brine::liquidViscosity(temperature, pressure); Valgrind::CheckDefined(result); return result; @@ -388,7 +388,7 @@ public: Scalar temperature = fluidState.temperature(phaseIdx); Scalar pressure = fluidState.pressure(phaseIdx); - Scalar salinity = 0.1; //TODO major assumption in favor of runtime! + Scalar salinity = Brine::salinity(); // 0.1; //TODO major assumption in favor of runtime! //function is actually designed for use with NaCl not Ca. //Theoretically it should be: fluidState.massFraction(liquidPhaseIdx, CaIdx); @@ -546,7 +546,7 @@ private: "defined below 250MPa (is" << pl << ")"); } - Scalar rho_brine = Brine::liquidDensity(T, pl, XlSal); + Scalar rho_brine = Brine::liquidDensity(T, pl); Scalar rho_pure = H2O::liquidDensity(T, pl); Scalar rho_lCO2 = liquidDensityWaterCO2_(T, pl, xwH2O, xwCO2); Scalar contribCO2 = rho_lCO2 - rho_pure; diff --git a/exercises/extradoc/exercisebiomin_injectionFinal.png b/exercises/extradoc/exercisebiomin_injectionFinal.png index aa81d2555618d5cc598e3436122a7161848a5da2..a07d51c6ad44175699639c7c01459bee15871dde 100644 GIT binary patch literal 29636 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%0Ddl>SY4fOVY~WKVG&@4rmH7laiAc@Cf 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 #include "fluidsystems/biomin.hh" // The biomineralization fluid system -#include "chemistry/simplebiominreactions.hh" // chemical reactions +// TODO: dumux-course-task +// include chemistry file here +#include "chemistry/simplebiominreactions.hh" // chemical reactions #include "biominspatialparams.hh" // Spatially dependent parameters namespace Dumux { @@ -50,42 +52,54 @@ class ExerciseFourBioMinProblem; namespace Properties { //! Create new type tag for the problem -NEW_TYPE_TAG(ExerciseFourBioMinTypeTag, INHERITS_FROM(TwoPNCMin, BioMinSpatialparams)); -NEW_TYPE_TAG(ExerciseFourBioMinCCTpfaTypeTag, INHERITS_FROM(CCTpfaModel, ExerciseFourBioMinTypeTag)); +// Create new type tags +namespace TTag { +struct ExerciseFourBioMinTypeTag { using InheritsFrom = std::tuple; }; +struct ExerciseFourBioMinCCTpfaTypeTag { using InheritsFrom = std::tuple; }; +} // end namespace TTag //! Set the problem property -SET_TYPE_PROP(ExerciseFourBioMinTypeTag, Problem, ExerciseFourBioMinProblem); +template +struct Problem { using type = ExerciseFourBioMinProblem; }; //! Set grid and the grid creator to be used #if HAVE_DUNE_ALUGRID -SET_TYPE_PROP(ExerciseFourBioMinTypeTag, Grid, Dune::ALUGrid); +template +struct Grid { using type = Dune::ALUGrid; }; #elif HAVE_UG -SET_TYPE_PROP(ExerciseFourBioMinTypeTag, Grid, Dune::UGGrid<2>); +template +struct Grid { using type = Dune::UGGrid<2>; }; #else -SET_TYPE_PROP(ExerciseFourBioMinTypeTag, Grid, Dune::YaspGrid<2>); +template +struct Grid { using type = Dune::YaspGrid<2>; }; #endif // HAVE_DUNE_ALUGRID //! Set the fluid system type -SET_PROP(ExerciseFourBioMinTypeTag, FluidSystem) +template +struct FluidSystem { private: - using Scalar = typename GET_PROP_TYPE(TypeTag, Scalar); + using Scalar = GetPropType; using CO2Tables = Dumux::CO2Tables; using H2OType = Components::TabulatedComponent>; public: using type = FluidSystems::BioMin; }; -SET_PROP(ExerciseFourBioMinTypeTag, SolidSystem) +template +struct SolidSystem { - using Scalar = typename GET_PROP_TYPE(TypeTag, Scalar); + using Scalar = GetPropType; using type = SolidSystems::BiominSolidPhase; }; -SET_BOOL_PROP(ExerciseFourBioMinTypeTag, EnableFVGridGeometryCache, false); -SET_BOOL_PROP(ExerciseFourBioMinTypeTag, EnableGridVolumeVariablesCache, false); -SET_BOOL_PROP(ExerciseFourBioMinTypeTag, EnableGridFluxVariablesCache, false); +template +struct EnableFVGridGeometryCache { static constexpr bool value = false; }; +template +struct EnableGridVolumeVariablesCache { static constexpr bool value = false; }; +template +struct EnableGridFluxVariablesCache { static constexpr bool value = false; }; } // end namespace properties /*! @@ -97,16 +111,16 @@ class ExerciseFourBioMinProblem : public PorousMediumFlowProblem { using ParentType = PorousMediumFlowProblem; - using GridView = typename GET_PROP_TYPE(TypeTag, GridView); - using Scalar = typename GET_PROP_TYPE(TypeTag, Scalar); - using FluidSystem = typename GET_PROP_TYPE(TypeTag, FluidSystem); - using SolidSystem = typename GET_PROP_TYPE(TypeTag, SolidSystem); - using Indices = typename GET_PROP_TYPE(TypeTag, ModelTraits)::Indices; - using PrimaryVariables = typename GET_PROP_TYPE(TypeTag, PrimaryVariables); - using BoundaryTypes = typename GET_PROP_TYPE(TypeTag, BoundaryTypes); - using VolumeVariables = typename GET_PROP_TYPE(TypeTag, VolumeVariables); - using FVGridGeometry = typename GET_PROP_TYPE(TypeTag, FVGridGeometry); - using FVElementGeometry = typename GET_PROP_TYPE(TypeTag, FVGridGeometry)::LocalView; + using GridView = GetPropType; + using Scalar = GetPropType; + using FluidSystem = GetPropType; + using SolidSystem = GetPropType; + using Indices = typename GetPropType::Indices; + using PrimaryVariables = GetPropType; + using BoundaryTypes = GetPropType; + using VolumeVariables = GetPropType; + using FVGridGeometry = GetPropType; + using FVElementGeometry = typename GetPropType::LocalView; // Grid dimension enum @@ -116,11 +130,13 @@ class ExerciseFourBioMinProblem : public PorousMediumFlowProblem }; using GlobalPosition = Dune::FieldVector; - using NumEqVector = typename GET_PROP_TYPE(TypeTag, NumEqVector); - using ElementVolumeVariables = typename GET_PROP_TYPE(TypeTag, GridVolumeVariables)::LocalView; + using NumEqVector = GetPropType; + using ElementVolumeVariables = typename GetPropType::LocalView; using Element = typename GridView::template Codim<0>::Entity; - using SolutionVector = typename GET_PROP_TYPE(TypeTag, SolutionVector); + using SolutionVector = GetPropType; using SubControlVolume = typename FVElementGeometry::SubControlVolume; + // TODO: dumux-course-task + // set the chemistry TypeTag using Chemistry = typename Dumux::SimpleBiominReactions; enum @@ -171,7 +187,7 @@ public: concCa_ = getParam("Injection.ConcCa"); concUrea_ = getParam("Injection.ConcUrea"); - unsigned int codim = GET_PROP_TYPE(TypeTag, FVGridGeometry)::discMethod == DiscretizationMethod::box ? dim : 0; + unsigned int codim = GetPropType::discMethod == DiscretizationMethod::box ? dim : 0; Kxx_.resize(fvGridGeometry->gridView().size(codim)); Kyy_.resize(fvGridGeometry->gridView().size(codim)); @@ -279,6 +295,7 @@ public: values[conti0EqIdx + CaIdx] = - waterFlux * concCa_ / FluidSystem::molarMass(CaIdx); values[conti0EqIdx + UreaIdx] = - waterFlux * concUrea_ / FluidSystem::molarMass(UreaIdx); } + // TODO: dumux-course-task // Set CO2 injection below aquitard after the injBioTime else if(globalPos[0] < eps_ && globalPos[1] > 2.0 + eps_ @@ -351,6 +368,10 @@ public: { NumEqVector source(0.0); + // TODO: dumux-course-task + // set Chemistry + // set VolumeVariables + // call reactionSource() in chemistry Chemistry chemistry; const auto& volVars = elemVolVars[scv]; chemistry.reactionSource(source, volVars); @@ -412,6 +433,6 @@ private: Scalar time_; }; -} //end namespace Dumux +} //end namespace #endif diff --git a/exercises/solution/exercise-biomineralization/biominspatialparams.hh b/exercises/solution/exercise-biomineralization/biominspatialparams.hh new file mode 100644 index 0000000..12be491 --- /dev/null +++ b/exercises/solution/exercise-biomineralization/biominspatialparams.hh @@ -0,0 +1,354 @@ +// -*- 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 . * + *****************************************************************************/ +/*! + * \file + * \brief Spatial parameters for the bio mineralization problem where urea is used to + * precipitate calcite. + */ +#ifndef DUMUX_BIOMIN_SPATIAL_PARAMETERS_HH +#define DUMUX_BIOMIN_SPATIAL_PARAMETERS_HH + +#include +#include +#include +#include +#include +#include + +#include + +namespace Dumux +{ +//forward declaration +template +class BioMinSpatialparams; + +namespace Properties +{ +// The spatial parameters TypeTag +NEW_TYPE_TAG(BioMinSpatialparams); + +// Set the spatial parameters +template +struct SpatialParams { using type = BioMinSpatialparams; }; +} // end namespace Properties + +/*! + * \brief Definition of the spatial parameters for the biomineralisation problem + * with geostatistically distributed initial permeability. + */ +template +class BioMinSpatialparams +: public FVSpatialParams, + GetPropType, + BioMinSpatialparams> +{ + using Scalar = GetPropType; + using FVGridGeometry = GetPropType; + using FVElementGeometry = typename FVGridGeometry::LocalView; + using SubControlVolume = typename FVElementGeometry::SubControlVolume; + using ParentType = FVSpatialParams>; + using EffectiveLaw = RegularizedBrooksCorey; + using SolutionVector = GetPropType; + + using GridView = typename FVGridGeometry::GridView; + using CoordScalar = typename GridView::ctype; + enum { dimWorld=GridView::dimensionworld }; + using Element = typename GridView::template Codim<0>::Entity; + + using GlobalPosition = Dune::FieldVector; + using Tensor = Dune::FieldMatrix; + +public: + using SolidSystem = GetPropType; + using PermeabilityType = Tensor; + using MaterialLaw = EffToAbsLaw; + using MaterialLawParams = typename MaterialLaw::Params; + + /*! + * \brief The constructor + * + * \param gridView The grid view + */ + BioMinSpatialparams(std::shared_ptr fvGridGeometry) + : ParentType(fvGridGeometry) + { + //! set initial aquifer params + initialPorosity_ = getParam("SpatialParams.InitialPorosity"); + initialPermeability_ = getParam("SpatialParams.InitialPermeability"); + + // set main diagonal entries of the permeability tensor to a value + // setting to one value means: isotropic, homogeneous + + // residual saturations + materialParams_.setSwr(0.2); + materialParams_.setSnr(0.05); + + // parameters for the Brooks-Corey law + materialParams_.setPe(1e4); + materialParams_.setLambda(2.0); + + //! hard code specific params for aquitard layer + aquitardPorosity_ = 0.1; + aquitardPermeability_ = 1e-15; + + // residual saturations + aquitardMaterialParams_.setSwr(0.0); + aquitardMaterialParams_.setSnr(0.0); + + // parameters for the Brooks-Corey law + aquitardMaterialParams_.setPe(1e7); + aquitardMaterialParams_.setLambda(2.0); + } + + template + Scalar inertVolumeFraction(const Element& element, + const SubControlVolume& scv, + const ElementSolution& elemSol, + int compIdx) const + { + return 1-referencePorosity(element, scv); + } + + /*! + * \brief Define the initial porosity \f$[-]\f$ distribution + * For this special case, the initialPorosity is precalculated value + * as a referencePorosity due to an initial volume fraction of biofilm. + * + * \param element The finite element + * \param scv The sub-control volume + */ + Scalar referencePorosity(const Element& element, + const SubControlVolume &scv) const + { + const auto eIdx = this->fvGridGeometry().elementMapper().index(element); + return referencePorosity_[eIdx][scv.indexInElement()]; + } + + /*! + * \brief Compute the reference porosity which is needed to set the correct initialPorosity. + * This value calculates the correct porosity that needs to be set + * in for the initialPorosity when an initial volume fraction of + * biofilm or other precipitate is in the system. + * This function makes use of evaluatePorosity from the porosityprecipitation law. + * The reference porosity is calculated as: + * \f[referencePorosity = initialPorosity + \sum \phi \f] + * which in making use of already available functions is + * + * \f[referencePorosity = 2 \cdot initialPorosity - evaluatePorosity() \f] + * + * \param fvGridGeometry The fvGridGeometry + * \param sol The (initial) solution vector + */ + void computeReferencePorosity(const FVGridGeometry& fvGridGeometry, + const SolutionVector& sol) + { + referencePorosity_.resize(fvGridGeometry.gridView().size(0)); + for (const auto& element : elements(fvGridGeometry.gridView())) + { + auto fvGeometry = localView(fvGridGeometry); + fvGeometry.bindElement(element); + + const auto eIdx = this->fvGridGeometry().elementMapper().index(element); + + auto elemSol = elementSolution(element, sol, fvGridGeometry); + referencePorosity_[eIdx].resize(fvGeometry.numScv()); + for (const auto& scv : scvs(fvGeometry)) + { + const auto& dofPosition = scv.dofPosition(); + const bool isInAquitardNotFaultZone = isInAquitard_(dofPosition) && !isFaultZone_(dofPosition); + auto phi = isInAquitardNotFaultZone ? aquitardPorosity_ : initialPorosity_; + auto phiEvaluated = poroLaw_.evaluatePorosity(element, scv, elemSol, phi); + referencePorosity_[eIdx][scv.indexInElement()] = calculatephiRef(phi, phiEvaluated); + } + } + } + + /*! + * \brief Return the actual recent porosity \f$[-]\f$ accounting for + * clogging caused by mineralization. + * + * \param element The finite element + * \param scv The sub-control volume + */ + template + Scalar porosity(const Element& element, + const SubControlVolume& scv, + const ElementSolution& elemSol) const + { + const auto refPoro = referencePorosity(element, scv); + return poroLaw_.evaluatePorosity(element, scv, elemSol, refPoro); + } + + /*! + * \brief Define the reference permeability \f$[m^2]\f$ distribution + * + * \param element The finite element + * \param scv The sub-control volume + */ + PermeabilityType referencePermeability(const Element& element, + const SubControlVolume &scv) const + { + const auto eIdx = this->fvGridGeometry().elementMapper().index(element); + return referencePermeability_[eIdx][scv.indexInElement()]; + } + + /*! + * \brief Compute the reference permeability which depends on the porosity. + * This value calculates the correct permeability that needs to be set + * for the initialPermeability when an initial volume fraction of + * biofilm or other precipitate is in the system. + * This function makes use of evaluatePermeability function + * from the Kozeny-Carman permeability law. + * The reference permeability is calculated as: + * \f[referencePorosity = initialPermeability + * \cdot f(refPoro / initPoro) - evaluatePermeability \cdot f(refPoro/initPoro) \f] + * which in making use of already available functions is + * + * \f[referencePermeability = initialPermeability^2 / evaluatePermeability() \f] + * + * \param fvGridGeometry The fvGridGeometry + * \param sol The (initial) solution vector + */ + void computeReferencePermeability(const FVGridGeometry& fvGridGeometry, + const SolutionVector& sol) + { + referencePermeability_.resize(fvGridGeometry.gridView().size(0)); + for (const auto& element : elements(fvGridGeometry.gridView())) + { + auto fvGeometry = localView(fvGridGeometry); + fvGeometry.bindElement(element); + + const auto eIdx = this->fvGridGeometry().elementMapper().index(element); + + auto elemSol = elementSolution(element, sol, fvGridGeometry); + referencePermeability_[eIdx].resize(fvGeometry.numScv()); + for (const auto& scv : scvs(fvGeometry)) + { + const auto& dofPosition = scv.dofPosition(); + const bool isInAquitardNotFaultZone = isInAquitard_(dofPosition) && !isFaultZone_(dofPosition); + auto kInit = isInAquitardNotFaultZone ? aquitardPermeability_ : initialPermeability_; + const auto refPoro = referencePorosity(element, scv); + const auto poro = porosity(element, scv, elemSol); + auto kEvaluated = permLaw_.evaluatePermeability(kInit, refPoro, poro); + referencePermeability_[eIdx][scv.indexInElement()] = calculateKRef(kInit, kEvaluated); + } + } + } + + /*! Intrinsic permeability tensor K \f$[m^2]\f$ depending + * on the position in the domain + * + * \param element The finite volume element + * \param scv The sub-control volume + * + * Solution dependent permeability function. + */ + template + PermeabilityType permeability(const Element& element, + const SubControlVolume& scv, + const ElementSolution& elemSol) const + { + const auto refPerm = referencePermeability(element, scv); + const auto refPoro = referencePorosity(element, scv); + const auto poro = porosity(element, scv, elemSol); + return permLaw_.evaluatePermeability(refPerm, refPoro, poro); + } + + /*! + * \brief return the parameter object for the Brooks-Corey material law which depends on the position + * + * \param globalPos The global position + */ + const MaterialLawParams& materialLawParamsAtPos(const GlobalPosition& globalPos) const + { + if (isInAquitard_(globalPos) && !isFaultZone_(globalPos)) + return aquitardMaterialParams_; + else + return materialParams_; + } + + // define which phase is to be considered as the wetting phase + template + int wettingPhaseAtPos(const GlobalPosition& globalPos) const + { return FluidSystem::liquidPhaseIdx; } + +private: + + static constexpr Scalar eps_ = 1e-6; + + //! calculateKRef for tensorial permeabilities + PermeabilityType calculateKRef(PermeabilityType K, PermeabilityType kEvaluated) + { + //TODO this assumes the change in permeability is homogeneous as currently also assumed in PermeabilityKozenyCarman. + // there also might be nicer/safer ways to calculate this. + Scalar factor = 0.0; + int counter = 0; + for (int i = 0; i < dimWorld; ++i) + for (int j = 0; i < dimWorld; ++i) + if(kEvaluated[i][j]!=0) + { + factor += K[i][j] / kEvaluated[i][j]; + ++counter; + } + factor /= counter; + K *= factor; + + return K; + } + + //! calculateKRef for scalar permeabilities + template::value, int> = 0> + PermeabilityType calculateKRef(PermeabilityType K, PermeabilityType kEvaluated) + { + Scalar factor = K / kEvaluated; + K *= factor; + return K; + } + + Scalar calculatephiRef(Scalar phiInit, Scalar phiEvaluated) + { return 2*phiInit - phiEvaluated;} + + bool isInAquitard_(const GlobalPosition &globalPos) const + { return globalPos[dimWorld-1] > 8 - eps_ && globalPos[dimWorld-1] < 10 + eps_;} + + bool isFaultZone_(const GlobalPosition &globalPos) const + { return globalPos[dimWorld-2] > 2 - eps_ && globalPos[dimWorld-2] < 3 + eps_;} + + using ModelTraits = GetPropType; + PorosityPrecipitation poroLaw_; + PermeabilityKozenyCarman permLaw_; + + + Scalar initialPorosity_; + std::vector< std::vector > referencePorosity_; + Scalar initialPermeability_; + std::vector< std::vector > referencePermeability_; + + MaterialLawParams materialParams_; + + Scalar aquitardPorosity_; + Scalar aquitardPermeability_; + MaterialLawParams aquitardMaterialParams_; +}; + +} // end namespace Dumux + +#endif diff --git a/exercises/solution/exercise-biomineralization/simplebiominreactions.hh b/exercises/solution/exercise-biomineralization/chemistry/simplebiominreactions.hh similarity index 88% rename from exercises/solution/exercise-biomineralization/simplebiominreactions.hh rename to exercises/solution/exercise-biomineralization/chemistry/simplebiominreactions.hh index 6d14d12..02eec51 100644 --- a/exercises/solution/exercise-biomineralization/simplebiominreactions.hh +++ b/exercises/solution/exercise-biomineralization/chemistry/simplebiominreactions.hh @@ -19,8 +19,7 @@ /*! * \file * \ingroup Chemistry - * \brief The source and sink terms due to reactions are calculated in this class. The chemical functions and derivations are implemented in the private part of - * class. + * \brief The source and sink terms due to reactions are calculated in this class. */ #ifndef DUMUX_BIOMIN_REACTIONS_HH #define DUMUX_BIOMIN_REACTIONS_HH @@ -29,18 +28,17 @@ namespace Dumux { /*! * \ingroup Chemistry - * \brief The source and sink terms due to reactions are calculated in this class. The chemical functions and derivations are implemented in the private part of - * class. + * \brief The source and sink terms due to reactions are calculated in this class. */ template class SimpleBiominReactions { - using Scalar = typename GET_PROP_TYPE(TypeTag, Scalar); - using FluidSystem = typename GET_PROP_TYPE(TypeTag, FluidSystem); - using SolidSystem = typename GET_PROP_TYPE(TypeTag, SolidSystem); - using VolumeVariables = typename GET_PROP_TYPE(TypeTag, VolumeVariables); + using Scalar = GetPropType; + using FluidSystem = GetPropType; + using SolidSystem = GetPropType; + using VolumeVariables = GetPropType; using ThisType = SimpleBiominReactions; - using Sources = typename GET_PROP_TYPE(TypeTag, NumEqVector); + using Sources = GetPropType; public: @@ -93,6 +91,9 @@ public: if (volFracBiofilm < 0) volFracBiofilm = 0; + + // TODO: dumux-course-task + // implement mass of biofilm Scalar massBiofilm = densityBiofilm * volFracBiofilm; Scalar molalityUrea = moleFracToMolality(volVars.moleFraction(liquidPhaseIdx,UreaIdx), @@ -101,7 +102,8 @@ public: if (molalityUrea < 0) molalityUrea = 0; - // compute rate of ureolysis: + // TODO: dumux-course-task + // compute rate of ureolysis by implementing Z_urease,biofilm and r_urea Scalar Zub = kub_ * massBiofilm; // [kg urease/m³] Scalar rurea = kurease_ * Zub * molalityUrea / (ku_ + molalityUrea); // [mol/m³s] @@ -113,6 +115,8 @@ public: rprec = rurea; // set source terms + // TODO: dumux-course-task + // update terms according to stochiometry q[H2OIdx] += 0; q[CO2Idx] += rurea - rprec ; q[CaIdx] += - rprec; @@ -120,6 +124,7 @@ public: q[BiofilmIdx] += 0; q[CalciteIdx] += rprec; } + private: // urease parameters diff --git a/exercises/solution/exercise-biomineralization/components/biofilm.hh b/exercises/solution/exercise-biomineralization/components/biofilm.hh new file mode 100644 index 0000000..c3348a0 --- /dev/null +++ b/exercises/solution/exercise-biomineralization/components/biofilm.hh @@ -0,0 +1,77 @@ +// -*- 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 . * + *****************************************************************************/ +/*! + * \file + * \ingroup Components + * \brief A class for the biofilm solid component properties. + */ +#ifndef DUMUX_BIOFILM_HH +#define DUMUX_BIOFILM_HH + +#include +#include + +namespace Dumux { +namespace Components { + +/*! + * \ingroup Components + * \brief A class for the biofilm solid component properties. + */ +template +class Biofilm +: public Components::Base > +, public Components::Solid > +{ +public: + /*! + * \brief A human readable name for the biofilm. + */ + static std::string name() + { return "Biofilm"; } + + /*! + * \brief The molar mass in \f$\mathrm{[kg/mol]}\f$ of molecular biofilm. + * This can be set in the input file, as the correct molar mass of a biofilm is hard to define and + * any choice is arbitrary. Based on a cell mass of 2.5e-16 kg, the molar mass of "cells" would + * be 1.5e8 kg/mol, but biofilms are more than just cells ... + */ + static Scalar molarMass() + { + Scalar molarMass = getParam("BioCoefficients.BiofilmMolarMass", 1); + return molarMass; + } + + /*! + * \brief The (dry) density \f$\mathrm{[kg/m^3]}\f$ of biofilm. + * This is set in the input file, as biofilm densities vary over orders of magnitude. + * A value of "10" is fitted by Ebigbo 2012 WRR + * Hommel 2015 WRR uses "6.9". + */ + static Scalar solidDensity(Scalar temperature) + { + Scalar rho = getParam("BioCoefficients.RhoBiofilm", 10); + return rho; + } +}; + +} // end namespace Components +} // end namespace Dumux + +#endif diff --git a/exercises/solution/exercise-biomineralization/components/urea.hh b/exercises/solution/exercise-biomineralization/components/urea.hh new file mode 100644 index 0000000..1dc5330 --- /dev/null +++ b/exercises/solution/exercise-biomineralization/components/urea.hh @@ -0,0 +1,58 @@ +// -*- 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 . * + *****************************************************************************/ +/*! + * \file + * \ingroup Components + * \brief A class for the urea component properties. + */ +#ifndef DUMUX_UREA_HH +#define DUMUX_UREA_HH + +#include + +namespace Dumux { +namespace Components { + +/*! + * \ingroup Components + * \brief A class for the urea properties + */ +template +class Urea +: public Components::Base > +{ +public: + /*! + * \brief A human readable name for the urea. + */ + static std::string name() + { return "urea"; } + + /*! + * \brief The molar mass in \f$\mathrm{[kg/mol]}\f$ of urea. + */ + static constexpr Scalar molarMass() + { return 0.0606; } // kg/mol + +}; + +} // end namespace Components +} // end namespace Dumux + +#endif diff --git a/exercises/solution/exercise-biomineralization/exercisebiomin.cc b/exercises/solution/exercise-biomineralization/exercisebiomin.cc new file mode 100644 index 0000000..a4cbddf --- /dev/null +++ b/exercises/solution/exercise-biomineralization/exercisebiomin.cc @@ -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: +/***************************************************************************** + * 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 . * + *****************************************************************************/ +/*! + * \file + * + * \brief Exercise for the two-phase n-component bio mineralization CC model. + */ +#include + +#include +#include + +#include +#include +#include +#include +#include + +#include +#include +#include +#include +#include + +#include +#include + +#include +#include + +#include + +#include +#include + +#include "biominproblem.hh" + +//////////////////////// +// the main function +//////////////////////// +int main(int argc, char** argv) try +{ + using namespace Dumux; + + // define the type tag for this problem + using TypeTag = Properties::TTag::ExerciseFourBioMinCCTpfaTypeTag; + + // initialize MPI, finalize is done automatically on exit + const auto& mpiHelper = Dune::MPIHelper::instance(argc, argv); + + // print dumux start message + if (mpiHelper.rank() == 0) + DumuxMessage::print(/*firstCall=*/true); + + // parse command line arguments and input file + Parameters::init(argc, argv); + + // try to create a grid (from the given grid file or the input file) + GridManager> gridManager; + gridManager.init(); + + //////////////////////////////////////////////////////////// + // run instationary non-linear problem on this grid + //////////////////////////////////////////////////////////// + + // we compute on the leaf grid view + const auto& leafGridView = gridManager.grid().leafGridView(); + + // create the finite volume grid geometry + using FVGridGeometry = GetPropType; + auto fvGridGeometry = std::make_shared(leafGridView); + fvGridGeometry->update(); + + // the problem (initial and boundary conditions) + using Problem = GetPropType; + auto problem = std::make_shared(fvGridGeometry); + + // the solution vector + using SolutionVector = GetPropType; + SolutionVector x(fvGridGeometry->numDofs()); + problem->applyInitialSolution(x); + auto xOld = x; + + // initialize the spatialParams separately to compute the referencePorosity and referencePermeability + problem->spatialParams().computeReferencePorosity(*fvGridGeometry, x); + problem->spatialParams().computeReferencePermeability(*fvGridGeometry, x); + + // the grid variables + using GridVariables = GetPropType; + auto gridVariables = std::make_shared(problem, fvGridGeometry); + gridVariables->init(x, xOld); + + // get some time loop parameters + using Scalar = GetPropType; + const auto tEnd = getParam("TimeLoop.TEnd"); + const auto maxDt = getParam("TimeLoop.MaxTimeStepSize"); + auto dt = getParam("TimeLoop.DtInitial"); + + // initialize the vtk output module + using VtkOutputFields = GetPropType; + VtkOutputModule vtkWriter(*gridVariables, x, problem->name()); + VtkOutputFields::init(vtkWriter); //!< Add model specific output fields + //add specific output + vtkWriter.addField(problem->getKxx(), "Kxx"); + vtkWriter.addField(problem->getKyy(), "Kyy"); + // update the output fields before write + problem->updateVtkOutput(x); + vtkWriter.write(0.0); + + // instantiate time loop + auto timeLoop = std::make_shared>(0.0, dt, tEnd); + const auto injBioTime = getParam("Injection.InjBioTime")*86400; + const auto maxDtCO2 = getParam("TimeLoop.MaxTimeStepSizeCO2"); + + // the assembler with time loop for instationary problem + using Assembler = FVAssembler; + auto assembler = std::make_shared(problem, fvGridGeometry, gridVariables, timeLoop); + + // the linear solver + using LinearSolver = AMGBackend; + auto linearSolver = std::make_shared(leafGridView, fvGridGeometry->dofMapper()); + + // the non-linear solver + using NewtonSolver = NewtonSolver; + NewtonSolver nonLinearSolver(assembler, linearSolver); + + // time loop + timeLoop->start(); do + { + // set previous solution for storage evaluations + assembler->setPreviousSolution(xOld); + + // solve the non-linear system with time step control + nonLinearSolver.solve(x, *timeLoop); + + //reset MaxTimeStepSize for CO2 Injection + bool injCO2 = injBioTime < timeLoop->time() + timeLoop->timeStepSize(); + timeLoop->setMaxTimeStepSize( injCO2 ? maxDtCO2 : maxDt); + + //set time in problem (is used in time-dependent Neumann boundary condition) + problem->setTime(timeLoop->time()+timeLoop->timeStepSize()); + + // make the new solution the old solution + xOld = x; + gridVariables->advanceTimeStep(); + + // advance to the time loop to the next step + timeLoop->advanceTimeStep(); + + // update the output fields before write + problem->updateVtkOutput(x); + + // write vtk output + if (timeLoop->timeStepIndex()==0 || injCO2 == false || timeLoop->timeStepIndex() || timeLoop->willBeFinished()) + vtkWriter.write(timeLoop->time()); + + // report statistics of this time step + timeLoop->reportTimeStep(); + + // set new dt as suggested by newton controller + timeLoop->setTimeStepSize(nonLinearSolver.suggestTimeStepSize(timeLoop->timeStepSize())); + + } while (!timeLoop->finished()); + + timeLoop->finalize(leafGridView.comm()); + + //////////////////////////////////////////////////////////// + // finalize, print dumux message to say goodbye + //////////////////////////////////////////////////////////// + + // print dumux end message + if (mpiHelper.rank() == 0) + { + Parameters::print(); + DumuxMessage::print(/*firstCall=*/false); + } + + return 0; +} // end main +catch (Dumux::ParameterException &e) +{ + std::cerr << std::endl << e << " ---> Abort!" << std::endl; + return 1; +} +catch (Dune::DGFException & e) +{ + std::cerr << "DGF exception thrown (" << e << + "). Most likely, the DGF file name is wrong " + "or the DGF file is corrupted, " + "e.g. missing hash at end of file or wrong number (dimensions) of entries." + << " ---> Abort!" << std::endl; + return 2; +} +catch (Dune::Exception &e) +{ + std::cerr << "Dune reported error: " << e << " ---> Abort!" << std::endl; + return 3; +} +catch (...) +{ + std::cerr << "Unknown exception thrown! ---> Abort!" << std::endl; + return 4; +} diff --git a/exercises/solution/exercise-biomineralization/exercisebiomin.input b/exercises/solution/exercise-biomineralization/exercisebiomin_solution.input similarity index 97% rename from exercises/solution/exercise-biomineralization/exercisebiomin.input rename to exercises/solution/exercise-biomineralization/exercisebiomin_solution.input index 6d57216..0f3d3e4 100644 --- a/exercises/solution/exercise-biomineralization/exercisebiomin.input +++ b/exercises/solution/exercise-biomineralization/exercisebiomin_solution.input @@ -37,3 +37,6 @@ RhoBiofilm = 6.9 # [kg/m³] density of biofilm Kub = 8.81e-3 # [kg_urease/kg_bio] (max: 0.01) Kurease = 1000 # [mol_urea/(kg_urease s)] Ku = 0.355 # [mol/kgH2O] Lauchnor et al. 2014 + +[Brine] +Salinity = 0.1 diff --git a/exercises/solution/exercise-biomineralization/fluidsystems/biomin.hh b/exercises/solution/exercise-biomineralization/fluidsystems/biomin.hh new file mode 100644 index 0000000..617bf8b --- /dev/null +++ b/exercises/solution/exercise-biomineralization/fluidsystems/biomin.hh @@ -0,0 +1,583 @@ +// -*- 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 . * + *****************************************************************************/ +/*! + * \file + * \ingroup Fluidsystems + * \brief A fluid system with water and gas as phases and brine and CO2 + * as components. + */ +#ifndef DUMUX_BIOMIN_FLUID_SYSTEM_HH +#define DUMUX_BIOMIN_FLUID_SYSTEM_HH + +#include +#include +#include + +#include +#include +#include +#include + +#include +#include "../components/urea.hh" + +#include + +namespace Dumux { +namespace FluidSystems { + +/*! + * \ingroup Fluidsystems + * \brief A compositional fluid with brine and carbon dioxide as + * components in both, the liquid and the gas (supercritical) phase, + * additional biomineralisation components (Ca and Urea) in the liquid phase + * + * This class provides acess to the Bio fluid system when no property system is used. + * For Dumux users, using BioMinFluid and the documentation therein is + * recommended. + * + * The user can provide their own material table for co2 properties. + * This fluidsystem is initialized as default with the tabulated version of + * water of the IAPWS-formulation, and the tabularized adapter to transfer + * this into brine. + * In the non-TypeTagged version, salinity information has to be provided with + * the init() methods. + */ +template > > +class BioMin +: public Base > +{ + + using ThisType = BioMin; + using Base = Dumux::FluidSystems::Base; + using Brine_CO2 = BinaryCoeff::Brine_CO2; + + using IdealGas = Dumux::IdealGas; + +public: + using CO2 = Components::CO2; + using H2O = H2OType; + using Ca = Components::CalciumIon; + using Urea = Components::Urea; + using Brine = Components::Brine; + + // the type of parameter cache objects. this fluid system does not + // cache anything, so it uses Dumux::NullParameterCache + using ParameterCache = Dumux::NullParameterCache; + + /**************************************** + * Fluid phase related static parameters + ****************************************/ + static constexpr int numPhases = 2; // liquid and gas phases + static constexpr int liquidPhaseIdx = 0; // index of the liquid phase + static constexpr int gasPhaseIdx = 1; // index of the gas phase + + static constexpr int phase0Idx = liquidPhaseIdx; // index of the first phase + static constexpr int phase1Idx = gasPhaseIdx; // index of the second phase + /*! + * \brief Return the human readable name of a fluid phase + * + * \param phaseIdx The index of the fluid phase to consider + */ + static std::string phaseName(int phaseIdx) + { + static std::string name[] = + { + "liquid", + "gas" + }; + + assert(0 <= phaseIdx && phaseIdx < numPhases); + return name[phaseIdx]; + } + + /*! + * \brief Returns whether the fluids are miscible + */ + static constexpr bool isMiscible() + { return true; } + + /*! + * \brief Return whether a phase is liquid + * + * \param phaseIdx The index of the fluid phase to consider + */ + static constexpr bool isLiquid(int phaseIdx) + { + assert(0 <= phaseIdx && phaseIdx < numPhases); + return phaseIdx != gasPhaseIdx; + } + + /*! + * \brief Returns true if and only if a fluid phase is assumed to + * be an ideal mixture. + * + * We define an ideal mixture as a fluid phase where the fugacity + * coefficients of all components times the pressure of the phase + * are independent on the fluid composition. This assumption is true + * if Henry's law and Raoult's law apply. If you are unsure what + * this function should return, it is safe to return false. The + * only damage done will be (slightly) increased computation times + * in some cases. + * + * \param phaseIdx The index of the fluid phase to consider + */ + static constexpr bool isIdealMixture(int phaseIdx) + { + assert(0 <= phaseIdx && phaseIdx < numPhases); + return true; + } + + /*! + * \brief Returns true if and only if a fluid phase is assumed to + * be compressible. + * + * Compressible means that the partial derivative of the density + * to the fluid pressure is always larger than zero. + * + * \param phaseIdx The index of the fluid phase to consider + */ + static constexpr bool isCompressible(int phaseIdx) + { + assert(0 <= phaseIdx && phaseIdx < numPhases); + return true; + } + + /*! + * \brief Returns true if and only if a fluid phase is assumed to + * be an ideal gas. + * + * \param phaseIdx The index of the fluid phase to consider + */ + static bool isIdealGas(int phaseIdx) + { + assert(0 <= phaseIdx && phaseIdx < numPhases); + + // let the fluids decide + if (phaseIdx == gasPhaseIdx) + return H2O::gasIsIdeal() && CO2::gasIsIdeal(); + return false; // not a gas + } + + /**************************************** + * Component related static parameters + ****************************************/ + static constexpr int numComponents = 4; // H2O/brine, CO2, Ca, urea + static constexpr int H2OIdx = 0; + static constexpr int CO2Idx = 1; + static constexpr int CaIdx = 2; + static constexpr int UreaIdx = 3; + + static constexpr int BrineIdx = H2OIdx; + static constexpr int comp0Idx = BrineIdx; + static constexpr int comp1Idx = CO2Idx; + + /*! + * \brief Return the human readable name of a component + * + * \param compIdx The index of the component to consider + */ + static std::string componentName(int compIdx) + { + switch (compIdx) { + case BrineIdx: return Brine::name(); + case CO2Idx: return "CO2"; + case CaIdx: return Ca::name(); + case UreaIdx: return Urea::name(); + default: DUNE_THROW(Dune::InvalidStateException, "Invalid component index " << compIdx); + }; + } + + /*! + * \brief Return the molar mass of a component in \f$\mathrm{[kg/mol]}\f$. + * + * \param compIdx The index of the component to consider + */ + static Scalar molarMass(int compIdx) + { + switch (compIdx) { + case H2OIdx: return H2O::molarMass(); + // actually, the molar mass of brine is only needed for diffusion + // but since solutes are accounted for seperately + // only the molar mass of water is returned. + case CO2Idx: return CO2::molarMass(); + case CaIdx: return Ca::molarMass(); + case UreaIdx: return Urea::molarMass(); + default: DUNE_THROW(Dune::InvalidStateException, "Invalid component index " << compIdx); + }; + } + + /**************************************** + * thermodynamic relations + ****************************************/ + + static void init() + { + init(/*startTemp=*/295.15, /*endTemp=*/305.15, /*tempSteps=*/10, + /*startPressure=*/1e4, /*endPressure=*/1e6, /*pressureSteps=*/200); + + } + + static void init(Scalar startTemp, Scalar endTemp, int tempSteps, + Scalar startPressure, Scalar endPressure, int pressureSteps) + { + std::cout << "Initializing tables for the pure-water properties.\n"; + H2O::init(startTemp, endTemp, tempSteps, + startPressure, endPressure, pressureSteps); + } + + /*! + * \brief Given a phase's composition, temperature, pressure, and + * the partial pressures of all components, return its + * density \f$\mathrm{[kg/m^3]}\f$. + * + * \param fluidState The fluid state + * \param phaseIdx The index of the phase + */ + template + static Scalar density(const FluidState &fluidState, + const ParameterCache ¶mCache, + int phaseIdx) + { + assert(0 <= phaseIdx && phaseIdx < numPhases); + + Scalar temperature = fluidState.temperature(phaseIdx); + Scalar pressure = fluidState.pressure(phaseIdx); + + switch (phaseIdx) { + // assume pure brine for the liquid phase. + case liquidPhaseIdx: + return liquidDensity_(temperature, + pressure, + fluidState.moleFraction(liquidPhaseIdx, CO2Idx), + fluidState.moleFraction(liquidPhaseIdx, H2OIdx), + fluidState.massFraction(liquidPhaseIdx, CaIdx)); //consider density effect of dissolved calcium + + // assume pure CO2 for the gas phase. + case gasPhaseIdx: + return CO2::gasDensity(temperature, pressure); + + default: + DUNE_THROW(Dune::InvalidStateException, "Invalid phase index " << phaseIdx); break; + } + } + + /*! + * \brief The molar density \f$\rho_{mol,\alpha}\f$ + * of a fluid phase \f$\alpha\f$ in \f$\mathrm{[mol/m^3]}\f$ + * + * The molar density is defined by the + * mass density \f$\rho_\alpha\f$ and the mean molar mass \f$\overline M_\alpha\f$: + * + * \f[\rho_{mol,\alpha} = \frac{\rho_\alpha}{\overline M_\alpha} \;.\f] + */ + template + static Scalar molarDensity(const FluidState &fluidState, + const ParameterCache ¶mCache, + int phaseIdx) + { + const Scalar temperature = fluidState.temperature(phaseIdx); + const Scalar pressure = fluidState.pressure(phaseIdx); + if (phaseIdx == liquidPhaseIdx) + { + return density(fluidState, paramCache, phaseIdx) + / fluidState.averageMolarMass(phaseIdx); + } + else if (phaseIdx == gasPhaseIdx) + { + // for the gas phase assume an ideal gas + return CO2::gasMolarDensity(temperature, pressure); + } + else + DUNE_THROW(Dune::InvalidStateException, "Invalid phase index " << phaseIdx); + } + + /*! + * \brief The dynamic viscosity \f$\mathrm{[Pa*s]}\f$. + * + * \param temperature temperature of component in \f$\mathrm{[K]}\f$ + * \param pressure pressure of component in \f$\mathrm{[Pa]}\f$ + * + * Equation given in: - Batzle & Wang (1992) + * - cited by: Bachu & Adams (2002) + * "Equations of State for basin geofluids" + */ + template + static Scalar viscosity(const FluidState &fluidState, + const ParameterCache ¶mCache, + int phaseIdx) + { + assert(0 <= phaseIdx && phaseIdx < numPhases); + + Scalar temperature = fluidState.temperature(phaseIdx); + Scalar pressure = fluidState.pressure(phaseIdx); + + if (phaseIdx == liquidPhaseIdx) + { + // assume brine with viscosity effect of Ca for the liquid phase. + //F Scalar salinity = fluidState.massFraction(liquidPhaseIdx, CaIdx); + Scalar result = Brine::liquidViscosity(temperature, pressure); + + Valgrind::CheckDefined(result); + return result; + } + else if (phaseIdx == gasPhaseIdx) + { + // assume pure CO2 for the gas phase. + Scalar result = CO2::gasViscosity(temperature, pressure); + Valgrind::CheckDefined(result); + return result; + } + else + DUNE_THROW(Dune::InvalidStateException, "Invalid phase index " << phaseIdx); + + } + + /*! + * \brief Returns the fugacity coefficient [Pa] of a component in a + * phase. + * + * The fugacity coefficient \f$\phi^\kappa_\alpha\f$ of a + * component \f$\kappa\f$ for a fluid phase \f$\alpha\f$ defines + * the fugacity \f$f^\kappa_\alpha\f$ by the equation + * + * \f[ + f^\kappa_\alpha := \phi^\kappa_\alpha x^\kappa_\alpha p_\alpha\;. + \f] + * + * The fugacity itself is just an other way to express the + * chemical potential \f$\zeta^\kappa_\alpha\f$ of the component: + * + * \f[ + f^\kappa_\alpha := \exp\left\{\frac{\zeta^\kappa_\alpha}{k_B T_\alpha} \right\} + \f] + * where \f$k_B\f$ is Boltzmann's constant. + */ + template + static Scalar fugacityCoefficient(const FluidState &fluidState, + const ParameterCache ¶mCache, + int phaseIdx, + int compIdx) + { + assert(0 <= phaseIdx && phaseIdx < numPhases); + assert(0 <= compIdx && compIdx < numComponents); + + if (phaseIdx == gasPhaseIdx) + // use the fugacity coefficients of an ideal gas. the + // actual value of the fugacity is not relevant, as long + // as the relative fluid compositions are observed, + return 1.0; + + Scalar temperature = fluidState.temperature(phaseIdx); + Scalar pressure = fluidState.pressure(phaseIdx); + Scalar salinity = Brine::salinity(); // 0.1; //TODO major assumption in favor of runtime! + //function is actually designed for use with NaCl not Ca. + //Theoretically it should be: fluidState.massFraction(liquidPhaseIdx, CaIdx); + + assert(temperature > 0); + assert(pressure > 0); + // calulate the equilibrium composition for the given + // temperature and pressure. + Scalar xwH2O, xnH2O; + Scalar xwCO2, xnCO2; + Brine_CO2::calculateMoleFractions(temperature, + pressure, + salinity, + /*knowgasPhaseIdx=*/-1, + xwCO2, + xnH2O); + + // normalize the phase compositions + using std::min; + using std::max; + xwCO2 = max(0.0, min(1.0, xwCO2)); + xnH2O = max(0.0, min(1.0, xnH2O)); + + xwH2O = 1.0 - xwCO2; + xnCO2 = 1.0 - xnH2O; + + if (compIdx == BrineIdx) + { + Scalar phigH2O = 1.0; + return phigH2O * xnH2O / xwH2O; + } + if (compIdx == CO2Idx) + { + Scalar phigCO2 = 1.0; + return phigCO2 * xnCO2 / xwCO2; + } + else + return 1/pressure; //all other components stay in the liquid phase + } + + /*! + * \brief Given the phase compositions, return the binary + * diffusion coefficient \f$\mathrm{[m^2/s]}\f$ of two components in a phase. + * \param fluidState An arbitrary fluid state + * \param phaseIdx The index of the fluid phase to consider + * \param compIIdx Index of the component i + * \param compJIdx Index of the component j + */ + template + static Scalar binaryDiffusionCoefficient(const FluidState &fluidState, + const ParameterCache ¶mCache, + int phaseIdx, + int compIIdx, + int compJIdx) + { + assert(0 <= phaseIdx && phaseIdx < numPhases); + assert(0 <= compIIdx && compIIdx < numComponents); + assert(0 <= compJIdx && compJIdx < numComponents); + + Scalar temperature = fluidState.temperature(phaseIdx); + Scalar pressure = fluidState.pressure(phaseIdx); + + if (phaseIdx == liquidPhaseIdx) + { + assert(compIIdx == H2OIdx); + Scalar result = 0.0; + if(compJIdx == CO2Idx) + result = Brine_CO2::liquidDiffCoeff(temperature, pressure); + + else if (compJIdx < numComponents) //Calcium and urea + result = 1.587e-9; //[m²/s] educated guess, value for NaCl from J. Phys. D: Appl. Phys. 40 (2007) 2769-2776 + else + DUNE_THROW(Dune::NotImplemented, "Binary difussion coefficient : Incorrect compIdx"); + + Valgrind::CheckDefined(result); + return result; + } + else + { + assert(phaseIdx == gasPhaseIdx); + assert(compIIdx == CO2Idx); + Scalar result = 0.0; + if(compJIdx == H2OIdx) + result = Brine_CO2::gasDiffCoeff(temperature, pressure); + + else if (compJIdx + * + * Formula (2.42): + * the specific enthalpy of a gasphase result from the sum of (enthalpies*mass fraction) of the components + * + */ + template + static Scalar enthalpy(const FluidState &fluidState, + const ParameterCache ¶mCache, + int phaseIdx) + { + assert(0 <= phaseIdx && phaseIdx < numPhases); + + Scalar temperature = fluidState.temperature(phaseIdx); + Scalar pressure = fluidState.pressure(phaseIdx); + + if (phaseIdx == liquidPhaseIdx) + { + // assume pure brine for the liquid phase. + return Brine::liquidEnthalpy(temperature, pressure); + } + else + { + // assume pure CO2 for the gas phase. + return CO2::gasEnthalpy(temperature, pressure); + } + }; + +private: + //! calculate liquid density with respect to Water, CO2 and salt + static Scalar liquidDensity_(Scalar T, + Scalar pl, + Scalar xwCO2, + Scalar xwH2O, + Scalar XlSal) + { + Valgrind::CheckDefined(T); + Valgrind::CheckDefined(pl); + Valgrind::CheckDefined(XlSal); + Valgrind::CheckDefined(xwCO2); + + if(T < 273.15) + { + DUNE_THROW(NumericalProblem, + "Liquid density for Brine and CO2 is only " + "defined above 273.15K (is" << T << ")"); + } + if(pl >= 2.5e8) + { + DUNE_THROW(NumericalProblem, + "Liquid density for Brine and CO2 is only " + "defined below 250MPa (is" << pl << ")"); + } + + Scalar rho_brine = Brine::liquidDensity(T, pl); + Scalar rho_pure = H2O::liquidDensity(T, pl); + Scalar rho_lCO2 = liquidDensityWaterCO2_(T, pl, xwH2O, xwCO2); + Scalar contribCO2 = rho_lCO2 - rho_pure; + return rho_brine + contribCO2; + } + + //! calculate liquid Density of water and CO2 + static Scalar liquidDensityWaterCO2_(Scalar temperature, + Scalar pl, + Scalar xwH2O, + Scalar xwCO2) + { + const Scalar M_CO2 = CO2::molarMass(); + const Scalar M_H2O = H2O::molarMass(); + + const Scalar tempC = temperature - 273.15; /* tempC : temperature in °C */ + const Scalar rho_pure = H2O::liquidDensity(temperature, pl); + xwH2O = 1.0 - xwCO2; // xwH2O is available, but in case of a pure gas phase + // the value of M_T for the virtual liquid phase can become very large + const Scalar M_T = M_H2O * xwH2O + M_CO2 * xwCO2; + const Scalar V_phi = + (37.51 + + tempC*(-9.585e-2 + + tempC*(8.74e-4 - + tempC*5.044e-7))) / 1.0e6; + return 1 / (xwCO2 * V_phi/M_T + M_H2O * xwH2O / (rho_pure * M_T)); + } + +}; + +} // end namespace FluidSystems +} // end namespace Dumux + +#endif diff --git a/exercises/solution/exercise-biomineralization/solidsystems/biominsolidphase.hh b/exercises/solution/exercise-biomineralization/solidsystems/biominsolidphase.hh new file mode 100644 index 0000000..b745676 --- /dev/null +++ b/exercises/solution/exercise-biomineralization/solidsystems/biominsolidphase.hh @@ -0,0 +1,201 @@ +// -*- 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 . * + *****************************************************************************/ +/*! + * \file + * \ingroup SolidSystems + * \brief @copybrief Dumux::SolidSystems::InertSolidPhase + */ +#ifndef DUMUX_SOLIDSYSTEMS_COMPOSITIONAL_SOLID_PHASE_HH +#define DUMUX_SOLIDSYSTEMS_COMPOSITIONAL_SOLID_PHASE_HH + +#include +#include + +#include "../components/biofilm.hh" +#include +#include + +namespace Dumux { +namespace SolidSystems { + +/*! + * \ingroup SolidSystems + * \brief A solid phase consisting of a single inert solid component and two reactive solid components + * \note a solid is considered inert if it can't dissolve in a liquid and + * and can't increase its mass by precipitation from a fluid phase. + * \note inert components have to come after all non-inert components + */ +template +class BiominSolidPhase +{ +public: + using Biofilm = Components::Biofilm; + using Calcite = Components::Calcite; + using Granite = Components::Granite; + + /**************************************** + * Solid phase related static parameters + ****************************************/ + static constexpr int numComponents = 3; + static constexpr int numInertComponents = 1; + static constexpr int BiofilmIdx = 0; + static constexpr int CalciteIdx = 1; + static constexpr int GraniteIdx = 2; + + /*! + * \brief Return the human readable name of a solid phase + * + * \param compIdx The index of the solid phase to consider + */ + static std::string componentName(int compIdx) + { + switch (compIdx) + { + case BiofilmIdx: return Biofilm::name(); + case CalciteIdx: return Calcite::name(); + case GraniteIdx: return Granite::name(); + default: DUNE_THROW(Dune::InvalidStateException, "Invalid component index " << compIdx); + } + } + + /*! + * \brief A human readable name for the solid system. + */ + static std::string name() + { return "ThreeComponentSolidPhase"; } + + /*! + * \brief Returns whether the phase is incompressible + */ + static constexpr bool isCompressible(int compIdx) + { return false; } + + /*! + * \brief Returns whether all components are inert (don't react) + */ + static constexpr bool isInert() + { return (numComponents == numInertComponents); } + + /*! + * \brief The molar mass in \f$\mathrm{[kg/mol]}\f$ of the component. + */ + static Scalar molarMass(int compIdx) + { + switch (compIdx) + { + case BiofilmIdx: return Biofilm::molarMass(); + case CalciteIdx: return Calcite::molarMass(); + case GraniteIdx: return Granite::molarMass(); + default: DUNE_THROW(Dune::InvalidStateException, "Invalid component index " << compIdx); + } + } + + /*! + * \brief The density \f$\mathrm{[kg/m^3]}\f$ of the solid phase at a given pressure and temperature. + */ + template + static Scalar density(const SolidState& solidState) + { + Scalar rho1 = Biofilm::solidDensity(solidState.temperature()); + Scalar rho2 = Calcite::solidDensity(solidState.temperature()); + Scalar rho3 = Granite::solidDensity(solidState.temperature()); + Scalar volFrac1 = solidState.volumeFraction(BiofilmIdx); + Scalar volFrac2 = solidState.volumeFraction(CalciteIdx); + Scalar volFrac3 = solidState.volumeFraction(GraniteIdx); + + return (rho1*volFrac1+ + rho2*volFrac2+ + rho3*volFrac3) + /(volFrac1+volFrac2+volFrac3); + } + + /*! + * \brief The density \f$\mathrm{[kg/m^3]}\f$ of the solid phase at a given pressure and temperature. + */ + template + static Scalar density(const SolidState& solidState, const int compIdx) + { + switch (compIdx) + { + case BiofilmIdx: return Biofilm::solidDensity(solidState.temperature()); + case CalciteIdx: return Calcite::solidDensity(solidState.temperature()); + case GraniteIdx: return Granite::solidDensity(solidState.temperature()); + default: DUNE_THROW(Dune::InvalidStateException, "Invalid component index " << compIdx); + } + } + + /*! + * \brief The molar density of the solid phase at a given pressure and temperature. + */ + template + static Scalar molarDensity(const SolidState& solidState, const int compIdx) + { + switch (compIdx) + { + case BiofilmIdx: return Biofilm::solidDensity(solidState.temperature())/Biofilm::molarMass(); + case CalciteIdx: return Calcite::solidDensity(solidState.temperature())/Calcite::molarMass(); + case GraniteIdx: return Granite::solidDensity(solidState.temperature())/Calcite::molarMass(); + default: DUNE_THROW(Dune::InvalidStateException, "Invalid component index " << compIdx); + } + } + + /*! + * \brief Thermal conductivity of the solid \f$\mathrm{[W/(m K)]}\f$. + */ + template + static Scalar thermalConductivity(const SolidState &solidState) + { + Scalar lambda1 = Biofilm::solidThermalConductivity(solidState.temperature()); + Scalar lambda2 = Calcite::solidThermalConductivity(solidState.temperature()); + Scalar lambda3 = Granite::solidThermalConductivity(solidState.temperature()); + Scalar volFrac1 = solidState.volumeFraction(BiofilmIdx); + Scalar volFrac2 = solidState.volumeFraction(CalciteIdx); + Scalar volFrac3 = solidState.volumeFraction(GraniteIdx); + + return (lambda1*volFrac1+ + lambda2*volFrac2+ + lambda3*volFrac3) + /(volFrac1+volFrac2+volFrac3); + } + + /*! + * \brief Specific isobaric heat capacity of the pure solids \f$\mathrm{[J/(kg K)]}\f$. + */ + template + static Scalar heatCapacity(const SolidState &solidState) + { + Scalar c1 = Biofilm::solidHeatCapacity(solidState.temperature()); + Scalar c2 = Calcite::solidHeatCapacity(solidState.temperature()); + Scalar c3 = Granite::solidHeatCapacity(solidState.temperature()); + Scalar volFrac1 = solidState.volumeFraction(BiofilmIdx); + Scalar volFrac2 = solidState.volumeFraction(CalciteIdx); + Scalar volFrac3 = solidState.volumeFraction(GraniteIdx); + + return (c1*volFrac1+ + c2*volFrac2+ + c3*volFrac3) + /(volFrac1+volFrac2+volFrac3); + } + +}; + +} // end namespace SolidSystems +} // end namespace Dumux + +#endif -- GitLab From 440692db6a2eae4834428ccd007c72b25284c18f Mon Sep 17 00:00:00 2001 From: Kilian Weishaupt Date: Thu, 6 Dec 2018 10:56:16 +0100 Subject: [PATCH 13/25] [ff-pnm] Update first exercise --- .../1pspatialparams.hh | 12 ++-- .../2pspatialparams.hh | 12 ++-- exercises/exercise-coupling-ff-pm/README.md | 10 +++- .../interface/ex_interface_coupling_ff-pm.cc | 53 +++++++++-------- .../ex_interface_coupling_ff-pm.input | 1 + .../interface/ex_interface_ffproblem.hh | 58 +++++++++++-------- .../interface/ex_interface_pmproblem.hh | 43 ++++++++------ .../1pspatialparams.hh | 12 ++-- .../2pspatialparams.hh | 12 ++-- .../interface/ex_interface_coupling_ff-pm.cc | 23 ++++---- .../ex_interface_coupling_ff-pm.input | 1 + .../interface/ex_interface_ffproblem.hh | 19 +++--- .../interface/ex_interface_pmproblem.hh | 2 +- 13 files changed, 138 insertions(+), 120 deletions(-) diff --git a/exercises/exercise-coupling-ff-pm/1pspatialparams.hh b/exercises/exercise-coupling-ff-pm/1pspatialparams.hh index 64887e3..e95c249 100644 --- a/exercises/exercise-coupling-ff-pm/1pspatialparams.hh +++ b/exercises/exercise-coupling-ff-pm/1pspatialparams.hh @@ -38,14 +38,14 @@ namespace Dumux */ template class OnePSpatialParams -: public FVSpatialParamsOneP, + GetPropType, OnePSpatialParams> { - using FVGridGeometry = typename GET_PROP_TYPE(TypeTag, FVGridGeometry); - using Scalar = typename GET_PROP_TYPE(TypeTag, Scalar); - using Problem = typename GET_PROP_TYPE(TypeTag, Problem); - using GridView = typename GET_PROP_TYPE(TypeTag, GridView); + using FVGridGeometry = GetPropType; + using Scalar = GetPropType; + using Problem = GetPropType; + using GridView = GetPropType; using ParentType = FVSpatialParamsOneP>; using Element = typename GridView::template Codim<0>::Entity; diff --git a/exercises/exercise-coupling-ff-pm/2pspatialparams.hh b/exercises/exercise-coupling-ff-pm/2pspatialparams.hh index 1830f3c..948b7a7 100644 --- a/exercises/exercise-coupling-ff-pm/2pspatialparams.hh +++ b/exercises/exercise-coupling-ff-pm/2pspatialparams.hh @@ -40,15 +40,15 @@ namespace Dumux */ template class TwoPSpatialParams -: public FVSpatialParams, + GetPropType, TwoPSpatialParams> { - using Scalar = typename GET_PROP_TYPE(TypeTag, Scalar); - using Problem = typename GET_PROP_TYPE(TypeTag, Problem); - using GridView = typename GET_PROP_TYPE(TypeTag, GridView); + using Scalar = GetPropType; + using Problem = GetPropType; + using GridView = GetPropType; using Element = typename GridView::template Codim<0>::Entity; - using FVGridGeometry = typename GET_PROP_TYPE(TypeTag, FVGridGeometry); + using FVGridGeometry = GetPropType; using FVElementGeometry = typename FVGridGeometry::LocalView; using SubControlVolume = typename FVElementGeometry::SubControlVolume; using ParentType = FVSpatialParams>; diff --git a/exercises/exercise-coupling-ff-pm/README.md b/exercises/exercise-coupling-ff-pm/README.md index 58b7545..ec4e22a 100644 --- a/exercises/exercise-coupling-ff-pm/README.md +++ b/exercises/exercise-coupling-ff-pm/README.md @@ -83,6 +83,7 @@ if(couplingManager().isCoupledEntity(CouplingManager::stokesIdx, scvf)) { values.setCouplingNeumann(Indices::conti0EqIdx); values.setCouplingNeumann(Indices::momentumYBalanceIdx); + values.setDirichlet(Indices::velocityXIdx); // assume no slip on interface } ``` @@ -123,7 +124,11 @@ $`\frac{\partial v_x}{\partial y} = \frac{\alpha}{\sqrt K} (v_x - q_{pm})\quad`$ with $`\quad q_{pm}=0`$. -To include this, just set a Beavers-Joseph-Saffman (BJS) boundary condition for the respective momentum balance: +To include this, just replace the no-slip condition at the interface +``` cpp +values.setDirichlet(Indices::velocityXIdx); // assume no slip on interface +``` +with a Beavers-Joseph-Saffman (BJS) boundary condition for the respective momentum balance: ``` cpp values.setBJS(Indices::momentumXBalanceIdx); ``` @@ -223,7 +228,8 @@ liquid saturation as primary variables (p_g-S_l -> `p1s0`) or vice versa. * Set the property ``` -SET_PROP(DarcyTypeTag, Formulation) +template +struct Formulation { static constexpr auto value = TwoPFormulation::p1s0; }; ``` in the Properties section in the problem file. diff --git a/exercises/exercise-coupling-ff-pm/interface/ex_interface_coupling_ff-pm.cc b/exercises/exercise-coupling-ff-pm/interface/ex_interface_coupling_ff-pm.cc index 85226b9..62673d5 100644 --- a/exercises/exercise-coupling-ff-pm/interface/ex_interface_coupling_ff-pm.cc +++ b/exercises/exercise-coupling-ff-pm/interface/ex_interface_coupling_ff-pm.cc @@ -31,10 +31,11 @@ #include #include #include +#include #include #include #include -#include +#include #include #include #include @@ -51,15 +52,17 @@ namespace Dumux { namespace Properties { -SET_PROP(StokesOnePTypeTag, CouplingManager) +template +struct CouplingManager { - using Traits = StaggeredMultiDomainTraits; + using Traits = StaggeredMultiDomainTraits; using type = Dumux::StokesDarcyCouplingManager; }; -SET_PROP(DarcyOnePTypeTag, CouplingManager) +template +struct CouplingManager { - using Traits = StaggeredMultiDomainTraits; + using Traits = StaggeredMultiDomainTraits; using type = Dumux::StokesDarcyCouplingManager; }; @@ -81,8 +84,8 @@ int main(int argc, char** argv) try Parameters::init(argc, argv); // Define the sub problem type tags - using StokesTypeTag = TTAG(StokesOnePTypeTag); - using DarcyTypeTag = TTAG(DarcyOnePTypeTag); + using StokesTypeTag = Properties::TTag::StokesOnePTypeTag; + using DarcyTypeTag = Properties::TTag::DarcyOnePTypeTag; @@ -90,11 +93,11 @@ int main(int argc, char** argv) try // create two individual grids (from the given grid file or the input file) // for both sub-domains - using DarcyGridManager = Dumux::GridManager; + using DarcyGridManager = Dumux::GridManager>; DarcyGridManager darcyGridManager; darcyGridManager.init("Darcy"); // pass parameter group - using StokesGridManager = Dumux::GridManager; + using StokesGridManager = Dumux::GridManager>; StokesGridManager stokesGridManager; stokesGridManager.init("Stokes"); // pass parameter group @@ -149,10 +152,10 @@ int main(int argc, char** argv) try // create the finite volume grid geometry - using StokesFVGridGeometry = typename GET_PROP_TYPE(StokesTypeTag, FVGridGeometry); + using StokesFVGridGeometry = GetPropType; auto stokesFvGridGeometry = std::make_shared(stokesGridView); stokesFvGridGeometry->update(); - using DarcyFVGridGeometry = typename GET_PROP_TYPE(DarcyTypeTag, FVGridGeometry); + using DarcyFVGridGeometry = GetPropType; auto darcyFvGridGeometry = std::make_shared(darcyGridView); darcyFvGridGeometry->update(); @@ -168,9 +171,9 @@ int main(int argc, char** argv) try constexpr auto darcyIdx = CouplingManager::darcyIdx; // the problem (initial and boundary conditions) - using StokesProblem = typename GET_PROP_TYPE(StokesTypeTag, Problem); + using StokesProblem = GetPropType; auto stokesProblem = std::make_shared(stokesFvGridGeometry, couplingManager); - using DarcyProblem = typename GET_PROP_TYPE(DarcyTypeTag, Problem); + using DarcyProblem = GetPropType; auto darcyProblem = std::make_shared(darcyFvGridGeometry, couplingManager); // the solution vector @@ -179,24 +182,18 @@ int main(int argc, char** argv) try sol[stokesFaceIdx].resize(stokesFvGridGeometry->numFaceDofs()); sol[darcyIdx].resize(darcyFvGridGeometry->numDofs()); - const auto& cellCenterSol = sol[stokesCellCenterIdx]; - const auto& faceSol = sol[stokesFaceIdx]; + auto stokesSol = partial(sol, stokesCellCenterIdx, stokesFaceIdx); - // apply initial solution for instationary problems - typename GET_PROP_TYPE(StokesTypeTag, SolutionVector) stokesSol; - std::get<0>(stokesSol) = cellCenterSol; - std::get<1>(stokesSol) = faceSol; stokesProblem->applyInitialSolution(stokesSol); - sol[stokesCellCenterIdx] = stokesSol[stokesCellCenterIdx]; - sol[stokesFaceIdx] = stokesSol[stokesFaceIdx]; + darcyProblem->applyInitialSolution(sol[darcyIdx]); couplingManager->init(stokesProblem, darcyProblem, sol); // the grid variables - using StokesGridVariables = typename GET_PROP_TYPE(StokesTypeTag, GridVariables); + using StokesGridVariables = GetPropType; auto stokesGridVariables = std::make_shared(stokesProblem, stokesFvGridGeometry); stokesGridVariables->init(stokesSol); - using DarcyGridVariables = typename GET_PROP_TYPE(DarcyTypeTag, GridVariables); + using DarcyGridVariables = GetPropType; auto darcyGridVariables = std::make_shared(darcyProblem, darcyFvGridGeometry); darcyGridVariables->init(sol[darcyIdx]); @@ -204,16 +201,18 @@ int main(int argc, char** argv) try const auto stokesName = getParam("Problem.Name") + "_" + stokesProblem->name(); const auto darcyName = getParam("Problem.Name") + "_" + darcyProblem->name(); - StaggeredVtkOutputModule stokesVtkWriter(*stokesProblem, *stokesFvGridGeometry, *stokesGridVariables, stokesSol, stokesName); - GET_PROP_TYPE(StokesTypeTag, VtkOutputFields)::init(stokesVtkWriter); + StaggeredVtkOutputModule stokesVtkWriter(*stokesGridVariables, stokesSol, stokesName); + GetPropType::initOutputModule(stokesVtkWriter); //****** uncomment the add analytical solution of v_x *****// // stokesVtkWriter.addField(stokesProblem->getAnalyticalVelocityX(), "analyticalV_x"); stokesVtkWriter.write(0.0); - VtkOutputModule darcyVtkWriter(*darcyProblem, *darcyFvGridGeometry, *darcyGridVariables, sol[darcyIdx], darcyName); - GET_PROP_TYPE(DarcyTypeTag, VtkOutputFields)::init(darcyVtkWriter); + VtkOutputModule> darcyVtkWriter(*darcyGridVariables, sol[darcyIdx], darcyName); + using DarcyVelocityOutput = GetPropType; + darcyVtkWriter.addVelocityOutput(std::make_shared(*darcyGridVariables)); + GetPropType::initOutputModule(darcyVtkWriter); darcyVtkWriter.write(0.0); // the assembler for a stationary problem diff --git a/exercises/exercise-coupling-ff-pm/interface/ex_interface_coupling_ff-pm.input b/exercises/exercise-coupling-ff-pm/interface/ex_interface_coupling_ff-pm.input index e381395..4117b7f 100644 --- a/exercises/exercise-coupling-ff-pm/interface/ex_interface_coupling_ff-pm.input +++ b/exercises/exercise-coupling-ff-pm/interface/ex_interface_coupling_ff-pm.input @@ -28,6 +28,7 @@ Grading1 = 1 [Stokes.Problem] Name = stokes PressureDifference = 1e-9 +EnableInertiaTerms = false [Darcy.Problem] Name = darcy diff --git a/exercises/exercise-coupling-ff-pm/interface/ex_interface_ffproblem.hh b/exercises/exercise-coupling-ff-pm/interface/ex_interface_ffproblem.hh index 48d29d6..c5649a7 100644 --- a/exercises/exercise-coupling-ff-pm/interface/ex_interface_ffproblem.hh +++ b/exercises/exercise-coupling-ff-pm/interface/ex_interface_ffproblem.hh @@ -42,20 +42,25 @@ class StokesSubProblem; namespace Properties { -NEW_TYPE_TAG(StokesOnePTypeTag, INHERITS_FROM(StaggeredFreeFlowModel, NavierStokes)); +// Create new type tags +namespace TTag { +struct StokesOnePTypeTag { using InheritsFrom = std::tuple; }; +} // end namespace TTag // the fluid system -SET_PROP(StokesOnePTypeTag, FluidSystem) +template +struct FluidSystem { - using Scalar = typename GET_PROP_TYPE(TypeTag, Scalar); + using Scalar = GetPropType; using type = FluidSystems::OnePLiquid > ; }; // Set the grid type -SET_PROP(StokesOnePTypeTag, Grid) +template +struct Grid { static constexpr auto dim = 2; - using Scalar = typename GET_PROP_TYPE(TypeTag, Scalar); + using Scalar = GetPropType; using TensorGrid = Dune::YaspGrid<2, Dune::TensorProductCoordinates >; //****** comment out for the last exercise *****// @@ -67,13 +72,15 @@ SET_PROP(StokesOnePTypeTag, Grid) }; // Set the problem property -SET_TYPE_PROP(StokesOnePTypeTag, Problem, Dumux::StokesSubProblem ); - -SET_BOOL_PROP(StokesOnePTypeTag, EnableFVGridGeometryCache, true); -SET_BOOL_PROP(StokesOnePTypeTag, EnableGridFluxVariablesCache, true); -SET_BOOL_PROP(StokesOnePTypeTag, EnableGridVolumeVariablesCache, true); - -SET_BOOL_PROP(StokesOnePTypeTag, EnableInertiaTerms, false); +template +struct Problem { using type = Dumux::StokesSubProblem ; }; + +template +struct EnableFVGridGeometryCache { static constexpr bool value = true; }; +template +struct EnableGridFluxVariablesCache { static constexpr bool value = true; }; +template +struct EnableGridVolumeVariablesCache { static constexpr bool value = true; }; } /*! @@ -84,25 +91,25 @@ class StokesSubProblem : public NavierStokesProblem { using ParentType = NavierStokesProblem; - using GridView = typename GET_PROP_TYPE(TypeTag, GridView); - using Scalar = typename GET_PROP_TYPE(TypeTag, Scalar); + using GridView = GetPropType; + using Scalar = GetPropType; - using Indices = typename GET_PROP_TYPE(TypeTag, ModelTraits)::Indices; + using Indices = typename GetPropType::Indices; - using BoundaryTypes = typename GET_PROP_TYPE(TypeTag, BoundaryTypes); + using BoundaryTypes = GetPropType; - using FVGridGeometry = typename GET_PROP_TYPE(TypeTag, FVGridGeometry); + using FVGridGeometry = GetPropType; using FVElementGeometry = typename FVGridGeometry::LocalView; using SubControlVolumeFace = typename FVElementGeometry::SubControlVolumeFace; using Element = typename GridView::template Codim<0>::Entity; using GlobalPosition = typename Element::Geometry::GlobalCoordinate; - using PrimaryVariables = typename GET_PROP_TYPE(TypeTag, PrimaryVariables); - using NumEqVector = typename GET_PROP_TYPE(TypeTag, NumEqVector); - using FluidSystem = typename GET_PROP_TYPE(TypeTag, FluidSystem); + using PrimaryVariables = GetPropType; + using NumEqVector = GetPropType; + using FluidSystem = GetPropType; - using CouplingManager = typename GET_PROP_TYPE(TypeTag, CouplingManager); + using CouplingManager = GetPropType; public: StokesSubProblem(std::shared_ptr fvGridGeometry, std::shared_ptr couplingManager) @@ -170,6 +177,7 @@ public: { values.setCouplingNeumann(Indices::conti0EqIdx); values.setCouplingNeumann(Indices::momentumYBalanceIdx); + values.setDirichlet(Indices::velocityXIdx); // assume no slip on interface } return values; @@ -208,8 +216,8 @@ public: if(couplingManager().isCoupledEntity(CouplingManager::stokesIdx, scvf)) { - values[Indices::conti0EqIdx] = couplingManager().couplingData().massCouplingCondition(fvGeometry, elemVolVars, elemFaceVars, scvf); - values[Indices::momentumYBalanceIdx] = couplingManager().couplingData().momentumCouplingCondition(fvGeometry, elemVolVars, elemFaceVars, scvf); + values[Indices::conti0EqIdx] = couplingManager().couplingData().massCouplingCondition(element, fvGeometry, elemVolVars, elemFaceVars, scvf); + values[Indices::momentumYBalanceIdx] = couplingManager().couplingData().momentumCouplingCondition(element, fvGeometry, elemVolVars, elemFaceVars, scvf); } return values; @@ -246,9 +254,9 @@ public: /*! * \brief Returns the intrinsic permeability of required as input parameter for the Beavers-Joseph-Saffman boundary condition */ - Scalar permeability(const SubControlVolumeFace& scvf) const + Scalar permeability(const Element& element, const SubControlVolumeFace& scvf) const { - return couplingManager().couplingData().darcyPermeability(scvf); + return couplingManager().couplingData().darcyPermeability(element, scvf); } /*! diff --git a/exercises/exercise-coupling-ff-pm/interface/ex_interface_pmproblem.hh b/exercises/exercise-coupling-ff-pm/interface/ex_interface_pmproblem.hh index 8b9f749..e447100 100644 --- a/exercises/exercise-coupling-ff-pm/interface/ex_interface_pmproblem.hh +++ b/exercises/exercise-coupling-ff-pm/interface/ex_interface_pmproblem.hh @@ -46,23 +46,29 @@ class DarcySubProblem; namespace Properties { -NEW_TYPE_TAG(DarcyOnePTypeTag, INHERITS_FROM(CCTpfaModel, OneP)); +// Create new type tags +namespace TTag { +struct DarcyOnePTypeTag { using InheritsFrom = std::tuple; }; +} // end namespace TTag // Set the problem property -SET_TYPE_PROP(DarcyOnePTypeTag, Problem, Dumux::DarcySubProblem); +template +struct Problem { using type = Dumux::DarcySubProblem; }; // the fluid system -SET_PROP(DarcyOnePTypeTag, FluidSystem) +template +struct FluidSystem { - using Scalar = typename GET_PROP_TYPE(TypeTag, Scalar); + using Scalar = GetPropType; using type = FluidSystems::OnePLiquid > ; }; // Set the grid type -SET_PROP(DarcyOnePTypeTag, Grid) +template +struct Grid { static constexpr auto dim = 2; - using Scalar = typename GET_PROP_TYPE(TypeTag, Scalar); + using Scalar = GetPropType; using TensorGrid = Dune::YaspGrid<2, Dune::TensorProductCoordinates >; //****** comment out for the last exercise *****// @@ -73,7 +79,8 @@ SET_PROP(DarcyOnePTypeTag, Grid) // using type = Dune::SubGrid; }; -SET_TYPE_PROP(DarcyOnePTypeTag, SpatialParams, OnePSpatialParams); +template +struct SpatialParams { using type = OnePSpatialParams; }; } /*! @@ -83,23 +90,23 @@ template class DarcySubProblem : public PorousMediumFlowProblem { using ParentType = PorousMediumFlowProblem; - using GridView = typename GET_PROP_TYPE(TypeTag, GridView); - using Scalar = typename GET_PROP_TYPE(TypeTag, Scalar); - using PrimaryVariables = typename GET_PROP_TYPE(TypeTag, PrimaryVariables); - using NumEqVector = typename GET_PROP_TYPE(TypeTag, NumEqVector); - using BoundaryTypes = typename GET_PROP_TYPE(TypeTag, BoundaryTypes); - using VolumeVariables = typename GET_PROP_TYPE(TypeTag, VolumeVariables); - using FVElementGeometry = typename GET_PROP_TYPE(TypeTag, FVGridGeometry)::LocalView; + using GridView = GetPropType; + using Scalar = GetPropType; + using PrimaryVariables = GetPropType; + using NumEqVector = GetPropType; + using BoundaryTypes = GetPropType; + using VolumeVariables = GetPropType; + using FVElementGeometry = typename GetPropType::LocalView; using SubControlVolume = typename FVElementGeometry::SubControlVolume; using SubControlVolumeFace = typename FVElementGeometry::SubControlVolumeFace; - using FVGridGeometry = typename GET_PROP_TYPE(TypeTag, FVGridGeometry); + using FVGridGeometry = GetPropType; - using Indices = typename GET_PROP_TYPE(TypeTag, ModelTraits)::Indices; + using Indices = typename GetPropType::Indices; using Element = typename GridView::template Codim<0>::Entity; using GlobalPosition = typename Element::Geometry::GlobalCoordinate; - using CouplingManager = typename GET_PROP_TYPE(TypeTag, CouplingManager); + using CouplingManager = GetPropType; public: DarcySubProblem(std::shared_ptr fvGridGeometry, @@ -188,7 +195,7 @@ public: // ... except at the coupling interface if (couplingManager().isCoupledEntity(CouplingManager::darcyIdx, scvf)) - values[Indices::conti0EqIdx] = couplingManager().couplingData().massCouplingCondition(fvGeometry, elemVolVars, scvf); + values[Indices::conti0EqIdx] = couplingManager().couplingData().massCouplingCondition(element, fvGeometry, elemVolVars, scvf); return values; } diff --git a/exercises/solution/exercise-coupling-ff-pm/1pspatialparams.hh b/exercises/solution/exercise-coupling-ff-pm/1pspatialparams.hh index 64887e3..e95c249 100644 --- a/exercises/solution/exercise-coupling-ff-pm/1pspatialparams.hh +++ b/exercises/solution/exercise-coupling-ff-pm/1pspatialparams.hh @@ -38,14 +38,14 @@ namespace Dumux */ template class OnePSpatialParams -: public FVSpatialParamsOneP, + GetPropType, OnePSpatialParams> { - using FVGridGeometry = typename GET_PROP_TYPE(TypeTag, FVGridGeometry); - using Scalar = typename GET_PROP_TYPE(TypeTag, Scalar); - using Problem = typename GET_PROP_TYPE(TypeTag, Problem); - using GridView = typename GET_PROP_TYPE(TypeTag, GridView); + using FVGridGeometry = GetPropType; + using Scalar = GetPropType; + using Problem = GetPropType; + using GridView = GetPropType; using ParentType = FVSpatialParamsOneP>; using Element = typename GridView::template Codim<0>::Entity; diff --git a/exercises/solution/exercise-coupling-ff-pm/2pspatialparams.hh b/exercises/solution/exercise-coupling-ff-pm/2pspatialparams.hh index 1830f3c..948b7a7 100644 --- a/exercises/solution/exercise-coupling-ff-pm/2pspatialparams.hh +++ b/exercises/solution/exercise-coupling-ff-pm/2pspatialparams.hh @@ -40,15 +40,15 @@ namespace Dumux */ template class TwoPSpatialParams -: public FVSpatialParams, + GetPropType, TwoPSpatialParams> { - using Scalar = typename GET_PROP_TYPE(TypeTag, Scalar); - using Problem = typename GET_PROP_TYPE(TypeTag, Problem); - using GridView = typename GET_PROP_TYPE(TypeTag, GridView); + using Scalar = GetPropType; + using Problem = GetPropType; + using GridView = GetPropType; using Element = typename GridView::template Codim<0>::Entity; - using FVGridGeometry = typename GET_PROP_TYPE(TypeTag, FVGridGeometry); + using FVGridGeometry = GetPropType; using FVElementGeometry = typename FVGridGeometry::LocalView; using SubControlVolume = typename FVElementGeometry::SubControlVolume; using ParentType = FVSpatialParams>; diff --git a/exercises/solution/exercise-coupling-ff-pm/interface/ex_interface_coupling_ff-pm.cc b/exercises/solution/exercise-coupling-ff-pm/interface/ex_interface_coupling_ff-pm.cc index 116ed7e..8443475 100644 --- a/exercises/solution/exercise-coupling-ff-pm/interface/ex_interface_coupling_ff-pm.cc +++ b/exercises/solution/exercise-coupling-ff-pm/interface/ex_interface_coupling_ff-pm.cc @@ -31,10 +31,11 @@ #include #include #include +#include #include #include #include -#include +#include #include #include #include @@ -171,16 +172,10 @@ int main(int argc, char** argv) try sol[stokesFaceIdx].resize(stokesFvGridGeometry->numFaceDofs()); sol[darcyIdx].resize(darcyFvGridGeometry->numDofs()); - const auto& cellCenterSol = sol[stokesCellCenterIdx]; - const auto& faceSol = sol[stokesFaceIdx]; + auto stokesSol = partial(sol, stokesCellCenterIdx, stokesFaceIdx); - // apply initial solution for instationary problems - typename GET_PROP_TYPE(StokesTypeTag, SolutionVector) stokesSol; - std::get<0>(stokesSol) = cellCenterSol; - std::get<1>(stokesSol) = faceSol; stokesProblem->applyInitialSolution(stokesSol); - sol[stokesCellCenterIdx] = stokesSol[stokesCellCenterIdx]; - sol[stokesFaceIdx] = stokesSol[stokesFaceIdx]; + darcyProblem->applyInitialSolution(sol[darcyIdx]); couplingManager->init(stokesProblem, darcyProblem, sol); @@ -196,8 +191,8 @@ int main(int argc, char** argv) try const auto stokesName = getParam("Problem.Name") + "_" + stokesProblem->name(); const auto darcyName = getParam("Problem.Name") + "_" + darcyProblem->name(); - StaggeredVtkOutputModule stokesVtkWriter(*stokesProblem, *stokesFvGridGeometry, *stokesGridVariables, stokesSol, stokesName); - GET_PROP_TYPE(StokesTypeTag, VtkOutputFields)::init(stokesVtkWriter); + StaggeredVtkOutputModule stokesVtkWriter(*stokesGridVariables, stokesSol, stokesName); + GetPropType::initOutputModule(stokesVtkWriter); #if EXNUMBER >= 2 stokesVtkWriter.addField(stokesProblem->getAnalyticalVelocityX(), "analyticalV_x"); @@ -205,8 +200,10 @@ int main(int argc, char** argv) try stokesVtkWriter.write(0.0); - VtkOutputModule darcyVtkWriter(*darcyProblem, *darcyFvGridGeometry, *darcyGridVariables, sol[darcyIdx], darcyName); - GET_PROP_TYPE(DarcyTypeTag, VtkOutputFields)::init(darcyVtkWriter); + VtkOutputModule> darcyVtkWriter(*darcyGridVariables, sol[darcyIdx], darcyName); + using DarcyVelocityOutput = GetPropType; + darcyVtkWriter.addVelocityOutput(std::make_shared(*darcyGridVariables)); + GetPropType::initOutputModule(darcyVtkWriter); darcyVtkWriter.write(0.0); // the assembler for a stationary problem diff --git a/exercises/solution/exercise-coupling-ff-pm/interface/ex_interface_coupling_ff-pm.input b/exercises/solution/exercise-coupling-ff-pm/interface/ex_interface_coupling_ff-pm.input index e381395..4117b7f 100644 --- a/exercises/solution/exercise-coupling-ff-pm/interface/ex_interface_coupling_ff-pm.input +++ b/exercises/solution/exercise-coupling-ff-pm/interface/ex_interface_coupling_ff-pm.input @@ -28,6 +28,7 @@ Grading1 = 1 [Stokes.Problem] Name = stokes PressureDifference = 1e-9 +EnableInertiaTerms = false [Darcy.Problem] Name = darcy diff --git a/exercises/solution/exercise-coupling-ff-pm/interface/ex_interface_ffproblem.hh b/exercises/solution/exercise-coupling-ff-pm/interface/ex_interface_ffproblem.hh index 369a7bd..c0dc455 100644 --- a/exercises/solution/exercise-coupling-ff-pm/interface/ex_interface_ffproblem.hh +++ b/exercises/solution/exercise-coupling-ff-pm/interface/ex_interface_ffproblem.hh @@ -74,7 +74,6 @@ SET_BOOL_PROP(StokesOnePTypeTag, EnableFVGridGeometryCache, true); SET_BOOL_PROP(StokesOnePTypeTag, EnableGridFluxVariablesCache, true); SET_BOOL_PROP(StokesOnePTypeTag, EnableGridVolumeVariablesCache, true); -SET_BOOL_PROP(StokesOnePTypeTag, EnableInertiaTerms, false); } /*! @@ -185,12 +184,12 @@ public: values.setCouplingNeumann(scvf.directionIndex()); #endif -#if EXNUMBER == 2 +#if EXNUMBER < 2 + values.setDirichlet(Indices::velocityXIdx); // assume no slip on interface +#elif EXNUMBER == 2 // set the Beaver-Joseph-Saffman slip condition for the tangential momentum balance equation values.setBJS(Indices::momentumXBalanceIdx); -#endif - -#if EXNUMBER == 3 +#else // set the Beaver-Joseph-Saffman slip condition for the tangential momentum balance equation, // consider orientation of face automatically values.setBJS(1 - scvf.directionIndex()); @@ -233,11 +232,11 @@ public: if(couplingManager().isCoupledEntity(CouplingManager::stokesIdx, scvf)) { - values[Indices::conti0EqIdx] = couplingManager().couplingData().massCouplingCondition(fvGeometry, elemVolVars, elemFaceVars, scvf); + values[Indices::conti0EqIdx] = couplingManager().couplingData().massCouplingCondition(element, fvGeometry, elemVolVars, elemFaceVars, scvf); #if EXNUMBER < 3 - values[Indices::momentumYBalanceIdx] = couplingManager().couplingData().momentumCouplingCondition(fvGeometry, elemVolVars, elemFaceVars, scvf); + values[Indices::momentumYBalanceIdx] = couplingManager().couplingData().momentumCouplingCondition(element, fvGeometry, elemVolVars, elemFaceVars, scvf); #else - values[scvf.directionIndex()] = couplingManager().couplingData().momentumCouplingCondition(fvGeometry, elemVolVars, elemFaceVars, scvf); + values[scvf.directionIndex()] = couplingManager().couplingData().momentumCouplingCondition(element, fvGeometry, elemVolVars, elemFaceVars, scvf); #endif } @@ -283,9 +282,9 @@ public: /*! * \brief Returns the intrinsic permeability of required as input parameter for the Beavers-Joseph-Saffman boundary condition */ - Scalar permeability(const SubControlVolumeFace& scvf) const + Scalar permeability(const Element& element, const SubControlVolumeFace& scvf) const { - return couplingManager().couplingData().darcyPermeability(scvf); + return couplingManager().couplingData().darcyPermeability(element, scvf); } /*! diff --git a/exercises/solution/exercise-coupling-ff-pm/interface/ex_interface_pmproblem.hh b/exercises/solution/exercise-coupling-ff-pm/interface/ex_interface_pmproblem.hh index d78c76f..3549ff0 100644 --- a/exercises/solution/exercise-coupling-ff-pm/interface/ex_interface_pmproblem.hh +++ b/exercises/solution/exercise-coupling-ff-pm/interface/ex_interface_pmproblem.hh @@ -184,7 +184,7 @@ public: NumEqVector values(0.0); if (couplingManager().isCoupledEntity(CouplingManager::darcyIdx, scvf)) - values[Indices::conti0EqIdx] = couplingManager().couplingData().massCouplingCondition(fvGeometry, elemVolVars, scvf); + values[Indices::conti0EqIdx] = couplingManager().couplingData().massCouplingCondition(element, fvGeometry, elemVolVars, scvf); return values; } -- GitLab From 111c328dd3691307f5a8c60ba181577bdd8cce49 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Dennis=20Gl=C3=A4ser?= Date: Tue, 11 Dec 2018 10:11:13 +0100 Subject: [PATCH 14/25] [ex-fractures] port to Dumux3.0 --- .../exercise-fractures/exercise_fractures.cc | 51 +++++++++-------- .../exercise-fractures/fractureproblem.hh | 50 ++++++++++------- exercises/exercise-fractures/matrixproblem.hh | 56 +++++++++++-------- 3 files changed, 92 insertions(+), 65 deletions(-) diff --git a/exercises/exercise-fractures/exercise_fractures.cc b/exercises/exercise-fractures/exercise_fractures.cc index ac6a9f1..7a61562 100644 --- a/exercises/exercise-fractures/exercise_fractures.cc +++ b/exercises/exercise-fractures/exercise_fractures.cc @@ -50,10 +50,10 @@ // Define some types for this test so that we can set them as properties below and // reuse them again in the main function with only one single definition of them here -using MatrixTypeTag = TTAG(MatrixProblemTypeTag); -using FractureTypeTag = TTAG(FractureProblemTypeTag); -using MatrixFVGridGeometry = typename GET_PROP_TYPE(MatrixTypeTag, FVGridGeometry); -using FractureFVGridGeometry = typename GET_PROP_TYPE(FractureTypeTag, FVGridGeometry); +using MatrixTypeTag = Dumux::Properties::TTag::MatrixProblemTypeTag; +using FractureTypeTag = Dumux::Properties::TTag::FractureProblemTypeTag; +using MatrixFVGridGeometry = Dumux::GetPropType; +using FractureFVGridGeometry = Dumux::GetPropType; using TheMultiDomainTraits = Dumux::MultiDomainTraits; using TheCouplingMapper = Dumux::FacetCouplingMapper; using TheCouplingManager = Dumux::FacetCouplingManager; @@ -61,8 +61,13 @@ using TheCouplingManager = Dumux::FacetCouplingManager +struct CouplingManager { using type = TheCouplingManager; }; + +template +struct CouplingManager { using type = TheCouplingManager; }; + } // end namespace Properties } // end namespace Dumux @@ -85,8 +90,8 @@ int main(int argc, char** argv) try // This requires the grids used to be passed as template arguments, where // they are assumed to be ordered in descending grid dimension. Thus, // we pass the matrix grid as first and the fracture grid as second argument. - using MatrixGrid = typename GET_PROP_TYPE(MatrixTypeTag, Grid); - using FractureGrid = typename GET_PROP_TYPE(FractureTypeTag, Grid); + using MatrixGrid = GetPropType; + using FractureGrid = GetPropType; using GridManager = Dumux::FacetCouplingGridManager; GridManager gridManager; @@ -114,8 +119,8 @@ int main(int argc, char** argv) try fractureFvGridGeometry->update(); // the problems (boundary/initial conditions etc) - using MatrixProblem = typename GET_PROP_TYPE(MatrixTypeTag, Problem); - using FractureProblem = typename GET_PROP_TYPE(FractureTypeTag, Problem); + using MatrixProblem = GetPropType; + using FractureProblem = GetPropType; // pass the model parameter group to the spatial params so that they obtain the right // values from the input file since we use groups for matrix and fracture @@ -140,8 +145,8 @@ int main(int argc, char** argv) try // in case you have more subdomains involved. We domain ids // correspond to the order of the type tags passed to the multidomain // traits (see definition of the traits class at the beginning of this file) - static const auto matrixDomainId = typename TheMultiDomainTraits::template DomainIdx<0>(); - static const auto fractureDomainId = typename TheMultiDomainTraits::template DomainIdx<1>(); + static const auto matrixDomainId = typename TheMultiDomainTraits::template SubDomain<0>::Index(); + static const auto fractureDomainId = typename TheMultiDomainTraits::template SubDomain<1>::Index(); // resize the solution vector and write initial solution to it x[matrixDomainId].resize(matrixFvGridGeometry->numDofs()); @@ -167,23 +172,25 @@ int main(int argc, char** argv) try fractureProblem->setCouplingManager(couplingManager); // the grid variables - using MatrixGridVariables = typename GET_PROP_TYPE(MatrixTypeTag, GridVariables); - using FractureGridVariables = typename GET_PROP_TYPE(FractureTypeTag, GridVariables); + using MatrixGridVariables = GetPropType; + using FractureGridVariables = GetPropType; auto matrixGridVariables = std::make_shared(matrixProblem, matrixFvGridGeometry); auto fractureGridVariables = std::make_shared(fractureProblem, fractureFvGridGeometry); xOld = x; - matrixGridVariables->init(x[matrixDomainId], xOld[matrixDomainId]); - fractureGridVariables->init(x[fractureDomainId], xOld[fractureDomainId]); + matrixGridVariables->init(x[matrixDomainId]); + fractureGridVariables->init(x[fractureDomainId]); // intialize the vtk output modules - VtkOutputModule matrixVtkWriter(*matrixProblem, *matrixFvGridGeometry, *matrixGridVariables, x[matrixDomainId], matrixProblem->name()); - VtkOutputModule fractureVtkWriter(*fractureProblem, *fractureFvGridGeometry, *fractureGridVariables, x[fractureDomainId], fractureProblem->name()); + using MatrixVtkOutputModule = VtkOutputModule>; + using FractureVtkOutputModule = VtkOutputModule>; + MatrixVtkOutputModule matrixVtkWriter(*matrixGridVariables, x[matrixDomainId], matrixProblem->name()); + FractureVtkOutputModule fractureVtkWriter(*fractureGridVariables, x[fractureDomainId], fractureProblem->name()); // Add model specific output fields - using MatrixVtkOutputFields = typename GET_PROP_TYPE(MatrixTypeTag, VtkOutputFields); - using FractureVtkOutputFields = typename GET_PROP_TYPE(FractureTypeTag, VtkOutputFields); - MatrixVtkOutputFields::init(matrixVtkWriter); - FractureVtkOutputFields::init(fractureVtkWriter); + using MatrixVtkOutputFields = GetPropType; + using FractureVtkOutputFields = GetPropType; + MatrixVtkOutputFields::initOutputModule(matrixVtkWriter); + FractureVtkOutputFields::initOutputModule(fractureVtkWriter); // add domain markers to output std::vector matrixDomainMarkers(matrixFvGridGeometry->gridView().size(0)); diff --git a/exercises/exercise-fractures/fractureproblem.hh b/exercises/exercise-fractures/fractureproblem.hh index 297aa34..68153d2 100644 --- a/exercises/exercise-fractures/fractureproblem.hh +++ b/exercises/exercise-fractures/fractureproblem.hh @@ -48,24 +48,36 @@ namespace Dumux { template class FractureSubProblem; namespace Properties { -NEW_PROP_TAG(GridData); // forward declaration of property -// create the type tag nodes -NEW_TYPE_TAG(FractureProblemTypeTag, INHERITS_FROM(CCTpfaModel, TwoP)); +// Create new type tag node +namespace TTag { +struct FractureProblemTypeTag { using InheritsFrom = std::tuple; }; +} // end namespace TTag + // Set the grid type -SET_TYPE_PROP(FractureProblemTypeTag, Grid, Dune::FoamGrid<1, 2>); +template +struct Grid { using type = Dune::FoamGrid<1, 2>; }; + // Set the problem type -SET_TYPE_PROP(FractureProblemTypeTag, Problem, FractureSubProblem); +template +struct Problem { using type = FractureSubProblem; }; + // set the spatial params -SET_TYPE_PROP(FractureProblemTypeTag, - SpatialParams, - FractureSpatialParams< typename GET_PROP_TYPE(TypeTag, FVGridGeometry), - typename GET_PROP_TYPE(TypeTag, Scalar) >); +template +struct SpatialParams +{ + using type = FractureSpatialParams< GetPropType, + GetPropType >; +}; + // the fluid system -SET_TYPE_PROP(FractureProblemTypeTag, - FluidSystem, - Dumux::FluidSystems::H2ON2< typename GET_PROP_TYPE(TypeTag, Scalar), - FluidSystems::H2ON2DefaultPolicy >); +template +struct FluidSystem +{ + using type = Dumux::FluidSystems::H2ON2< GetPropType, + FluidSystems::H2ON2DefaultPolicy >; +}; + } // end namespace Properties /*! @@ -79,10 +91,10 @@ class FractureSubProblem : public PorousMediumFlowProblem { using ParentType = PorousMediumFlowProblem; - using BoundaryTypes = typename GET_PROP_TYPE(TypeTag, BoundaryTypes); - using CouplingManager = typename GET_PROP_TYPE(TypeTag, CouplingManager); - using NumEqVector = typename GET_PROP_TYPE(TypeTag, NumEqVector); - using GridVariables = typename GET_PROP_TYPE(TypeTag, GridVariables); + using BoundaryTypes = GetPropType; + using CouplingManager = GetPropType; + using NumEqVector = GetPropType; + using GridVariables = GetPropType; using ElementVolumeVariables = typename GridVariables::GridVolumeVariables::LocalView; using PrimaryVariables = typename GridVariables::PrimaryVariables; using Scalar = typename GridVariables::Scalar; @@ -95,7 +107,7 @@ class FractureSubProblem : public PorousMediumFlowProblem using GlobalPosition = typename Element::Geometry::GlobalCoordinate; // some indices for convenience - using Indices = typename GET_PROP_TYPE(TypeTag, ModelTraits)::Indices; + using Indices = typename GetPropType::Indices; enum { pressureIdx = Indices::pressureIdx, @@ -112,7 +124,7 @@ public: { // initialize the fluid system, i.e. the tabulation // of water properties. Use the default p/T ranges. - using FluidSystem = typename GET_PROP_TYPE(TypeTag, FluidSystem); + using FluidSystem = GetPropType; FluidSystem::init(); } diff --git a/exercises/exercise-fractures/matrixproblem.hh b/exercises/exercise-fractures/matrixproblem.hh index c4a8395..854902a 100644 --- a/exercises/exercise-fractures/matrixproblem.hh +++ b/exercises/exercise-fractures/matrixproblem.hh @@ -56,28 +56,36 @@ namespace Dumux { template class MatrixSubProblem; namespace Properties { -NEW_PROP_TAG(GridData); // forward declaration of property - -// create the type tag node for the matrix sub-problem -// We need to put the facet-coupling type tag after the physics-related type tag -// because it overwrites some of the properties inherited from "TwoP". This is -// necessary because we need e.g. a modified implementation of darcys law that -// evaluates the coupling conditions on faces that coincide with the fractures. -NEW_TYPE_TAG(MatrixProblemTypeTag, INHERITS_FROM(TwoP, CCTpfaFacetCouplingModel)); + +// create the type tag node +namespace TTag { +struct MatrixProblemTypeTag { using InheritsFrom = std::tuple; }; +} // end namespace TTag + // Set the grid type -SET_TYPE_PROP(MatrixProblemTypeTag, Grid, Dune::ALUGrid<2, 2, Dune::simplex, Dune::conforming>); +template +struct Grid { using type = Dune::ALUGrid<2, 2, Dune::simplex, Dune::conforming>; }; + // Set the problem type -SET_TYPE_PROP(MatrixProblemTypeTag, Problem, MatrixSubProblem); +template +struct Problem { using type = MatrixSubProblem; }; + // set the spatial params -SET_TYPE_PROP(MatrixProblemTypeTag, - SpatialParams, - MatrixSpatialParams< typename GET_PROP_TYPE(TypeTag, FVGridGeometry), - typename GET_PROP_TYPE(TypeTag, Scalar) >); +template +struct SpatialParams +{ + using type = MatrixSpatialParams< GetPropType, + GetPropType >; +}; + // the fluid system -SET_TYPE_PROP(MatrixProblemTypeTag, - FluidSystem, - Dumux::FluidSystems::H2ON2< typename GET_PROP_TYPE(TypeTag, Scalar), - FluidSystems::H2ON2DefaultPolicy >); +template +struct FluidSystem +{ + using type = Dumux::FluidSystems::H2ON2< GetPropType, + FluidSystems::H2ON2DefaultPolicy >; +}; + } // end namespace Properties /*! @@ -91,10 +99,10 @@ class MatrixSubProblem : public PorousMediumFlowProblem { using ParentType = PorousMediumFlowProblem; - using BoundaryTypes = typename GET_PROP_TYPE(TypeTag, BoundaryTypes); - using CouplingManager = typename GET_PROP_TYPE(TypeTag, CouplingManager); - using NumEqVector = typename GET_PROP_TYPE(TypeTag, NumEqVector); - using GridVariables = typename GET_PROP_TYPE(TypeTag, GridVariables); + using BoundaryTypes = GetPropType; + using CouplingManager = GetPropType; + using NumEqVector = GetPropType; + using GridVariables = GetPropType; using PrimaryVariables = typename GridVariables::PrimaryVariables; using Scalar = typename GridVariables::Scalar; @@ -107,7 +115,7 @@ class MatrixSubProblem : public PorousMediumFlowProblem using GlobalPosition = typename Element::Geometry::GlobalCoordinate; // some indices for convenience - using Indices = typename GET_PROP_TYPE(TypeTag, ModelTraits)::Indices; + using Indices = typename GetPropType::Indices; enum { pressureIdx = Indices::pressureIdx, @@ -125,7 +133,7 @@ public: { // initialize the fluid system, i.e. the tabulation // of water properties. Use the default p/T ranges. - using FluidSystem = typename GET_PROP_TYPE(TypeTag, FluidSystem); + using FluidSystem = GetPropType; FluidSystem::init(); } -- GitLab From e53d6fab3235c3b63b6ef8805e203c3e43c0de1e Mon Sep 17 00:00:00 2001 From: Kilian Weishaupt Date: Tue, 11 Dec 2018 18:46:33 +0100 Subject: [PATCH 15/25] [ff-pnm] Update second exercise --- exercises/exercise-coupling-ff-pm/README.md | 8 +- .../models/ex_models_coupling_ff-pm.cc | 73 +++++------ .../models/ex_models_coupling_ff-pm.input | 13 +- .../models/ex_models_ffproblem.hh | 87 +++++++------ .../models/ex_models_pmproblem.hh | 73 +++++------ .../models/ex_models_coupling_ff-pm.cc | 84 +++++------- .../models/ex_models_coupling_ff-pm.input | 5 +- .../models/ex_models_ffproblem.hh | 123 ++++++++++-------- .../models/ex_models_pmproblem.hh | 82 ++++++------ 9 files changed, 266 insertions(+), 282 deletions(-) diff --git a/exercises/exercise-coupling-ff-pm/README.md b/exercises/exercise-coupling-ff-pm/README.md index ec4e22a..f3d56c7 100644 --- a/exercises/exercise-coupling-ff-pm/README.md +++ b/exercises/exercise-coupling-ff-pm/README.md @@ -269,7 +269,7 @@ Finally we want to know the distribution of the water mass fluxes across the int Use the facilities therein to return the values of ...massCouplingCondition... from the `couplingManager` for each coupling scvf. Then the fluxes are visualized with gnuplot, when setting `Problem.PlotFluxes = true`. If the simulation is too fast, you can have a look at the flux*.png files after the simulation. -* You can use the property `Problem.PlotStorage = true` to see the temporal evolution of the evaporation rate +* You can use the parameter `Problem.PlotStorage = true` to see the temporal evolution of the evaporation rate and the cumulative water mass loss. Compile and run the simulation and take a look at the results. @@ -295,10 +295,6 @@ for this case the liquid saturation cannot serve as primary variable anymore. Ho manually adapting the primary variable states and values is inconvenient. [Class et al. (2002)](http://dx.doi.org/10.1016/S0309-1708(02)00014-3) describe an algorithm to switch the primary variables, if phases should appear or disappear during a simulation. -- Replace the current implementation of the Newton solver with the version which can handle - primary variable switches: `dumux/multidomain/privarswitchnewtonsolver.hh`. - You also have to uncomment the line containing the `PriVarSwitchTuple` and to overwrite - the last argument with the `PrimaryVariableSwitch` property from the Darcy model. Now you are able to simulate a complete drying of the porous medium. @@ -355,7 +351,7 @@ However, there is also a solution-dependent component of these interactions, e.g damping of the eddy viscosity toward the wall, the velocity gradient at the wall and inside the cells is needed. These dynamic interactions are to be updated by calling -```cpp +```cpp stokesProblem->updateDynamicWallProperties(stokesSol) ``` in the time loop (after `// update dynamic wall properties`). diff --git a/exercises/exercise-coupling-ff-pm/models/ex_models_coupling_ff-pm.cc b/exercises/exercise-coupling-ff-pm/models/ex_models_coupling_ff-pm.cc index b54ae19..8dc210c 100644 --- a/exercises/exercise-coupling-ff-pm/models/ex_models_coupling_ff-pm.cc +++ b/exercises/exercise-coupling-ff-pm/models/ex_models_coupling_ff-pm.cc @@ -34,11 +34,11 @@ #include #include #include -#include +#include #include #include #include -#include +#include #include #include #include @@ -55,15 +55,17 @@ namespace Dumux { namespace Properties { -SET_PROP(StokesTypeTag, CouplingManager) +template +struct CouplingManager { - using Traits = StaggeredMultiDomainTraits; + using Traits = StaggeredMultiDomainTraits; using type = Dumux::StokesDarcyCouplingManager; }; -SET_PROP(DarcyTypeTag, CouplingManager) +template +struct CouplingManager { - using Traits = StaggeredMultiDomainTraits; + using Traits = StaggeredMultiDomainTraits; using type = Dumux::StokesDarcyCouplingManager; }; @@ -85,16 +87,16 @@ int main(int argc, char** argv) try Parameters::init(argc, argv); // Define the sub problem type tags - using StokesTypeTag = TTAG(StokesTypeTag); - using DarcyTypeTag = TTAG(DarcyTypeTag); + using StokesTypeTag = Properties::TTag::StokesTypeTag; + using DarcyTypeTag = Properties::TTag::DarcyTypeTag; // try to create a grid (from the given grid file or the input file) // for both sub-domains - using DarcyGridManager = Dumux::GridManager; + using DarcyGridManager = Dumux::GridManager>; DarcyGridManager darcyGridManager; darcyGridManager.init("Darcy"); // pass parameter group - using StokesGridManager = Dumux::GridManager; + using StokesGridManager = Dumux::GridManager>; StokesGridManager stokesGridManager; stokesGridManager.init("Stokes"); // pass parameter group @@ -103,10 +105,10 @@ int main(int argc, char** argv) try const auto& stokesGridView = stokesGridManager.grid().leafGridView(); // create the finite volume grid geometry - using StokesFVGridGeometry = typename GET_PROP_TYPE(StokesTypeTag, FVGridGeometry); + using StokesFVGridGeometry = GetPropType; auto stokesFvGridGeometry = std::make_shared(stokesGridView); stokesFvGridGeometry->update(); - using DarcyFVGridGeometry = typename GET_PROP_TYPE(DarcyTypeTag, FVGridGeometry); + using DarcyFVGridGeometry = GetPropType; auto darcyFvGridGeometry = std::make_shared(darcyGridView); darcyFvGridGeometry->update(); @@ -122,27 +124,22 @@ int main(int argc, char** argv) try constexpr auto darcyIdx = CouplingManager::darcyIdx; // the problem (initial and boundary conditions) - using StokesProblem = typename GET_PROP_TYPE(StokesTypeTag, Problem); + using StokesProblem = GetPropType; auto stokesProblem = std::make_shared(stokesFvGridGeometry, couplingManager); - using DarcyProblem = typename GET_PROP_TYPE(DarcyTypeTag, Problem); + using DarcyProblem = GetPropType; auto darcyProblem = std::make_shared(darcyFvGridGeometry, couplingManager); // initialize the fluidsystem (tabulation) - GET_PROP_TYPE(StokesTypeTag, FluidSystem)::init(); + GetPropType::init(); // get some time loop parameters - using Scalar = typename GET_PROP_TYPE(StokesTypeTag, Scalar); + using Scalar = GetPropType; const auto tEnd = getParam("TimeLoop.TEnd"); const auto maxDt = getParam("TimeLoop.MaxTimeStepSize"); auto dt = getParam("TimeLoop.DtInitial"); - // check if we are about to restart a previously interrupted simulation - Scalar restartTime = 0; - if (Parameters::getTree().hasKey("Restart") || Parameters::getTree().hasKey("TimeLoop.Restart")) - restartTime = getParam("TimeLoop.Restart"); - // instantiate time loop - auto timeLoop = std::make_shared>(restartTime, dt, tEnd); + auto timeLoop = std::make_shared>(0, dt, tEnd); timeLoop->setMaxTimeStepSize(maxDt); stokesProblem->setTimeLoop(timeLoop); darcyProblem->setTimeLoop(timeLoop); @@ -153,43 +150,35 @@ int main(int argc, char** argv) try sol[stokesFaceIdx].resize(stokesFvGridGeometry->numFaceDofs()); sol[darcyIdx].resize(darcyFvGridGeometry->numDofs()); - const auto& cellCenterSol = sol[stokesCellCenterIdx]; - const auto& faceSol = sol[stokesFaceIdx]; + auto stokesSol = partial(sol, stokesCellCenterIdx, stokesFaceIdx); - // apply initial solution for instationary problems - typename GET_PROP_TYPE(StokesTypeTag, SolutionVector) stokesSol; - std::get<0>(stokesSol) = cellCenterSol; - std::get<1>(stokesSol) = faceSol; stokesProblem->applyInitialSolution(stokesSol); - auto solStokesOld = stokesSol; - sol[stokesCellCenterIdx] = stokesSol[stokesCellCenterIdx]; - sol[stokesFaceIdx] = stokesSol[stokesFaceIdx]; - darcyProblem->applyInitialSolution(sol[darcyIdx]); - auto solDarcyOld = sol[darcyIdx]; auto solOld = sol; couplingManager->init(stokesProblem, darcyProblem, sol); // the grid variables - using StokesGridVariables = typename GET_PROP_TYPE(StokesTypeTag, GridVariables); + using StokesGridVariables = GetPropType; auto stokesGridVariables = std::make_shared(stokesProblem, stokesFvGridGeometry); - stokesGridVariables->init(stokesSol, solStokesOld); - using DarcyGridVariables = typename GET_PROP_TYPE(DarcyTypeTag, GridVariables); + stokesGridVariables->init(stokesSol); + using DarcyGridVariables = GetPropType; auto darcyGridVariables = std::make_shared(darcyProblem, darcyFvGridGeometry); - darcyGridVariables->init(sol[darcyIdx], solDarcyOld); + darcyGridVariables->init(sol[darcyIdx]); // intialize the vtk output module const auto stokesName = getParam("Problem.Name") + "_" + stokesProblem->name(); const auto darcyName = getParam("Problem.Name") + "_" + darcyProblem->name(); - StaggeredVtkOutputModule stokesVtkWriter(*stokesProblem, *stokesFvGridGeometry, *stokesGridVariables, stokesSol, stokesName); - GET_PROP_TYPE(StokesTypeTag, VtkOutputFields)::init(stokesVtkWriter); + StaggeredVtkOutputModule stokesVtkWriter(*stokesGridVariables, stokesSol, stokesName); + GetPropType::initOutputModule(stokesVtkWriter); stokesVtkWriter.write(0.0); - VtkOutputModule darcyVtkWriter(*darcyProblem, *darcyFvGridGeometry, *darcyGridVariables, sol[darcyIdx], darcyName); - GET_PROP_TYPE(DarcyTypeTag, VtkOutputFields)::init(darcyVtkWriter); + VtkOutputModule> darcyVtkWriter(*darcyGridVariables, sol[darcyIdx], darcyName); + using DarcyVelocityOutput = GetPropType; + darcyVtkWriter.addVelocityOutput(std::make_shared(*darcyGridVariables)); + GetPropType::initOutputModule(darcyVtkWriter); darcyVtkWriter.write(0.0); // intialize the subproblems @@ -211,8 +200,6 @@ int main(int argc, char** argv) try using LinearSolver = UMFPackBackend; auto linearSolver = std::make_shared(); - // the primary variable switches used by the sub models and the non-linear solver -// using PriVarSwitchTuple = std::tuple; using NewtonSolver = MultiDomainNewtonSolver; NewtonSolver nonLinearSolver(assembler, linearSolver, couplingManager); diff --git a/exercises/exercise-coupling-ff-pm/models/ex_models_coupling_ff-pm.input b/exercises/exercise-coupling-ff-pm/models/ex_models_coupling_ff-pm.input index d3f6851..07bb4dd 100644 --- a/exercises/exercise-coupling-ff-pm/models/ex_models_coupling_ff-pm.input +++ b/exercises/exercise-coupling-ff-pm/models/ex_models_coupling_ff-pm.input @@ -1,5 +1,5 @@ [TimeLoop] -DtInitial = 100 # s +DtInitial = 1 # s EpisodeLength = -360 # s # 0.25 days TEnd = 256000 # s # 2 days @@ -14,10 +14,11 @@ Cells = 16 16 [Stokes.Problem] Name = stokes -EnableGravity = false +EnableGravity = true +EnableInertiaTerms = true MoleFraction = 0.0 # - Pressure = 1e5 # Pa -Velocity = 1e-3 # m/s +Velocity = 1 # m/s [Darcy.Problem] Name = darcy @@ -43,7 +44,11 @@ PlotStorage = false [Newton] MaxSteps = 12 -MaxRelativeShift = 1e-5 +MaxRelativeShift = 1e-7 +TargetSteps = 5 [Vtk] AddVelocity = 1 + +[Assembly] +NumericDifference.BaseEpsilon = 1e-8 diff --git a/exercises/exercise-coupling-ff-pm/models/ex_models_ffproblem.hh b/exercises/exercise-coupling-ff-pm/models/ex_models_ffproblem.hh index 1fe98c0..6f00aa1 100644 --- a/exercises/exercise-coupling-ff-pm/models/ex_models_ffproblem.hh +++ b/exercises/exercise-coupling-ff-pm/models/ex_models_ffproblem.hh @@ -40,32 +40,41 @@ class StokesSubProblem; namespace Properties { -NEW_TYPE_TAG(StokesTypeTag, INHERITS_FROM(StaggeredFreeFlowModel, NavierStokesNC)); +// Create new type tags +namespace TTag { +struct StokesTypeTag { using InheritsFrom = std::tuple; }; +} // end namespace TTag // Set the grid type -SET_TYPE_PROP(StokesTypeTag, Grid, Dune::YaspGrid<2, Dune::EquidistantOffsetCoordinates >); +template +struct Grid { using type = Dune::YaspGrid<2, Dune::EquidistantOffsetCoordinates, 2> >; }; // The fluid system -SET_PROP(StokesTypeTag, FluidSystem) +template +struct FluidSystem { - using H2OAir = FluidSystems::H2OAir; + using H2OAir = FluidSystems::H2OAir>; using type = FluidSystems::OnePAdapter; }; // Do not replace one equation with a total mass balance -SET_INT_PROP(StokesTypeTag, ReplaceCompEqIdx, 3); +template +struct ReplaceCompEqIdx { static constexpr int value = 3; }; // Use formulation based on mass fractions -SET_BOOL_PROP(StokesTypeTag, UseMoles, true); +template +struct UseMoles { static constexpr bool value = true; }; // Set the problem property -SET_TYPE_PROP(StokesTypeTag, Problem, Dumux::StokesSubProblem ); - -SET_BOOL_PROP(StokesTypeTag, EnableFVGridGeometryCache, true); -SET_BOOL_PROP(StokesTypeTag, EnableGridFluxVariablesCache, true); -SET_BOOL_PROP(StokesTypeTag, EnableGridVolumeVariablesCache, true); - -SET_BOOL_PROP(StokesTypeTag, EnableInertiaTerms, false); +template +struct Problem { using type = Dumux::StokesSubProblem ; }; + +template +struct EnableFVGridGeometryCache { static constexpr bool value = true; }; +template +struct EnableGridFluxVariablesCache { static constexpr bool value = true; }; +template +struct EnableGridVolumeVariablesCache { static constexpr bool value = true; }; } /*! @@ -79,29 +88,29 @@ class StokesSubProblem : public NavierStokesProblem { using ParentType = NavierStokesProblem; - using GridView = typename GET_PROP_TYPE(TypeTag, GridView); - using Scalar = typename GET_PROP_TYPE(TypeTag, Scalar); - using FluidSystem = typename GET_PROP_TYPE(TypeTag, FluidSystem); - using Indices = typename GET_PROP_TYPE(TypeTag, ModelTraits)::Indices; - using BoundaryTypes = typename GET_PROP_TYPE(TypeTag, BoundaryTypes); + using GridView = GetPropType; + using Scalar = GetPropType; + using FluidSystem = GetPropType; + using Indices = typename GetPropType::Indices; + using BoundaryTypes = GetPropType; - using FVGridGeometry = typename GET_PROP_TYPE(TypeTag, FVGridGeometry); + using FVGridGeometry = GetPropType; using FVElementGeometry = typename FVGridGeometry::LocalView; using SubControlVolumeFace = typename FVElementGeometry::SubControlVolumeFace; using Element = typename GridView::template Codim<0>::Entity; - using ElementVolumeVariables = typename GET_PROP_TYPE(TypeTag, GridVolumeVariables)::LocalView; - using ElementFaceVariables = typename GET_PROP_TYPE(TypeTag, GridFaceVariables)::LocalView; - using FluidState = typename GET_PROP_TYPE(TypeTag, FluidState); + using ElementVolumeVariables = typename GetPropType::LocalView; + using ElementFaceVariables = typename GetPropType::LocalView; + using FluidState = GetPropType; using GlobalPosition = typename Element::Geometry::GlobalCoordinate; - using PrimaryVariables = typename GET_PROP_TYPE(TypeTag, PrimaryVariables); - using NumEqVector = typename GET_PROP_TYPE(TypeTag, NumEqVector); + using PrimaryVariables = GetPropType; + using NumEqVector = GetPropType; - using CouplingManager = typename GET_PROP_TYPE(TypeTag, CouplingManager); + using CouplingManager = GetPropType; using TimeLoopPtr = std::shared_ptr>; - static constexpr bool useMoles = GET_PROP_TYPE(TypeTag, ModelTraits)::useMoles(); + static constexpr bool useMoles = GetPropType::useMoles(); public: StokesSubProblem(std::shared_ptr fvGridGeometry, std::shared_ptr couplingManager) @@ -117,10 +126,6 @@ public: */ // \{ - - bool shouldWriteRestartFile() const - { return false; } - /*! * \brief Return the temperature within the domain in [K]. */ @@ -218,9 +223,9 @@ public: if(couplingManager().isCoupledEntity(CouplingManager::stokesIdx, scvf)) { - values[Indices::momentumYBalanceIdx] = couplingManager().couplingData().momentumCouplingCondition(fvGeometry, elemVolVars, elemFaceVars, scvf); + values[Indices::momentumYBalanceIdx] = couplingManager().couplingData().momentumCouplingCondition(element, fvGeometry, elemVolVars, elemFaceVars, scvf); - const auto massFlux = couplingManager().couplingData().massCouplingCondition(fvGeometry, elemVolVars, elemFaceVars, scvf); + const auto massFlux = couplingManager().couplingData().massCouplingCondition(element, fvGeometry, elemVolVars, elemFaceVars, scvf); values[Indices::conti0EqIdx] = massFlux[0]; values[Indices::conti0EqIdx + 1] = massFlux[1]; } @@ -251,14 +256,22 @@ public: * * \param globalPos The global position */ - PrimaryVariables initialAtPos(const GlobalPosition &globalPos) const + PrimaryVariables initialAtPos(const GlobalPosition& globalPos) const { + PrimaryVariables values(0.0); + + // This is only an approximation of the actual hydorostatic pressure gradient. + // Air is compressible (the density depends on pressure), thus the actual + // vertical pressure profile is non-linear. + // This discrepancy can lead to spurious flows at the outlet if the inlet + // velocity is chosen too small. FluidState fluidState; updateFluidStateForBC_(fluidState, pressure_); const Scalar density = FluidSystem::density(fluidState, 0); + values[Indices::pressureIdx] = pressure_ - density*this->gravity()[1]*(this->fvGridGeometry().bBoxMax()[1] - globalPos[1]); - PrimaryVariables values(0.0); - values[Indices::pressureIdx] = pressure_ + density*this->gravity()[1]*(globalPos[1] - this->fvGridGeometry().bBoxMin()[1]); + + // gravity has negative sign values[Indices::conti0EqIdx + 1] = moleFraction_; values[Indices::velocityXIdx] = 4.0 * velocity_ * (globalPos[1] - this->fvGridGeometry().bBoxMin()[1]) * (this->fvGridGeometry().bBoxMax()[1] - globalPos[1]) @@ -273,9 +286,9 @@ public: /*! * \brief Returns the intrinsic permeability of required as input parameter for the Beavers-Joseph-Saffman boundary condition */ - Scalar permeability(const SubControlVolumeFace& scvf) const + Scalar permeability(const Element& element, const SubControlVolumeFace& scvf) const { - return couplingManager().couplingData().darcyPermeability(scvf); + return couplingManager().couplingData().darcyPermeability(element, scvf); } /*! diff --git a/exercises/exercise-coupling-ff-pm/models/ex_models_pmproblem.hh b/exercises/exercise-coupling-ff-pm/models/ex_models_pmproblem.hh index c20e9e4..fb4f258 100644 --- a/exercises/exercise-coupling-ff-pm/models/ex_models_pmproblem.hh +++ b/exercises/exercise-coupling-ff-pm/models/ex_models_pmproblem.hh @@ -44,52 +44,61 @@ class DarcySubProblem; namespace Properties { -NEW_TYPE_TAG(DarcyTypeTag, INHERITS_FROM(CCTpfaModel, OnePNC)); +// Create new type tags +namespace TTag { +struct DarcyTypeTag { using InheritsFrom = std::tuple; }; +} // end namespace TTag // Set the problem property -SET_TYPE_PROP(DarcyTypeTag, Problem, Dumux::DarcySubProblem); +template +struct Problem { using type = Dumux::DarcySubProblem; }; // The fluid system -SET_PROP(DarcyTypeTag, FluidSystem) +template +struct FluidSystem { - using H2OAir = FluidSystems::H2OAir; + using H2OAir = FluidSystems::H2OAir>; using type = FluidSystems::OnePAdapter; }; // Use moles -SET_BOOL_PROP(DarcyTypeTag, UseMoles, true); +template +struct UseMoles { static constexpr bool value = true; }; // Do not replace one equation with a total mass balance -SET_INT_PROP(DarcyTypeTag, ReplaceCompEqIdx, 3); +template +struct ReplaceCompEqIdx { static constexpr int value = 3; }; //! Use a model with constant tortuosity for the effective diffusivity SET_TYPE_PROP(DarcyTypeTag, EffectiveDiffusivityModel, - DiffusivityConstantTortuosity); + DiffusivityConstantTortuosity>); // Set the grid type -SET_TYPE_PROP(DarcyTypeTag, Grid, Dune::YaspGrid<2>); +template +struct Grid { using type = Dune::YaspGrid<2>; }; // Set the spatial paramaters type -SET_TYPE_PROP(DarcyTypeTag, SpatialParams, OnePSpatialParams); +template +struct SpatialParams { using type = OnePSpatialParams; }; } template class DarcySubProblem : public PorousMediumFlowProblem { using ParentType = PorousMediumFlowProblem; - using GridView = typename GET_PROP_TYPE(TypeTag, GridView); - using Scalar = typename GET_PROP_TYPE(TypeTag, Scalar); - using PrimaryVariables = typename GET_PROP_TYPE(TypeTag, PrimaryVariables); - using FluidSystem = typename GET_PROP_TYPE(TypeTag, FluidSystem); - using NumEqVector = typename GET_PROP_TYPE(TypeTag, NumEqVector); - using BoundaryTypes = typename GET_PROP_TYPE(TypeTag, BoundaryTypes); - using FVElementGeometry = typename GET_PROP_TYPE(TypeTag, FVGridGeometry)::LocalView; + using GridView = GetPropType; + using Scalar = GetPropType; + using PrimaryVariables = GetPropType; + using FluidSystem = GetPropType; + using NumEqVector = GetPropType; + using BoundaryTypes = GetPropType; + using FVElementGeometry = typename GetPropType::LocalView; using SubControlVolume = typename FVElementGeometry::SubControlVolume; using SubControlVolumeFace = typename FVElementGeometry::SubControlVolumeFace; - using FVGridGeometry = typename GET_PROP_TYPE(TypeTag, FVGridGeometry); + using FVGridGeometry = GetPropType; // copy some indices for convenience - using Indices = typename GET_PROP_TYPE(TypeTag, ModelTraits)::Indices; + using Indices = typename GetPropType::Indices; enum { // grid and world dimension dim = GridView::dimension, @@ -105,7 +114,7 @@ class DarcySubProblem : public PorousMediumFlowProblem using Element = typename GridView::template Codim<0>::Entity; using GlobalPosition = Dune::FieldVector; - using CouplingManager = typename GET_PROP_TYPE(TypeTag, CouplingManager); + using CouplingManager = GetPropType; using TimeLoopPtr = std::shared_ptr>; public: @@ -114,7 +123,6 @@ public: : ParentType(fvGridGeometry, "Darcy"), eps_(1e-7), couplingManager_(couplingManager) { moleFraction_ = getParamFromGroup(this->paramGroup(), "Problem.MoleFraction"); - pressure_ = getParamFromGroup(this->paramGroup(), "Problem.Pressure"); // initialize output file plotFluxes_ = getParamFromGroup(this->paramGroup(), "Problem.PlotFluxes", false); @@ -224,8 +232,6 @@ public: if (!couplingManager().isCoupledEntity(CouplingManager::darcyIdx, scvf)) continue; - // NOTE: binding the coupling context is necessary - couplingManager_->bindCouplingContext(CouplingManager::darcyIdx, element); NumEqVector flux(0.0); // use "massCouplingCondition" from the couplingManager here x.push_back(scvf.center()[0]); @@ -246,21 +252,11 @@ public: gnuplotInterfaceFluxes_.plot("flux_" + std::to_string(timeLoop_->timeStepIndex())); } - /*! - * \brief Returns true if a restart file should be written to - * disk. - */ - bool shouldWriteRestartFile() const - { return false; } - /*! * \name Problem parameters */ // \{ - bool shouldWriteOutput() const // define output - { return true; } - /*! * \brief Return the temperature within the domain in [K]. * @@ -311,7 +307,7 @@ public: NumEqVector values(0.0); if (couplingManager().isCoupledEntity(CouplingManager::darcyIdx, scvf)) - values = couplingManager().couplingData().massCouplingCondition(fvGeometry, elemVolVars, scvf); + values = couplingManager().couplingData().massCouplingCondition(element, fvGeometry, elemVolVars, scvf); return values; } @@ -332,10 +328,10 @@ public: * \param scv The subcontrolvolume */ template - NumEqVector source(const Element &element, + NumEqVector source(const Element& element, const FVElementGeometry& fvGeometry, const ElementVolumeVariables& elemVolVars, - const SubControlVolume &scv) const + const SubControlVolume& scv) const { return NumEqVector(0.0); } // \} @@ -348,11 +344,13 @@ public: * For this method, the \a priVars parameter stores primary * variables. */ - PrimaryVariables initialAtPos(const GlobalPosition &globalPos) const + PrimaryVariables initialAtPos(const GlobalPosition& globalPos) const { + static const Scalar stokesPressure = getParamFromGroup("Stokes", "Problem.Pressure"); + PrimaryVariables values(0.0); + values[Indices::pressureIdx] = stokesPressure; values[transportCompIdx] = moleFraction_; - values[pressureIdx] = pressure_; return values; } @@ -384,7 +382,6 @@ private: Scalar eps_; Scalar moleFraction_; - Scalar pressure_; Scalar initialWaterContent_ = 0.0; Scalar lastWaterMass_ = 0.0; diff --git a/exercises/solution/exercise-coupling-ff-pm/models/ex_models_coupling_ff-pm.cc b/exercises/solution/exercise-coupling-ff-pm/models/ex_models_coupling_ff-pm.cc index cdb7abd..8528aeb 100644 --- a/exercises/solution/exercise-coupling-ff-pm/models/ex_models_coupling_ff-pm.cc +++ b/exercises/solution/exercise-coupling-ff-pm/models/ex_models_coupling_ff-pm.cc @@ -34,22 +34,18 @@ #include #include #include -#include +#include #include #include #include -#include +#include #include #include #include #include #include -#if EXNUMBER >= 3 -#include -#else #include -#endif #include @@ -59,15 +55,17 @@ namespace Dumux { namespace Properties { -SET_PROP(StokesTypeTag, CouplingManager) +template +struct CouplingManager { - using Traits = StaggeredMultiDomainTraits; + using Traits = StaggeredMultiDomainTraits; using type = Dumux::StokesDarcyCouplingManager; }; -SET_PROP(DarcyTypeTag, CouplingManager) +template +struct CouplingManager { - using Traits = StaggeredMultiDomainTraits; + using Traits = StaggeredMultiDomainTraits; using type = Dumux::StokesDarcyCouplingManager; }; @@ -89,16 +87,16 @@ int main(int argc, char** argv) try Parameters::init(argc, argv); // Define the sub problem type tags - using StokesTypeTag = TTAG(StokesTypeTag); - using DarcyTypeTag = TTAG(DarcyTypeTag); + using StokesTypeTag = Properties::TTag::StokesTypeTag; + using DarcyTypeTag = Properties::TTag::DarcyTypeTag; // try to create a grid (from the given grid file or the input file) // for both sub-domains - using DarcyGridManager = Dumux::GridManager; + using DarcyGridManager = Dumux::GridManager>; DarcyGridManager darcyGridManager; darcyGridManager.init("Darcy"); // pass parameter group - using StokesGridManager = Dumux::GridManager; + using StokesGridManager = Dumux::GridManager>; StokesGridManager stokesGridManager; stokesGridManager.init("Stokes"); // pass parameter group @@ -107,10 +105,10 @@ int main(int argc, char** argv) try const auto& stokesGridView = stokesGridManager.grid().leafGridView(); // create the finite volume grid geometry - using StokesFVGridGeometry = typename GET_PROP_TYPE(StokesTypeTag, FVGridGeometry); + using StokesFVGridGeometry = GetPropType; auto stokesFvGridGeometry = std::make_shared(stokesGridView); stokesFvGridGeometry->update(); - using DarcyFVGridGeometry = typename GET_PROP_TYPE(DarcyTypeTag, FVGridGeometry); + using DarcyFVGridGeometry = GetPropType; auto darcyFvGridGeometry = std::make_shared(darcyGridView); darcyFvGridGeometry->update(); @@ -126,27 +124,22 @@ int main(int argc, char** argv) try constexpr auto darcyIdx = CouplingManager::darcyIdx; // the problem (initial and boundary conditions) - using StokesProblem = typename GET_PROP_TYPE(StokesTypeTag, Problem); + using StokesProblem = GetPropType; auto stokesProblem = std::make_shared(stokesFvGridGeometry, couplingManager); - using DarcyProblem = typename GET_PROP_TYPE(DarcyTypeTag, Problem); + using DarcyProblem = GetPropType; auto darcyProblem = std::make_shared(darcyFvGridGeometry, couplingManager); // initialize the fluidsystem (tabulation) - GET_PROP_TYPE(StokesTypeTag, FluidSystem)::init(); + GetPropType::init(); // get some time loop parameters - using Scalar = typename GET_PROP_TYPE(StokesTypeTag, Scalar); + using Scalar = GetPropType; const auto tEnd = getParam("TimeLoop.TEnd"); const auto maxDt = getParam("TimeLoop.MaxTimeStepSize"); auto dt = getParam("TimeLoop.DtInitial"); - // check if we are about to restart a previously interrupted simulation - Scalar restartTime = 0; - if (Parameters::getTree().hasKey("Restart") || Parameters::getTree().hasKey("TimeLoop.Restart")) - restartTime = getParam("TimeLoop.Restart"); - // instantiate time loop - auto timeLoop = std::make_shared>(restartTime, dt, tEnd); + auto timeLoop = std::make_shared>(0, dt, tEnd); timeLoop->setMaxTimeStepSize(maxDt); stokesProblem->setTimeLoop(timeLoop); darcyProblem->setTimeLoop(timeLoop); @@ -157,32 +150,22 @@ int main(int argc, char** argv) try sol[stokesFaceIdx].resize(stokesFvGridGeometry->numFaceDofs()); sol[darcyIdx].resize(darcyFvGridGeometry->numDofs()); - const auto& cellCenterSol = sol[stokesCellCenterIdx]; - const auto& faceSol = sol[stokesFaceIdx]; + auto stokesSol = partial(sol, stokesCellCenterIdx, stokesFaceIdx); - // apply initial solution for instationary problems - typename GET_PROP_TYPE(StokesTypeTag, SolutionVector) stokesSol; - std::get<0>(stokesSol) = cellCenterSol; - std::get<1>(stokesSol) = faceSol; stokesProblem->applyInitialSolution(stokesSol); - auto solStokesOld = stokesSol; - sol[stokesCellCenterIdx] = stokesSol[stokesCellCenterIdx]; - sol[stokesFaceIdx] = stokesSol[stokesFaceIdx]; - darcyProblem->applyInitialSolution(sol[darcyIdx]); - auto solDarcyOld = sol[darcyIdx]; auto solOld = sol; couplingManager->init(stokesProblem, darcyProblem, sol); // the grid variables - using StokesGridVariables = typename GET_PROP_TYPE(StokesTypeTag, GridVariables); + using StokesGridVariables = GetPropType; auto stokesGridVariables = std::make_shared(stokesProblem, stokesFvGridGeometry); - stokesGridVariables->init(stokesSol, solStokesOld); - using DarcyGridVariables = typename GET_PROP_TYPE(DarcyTypeTag, GridVariables); + stokesGridVariables->init(stokesSol); + using DarcyGridVariables = GetPropType; auto darcyGridVariables = std::make_shared(darcyProblem, darcyFvGridGeometry); - darcyGridVariables->init(sol[darcyIdx], solDarcyOld); + darcyGridVariables->init(sol[darcyIdx]); // intialize the vtk output module #if EXNUMBER >= 1 @@ -194,12 +177,14 @@ int main(int argc, char** argv) try const auto darcyName = "orig_" + getParam("Problem.Name") + "_" + darcyProblem->name(); #endif - StaggeredVtkOutputModule stokesVtkWriter(*stokesProblem, *stokesFvGridGeometry, *stokesGridVariables, stokesSol, stokesName); - GET_PROP_TYPE(StokesTypeTag, VtkOutputFields)::init(stokesVtkWriter); - stokesVtkWriter.write(0.0); + StaggeredVtkOutputModule stokesVtkWriter(*stokesGridVariables, stokesSol, stokesName); + GetPropType::initOutputModule(stokesVtkWriter); + stokesVtkWriter.write(0); - VtkOutputModule darcyVtkWriter(*darcyProblem, *darcyFvGridGeometry, *darcyGridVariables, sol[darcyIdx], darcyName); - GET_PROP_TYPE(DarcyTypeTag, VtkOutputFields)::init(darcyVtkWriter); + VtkOutputModule> darcyVtkWriter(*darcyGridVariables, sol[darcyIdx], darcyName); + using DarcyVelocityOutput = GetPropType; + darcyVtkWriter.addVelocityOutput(std::make_shared(*darcyGridVariables)); + GetPropType::initOutputModule(darcyVtkWriter); darcyVtkWriter.write(0.0); // intialize the subproblems @@ -221,14 +206,7 @@ int main(int argc, char** argv) try using LinearSolver = UMFPackBackend; auto linearSolver = std::make_shared(); - // the primary variable switches used by the sub models and the non-linear solver -#if EXNUMBER >= 3 - using PriVarSwitchTuple = std::tuple; - using NewtonSolver = MultiDomainPriVarSwitchNewtonSolver; -#else -// using PriVarSwitchTuple = std::tuple; using NewtonSolver = MultiDomainNewtonSolver; -#endif NewtonSolver nonLinearSolver(assembler, linearSolver, couplingManager); // time loop diff --git a/exercises/solution/exercise-coupling-ff-pm/models/ex_models_coupling_ff-pm.input b/exercises/solution/exercise-coupling-ff-pm/models/ex_models_coupling_ff-pm.input index 8d08fe8..1b0a62a 100644 --- a/exercises/solution/exercise-coupling-ff-pm/models/ex_models_coupling_ff-pm.input +++ b/exercises/solution/exercise-coupling-ff-pm/models/ex_models_coupling_ff-pm.input @@ -14,10 +14,11 @@ Cells = 16 16 [Stokes.Problem] Name = stokes -EnableGravity = false +EnableGravity = true +EnableInertiaTerms = true MoleFraction = 0.0 # - Pressure = 1e5 # Pa -Velocity = 1e-3 # m/s +Velocity = 1 # m/s [Darcy.Problem] Name = darcy diff --git a/exercises/solution/exercise-coupling-ff-pm/models/ex_models_ffproblem.hh b/exercises/solution/exercise-coupling-ff-pm/models/ex_models_ffproblem.hh index 3d59b25..ae63df0 100644 --- a/exercises/solution/exercise-coupling-ff-pm/models/ex_models_ffproblem.hh +++ b/exercises/solution/exercise-coupling-ff-pm/models/ex_models_ffproblem.hh @@ -40,32 +40,41 @@ class StokesSubProblem; namespace Properties { -NEW_TYPE_TAG(StokesTypeTag, INHERITS_FROM(StaggeredFreeFlowModel, NavierStokesNC)); +// Create new type tags +namespace TTag { +struct StokesTypeTag { using InheritsFrom = std::tuple; }; +} // end namespace TTag // Set the grid type -SET_TYPE_PROP(StokesTypeTag, Grid, Dune::YaspGrid<2, Dune::EquidistantOffsetCoordinates >); +template +struct Grid { using type = Dune::YaspGrid<2, Dune::EquidistantOffsetCoordinates, 2> >; }; // The fluid system -SET_PROP(StokesTypeTag, FluidSystem) +template +struct FluidSystem { - using H2OAir = FluidSystems::H2OAir; + using H2OAir = FluidSystems::H2OAir>; using type = FluidSystems::OnePAdapter; }; // Do not replace one equation with a total mass balance -SET_INT_PROP(StokesTypeTag, ReplaceCompEqIdx, 3); +template +struct ReplaceCompEqIdx { static constexpr int value = 3; }; // Use formulation based on mass fractions -SET_BOOL_PROP(StokesTypeTag, UseMoles, true); +template +struct UseMoles { static constexpr bool value = true; }; // Set the problem property -SET_TYPE_PROP(StokesTypeTag, Problem, Dumux::StokesSubProblem ); - -SET_BOOL_PROP(StokesTypeTag, EnableFVGridGeometryCache, true); -SET_BOOL_PROP(StokesTypeTag, EnableGridFluxVariablesCache, true); -SET_BOOL_PROP(StokesTypeTag, EnableGridVolumeVariablesCache, true); - -SET_BOOL_PROP(StokesTypeTag, EnableInertiaTerms, false); +template +struct Problem { using type = Dumux::StokesSubProblem ; }; + +template +struct EnableFVGridGeometryCache { static constexpr bool value = true; }; +template +struct EnableGridFluxVariablesCache { static constexpr bool value = true; }; +template +struct EnableGridVolumeVariablesCache { static constexpr bool value = true; }; } /*! @@ -79,31 +88,31 @@ class StokesSubProblem : public NavierStokesProblem { using ParentType = NavierStokesProblem; - using GridView = typename GET_PROP_TYPE(TypeTag, GridView); - using Scalar = typename GET_PROP_TYPE(TypeTag, Scalar); - using FluidSystem = typename GET_PROP_TYPE(TypeTag, FluidSystem); - using Indices = typename GET_PROP_TYPE(TypeTag, ModelTraits)::Indices; - using BoundaryTypes = typename GET_PROP_TYPE(TypeTag, BoundaryTypes); + using GridView = GetPropType; + using Scalar = GetPropType; + using FluidSystem = GetPropType; + using Indices = typename GetPropType::Indices; + using BoundaryTypes = GetPropType; - using FVGridGeometry = typename GET_PROP_TYPE(TypeTag, FVGridGeometry); + using FVGridGeometry = GetPropType; using FVElementGeometry = typename FVGridGeometry::LocalView; using SubControlVolumeFace = typename FVElementGeometry::SubControlVolumeFace; using Element = typename GridView::template Codim<0>::Entity; - using ElementVolumeVariables = typename GET_PROP_TYPE(TypeTag, GridVolumeVariables)::LocalView; - using ElementFaceVariables = typename GET_PROP_TYPE(TypeTag, GridFaceVariables)::LocalView; - using FluidState = typename GET_PROP_TYPE(TypeTag, FluidState); + using ElementVolumeVariables = typename GetPropType::LocalView; + using ElementFaceVariables = typename GetPropType::LocalView; + using FluidState = GetPropType; using GlobalPosition = typename Element::Geometry::GlobalCoordinate; - using PrimaryVariables = typename GET_PROP_TYPE(TypeTag, PrimaryVariables); - using NumEqVector = typename GET_PROP_TYPE(TypeTag, NumEqVector); + using PrimaryVariables = GetPropType; + using NumEqVector = GetPropType; - using CouplingManager = typename GET_PROP_TYPE(TypeTag, CouplingManager); + using CouplingManager = GetPropType; using TimeLoopPtr = std::shared_ptr>; - static constexpr bool useMoles = GET_PROP_TYPE(TypeTag, ModelTraits)::useMoles(); + static constexpr bool useMoles = GetPropType::useMoles(); - static constexpr auto dim = GET_PROP_TYPE(TypeTag, ModelTraits)::dim(); + static constexpr auto dim = GetPropType::dim(); static constexpr auto transportCompIdx = 1; public: @@ -120,10 +129,6 @@ public: */ // \{ - - bool shouldWriteRestartFile() const - { return false; } - /*! * \brief Return the temperature within the domain in [K]. */ @@ -221,9 +226,9 @@ public: if(couplingManager().isCoupledEntity(CouplingManager::stokesIdx, scvf)) { - values[Indices::momentumYBalanceIdx] = couplingManager().couplingData().momentumCouplingCondition(fvGeometry, elemVolVars, elemFaceVars, scvf); + values[Indices::momentumYBalanceIdx] = couplingManager().couplingData().momentumCouplingCondition(element, fvGeometry, elemVolVars, elemFaceVars, scvf); - const auto massFlux = couplingManager().couplingData().massCouplingCondition(fvGeometry, elemVolVars, elemFaceVars, scvf); + const auto massFlux = couplingManager().couplingData().massCouplingCondition(element, fvGeometry, elemVolVars, elemFaceVars, scvf); values[Indices::conti0EqIdx] = massFlux[0]; values[Indices::conti0EqIdx + 1] = massFlux[1]; } @@ -249,26 +254,34 @@ public: */ // \{ - /*! - * \brief Evaluate the initial value for a control volume. - * - * \param globalPos The global position - */ - PrimaryVariables initialAtPos(const GlobalPosition &globalPos) const - { - FluidState fluidState; - updateFluidStateForBC_(fluidState, pressure_); - const Scalar density = FluidSystem::density(fluidState, 0); - - PrimaryVariables values(0.0); - values[Indices::pressureIdx] = pressure_ + density*this->gravity()[1]*(globalPos[1] - this->fvGridGeometry().bBoxMin()[1]); - values[Indices::conti0EqIdx + 1] = moleFraction_; - values[Indices::velocityXIdx] = 4.0 * velocity_ * (globalPos[1] - this->fvGridGeometry().bBoxMin()[1]) - * (this->fvGridGeometry().bBoxMax()[1] - globalPos[1]) - / (height_() * height_()); - - return values; - } + /*! + * \brief Evaluate the initial value for a control volume. + * + * \param globalPos The global position + */ + PrimaryVariables initialAtPos(const GlobalPosition& globalPos) const + { + PrimaryVariables values(0.0); + + // This is only an approximation of the actual hydorostatic pressure gradient. + // Air is compressible (the density depends on pressure), thus the actual + // vertical pressure profile is non-linear. + // This discrepancy can lead to spurious flows at the outlet if the inlet + // velocity is chosen too small. + FluidState fluidState; + updateFluidStateForBC_(fluidState, pressure_); + const Scalar density = FluidSystem::density(fluidState, 0); + values[Indices::pressureIdx] = pressure_ - density*this->gravity()[1]*(this->fvGridGeometry().bBoxMax()[1] - globalPos[1]); + + + // gravity has negative sign + values[Indices::conti0EqIdx + 1] = moleFraction_; + values[Indices::velocityXIdx] = 4.0 * velocity_ * (globalPos[1] - this->fvGridGeometry().bBoxMin()[1]) + * (this->fvGridGeometry().bBoxMax()[1] - globalPos[1]) + / (height_() * height_()); + + return values; + } void setTimeLoop(TimeLoopPtr timeLoop) { timeLoop_ = timeLoop; } @@ -276,9 +289,9 @@ public: /*! * \brief Returns the intrinsic permeability of required as input parameter for the Beavers-Joseph-Saffman boundary condition */ - Scalar permeability(const SubControlVolumeFace& scvf) const + Scalar permeability(const Element& element, const SubControlVolumeFace& scvf) const { - return couplingManager().couplingData().darcyPermeability(scvf); + return couplingManager().couplingData().darcyPermeability(element, scvf); } /*! diff --git a/exercises/solution/exercise-coupling-ff-pm/models/ex_models_pmproblem.hh b/exercises/solution/exercise-coupling-ff-pm/models/ex_models_pmproblem.hh index b2d951b..cb79f6a 100644 --- a/exercises/solution/exercise-coupling-ff-pm/models/ex_models_pmproblem.hh +++ b/exercises/solution/exercise-coupling-ff-pm/models/ex_models_pmproblem.hh @@ -49,19 +49,24 @@ class DarcySubProblem; namespace Properties { +// Create new type tags +namespace TTag { #if EXNUMBER >= 1 -NEW_TYPE_TAG(DarcyTypeTag, INHERITS_FROM(CCTpfaModel, TwoPNC)); +struct DarcyTypeTag { using InheritsFrom = std::tuple; }; #else -NEW_TYPE_TAG(DarcyTypeTag, INHERITS_FROM(CCTpfaModel, OnePNC)); +struct DarcyTypeTag { using InheritsFrom = std::tuple; }; #endif +} // end namespace TTag // Set the problem property -SET_TYPE_PROP(DarcyTypeTag, Problem, Dumux::DarcySubProblem); +template +struct Problem { using type = Dumux::DarcySubProblem; }; // The fluid system -SET_PROP(DarcyTypeTag, FluidSystem) +template +struct FluidSystem { - using H2OAir = FluidSystems::H2OAir; + using H2OAir = FluidSystems::H2OAir>; #if EXNUMBER == 0 using type = FluidSystems::OnePAdapter; #else @@ -70,29 +75,35 @@ SET_PROP(DarcyTypeTag, FluidSystem) }; // Use moles -SET_BOOL_PROP(DarcyTypeTag, UseMoles, true); +template +struct UseMoles { static constexpr bool value = true; }; // Do not replace one equation with a total mass balance -SET_INT_PROP(DarcyTypeTag, ReplaceCompEqIdx, 3); +template +struct ReplaceCompEqIdx { static constexpr int value = 3; }; //! Use a model with constant tortuosity for the effective diffusivity SET_TYPE_PROP(DarcyTypeTag, EffectiveDiffusivityModel, - DiffusivityConstantTortuosity); + DiffusivityConstantTortuosity>); // Set the grid type -SET_TYPE_PROP(DarcyTypeTag, Grid, Dune::YaspGrid<2>); +template +struct Grid { using type = Dune::YaspGrid<2>; }; #if EXNUMBER >= 1 //! Set the default formulation to pw-Sn: This can be over written in the problem. -SET_PROP(DarcyTypeTag, Formulation) +template +struct Formulation { static constexpr auto value = TwoPFormulation::p1s0; }; #endif // Set the spatial paramaters type #if EXNUMBER >= 1 -SET_TYPE_PROP(DarcyTypeTag, SpatialParams, TwoPSpatialParams); +template +struct SpatialParams { using type = TwoPSpatialParams; }; #else -SET_TYPE_PROP(DarcyTypeTag, SpatialParams, OnePSpatialParams); +template +struct SpatialParams { using type = OnePSpatialParams; }; #endif } @@ -100,19 +111,19 @@ template class DarcySubProblem : public PorousMediumFlowProblem { using ParentType = PorousMediumFlowProblem; - using GridView = typename GET_PROP_TYPE(TypeTag, GridView); - using Scalar = typename GET_PROP_TYPE(TypeTag, Scalar); - using PrimaryVariables = typename GET_PROP_TYPE(TypeTag, PrimaryVariables); - using FluidSystem = typename GET_PROP_TYPE(TypeTag, FluidSystem); - using NumEqVector = typename GET_PROP_TYPE(TypeTag, NumEqVector); - using BoundaryTypes = typename GET_PROP_TYPE(TypeTag, BoundaryTypes); - using FVElementGeometry = typename GET_PROP_TYPE(TypeTag, FVGridGeometry)::LocalView; + using GridView = GetPropType; + using Scalar = GetPropType; + using PrimaryVariables = GetPropType; + using FluidSystem = GetPropType; + using NumEqVector = GetPropType; + using BoundaryTypes = GetPropType; + using FVElementGeometry = typename GetPropType::LocalView; using SubControlVolume = typename FVElementGeometry::SubControlVolume; using SubControlVolumeFace = typename FVElementGeometry::SubControlVolumeFace; - using FVGridGeometry = typename GET_PROP_TYPE(TypeTag, FVGridGeometry); + using FVGridGeometry = GetPropType; // copy some indices for convenience - using Indices = typename GET_PROP_TYPE(TypeTag, ModelTraits)::Indices; + using Indices = typename GetPropType::Indices; enum { // grid and world dimension dim = GridView::dimension, @@ -135,7 +146,7 @@ class DarcySubProblem : public PorousMediumFlowProblem using Element = typename GridView::template Codim<0>::Entity; using GlobalPosition = Dune::FieldVector; - using CouplingManager = typename GET_PROP_TYPE(TypeTag, CouplingManager); + using CouplingManager = GetPropType; using TimeLoopPtr = std::shared_ptr>; public: @@ -148,7 +159,6 @@ public: #else moleFraction_ = getParamFromGroup(this->paramGroup(), "Problem.MoleFraction"); #endif - pressure_ = getParamFromGroup(this->paramGroup(), "Problem.Pressure"); // initialize output file plotFluxes_ = getParamFromGroup(this->paramGroup(), "Problem.PlotFluxes", false); @@ -275,10 +285,8 @@ public: if (!couplingManager().isCoupledEntity(CouplingManager::darcyIdx, scvf)) continue; - // NOTE: binding the coupling context is necessary - couplingManager_->bindCouplingContext(CouplingManager::darcyIdx, element); #if EXNUMBER >= 2 - NumEqVector flux = couplingManager().couplingData().massCouplingCondition(fvGeometry, elemVolVars, scvf); + NumEqVector flux = couplingManager().couplingData().massCouplingCondition(element, fvGeometry, elemVolVars, scvf); #else NumEqVector flux(0.0); // add "massCouplingCondition" from the couplingManager here #endif @@ -301,21 +309,6 @@ public: gnuplotInterfaceFluxes_.plot("flux_" + std::to_string(timeLoop_->timeStepIndex())); } - /*! - * \brief Returns true if a restart file should be written to - * disk. - */ - bool shouldWriteRestartFile() const - { return false; } - - /*! - * \name Problem parameters - */ - // \{ - - bool shouldWriteOutput() const // define output - { return true; } - /*! * \brief Return the temperature within the domain in [K]. * @@ -366,7 +359,7 @@ public: NumEqVector values(0.0); if (couplingManager().isCoupledEntity(CouplingManager::darcyIdx, scvf)) - values = couplingManager().couplingData().massCouplingCondition(fvGeometry, elemVolVars, scvf); + values = couplingManager().couplingData().massCouplingCondition(element, fvGeometry, elemVolVars, scvf); return values; } @@ -405,6 +398,8 @@ public: */ PrimaryVariables initialAtPos(const GlobalPosition &globalPos) const { + static const Scalar stokesPressure = getParamFromGroup("Stokes", "Problem.Pressure"); + PrimaryVariables values(0.0); #if EXNUMBER >= 3 values.setState(3/*bothPhases*/); @@ -415,7 +410,7 @@ public: #else values[transportCompIdx] = moleFraction_; #endif - values[pressureIdx] = pressure_; + values[pressureIdx] = stokesPressure; return values; } @@ -451,7 +446,6 @@ private: #else Scalar moleFraction_; #endif - Scalar pressure_; Scalar initialWaterContent_ = 0.0; Scalar lastWaterMass_ = 0.0; -- GitLab From 840d51d8d2f2f7b00eb37f0b981aaeeda0d0e1b9 Mon Sep 17 00:00:00 2001 From: Kilian Weishaupt Date: Wed, 12 Dec 2018 11:03:28 +0100 Subject: [PATCH 16/25] [ff-pnm] Update third exercise --- exercises/exercise-coupling-ff-pm/README.md | 8 +- .../ex_turbulence_coupling_ff-pm.cc | 82 +++++++----------- .../ex_turbulence_coupling_ff-pm.input | 6 ++ .../turbulence/ex_turbulence_ffproblem.hh | 79 +++++++++-------- .../turbulence/ex_turbulence_pmproblem.hh | 54 +++++++----- .../models/ex_models_coupling_ff-pm.input | 4 +- .../ex_turbulence_coupling_ff-pm.cc | 82 +++++++----------- .../ex_turbulence_coupling_ff-pm.input | 6 ++ .../turbulence/ex_turbulence_ffproblem.hh | 85 ++++++++++--------- .../turbulence/ex_turbulence_pmproblem.hh | 54 +++++++----- 10 files changed, 239 insertions(+), 221 deletions(-) diff --git a/exercises/exercise-coupling-ff-pm/README.md b/exercises/exercise-coupling-ff-pm/README.md index f3d56c7..d37eabf 100644 --- a/exercises/exercise-coupling-ff-pm/README.md +++ b/exercises/exercise-coupling-ff-pm/README.md @@ -323,7 +323,7 @@ For using the compositional zero equation turbulence model, the following header The includes for the NavierStokesNC model and the NavierStokesProblem are no longer needed and can be removed. Make sure your free flow problem inherits from the correct parent type: -* Change the last entry in the `NEW_TYPE_TAG` definition accordingly (non-isothermal zero equation model) +* Change the entry in the `ZeroEqTypeTag` definition accordingly (non-isothermal zero equation model) * Adapt the inheritance of the problem class (hint: two occurrences) Take a look into the two headers included above to see how the correct TypeTag and the Problem class the inherit from are called. @@ -332,9 +332,9 @@ Here, the turbulent free flow is wall bounded which means that the main reason f of turbulent flow is the presence of walls. The porous medium at the bottom and also the channel wall are such walls. Inside the problem you have to tell the turbulence model, where these walls are located -by providing an `isOnWall()` function: +by providing an `isOnWallAtPos()` function: ```c++ -bool isOnWall(const GlobalPosition& globalPos) const +bool isOnWallAtPos(const GlobalPosition& globalPos) const { return (onLowerBoundary_(globalPos) || onUpperBoundary_(globalPos)); } @@ -371,7 +371,7 @@ Instead of computing the whole cross-section of a channel, you can use symmetric values.setAllSymmetry(); ``` -In addition, you have to remove the condition `onUpperBoundary_(globalPos)` from the `isOnWall(globalPos)` +In addition, you have to remove the condition `onUpperBoundary_(globalPos)` from the `isOnWallAtPos(globalPos)` and `initialAtPos(globalPos)` method. __Task C__: diff --git a/exercises/exercise-coupling-ff-pm/turbulence/ex_turbulence_coupling_ff-pm.cc b/exercises/exercise-coupling-ff-pm/turbulence/ex_turbulence_coupling_ff-pm.cc index 233cdd3..523a337 100644 --- a/exercises/exercise-coupling-ff-pm/turbulence/ex_turbulence_coupling_ff-pm.cc +++ b/exercises/exercise-coupling-ff-pm/turbulence/ex_turbulence_coupling_ff-pm.cc @@ -34,18 +34,18 @@ #include #include #include -#include +#include #include #include #include -#include +#include #include #include #include #include #include -#include +#include #include @@ -55,15 +55,17 @@ namespace Dumux { namespace Properties { -SET_PROP(ZeroEqTypeTag, CouplingManager) +template +struct CouplingManager { - using Traits = StaggeredMultiDomainTraits; + using Traits = StaggeredMultiDomainTraits; using type = Dumux::StokesDarcyCouplingManager; }; -SET_PROP(DarcyTwoPTwoCTypeTag, CouplingManager) +template +struct CouplingManager { - using Traits = StaggeredMultiDomainTraits; + using Traits = StaggeredMultiDomainTraits; using type = Dumux::StokesDarcyCouplingManager; }; @@ -85,16 +87,16 @@ int main(int argc, char** argv) try Parameters::init(argc, argv); // Define the sub problem type tags - using StokesTypeTag = TTAG(ZeroEqTypeTag); - using DarcyTypeTag = TTAG(DarcyTwoPTwoCTypeTag); + using StokesTypeTag = Properties::TTag::ZeroEqTypeTag; + using DarcyTypeTag = Properties::TTag::DarcyTwoPTwoCTypeTag; // try to create a grid (from the given grid file or the input file) // for both sub-domains - using DarcyGridManager = Dumux::GridManager; + using DarcyGridManager = Dumux::GridManager>; DarcyGridManager darcyGridManager; darcyGridManager.init("Darcy"); // pass parameter group - using StokesGridManager = Dumux::GridManager; + using StokesGridManager = Dumux::GridManager>; StokesGridManager stokesGridManager; stokesGridManager.init("Stokes"); // pass parameter group @@ -103,10 +105,10 @@ int main(int argc, char** argv) try const auto& stokesGridView = stokesGridManager.grid().leafGridView(); // create the finite volume grid geometry - using StokesFVGridGeometry = typename GET_PROP_TYPE(StokesTypeTag, FVGridGeometry); + using StokesFVGridGeometry = GetPropType; auto stokesFvGridGeometry = std::make_shared(stokesGridView); stokesFvGridGeometry->update(); - using DarcyFVGridGeometry = typename GET_PROP_TYPE(DarcyTypeTag, FVGridGeometry); + using DarcyFVGridGeometry = GetPropType; auto darcyFvGridGeometry = std::make_shared(darcyGridView); darcyFvGridGeometry->update(); @@ -122,27 +124,22 @@ int main(int argc, char** argv) try constexpr auto darcyIdx = CouplingManager::darcyIdx; // the problem (initial and boundary conditions) - using StokesProblem = typename GET_PROP_TYPE(StokesTypeTag, Problem); + using StokesProblem = GetPropType; auto stokesProblem = std::make_shared(stokesFvGridGeometry, couplingManager); - using DarcyProblem = typename GET_PROP_TYPE(DarcyTypeTag, Problem); + using DarcyProblem = GetPropType; auto darcyProblem = std::make_shared(darcyFvGridGeometry, couplingManager); // initialize the fluidsystem (tabulation) - GET_PROP_TYPE(StokesTypeTag, FluidSystem)::init(); + GetPropType::init(); // get some time loop parameters - using Scalar = typename GET_PROP_TYPE(StokesTypeTag, Scalar); + using Scalar = GetPropType; const auto tEnd = getParam("TimeLoop.TEnd"); const auto maxDt = getParam("TimeLoop.MaxTimeStepSize"); auto dt = getParam("TimeLoop.DtInitial"); - // check if we are about to restart a previously interrupted simulation - Scalar restartTime = 0; - if (Parameters::getTree().hasKey("Restart") || Parameters::getTree().hasKey("TimeLoop.Restart")) - restartTime = getParam("TimeLoop.Restart"); - // instantiate time loop - auto timeLoop = std::make_shared>(restartTime, dt, tEnd); + auto timeLoop = std::make_shared>(0, dt, tEnd); timeLoop->setMaxTimeStepSize(maxDt); // set timeloop for the subproblems, needed for boundary value variations @@ -155,18 +152,10 @@ int main(int argc, char** argv) try sol[stokesFaceIdx].resize(stokesFvGridGeometry->numFaceDofs()); sol[darcyIdx].resize(darcyFvGridGeometry->numDofs()); - // apply initial solution for instationary problems - // auxiliary free flow solution vector - typename GET_PROP_TYPE(StokesTypeTag, SolutionVector) stokesSol; - stokesSol[stokesCellCenterIdx].resize(sol[stokesCellCenterIdx].size()); - stokesSol[stokesFaceIdx].resize(sol[stokesFaceIdx].size()); - stokesProblem->applyInitialSolution(stokesSol); - auto solStokesOld = stokesSol; - sol[stokesCellCenterIdx] = stokesSol[stokesCellCenterIdx]; - sol[stokesFaceIdx] = stokesSol[stokesFaceIdx]; + auto stokesSol = partial(sol, stokesCellCenterIdx, stokesFaceIdx); + stokesProblem->applyInitialSolution(stokesSol); darcyProblem->applyInitialSolution(sol[darcyIdx]); - auto solDarcyOld = sol[darcyIdx]; auto solOld = sol; @@ -176,23 +165,25 @@ int main(int argc, char** argv) try // TODO: update dynamic wall properties // the grid variables - using StokesGridVariables = typename GET_PROP_TYPE(StokesTypeTag, GridVariables); + using StokesGridVariables = GetPropType; auto stokesGridVariables = std::make_shared(stokesProblem, stokesFvGridGeometry); - stokesGridVariables->init(stokesSol, solStokesOld); - using DarcyGridVariables = typename GET_PROP_TYPE(DarcyTypeTag, GridVariables); + stokesGridVariables->init(stokesSol); + using DarcyGridVariables = GetPropType; auto darcyGridVariables = std::make_shared(darcyProblem, darcyFvGridGeometry); - darcyGridVariables->init(sol[darcyIdx], solDarcyOld); + darcyGridVariables->init(sol[darcyIdx]); // intialize the vtk output module const auto stokesName = getParam("Problem.Name") + "_" + stokesProblem->name(); const auto darcyName = getParam("Problem.Name") + "_" + darcyProblem->name(); - StaggeredVtkOutputModule stokesVtkWriter(*stokesProblem, *stokesFvGridGeometry, *stokesGridVariables, stokesSol, stokesName); - GET_PROP_TYPE(StokesTypeTag, VtkOutputFields)::init(stokesVtkWriter); + StaggeredVtkOutputModule stokesVtkWriter(*stokesGridVariables, stokesSol, stokesName); + GetPropType::initOutputModule(stokesVtkWriter); stokesVtkWriter.write(0.0); - VtkOutputModule darcyVtkWriter(*darcyProblem, *darcyFvGridGeometry, *darcyGridVariables, sol[darcyIdx], darcyName); - GET_PROP_TYPE(DarcyTypeTag, VtkOutputFields)::init(darcyVtkWriter); + VtkOutputModule> darcyVtkWriter(*darcyGridVariables, sol[darcyIdx], darcyName); + using DarcyVelocityOutput = GetPropType; + darcyVtkWriter.addVelocityOutput(std::make_shared(*darcyGridVariables)); + GetPropType::initOutputModule(darcyVtkWriter); darcyVtkWriter.write(0.0); // the assembler with time loop for instationary problem @@ -211,11 +202,8 @@ int main(int argc, char** argv) try using LinearSolver = UMFPackBackend; auto linearSolver = std::make_shared(); - // the primary variable switches used by the sub models - using PriVarSwitchTuple = std::tuple; - // the non-linear solver - using NewtonSolver = MultiDomainPriVarSwitchNewtonSolver; + using NewtonSolver = MultiDomainNewtonSolver; NewtonSolver nonLinearSolver(assembler, linearSolver, couplingManager); // time loop @@ -230,10 +218,6 @@ int main(int argc, char** argv) try // make the new solution the old solution solOld = sol; - // update the auxiliary free flow solution vector - stokesSol[stokesCellCenterIdx] = sol[stokesCellCenterIdx]; - stokesSol[stokesFaceIdx] = sol[stokesFaceIdx]; - // TODO: update dynamic wall properties // post time step treatment of Darcy problem diff --git a/exercises/exercise-coupling-ff-pm/turbulence/ex_turbulence_coupling_ff-pm.input b/exercises/exercise-coupling-ff-pm/turbulence/ex_turbulence_coupling_ff-pm.input index 514cf15..00e0246 100644 --- a/exercises/exercise-coupling-ff-pm/turbulence/ex_turbulence_coupling_ff-pm.input +++ b/exercises/exercise-coupling-ff-pm/turbulence/ex_turbulence_coupling_ff-pm.input @@ -27,6 +27,7 @@ RefVelocity = 3.5 # [m/s] RefPressure = 1e5 # [Pa] refMoleFrac = 0 # [-] RefTemperature = 298.15 # [K] +EnableInertiaTerms = true [Darcy.Problem] Name = darcy @@ -60,3 +61,8 @@ MaxRelativeShift = 1e-5 [Assembly] NumericDifferenceMethod = 0 NumericDifference.BaseEpsilon = 1e-8 + +[Component] +SolidDensity = 2700 +SolidThermalConductivity = 2.8 +SolidHeatCapacity = 790 diff --git a/exercises/exercise-coupling-ff-pm/turbulence/ex_turbulence_ffproblem.hh b/exercises/exercise-coupling-ff-pm/turbulence/ex_turbulence_ffproblem.hh index 6c89102..88d9cde 100644 --- a/exercises/exercise-coupling-ff-pm/turbulence/ex_turbulence_ffproblem.hh +++ b/exercises/exercise-coupling-ff-pm/turbulence/ex_turbulence_ffproblem.hh @@ -39,32 +39,41 @@ class FreeFlowSubProblem; namespace Properties { -NEW_TYPE_TAG(ZeroEqTypeTag, INHERITS_FROM(StaggeredFreeFlowModel, NavierStokesNCNI)); +// Create new type tags +namespace TTag { +struct ZeroEqTypeTag { using InheritsFrom = std::tuple; }; +} // end namespace TTag // Set the grid type -SET_TYPE_PROP(ZeroEqTypeTag, Grid, Dune::YaspGrid<2, Dune::TensorProductCoordinates >); +template +struct Grid { using type = Dune::YaspGrid<2, Dune::TensorProductCoordinates, 2> >; }; // The fluid system -SET_PROP(ZeroEqTypeTag, FluidSystem) +template +struct FluidSystem { - using H2OAir = FluidSystems::H2OAir; + using H2OAir = FluidSystems::H2OAir>; static constexpr auto phaseIdx = H2OAir::gasPhaseIdx; // simulate the air phase using type = FluidSystems::OnePAdapter; }; -SET_INT_PROP(ZeroEqTypeTag, ReplaceCompEqIdx, 3); +template +struct ReplaceCompEqIdx { static constexpr int value = 3; }; // Use formulation based on mass fractions -SET_BOOL_PROP(ZeroEqTypeTag, UseMoles, true); +template +struct UseMoles { static constexpr bool value = true; }; // Set the problem property -SET_TYPE_PROP(ZeroEqTypeTag, Problem, Dumux::FreeFlowSubProblem ); - -SET_BOOL_PROP(ZeroEqTypeTag, EnableFVGridGeometryCache, true); -SET_BOOL_PROP(ZeroEqTypeTag, EnableGridFluxVariablesCache, true); -SET_BOOL_PROP(ZeroEqTypeTag, EnableGridVolumeVariablesCache, true); - -SET_BOOL_PROP(ZeroEqTypeTag, EnableInertiaTerms, true); +template +struct Problem { using type = Dumux::FreeFlowSubProblem ; }; + +template +struct EnableFVGridGeometryCache { static constexpr bool value = true; }; +template +struct EnableGridFluxVariablesCache { static constexpr bool value = true; }; +template +struct EnableGridVolumeVariablesCache { static constexpr bool value = true; }; } /*! @@ -75,31 +84,31 @@ class FreeFlowSubProblem : public NavierStokesProblem { using ParentType = NavierStokesProblem; - using GridView = typename GET_PROP_TYPE(TypeTag, GridView); - using Scalar = typename GET_PROP_TYPE(TypeTag, Scalar); - using FluidSystem = typename GET_PROP_TYPE(TypeTag, FluidSystem); - using Indices = typename GET_PROP_TYPE(TypeTag, ModelTraits)::Indices; - using BoundaryTypes = typename GET_PROP_TYPE(TypeTag, BoundaryTypes); + using GridView = GetPropType; + using Scalar = GetPropType; + using FluidSystem = GetPropType; + using Indices = typename GetPropType::Indices; + using BoundaryTypes = GetPropType; - using FVGridGeometry = typename GET_PROP_TYPE(TypeTag, FVGridGeometry); + using FVGridGeometry = GetPropType; using FVElementGeometry = typename FVGridGeometry::LocalView; using SubControlVolumeFace = typename FVElementGeometry::SubControlVolumeFace; using Element = typename GridView::template Codim<0>::Entity; - using ElementVolumeVariables = typename GET_PROP_TYPE(TypeTag, GridVolumeVariables)::LocalView; - using ElementFaceVariables = typename GET_PROP_TYPE(TypeTag, GridFaceVariables)::LocalView; - using FluidState = typename GET_PROP_TYPE(TypeTag, FluidState); + using ElementVolumeVariables = typename GetPropType::LocalView; + using ElementFaceVariables = typename GetPropType::LocalView; + using FluidState = GetPropType; using GlobalPosition = typename Element::Geometry::GlobalCoordinate; - using PrimaryVariables = typename GET_PROP_TYPE(TypeTag, PrimaryVariables); - using NumEqVector = typename GET_PROP_TYPE(TypeTag, NumEqVector); + using PrimaryVariables = GetPropType; + using NumEqVector = GetPropType; - using CouplingManager = typename GET_PROP_TYPE(TypeTag, CouplingManager); + using CouplingManager = GetPropType; using TimeLoopPtr = std::shared_ptr>; using DiffusionCoefficientAveragingType = typename StokesDarcyCouplingOptions::DiffusionCoefficientAveragingType; - static constexpr bool useMoles = GET_PROP_TYPE(TypeTag, ModelTraits)::useMoles(); + static constexpr bool useMoles = GetPropType::useMoles(); public: FreeFlowSubProblem(std::shared_ptr fvGridGeometry, std::shared_ptr couplingManager) @@ -158,7 +167,7 @@ public: values.setDirichlet(Indices::velocityXIdx); values.setDirichlet(Indices::velocityYIdx); values.setDirichlet(Indices::conti0EqIdx + 1); - values.setDirichlet(Indices::energyBalanceIdx); + values.setDirichlet(Indices::energyEqIdx); } if (onLowerBoundary_(globalPos)) @@ -167,7 +176,7 @@ public: values.setDirichlet(Indices::velocityYIdx); values.setNeumann(Indices::conti0EqIdx); values.setNeumann(Indices::conti0EqIdx + 1); - values.setNeumann(Indices::energyBalanceIdx); + values.setNeumann(Indices::energyEqIdx); } if (onUpperBoundary_(globalPos)) @@ -176,21 +185,21 @@ public: values.setDirichlet(Indices::velocityYIdx); values.setNeumann(Indices::conti0EqIdx); values.setNeumann(Indices::conti0EqIdx + 1); - values.setNeumann(Indices::energyBalanceIdx); + values.setNeumann(Indices::energyEqIdx); } if (onRightBoundary_(globalPos)) { values.setDirichlet(Indices::pressureIdx); values.setOutflow(Indices::conti0EqIdx + 1); - values.setOutflow(Indices::energyBalanceIdx); + values.setOutflow(Indices::energyEqIdx); } if (couplingManager().isCoupledEntity(CouplingManager::stokesIdx, scvf)) { values.setCouplingNeumann(Indices::conti0EqIdx); values.setCouplingNeumann(Indices::conti0EqIdx + 1); - values.setCouplingNeumann(Indices::energyBalanceIdx); + values.setCouplingNeumann(Indices::energyEqIdx); values.setCouplingNeumann(Indices::momentumYBalanceIdx); values.setBJS(Indices::momentumXBalanceIdx); } @@ -229,12 +238,12 @@ public: PrimaryVariables values(0.0); if(couplingManager().isCoupledEntity(CouplingManager::stokesIdx, scvf)) { - values[Indices::momentumYBalanceIdx] = couplingManager().couplingData().momentumCouplingCondition(fvGeometry, elemVolVars, elemFaceVars, scvf); + values[Indices::momentumYBalanceIdx] = couplingManager().couplingData().momentumCouplingCondition(element, fvGeometry, elemVolVars, elemFaceVars, scvf); - const auto massFlux = couplingManager().couplingData().massCouplingCondition(fvGeometry, elemVolVars, elemFaceVars, scvf, diffCoeffAvgType_); + const auto massFlux = couplingManager().couplingData().massCouplingCondition(element, fvGeometry, elemVolVars, elemFaceVars, scvf, diffCoeffAvgType_); values[Indices::conti0EqIdx] = massFlux[0]; values[Indices::conti0EqIdx + 1] = massFlux[1]; - values[Indices::energyBalanceIdx] = couplingManager().couplingData().energyCouplingCondition(fvGeometry, elemVolVars, elemFaceVars, scvf, diffCoeffAvgType_); + values[Indices::energyEqIdx] = couplingManager().couplingData().energyCouplingCondition(element, fvGeometry, elemVolVars, elemFaceVars, scvf, diffCoeffAvgType_); } return values; } @@ -305,7 +314,7 @@ public: /*! * \brief Returns the intrinsic permeability of required as input parameter for the Beavers-Joseph-Saffman boundary condition */ - Scalar permeability(const SubControlVolumeFace& scvf) const + Scalar permeability(const Element& element, const SubControlVolumeFace& scvf) const { return couplingManager().problem(CouplingManager::darcyIdx).spatialParams().permeabilityAtPos(scvf.center()); } diff --git a/exercises/exercise-coupling-ff-pm/turbulence/ex_turbulence_pmproblem.hh b/exercises/exercise-coupling-ff-pm/turbulence/ex_turbulence_pmproblem.hh index 0a9cd5f..de4bb4e 100644 --- a/exercises/exercise-coupling-ff-pm/turbulence/ex_turbulence_pmproblem.hh +++ b/exercises/exercise-coupling-ff-pm/turbulence/ex_turbulence_pmproblem.hh @@ -42,27 +42,37 @@ class DarcySubProblem; namespace Properties { -NEW_TYPE_TAG(DarcyTwoPTwoCTypeTag, INHERITS_FROM(CCTpfaModel, TwoPTwoCNI)); +// Create new type tags +namespace TTag { +struct DarcyTwoPTwoCTypeTag { using InheritsFrom = std::tuple; }; +} // end namespace TTag // Set the problem property -SET_TYPE_PROP(DarcyTwoPTwoCTypeTag, Problem, Dumux::DarcySubProblem); +template +struct Problem { using type = Dumux::DarcySubProblem; }; // the fluid system -SET_TYPE_PROP(DarcyTwoPTwoCTypeTag, FluidSystem, FluidSystems::H2OAir); +template +struct FluidSystem { using type = FluidSystems::H2OAir>; }; //! Set the default formulation to pw-Sn: This can be over written in the problem. -SET_PROP(DarcyTwoPTwoCTypeTag, Formulation) +template +struct Formulation { static constexpr auto value = TwoPFormulation::p1s0; }; // The gas component balance (air) is replaced by the total mass balance -SET_INT_PROP(DarcyTwoPTwoCTypeTag, ReplaceCompEqIdx, 3); +template +struct ReplaceCompEqIdx { static constexpr int value = 3; }; // Set the grid type -SET_TYPE_PROP(DarcyTwoPTwoCTypeTag, Grid, Dune::YaspGrid<2, Dune::TensorProductCoordinates >); +template +struct Grid { using type = Dune::YaspGrid<2, Dune::TensorProductCoordinates, 2> >; }; -SET_BOOL_PROP(DarcyTwoPTwoCTypeTag, UseMoles, true); +template +struct UseMoles { static constexpr bool value = true; }; -SET_TYPE_PROP(DarcyTwoPTwoCTypeTag, SpatialParams, TwoPSpatialParams); +template +struct SpatialParams { using type = TwoPSpatialParams; }; } /*! @@ -72,22 +82,22 @@ template class DarcySubProblem : public PorousMediumFlowProblem { using ParentType = PorousMediumFlowProblem; - using GridView = typename GET_PROP_TYPE(TypeTag, GridView); - using Scalar = typename GET_PROP_TYPE(TypeTag, Scalar); - using PrimaryVariables = typename GET_PROP_TYPE(TypeTag, PrimaryVariables); - using NumEqVector = typename GET_PROP_TYPE(TypeTag, NumEqVector); - using BoundaryTypes = typename GET_PROP_TYPE(TypeTag, BoundaryTypes); - using VolumeVariables = typename GET_PROP_TYPE(TypeTag, VolumeVariables); - using FVElementGeometry = typename GET_PROP_TYPE(TypeTag, FVGridGeometry)::LocalView; + using GridView = GetPropType; + using Scalar = GetPropType; + using PrimaryVariables = GetPropType; + using NumEqVector = GetPropType; + using BoundaryTypes = GetPropType; + using VolumeVariables = GetPropType; + using FVElementGeometry = typename GetPropType::LocalView; using SubControlVolume = typename FVElementGeometry::SubControlVolume; using SubControlVolumeFace = typename FVElementGeometry::SubControlVolumeFace; - using FVGridGeometry = typename GET_PROP_TYPE(TypeTag, FVGridGeometry); - using ElementVolumeVariables = typename GET_PROP_TYPE(TypeTag, GridVolumeVariables)::LocalView; + using FVGridGeometry = GetPropType; + using ElementVolumeVariables = typename GetPropType::LocalView; - using FluidSystem = typename GET_PROP_TYPE(TypeTag, FluidSystem); + using FluidSystem = GetPropType; // copy some indices for convenience - using Indices = typename GET_PROP_TYPE(TypeTag, ModelTraits)::Indices; + using Indices = typename GetPropType::Indices; enum { // primary variable indices conti0EqIdx = Indices::conti0EqIdx, @@ -100,7 +110,7 @@ class DarcySubProblem : public PorousMediumFlowProblem using Element = typename GridView::template Codim<0>::Entity; using GlobalPosition = typename Element::Geometry::GlobalCoordinate; - using CouplingManager = typename GET_PROP_TYPE(TypeTag, CouplingManager); + using CouplingManager = GetPropType; using TimeLoopPtr = std::shared_ptr>; using DiffusionCoefficientAveragingType = typename StokesDarcyCouplingOptions::DiffusionCoefficientAveragingType; @@ -220,12 +230,12 @@ public: if (couplingManager().isCoupledEntity(CouplingManager::darcyIdx, scvf)) { - const auto massFlux = couplingManager().couplingData().massCouplingCondition(fvGeometry, elemVolVars, scvf, diffCoeffAvgType_); + const auto massFlux = couplingManager().couplingData().massCouplingCondition(element, fvGeometry, elemVolVars, scvf, diffCoeffAvgType_); for(int i = 0; i< massFlux.size(); ++i) values[i] = massFlux[i]; - values[Indices::energyEqIdx] = couplingManager().couplingData().energyCouplingCondition(fvGeometry, elemVolVars, scvf, diffCoeffAvgType_); + values[Indices::energyEqIdx] = couplingManager().couplingData().energyCouplingCondition(element, fvGeometry, elemVolVars, scvf, diffCoeffAvgType_); } return values; diff --git a/exercises/solution/exercise-coupling-ff-pm/models/ex_models_coupling_ff-pm.input b/exercises/solution/exercise-coupling-ff-pm/models/ex_models_coupling_ff-pm.input index 1b0a62a..7dda6b1 100644 --- a/exercises/solution/exercise-coupling-ff-pm/models/ex_models_coupling_ff-pm.input +++ b/exercises/solution/exercise-coupling-ff-pm/models/ex_models_coupling_ff-pm.input @@ -39,8 +39,8 @@ VgN = 8.0 [Problem] Name = ex_models_coupling -PlotFluxes = false -PlotStorage = false +PlotFluxes = true +PlotStorage = true [Newton] MaxSteps = 12 diff --git a/exercises/solution/exercise-coupling-ff-pm/turbulence/ex_turbulence_coupling_ff-pm.cc b/exercises/solution/exercise-coupling-ff-pm/turbulence/ex_turbulence_coupling_ff-pm.cc index e1e4739..ac7f758 100644 --- a/exercises/solution/exercise-coupling-ff-pm/turbulence/ex_turbulence_coupling_ff-pm.cc +++ b/exercises/solution/exercise-coupling-ff-pm/turbulence/ex_turbulence_coupling_ff-pm.cc @@ -34,18 +34,18 @@ #include #include #include -#include +#include #include #include #include -#include +#include #include #include #include #include #include -#include +#include #include @@ -55,15 +55,17 @@ namespace Dumux { namespace Properties { -SET_PROP(ZeroEqTypeTag, CouplingManager) +template +struct CouplingManager { - using Traits = StaggeredMultiDomainTraits; + using Traits = StaggeredMultiDomainTraits; using type = Dumux::StokesDarcyCouplingManager; }; -SET_PROP(DarcyTwoPTwoCTypeTag, CouplingManager) +template +struct CouplingManager { - using Traits = StaggeredMultiDomainTraits; + using Traits = StaggeredMultiDomainTraits; using type = Dumux::StokesDarcyCouplingManager; }; @@ -85,16 +87,16 @@ int main(int argc, char** argv) try Parameters::init(argc, argv); // Define the sub problem type tags - using StokesTypeTag = TTAG(ZeroEqTypeTag); - using DarcyTypeTag = TTAG(DarcyTwoPTwoCTypeTag); + using StokesTypeTag = Properties::TTag::ZeroEqTypeTag; + using DarcyTypeTag = Properties::TTag::DarcyTwoPTwoCTypeTag; // try to create a grid (from the given grid file or the input file) // for both sub-domains - using DarcyGridManager = Dumux::GridManager; + using DarcyGridManager = Dumux::GridManager>; DarcyGridManager darcyGridManager; darcyGridManager.init("Darcy"); // pass parameter group - using StokesGridManager = Dumux::GridManager; + using StokesGridManager = Dumux::GridManager>; StokesGridManager stokesGridManager; stokesGridManager.init("Stokes"); // pass parameter group @@ -103,10 +105,10 @@ int main(int argc, char** argv) try const auto& stokesGridView = stokesGridManager.grid().leafGridView(); // create the finite volume grid geometry - using StokesFVGridGeometry = typename GET_PROP_TYPE(StokesTypeTag, FVGridGeometry); + using StokesFVGridGeometry = GetPropType; auto stokesFvGridGeometry = std::make_shared(stokesGridView); stokesFvGridGeometry->update(); - using DarcyFVGridGeometry = typename GET_PROP_TYPE(DarcyTypeTag, FVGridGeometry); + using DarcyFVGridGeometry = GetPropType; auto darcyFvGridGeometry = std::make_shared(darcyGridView); darcyFvGridGeometry->update(); @@ -122,27 +124,22 @@ int main(int argc, char** argv) try constexpr auto darcyIdx = CouplingManager::darcyIdx; // the problem (initial and boundary conditions) - using StokesProblem = typename GET_PROP_TYPE(StokesTypeTag, Problem); + using StokesProblem = GetPropType; auto stokesProblem = std::make_shared(stokesFvGridGeometry, couplingManager); - using DarcyProblem = typename GET_PROP_TYPE(DarcyTypeTag, Problem); + using DarcyProblem = GetPropType; auto darcyProblem = std::make_shared(darcyFvGridGeometry, couplingManager); // initialize the fluidsystem (tabulation) - GET_PROP_TYPE(StokesTypeTag, FluidSystem)::init(); + GetPropType::init(); // get some time loop parameters - using Scalar = typename GET_PROP_TYPE(StokesTypeTag, Scalar); + using Scalar = GetPropType; const auto tEnd = getParam("TimeLoop.TEnd"); const auto maxDt = getParam("TimeLoop.MaxTimeStepSize"); auto dt = getParam("TimeLoop.DtInitial"); - // check if we are about to restart a previously interrupted simulation - Scalar restartTime = 0; - if (Parameters::getTree().hasKey("Restart") || Parameters::getTree().hasKey("TimeLoop.Restart")) - restartTime = getParam("TimeLoop.Restart"); - // instantiate time loop - auto timeLoop = std::make_shared>(restartTime, dt, tEnd); + auto timeLoop = std::make_shared>(0, dt, tEnd); timeLoop->setMaxTimeStepSize(maxDt); // set timeloop for the subproblems, needed for boundary value variations @@ -155,18 +152,10 @@ int main(int argc, char** argv) try sol[stokesFaceIdx].resize(stokesFvGridGeometry->numFaceDofs()); sol[darcyIdx].resize(darcyFvGridGeometry->numDofs()); - // apply initial solution for instationary problems - // auxiliary free flow solution vector - typename GET_PROP_TYPE(StokesTypeTag, SolutionVector) stokesSol; - stokesSol[stokesCellCenterIdx].resize(sol[stokesCellCenterIdx].size()); - stokesSol[stokesFaceIdx].resize(sol[stokesFaceIdx].size()); - stokesProblem->applyInitialSolution(stokesSol); - auto solStokesOld = stokesSol; - sol[stokesCellCenterIdx] = stokesSol[stokesCellCenterIdx]; - sol[stokesFaceIdx] = stokesSol[stokesFaceIdx]; + auto stokesSol = partial(sol, stokesCellCenterIdx, stokesFaceIdx); + stokesProblem->applyInitialSolution(stokesSol); darcyProblem->applyInitialSolution(sol[darcyIdx]); - auto solDarcyOld = sol[darcyIdx]; auto solOld = sol; @@ -179,23 +168,25 @@ int main(int argc, char** argv) try #endif // the grid variables - using StokesGridVariables = typename GET_PROP_TYPE(StokesTypeTag, GridVariables); + using StokesGridVariables = GetPropType; auto stokesGridVariables = std::make_shared(stokesProblem, stokesFvGridGeometry); - stokesGridVariables->init(stokesSol, solStokesOld); - using DarcyGridVariables = typename GET_PROP_TYPE(DarcyTypeTag, GridVariables); + stokesGridVariables->init(stokesSol); + using DarcyGridVariables = GetPropType; auto darcyGridVariables = std::make_shared(darcyProblem, darcyFvGridGeometry); - darcyGridVariables->init(sol[darcyIdx], solDarcyOld); + darcyGridVariables->init(sol[darcyIdx]); // intialize the vtk output module const auto stokesName = getParam("Problem.Name") + "_" + stokesProblem->name(); const auto darcyName = getParam("Problem.Name") + "_" + darcyProblem->name(); - StaggeredVtkOutputModule stokesVtkWriter(*stokesProblem, *stokesFvGridGeometry, *stokesGridVariables, stokesSol, stokesName); - GET_PROP_TYPE(StokesTypeTag, VtkOutputFields)::init(stokesVtkWriter); + StaggeredVtkOutputModule stokesVtkWriter(*stokesGridVariables, stokesSol, stokesName); + GetPropType::initOutputModule(stokesVtkWriter); stokesVtkWriter.write(0.0); - VtkOutputModule darcyVtkWriter(*darcyProblem, *darcyFvGridGeometry, *darcyGridVariables, sol[darcyIdx], darcyName); - GET_PROP_TYPE(DarcyTypeTag, VtkOutputFields)::init(darcyVtkWriter); + VtkOutputModule> darcyVtkWriter(*darcyGridVariables, sol[darcyIdx], darcyName); + using DarcyVelocityOutput = GetPropType; + darcyVtkWriter.addVelocityOutput(std::make_shared(*darcyGridVariables)); + GetPropType::initOutputModule(darcyVtkWriter); darcyVtkWriter.write(0.0); // the assembler with time loop for instationary problem @@ -214,11 +205,8 @@ int main(int argc, char** argv) try using LinearSolver = UMFPackBackend; auto linearSolver = std::make_shared(); - // the primary variable switches used by the sub models - using PriVarSwitchTuple = std::tuple; - // the non-linear solver - using NewtonSolver = MultiDomainPriVarSwitchNewtonSolver; + using NewtonSolver = MultiDomainNewtonSolver; NewtonSolver nonLinearSolver(assembler, linearSolver, couplingManager); // time loop @@ -233,10 +221,6 @@ int main(int argc, char** argv) try // make the new solution the old solution solOld = sol; - // update the auxiliary free flow solution vector - stokesSol[stokesCellCenterIdx] = sol[stokesCellCenterIdx]; - stokesSol[stokesFaceIdx] = sol[stokesFaceIdx]; - #if EXNUMBER >= 1 // TODO: update dynamic wall properties stokesProblem->updateDynamicWallProperties(stokesSol); diff --git a/exercises/solution/exercise-coupling-ff-pm/turbulence/ex_turbulence_coupling_ff-pm.input b/exercises/solution/exercise-coupling-ff-pm/turbulence/ex_turbulence_coupling_ff-pm.input index 514cf15..00e0246 100644 --- a/exercises/solution/exercise-coupling-ff-pm/turbulence/ex_turbulence_coupling_ff-pm.input +++ b/exercises/solution/exercise-coupling-ff-pm/turbulence/ex_turbulence_coupling_ff-pm.input @@ -27,6 +27,7 @@ RefVelocity = 3.5 # [m/s] RefPressure = 1e5 # [Pa] refMoleFrac = 0 # [-] RefTemperature = 298.15 # [K] +EnableInertiaTerms = true [Darcy.Problem] Name = darcy @@ -60,3 +61,8 @@ MaxRelativeShift = 1e-5 [Assembly] NumericDifferenceMethod = 0 NumericDifference.BaseEpsilon = 1e-8 + +[Component] +SolidDensity = 2700 +SolidThermalConductivity = 2.8 +SolidHeatCapacity = 790 diff --git a/exercises/solution/exercise-coupling-ff-pm/turbulence/ex_turbulence_ffproblem.hh b/exercises/solution/exercise-coupling-ff-pm/turbulence/ex_turbulence_ffproblem.hh index 194597f..a78efe8 100644 --- a/exercises/solution/exercise-coupling-ff-pm/turbulence/ex_turbulence_ffproblem.hh +++ b/exercises/solution/exercise-coupling-ff-pm/turbulence/ex_turbulence_ffproblem.hh @@ -44,36 +44,45 @@ class FreeFlowSubProblem; namespace Properties { +// Create new type tags +namespace TTag { #if EXNUMBER >= 1 -NEW_TYPE_TAG(ZeroEqTypeTag, INHERITS_FROM(StaggeredFreeFlowModel, ZeroEqNCNI)); +struct ZeroEqTypeTag { using InheritsFrom = std::tuple; }; #else -NEW_TYPE_TAG(ZeroEqTypeTag, INHERITS_FROM(StaggeredFreeFlowModel, NavierStokesNCNI)); +struct ZeroEqTypeTag { using InheritsFrom = std::tuple; }; #endif +} // end namespace TTag // Set the grid type -SET_TYPE_PROP(ZeroEqTypeTag, Grid, Dune::YaspGrid<2, Dune::TensorProductCoordinates >); +template +struct Grid { using type = Dune::YaspGrid<2, Dune::TensorProductCoordinates, 2> >; }; // The fluid system -SET_PROP(ZeroEqTypeTag, FluidSystem) +template +struct FluidSystem { - using H2OAir = FluidSystems::H2OAir; + using H2OAir = FluidSystems::H2OAir>; static constexpr auto phaseIdx = H2OAir::gasPhaseIdx; // simulate the air phase using type = FluidSystems::OnePAdapter; }; -SET_INT_PROP(ZeroEqTypeTag, ReplaceCompEqIdx, 3); +template +struct ReplaceCompEqIdx { static constexpr int value = 3; }; // Use formulation based on mass fractions -SET_BOOL_PROP(ZeroEqTypeTag, UseMoles, true); +template +struct UseMoles { static constexpr bool value = true; }; // Set the problem property -SET_TYPE_PROP(ZeroEqTypeTag, Problem, Dumux::FreeFlowSubProblem ); - -SET_BOOL_PROP(ZeroEqTypeTag, EnableFVGridGeometryCache, true); -SET_BOOL_PROP(ZeroEqTypeTag, EnableGridFluxVariablesCache, true); -SET_BOOL_PROP(ZeroEqTypeTag, EnableGridVolumeVariablesCache, true); - -SET_BOOL_PROP(ZeroEqTypeTag, EnableInertiaTerms, true); +template +struct Problem { using type = Dumux::FreeFlowSubProblem ; }; + +template +struct EnableFVGridGeometryCache { static constexpr bool value = true; }; +template +struct EnableGridFluxVariablesCache { static constexpr bool value = true; }; +template +struct EnableGridVolumeVariablesCache { static constexpr bool value = true; }; } /*! @@ -90,31 +99,31 @@ class FreeFlowSubProblem : public NavierStokesProblem using ParentType = NavierStokesProblem; #endif - using GridView = typename GET_PROP_TYPE(TypeTag, GridView); - using Scalar = typename GET_PROP_TYPE(TypeTag, Scalar); - using FluidSystem = typename GET_PROP_TYPE(TypeTag, FluidSystem); - using Indices = typename GET_PROP_TYPE(TypeTag, ModelTraits)::Indices; - using BoundaryTypes = typename GET_PROP_TYPE(TypeTag, BoundaryTypes); + using GridView = GetPropType; + using Scalar = GetPropType; + using FluidSystem = GetPropType; + using Indices = typename GetPropType::Indices; + using BoundaryTypes = GetPropType; - using FVGridGeometry = typename GET_PROP_TYPE(TypeTag, FVGridGeometry); + using FVGridGeometry = GetPropType; using FVElementGeometry = typename FVGridGeometry::LocalView; using SubControlVolumeFace = typename FVElementGeometry::SubControlVolumeFace; using Element = typename GridView::template Codim<0>::Entity; - using ElementVolumeVariables = typename GET_PROP_TYPE(TypeTag, GridVolumeVariables)::LocalView; - using ElementFaceVariables = typename GET_PROP_TYPE(TypeTag, GridFaceVariables)::LocalView; - using FluidState = typename GET_PROP_TYPE(TypeTag, FluidState); + using ElementVolumeVariables = typename GetPropType::LocalView; + using ElementFaceVariables = typename GetPropType::LocalView; + using FluidState = GetPropType; using GlobalPosition = typename Element::Geometry::GlobalCoordinate; - using PrimaryVariables = typename GET_PROP_TYPE(TypeTag, PrimaryVariables); - using NumEqVector = typename GET_PROP_TYPE(TypeTag, NumEqVector); + using PrimaryVariables = GetPropType; + using NumEqVector = GetPropType; - using CouplingManager = typename GET_PROP_TYPE(TypeTag, CouplingManager); + using CouplingManager = GetPropType; using TimeLoopPtr = std::shared_ptr>; using DiffusionCoefficientAveragingType = typename StokesDarcyCouplingOptions::DiffusionCoefficientAveragingType; - static constexpr bool useMoles = GET_PROP_TYPE(TypeTag, ModelTraits)::useMoles(); + static constexpr bool useMoles = GetPropType::useMoles(); public: FreeFlowSubProblem(std::shared_ptr fvGridGeometry, std::shared_ptr couplingManager) @@ -173,7 +182,7 @@ public: values.setDirichlet(Indices::velocityXIdx); values.setDirichlet(Indices::velocityYIdx); values.setDirichlet(Indices::conti0EqIdx + 1); - values.setDirichlet(Indices::energyBalanceIdx); + values.setDirichlet(Indices::energyEqIdx); } if (onLowerBoundary_(globalPos)) @@ -182,7 +191,7 @@ public: values.setDirichlet(Indices::velocityYIdx); values.setNeumann(Indices::conti0EqIdx); values.setNeumann(Indices::conti0EqIdx + 1); - values.setNeumann(Indices::energyBalanceIdx); + values.setNeumann(Indices::energyEqIdx); } if (onUpperBoundary_(globalPos)) @@ -194,7 +203,7 @@ public: values.setDirichlet(Indices::velocityYIdx); values.setNeumann(Indices::conti0EqIdx); values.setNeumann(Indices::conti0EqIdx + 1); - values.setNeumann(Indices::energyBalanceIdx); + values.setNeumann(Indices::energyEqIdx); #endif } @@ -202,14 +211,14 @@ public: { values.setDirichlet(Indices::pressureIdx); values.setOutflow(Indices::conti0EqIdx + 1); - values.setOutflow(Indices::energyBalanceIdx); + values.setOutflow(Indices::energyEqIdx); } if (couplingManager().isCoupledEntity(CouplingManager::stokesIdx, scvf)) { values.setCouplingNeumann(Indices::conti0EqIdx); values.setCouplingNeumann(Indices::conti0EqIdx + 1); - values.setCouplingNeumann(Indices::energyBalanceIdx); + values.setCouplingNeumann(Indices::energyEqIdx); values.setCouplingNeumann(Indices::momentumYBalanceIdx); values.setBJS(Indices::momentumXBalanceIdx); } @@ -248,12 +257,12 @@ public: PrimaryVariables values(0.0); if(couplingManager().isCoupledEntity(CouplingManager::stokesIdx, scvf)) { - values[Indices::momentumYBalanceIdx] = couplingManager().couplingData().momentumCouplingCondition(fvGeometry, elemVolVars, elemFaceVars, scvf); + values[Indices::momentumYBalanceIdx] = couplingManager().couplingData().momentumCouplingCondition(element, fvGeometry, elemVolVars, elemFaceVars, scvf); - const auto massFlux = couplingManager().couplingData().massCouplingCondition(fvGeometry, elemVolVars, elemFaceVars, scvf, diffCoeffAvgType_); + const auto massFlux = couplingManager().couplingData().massCouplingCondition(element, fvGeometry, elemVolVars, elemFaceVars, scvf, diffCoeffAvgType_); values[Indices::conti0EqIdx] = massFlux[0]; values[Indices::conti0EqIdx + 1] = massFlux[1]; - values[Indices::energyBalanceIdx] = couplingManager().couplingData().energyCouplingCondition(fvGeometry, elemVolVars, elemFaceVars, scvf, diffCoeffAvgType_); + values[Indices::energyEqIdx] = couplingManager().couplingData().energyCouplingCondition(element, fvGeometry, elemVolVars, elemFaceVars, scvf, diffCoeffAvgType_); } return values; } @@ -273,12 +282,12 @@ public: { return *couplingManager_; } #if EXNUMBER >= 2 - bool isOnWall(const GlobalPosition& globalPos) const + bool isOnWallAtPos(const GlobalPosition& globalPos) const { return (onLowerBoundary_(globalPos)); } #elif EXNUMBER >= 1 - bool isOnWall(const GlobalPosition& globalPos) const + bool isOnWallAtPos(const GlobalPosition& globalPos) const { return (onLowerBoundary_(globalPos) || onUpperBoundary_(globalPos)); } @@ -341,7 +350,7 @@ public: /*! * \brief Returns the intrinsic permeability of required as input parameter for the Beavers-Joseph-Saffman boundary condition */ - Scalar permeability(const SubControlVolumeFace& scvf) const + Scalar permeability(const Element& element, const SubControlVolumeFace& scvf) const { return couplingManager().problem(CouplingManager::darcyIdx).spatialParams().permeabilityAtPos(scvf.center()); } diff --git a/exercises/solution/exercise-coupling-ff-pm/turbulence/ex_turbulence_pmproblem.hh b/exercises/solution/exercise-coupling-ff-pm/turbulence/ex_turbulence_pmproblem.hh index 1b46ce7..e8d4477 100644 --- a/exercises/solution/exercise-coupling-ff-pm/turbulence/ex_turbulence_pmproblem.hh +++ b/exercises/solution/exercise-coupling-ff-pm/turbulence/ex_turbulence_pmproblem.hh @@ -42,27 +42,37 @@ class DarcySubProblem; namespace Properties { -NEW_TYPE_TAG(DarcyTwoPTwoCTypeTag, INHERITS_FROM(CCTpfaModel, TwoPTwoCNI)); +// Create new type tags +namespace TTag { +struct DarcyTwoPTwoCTypeTag { using InheritsFrom = std::tuple; }; +} // end namespace TTag // Set the problem property -SET_TYPE_PROP(DarcyTwoPTwoCTypeTag, Problem, Dumux::DarcySubProblem); +template +struct Problem { using type = Dumux::DarcySubProblem; }; // the fluid system -SET_TYPE_PROP(DarcyTwoPTwoCTypeTag, FluidSystem, FluidSystems::H2OAir); +template +struct FluidSystem { using type = FluidSystems::H2OAir>; }; //! Set the default formulation to pw-Sn: This can be over written in the problem. -SET_PROP(DarcyTwoPTwoCTypeTag, Formulation) +template +struct Formulation { static constexpr auto value = TwoPFormulation::p1s0; }; // The gas component balance (air) is replaced by the total mass balance -SET_INT_PROP(DarcyTwoPTwoCTypeTag, ReplaceCompEqIdx, 3); +template +struct ReplaceCompEqIdx { static constexpr int value = 3; }; // Set the grid type -SET_TYPE_PROP(DarcyTwoPTwoCTypeTag, Grid, Dune::YaspGrid<2, Dune::TensorProductCoordinates >); +template +struct Grid { using type = Dune::YaspGrid<2, Dune::TensorProductCoordinates, 2> >; }; -SET_BOOL_PROP(DarcyTwoPTwoCTypeTag, UseMoles, true); +template +struct UseMoles { static constexpr bool value = true; }; -SET_TYPE_PROP(DarcyTwoPTwoCTypeTag, SpatialParams, TwoPSpatialParams); +template +struct SpatialParams { using type = TwoPSpatialParams; }; } /*! @@ -72,22 +82,22 @@ template class DarcySubProblem : public PorousMediumFlowProblem { using ParentType = PorousMediumFlowProblem; - using GridView = typename GET_PROP_TYPE(TypeTag, GridView); - using Scalar = typename GET_PROP_TYPE(TypeTag, Scalar); - using PrimaryVariables = typename GET_PROP_TYPE(TypeTag, PrimaryVariables); - using NumEqVector = typename GET_PROP_TYPE(TypeTag, NumEqVector); - using BoundaryTypes = typename GET_PROP_TYPE(TypeTag, BoundaryTypes); - using VolumeVariables = typename GET_PROP_TYPE(TypeTag, VolumeVariables); - using FVElementGeometry = typename GET_PROP_TYPE(TypeTag, FVGridGeometry)::LocalView; + using GridView = GetPropType; + using Scalar = GetPropType; + using PrimaryVariables = GetPropType; + using NumEqVector = GetPropType; + using BoundaryTypes = GetPropType; + using VolumeVariables = GetPropType; + using FVElementGeometry = typename GetPropType::LocalView; using SubControlVolume = typename FVElementGeometry::SubControlVolume; using SubControlVolumeFace = typename FVElementGeometry::SubControlVolumeFace; - using FVGridGeometry = typename GET_PROP_TYPE(TypeTag, FVGridGeometry); - using ElementVolumeVariables = typename GET_PROP_TYPE(TypeTag, GridVolumeVariables)::LocalView; + using FVGridGeometry = GetPropType; + using ElementVolumeVariables = typename GetPropType::LocalView; - using FluidSystem = typename GET_PROP_TYPE(TypeTag, FluidSystem); + using FluidSystem = GetPropType; // copy some indices for convenience - using Indices = typename GET_PROP_TYPE(TypeTag, ModelTraits)::Indices; + using Indices = typename GetPropType::Indices; enum { // primary variable indices conti0EqIdx = Indices::conti0EqIdx, @@ -100,7 +110,7 @@ class DarcySubProblem : public PorousMediumFlowProblem using Element = typename GridView::template Codim<0>::Entity; using GlobalPosition = typename Element::Geometry::GlobalCoordinate; - using CouplingManager = typename GET_PROP_TYPE(TypeTag, CouplingManager); + using CouplingManager = GetPropType; using TimeLoopPtr = std::shared_ptr>; using DiffusionCoefficientAveragingType = typename StokesDarcyCouplingOptions::DiffusionCoefficientAveragingType; @@ -220,12 +230,12 @@ public: if (couplingManager().isCoupledEntity(CouplingManager::darcyIdx, scvf)) { - const auto massFlux = couplingManager().couplingData().massCouplingCondition(fvGeometry, elemVolVars, scvf, diffCoeffAvgType_); + const auto massFlux = couplingManager().couplingData().massCouplingCondition(element, fvGeometry, elemVolVars, scvf, diffCoeffAvgType_); for(int i = 0; i< massFlux.size(); ++i) values[i] = massFlux[i]; - values[Indices::energyEqIdx] = couplingManager().couplingData().energyCouplingCondition(fvGeometry, elemVolVars, scvf, diffCoeffAvgType_); + values[Indices::energyEqIdx] = couplingManager().couplingData().energyCouplingCondition(element, fvGeometry, elemVolVars, scvf, diffCoeffAvgType_); } return values; -- GitLab From 0bc75014363c3110dd00c2cd04bd5d10b0fe62e8 Mon Sep 17 00:00:00 2001 From: Theresa Kurz Date: Thu, 13 Dec 2018 11:39:12 +0100 Subject: [PATCH 17/25] [cleanup] rename VtkOutputFields to IOFields --- exercises/exercise-basic/exercise_basic_2p2c.cc | 9 ++------- .../exercise-biomineralization/exercisebiomin.cc | 6 +++--- .../interface/ex_interface_coupling_ff-pm.cc | 2 +- .../models/ex_models_coupling_ff-pm.cc | 2 +- .../turbulence/ex_turbulence_coupling_ff-pm.cc | 2 +- .../exercise-fluidsystem/exercise-fluidsystem.cc | 4 ++-- exercises/exercise-fractures/exercise_fractures.cc | 8 ++++---- exercises/exercise-grids/exercise_grids.cc | 4 ++-- exercises/exercise-mainfile/exercise_1p_c.cc | 2 +- exercises/exercise-properties/exercise_properties.cc | 7 ++----- .../exercise-runtimeparams/exercise_runtimeparams.cc | 4 ++-- .../solution/exercise-basic/exercise_basic_2pni.cc | 4 ++-- .../exercise-biomineralization/exercisebiomin.cc | 6 +++--- .../interface/ex_interface_coupling_ff-pm.cc | 2 +- .../models/ex_models_coupling_ff-pm.cc | 2 +- .../turbulence/ex_turbulence_coupling_ff-pm.cc | 2 +- .../exercise-fluidsystem/exercise-fluidsystem.cc | 6 +++--- .../fluidsystems/h2omycompressiblecomponent.hh | 6 ++++++ .../exercise-fractures/exercise_fractures.cc | 8 ++++---- .../exercise-grids/exercise_grids_solution.cc | 4 ++-- .../solution/exercise-grids/injection2pproblem.hh | 12 ++++++------ .../exercise_properties_solution.cc | 7 ++----- .../solution/exercise-properties/mylocalresidual.hh | 2 +- .../exercise_runtimeparams_solution.cc | 4 ++-- 24 files changed, 55 insertions(+), 60 deletions(-) diff --git a/exercises/exercise-basic/exercise_basic_2p2c.cc b/exercises/exercise-basic/exercise_basic_2p2c.cc index 68c91ea..3232900 100644 --- a/exercises/exercise-basic/exercise_basic_2p2c.cc +++ b/exercises/exercise-basic/exercise_basic_2p2c.cc @@ -124,16 +124,11 @@ int main(int argc, char** argv) try auto dt = getParam("TimeLoop.DtInitial"); // intialize the vtk output module -// using VtkOutputFields = GetPropType; -// VtkOutputModule vtkWriter(*problem, *fvGridGeometry, *gridVariables, x, problem->name()); -// VtkOutputFields::init(vtkWriter); //! Add model specific output fields - - // intialize the vtk output module - using VtkOutputFields = GetPropType; + using IOFields = GetPropType; VtkOutputModule vtkWriter(*gridVariables, x, problem->name()); using VelocityOutput = GetPropType; vtkWriter.addVelocityOutput(std::make_shared(*gridVariables)); - VtkOutputFields::initOutputModule(vtkWriter); //!< Add model specific output fields + IOFields::initOutputModule(vtkWriter); //!< Add model specific output fields vtkWriter.write(restartTime); // instantiate time loop diff --git a/exercises/exercise-biomineralization/exercisebiomin.cc b/exercises/exercise-biomineralization/exercisebiomin.cc index a4cbddf..0ac7f19 100644 --- a/exercises/exercise-biomineralization/exercisebiomin.cc +++ b/exercises/exercise-biomineralization/exercisebiomin.cc @@ -104,7 +104,7 @@ int main(int argc, char** argv) try // the grid variables using GridVariables = GetPropType; auto gridVariables = std::make_shared(problem, fvGridGeometry); - gridVariables->init(x, xOld); + gridVariables->init(x); // get some time loop parameters using Scalar = GetPropType; @@ -113,9 +113,9 @@ int main(int argc, char** argv) try auto dt = getParam("TimeLoop.DtInitial"); // initialize the vtk output module - using VtkOutputFields = GetPropType; + using IOFields = GetPropType; VtkOutputModule vtkWriter(*gridVariables, x, problem->name()); - VtkOutputFields::init(vtkWriter); //!< Add model specific output fields + IOFields::initOutputModule(vtkWriter); //!< Add model specific output fields //add specific output vtkWriter.addField(problem->getKxx(), "Kxx"); vtkWriter.addField(problem->getKyy(), "Kyy"); diff --git a/exercises/exercise-coupling-ff-pm/interface/ex_interface_coupling_ff-pm.cc b/exercises/exercise-coupling-ff-pm/interface/ex_interface_coupling_ff-pm.cc index 62673d5..53c927f 100644 --- a/exercises/exercise-coupling-ff-pm/interface/ex_interface_coupling_ff-pm.cc +++ b/exercises/exercise-coupling-ff-pm/interface/ex_interface_coupling_ff-pm.cc @@ -202,7 +202,7 @@ int main(int argc, char** argv) try const auto darcyName = getParam("Problem.Name") + "_" + darcyProblem->name(); StaggeredVtkOutputModule stokesVtkWriter(*stokesGridVariables, stokesSol, stokesName); - GetPropType::initOutputModule(stokesVtkWriter); + GetPropType::initOutputModule(stokesVtkWriter); //****** uncomment the add analytical solution of v_x *****// // stokesVtkWriter.addField(stokesProblem->getAnalyticalVelocityX(), "analyticalV_x"); diff --git a/exercises/exercise-coupling-ff-pm/models/ex_models_coupling_ff-pm.cc b/exercises/exercise-coupling-ff-pm/models/ex_models_coupling_ff-pm.cc index 8dc210c..48d89fe 100644 --- a/exercises/exercise-coupling-ff-pm/models/ex_models_coupling_ff-pm.cc +++ b/exercises/exercise-coupling-ff-pm/models/ex_models_coupling_ff-pm.cc @@ -172,7 +172,7 @@ int main(int argc, char** argv) try const auto darcyName = getParam("Problem.Name") + "_" + darcyProblem->name(); StaggeredVtkOutputModule stokesVtkWriter(*stokesGridVariables, stokesSol, stokesName); - GetPropType::initOutputModule(stokesVtkWriter); + GetPropType::initOutputModule(stokesVtkWriter); stokesVtkWriter.write(0.0); VtkOutputModule> darcyVtkWriter(*darcyGridVariables, sol[darcyIdx], darcyName); diff --git a/exercises/exercise-coupling-ff-pm/turbulence/ex_turbulence_coupling_ff-pm.cc b/exercises/exercise-coupling-ff-pm/turbulence/ex_turbulence_coupling_ff-pm.cc index 523a337..3d756d6 100644 --- a/exercises/exercise-coupling-ff-pm/turbulence/ex_turbulence_coupling_ff-pm.cc +++ b/exercises/exercise-coupling-ff-pm/turbulence/ex_turbulence_coupling_ff-pm.cc @@ -177,7 +177,7 @@ int main(int argc, char** argv) try const auto darcyName = getParam("Problem.Name") + "_" + darcyProblem->name(); StaggeredVtkOutputModule stokesVtkWriter(*stokesGridVariables, stokesSol, stokesName); - GetPropType::initOutputModule(stokesVtkWriter); + GetPropType::initOutputModule(stokesVtkWriter); stokesVtkWriter.write(0.0); VtkOutputModule> darcyVtkWriter(*darcyGridVariables, sol[darcyIdx], darcyName); diff --git a/exercises/exercise-fluidsystem/exercise-fluidsystem.cc b/exercises/exercise-fluidsystem/exercise-fluidsystem.cc index 61f3df1..184814d 100644 --- a/exercises/exercise-fluidsystem/exercise-fluidsystem.cc +++ b/exercises/exercise-fluidsystem/exercise-fluidsystem.cc @@ -116,11 +116,11 @@ int main(int argc, char** argv) try auto dt = getParam("TimeLoop.DtInitial"); // intialize the vtk output module - using VtkOutputFields = GetPropType; + using IOFields = GetPropType; VtkOutputModule vtkWriter(*gridVariables, x, problem->name()); using VelocityOutput = GetPropType; vtkWriter.addVelocityOutput(std::make_shared(*gridVariables)); - VtkOutputFields::initOutputModule(vtkWriter); //!< Add model specific output fields + IOFields::initOutputModule(vtkWriter); //!< Add model specific output fields // instantiate time loop auto timeLoop = std::make_shared>(/*start time*/0.0, dt, tEnd); diff --git a/exercises/exercise-fractures/exercise_fractures.cc b/exercises/exercise-fractures/exercise_fractures.cc index 7a61562..55ebc0d 100644 --- a/exercises/exercise-fractures/exercise_fractures.cc +++ b/exercises/exercise-fractures/exercise_fractures.cc @@ -187,10 +187,10 @@ int main(int argc, char** argv) try FractureVtkOutputModule fractureVtkWriter(*fractureGridVariables, x[fractureDomainId], fractureProblem->name()); // Add model specific output fields - using MatrixVtkOutputFields = GetPropType; - using FractureVtkOutputFields = GetPropType; - MatrixVtkOutputFields::initOutputModule(matrixVtkWriter); - FractureVtkOutputFields::initOutputModule(fractureVtkWriter); + using MatrixIOFields = GetPropType; + using FractureIOFields = GetPropType; + MatrixIOFields::initOutputModule(matrixVtkWriter); + FractureIOFields::initOutputModule(fractureVtkWriter); // add domain markers to output std::vector matrixDomainMarkers(matrixFvGridGeometry->gridView().size(0)); diff --git a/exercises/exercise-grids/exercise_grids.cc b/exercises/exercise-grids/exercise_grids.cc index 4c5a065..5f57026 100644 --- a/exercises/exercise-grids/exercise_grids.cc +++ b/exercises/exercise-grids/exercise_grids.cc @@ -125,11 +125,11 @@ int main(int argc, char** argv) try auto dt = getParam("TimeLoop.DtInitial"); // intialize the vtk output module - using VtkOutputFields = GetPropType; + using IOFields = GetPropType; VtkOutputModule vtkWriter(*gridVariables, x, problem->name()); using VelocityOutput = GetPropType; vtkWriter.addVelocityOutput(std::make_shared(*gridVariables)); - VtkOutputFields::initOutputModule(vtkWriter); //!< Add model specific output fields + IOFields::initOutputModule(vtkWriter); //!< Add model specific output fields vtkWriter.write(restartTime); // instantiate time loop diff --git a/exercises/exercise-mainfile/exercise_1p_c.cc b/exercises/exercise-mainfile/exercise_1p_c.cc index 11f31b1..94636e1 100644 --- a/exercises/exercise-mainfile/exercise_1p_c.cc +++ b/exercises/exercise-mainfile/exercise_1p_c.cc @@ -99,7 +99,7 @@ int main(int argc, char** argv) try // the grid variables using GridVariables = GetPropType; auto gridVariables = std::make_shared(problem, fvGridGeometry); - gridVariables->init(x, xOld); + gridVariables->init(x); // intialize the vtk output module VtkOutputModule vtkWriter(*gridVariables, x, problem->name()); diff --git a/exercises/exercise-properties/exercise_properties.cc b/exercises/exercise-properties/exercise_properties.cc index 558a13a..edcb4c5 100644 --- a/exercises/exercise-properties/exercise_properties.cc +++ b/exercises/exercise-properties/exercise_properties.cc @@ -155,14 +155,11 @@ int main(int argc, char** argv) try auto dt = getParam("TimeLoop.DtInitial"); // intialize the vtk output module - using VtkOutputFields = GetPropType; - - // intialize the vtk output module - using VtkOutputFields = GetPropType; + using IOFields = GetPropType; VtkOutputModule vtkWriter(*gridVariables, x, problem->name()); using VelocityOutput = GetPropType; vtkWriter.addVelocityOutput(std::make_shared(*gridVariables)); - VtkOutputFields::initOutputModule(vtkWriter); //!< Add model specific output fields + IOFields::initOutputModule(vtkWriter); //!< Add model specific output fields vtkWriter.write(restartTime); // instantiate time loop diff --git a/exercises/exercise-runtimeparams/exercise_runtimeparams.cc b/exercises/exercise-runtimeparams/exercise_runtimeparams.cc index 315fb6f..e1f5979 100644 --- a/exercises/exercise-runtimeparams/exercise_runtimeparams.cc +++ b/exercises/exercise-runtimeparams/exercise_runtimeparams.cc @@ -125,11 +125,11 @@ int main(int argc, char** argv) try auto dt = getParam("TimeLoop.DtInitial"); // intialize the vtk output module - using VtkOutputFields = GetPropType; + using IOFields = GetPropType; VtkOutputModule vtkWriter(*gridVariables, x, problem->name()); using VelocityOutput = GetPropType; vtkWriter.addVelocityOutput(std::make_shared(*gridVariables)); - VtkOutputFields::initOutputModule(vtkWriter); //!< Add model specific output fields + IOFields::initOutputModule(vtkWriter); //!< Add model specific output fields vtkWriter.write(restartTime); // instantiate time loop diff --git a/exercises/solution/exercise-basic/exercise_basic_2pni.cc b/exercises/solution/exercise-basic/exercise_basic_2pni.cc index 3a9037d..e8e234a 100644 --- a/exercises/solution/exercise-basic/exercise_basic_2pni.cc +++ b/exercises/solution/exercise-basic/exercise_basic_2pni.cc @@ -123,11 +123,11 @@ int main(int argc, char** argv) try auto dt = getParam("TimeLoop.DtInitial"); // intialize the vtk output module - using VtkOutputFields = GetPropType; + using IOFields = GetPropType; VtkOutputModule vtkWriter(*gridVariables, x, problem->name()); using VelocityOutput = GetPropType; vtkWriter.addVelocityOutput(std::make_shared(*gridVariables)); - VtkOutputFields::initOutputModule(vtkWriter); //!< Add model specific output fields + IOFields::initOutputModule(vtkWriter); //!< Add model specific output fields vtkWriter.write(restartTime); // instantiate time loop diff --git a/exercises/solution/exercise-biomineralization/exercisebiomin.cc b/exercises/solution/exercise-biomineralization/exercisebiomin.cc index a4cbddf..0ac7f19 100644 --- a/exercises/solution/exercise-biomineralization/exercisebiomin.cc +++ b/exercises/solution/exercise-biomineralization/exercisebiomin.cc @@ -104,7 +104,7 @@ int main(int argc, char** argv) try // the grid variables using GridVariables = GetPropType; auto gridVariables = std::make_shared(problem, fvGridGeometry); - gridVariables->init(x, xOld); + gridVariables->init(x); // get some time loop parameters using Scalar = GetPropType; @@ -113,9 +113,9 @@ int main(int argc, char** argv) try auto dt = getParam("TimeLoop.DtInitial"); // initialize the vtk output module - using VtkOutputFields = GetPropType; + using IOFields = GetPropType; VtkOutputModule vtkWriter(*gridVariables, x, problem->name()); - VtkOutputFields::init(vtkWriter); //!< Add model specific output fields + IOFields::initOutputModule(vtkWriter); //!< Add model specific output fields //add specific output vtkWriter.addField(problem->getKxx(), "Kxx"); vtkWriter.addField(problem->getKyy(), "Kyy"); diff --git a/exercises/solution/exercise-coupling-ff-pm/interface/ex_interface_coupling_ff-pm.cc b/exercises/solution/exercise-coupling-ff-pm/interface/ex_interface_coupling_ff-pm.cc index 8443475..4f3bc84 100644 --- a/exercises/solution/exercise-coupling-ff-pm/interface/ex_interface_coupling_ff-pm.cc +++ b/exercises/solution/exercise-coupling-ff-pm/interface/ex_interface_coupling_ff-pm.cc @@ -192,7 +192,7 @@ int main(int argc, char** argv) try const auto darcyName = getParam("Problem.Name") + "_" + darcyProblem->name(); StaggeredVtkOutputModule stokesVtkWriter(*stokesGridVariables, stokesSol, stokesName); - GetPropType::initOutputModule(stokesVtkWriter); + GetPropType::initOutputModule(stokesVtkWriter); #if EXNUMBER >= 2 stokesVtkWriter.addField(stokesProblem->getAnalyticalVelocityX(), "analyticalV_x"); diff --git a/exercises/solution/exercise-coupling-ff-pm/models/ex_models_coupling_ff-pm.cc b/exercises/solution/exercise-coupling-ff-pm/models/ex_models_coupling_ff-pm.cc index 8528aeb..da40064 100644 --- a/exercises/solution/exercise-coupling-ff-pm/models/ex_models_coupling_ff-pm.cc +++ b/exercises/solution/exercise-coupling-ff-pm/models/ex_models_coupling_ff-pm.cc @@ -178,7 +178,7 @@ int main(int argc, char** argv) try #endif StaggeredVtkOutputModule stokesVtkWriter(*stokesGridVariables, stokesSol, stokesName); - GetPropType::initOutputModule(stokesVtkWriter); + GetPropType::initOutputModule(stokesVtkWriter); stokesVtkWriter.write(0); VtkOutputModule> darcyVtkWriter(*darcyGridVariables, sol[darcyIdx], darcyName); diff --git a/exercises/solution/exercise-coupling-ff-pm/turbulence/ex_turbulence_coupling_ff-pm.cc b/exercises/solution/exercise-coupling-ff-pm/turbulence/ex_turbulence_coupling_ff-pm.cc index ac7f758..a50ebce 100644 --- a/exercises/solution/exercise-coupling-ff-pm/turbulence/ex_turbulence_coupling_ff-pm.cc +++ b/exercises/solution/exercise-coupling-ff-pm/turbulence/ex_turbulence_coupling_ff-pm.cc @@ -180,7 +180,7 @@ int main(int argc, char** argv) try const auto darcyName = getParam("Problem.Name") + "_" + darcyProblem->name(); StaggeredVtkOutputModule stokesVtkWriter(*stokesGridVariables, stokesSol, stokesName); - GetPropType::initOutputModule(stokesVtkWriter); + GetPropType::initOutputModule(stokesVtkWriter); stokesVtkWriter.write(0.0); VtkOutputModule> darcyVtkWriter(*darcyGridVariables, sol[darcyIdx], darcyName); diff --git a/exercises/solution/exercise-fluidsystem/exercise-fluidsystem.cc b/exercises/solution/exercise-fluidsystem/exercise-fluidsystem.cc index ce136ff..723a640 100644 --- a/exercises/solution/exercise-fluidsystem/exercise-fluidsystem.cc +++ b/exercises/solution/exercise-fluidsystem/exercise-fluidsystem.cc @@ -105,7 +105,7 @@ int main(int argc, char** argv) try // the grid variables using GridVariables = GetPropType; auto gridVariables = std::make_shared(problem, fvGridGeometry); - gridVariables->init(x, xOld); + gridVariables->init(x); // get some time loop parameters using Scalar = GetPropType; @@ -113,11 +113,11 @@ int main(int argc, char** argv) try const auto maxDt = getParam("TimeLoop.MaxTimeStepSize"); auto dt = getParam("TimeLoop.DtInitial"); // intialize the vtk output module - using VtkOutputFields = GetPropType; + using IOFields = GetPropType; VtkOutputModule vtkWriter(*gridVariables, x, problem->name()); using VelocityOutput = GetPropType; vtkWriter.addVelocityOutput(std::make_shared(*gridVariables)); - VtkOutputFields::initOutputModule(vtkWriter); //!< Add model specific output fields + IOFields::initOutputModule(vtkWriter); //!< Add model specific output fields // instantiate time loop auto timeLoop = std::make_shared>(/*start time*/0.0, dt, tEnd); diff --git a/exercises/solution/exercise-fluidsystem/fluidsystems/h2omycompressiblecomponent.hh b/exercises/solution/exercise-fluidsystem/fluidsystems/h2omycompressiblecomponent.hh index 6f4d9be..4ff5595 100644 --- a/exercises/solution/exercise-fluidsystem/fluidsystems/h2omycompressiblecomponent.hh +++ b/exercises/solution/exercise-fluidsystem/fluidsystems/h2omycompressiblecomponent.hh @@ -122,6 +122,12 @@ public: return true; } + static constexpr bool isGas(int phaseIdx) + { + assert(0 <= phaseIdx && phaseIdx < numPhases); + return phaseIdx == phase1Idx; + } + static constexpr bool isIdealGas(int phaseIdx) { return H2O::gasIsIdeal() && MyCompressibleComponent::gasIsIdeal(); } diff --git a/exercises/solution/exercise-fractures/exercise_fractures.cc b/exercises/solution/exercise-fractures/exercise_fractures.cc index ac6a9f1..c545a6e 100644 --- a/exercises/solution/exercise-fractures/exercise_fractures.cc +++ b/exercises/solution/exercise-fractures/exercise_fractures.cc @@ -180,10 +180,10 @@ int main(int argc, char** argv) try VtkOutputModule fractureVtkWriter(*fractureProblem, *fractureFvGridGeometry, *fractureGridVariables, x[fractureDomainId], fractureProblem->name()); // Add model specific output fields - using MatrixVtkOutputFields = typename GET_PROP_TYPE(MatrixTypeTag, VtkOutputFields); - using FractureVtkOutputFields = typename GET_PROP_TYPE(FractureTypeTag, VtkOutputFields); - MatrixVtkOutputFields::init(matrixVtkWriter); - FractureVtkOutputFields::init(fractureVtkWriter); + using MatrixIOFields = typename GET_PROP_TYPE(MatrixTypeTag, IOFields); + using FractureIOFields = typename GET_PROP_TYPE(FractureTypeTag, IOFields); + MatrixIOFields::initOutputModule(matrixVtkWriter); + FractureIOFields::initOutputModule(fractureVtkWriter); // add domain markers to output std::vector matrixDomainMarkers(matrixFvGridGeometry->gridView().size(0)); diff --git a/exercises/solution/exercise-grids/exercise_grids_solution.cc b/exercises/solution/exercise-grids/exercise_grids_solution.cc index 6a90753..0f5ba98 100644 --- a/exercises/solution/exercise-grids/exercise_grids_solution.cc +++ b/exercises/solution/exercise-grids/exercise_grids_solution.cc @@ -125,11 +125,11 @@ int main(int argc, char** argv) try auto dt = getParam("TimeLoop.DtInitial"); // intialize the vtk output module - using VtkOutputFields = GetPropType; + using IOFields = GetPropType; VtkOutputModule vtkWriter(*gridVariables, x, problem->name()); using VelocityOutput = GetPropType; vtkWriter.addVelocityOutput(std::make_shared(*gridVariables)); - VtkOutputFields::initOutputModule(vtkWriter); //!< Add model specific output fields + IOFields::initOutputModule(vtkWriter); //!< Add model specific output fields vtkWriter.write(restartTime); // instantiate time loop diff --git a/exercises/solution/exercise-grids/injection2pproblem.hh b/exercises/solution/exercise-grids/injection2pproblem.hh index 325d555..a18e2f4 100644 --- a/exercises/solution/exercise-grids/injection2pproblem.hh +++ b/exercises/solution/exercise-grids/injection2pproblem.hh @@ -47,19 +47,19 @@ struct Injection2pCCTypeTag { using InheritsFrom = std::tuple -struct Grid { using type = Dune::YaspGrid<2>; }; +// template +// struct Grid { using type = Dune::YaspGrid<2>; }; // TODO: Task 2: Replace the above Grid Property definition with a more flexible grid (Use Dune::TensorProductCoordinates) template struct Grid { using type = Dune::YaspGrid<2, Dune::TensorProductCoordinates >; }; // TODO: Task 4: Replace the above Grid Property definition to read in a external structured grid via a .msh file (Use Dune::ALUGrid and Dune:cube) -template -struct Grid { using type = Dune::ALUGrid<2, 2, Dune::cube, Dune::nonconforming>; }; +// template +// struct Grid { using type = Dune::ALUGrid<2, 2, Dune::cube, Dune::nonconforming>; }; // TODO: Task 5: Replace the above Grid Property definition to read in a external unstructured grid via a .msh file (Use Dune::ALUGrid and Dune::simplex) -template -struct Grid { using type = Dune::ALUGrid<2, 2, Dune::simplex, Dune::nonconforming>; }; +// template +// struct Grid { using type = Dune::ALUGrid<2, 2, Dune::simplex, Dune::nonconforming>; }; // Set the problem property template diff --git a/exercises/solution/exercise-properties/exercise_properties_solution.cc b/exercises/solution/exercise-properties/exercise_properties_solution.cc index 2b4e03a..f532f0d 100644 --- a/exercises/solution/exercise-properties/exercise_properties_solution.cc +++ b/exercises/solution/exercise-properties/exercise_properties_solution.cc @@ -154,14 +154,11 @@ int main(int argc, char** argv) try auto dt = getParam("TimeLoop.DtInitial"); // intialize the vtk output module - using VtkOutputFields = GetPropType; - - // intialize the vtk output module - using VtkOutputFields = GetPropType; + using IOFields = GetPropType; VtkOutputModule vtkWriter(*gridVariables, x, problem->name()); using VelocityOutput = GetPropType; vtkWriter.addVelocityOutput(std::make_shared(*gridVariables)); - VtkOutputFields::initOutputModule(vtkWriter); //!< Add model specific output fields + IOFields::initOutputModule(vtkWriter); //!< Add model specific output fields vtkWriter.write(restartTime); // instantiate time loop diff --git a/exercises/solution/exercise-properties/mylocalresidual.hh b/exercises/solution/exercise-properties/mylocalresidual.hh index 485f33a..2270f28 100644 --- a/exercises/solution/exercise-properties/mylocalresidual.hh +++ b/exercises/solution/exercise-properties/mylocalresidual.hh @@ -53,7 +53,7 @@ class MyLocalResidual : public GET_PROP_TYPE(TypeTag, BaseLocalResidual) using EnergyLocalResidual = typename GET_PROP_TYPE(TypeTag, EnergyLocalResidual); using ModelTraits = typename GET_PROP_TYPE(TypeTag, ModelTraits); - static constexpr int numPhases = ModelTraits::numPhases(); + static constexpr int numPhases = ModelTraits::numFluidPhases(); static constexpr int conti0EqIdx = ModelTraits::Indices::conti0EqIdx; //!< first index for the mass balance public: diff --git a/exercises/solution/exercise-runtimeparams/exercise_runtimeparams_solution.cc b/exercises/solution/exercise-runtimeparams/exercise_runtimeparams_solution.cc index 315fb6f..e1f5979 100644 --- a/exercises/solution/exercise-runtimeparams/exercise_runtimeparams_solution.cc +++ b/exercises/solution/exercise-runtimeparams/exercise_runtimeparams_solution.cc @@ -125,11 +125,11 @@ int main(int argc, char** argv) try auto dt = getParam("TimeLoop.DtInitial"); // intialize the vtk output module - using VtkOutputFields = GetPropType; + using IOFields = GetPropType; VtkOutputModule vtkWriter(*gridVariables, x, problem->name()); using VelocityOutput = GetPropType; vtkWriter.addVelocityOutput(std::make_shared(*gridVariables)); - VtkOutputFields::initOutputModule(vtkWriter); //!< Add model specific output fields + IOFields::initOutputModule(vtkWriter); //!< Add model specific output fields vtkWriter.write(restartTime); // instantiate time loop -- GitLab From 5affa74e0d8a3099fc9ff6e6940ed62128466cc1 Mon Sep 17 00:00:00 2001 From: Felix Weinhardt Date: Fri, 14 Dec 2018 11:57:25 +0100 Subject: [PATCH 18/25] [exercise-basic] changed captions Task 2, Task 3 and Task 4 to appear bold in the readme --- exercises/exercise-basic/README.md | 6 +++--- 1 file changed, 3 insertions(+), 3 deletions(-) diff --git a/exercises/exercise-basic/README.md b/exercises/exercise-basic/README.md index cc81fd4..f0dbdf8 100644 --- a/exercises/exercise-basic/README.md +++ b/exercises/exercise-basic/README.md @@ -25,7 +25,7 @@ Locate all the files you will need for this exercise * The shared __spatial parameters file__: `injection2pspatialparams.hh` * The shared __input file__: `exercise_basic.input` -


+

### Task 2: Compiling and running an executable
@@ -54,7 +54,7 @@ make exercise_basic_2p exercise_basic_2p2c paraview injection-2p2c.pvd ``` -


+

### Task 3: Setting up a new executable (for a non-isothermal simulation)
@@ -77,7 +77,7 @@ make # should rerun cmake make exercise_basic_2pni # builds new executable ``` -


+

### Task 4: Setting up a non-isothermal __2pni__ test problem
-- GitLab From 8a17b46055eacac9caffcb0b099e3fe3adee455b Mon Sep 17 00:00:00 2001 From: Theresa Kurz Date: Fri, 14 Dec 2018 15:12:00 +0100 Subject: [PATCH 19/25] [exercise-fracture] update solution --- .../exercise-fractures/exercise_fractures.cc | 47 +++++++++------- .../exercise-fractures/fractureproblem.hh | 50 ++++++++++------- .../exercise-fractures/matrixproblem.hh | 56 +++++++++++-------- 3 files changed, 90 insertions(+), 63 deletions(-) diff --git a/exercises/solution/exercise-fractures/exercise_fractures.cc b/exercises/solution/exercise-fractures/exercise_fractures.cc index c545a6e..55ebc0d 100644 --- a/exercises/solution/exercise-fractures/exercise_fractures.cc +++ b/exercises/solution/exercise-fractures/exercise_fractures.cc @@ -50,10 +50,10 @@ // Define some types for this test so that we can set them as properties below and // reuse them again in the main function with only one single definition of them here -using MatrixTypeTag = TTAG(MatrixProblemTypeTag); -using FractureTypeTag = TTAG(FractureProblemTypeTag); -using MatrixFVGridGeometry = typename GET_PROP_TYPE(MatrixTypeTag, FVGridGeometry); -using FractureFVGridGeometry = typename GET_PROP_TYPE(FractureTypeTag, FVGridGeometry); +using MatrixTypeTag = Dumux::Properties::TTag::MatrixProblemTypeTag; +using FractureTypeTag = Dumux::Properties::TTag::FractureProblemTypeTag; +using MatrixFVGridGeometry = Dumux::GetPropType; +using FractureFVGridGeometry = Dumux::GetPropType; using TheMultiDomainTraits = Dumux::MultiDomainTraits; using TheCouplingMapper = Dumux::FacetCouplingMapper; using TheCouplingManager = Dumux::FacetCouplingManager; @@ -61,8 +61,13 @@ using TheCouplingManager = Dumux::FacetCouplingManager +struct CouplingManager { using type = TheCouplingManager; }; + +template +struct CouplingManager { using type = TheCouplingManager; }; + } // end namespace Properties } // end namespace Dumux @@ -85,8 +90,8 @@ int main(int argc, char** argv) try // This requires the grids used to be passed as template arguments, where // they are assumed to be ordered in descending grid dimension. Thus, // we pass the matrix grid as first and the fracture grid as second argument. - using MatrixGrid = typename GET_PROP_TYPE(MatrixTypeTag, Grid); - using FractureGrid = typename GET_PROP_TYPE(FractureTypeTag, Grid); + using MatrixGrid = GetPropType; + using FractureGrid = GetPropType; using GridManager = Dumux::FacetCouplingGridManager; GridManager gridManager; @@ -114,8 +119,8 @@ int main(int argc, char** argv) try fractureFvGridGeometry->update(); // the problems (boundary/initial conditions etc) - using MatrixProblem = typename GET_PROP_TYPE(MatrixTypeTag, Problem); - using FractureProblem = typename GET_PROP_TYPE(FractureTypeTag, Problem); + using MatrixProblem = GetPropType; + using FractureProblem = GetPropType; // pass the model parameter group to the spatial params so that they obtain the right // values from the input file since we use groups for matrix and fracture @@ -140,8 +145,8 @@ int main(int argc, char** argv) try // in case you have more subdomains involved. We domain ids // correspond to the order of the type tags passed to the multidomain // traits (see definition of the traits class at the beginning of this file) - static const auto matrixDomainId = typename TheMultiDomainTraits::template DomainIdx<0>(); - static const auto fractureDomainId = typename TheMultiDomainTraits::template DomainIdx<1>(); + static const auto matrixDomainId = typename TheMultiDomainTraits::template SubDomain<0>::Index(); + static const auto fractureDomainId = typename TheMultiDomainTraits::template SubDomain<1>::Index(); // resize the solution vector and write initial solution to it x[matrixDomainId].resize(matrixFvGridGeometry->numDofs()); @@ -167,21 +172,23 @@ int main(int argc, char** argv) try fractureProblem->setCouplingManager(couplingManager); // the grid variables - using MatrixGridVariables = typename GET_PROP_TYPE(MatrixTypeTag, GridVariables); - using FractureGridVariables = typename GET_PROP_TYPE(FractureTypeTag, GridVariables); + using MatrixGridVariables = GetPropType; + using FractureGridVariables = GetPropType; auto matrixGridVariables = std::make_shared(matrixProblem, matrixFvGridGeometry); auto fractureGridVariables = std::make_shared(fractureProblem, fractureFvGridGeometry); xOld = x; - matrixGridVariables->init(x[matrixDomainId], xOld[matrixDomainId]); - fractureGridVariables->init(x[fractureDomainId], xOld[fractureDomainId]); + matrixGridVariables->init(x[matrixDomainId]); + fractureGridVariables->init(x[fractureDomainId]); // intialize the vtk output modules - VtkOutputModule matrixVtkWriter(*matrixProblem, *matrixFvGridGeometry, *matrixGridVariables, x[matrixDomainId], matrixProblem->name()); - VtkOutputModule fractureVtkWriter(*fractureProblem, *fractureFvGridGeometry, *fractureGridVariables, x[fractureDomainId], fractureProblem->name()); + using MatrixVtkOutputModule = VtkOutputModule>; + using FractureVtkOutputModule = VtkOutputModule>; + MatrixVtkOutputModule matrixVtkWriter(*matrixGridVariables, x[matrixDomainId], matrixProblem->name()); + FractureVtkOutputModule fractureVtkWriter(*fractureGridVariables, x[fractureDomainId], fractureProblem->name()); // Add model specific output fields - using MatrixIOFields = typename GET_PROP_TYPE(MatrixTypeTag, IOFields); - using FractureIOFields = typename GET_PROP_TYPE(FractureTypeTag, IOFields); + using MatrixIOFields = GetPropType; + using FractureIOFields = GetPropType; MatrixIOFields::initOutputModule(matrixVtkWriter); FractureIOFields::initOutputModule(fractureVtkWriter); diff --git a/exercises/solution/exercise-fractures/fractureproblem.hh b/exercises/solution/exercise-fractures/fractureproblem.hh index b3300c8..4250c83 100644 --- a/exercises/solution/exercise-fractures/fractureproblem.hh +++ b/exercises/solution/exercise-fractures/fractureproblem.hh @@ -48,24 +48,36 @@ namespace Dumux { template class FractureSubProblem; namespace Properties { -NEW_PROP_TAG(GridData); // forward declaration of property -// create the type tag nodes -NEW_TYPE_TAG(FractureProblemTypeTag, INHERITS_FROM(CCTpfaModel, TwoP)); +// Create new type tag node +namespace TTag { +struct FractureProblemTypeTag { using InheritsFrom = std::tuple; }; +} // end namespace TTag + // Set the grid type -SET_TYPE_PROP(FractureProblemTypeTag, Grid, Dune::FoamGrid<1, 2>); +template +struct Grid { using type = Dune::FoamGrid<1, 2>; }; + // Set the problem type -SET_TYPE_PROP(FractureProblemTypeTag, Problem, FractureSubProblem); +template +struct Problem { using type = FractureSubProblem; }; + // set the spatial params -SET_TYPE_PROP(FractureProblemTypeTag, - SpatialParams, - FractureSpatialParams< typename GET_PROP_TYPE(TypeTag, FVGridGeometry), - typename GET_PROP_TYPE(TypeTag, Scalar) >); +template +struct SpatialParams +{ + using type = FractureSpatialParams< GetPropType, + GetPropType >; +}; + // the fluid system -SET_TYPE_PROP(FractureProblemTypeTag, - FluidSystem, - Dumux::FluidSystems::H2ON2< typename GET_PROP_TYPE(TypeTag, Scalar), - FluidSystems::H2ON2DefaultPolicy >); +template +struct FluidSystem +{ + using type = Dumux::FluidSystems::H2ON2< GetPropType, + FluidSystems::H2ON2DefaultPolicy >; +}; + } // end namespace Properties /*! @@ -79,10 +91,10 @@ class FractureSubProblem : public PorousMediumFlowProblem { using ParentType = PorousMediumFlowProblem; - using BoundaryTypes = typename GET_PROP_TYPE(TypeTag, BoundaryTypes); - using CouplingManager = typename GET_PROP_TYPE(TypeTag, CouplingManager); - using NumEqVector = typename GET_PROP_TYPE(TypeTag, NumEqVector); - using GridVariables = typename GET_PROP_TYPE(TypeTag, GridVariables); + using BoundaryTypes = GetPropType; + using CouplingManager = GetPropType; + using NumEqVector = GetPropType; + using GridVariables = GetPropType; using ElementVolumeVariables = typename GridVariables::GridVolumeVariables::LocalView; using PrimaryVariables = typename GridVariables::PrimaryVariables; using Scalar = typename GridVariables::Scalar; @@ -95,7 +107,7 @@ class FractureSubProblem : public PorousMediumFlowProblem using GlobalPosition = typename Element::Geometry::GlobalCoordinate; // some indices for convenience - using Indices = typename GET_PROP_TYPE(TypeTag, ModelTraits)::Indices; + using Indices = typename GetPropType::Indices; enum { pressureIdx = Indices::pressureIdx, @@ -115,7 +127,7 @@ public: { // initialize the fluid system, i.e. the tabulation // of water properties. Use the default p/T ranges. - using FluidSystem = typename GET_PROP_TYPE(TypeTag, FluidSystem); + using FluidSystem = GetPropType; FluidSystem::init(); } diff --git a/exercises/solution/exercise-fractures/matrixproblem.hh b/exercises/solution/exercise-fractures/matrixproblem.hh index ce80b4e..9eff129 100644 --- a/exercises/solution/exercise-fractures/matrixproblem.hh +++ b/exercises/solution/exercise-fractures/matrixproblem.hh @@ -56,28 +56,36 @@ namespace Dumux { template class MatrixSubProblem; namespace Properties { -NEW_PROP_TAG(GridData); // forward declaration of property - -// create the type tag node for the matrix sub-problem -// We need to put the facet-coupling type tag after the physics-related type tag -// because it overwrites some of the properties inherited from "TwoP". This is -// necessary because we need e.g. a modified implementation of darcys law that -// evaluates the coupling conditions on faces that coincide with the fractures. -NEW_TYPE_TAG(MatrixProblemTypeTag, INHERITS_FROM(TwoP, CCTpfaFacetCouplingModel)); + +// create the type tag node +namespace TTag { +struct MatrixProblemTypeTag { using InheritsFrom = std::tuple; }; +} // end namespace TTag + // Set the grid type -SET_TYPE_PROP(MatrixProblemTypeTag, Grid, Dune::ALUGrid<2, 2, Dune::simplex, Dune::conforming>); +template +struct Grid { using type = Dune::ALUGrid<2, 2, Dune::simplex, Dune::conforming>; }; + // Set the problem type -SET_TYPE_PROP(MatrixProblemTypeTag, Problem, MatrixSubProblem); +template +struct Problem { using type = MatrixSubProblem; }; + // set the spatial params -SET_TYPE_PROP(MatrixProblemTypeTag, - SpatialParams, - MatrixSpatialParams< typename GET_PROP_TYPE(TypeTag, FVGridGeometry), - typename GET_PROP_TYPE(TypeTag, Scalar) >); +template +struct SpatialParams +{ + using type = MatrixSpatialParams< GetPropType, + GetPropType >; +}; + // the fluid system -SET_TYPE_PROP(MatrixProblemTypeTag, - FluidSystem, - Dumux::FluidSystems::H2ON2< typename GET_PROP_TYPE(TypeTag, Scalar), - FluidSystems::H2ON2DefaultPolicy >); +template +struct FluidSystem +{ + using type = Dumux::FluidSystems::H2ON2< GetPropType, + FluidSystems::H2ON2DefaultPolicy >; +}; + } // end namespace Properties /*! @@ -91,10 +99,10 @@ class MatrixSubProblem : public PorousMediumFlowProblem { using ParentType = PorousMediumFlowProblem; - using BoundaryTypes = typename GET_PROP_TYPE(TypeTag, BoundaryTypes); - using CouplingManager = typename GET_PROP_TYPE(TypeTag, CouplingManager); - using NumEqVector = typename GET_PROP_TYPE(TypeTag, NumEqVector); - using GridVariables = typename GET_PROP_TYPE(TypeTag, GridVariables); + using BoundaryTypes = GetPropType; + using CouplingManager = GetPropType; + using NumEqVector = GetPropType; + using GridVariables = GetPropType; using PrimaryVariables = typename GridVariables::PrimaryVariables; using Scalar = typename GridVariables::Scalar; @@ -107,7 +115,7 @@ class MatrixSubProblem : public PorousMediumFlowProblem using GlobalPosition = typename Element::Geometry::GlobalCoordinate; // some indices for convenience - using Indices = typename GET_PROP_TYPE(TypeTag, ModelTraits)::Indices; + using Indices = typename GetPropType::Indices; enum { pressureIdx = Indices::pressureIdx, @@ -128,7 +136,7 @@ public: { // initialize the fluid system, i.e. the tabulation // of water properties. Use the default p/T ranges. - using FluidSystem = typename GET_PROP_TYPE(TypeTag, FluidSystem); + using FluidSystem = GetPropType; FluidSystem::init(); // there can only be one exercise part active -- GitLab From 224ec196c12189ea265af7728c4a50baf6b05d22 Mon Sep 17 00:00:00 2001 From: Theresa Kurz Date: Mon, 17 Dec 2018 09:04:23 +0100 Subject: [PATCH 20/25] [cleanup] comment local residual in exercise-mainfile, improve description in mainfile --- exercises/exercise-mainfile/1pproblem.hh | 6 +++--- exercises/exercise-mainfile/README.md | 2 +- 2 files changed, 4 insertions(+), 4 deletions(-) diff --git a/exercises/exercise-mainfile/1pproblem.hh b/exercises/exercise-mainfile/1pproblem.hh index 7f1d69c..14273f4 100644 --- a/exercises/exercise-mainfile/1pproblem.hh +++ b/exercises/exercise-mainfile/1pproblem.hh @@ -38,7 +38,7 @@ // TODO: dumux-course-task // uncomment the incompressiblelocalresidual which is a specialization of the standard immisible localresidual for one phase incompressible cases and provides an analytic jacobian. -#include +// #include #include #include @@ -84,8 +84,8 @@ public: // TODO: dumux-course-task // set the OneP Incompressible local residual for the OnePIncompressible type tag. This provides an analytic jacobian to be used for the analytic solution. Change that by setting: -template -struct LocalResidual { using type = OnePIncompressibleLocalResidual; }; +// template +// struct LocalResidual { using type = OnePIncompressibleLocalResidual; }; // the fluid system for compressible tests diff --git a/exercises/exercise-mainfile/README.md b/exercises/exercise-mainfile/README.md index 5be7515..04d5aa5 100644 --- a/exercises/exercise-mainfile/README.md +++ b/exercises/exercise-mainfile/README.md @@ -185,6 +185,6 @@ For the incompressible one phase problem it is possible to also have an analytic ```c++ // TODO: dumux-course-task ``` -For the analytic solution of your immiscible problem you need analytic solutions for the derivatives of the jacobian. For that we have a special local residual, the `OnePIncompressibleLocalResidual` which provides that. You just need to include that in your `1pproblem.hh` and use that instead of the `immisciblelocalresidual.hh` which is used as a standard for all immiscible models. +For the analytic solution of your immiscible problem you need analytic solutions for the derivatives of the jacobian. For that we have a special local residual, the `OnePIncompressibleLocalResidual` which provides that. You just need to include `incompressiblelocalresidual.hh` in your `1pproblem.hh` and use that instead of the `immisciblelocalresidual.hh` which is used as a standard for all immiscible models. Additionally you need to set the differentiation method in the main file `exercise_1p_a.cc` to analytic. -- GitLab From 4a20c1e0b4e43a8206df8b342bde302d284fc0db Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Dennis=20Gl=C3=A4ser?= Date: Mon, 17 Dec 2018 09:51:27 +0100 Subject: [PATCH 21/25] [ex-fractures][solution] use correct call to problem() --- exercises/solution/exercise-fractures/matrixproblem.hh | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/exercises/solution/exercise-fractures/matrixproblem.hh b/exercises/solution/exercise-fractures/matrixproblem.hh index 9eff129..0c91909 100644 --- a/exercises/solution/exercise-fractures/matrixproblem.hh +++ b/exercises/solution/exercise-fractures/matrixproblem.hh @@ -198,8 +198,8 @@ public: // we need to obtain the domain marker of the fracture element that is coupled to this face // therefore we first get the fracture problem from the coupling manager. For this test, we // know that the fracture domain id is 1 (see main file) - static constexpr std::size_t fractureDomainId = 1; - const auto& fractureProblem = couplingManager().template problem(); + static constexpr auto fractureDomainId = Dune::index_constant<1>(); + const auto& fractureProblem = couplingManager().problem(fractureDomainId); // use helper function in coupling manager to obtain the element this face couples to const auto fractureElement = couplingManager().getLowDimElement(element, scvf); -- GitLab From abb342b8d17f94d06b4336d0bf7737c52ce396b1 Mon Sep 17 00:00:00 2001 From: Theresa Kurz Date: Mon, 17 Dec 2018 15:08:30 +0100 Subject: [PATCH 22/25] [cleanup] correct input file for exercise-biomin --- exercises/solution/exercise-biomineralization/CMakeLists.txt | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/exercises/solution/exercise-biomineralization/CMakeLists.txt b/exercises/solution/exercise-biomineralization/CMakeLists.txt index 734c1fe..46b5a72 100644 --- a/exercises/solution/exercise-biomineralization/CMakeLists.txt +++ b/exercises/solution/exercise-biomineralization/CMakeLists.txt @@ -1,7 +1,7 @@ # executables for exercisebiomin dune_add_test(NAME exercisebiomin_solution SOURCES exercisebiomin.cc - CMD_ARGS exercisebiomin.input) + CMD_ARGS exercisebiomin_solution.input) # add tutorial to the common target add_dependencies(test_exercises exercisebiomin_solution) -- GitLab From 600f2cdf3a0fa5eec2b64b412193a806b9cea3a4 Mon Sep 17 00:00:00 2001 From: Theresa Kurz Date: Mon, 17 Dec 2018 16:08:18 +0100 Subject: [PATCH 23/25] [exercise-fracture] update README --- exercises/exercise-fractures/README.md | 15 +++++++-------- 1 file changed, 7 insertions(+), 8 deletions(-) diff --git a/exercises/exercise-fractures/README.md b/exercises/exercise-fractures/README.md index b526647..067ac67 100644 --- a/exercises/exercise-fractures/README.md +++ b/exercises/exercise-fractures/README.md @@ -67,11 +67,10 @@ From the matrix side, the coupling works a bit different. Since the fracture dom ... // create the type tag node for the matrix sub-problem -// We need to put the facet-coupling type tag after the physics-related type tag -// because it overwrites some of the properties inherited from "TwoP". This is -// necessary because we need e.g. a modified implementation of darcys law that -// evaluates the coupling conditions on faces that coincide with the fractures. -NEW_TYPE_TAG(MatrixProblemTypeTag, INHERITS_FROM(TwoP, CCTpfaFacetCouplingModel)); +// Create new type tags +namespace TTag { +struct MatrixProblemTypeTag { using InheritsFrom = std::tuple; }; +} // end namespace TTag ``` Additionally, we need to provide access to the coupling manager in the matrix problem, so that the flux assembly engine of the matrix domain has access to the state inside the fracture (which the fluxes depend on): @@ -189,7 +188,7 @@ int getElementDomainMarker(const Element& element) const { return gridDataPtr_->getElementDomainMarker(element); } ``` -The domain markers are also already added to the output (see `exercise_fractures.cc`, lines 188-197). To visualize them, open any of your previously produced results with _Paraview_ and take a look at them by selecting __domainMarker__. +The domain markers are also already added to the output (see `exercise_fractures.cc`, lines 195-199). To visualize them, open any of your previously produced results with _Paraview_ and take a look at them by selecting __domainMarker__. Adjust the functions for permeability, porosity and material law parameters in the `fracturespatialparams.hh` file such that they are selected depending on the domain marker of the elements. You will see in the results that the pressure jump across the first vertical fracture is now lower than before, because there are highly permeable fractures crossing it, allowing for a pressure release into the other parts of the domain. @@ -201,8 +200,8 @@ We can now also set the interior boundary condition depending on the domain mark // we need to obtain the domain marker of the fracture element that is coupled to this face // therefore we first get the fracture problem from the coupling manager. For this test, we // know that the fracture domain id is 1 (see main file) -static constexpr std::size_t fractureDomainId = 1; -const auto& fractureProblem = couplingManager().template problem(); +static constexpr auto fractureDomainId = Dune::index_constant<1>(); +const auto& fractureProblem = couplingManager().problem(fractureDomainId); // use helper function in coupling manager to obtain the element this face couples to const auto fractureElement = couplingManager().getLowDimElement(element, scvf); -- GitLab From 6834ca306cd9695fdf06819f5267f189e6f194b3 Mon Sep 17 00:00:00 2001 From: Felix Weinhardt Date: Mon, 17 Dec 2018 18:04:26 +0100 Subject: [PATCH 24/25] [exercise-coupling-ff-pm] update readme --- exercises/exercise-coupling-ff-pm/README.md | 6 +++--- 1 file changed, 3 insertions(+), 3 deletions(-) diff --git a/exercises/exercise-coupling-ff-pm/README.md b/exercises/exercise-coupling-ff-pm/README.md index d37eabf..50b8d24 100644 --- a/exercises/exercise-coupling-ff-pm/README.md +++ b/exercises/exercise-coupling-ff-pm/README.md @@ -27,7 +27,7 @@ The same applies for types such as `GridManager`, `FVGridGeometry`, `Problem`, e Since we use a monolithic coupling scheme, there is only one `Assembler` and one `NewtonSolver`. The problem files very much look like "regular", uncoupled ones with the exception that they hold a pointer to the `CouplingManager` which allows to evaluate the coupling conditions and to exchange information between the coupled models. -The coupling conditions are realized technically in terms of boundary condition. For instance, in lines 171 and 172 +The coupling conditions are realized technically in terms of boundary condition. For instance, in lines 178 and 179 in `ex_interface_ffproblem.hh`, `couplingNeumann` boundary conditions are set, which means that the free flow models evaluates the mass and momentum fluxes coming from the porous domain and uses these values as boundary conditions at the interface. @@ -147,7 +147,7 @@ the analytical solution of $`v_x`$ on the free flow domain. Play around with the __Task C: Cange shape of interface__ Now we want to include a non-flat interface between the two domains. We use `dune-subgrid` to construct -two grids for the two domains from one common host grid. Comment out lines 93-103 in `ex_interface_coupling_ff-pm.cc` and comment lines 112-147 in the same file. This will instantiate a host grid and define two helper lambda functions that are used to choose elements from to host grid for the respective sub grid. In the given case, +two grids for the two domains from one common host grid. Comment out lines 96-106 in `ex_interface_coupling_ff-pm.cc` and comment lines 114-149 in the same file. This will instantiate a host grid and define two helper lambda functions that are used to choose elements from to host grid for the respective sub grid. In the given case, the domain is split in two haves, separated by a sinusoidal interface. ```cpp @@ -186,7 +186,7 @@ values.setCouplingNeumann(scvf.directionIndex()); ``` The same if true for the BJS condition, however, here we need to consider the tangential direction: ```cpp -values.setCouplingNeumann(1 - scvf.directionIndex()); +values.setBJS(1 - scvf.directionIndex()); ``` The final result should look something like this: -- GitLab From a94f71b8eb7e072e0c537be86a399bc178233c1c Mon Sep 17 00:00:00 2001 From: Timo Koch Date: Wed, 19 Dec 2018 15:26:53 +0100 Subject: [PATCH 25/25] Remove unused variable warning --- exercises/exercise-biomineralization/biominproblem.hh | 2 +- exercises/exercise-coupling-ff-pm/models/ex_models_pmproblem.hh | 2 +- .../exercise-coupling-ff-pm/models/ex_models_pmproblem.hh | 2 +- 3 files changed, 3 insertions(+), 3 deletions(-) diff --git a/exercises/exercise-biomineralization/biominproblem.hh b/exercises/exercise-biomineralization/biominproblem.hh index f015d7e..5b1a8b2 100644 --- a/exercises/exercise-biomineralization/biominproblem.hh +++ b/exercises/exercise-biomineralization/biominproblem.hh @@ -280,7 +280,6 @@ public: NumEqVector values(0.0); Scalar waterFlux = injVolumeflux_; // divide by area if area not 1! [m/s] - Scalar gasFlux = injCO2_; // divide by area if area not 1! [m/s] // Set values for Ca + urea injection above aquitard. // Use negative values for injection. @@ -297,6 +296,7 @@ public: // Set CO2 injection below aquitard after the injBioTime else { + // Scalar gasFlux = injCO2_; // divide by area if area not 1! [m/s] values = 0.0; //mol/m²/s } diff --git a/exercises/exercise-coupling-ff-pm/models/ex_models_pmproblem.hh b/exercises/exercise-coupling-ff-pm/models/ex_models_pmproblem.hh index fb4f258..357d790 100644 --- a/exercises/exercise-coupling-ff-pm/models/ex_models_pmproblem.hh +++ b/exercises/exercise-coupling-ff-pm/models/ex_models_pmproblem.hh @@ -190,7 +190,7 @@ public: for (auto&& scv : scvs(fvGeometry)) { - const auto& volVars = elemVolVars[scv]; + // const auto& volVars = elemVolVars[scv]; // insert calculation of the water mass here waterMass += 0.0; } diff --git a/exercises/solution/exercise-coupling-ff-pm/models/ex_models_pmproblem.hh b/exercises/solution/exercise-coupling-ff-pm/models/ex_models_pmproblem.hh index cb79f6a..00a4807 100644 --- a/exercises/solution/exercise-coupling-ff-pm/models/ex_models_pmproblem.hh +++ b/exercises/solution/exercise-coupling-ff-pm/models/ex_models_pmproblem.hh @@ -231,11 +231,11 @@ public: for (auto&& scv : scvs(fvGeometry)) { - const auto& volVars = elemVolVars[scv]; for(int phaseIdx = 0; phaseIdx < FluidSystem::numPhases; ++phaseIdx) { // insert calculation of the water mass here #if EXNUMBER >= 2 + const auto& volVars = elemVolVars[scv]; waterMass += volVars.massFraction(phaseIdx, FluidSystem::H2OIdx) * volVars.density(phaseIdx) * volVars.saturation(phaseIdx) * volVars.porosity() * scv.volume() * volVars.extrusionFactor(); -- GitLab