Commit 337bbae4 by Farid Mohammadi Committed by Gabi Seitz

### Cleanup/Checkup for release 3.2

parent 4c333c87
 # Exercise Basics (DuMuX course)
## Problem set-up N$_2$ is injected in an aquifer previously saturated with water with an injection rate of 0.0001 kg/(s*m$^2$). ... ... @@ -25,7 +26,7 @@ Locate all the files you will need for this exercise * The shared __spatial parameters file__: injection2pspatialparams.hh * The shared __input file__: params.input

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

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

### Task 4: Setting up a non-isothermal __2pni__ test problem
* Open the file injection2pniproblem.hh. It is a copy of the injection2pproblem.hh with some useful comments on how to implement a non-isothermal model. Look for comments containing c++ // TODO: dumux-course-task // TODO: dumux-course-task 4  * The following set-up should be realized: __Boundary conditions:__ Dirichlet conditions at the left boundary. For the primary variable 'temperature' use a varying temperature of
$\displaystyle T(y) = 283~\text{K} + 0.03~\frac{\text{K}}{\text{m}} \cdot \left( d_\text{aquifer} - y \right) $,
with the aquifer depth with the aquifer depth $\displaystyle d_\text{aquifer}=2700~\text{m}$. Assign Neumann no-flow for the energy balance to the rest of the boundaries. ... ...
 ... ... @@ -43,8 +43,8 @@ class Injection2PNIProblem; namespace Properties { /*! * TODO:dumux-course-task: * inherit from the TwoPNI model instead of TwoP here * TODO:dumux-course-task 4 * Inherit from the TwoPNI model instead of TwoP here */ // Create new type tags namespace TTag { ... ...
 # Exercise Biomineralization # Exercise Biomineralization (DuMuX Course) The aim of this exercise is to get a first glimpse at the _DuMuX_ way of implementing mineralization and reaction processes. In the scope of this exercise, the setting of boundary conditions is revisited and a new reaction term is implemented. The aim of this exercise is to get a first glimpse at the _DuMux_ way of implementing mineralization and reaction processes. In the scope of this exercise, the setting of boundary conditions is revisited and a new reaction term is implemented. ## Problem set-up ... ... @@ -37,7 +37,7 @@ There are two types of solid components. Reactive and inert. For each reactive c ### 2. Implement a chemical equation In the following the basic steps required to set the new chemical equation are outlined. Here, this is done in the __chemistry__ folder in the prepared file: simplebiominreactions.hh within the function reactionSource(). In the following the basic steps required to set the new chemical equation are outlined. Here, this is done in the __chemistry__ folder in the prepared file: simplebiominreactions.hh within the function reactionSource(). Please be aware, that the chemistry file already provides some convenience functions (e.g. moleFracToMolality()). __Task__ ... ... @@ -74,7 +74,7 @@ To enable your newly created chemical equation, the chemistry file has to be inc #include "chemistry/simplebiominreactions.hh" // chemical reactions  Additionally the TypeTag of your chemistry file needs to be set in the problem file, within the class ExerciseFourBioMinProblem: Additionally the TypeTag of your chemistry file needs to be set in the problem file, within the class ExerciseFourBioMinProblem: c++ using Chemistry = typename Dumux::SimpleBiominReactions; ... ... @@ -82,7 +82,7 @@ using Chemistry = typename Dumux::SimpleBiominReactions
 # Exercise Coupling free flow/porous medium flow # Exercise Coupling free flow/porous medium flow (DuMuX Course) The aim of this exercise is to get familiar with setting up coupled free flow/porous medium flow problems. ... ... @@ -113,7 +113,7 @@ if (couplingManager().isCoupledEntity(CouplingManager::darcyIdx, scvf))  This should make the flow go from left to right. You can also delete the initial vertical velocity from initialAtPos(), to be consistent with the new boundary conditions. You can also delete the initial vertical velocity from initialAtPos(), to be consistent with the new boundary conditions. __Task B: Include slip-condition__ ... ... @@ -137,7 +137,7 @@ values.setBJS(Indices::momentumXBalanceIdx); at the position where the coupling boundary conditions are set in interface/freeflowsubproblem.hh. To check if the simulation behaves as expected, we can compare the velocity profile $v_x(y)$ with the analytical solution provided by [Beavers and Joseph (1967)](https://doi.org/10.1017/S0022112067001375). For doing so, we uncomment line 212 in exerciseinterfacecouplingffpm.cc. For doing so, we uncomment the following line in main.cc in the subfolder interface. cpp stokesVtkWriter.addField(stokesProblem->getAnalyticalVelocityX(), "analyticalV_x");  ... ... @@ -145,11 +145,9 @@ stokesVtkWriter.addField(stokesProblem->getAnalyticalVelocityX(), "analyticalV_x After re-compiling and re-running the executable, we should be able to see also the analytical solution of $v_x$ on the free flow domain. Play around with the grid resolution to see how that affects the velocity profile. __Task C: Cange shape of interface__ __Task C: Change the 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 96-106 in exerciseinterfacecouplingffpm.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. 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. To do so, open main.cc in the subfolder interface again and search for TODO: dumux-course-task 1.C. Comment out the first code block and uncomment the second. 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 auto elementSelectorStokes = [&](const auto& element) ... ... @@ -185,7 +183,9 @@ values.setCouplingNeumann(Indices::momentumYBalanceIdx); cpp values.setCouplingNeumann(scvf.directionIndex());  The same if true for the BJS condition, however, here we need to consider the tangential direction: in main.cc in the subfolder interface. The same is true for the BJS condition, however, here we need to consider the tangential direction: cpp values.setBJS(1 - scvf.directionIndex());  ... ... @@ -219,7 +219,7 @@ Although a 2p2c system is plugged in, we still want to simulate the same situati The following changes have to be made in the porous-medium model (models/porousmediumsubproblem.hh): * Include the 2pnc model: include the respective headers and inherit from the new model TwoPNC * Exchange the spatial parameters for the 1-phase system by those for a 2-phase system (hint: two occurrences). * Since two phases are involved now, we do not need to use the OnePAdapter anymore. Change to property of the FluidSystem such that H2OAir is used directly. * Since two phases are involved now, we do not need to use the OnePAdapter anymore. Change to property of the FluidSystem such that H2OAir is used directly. Afterwards, set the transportCompIdx to Indices::switchIdx. One big difference between the 1p and 2p model is, that the primary variables for which ... ... @@ -237,21 +237,19 @@ struct Formulation In contrast to the formulation, which stays the same during one simulation, the meaning of the primary variables may vary during one simulation. In the case we are investigating, we want to use the gas pressure and the liquid saturation as primary variables. In the case under investigation, we want to use the gas pressure and the liquid saturation as primary variables. However, if only the gas phase is present, the liquid saturation is always zero. In this case, the chosen formulation will set the given value as the mole fraction of water vapor in the gas phase. * To tell to program which phases are present in which parts of the domain at the beginning of the simulation, you have to call values.setState(MY_PHASE_PRESENCE); in initialAtPos(). Have a look at the indices.hh in the 2pnc model (as the 2p2c model is a special case of the 2pnc model) to figure out which is the correct value of MY_PHASE_PRESENCE for the presence of a gas-phase only (hint: the numbering of phase indices begins with 0, the numbering of the phase presence states begins with 1. Take a look at your formulation to find out which phase index to use for the gas phase.) you have to call values.setState(MY_PHASE_PRESENCE); in initialAtPos(). MY_PHASE_PRESENCE should be replaced with the correct value for the case where only a gas-phase is present. Have a look at the indices.hh in the 2pnc model (as the 2p2c model is a special case of the 2pnc model) in the subfolder porousmediumflow in your DuMuX directory. (hint: the numbering of phase indices begins with 0, the numbering of the phase presence states begins with 1. Take a look at your formulation to find out which phase index to use for the gas phase.) __Task B: Add output__: In the next step, we want to add some output to the simulation. First we want to know the water mass in the (porous-medium) system. Therefore, we evaluate the storage term of the water component. * Have a look at the function evaluateWaterMassStorageTerm() in the porous medium subproblem. * Have a look at the function evaluateWaterMassStorageTerm() in the porousmediumsubproblem.hh. Then implement a calculation of the total water mass: $\sum_{\alpha \in \textrm{g,l}} \left( \phi S_\alpha X^\text{w}_\alpha \varrho_\alpha V_\textrm{scv} \right)$. Afterwards, adapt the method init() such that the variable initialWaterContent_ is initialized correctly using the evaluateWaterMassStorageTerm() method and assign that value also to the variable lastWaterMass_. ... ... @@ -300,9 +298,9 @@ describe an algorithm to switch the primary variables, if phases should appear o Now you are able to simulate a complete drying of the porous medium. ### 4. Use a turbulence model in the free flow domain ### 3. Use a turbulence model in the free flow domain Several RANS turbulence models are implemented in DuMuX. Several RANS turbulence models are implemented in DuMux. This part of the exercise consists of the following steps: * replacing the Navier-Stokes model by the zero equation turbulence model, * switching to a symmetry boundary condition, ... ... @@ -355,7 +353,7 @@ These dynamic interactions are to be updated by calling cpp stokesProblem->updateDynamicWallProperties(stokesSol);  in the time loop (after // update dynamic wall properties). in the time loop (after // Update dynamic wall properties). Compile and run your new coupled problem and take a look at the results in Paraview. In addition to the standard variables and parameters, you can now analyze turbulence model specific quantities ... ...
 ... ... @@ -25,9 +25,9 @@ #include // TODO: dumux-course-task // TODO: dumux-course-task 1.C //****** uncomment for the last exercise *****// // #include // #include #include #include ... ... @@ -64,7 +64,7 @@ struct Grid using Scalar = GetPropType; using TensorGrid = Dune::YaspGrid<2, Dune::TensorProductCoordinates >; // TODO: dumux-course-task // TODO: dumux-course-task 1.C //****** comment out for the last exercise *****// using type = TensorGrid; ... ... @@ -161,8 +161,8 @@ public: const auto& globalPos = scvf.dofPosition(); // TODO: dumux-course-task // change the boundary conditions here as described in the exercise // TODO: dumux-course-task 1.A // Change the boundary conditions here as described in the exercise if(onUpperBoundary_(globalPos)) { values.setDirichlet(Indices::velocityXIdx); ... ... @@ -181,7 +181,14 @@ public: { values.setCouplingNeumann(Indices::conti0EqIdx); values.setCouplingNeumann(Indices::momentumYBalanceIdx); // TODO: dumux-course-task 1.B // Replace Dirichlet BC with Beavers-Joseph-Saffman slip condition for the tangential momentum balance values.setDirichlet(Indices::velocityXIdx); // assume no slip on interface // TODO: dumux-course-task 1.C // set the Beaver-Joseph-Saffman slip condition for the tangential momentum balance equation, // consider orientation of face automatically } return values; ... ... @@ -251,6 +258,8 @@ public: { PrimaryVariables values(0.0); values[Indices::velocityYIdx] = -1e-6 * globalPos[0] * (this->gridGeometry().bBoxMax()[0] - globalPos[0]); // TODO: dumux-course-task 1.A // Set fixed pressures on the left and right boundary return values; } ... ...
 ... ... @@ -88,8 +88,8 @@ int main(int argc, char** argv) try using DarcyTypeTag = Properties::TTag::DarcyOneP; // TODO: dumux-course-task: comment-out this section for the last exercise **************** // //TODO: dumux-course-task 1.C // ******************** comment-out this section for the last exercise **************** // // create two individual grids (from the given grid file or the input file) // for both sub-domains ... ... @@ -209,6 +209,7 @@ int main(int argc, char** argv) try StaggeredVtkOutputModule stokesVtkWriter(*stokesGridVariables, stokesSol, stokesName); GetPropType::initOutputModule(stokesVtkWriter); //TODO: dumux-course-task 1.B //****** uncomment the add analytical solution of v_x *****// // stokesVtkWriter.addField(stokesProblem->getAnalyticalVelocityX(), "analyticalV_x"); ... ...
 ... ... @@ -26,9 +26,9 @@ #include // TODO: dumux-course-task // TODO: dumux-course-task 1.C //****** uncomment for the last exercise *****// // #include // #include #include ... ...
 ... ... @@ -33,8 +33,11 @@ #include #include // TODO: dumux-course-task 2.A // Include 2pnc model here #include // TODO: dumux-course-task 2.A // Include spatial params for a 2-phase system #include "../1pspatialparams.hh" namespace Dumux ... ... @@ -46,6 +49,8 @@ namespace Properties { // Create new type tags namespace TTag { // TODO: dumux-course-task 2.A // Change to property of the FluidSystem such that H2OAir is used directly. struct DarcyOnePNC { using InheritsFrom = std::tuple; }; } // end namespace TTag ... ... @@ -77,8 +82,14 @@ struct EffectiveDiffusivityModel template struct Grid { using type = Dune::YaspGrid<2>; }; // TODO: dumux-course-task 2.A // Define new formulation for primary variables here. // Set the spatial paramaters type template // TODO: dumux-course-task 2.A // Adapt the spatial params here. struct SpatialParams { using type = OnePSpatialParams, GetPropType>; }; ... ... @@ -113,6 +124,8 @@ class PorousMediumSubProblem : public PorousMediumFlowProblem conti0EqIdx = Indices::conti0EqIdx, pressureIdx = Indices::pressureIdx, phaseIdx = 0, // TODO: dumux-course-task 2.A // set the transportCompIdx to Indices::switchIdx. transportCompIdx = 1 }; ... ... @@ -152,7 +165,11 @@ public: template void init(const SolutionVector& curSol, const GridVariables& gridVariables) { } { // TODO: dumux-course-task 2.B // Initialize initialWaterContent_ and assign that to lastWaterMass_. } template void postTimeStep(const SolutionVector& curSol, ... ... @@ -196,7 +213,9 @@ public: for (auto&& scv : scvs(fvGeometry)) { // const auto& volVars = elemVolVars[scv]; // insert calculation of the water mass here // TODO: dumux-course-task 2.B // Insert calculation of the water mass here waterMass += 0.0; } } ... ... @@ -237,7 +256,9 @@ public: if (!couplingManager().isCoupledEntity(CouplingManager::darcyIdx, scvf)) continue; NumEqVector flux(0.0); // use "massCouplingCondition" from the couplingManager here // TODO: dumux-course-task 2.B // Use "massCouplingCondition" from the couplingManager here NumEqVector flux(0.0); x.push_back(scvf.center()[0]); y.push_back(flux[transportCompIdx]); ... ... @@ -355,6 +376,10 @@ public: static const Scalar stokesPressure = getParamFromGroup("Stokes", "Problem.Pressure"); PrimaryVariables values(0.0); // TODO: dumux-course-task 2.A // Declare here which phases are present. values[Indices::pressureIdx] = stokesPressure; values[transportCompIdx] = moleFraction_; return values; ... ...
 ... ... @@ -29,6 +29,8 @@ #include #include // TODO: dumux-course-task 3.A // Include headers for compositional zero equation turbulence model here. #include #include ... ... @@ -41,6 +43,8 @@ namespace Properties { // Create new type tags namespace TTag { // TODO: dumux-course-task 3.A // Change the entry in the StokesZeroEq definition accordingly. struct StokesZeroEq { using InheritsFrom = std::tuple; }; } // end namespace TTag ... ... @@ -80,6 +84,8 @@ struct EnableGridVolumeVariablesCache { static cons * \brief The free-flow sub problem */ template // TODO: dumux-course-task 3.A // Adapt the inheritance of the problem class. class FreeFlowSubProblem : public NavierStokesProblem { using ParentType = NavierStokesProblem; ... ... @@ -181,6 +187,8 @@ public: if (onUpperBoundary_(globalPos)) { // TODO: dumux-course-task 3.B // Replace all conditions here with symmetric BCs. values.setDirichlet(Indices::velocityXIdx); values.setDirichlet(Indices::velocityYIdx); values.setNeumann(Indices::conti0EqIdx); ... ... @@ -262,6 +270,12 @@ public: const CouplingManager& couplingManager() const { return *couplingManager_; } // TODO: dumux-course-task 3.A // Tell the turbulence model, where the walls are located // TODO: dumux-course-task 3.B // Remove the condition onUpperBoundary_(globalPos) from the isOnWallAtPos(globalPos) /*! * \name Volume terms */ ... ... @@ -285,6 +299,8 @@ public: values[Indices::velocityXIdx] = refVelocity(); values[Indices::temperatureIdx] = refTemperature(); // TODO: dumux-course-task 3.B // Remove the condition onUpperBoundary_(globalPos) here. if(onUpperBoundary_(globalPos) || onLowerBoundary_(globalPos)) values[Indices::velocityXIdx] = 0.0; ... ...
 ... ... @@ -161,8 +161,11 @@ int main(int argc, char** argv) try couplingManager->init(stokesProblem, darcyProblem, sol); // TODO: update static wall properties // TODO: update dynamic wall properties // TODO: dumux-course-task 3.A // Update static wall properties // TODO: dumux-course-task 3.A // Update dynamic wall properties // the grid variables using StokesGridVariables = GetPropType; ... ... @@ -218,7 +221,8 @@ int main(int argc, char** argv) try // make the new solution the old solution solOld = sol; // TODO: update dynamic wall properties // TODO: dumux-course-task 3.A // Update dynamic wall properties // post time step treatment of Darcy problem darcyProblem->postTimeStep(sol[darcyIdx], *darcyGridVariables, timeLoop->timeStepSize()); ... ...

... ... @@ -33,7 +33,7 @@ The following command will configure your new module You need to run this command in the folder with content dumux, dumux-course, dune-common, dune-geometry, dune-grid, dune-istl, etc.  needs to be replaced (please replace the angle brackets also) by an options file, e.g., by ./dumux/cmake.opts. Have a look at the comments in this file to see how you can adapt it to your needs.

### Task 3: Create a new test case within your new DuMuX module
... ... @@ -77,7 +77,7 @@ cd appl ./test_1p_compressible_stationary_tpfa params.input 

### Task 4: Create a new GitLab project
... ...
 ... ... @@ -44,6 +44,8 @@ #include // The components that will be created in this exercise // TODO: dumux-course-task 2.2 //****** Include the corresponding header for the task *****// #include "components/myincompressiblecomponent.hh" // #include "components/mycompressiblecomponent.hh" ... ... @@ -94,10 +96,10 @@ private: using Scalar = GetPropType; using TabulatedH2O = Components::TabulatedComponent>; using LiquidWaterPhase = typename FluidSystems::OnePLiquid; /*! * Uncomment first line and comment second line for using the incompressible component * Uncomment second line and comment first line for using the compressible component */ // TODO: dumux-course-task 2.2 //****** Select the corresponding component for the task *****// // Uncomment first line and comment second line for using the compressible component using LiquidMyComponentPhase = typename FluidSystems::OnePLiquid >; // using LiquidMyComponentPhase = typename FluidSystems::OnePLiquid >; ... ...
 # Exercise Fluidsystem # Exercise Fluidsystem (DuMuX Course) The aim of this exercise is to get familiar with the _DuMuX_ way of implementing new components (fluids) and fluid systems (mixtures). In the scope of this exercise, a new fictitious component is implemented (exercise fluidsystem a) as well as its mixture with water (exercise fluidsystem b). The aim of this exercise is to get familiar with the _DuMux_ way of implementing new components (fluids) and fluid systems (mixtures). In the scope of this exercise, a new fictitious component is implemented (Section 2) as well as its mixture with water (Section 3). ## Problem set-up ... ... @@ -91,9 +90,8 @@ This fluid system expects __phases__ as input and so far we have only included t #include  which creates a _liquid phase_ from a given component. Finally, using all of the included classes we set the fluid system property by choosing that the water phase is liquid (OnePLiquid) and consists of the tabulated water component, and the other phase is liquid as well and consists of the incompressible fictitious component. Both will make up the immiscible fluid system (TwoPImmiscible): which creates a _liquid phase_ from a given component. Finally, using all of the included classes we set the fluid system property by choosing that the water phase is liquid (OnePLiquid) and consists of the tabulated water component, and the other phase is liquid as well and consists of the incompressible fictitious component. Both will make up the immiscible fluid system (TwoPImmiscible): c++ ... ... @@ -105,10 +103,10 @@ private: using Scalar = GetPropType; using TabulatedH2O = Components::TabulatedComponent>; using LiquidWaterPhase = typename FluidSystems::OnePLiquid; /*! * Uncomment first line and comment second line for using the incompressible component * Uncomment second line and comment first line for using the compressible component */ // TODO: dumux-course-task 2.2 //****** Select the corresponding component for the task *****// // Uncomment first line and comment second line for using the compressible component using LiquidMyComponentPhase = typename FluidSystems::OnePLiquid >; // using LiquidMyComponentPhase = typename FluidSystems::OnePLiquid >; ... ... @@ -164,7 +162,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 109 and uncomment line 110. 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 the corresponding line. Furthermore, the new component has to be set as a liquid phase in the fluid system. To do so, search for TODO: dumux-course-task 2.2. Comment out the corresponding line and uncomment the other. The density distribution of this phase (rhoN) at the final simulation time should look like this: ![](../extradoc/exercise-fluidsystem_a_solution2.png) ... ... @@ -224,7 +222,7 @@ Under the assumption that one molecule of MyCompressibleComponent displaces ex $ \rho_{w} = \frac{ \rho_{w, pure} }{ M_{H_2O} }*(M_{H_2O}*x_{H_2O} + M_{MyComponent}*x_{MyComponent}) $ Implement this dependency in the density() method in the fluid system. In order to compile and execute the program run Implement this dependency in the density() method in the fluid system. In order to compile and execute the program, run the following commands: bash cd build-cmake/exercises/exercise-fluidsystem ... ... @@ -255,7 +253,7 @@ int wettingPhaseAtPos(const GlobalPosition& globalPos) const }  Change this function such that the the phase of our new component is the wetting phase __only__ within the lenses. Execute the program of task 3 again: Change this function such that the phase of our new component is the wetting phase __only__ within the lenses. Execute the program of task 3 again: bash cd build-cmake/exercises/exercise-fluidsystem ... ...
 ... ... @@ -50,12 +50,7 @@ public: static std::string name() { return "MyCompressibleComponent"; } /*! * TODO: Copy the methods implemented in MyIncompressibleComponent and substitute * the density calculation by the expression given in the exercise description. */ /*! /*! * \brief Returns true if the liquid phase is assumed to be compressible */ static constexpr bool liquidIsCompressible() ... ... @@ -66,7 +61,10 @@ public: */ static Scalar molarMass() { // TODO: replace the line below by a meaningful return statement // TODO: dumux-course-task 2.2 // Copy the methods implemented in MyIncompressibleComponent and substitute // the density calculation by the expression given in the exercise description. // Replace the line below by a meaningful return statement DUNE_THROW(Dune::NotImplemented, "Todo: implement molar mass"); } ... ... @@ -79,7 +77,8 @@ public: */ static Scalar liquidDensity(Scalar temperature, Scalar pressure) { // TODO: replace the line below by a meaningful return statement // TODO: dumux-course-task 2.2: // Replace the line below by a meaningful return statement DUNE_THROW(Dune::NotImplemented, "Todo: implement liquid density"); } ... ... @@ -104,7 +103,8 @@ public: */ static Scalar liquidViscosity(Scalar temperature, Scalar pressure) { // TODO: replace the line below by a meaningful return statement // TODO: dumux-course-task 2.2: // Replace the line below by a meaningful return statement DUNE_THROW(Dune::NotImplemented, "Todo: implement liquid viscosity"); } ... ... @@ -116,7 +116,8 @@ public: */