diff --git a/exercises/exercise-basic/README.md b/exercises/exercise-basic/README.md index 8aee3292b4f5fc7e87d5e474f241aa70c50fbbf9..f0dbdf870d69e7061cb0872a76bc0b34a614995f 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,13 +54,13 @@ make exercise_basic_2p exercise_basic_2p2c paraview injection-2p2c.pvd ``` -


+

### Task 3: Setting up a new executable (for a non-isothermal simulation)
* 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 @@ -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
diff --git a/exercises/exercise-basic/exercise_basic_2p.cc b/exercises/exercise-basic/exercise_basic_2p.cc index 88f18f84da4bccded1a97b48ccf2bab040369909..babdd6785167f3d519fa9dc664aff95b0dc551bd 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 b4359b9ea717c3b3a01ae3ba0601ecda031f64e5..3232900d53c192578da9b4c550919b3db82b5ac7 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,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); +// 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; + VtkOutputModule vtkWriter(*gridVariables, x, problem->name()); + 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); + auto timeLoop = std::make_shared>(restartTime, dt, tEnd); timeLoop->setMaxTimeStepSize(maxDt); // the assembler with time loop for instationary problem @@ -124,8 +144,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 39b0ab57b0389f731defb65b161dbef572692a73..9e483829ade944566991f052555a1d3a644fc50e 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 @@ -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 5d03855918653c1227ee2d31bc21cba1f6644df8..eb5c5a44fd9f962870160bfb835023752205e9c8 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 @@ -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 aae875173477bd98d8ac046ab2c7ba976132b5ed..414b4124b94c7778d60e1ab42f912cd50a8d530f 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 @@ -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/exercise-biomineralization/README.md b/exercises/exercise-biomineralization/README.md index f7348b045b8e3cb182b7fb65b48406d6bb9023cd..dfd4c1b145e4d0433ce2a177bcdf782ff10981b4 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 aa2c8a2c5d75e680dd96fff7ee81b03dc3c38ee4..5b1a8b2859a2765059e9eb00cd8da976e7fadcde 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 @@ -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)); @@ -268,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. @@ -285,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-biomineralization/biominspatialparams.hh b/exercises/exercise-biomineralization/biominspatialparams.hh index c8d01efc71a2bcb7b63c87d7111a6f58a72fc14c..12be491883ddd47bb5e96e5495b4f101b7e37520 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 fff7201abdffedb149802d904e7b2377bb5dd750..bc0e0f0a9a086aa4c51f7688ba0581abee0d0ef4 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 dc84ce8082c5b1737d36b1cb277f1b78cc281513..0ac7f193b04829a529f0d00725ebf41c391f1df7 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,20 +102,20 @@ 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); + 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"); // 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 + using IOFields = GetPropType; + VtkOutputModule vtkWriter(*gridVariables, x, problem->name()); + IOFields::initOutputModule(vtkWriter); //!< Add model specific output fields //add specific output vtkWriter.addField(problem->getKxx(), "Kxx"); vtkWriter.addField(problem->getKyy(), "Kyy"); @@ -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 6d57216469125c157f673969875c905f585b97e1..0f3d3e413948411a6b4fd939d9c88f1e7b5bead7 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 6f4be1e8b8343ef6b04a8dfd9af807bab4ce4a25..617bf8b82cf9e998fcab84116fcc85a7ca3d3c86 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/exercise-coupling-ff-pm/1pspatialparams.hh b/exercises/exercise-coupling-ff-pm/1pspatialparams.hh index 64887e33307e8a45908dabc131e919a99f95dfa1..e95c24917d05382c77b53c769357a61ee41a9994 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 1830f3cbf2381280ca1213b8a07a17890846203c..948b7a7b7ce4e00bbba83f88b399b8889eee7177 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 58b75459bbae1fe406dca15062d96d27b8adff8f..50b8d2426845b928cfe570781175c6c12a50b089 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. @@ -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); ``` @@ -142,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 @@ -181,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: @@ -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. @@ -263,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. @@ -289,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. @@ -321,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. @@ -330,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)); } @@ -349,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`). @@ -369,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/interface/ex_interface_coupling_ff-pm.cc b/exercises/exercise-coupling-ff-pm/interface/ex_interface_coupling_ff-pm.cc index 85226b998887b5ea030ed889ae598573ce250da3..53c927f67e80d2408004db3e748fbb3e1dc6ad85 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 e3813950725ba4837e96b79d76dc9ccc74dc0d4f..4117b7f17c501817b738dfdb6836cc2c3223e4a8 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 48d29d667983db35a315d3417554f0c1880784db..c5649a77e27284fe946d8821ca4c526e4f4bf17c 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 6c60375e50efee86f4141ceb406cc38208f7f77e..e447100ca1c7e3d2852acf622f1b3570ab0772a7 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 @@ -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/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 b54ae19ed5f17fa1d5bcc47a0d3e01f1c5f502ed..48d89fe4f579aca4aad2350bbb33db7054ffba97 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 d3f68518fa9a38504ee876af35f0c9e79f31cf17..07bb4dd0e86001358836ac361a1399f344add5d5 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 1fe98c085805a45045474cece286db0f4561b399..6f00aa101770dcd2c1e0e4f0a5b3cd5c874f99e0 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 0e48d23560788095b46c641d55c64606f9ecf6d6..357d7909634f3b59480f35111ea86f6aec78c168 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 @@ -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); @@ -182,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; } @@ -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/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 233cdd3fe0dff13f2afd3052f56dd7bce30ded28..3d756d624d227265bcd9a63c27871acde570e425 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 514cf156d55211777c2ec0980f37d1a95124867e..00e02465ce811bb20125e851dbe57964dc023e52 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 6c89102d08587d591a7d4f1125feede34dd0b6da..88d9cdeea6cd9551067187e2a7ab6a7929fba8a5 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 2d3a84d25c4884441720cc2ad10b0ccb8ab7a4ab..de4bb4e71ccca3ce12c36ba5cbb455600c15aa13 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 @@ -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/exercise-dunemodule/README.md b/exercises/exercise-dunemodule/README.md index 53b4ba97101e7a6036d5c66be8596d2bd65f9e2b..dafdf9d61fbba54e4ad80adb67c308da60bd4a2f 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/2p2cproblem.hh b/exercises/exercise-fluidsystem/2p2cproblem.hh index 8cff7cc77480322f0a88bff3ba194ea3c8a9313d..a89f4dae9c96dc618d76718eed070ce8781b8a7b 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 @@ -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 c5decbfe9a18b8bde3565693ea6ba9c98d40629a..33950b28e6a080b8e7a31a6a632760c388a80725 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 @@ -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 c9db143d4e66746da540bfb0cb088c3fe75e61aa..3cfe4bacafa1667607ce061713a0dfc77b8cac9f 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. @@ -53,8 +56,8 @@ 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 -#include +// The box discretization +#include ``` For a cell-centered scheme, you could derive from `CCTpfaModel` or `CCMpfaModel` instead (and, of course, include the right headers). @@ -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; /*! @@ -160,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) @@ -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 90a44e1a003e1e3b0d9a049eeca9afa9e9ef089b..184814d6ef3cc3f5112ec20d85228405b7d4b7f9 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 IOFields = GetPropType; + VtkOutputModule vtkWriter(*gridVariables, x, problem->name()); + using VelocityOutput = GetPropType; + vtkWriter.addVelocityOutput(std::make_shared(*gridVariables)); + IOFields::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 b2446b79b8ac53ad79e790846a0cf6afaedeb62c..62965b2a29cab549becbdc54de506701e1aff5e3 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/exercise-fractures/README.md b/exercises/exercise-fractures/README.md index b526647b45ef6aaa5da1e44200fbee18a6e2befb..067ac67f0c181a22cab57b71e3ccae5b8235a044 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); diff --git a/exercises/exercise-fractures/exercise_fractures.cc b/exercises/exercise-fractures/exercise_fractures.cc index ac6a9f1b3223a6bc4c189cd1e340e616e9b13296..55ebc0d96369e9647767bda8ea8e6a53f27b7752 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 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-fractures/fractureproblem.hh b/exercises/exercise-fractures/fractureproblem.hh index 2df7b24bb7c1738216e44d88a9fdfa9f7f4b8629..68153d271483efc1a4a2b959e3011453f39313b5 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 @@ -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 c4a83952e551265c947d899381457c93830abc13..854902ae7cbc8aae170be0d2d8d9b0d1d637aa76 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(); } diff --git a/exercises/exercise-grids/README.md b/exercises/exercise-grids/README.md index aeffdc23be6fc91f672e595f2a3da750ed7a5c66..08b2a50893a4c5c099f93ee267616a1ebb543e03 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 5e56eb4b7f3ea4b8f3cf9397143383ba6f47161e..5f57026c15a0284cef6834d618cb1e84a513c623 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 IOFields = GetPropType; + VtkOutputModule vtkWriter(*gridVariables, x, problem->name()); + 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-grids/injection2pproblem.hh b/exercises/exercise-grids/injection2pproblem.hh index ab11ae93baaac7983b912affa002bf66f8d21992..209e9f50def2618920204576d99f6c1c5b8128ad 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 @@ -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/exercise-mainfile/1pproblem.hh b/exercises/exercise-mainfile/1pproblem.hh index 3a8f3ae0b31ee2c400247271da08b35a35090f40..14273f4eabf0cc4d89f4309eb80286beef047e95 100644 --- a/exercises/exercise-mainfile/1pproblem.hh +++ b/exercises/exercise-mainfile/1pproblem.hh @@ -31,14 +31,14 @@ #include #include -#include -#include -#include +#include +#include +#include // 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/README.md b/exercises/exercise-mainfile/README.md index a4028bedb8c088fff61561287972c81138fb2955..04d5aa5f4355601edded03b7d3511c6edb76cc80 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"); @@ -183,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. diff --git a/exercises/exercise-mainfile/exercise_1p_a.cc b/exercises/exercise-mainfile/exercise_1p_a.cc index 5ce59ce96e9c4b6cf1669e94759f85f850c03675..0c624197883ce5eddd7e85bd2316a9f476f1f66c 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 4fdde99b6f09fd59bab2278797a14f050ad6ab15..9c4af7d58f7b97b9239422b722ccde1495da9bb1 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 aaa2209c7874c439e0ff296e2b53426fa1de78ed..94636e1af9c6c49ac11750dad520a35b405afee8 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 + gridVariables->init(x); + + // 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/exercise-properties/README.md b/exercises/exercise-properties/README.md index 92a890a06ec1deed2f81bcbd846edd00820e590f..1e80194f43c50d4302de5948bb76d09068dfbca8 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`. @@ -68,17 +57,13 @@ 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 -SET_PROP(TwoPIncompressible, LocalResidual) + +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. 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: diff --git a/exercises/exercise-properties/exercise_properties.cc b/exercises/exercise-properties/exercise_properties.cc index 3583260ed9bfd2083e546a8771dca79488c4cae5..edcb4c519e9a111b5732623af07a528c3d23d859 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,54 @@ 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); - - // 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); + using IOFields = GetPropType; + VtkOutputModule vtkWriter(*gridVariables, x, problem->name()); + 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-properties/problem.hh b/exercises/exercise-properties/problem.hh index 020272c32ad3ee0f94e11a7db32b462a4c3dfdd0..f336029375bf8b5acfa01ebe3d267e6e9df92d5d 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 @@ -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/exercise-runtimeparams/exercise_runtimeparams.cc b/exercises/exercise-runtimeparams/exercise_runtimeparams.cc index 5356a47778b40b14dedb9e6102b7c6d8b20e3870..e1f59795af2dae7d00be6db859aab85e2969adec 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 IOFields = GetPropType; + VtkOutputModule vtkWriter(*gridVariables, x, problem->name()); + 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-runtimeparams/injection2pproblem.hh b/exercises/exercise-runtimeparams/injection2pproblem.hh index cdc33ece0f628574cedb16009f2b98fb6066a002..7ac8abb9365b2c5c88ac9d358055724bdddeb940 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 @@ -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/extradoc/exercisebiomin_injectionFinal.png b/exercises/extradoc/exercisebiomin_injectionFinal.png index aa81d2555618d5cc598e3436122a7161848a5da2..a07d51c6ad44175699639c7c01459bee15871dde 100644 Binary files a/exercises/extradoc/exercisebiomin_injectionFinal.png and b/exercises/extradoc/exercisebiomin_injectionFinal.png differ diff --git a/exercises/extradoc/exercisebiomin_porosityFinal.png b/exercises/extradoc/exercisebiomin_porosityFinal.png index 0910b88d4794b7616fed33992c1a7c9017271c44..588a33b0b3202f08d32e1f14d22bb59cfc638013 100644 Binary files a/exercises/extradoc/exercisebiomin_porosityFinal.png and b/exercises/extradoc/exercisebiomin_porosityFinal.png differ diff --git a/exercises/solution/CMakeLists.txt b/exercises/solution/CMakeLists.txt index 724d926935b55d8c54a4e26234e3fa21bf42e507..64f79df29715303846bfad2f5e00681691b58f2b 100644 --- a/exercises/solution/CMakeLists.txt +++ b/exercises/solution/CMakeLists.txt @@ -6,3 +6,4 @@ add_subdirectory(exercise-grids) add_subdirectory(exercise-mainfile) add_subdirectory(exercise-properties) add_subdirectory(exercise-runtimeparams) +add_subdirectory(exercise-biomineralization) diff --git a/exercises/solution/exercise-basic/exercise_basic_2pni.cc b/exercises/solution/exercise-basic/exercise_basic_2pni.cc index c772513cb855bb999ad5e85713ff964a383fcf63..e8e234af521c072dcee617232787820f4bc23ece 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 IOFields = GetPropType; + VtkOutputModule vtkWriter(*gridVariables, x, problem->name()); + 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/solution/exercise-basic/injection2pniproblem.hh b/exercises/solution/exercise-basic/injection2pniproblem.hh index f8868632743897a52c318d4a6d00a1bcb0315bcd..4e20b2b4ee99ee208ced03c35946a5e7391e0a2c 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 @@ -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; diff --git a/exercises/solution/exercise-biomineralization/CMakeLists.txt b/exercises/solution/exercise-biomineralization/CMakeLists.txt new file mode 100644 index 0000000000000000000000000000000000000000..46b5a728813d845fa69b7921104f1bc3076ceec1 --- /dev/null +++ b/exercises/solution/exercise-biomineralization/CMakeLists.txt @@ -0,0 +1,10 @@ +# executables for exercisebiomin +dune_add_test(NAME exercisebiomin_solution + SOURCES exercisebiomin.cc + CMD_ARGS exercisebiomin_solution.input) + +# add tutorial to the common target +add_dependencies(test_exercises exercisebiomin_solution) + +# add symlinks for the input files +add_input_file_links(FILES "exercisebiomin.input") diff --git a/exercises/solution/exercise-biomineralization/biominproblem.hh b/exercises/solution/exercise-biomineralization/biominproblem.hh index 3c24e6dad80b89cb893d424aa1efdbc14a2664a0..2101a3b2fdc5fa782f8f7d1ecb795be05363c8aa 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 @@ -32,7 +32,9 @@ #include #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 0000000000000000000000000000000000000000..12be491883ddd47bb5e96e5495b4f101b7e37520 --- /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 6d14d12bab6350f3d79ccf46d552fae6e5e8ea56..02eec51ab98100461212e3b90043a703b992f4d7 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 0000000000000000000000000000000000000000..c3348a092628269aeb7d4c9b48d9d6bcd09f51eb --- /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 0000000000000000000000000000000000000000..1dc533034e6aa916663ce26efc8b45b6c8536d84 --- /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 0000000000000000000000000000000000000000..0ac7f193b04829a529f0d00725ebf41c391f1df7 --- /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); + + // 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 IOFields = GetPropType; + VtkOutputModule vtkWriter(*gridVariables, x, problem->name()); + IOFields::initOutputModule(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 6d57216469125c157f673969875c905f585b97e1..0f3d3e413948411a6b4fd939d9c88f1e7b5bead7 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 0000000000000000000000000000000000000000..617bf8b82cf9e998fcab84116fcc85a7ca3d3c86 --- /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 0000000000000000000000000000000000000000..b74567665f787c46d733426296c43ddfb2481435 --- /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 diff --git a/exercises/solution/exercise-coupling-ff-pm/1pspatialparams.hh b/exercises/solution/exercise-coupling-ff-pm/1pspatialparams.hh index 64887e33307e8a45908dabc131e919a99f95dfa1..e95c24917d05382c77b53c769357a61ee41a9994 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 1830f3cbf2381280ca1213b8a07a17890846203c..948b7a7b7ce4e00bbba83f88b399b8889eee7177 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 116ed7e2d8e4469f44bde197b8b71974422264b1..4f3bc841f1402a4bfb27302854baa9bc6e64cbaf 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 e3813950725ba4837e96b79d76dc9ccc74dc0d4f..4117b7f17c501817b738dfdb6836cc2c3223e4a8 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 369a7bd2b9238272a36759a1856d4f7369f55a37..c0dc45575729802b20b101c00970934afb41e5c4 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 7a5c4baaa4cdcc2997ed77781f1ce5308f8718ef..3549ff03521c727f481ccf32af16817f2fd01e4b 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 @@ -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; } 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 cdb7abdd800c9994ade2dab51adda2076ed7a51d..da400646bb372dc2f387565ba66347f2b0f00fbf 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 8d08fe836a2682e36007bbafa51c6438a5d15c6e..7dda6b1b36292024dc4d5f410eb9c08f9b8b0675 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 @@ -38,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/models/ex_models_ffproblem.hh b/exercises/solution/exercise-coupling-ff-pm/models/ex_models_ffproblem.hh index 3d59b25a071ed0e71a0c3baac902b4847a2ce840..ae63df0d88f092b00544e4d3a6e38d0c976129a3 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 18ad042dfdb65cbfc9a61389f8a7084a21e34eed..00a48073e5773626091e5cbb52299b3602b4b1c9 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 @@ -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); @@ -221,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(); @@ -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; 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 e1e4739c3fabc8afdc943d6318472b984b23c6c4..a50ebcea412c54c256df918817b560d16efeb1c0 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 514cf156d55211777c2ec0980f37d1a95124867e..00e02465ce811bb20125e851dbe57964dc023e52 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 194597f76375334fccdd7473af2054e32f481028..a78efe81c38b40db995cca48a2413720d0787e33 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 bd589d6303f95b7c9ba96b94102174af24c8a129..e8d4477f21c0b02c5796b458b11e3d622677fc08 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 @@ -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-fluidsystem/2p2cproblem.hh b/exercises/solution/exercise-fluidsystem/2p2cproblem.hh index 13eb748b8a9f18e116d75d9b8746fed6a6ecffe9..35eca3501a634d0a02561f12c3f5631c7fe659c0 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 @@ -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 c228046e9de53e98f6611fc1d9346d1cf2c5c342..d97bba89f2840c75ff08e55975c69a74b39f1b8a 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 @@ -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 de8824921e934a09ad2f4fac330dd5ba36fcff75..723a640bc5756c99cb03a500358bf9af3f712d18 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); + 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; + VtkOutputModule vtkWriter(*gridVariables, x, problem->name()); + using VelocityOutput = GetPropType; + vtkWriter.addVelocityOutput(std::make_shared(*gridVariables)); + IOFields::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 212c0feb41328a235357b3f710eee56115e72124..4ff5595721564d460fcf466d04f618adf255de0f 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; @@ -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 ac6a9f1b3223a6bc4c189cd1e340e616e9b13296..55ebc0d96369e9647767bda8ea8e6a53f27b7752 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,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 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/solution/exercise-fractures/fractureproblem.hh b/exercises/solution/exercise-fractures/fractureproblem.hh index 02c89ce721a7449c89665b029c5577ddb3fc4994..4250c83a61865155240db1823af2b56f541d1d88 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 @@ -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 ce80b4eea7bb400045f7a37fe769d7a48c2d4c68..0c91909a1ae09048dd6b27812878fe1acdef33c9 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 @@ -190,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); diff --git a/exercises/solution/exercise-grids/exercise_grids_solution.cc b/exercises/solution/exercise-grids/exercise_grids_solution.cc index 9da491d6338c4049471432a54bf46b0de280087a..0f5ba9852fdad06cca4524bc93a6eff681db6008 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 IOFields = GetPropType; + VtkOutputModule vtkWriter(*gridVariables, x, problem->name()); + 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/solution/exercise-grids/injection2pproblem.hh b/exercises/solution/exercise-grids/injection2pproblem.hh index 0ac137c4e699e0faa4d5b268fa5b8b1d7b23dbbf..a18e2f4892fe371cf8824f7cd13a5f32a6f87efb 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 @@ -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)); - -// Set the grid type -SET_TYPE_PROP(Injection2pTypeTag, Grid, Dune::YaspGrid<2>); +// 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 +// 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; diff --git a/exercises/solution/exercise-mainfile/1pproblem.hh b/exercises/solution/exercise-mainfile/1pproblem.hh index b484f75ada5501eac0ecb6827ed020cb337208c5..7f1d69c5b38ad9433de05a912b703e3b19ebf07c 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 @@ -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 e78a822ae26df60fd21f7d45ea5b607f1c08b34f..55137bfd5b3cbf57f2bd7aac43c2412ce285b271 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); diff --git a/exercises/solution/exercise-properties/exercise_properties_solution.cc b/exercises/solution/exercise-properties/exercise_properties_solution.cc index 3583260ed9bfd2083e546a8771dca79488c4cae5..f532f0dad45de620de89be1a7c73e3e4c7a1eb9a 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 @@ -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,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); - - // 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); + using IOFields = GetPropType; + VtkOutputModule vtkWriter(*gridVariables, x, problem->name()); + 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/solution/exercise-properties/mylocalresidual.hh b/exercises/solution/exercise-properties/mylocalresidual.hh index 485f33a8eacb2e145382e0beded58fbf11cba68c..2270f28e38c03e69c4bec6cdbffebfc7dc4598d5 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-properties/problem.hh b/exercises/solution/exercise-properties/problem.hh index 4e1a3b4056e3831256a8ea9bd9a60ebd840a1452..1aae5fcb8c66a9d15039500ee4e94e63a9034cf4 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 @@ -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); diff --git a/exercises/solution/exercise-runtimeparams/exercise_runtimeparams_solution.cc b/exercises/solution/exercise-runtimeparams/exercise_runtimeparams_solution.cc index 5356a47778b40b14dedb9e6102b7c6d8b20e3870..e1f59795af2dae7d00be6db859aab85e2969adec 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 IOFields = GetPropType; + VtkOutputModule vtkWriter(*gridVariables, x, problem->name()); + 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/solution/exercise-runtimeparams/injection2pproblem.hh b/exercises/solution/exercise-runtimeparams/injection2pproblem.hh index 953e36e7bc5798038dd8a794d0dc4e7eaee9e283..f553316c5f5934bd917c3c7508c4b0b7730f5d74 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 @@ -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;