From ba7ae6bd204202df982ce20747ed578860da3950 Mon Sep 17 00:00:00 2001 From: tkurz <theresa.kurz@iws.uni-stuttgart.de> Date: Tue, 18 Jun 2019 22:39:14 +0200 Subject: [PATCH] [test][2pncminni] add a test for evaporation with salt precipitation for the 2pncmin nonisothermal model --- .../2pncmin/implicit/CMakeLists.txt | 38 +- .../implicit/isothermal/CMakeLists.txt | 34 ++ .../2pncmin/implicit/{ => isothermal}/main.cc | 0 .../implicit/{ => isothermal}/params.input | 0 .../implicit/{ => isothermal}/problem.hh | 0 .../{ => isothermal}/spatialparams.hh | 0 .../implicit/nonisothermal/CMakeLists.txt | 12 + .../2pncmin/implicit/nonisothermal/main.cc | 247 ++++++++ .../implicit/nonisothermal/params.input | 52 ++ .../2pncmin/implicit/nonisothermal/problem.hh | 568 ++++++++++++++++++ .../implicit/nonisothermal/spatialparams.hh | 181 ++++++ .../test_2pncminni_salinization-reference.vtu | 139 +++++ 12 files changed, 1235 insertions(+), 36 deletions(-) create mode 100644 test/porousmediumflow/2pncmin/implicit/isothermal/CMakeLists.txt rename test/porousmediumflow/2pncmin/implicit/{ => isothermal}/main.cc (100%) rename test/porousmediumflow/2pncmin/implicit/{ => isothermal}/params.input (100%) rename test/porousmediumflow/2pncmin/implicit/{ => isothermal}/problem.hh (100%) rename test/porousmediumflow/2pncmin/implicit/{ => isothermal}/spatialparams.hh (100%) create mode 100644 test/porousmediumflow/2pncmin/implicit/nonisothermal/CMakeLists.txt create mode 100644 test/porousmediumflow/2pncmin/implicit/nonisothermal/main.cc create mode 100644 test/porousmediumflow/2pncmin/implicit/nonisothermal/params.input create mode 100644 test/porousmediumflow/2pncmin/implicit/nonisothermal/problem.hh create mode 100644 test/porousmediumflow/2pncmin/implicit/nonisothermal/spatialparams.hh create mode 100644 test/references/test_2pncminni_salinization-reference.vtu diff --git a/test/porousmediumflow/2pncmin/implicit/CMakeLists.txt b/test/porousmediumflow/2pncmin/implicit/CMakeLists.txt index eb412f736f..bc7eb9a410 100644 --- a/test/porousmediumflow/2pncmin/implicit/CMakeLists.txt +++ b/test/porousmediumflow/2pncmin/implicit/CMakeLists.txt @@ -1,36 +1,2 @@ -dune_symlink_to_source_files(FILES params.input) - -# isothermal tests -dune_add_test(NAME test_2pncmin_dissolution_box - LABELS porousmediumflow 2pncmin - SOURCES main.cc - COMPILE_DEFINITIONS TYPETAG=DissolutionBox - TIMEOUT 1500 - COMMAND ${CMAKE_SOURCE_DIR}/bin/testing/runtest.py - CMD_ARGS --script fuzzy - --files ${CMAKE_SOURCE_DIR}/test/references/test_2pncmin_dissolution_box-reference.vtu - ${CMAKE_CURRENT_BINARY_DIR}/test_2pncmin_dissolution_box-00044.vtu - --command "${CMAKE_CURRENT_BINARY_DIR}/test_2pncmin_dissolution_box -ParameterFile params.input -Problem.Name test_2pncmin_dissolution_box") - -dune_add_test(NAME test_2pncmin_dissolution_box_restart - LABELS porousmediumflow 2pncmin - TARGET test_2pncmin_dissolution_box - COMMAND ${CMAKE_SOURCE_DIR}/bin/testing/runtest.py - CMD_ARGS --script fuzzy - --files ${CMAKE_SOURCE_DIR}/test/references/test_2pncmin_dissolution_box-reference.vtu - ${CMAKE_CURRENT_BINARY_DIR}/test_2pncmin_dissolution_box_restart-00005.vtu - --command "${CMAKE_CURRENT_BINARY_DIR}/test_2pncmin_dissolution_box params.input -Problem.Name test_2pncmin_dissolution_box_restart -TimeLoop.DtInitial 50000 -Restart.Time 756290 -Restart.File test_2pncmin_dissolution_box-00039.vtu") - -# the restart test has to run after the test that produces the corresponding vtu file -set_tests_properties(test_2pncmin_dissolution_box_restart PROPERTIES DEPENDS test_2pncmin_dissolution_box) - -dune_add_test(NAME test_2pncmin_dissolution_tpfa - LABELS porousmediumflow 2pncmin - SOURCES main.cc - COMPILE_DEFINITIONS TYPETAG=DissolutionCCTpfa - TIMEOUT 1500 - COMMAND ${CMAKE_SOURCE_DIR}/bin/testing/runtest.py - CMD_ARGS --script fuzzy - --files ${CMAKE_SOURCE_DIR}/test/references/test_2pncmin_dissolution_tpfa-reference.vtu - ${CMAKE_CURRENT_BINARY_DIR}/test_2pncmin_dissolution_tpfa-00043.vtu - --command "${CMAKE_CURRENT_BINARY_DIR}/test_2pncmin_dissolution_tpfa -ParameterFile params.input -Problem.Name test_2pncmin_dissolution_tpfa") +add_subdirectory(isothermal) +add_subdirectory(nonisothermal) diff --git a/test/porousmediumflow/2pncmin/implicit/isothermal/CMakeLists.txt b/test/porousmediumflow/2pncmin/implicit/isothermal/CMakeLists.txt new file mode 100644 index 0000000000..4b2d0333ce --- /dev/null +++ b/test/porousmediumflow/2pncmin/implicit/isothermal/CMakeLists.txt @@ -0,0 +1,34 @@ +dune_symlink_to_source_files(FILES params.input) + +# isothermal tests +dune_add_test(NAME test_2pncmin_dissolution_box + LABELS porousmediumflow 2pncmin + SOURCES main.cc + COMPILE_DEFINITIONS TYPETAG=DissolutionBox + COMMAND ${CMAKE_SOURCE_DIR}/bin/testing/runtest.py + CMD_ARGS --script fuzzy + --files ${CMAKE_SOURCE_DIR}/test/references/test_2pncmin_dissolution_box-reference.vtu + ${CMAKE_CURRENT_BINARY_DIR}/test_2pncmin_dissolution_box-00044.vtu + --command "${CMAKE_CURRENT_BINARY_DIR}/test_2pncmin_dissolution_box -ParameterFile params.input -Problem.Name test_2pncmin_dissolution_box") + +dune_add_test(NAME test_2pncmin_dissolution_box_restart + LABELS porousmediumflow 2pncmin + TARGET test_2pncmin_dissolution_box + COMMAND ${CMAKE_SOURCE_DIR}/bin/testing/runtest.py + CMD_ARGS --script fuzzy + --files ${CMAKE_SOURCE_DIR}/test/references/test_2pncmin_dissolution_box-reference.vtu + ${CMAKE_CURRENT_BINARY_DIR}/test_2pncmin_dissolution_box_restart-00005.vtu + --command "${CMAKE_CURRENT_BINARY_DIR}/test_2pncmin_dissolution_box params.input -Problem.Name test_2pncmin_dissolution_box_restart -TimeLoop.DtInitial 50000 -Restart.Time 756290 -Restart.File test_2pncmin_dissolution_box-00039.vtu") + +# the restart test has to run after the test that produces the corresponding vtu file +set_tests_properties(test_2pncmin_dissolution_box_restart PROPERTIES DEPENDS test_2pncmin_dissolution_box) + +dune_add_test(NAME test_2pncmin_dissolution_tpfa + LABELS porousmediumflow 2pncmin + SOURCES main.cc + COMPILE_DEFINITIONS TYPETAG=DissolutionCCTpfa + COMMAND ${CMAKE_SOURCE_DIR}/bin/testing/runtest.py + CMD_ARGS --script fuzzy + --files ${CMAKE_SOURCE_DIR}/test/references/test_2pncmin_dissolution_tpfa-reference.vtu + ${CMAKE_CURRENT_BINARY_DIR}/test_2pncmin_dissolution_tpfa-00043.vtu + --command "${CMAKE_CURRENT_BINARY_DIR}/test_2pncmin_dissolution_tpfa -ParameterFile params.input -Problem.Name test_2pncmin_dissolution_tpfa") diff --git a/test/porousmediumflow/2pncmin/implicit/main.cc b/test/porousmediumflow/2pncmin/implicit/isothermal/main.cc similarity index 100% rename from test/porousmediumflow/2pncmin/implicit/main.cc rename to test/porousmediumflow/2pncmin/implicit/isothermal/main.cc diff --git a/test/porousmediumflow/2pncmin/implicit/params.input b/test/porousmediumflow/2pncmin/implicit/isothermal/params.input similarity index 100% rename from test/porousmediumflow/2pncmin/implicit/params.input rename to test/porousmediumflow/2pncmin/implicit/isothermal/params.input diff --git a/test/porousmediumflow/2pncmin/implicit/problem.hh b/test/porousmediumflow/2pncmin/implicit/isothermal/problem.hh similarity index 100% rename from test/porousmediumflow/2pncmin/implicit/problem.hh rename to test/porousmediumflow/2pncmin/implicit/isothermal/problem.hh diff --git a/test/porousmediumflow/2pncmin/implicit/spatialparams.hh b/test/porousmediumflow/2pncmin/implicit/isothermal/spatialparams.hh similarity index 100% rename from test/porousmediumflow/2pncmin/implicit/spatialparams.hh rename to test/porousmediumflow/2pncmin/implicit/isothermal/spatialparams.hh diff --git a/test/porousmediumflow/2pncmin/implicit/nonisothermal/CMakeLists.txt b/test/porousmediumflow/2pncmin/implicit/nonisothermal/CMakeLists.txt new file mode 100644 index 0000000000..082a0bbdb4 --- /dev/null +++ b/test/porousmediumflow/2pncmin/implicit/nonisothermal/CMakeLists.txt @@ -0,0 +1,12 @@ +dune_symlink_to_source_files(FILES params.input) + +# isothermal tests +dune_add_test(NAME test_2pncminni_salinization + LABELS porousmediumflow 2pncmin + SOURCES main.cc + COMPILE_DEFINITIONS TYPETAG=SalinizationBox + COMMAND ${CMAKE_SOURCE_DIR}/bin/testing/runtest.py + CMD_ARGS --script fuzzy + --files ${CMAKE_SOURCE_DIR}/test/references/test_2pncminni_salinization-reference.vtu + ${CMAKE_CURRENT_BINARY_DIR}/test_2pncminni_salinization-00034.vtu + --command "${CMAKE_CURRENT_BINARY_DIR}/test_2pncminni_salinization -ParameterFile params.input -Problem.Name test_2pncminni_salinization") diff --git a/test/porousmediumflow/2pncmin/implicit/nonisothermal/main.cc b/test/porousmediumflow/2pncmin/implicit/nonisothermal/main.cc new file mode 100644 index 0000000000..d6ab3b32ed --- /dev/null +++ b/test/porousmediumflow/2pncmin/implicit/nonisothermal/main.cc @@ -0,0 +1,247 @@ +// -*- mode: C++; tab-width: 4; indent-tabs-mode: nil; c-basic-offset: 4 -*- +// vi: set et ts=4 sw=4 sts=4: +/***************************************************************************** + * See the file COPYING for full copying permissions. * + * * + * This program is free software: you can redistribute it and/or modify * + * it under the terms of the GNU General Public License as published by * + * the Free Software Foundation, either version 3 of the License, or * + * (at your option) any later version. * + * * + * This program is distributed in the hope that it will be useful, * + * but WITHOUT ANY WARRANTY; without even the implied warranty of * + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the * + * GNU General Public License for more details. * + * * + * You should have received a copy of the GNU General Public License * + * along with this program. If not, see <http://www.gnu.org/licenses/>. * + *****************************************************************************/ +/*! + * \file + * \ingroup TwoPNCMinTests + * \brief Test for the nonisothermal two-phase n-component finite volume model used to model e.g. salt precipitation. + */ +#include <config.h> + +#include <ctime> +#include <iostream> + +#include <dune/common/parallel/mpihelper.hh> +#include <dune/common/timer.hh> +#include <dune/grid/io/file/dgfparser/dgfexception.hh> +#include <dune/grid/io/file/vtk.hh> +#include <dune/istl/io.hh> + +#include "problem.hh" + +#include <dumux/common/properties.hh> +#include <dumux/common/parameters.hh> +#include <dumux/common/valgrind.hh> +#include <dumux/common/dumuxmessage.hh> +#include <dumux/common/defaultusagemessage.hh> + +#include <dumux/linear/amgbackend.hh> +#include <dumux/nonlinear/newtonsolver.hh> + +#include <dumux/assembly/fvassembler.hh> +#include <dumux/assembly/diffmethod.hh> + +#include <dumux/discretization/method.hh> + +#include <dumux/io/vtkoutputmodule.hh> +#include <dumux/io/grid/gridmanager.hh> +#include <dumux/io/loadsolution.hh> + +/*! + * \brief Provides an interface for customizing error messages associated with + * reading in parameters. + * + * \param progName The name of the program, that was tried to be started. + * \param errorMsg The error message that was issued by the start function. + * Comprises the thing that went wrong and a general help message. + */ +void usage(const char *progName, const std::string &errorMsg) +{ + if (errorMsg.size() > 0) { + std::string errorMessageOut = "\nUsage: "; + errorMessageOut += progName; + errorMessageOut += " [options]\n"; + errorMessageOut += errorMsg; + errorMessageOut += "\n\nThe list of mandatory options for this program is:\n" + "\t-ParameterFile Parameter file (Input file) \n"; + + std::cout << errorMessageOut + << "\n"; + } +} + +int main(int argc, char** argv) try +{ + using namespace Dumux; + + // define the type tag for this problem + using TypeTag = Properties::TTag::TYPETAG; + + // 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, usage); + + // try to create a grid (from the given grid file or the input file) + GridManager<GetPropType<TypeTag, Properties::Grid>> 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<TypeTag, Properties::FVGridGeometry>; + auto fvGridGeometry = std::make_shared<FVGridGeometry>(leafGridView); + fvGridGeometry->update(); + + // the problem (initial and boundary conditions) + using Problem = GetPropType<TypeTag, Properties::Problem>; + auto problem = std::make_shared<Problem>(fvGridGeometry); + + // get some time loop parameters + using Scalar = GetPropType<TypeTag, Properties::Scalar>; + const auto tEnd = getParam<Scalar>("TimeLoop.TEnd"); + const auto maxDt = getParam<Scalar>("TimeLoop.MaxTimeStepSize"); + auto dt = getParam<Scalar>("TimeLoop.DtInitial"); + + // check if we are about to restart a previously interrupted simulation + Scalar restartTime = getParam<Scalar>("Restart.Time", 0); + + // the solution vector + using SolutionVector = GetPropType<TypeTag, Properties::SolutionVector>; + SolutionVector x(fvGridGeometry->numDofs()); + if (restartTime > 0) + { + using IOFields = GetPropType<TypeTag, Properties::IOFields>; + using PrimaryVariables = GetPropType<TypeTag, Properties::PrimaryVariables>; + using ModelTraits = GetPropType<TypeTag, Properties::ModelTraits>; + using FluidSystem = GetPropType<TypeTag, Properties::FluidSystem>; + using SolidSystem = GetPropType<TypeTag, Properties::SolidSystem>; + const auto fileName = getParam<std::string>("Restart.File"); + const auto pvName = createPVNameFunction<IOFields, PrimaryVariables, ModelTraits, FluidSystem, SolidSystem>(); + loadSolution(x, fileName, pvName, *fvGridGeometry); + } + else + problem->applyInitialSolution(x); + auto xOld = x; + + // the grid variables + using GridVariables = GetPropType<TypeTag, Properties::GridVariables>; + auto gridVariables = std::make_shared<GridVariables>(problem, fvGridGeometry); + gridVariables->init(x); + + // initialize the vtk output module + using IOFields = GetPropType<TypeTag, Properties::IOFields>; + VtkOutputModule<GridVariables, SolutionVector> vtkWriter(*gridVariables, x, problem->name()); + using VelocityOutput = GetPropType<TypeTag, Properties::VelocityOutput>; + vtkWriter.addVelocityOutput(std::make_shared<VelocityOutput>(*gridVariables)); + IOFields::initOutputModule(vtkWriter); // Add model specific output fields + //add specific output + vtkWriter.addField(problem->getPermeability(), "Permeability"); + // update the output fields before write + problem->updateVtkOutput(x); + vtkWriter.write(restartTime); + + // instantiate time loop + auto timeLoop = std::make_shared<TimeLoop<Scalar>>(restartTime, dt, tEnd); + timeLoop->setMaxTimeStepSize(maxDt); + + // the assembler with time loop for instationary problem + using Assembler = FVAssembler<TypeTag, DiffMethod::numeric>; + auto assembler = std::make_shared<Assembler>(problem, fvGridGeometry, gridVariables, timeLoop); + + // the linear solver + using LinearSolver = AMGBackend<TypeTag>; + auto linearSolver = std::make_shared<LinearSolver>(leafGridView, fvGridGeometry->dofMapper()); + + // the non-linear solver + using NewtonSolver = NewtonSolver<Assembler, LinearSolver>; + NewtonSolver nonLinearSolver(assembler, linearSolver); + + // time loop + timeLoop->start(); do + { + // set time for problem for implicit Euler scheme + problem->setTime( timeLoop->time() + timeLoop->timeStepSize() ); + problem->setTimeStepSize( timeLoop->timeStepSize() ); + + // set previous solution for storage evaluations + assembler->setPreviousSolution(xOld); + + // solve the non-linear system with time step control + nonLinearSolver.solve(x, *timeLoop); + + // 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 + vtkWriter.write(timeLoop->time()); + + // report statistics of this time step + timeLoop->reportTimeStep(); + + // set new dt as suggested by the newton solver + 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/test/porousmediumflow/2pncmin/implicit/nonisothermal/params.input b/test/porousmediumflow/2pncmin/implicit/nonisothermal/params.input new file mode 100644 index 0000000000..67456e2cae --- /dev/null +++ b/test/porousmediumflow/2pncmin/implicit/nonisothermal/params.input @@ -0,0 +1,52 @@ +# Parameter file for test case 2pncmin. +# Everything behind a '#' is a comment. +# Type "./test_2pncmin --help" for more information. + +[TimeLoop] +TEnd = 80000 # duration of the simulation [s] +DtInitial = 1 # initial time step size [s] +MaxTimeStepSize = 5000 # maximum time step size + +[Grid] +Positions0 = 0 0.02 +Positions1 = 0 0.015 0.02 +Cells0 = 2 +Cells1 = 2 3 +Grading0 = 1.0 +Grading1 = 1.0 -1.2 + +[FluidSystem] +NTemperature = 100 # [-] number of tabularization entries +NPressure = 100 # [-] number of tabularization entries +PressureLow = 1e4 # [Pa]low end for tabularization of fluid properties +PressureHigh = 3e6 # [Pa]high end for tabularization of fluid properties +TemperatureLow = 273.15 # [K]low end for tabularization of fluid properties +TemperatureHigh = 400.00 # [K]high end for tabularization of fluid properties + +[Problem] +Name = test_2pncminni # [-] name for output files +Temperature = 299 # [K] initial temperature +InitialPressure = 1.00e5 # [Pa] Initial reservoir pressure +InitialGasSaturation = 0.5 # [-] initial gas saturation +InitialSalinity = 2.00e-2 # [-]=[kgNaCl/kgSolution] Initial salt mass fraction + +[FreeFlow] +RefMoleFracH2O = 6.0e-3 # [-] mole fraction of water vapor in air above the container +BoundaryLayerThickness = 1e-2 # [m] thickness of boundary layer over which the water vapor diffuses +MassTransferCoefficient = 1 +RefTemperature = 299 # [K] temperature in the air above container + +[SpatialParams] +SolubilityLimit = 0.26 # [-] solubility limit of NaCl in brine +referencePorosity = 0.4 # [-] initial porosity +referencePermeability = 1e-13 # [m²] initial permeability +VGAlpha = 0.00015 # Van Genuchten parameter +VGn = 14.0 # Van Genuchten parameter +IrreducibleLiqSat = 0.25 # [-] irreducible liquid saturation +IrreducibleGasSat = 0.025 # [-] irreducible gas saturation + +[Vtk] +AddVelocity = 1 # Add extra information + +[Output] +PlotFluidMatrixInteractions = false diff --git a/test/porousmediumflow/2pncmin/implicit/nonisothermal/problem.hh b/test/porousmediumflow/2pncmin/implicit/nonisothermal/problem.hh new file mode 100644 index 0000000000..8756092803 --- /dev/null +++ b/test/porousmediumflow/2pncmin/implicit/nonisothermal/problem.hh @@ -0,0 +1,568 @@ +// -*- 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 3 of the License, or * + * (at your option) any later version. * + * * + * This program is distributed in the hope that it will be useful, * + * but WITHOUT ANY WARRANTY; without even the implied warranty of * + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the * + * GNU General Public License for more details. * + * * + * You should have received a copy of the GNU General Public License * + * along with this program. If not, see <http://www.gnu.org/licenses/>. * + *****************************************************************************/ +/*! + * \file + * \ingroup TwoPNCMinTests + * \brief Problem where water is injected in a for flushing precipitated salt clogging a gas reservoir. + */ +#ifndef DUMUX_SALINIZATION_PROBLEM_HH +#define DUMUX_SALINIZATION_PROBLEM_HH + +#include <dune/grid/yaspgrid.hh> + +#include <dumux/discretization/elementsolution.hh> +#include <dumux/discretization/method.hh> +#include <dumux/discretization/cctpfa.hh> +#include <dumux/discretization/box.hh> +#include <dumux/porousmediumflow/2pncmin/model.hh> +#include <dumux/porousmediumflow/problem.hh> +#include <dumux/material/fluidsystems/brineair.hh> + +#include <dumux/material/components/nacl.hh> +#include <dumux/material/components/granite.hh> +#include <dumux/material/solidsystems/compositionalsolidphase.hh> + +#include "spatialparams.hh" + +namespace Dumux { +/*! + * \ingroup TwoPNCMinTests + * \brief Problem where brine is evaporating at the top boundary. The system is closed the remaining boundaries. + */ +template <class TypeTag> +class SalinizationProblem; + +namespace Properties { +// Create new type tags +namespace TTag { +struct Salinization { using InheritsFrom = std::tuple<TwoPNCMinNI>; }; +struct SalinizationBox { using InheritsFrom = std::tuple<Salinization, BoxModel>; }; +struct SalinizationCCTpfa { using InheritsFrom = std::tuple<Salinization, CCTpfaModel>; }; +} // end namespace TTag + +// Set the grid type +SET_TYPE_PROP(Salinization, Grid, Dune::YaspGrid<2, Dune::TensorProductCoordinates<double, 2> >); + +// Set the problem property +template<class TypeTag> +struct Problem<TypeTag, TTag::Salinization> { using type = SalinizationProblem<TypeTag>; }; + +// Set fluid configuration +template<class TypeTag> +struct FluidSystem<TypeTag, TTag::Salinization> +{ + using Scalar = GetPropType<TypeTag, Properties::Scalar>; + using type = FluidSystems::BrineAir<Scalar, Components::H2O<Scalar>>; +}; + +template<class TypeTag> +struct SolidSystem<TypeTag, TTag::Salinization> +{ + using Scalar = GetPropType<TypeTag, Properties::Scalar>; + using ComponentOne = Components::NaCl<Scalar>; + using ComponentTwo = Components::Granite<Scalar>; + static constexpr int numInertComponents = 1; + using type = SolidSystems::CompositionalSolidPhase<Scalar, ComponentOne, ComponentTwo, numInertComponents>; +}; + +// Set the spatial parameters +template<class TypeTag> +struct SpatialParams<TypeTag, TTag::Salinization> +{ + using FVGridGeometry = GetPropType<TypeTag, Properties::FVGridGeometry>; + using Scalar = GetPropType<TypeTag, Properties::Scalar>; + using type = SalinizationSpatialParams<FVGridGeometry, Scalar>; +}; + +// Set properties here to override the default property settings +template<class TypeTag> +struct ReplaceCompEqIdx<TypeTag, TTag::Salinization> { static constexpr int value = 1; }; //!< Replace gas balance by total mass balance +template<class TypeTag> +struct Formulation<TypeTag, TTag::Salinization> +{ static constexpr auto value = TwoPFormulation::p0s1; }; + +} // end namespace Properties + +/*! + * \ingroup TwoPNCMinTests + * \brief Problem where water is evaporating at the top of a porous media filled + * container saturated with brine and air, which causes precipitation at the top. + * + * Problem with a porous media in a container, which is open to the atmosphere + * at the top boundary. The container has dimensions of 0.2m by 0.2m. Neumann + * no-flow boundaries are applied at the left, right and bottom boundary. + * The grid is refined towards the upper boundary to capter the relevant processes. + * + * Initially the porous medium is 50 % saturated with brine. Evaporation takes + * place at the top boundary and hence the temperature and liquid saturation + * decreases first at the top, then in the whole system, whereas the sodium + * chloride (NaCl) concentration increases. This results in precipitaion of NaCl + * at the top as the solubility limit is exceeded. Due to the low liquid saturation + * the top after some time, top temperature rises again. + * + * The model uses mole fractions of dissolved components and volume fractions of + * precipitated salt as primary variables. Make sure that the according units + * are used in the problem set-up. + * + * This problem uses the \ref TwoPNCMinModel. + * + * To run the simulation execute the following line in shell: + * <tt>./test_2pncminni_salinization</tt> + */ +template <class TypeTag> +class SalinizationProblem : public PorousMediumFlowProblem<TypeTag> +{ + using ParentType = PorousMediumFlowProblem<TypeTag>; + using GridView = GetPropType<TypeTag, Properties::GridView>; + using Scalar = GetPropType<TypeTag, Properties::Scalar>; + using FluidSystem = GetPropType<TypeTag, Properties::FluidSystem>; + using VolumeVariables = GetPropType<TypeTag, Properties::VolumeVariables>; + using Indices = typename GetPropType<TypeTag, Properties::ModelTraits>::Indices; + using SolidSystem = GetPropType<TypeTag, Properties::SolidSystem>; + + enum + { + // primary variable indices + pressureIdx = Indices::pressureIdx, + switchIdx = Indices::switchIdx, + + // component indices + // TODO: using xwNaClIdx as privaridx works here, but + // looks like magic. Can this be done differently?? + xwNaClIdx = FluidSystem::NaClIdx, + precipNaClIdx = FluidSystem::numComponents, + + // Indices of the components + H2OIdx = FluidSystem::H2OIdx, + NaClIdx = FluidSystem::NaClIdx, + AirIdx = FluidSystem::AirIdx, + + // Indices of the phases + liquidPhaseIdx = FluidSystem::liquidPhaseIdx, + gasPhaseIdx = FluidSystem::gasPhaseIdx, + + // index of the solid phase + sPhaseIdx = SolidSystem::comp0Idx, + + + // Index of the primary component of G and L phase + conti0EqIdx = Indices::conti0EqIdx, //water component + conti1EqIdx = Indices::conti0EqIdx + 1, //air component + precipNaClEqIdx = Indices::conti0EqIdx + FluidSystem::numComponents, + energyEqIdx = Indices::energyEqIdx, + + // Phase State + bothPhases = Indices::bothPhases, + + // Grid and world dimension + dim = GridView::dimension, + dimWorld = GridView::dimensionworld, + }; + + using PrimaryVariables = GetPropType<TypeTag, Properties::PrimaryVariables>; + using NumEqVector = GetPropType<TypeTag, Properties::NumEqVector>; + using BoundaryTypes = GetPropType<TypeTag, Properties::BoundaryTypes>; + using GridVariables = GetPropType<TypeTag, Properties::GridVariables>; + using ElementFluxVariablesCache = typename GridVariables::GridFluxVariablesCache::LocalView; + using ElementVolumeVariables = typename GetPropType<TypeTag, Properties::GridVolumeVariables>::LocalView; + using Element = typename GridView::template Codim<0>::Entity; + using FVGridGeometry = GetPropType<TypeTag, Properties::FVGridGeometry>; + using SolutionVector = GetPropType<TypeTag, Properties::SolutionVector>; + using FVElementGeometry = typename GetPropType<TypeTag, Properties::FVGridGeometry>::LocalView; + using SubControlVolume = typename FVElementGeometry::SubControlVolume; + using GlobalPosition = typename SubControlVolume::GlobalPosition; + using NeumannFluxes = typename GET_PROP_TYPE(TypeTag, NumEqVector); + using SubControlVolumeFace = typename FVElementGeometry::SubControlVolumeFace; + using FluidState = typename GET_PROP_TYPE(TypeTag, FluidState); + +public: + SalinizationProblem(std::shared_ptr<const FVGridGeometry> fvGridGeometry) + : ParentType(fvGridGeometry) + { + //Fluidsystem + nTemperature_ = getParam<int>("FluidSystem.NTemperature"); + nPressure_ = getParam<int>("FluidSystem.NPressure"); + pressureLow_ = getParam<Scalar>("FluidSystem.PressureLow"); + pressureHigh_ = getParam<Scalar>("FluidSystem.PressureHigh"); + temperatureLow_ = getParam<Scalar>("FluidSystem.TemperatureLow"); + temperatureHigh_ = getParam<Scalar>("FluidSystem.TemperatureHigh"); + name_ = getParam<std::string>("Problem.Name"); + + //problem + name_ = getParam<std::string>("Problem.Name"); + temperature_ = getParam<Scalar>("Problem.Temperature"); + + //inital conditions + initPressure_ = getParam<Scalar>("Problem.InitialPressure"); + initGasSaturation_ = getParam<Scalar>("Problem.InitialGasSaturation"); + initSalinity_ = getParam<Scalar>("Problem.InitialSalinity"); + + unsigned int codim = GET_PROP_TYPE(TypeTag, FVGridGeometry)::discMethod == DiscretizationMethod::box ? dim : 0; + permeability_.resize(fvGridGeometry->gridView().size(codim)); + + FluidSystem::init(/*Tmin=*/temperatureLow_, + /*Tmax=*/temperatureHigh_, + /*nT=*/nTemperature_, + /*pmin=*/pressureLow_, + /*pmax=*/pressureHigh_, + /*np=*/nPressure_); + } + + /*! + * \brief The current time. + */ + void setTime( Scalar time ) + { + time_ = time; + } + + /*! + * \brief The time step size. + * + * This is used to calculate the source term. + */ + void setTimeStepSize( Scalar timeStepSize ) + { + timeStepSize_ = timeStepSize; + } + + /*! + * \name Problem parameters + */ + + /*! + * \brief The problem name. + * + * This is used as a prefix for files generated by the simulation. + */ + const std::string& name() const + { return name_; } + + /*! + * \brief Returns the temperature within the domain. + * + * This problem assumes a temperature of 10 degrees Celsius. + */ + Scalar temperature() const + { return temperature_; } + + + /*! + * \name Boundary conditions + */ + // \{ + + /*! + * \brief Specifies which kind of boundary condition should be + * used for which equation on a given boundary segment. + */ + BoundaryTypes boundaryTypesAtPos(const GlobalPosition &globalPos) const + { + BoundaryTypes bcTypes; + + // default to Neumann + bcTypes.setAllNeumann(); + + return bcTypes; + } + + /*! + * \brief Evaluates the boundary conditions for a Dirichlet boundary segment. + */ + PrimaryVariables dirichletAtPos(const GlobalPosition &globalPos) const + { + PrimaryVariables priVars(0.0); + priVars.setState(bothPhases); + + return priVars; + } + + + /*! + * \brief Evaluate the boundary conditions for a neumann + * boundary segment. + * + * This is the method for the case where the Neumann condition is + * potentially solution dependent + * + * \param element The finite element + * \param fvGeometry The finite-volume geometry + * \param elemVolVars All volume variables for the element + * \param elemFluxVarsCache Flux variables caches for all faces in stencil + * \param scvf The sub control volume face + * + * Negative values mean influx. + * E.g. for the mass balance that would be the mass flux in \f$ [ kg / (m^2 \cdot s)] \f$. + */ + NumEqVector neumann(const Element& element, + const FVElementGeometry& fvGeometry, + const ElementVolumeVariables& elemVolVars, + const ElementFluxVariablesCache& elemFluxVarsCache, + const SubControlVolumeFace& scvf) const + { + PrimaryVariables values(0.0); + + const auto& globalPos = scvf.ipGlobal(); + const auto& volVars = elemVolVars[scvf.insideScvIdx()]; + const Scalar hmax = this->fvGridGeometry().bBoxMax()[1]; + + static const Scalar temperatureRef = getParam<Scalar>("FreeFlow.RefTemperature"); + + + if(globalPos[1] > hmax - eps_) + { + // get free-flow properties: + static const Scalar moleFracRefH2O = getParam<Scalar>("FreeFlow.RefMoleFracH2O"); + static const Scalar boundaryLayerThickness = getParam<Scalar>("FreeFlow.BoundaryLayerThickness"); + static const Scalar massTransferCoefficient = getParam<Scalar>("FreeFlow.MassTransferCoefficient"); + + // get porous medium values: + Scalar moleFracH2OInside = volVars.moleFraction(gasPhaseIdx, H2OIdx); + Scalar referencePermeability_ = getParam<Scalar>("SpatialParams.referencePermeability", 2.23e-14); + + // calculate fluxes + // liquid phase + Scalar evaporationRateMole = 0; + if(moleFracH2OInside - moleFracRefH2O > 0) + { + evaporationRateMole = massTransferCoefficient + * volVars.diffusionCoefficient(gasPhaseIdx, H2OIdx) + * (moleFracH2OInside - moleFracRefH2O) + / boundaryLayerThickness + * volVars.molarDensity(gasPhaseIdx); + } + else + { + evaporationRateMole = massTransferCoefficient + * volVars.diffusionCoefficient(gasPhaseIdx, H2OIdx) + * (moleFracH2OInside - moleFracRefH2O) + / boundaryLayerThickness + * 1.2; + + } + + values[conti0EqIdx] = evaporationRateMole; + + // gas phase + // gas flows in + if (volVars.pressure(gasPhaseIdx) - 1e5 > 0) { + values[conti1EqIdx] = (volVars.pressure(gasPhaseIdx) - 1e5) + /(globalPos - fvGeometry.scv(scvf.insideScvIdx()).center()).two_norm() + *volVars.mobility(gasPhaseIdx) + *referencePermeability_ + *volVars.molarDensity(gasPhaseIdx) + *volVars.moleFraction(gasPhaseIdx, AirIdx); + } + //gas flows out + else { + values[conti1EqIdx] = (volVars.pressure(gasPhaseIdx) - 1e5) + /(globalPos - fvGeometry.scv(scvf.insideScvIdx()).center()).two_norm() + *volVars.mobility(gasPhaseIdx) + *referencePermeability_ + *volVars.molarDensity(gasPhaseIdx) * (1-moleFracRefH2O); + } + + + // energy fluxes + values[energyEqIdx] = FluidSystem::componentEnthalpy(volVars.fluidState(), gasPhaseIdx, H2OIdx) * values[conti0EqIdx] * FluidSystem::molarMass(H2OIdx); + + values[energyEqIdx] += FluidSystem::componentEnthalpy(volVars.fluidState(), gasPhaseIdx, AirIdx)* values[conti1EqIdx] * FluidSystem::molarMass(AirIdx); + + values[energyEqIdx] += FluidSystem::thermalConductivity(elemVolVars[scvf.insideScvIdx()].fluidState(), gasPhaseIdx) * (volVars.temperature() - temperatureRef)/boundaryLayerThickness; + + } + return values; + } + + + + + + + /*! + * \brief Evaluates the initial value for a control volume. + * + * \param globalPos The global position + * + * For this method, the \a values parameter stores primary + * variables. + */ + PrimaryVariables initialAtPos(const GlobalPosition& globalPos) const + { + PrimaryVariables priVars(0.0); + priVars.setState(bothPhases); + Scalar density = 1000.00; //FluidSystem::density(, liquidPhaseIdx); + + priVars[pressureIdx] = initPressure_ - density*9.81*globalPos[dimWorld-1]; + priVars[switchIdx] = initGasSaturation_; // Sg primary variable + priVars[xwNaClIdx] = massToMoleFrac_(initSalinity_); // mole fraction + priVars[precipNaClIdx] = 0.0; // [kg/m^3] + priVars[energyEqIdx] = temperature_; // [K] + + return priVars; + } + + /*! + * \name Volume terms + */ + // \{ + + /*! + * \brief Evaluates the source term for all phases within a given + * sub-controlvolume. + * + * This is the method for the case where the source term is + * potentially solution dependent and requires some quantities that + * are specific to the fully-implicit method. + * + * \param element The finite element + * \param fvGeometry The finite-volume geometry + * \param elemVolVars All volume variables for the element + * \param scv The subcontrolvolume + * + * For this method, the \a values parameter stores the conserved quantity rate + * generated or annihilated per volume unit. Positive values mean + * that the conserved quantity is created, negative ones mean that it vanishes. + * E.g. for the mass balance that would be a mass rate in \f$ [ kg / (m^3 \cdot s)] \f$. + */ + NumEqVector source(const Element &element, + const FVElementGeometry& fvGeometry, + const ElementVolumeVariables& elemVolVars, + const SubControlVolume &scv) const + { + NumEqVector source(0.0); + + const auto& volVars = elemVolVars[scv]; + + Scalar moleFracNaCl_wPhase = volVars.moleFraction(liquidPhaseIdx, NaClIdx); + Scalar massFracNaCl_Max_wPhase = this->spatialParams().solubilityLimit(); + Scalar moleFracNaCl_Max_wPhase = massToMoleFrac_(massFracNaCl_Max_wPhase); + Scalar saltPorosity = this->spatialParams().minimalPorosity(element, scv); + + // precipitation of amount of salt whic hexeeds the solubility limit + using std::abs; + Scalar precipSalt = volVars.porosity() * volVars.molarDensity(liquidPhaseIdx) + * volVars.saturation(liquidPhaseIdx) + * abs(moleFracNaCl_wPhase - moleFracNaCl_Max_wPhase); + if (moleFracNaCl_wPhase < moleFracNaCl_Max_wPhase) + precipSalt *= -1; + + // make sure we don't dissolve more salt than previously precipitated + if (precipSalt*timeStepSize_ + volVars.solidVolumeFraction(sPhaseIdx)* volVars.solidComponentMolarDensity(sPhaseIdx)< 0) + precipSalt = -volVars.solidVolumeFraction(sPhaseIdx)* volVars.solidComponentMolarDensity(sPhaseIdx)/timeStepSize_; + + // make sure there is still pore space available for precipitation + if (volVars.solidVolumeFraction(sPhaseIdx) >= this->spatialParams().referencePorosity(element, scv) - saltPorosity && precipSalt > 0) + precipSalt = 0; + + source[conti0EqIdx + NaClIdx] += -precipSalt; + source[precipNaClEqIdx] += precipSalt; + return source; + + } + + /*! + * \brief Adds additional VTK output data to the VTKWriter. + * + * Function is called by the output module on every write. + */ + + const std::vector<Scalar>& getPermeability() + { + return permeability_; + } + + void updateVtkOutput(const SolutionVector& curSol) + { + for (const auto& element : elements(this->fvGridGeometry().gridView())) + { + const auto elemSol = elementSolution(element, curSol, this->fvGridGeometry()); + + auto fvGeometry = localView(this->fvGridGeometry()); + fvGeometry.bindElement(element); + + for (auto&& scv : scvs(fvGeometry)) + { + VolumeVariables volVars; + volVars.update(elemSol, *this, element, scv); + const auto dofIdxGlobal = scv.dofIndex(); + permeability_[dofIdxGlobal] = volVars.permeability(); + } + } + } + + Scalar extrusionFactorAtPos(const GlobalPosition &globalPos) const + { + // As a default, i.e. if the user's problem does not overload + // any extrusion factor method, return 1.0 + return 0.054977871437821; + } + + + +private: + + /*! + * \brief Returns the molality of NaCl (mol NaCl / kg water) for a given mole fraction. + * + * \param XwNaCl The XwNaCl [kg NaCl / kg solution] + */ + static Scalar massToMoleFrac_(Scalar XwNaCl) + { + const Scalar Mw = 18.015e-3; //FluidSystem::molarMass(H2OIdx); /* molecular weight of water [kg/mol] */ //TODO use correct link to FluidSyswem later + const Scalar Ms = 58.44e-3; //FluidSystem::molarMass(NaClIdx); /* molecular weight of NaCl [kg/mol] */ + + const Scalar X_NaCl = XwNaCl; + /* XwNaCl: conversion from mass fraction to mol fraction */ + auto xwNaCl = -Mw * X_NaCl / ((Ms - Mw) * X_NaCl - Ms); + return xwNaCl; + } + + + std::string name_; + + Scalar initPressure_; + Scalar initGasSaturation_; + Scalar initSalinity_; + + Scalar temperature_; + + Scalar pressureLow_, pressureHigh_; + Scalar temperatureLow_, temperatureHigh_; + int nTemperature_; + int nPressure_; + + Scalar time_ = 0.0; + Scalar timeStepSize_ = 0.0; + static constexpr Scalar eps_ = 1e-6; + + std::vector<double> permeability_; + + Dumux::GnuplotInterface<double> gnuplot_; + Dumux::GnuplotInterface<double> gnuplot2_; + std::vector<double> x_; + std::vector<double> y_; + std::vector<double> y2_; + + +}; + +} // end namespace Dumux + +#endif diff --git a/test/porousmediumflow/2pncmin/implicit/nonisothermal/spatialparams.hh b/test/porousmediumflow/2pncmin/implicit/nonisothermal/spatialparams.hh new file mode 100644 index 0000000000..1a47d8bdd2 --- /dev/null +++ b/test/porousmediumflow/2pncmin/implicit/nonisothermal/spatialparams.hh @@ -0,0 +1,181 @@ +// -*- 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 3 of the License, or * + * (at your option) any later version. * + * * + * This program is distributed in the hope that it will be useful, * + * but WITHOUT ANY WARRANTY; without even the implied warranty of * + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the * + * GNU General Public License for more details. * + * * + * You should have received a copy of the GNU General Public License * + * along with this program. If not, see <http://www.gnu.org/licenses/>. * + *****************************************************************************/ +/*! + * \file + * \ingroup TwoPNCMinTests + * \brief Spatial parameters for the salinization problem, where evaporation + * from a porous medium saturated wit brine and air leads to precipitation of salt. + */ + +#ifndef DUMUX_SALINIZATION_SPATIAL_PARAMETERS_HH +#define DUMUX_SALINIZATION_SPATIAL_PARAMETERS_HH + +#include <dumux/io/gnuplotinterface.hh> +#include <dumux/io/plotmateriallaw.hh> +#include <dumux/material/spatialparams/fv.hh> +#include <dumux/material/fluidmatrixinteractions/2p/linearmaterial.hh> +#include <dumux/material/fluidmatrixinteractions/2p/regularizedvangenuchten.hh> +#include <dumux/material/fluidmatrixinteractions/2p/efftoabslaw.hh> +#include <dumux/material/fluidmatrixinteractions/porosityprecipitation.hh> +#include <dumux/material/fluidmatrixinteractions/permeabilitykozenycarman.hh> + +namespace Dumux { + +/*! + * \ingroup TwoPNCMinTests + * \brief Spatial parameters for the salinization problem, where evaporation + * from a porous medium saturated wit brine and air leads to precipitation of salt. + */ +template<class FVGridGeometry, class Scalar> +class SalinizationSpatialParams +: public FVSpatialParams<FVGridGeometry, Scalar, + SalinizationSpatialParams<FVGridGeometry, Scalar>> +{ + using GridView = typename FVGridGeometry::GridView; + using FVElementGeometry = typename FVGridGeometry::LocalView; + using SubControlVolume = typename FVElementGeometry::SubControlVolume; + using Element = typename GridView::template Codim<0>::Entity; + + using ParentType = FVSpatialParams<FVGridGeometry, Scalar, + SalinizationSpatialParams<FVGridGeometry, Scalar>>; + + using EffectiveLaw = RegularizedVanGenuchten<Scalar>; + + using GlobalPosition = typename SubControlVolume::GlobalPosition; + +public: + // type used for the permeability (i.e. tensor or scalar) + using PermeabilityType = Scalar; + //! Export the material law type used + using MaterialLaw = EffToAbsLaw<EffectiveLaw>; + using MaterialLawParams = typename MaterialLaw::Params; + + SalinizationSpatialParams(std::shared_ptr<const FVGridGeometry> fvGridGeometry) + : ParentType(fvGridGeometry) + { + solubilityLimit_ = getParam<Scalar>("SpatialParams.SolubilityLimit", 0.26); + referencePorosity_ = getParam<Scalar>("SpatialParams.referencePorosity", 0.11); + referencePermeability_ = getParam<Scalar>("SpatialParams.referencePermeability", 2.23e-14); + irreducibleLiqSat_ = getParam<Scalar>("SpatialParams.IrreducibleLiqSat", 0.2); + irreducibleGasSat_ = getParam<Scalar>("SpatialParams.IrreducibleGasSat", 1e-3); + vgAlpha_ = getParam<Scalar>("SpatialParams.VGAlpha", 1.5); + vgn_ = getParam<Scalar>("SpatialParams.VGn", 4.0); + + plotFluidMatrixInteractions_ = getParam<bool>("Output.PlotFluidMatrixInteractions"); + + //Van Genuchen parameters + // residual saturations + materialParams_.setSwr(irreducibleLiqSat_); + materialParams_.setSnr(irreducibleGasSat_); + + //Van Genuchen parameters + materialParams_.setVgAlpha(vgAlpha_ ); + materialParams_.setVgn(vgn_); + } + + /*! + * \brief Defines the minimum porosity \f$[-]\f$ distribution + * + * \param element The finite element + * \param scv The sub-control volume + */ + Scalar minimalPorosity(const Element& element, const SubControlVolume &scv) const + { return 1e-5; } + + /*! + * \brief Defines the volume fraction of the inert component + * + * \param globalPos The global position in the domain + * \param compIdx The index of the inert solid component + */ + template<class SolidSystem> + Scalar inertVolumeFractionAtPos(const GlobalPosition& globalPos, int compIdx) const + { return 1.0-referencePorosity_; } + + /*! + * \brief Defines the reference porosity \f$[-]\f$ distribution. + * + * This is the porosity of the porous medium without any of the + * considered solid phases. + * + * \param element The finite element + * \param scv The sub-control volume + */ + Scalar referencePorosity(const Element& element, const SubControlVolume &scv) const + { return referencePorosity_; } + + /*! 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 + * \param elemSol The element solution + * + * Solution dependent permeability function + */ + template<class ElementSolution> + PermeabilityType permeability(const Element& element, + const SubControlVolume& scv, + const ElementSolution& elemSol) const + { + auto priVars = evalSolution(element, element.geometry(), elemSol, scv.center(), /*ignoreState=*/true); + + Scalar sumPrecipitates = priVars[/*numComp*/3]; + + using std::max; + const auto poro = max(/*minPoro*/1e-5, referencePorosity_ - sumPrecipitates); + return permLaw_.evaluatePermeability(referencePermeability_, referencePorosity_, poro); + } + + // the solubility limit of NaCl + Scalar solubilityLimit() const + { return solubilityLimit_; } + + Scalar theta(const SubControlVolume &scv) const + { return 10.0; } + + // return the brooks-corey context depending on the position + const MaterialLawParams& materialLawParamsAtPos(const GlobalPosition& globalPos) const + { return materialParams_; } + + // define which phase is to be considered as the wetting phase + template<class FluidSystem> + int wettingPhaseAtPos(const GlobalPosition& globalPos) const + { return FluidSystem::H2OIdx; } + +private: + + MaterialLawParams materialParams_; + + PermeabilityKozenyCarman<PermeabilityType> permLaw_; + + Scalar solubilityLimit_; + Scalar referencePorosity_; + PermeabilityType referencePermeability_ = 0.0; + Scalar irreducibleLiqSat_; + Scalar irreducibleGasSat_; + Scalar vgAlpha_; + Scalar vgn_ ; + + bool plotFluidMatrixInteractions_; +}; + +} // end namespace Dumux + +#endif diff --git a/test/references/test_2pncminni_salinization-reference.vtu b/test/references/test_2pncminni_salinization-reference.vtu new file mode 100644 index 0000000000..1d14a543b1 --- /dev/null +++ b/test/references/test_2pncminni_salinization-reference.vtu @@ -0,0 +1,139 @@ +<?xml version="1.0"?> +<VTKFile type="UnstructuredGrid" version="0.1" byte_order="LittleEndian"> + <UnstructuredGrid> + <Piece NumberOfCells="10" NumberOfPoints="18"> + <PointData Scalars="S_liq" Vectors="velocity_liq (m/s)"> + <DataArray type="Float32" Name="S_liq" NumberOfComponents="1" format="ascii"> + 0.371972 0.371972 0.354829 0.354829 0.371972 0.354829 0.328148 0.328148 0.328148 0.315167 0.315167 0.315167 + 0.300425 0.300425 0.300425 0.283783 0.283783 0.283783 + </DataArray> + <DataArray type="Float32" Name="p_liq" NumberOfComponents="1" format="ascii"> + 92441.8 92441.8 92339.1 92339.1 92441.8 92339.1 92142.7 92142.7 92142.7 92022.1 92022.1 92022.1 + 91851.9 91851.9 91851.9 91583.7 91583.7 91583.7 + </DataArray> + <DataArray type="Float32" Name="rho_liq" NumberOfComponents="1" format="ascii"> + 1012.93 1012.93 1012.93 1012.93 1012.93 1012.93 1012.94 1012.94 1012.94 1013.29 1013.29 1013.29 + 1021.51 1021.51 1021.51 1200.29 1200.29 1200.29 + </DataArray> + <DataArray type="Float32" Name="mob_liq" NumberOfComponents="1" format="ascii"> + 6.3638 6.3638 4.25016 4.25016 6.3638 4.25016 1.94427 1.94427 1.94427 1.19814 1.19814 1.19814 + 0.594915 0.594915 0.594915 0.111125 0.111125 0.111125 + </DataArray> + <DataArray type="Float32" Name="S_gas" NumberOfComponents="1" format="ascii"> + 0.628028 0.628028 0.645171 0.645171 0.628028 0.645171 0.671852 0.671852 0.671852 0.684833 0.684833 0.684833 + 0.699575 0.699575 0.699575 0.716217 0.716217 0.716217 + </DataArray> + <DataArray type="Float32" Name="p_gas" NumberOfComponents="1" format="ascii"> + 100002 100002 100002 100002 100002 100002 100002 100002 100002 100002 100002 100002 + 100002 100002 100002 100001 100001 100001 + </DataArray> + <DataArray type="Float32" Name="rho_gas" NumberOfComponents="1" format="ascii"> + 1.21014 1.21014 1.21013 1.21013 1.21014 1.21013 1.21012 1.21012 1.21012 1.21012 1.21012 1.21012 + 1.21014 1.21014 1.21014 1.21073 1.21073 1.21073 + </DataArray> + <DataArray type="Float32" Name="mob_gas" NumberOfComponents="1" format="ascii"> + 39281.7 39281.7 41576.5 41576.5 39281.7 41576.5 45236.5 45236.5 45236.5 47150.2 47150.2 47150.2 + 49764.6 49764.6 49764.6 52753.5 52753.5 52753.5 + </DataArray> + <DataArray type="Float32" Name="pc" NumberOfComponents="1" format="ascii"> + 7560.19 7560.19 7662.75 7662.75 7560.19 7662.75 7859.09 7859.09 7859.09 7979.69 7979.69 7979.69 + 8149.9 8149.9 8149.9 8417.42 8417.42 8417.42 + </DataArray> + <DataArray type="Float32" Name="porosity" NumberOfComponents="1" format="ascii"> + 0.4 0.4 0.4 0.4 0.4 0.4 0.4 0.4 0.4 0.4 0.4 0.4 + 0.4 0.4 0.4 0.399824 0.399824 0.399824 + </DataArray> + <DataArray type="Float32" Name="x^H2O_liq" NumberOfComponents="1" format="ascii"> + 0.993731 0.993731 0.993731 0.993731 0.993731 0.993731 0.993726 0.993726 0.993726 0.993565 0.993565 0.993565 + 0.989756 0.989756 0.989756 0.902258 0.902258 0.902258 + </DataArray> + <DataArray type="Float32" Name="x^Air_liq" NumberOfComponents="1" format="ascii"> + 1.69669e-05 1.69669e-05 1.69666e-05 1.69666e-05 1.69669e-05 1.69666e-05 1.69657e-05 1.69657e-05 1.69657e-05 1.69654e-05 1.69654e-05 1.69654e-05 + 1.69661e-05 1.69661e-05 1.69661e-05 1.69884e-05 1.69884e-05 1.69884e-05 + </DataArray> + <DataArray type="Float32" Name="x^NaCl_liq" NumberOfComponents="1" format="ascii"> + 0.00625221 0.00625221 0.00625235 0.00625235 0.00625221 0.00625235 0.00625709 0.00625709 0.00625709 0.0064178 0.0064178 0.0064178 + 0.0102271 0.0102271 0.0102271 0.0977251 0.0977251 0.0977251 + </DataArray> + <DataArray type="Float32" Name="rhoMolar_liq" NumberOfComponents="1" format="ascii"> + 55447.9 55447.9 55447.9 55447.9 55447.9 55447.9 55447.8 55447.8 55447.8 55447.1 55447.1 55447.1 + 55430 55430 55430 54642.7 54642.7 54642.7 + </DataArray> + <DataArray type="Float32" Name="x^H2O_gas" NumberOfComponents="1" format="ascii"> + 0.0149431 0.0149431 0.0149438 0.0149438 0.0149431 0.0149438 0.014946 0.014946 0.014946 0.0149445 0.0149445 0.0149445 + 0.014888 0.014888 0.014888 0.0135726 0.0135726 0.0135726 + </DataArray> + <DataArray type="Float32" Name="x^Air_gas" NumberOfComponents="1" format="ascii"> + 0.985057 0.985057 0.985056 0.985056 0.985057 0.985056 0.985054 0.985054 0.985054 0.985056 0.985056 0.985056 + 0.985112 0.985112 0.985112 0.986427 0.986427 0.986427 + </DataArray> + <DataArray type="Float32" Name="x^NaCl_gas" NumberOfComponents="1" format="ascii"> + -0 -0 -0 -0 -0 -0 -0 -0 -0 -0 -0 -0 + -0 -0 -0 -0 -0 -0 + </DataArray> + <DataArray type="Float32" Name="rhoMolar_gas" NumberOfComponents="1" format="ascii"> + 42.0241 42.0241 42.024 42.024 42.0241 42.024 42.0236 42.0236 42.0236 42.0234 42.0234 42.0234 + 42.0233 42.0233 42.0233 42.0228 42.0228 42.0228 + </DataArray> + <DataArray type="Float32" Name="phase presence" NumberOfComponents="1" format="ascii"> + 3 3 3 3 3 3 3 3 3 3 3 3 + 3 3 3 3 3 3 + </DataArray> + <DataArray type="Float32" Name="precipitateVolumeFraction^NaCl" NumberOfComponents="1" format="ascii"> + 0 0 0 0 0 0 0 0 0 0 0 0 + 0 0 0 0.00017601 0.00017601 0.00017601 + </DataArray> + <DataArray type="Float32" Name="T" NumberOfComponents="1" format="ascii"> + 286.208 286.208 286.209 286.209 286.208 286.209 286.211 286.211 286.211 286.212 286.212 286.212 + 286.213 286.213 286.213 286.214 286.214 286.214 + </DataArray> + <DataArray type="Float32" Name="velocity_liq (m/s)" NumberOfComponents="3" format="ascii"> + -6.7602e-22 2.38612e-09 0 -3.79683e-22 2.38612e-09 0 -6.3085e-22 4.64661e-09 0 -3.23156e-22 4.64661e-09 0 + -8.3345e-23 2.38612e-09 0 -1.5462e-23 4.64661e-09 0 -3.42343e-22 8.41592e-09 0 -2.7727e-22 8.41592e-09 0 + -2.12196e-22 8.41592e-09 0 -4.95383e-22 1.05518e-08 0 -3.18852e-22 1.05518e-08 0 -1.42321e-22 1.05518e-08 0 + -1.73772e-22 1.1066e-08 0 -5.82074e-23 1.1066e-08 0 5.73568e-23 1.1066e-08 0 1.94852e-22 1.0953e-08 0 + 1.33006e-22 1.0953e-08 0 7.11605e-23 1.0953e-08 0 + </DataArray> + <DataArray type="Float32" Name="velocity_gas (m/s)" NumberOfComponents="3" format="ascii"> + -9.77477e-18 -2.47197e-09 0 -5.91631e-18 -2.47197e-09 0 -6.62494e-18 -4.83592e-09 0 -6.20143e-18 -4.83592e-09 0 + -2.05785e-18 -2.47197e-09 0 -5.77792e-18 -4.83592e-09 0 -5.75993e-18 -7.66282e-09 0 -7.17523e-18 -7.66282e-09 0 + -8.59053e-18 -7.66282e-09 0 -6.91496e-18 2.53119e-08 0 -1.30386e-17 2.53119e-08 0 -1.91623e-17 2.53119e-08 0 + 5.96753e-18 1.0712e-06 0 -8.72983e-18 1.0712e-06 0 -2.34272e-17 1.0712e-06 0 -3.41432e-19 2.08366e-06 0 + -2.79445e-18 2.08366e-06 0 -5.24746e-18 2.08366e-06 0 + </DataArray> + <DataArray type="Float32" Name="Permeability" NumberOfComponents="1" format="ascii"> + 1e-13 1e-13 1e-13 1e-13 1e-13 1e-13 1e-13 1e-13 1e-13 1e-13 1e-13 1e-13 + 9.99523e-14 9.99523e-14 9.99523e-14 9.98571e-14 9.98571e-14 9.98571e-14 + </DataArray> + </PointData> + <CellData Scalars="process rank"> + <DataArray type="Float32" Name="process rank" NumberOfComponents="1" format="ascii"> + 0 0 0 0 0 0 0 0 0 0 + </DataArray> + </CellData> + <Points> + <DataArray type="Float32" Name="Coordinates" NumberOfComponents="3" format="ascii"> + 0 0 0 0.01 0 0 0 0.0075 0 0.01 0.0075 0 + 0.02 0 0 0.02 0.0075 0 0 0.015 0 0.01 0.015 0 + 0.02 0.015 0 0 0.016978 0 0.01 0.016978 0 0.02 0.016978 0 + 0 0.0186264 0 0.01 0.0186264 0 0.02 0.0186264 0 0 0.02 0 + 0.01 0.02 0 0.02 0.02 0 + </DataArray> + </Points> + <Cells> + <DataArray type="Int32" Name="connectivity" NumberOfComponents="1" format="ascii"> + 0 1 3 2 1 4 5 3 2 3 7 6 + 3 5 8 7 6 7 10 9 7 8 11 10 + 9 10 13 12 10 11 14 13 12 13 16 15 + 13 14 17 16 + </DataArray> + <DataArray type="Int32" Name="offsets" NumberOfComponents="1" format="ascii"> + 4 8 12 16 20 24 28 32 36 40 + </DataArray> + <DataArray type="UInt8" Name="types" NumberOfComponents="1" format="ascii"> + 9 9 9 9 9 9 9 9 9 9 + </DataArray> + </Cells> + </Piece> + </UnstructuredGrid> +</VTKFile> -- GitLab