Dear Dumux community, I'm experiencing some difficulty with the attached simulation.
I borrowed it from 2p2c implicit examples and performed minimal modifications which to me should not create any problem.
It seems I am wrong but I cannot figure out where! May I ask you help to detect anything wrong, please? Kind regards, Lorenzo
// -*- 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 TwoPTwoCTests * \brief Definition of the spatial parameters for the water-polymer-oil problem. */ #ifndef DUMUX_WATER_POLYMER_OIL_SPATIAL_PARAMS_HH #define DUMUX_WATER_POLYMER_OIL_SPATIAL_PARAMS_HH #include <dumux/io/gnuplotinterface.hh> #include <dumux/io/ploteffectivediffusivitymodel.hh> #include <dumux/io/plotmateriallaw.hh> #include <dumux/io/plotthermalconductivitymodel.hh> #include <dumux/porousmediumflow/properties.hh> #include <dumux/material/spatialparams/fv.hh> #include <dumux/material/fluidmatrixinteractions/2p/regularizedbrookscorey.hh> #include <dumux/material/fluidmatrixinteractions/2p/efftoabslaw.hh> namespace Dumux { /*! * \ingroup TwoPTwoCModel * \brief Definition of the spatial parameters for the water-air problem. */ template<class GridGeometry, class Scalar> class WaterPolymerOilSpatialParams : public FVSpatialParams<GridGeometry, Scalar, WaterPolymerOilSpatialParams<GridGeometry, Scalar>> { using GridView = typename GridGeometry::GridView; using FVElementGeometry = typename GridGeometry::LocalView; using SubControlVolume = typename FVElementGeometry::SubControlVolume; using Element = typename GridView::template Codim<0>::Entity; using ParentType = FVSpatialParams<GridGeometry, Scalar, WaterPolymerOilSpatialParams<GridGeometry, Scalar>>; static constexpr int dimWorld = GridView::dimensionworld; using EffectiveLaw = RegularizedBrooksCorey<Scalar>; using GlobalPosition = typename Element::Geometry::GlobalCoordinate; public: //! Export the type used for the permeability using PermeabilityType = Scalar; //! Export the type used for the material law using MaterialLaw = EffToAbsLaw<EffectiveLaw>; using MaterialLawParams = typename MaterialLaw::Params; WaterPolymerOilSpatialParams(std::shared_ptr<const GridGeometry> gridGeometry) : ParentType(gridGeometry) { layerBottom_ = 22.0; // intrinsic permeabilities fineK_ = 1e-13; coarseK_ = 1e-12; // porosities finePorosity_ = 0.3; coarsePorosity_ = 0.3; // residual saturations fineMaterialParams_.setSwr(0.2); fineMaterialParams_.setSnr(0.0); coarseMaterialParams_.setSwr(0.2); coarseMaterialParams_.setSnr(0.0); // parameters for the Brooks-Corey law fineMaterialParams_.setPe(1e4); coarseMaterialParams_.setPe(1e4); fineMaterialParams_.setLambda(2.0); coarseMaterialParams_.setLambda(2.0); plotFluidMatrixInteractions_ = getParam<bool>("Output.PlotFluidMatrixInteractions"); } /*! * \brief This is called from the problem and creates a gnuplot output * of e.g the pc-Sw curve */ void plotMaterialLaw() { PlotMaterialLaw<Scalar, MaterialLaw> plotMaterialLaw; GnuplotInterface<Scalar> gnuplot(plotFluidMatrixInteractions_); gnuplot.setOpenPlotWindow(plotFluidMatrixInteractions_); plotMaterialLaw.addpcswcurve(gnuplot, fineMaterialParams_, 0.2, 1.0, "fine", "w lp"); plotMaterialLaw.addpcswcurve(gnuplot, coarseMaterialParams_, 0.2, 1.0, "coarse", "w l"); gnuplot.setOption("set xrange [0:1]"); gnuplot.setOption("set label \"residual\\nsaturation\" at 0.1,100000 center"); gnuplot.plot("pc-Sw"); gnuplot.resetAll(); plotMaterialLaw.addkrcurves(gnuplot, fineMaterialParams_, 0.2, 1.0, "fine"); plotMaterialLaw.addkrcurves(gnuplot, coarseMaterialParams_, 0.2, 1.0, "coarse"); gnuplot.plot("kr"); } /*! * \brief Applies the intrinsic permeability tensor to a pressure * potential gradient. * * \param globalPos The global position */ Scalar permeabilityAtPos(const GlobalPosition& globalPos) const { if (isFineMaterial_(globalPos)) return fineK_; return coarseK_; } /*! * \brief Defines the porosity \f$[-]\f$ of the spatial parameters * * \param globalPos The global position */ Scalar porosityAtPos(const GlobalPosition& globalPos) const { if (isFineMaterial_(globalPos)) return finePorosity_; else return coarsePorosity_; } /*! * \brief Returns 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 (isFineMaterial_(globalPos)) return fineMaterialParams_; else return coarseMaterialParams_; } /*! * \brief Function for defining which phase is to be considered as the wetting phase. * * \param globalPos The position of the center of the element * \return The wetting phase index */ template<class FluidSystem> int wettingPhaseAtPos(const GlobalPosition& globalPos) const { return FluidSystem::H2OIdx; } private: bool isFineMaterial_(const GlobalPosition &globalPos) const { return globalPos[dimWorld-1] > layerBottom_; } Scalar fineK_; Scalar coarseK_; Scalar layerBottom_; Scalar finePorosity_; Scalar coarsePorosity_; MaterialLawParams fineMaterialParams_; MaterialLawParams coarseMaterialParams_; bool plotFluidMatrixInteractions_; }; } // end namespace Dumux #endif
// -*- 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 TwoPTwoCTests * \brief (Non)-isothermal gas injection problem where a gas (e.g. air) * is injected into a fully water saturated medium. */ #ifndef DUMUX_WATER_POLYMER_OIL_PROBLEM_HH #define DUMUX_WATER_POLYMER_OIL_PROBLEM_HH #include <dune/grid/yaspgrid.hh> #include <dumux/discretization/cctpfa.hh> #include <dumux/discretization/box.hh> #include <dumux/discretization/method.hh> #include <dumux/material/solidstates/inertsolidstate.hh> #include <dumux/material/solidsystems/inertsolidphase.hh> #include <dumux/material/components/constant.hh> #include <dumux/material/components/n2.hh> #include <dumux/material/components/trichloroethene.hh> #include <dumux/material/components/simpleh2o.hh> #include <dumux/material/fluidsystems/h2oairxylene.hh> #include <dumux/material/fluidsystems/h2oairmesitylene.hh> #include <dumux/material/fluidsystems/h2oair.hh> #include <dumux/material/fluidsystems/h2on2.hh> #include <dumux/material/fluidstates/compositional.hh> #include <dumux/material/fluidsystems/1pliquid.hh> #include <dumux/material/fluidsystems/2pimmiscible.hh> #include <dumux/porousmediumflow/2p2c/model.hh> #include <dumux/porousmediumflow/problem.hh> #include <dumux/io/gnuplotinterface.hh> #include "spatialparams.hh" #ifndef GRIDTYPE #define GRIDTYPE Dune::ALUGrid<2, 2, Dune::simplex, Dune::conforming>; #endif #ifndef ENABLECACHING #define ENABLECACHING 0 #endif namespace Dumux { template <class TypeTag> class WaterPolymerOilProblem; namespace Properties { // Create new type tags namespace TTag { // uncomment for non-isothermal simulations and also temperature and energy fields //struct WaterPolymerOil { using InheritsFrom = std::tuple<TwoPTwoCNI>; }; struct WaterPolymerOil { using InheritsFrom = std::tuple<TwoPTwoC>; }; struct WaterPolymerOilBox { using InheritsFrom = std::tuple<WaterPolymerOil, BoxModel>; }; struct WaterPolymerOilCCTpfa { using InheritsFrom = std::tuple<WaterPolymerOil, CCTpfaModel>; }; } // end namespace TTag // Set the grid type //#if HAVE_UG //template<class TypeTag> //struct Grid<TypeTag, TTag::WaterPolymerOil> { using type = Dune::UGGrid<2>; }; //#else template<class TypeTag> //struct Grid<TypeTag, TTag::WaterPolymerOil> { using type = Dune::YaspGrid<1>; }; struct Grid<TypeTag, TTag::WaterPolymerOil> { using type = Dune::YaspGrid<2>; }; //#endif //struct Grid<TypeTag, TTag::WaterPolymerOil> { using type = GRIDTYPE; }; // Set the problem property template<class TypeTag> struct Problem<TypeTag, TTag::WaterPolymerOil> { using type = WaterPolymerOilProblem<TypeTag>; }; // Set the wetting phase TODO: change with the appropriate fluidsystem template<class TypeTag> struct FluidSystem<TypeTag, TTag::WaterPolymerOil> { //using type = FluidSystems::H2ON2<GetPropType<TypeTag, Properties::Scalar>>; using type = FluidSystems::H2ON2<GetPropType<TypeTag, Properties::Scalar>, FluidSystems::H2ON2DefaultPolicy</*fastButSimplifiedRelations=*/true>>; //using type = FluidSystems::H2OAirMesitylene<GetPropType<TypeTag, Properties::Scalar>>; //using type = FluidSystems::H2OAir<Scalar, // Components::TabulatedComponent<Components::H2O<Scalar>>, // FluidSystems::H2OAirDefaultPolicy</*fastButSimplifiedRelations=*/true>, // true /*useKelvinEquation*/>; }; // Set the spatial parameters template<class TypeTag> struct SpatialParams<TypeTag, TTag::WaterPolymerOil> { using GridGeometry = GetPropType<TypeTag, Properties::GridGeometry>; using Scalar = GetPropType<TypeTag, Properties::Scalar>; using type = WaterPolymerOilSpatialParams<GridGeometry, Scalar>; }; // decide which type to use for floating values (double / quad) template<class TypeTag> struct Scalar<TypeTag, TTag::WaterPolymerOil> { using type = double; }; template<class TypeTag> struct Formulation<TypeTag, TTag::WaterPolymerOil> { public: static const TwoPFormulation value = TwoPFormulation::p0s1; }; // Define whether mole(true) or mass (false) fractions are used template<class TypeTag> struct UseMoles<TypeTag, TTag::WaterPolymerOil> { static constexpr bool value = true; }; } // end namespace Dumux /*! * \ingroup TwoPTwoCModel TODO: fix description * \brief Non-isothermal gas injection problem where a gas (e.g. air) * is injected into a fully water saturated medium. * * This problem uses the \ref TwoPTwoCModel and \ref NIModel model. * * To run the simulation execute the following line in shell: * <tt>./test_box2p2cni</tt> or * <tt>./test_cc2p2cni</tt> * */ template <class TypeTag > class WaterPolymerOilProblem : public PorousMediumFlowProblem<TypeTag> { using ParentType = PorousMediumFlowProblem<TypeTag>; using Scalar = GetPropType<TypeTag, Properties::Scalar>; using GridView = GetPropType<TypeTag, Properties::GridView>; using FluidSystem = GetPropType<TypeTag, Properties::FluidSystem>; using ModelTraits = GetPropType<TypeTag, Properties::ModelTraits>; using Indices = typename ModelTraits::Indices; // primary variable indices enum { pressureIdx = Indices::pressureIdx, switchIdx = Indices::switchIdx //temperatureIdx = Indices::temperatureIdx, //energyEqIdx = Indices::energyEqIdx }; // equation indices enum { contiH2OEqIdx = Indices::conti0EqIdx + FluidSystem::H2OIdx, //!< Index of the mass conservation equation for the water component contiN2EqIdx = Indices::conti0EqIdx + FluidSystem::N2Idx }; // phase presence enum { wPhaseOnly = Indices::firstPhaseOnly, bothPhases = Indices::bothPhases }; // component index enum { N2Idx = FluidSystem::N2Idx }; using PrimaryVariables = GetPropType<TypeTag, Properties::PrimaryVariables>; using NumEqVector = GetPropType<TypeTag, Properties::NumEqVector>; using BoundaryTypes = GetPropType<TypeTag, Properties::BoundaryTypes>; using Element = typename GridView::template Codim<0>::Entity; using GlobalPosition = typename Element::Geometry::GlobalCoordinate; using FVElementGeometry = typename GetPropType<TypeTag, Properties::GridGeometry>::LocalView; using GridGeometry = GetPropType<TypeTag, Properties::GridGeometry>; using SubControlVolumeFace = typename FVElementGeometry::SubControlVolumeFace; using ElementVolumeVariables = typename GetPropType<TypeTag, Properties::GridVolumeVariables>::LocalView; //! Property that defines whether mole or mass fractions are used static constexpr bool useMoles = ModelTraits::useMoles(); //! Property that defines the discretizatin method static const bool isBox = GetPropType<TypeTag, Properties::GridGeometry>::discMethod == DiscretizationMethod::box; //! Property that defines the dimension of the problem static const int dimWorld = GridView::dimensionworld; //static constexpr int dim = GridView::dimension; //static constexpr int dimWorld = GridView::dimensionworld; //static constexpr bool isBox = GridGeometry::discMethod == DiscretizationMethod::box; //enum { dofCodim = isBox ? dim : 0 }; public: WaterPolymerOilProblem(std::shared_ptr<const GridGeometry> gridGeometry) : ParentType(gridGeometry) { // nTemperature_ = getParam<int>("Problem.NTemperature"); // nPressure_ = getParam<int>("Problem.NPressure"); // pressureLow_ = getParam<Scalar>("Problem.PressureLow"); // pressureHigh_ = getParam<Scalar>("Problem.PressureHigh"); // temperatureLow_ = getParam<Scalar>("Problem.TemperatureLow"); // temperatureHigh_ = getParam<Scalar>("Problem.TemperatureHigh"); // temperature_ = getParam<Scalar>("Problem.InitialTemperature"); // depthBOR_ = getParam<Scalar>("Problem.DepthBOR"); name_ = getParam<std::string>("Problem.Name"); // // // initialize the tables of the fluid system // FluidSystem::init(/*Tmin=*/temperatureLow_, // /*Tmax=*/temperatureHigh_, // /*nT=*/nTemperature_, // /*pmin=*/pressureLow_, // /*pmax=*/pressureHigh_, // /*np=*/nPressure_); // // not used // maxDepth_ = 1000.0; // [m] FluidSystem::init(); name_ = getParam<std::string>("Problem.Name"); // not used //useDirichlet_ = name_.find("buoyancy") != std::string::npos; //stating in the console whether mole or mass fractions are used if(useMoles) std::cout << "The problem uses mole-fractions" << std::endl; else std::cout << "The problem uses mass-fractions" << std::endl; this->spatialParams().plotMaterialLaw(); // in case this BC is used ... //InjRate_ = getParam<Scalar>("Problem.InjectionRate"); //[m/s] } /*! * \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 [K]. * * This problem assumes a temperature of 20 degrees Celsius. */ Scalar temperature() const { return 273.15 + 20; } // in [K] // \} /*! * \name Boundary conditions */ // \{ /*! * \brief Specifies which kind of boundary condition should be * used for which equation on a given boundary segment. * * \param globalPos The position for which the bc type should be evaluated */ BoundaryTypes boundaryTypesAtPos(const GlobalPosition &globalPos) const { BoundaryTypes bcTypes; // if(globalPos[0] > 40 - eps_ || globalPos[0] < eps_) // bcTypes.setAllDirichlet(); // else // bcTypes.setAllNeumann(); // // if (useDirichlet_) // { // if (isInjectionArea_(globalPos)) // bcTypes.setAllDirichlet(); // } if(globalPos[0] < eps_ || globalPos[0] > this->gridGeometry().bBoxMax()[0] - eps_) { bcTypes.setAllDirichlet(); } else { bcTypes.setAllNeumann(); } return bcTypes; } /*! * \brief Evaluates the boundary conditions for a Dirichlet boundary segment. * * \param globalPos The position for which the Dirichlet condition should be evaluated */ PrimaryVariables dirichletAtPos(const GlobalPosition &globalPos) const { PrimaryVariables priVars = initial_(globalPos); // if (useDirichlet_) // { // if (isInjectionArea_(globalPos)) // { // priVars.setState(Indices::bothPhases); // priVars[switchIdx] = 0.2; // return priVars; // } // } // condition for the polymer mole fraction at left boundary if (globalPos[0] < eps_ ) { //values[saturationOILIdx] = 0.25; // inject water //values[pressureH2OIdx] = 34e6; //values[PolymerIdx] = 0.01; //values[pressureIdx] = 34e6; // TODO: this may change with time to allow // water+polymer+water slug scenario priVars.setState(Indices::bothPhases); priVars[switchIdx] = 0.1; priVars[pressureIdx] = 0.3e5; return priVars; } } /*! * \brief Evaluates the boundary conditions for a Neumann boundary segment. * * \param globalPos The position for which the Neumann condition should be evaluated * \return the mole/mass flux of each component. Negative values mean influx. * * The units must be according to using either mole or mass fractions (mole/(m^2*s) or kg/(m^2*s)). */ NumEqVector neumannAtPos(const GlobalPosition &globalPos) const { NumEqVector values(0.0); // we inject pure gasous nitrogen at the initial condition temperature and pressure from the bottom (negative values mean injection) //if (isInjectionArea_(globalPos)) //{ // values[contiN2EqIdx] = useMoles ? -1e-3/FluidSystem::molarMass(N2Idx) : -1e-3; // kg/(m^2*s) or mole/(m^2*s) // const auto initialValues = initial_(globalPos); // const auto& mParams = this->spatialParams().materialLawParamsAtPos(globalPos); // using MaterialLaw = typename ParentType::SpatialParams::MaterialLaw; // const auto pn = initialValues[pressureIdx] + MaterialLaw::endPointPc(mParams); // //const auto t = initialValues[temperatureIdx]; // // note: energy equation is always formulated in terms of mass specific quantities, not per mole // //values[energyEqIdx] = -1e-3*Components::N2<Scalar>::gasEnthalpy(t, pn); //} return values; } // \} /*! * \name Volume terms */ // \{ /*! * \brief Evaluates the initial value for a control volume. * * \param globalPos The position for which the initial condition should be evaluated * * For this method, the \a values parameter stores primary * variables. */ PrimaryVariables initialAtPos(const GlobalPosition &globalPos) const { auto priVars = initial_(globalPos); // initially there is a heated lens in the domain //if (globalPos[0] > 20 - eps_ && globalPos[0] < 30 + eps_ && globalPos[1] < 30 + eps_) // priVars[temperatureIdx] = 380.0; return priVars; } /*! * \brief Evaluates the source term for all phases within a given * sub-control volume. * * For this method, the \a priVars parameter stores the rate mass * of a component is generated or annihilated per volume * unit. Positive values mean that mass is created, negative ones * mean that it vanishes. * * The units must be according to either using mole or mass fractions (mole/(m^3*s) or kg/(m^3*s)). */ NumEqVector sourceAtPos(const GlobalPosition &globalPos) const { return NumEqVector(0.0); } private: // internal method for the initial condition (reused for the // dirichlet conditions!) PrimaryVariables initial_(const GlobalPosition &globalPos) const { const auto xMax = this->gridGeometry().bBoxMax()[0]; PrimaryVariables priVars(0.0); priVars.setState(wPhaseOnly); //priVars.setState(bothPhases); //Scalar densityW = 1000.0; //Scalar densityW = FluidSystem::H2O::liquidDensity(temperature_, 1e5); //Scalar pl = 1e5 - densityW*this->spatialParams().gravity(globalPos)[1]*(depthBOR_ - globalPos[1]); //Scalar moleFracLiquidN2 = pl*0.95/BinaryCoeff::H2O_N2::henry(temperature_); //Scalar moleFracLiquidH2O = 1.0 - moleFracLiquidN2; //Scalar meanM = // FluidSystem::molarMass(H2OIdx)*moleFracLiquidH2O + // FluidSystem::molarMass(N2Idx)*moleFracLiquidN2; //if(useMoles) //{ // //mole-fraction formulation // priVars[switchIdx] = moleFracLiquidN2; //} //else //{ // //mass fraction formulation // Scalar massFracLiquidN2 = moleFracLiquidN2*FluidSystem::molarMass(N2Idx)/meanM; // priVars[switchIdx] = massFracLiquidN2; //} //priVars[pressureIdx] = 1e5 + (maxDepth_ - globalPos[1])*densityW*9.81; //priVars[pressureIdx] = 1e5; priVars[switchIdx] = 0.99; // should be full of oil (?) //priVars[temperatureIdx] = initialTemperatureProfile_(globalPos); if (globalPos[0] > xMax - eps_ ) priVars[pressureIdx] = -0.3e5; //if (globalPos[0] < 0.1 ) // priVars[switchIdx] = 0.01; return priVars; } // not used //Scalar initialTemperatureProfile_(const GlobalPosition &globalPos) const //{ return 283.0 + (maxDepth_ - globalPos[1])*0.03; } // not used //bool isInjectionArea_(const GlobalPosition& globalPos) const //{ // return globalPos[0] > 14.8 - eps_ && globalPos[0] < 25.2 + eps_ && globalPos[1] < eps_; //} Scalar maxDepth_; static constexpr Scalar eps_ = 1e-6; std::string name_; bool useDirichlet_; }; } // end namespace Dumux #endif
[TimeLoop] DtInitial = 1 # [s] TEnd = 432000 # [s] MaxTimeStepSize = 3600 # [s] [Grid] LowerLeft = 0 0 UpperRight = 10 10 Cells = 100 100 [Problem] Name = waterpolymeroil [SpatialParams] RandomField = false Porosity = 0.17 Permeability = 3.62E-14 [Gstat] ControlFile = control.gstat InputFile = gstatInput.txt OutputFilePrefix = permeability [Output] PlotFluidMatrixInteractions = false [LinearSolver] ResidualReduction = 1e-10 [Newton] MaxRelativeShift = 1e-13 EnableShiftCriterion = true # (relative shift convergence criterion) MinSteps = 2 MaxSteps = 18 TargetSteps = 10 # set the "desirable" number of Newton iterations of a time step RetryTimeStepReductionFactor = 5.000e-01 MaxTimeStepDivisions = 10 #EnableChop = true # chop for better convergence [Component] SolidDensity = 2700 SolidThermalConductivity = 2.8 SolidHeatCapacity = 790 Density = 2246 # Inert solid component density (kg/m3) AdsorptionGamma1 = 1000 AdsorptionGamma2 = 0 AdsorptionN = 1 adsMult = 5000 [Adaptive] RefineAtDirichletBC = 0 RefineAtFluxBC = 1 MinLevel = 0 MaxLevel = 2 CoarsenTolerance = 1e-4 RefineTolerance = 1e-4
// -*- 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 TwoPTwoCTests * \brief Test for the two-phase two-component CC model. */ #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 <dumux/common/properties.hh> #include <dumux/common/parameters.hh> #include <dumux/common/valgrind.hh> #include <dumux/common/dumuxmessage.hh> #include <dumux/linear/amgbackend.hh> #include <dumux/linear/seqsolverbackend.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> // the problem definitions #include "problem.hh" 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); // 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 GridGeometry = GetPropType<TypeTag, Properties::GridGeometry>; auto gridGeometry = std::make_shared<GridGeometry>(leafGridView); gridGeometry->update(); // the problem (initial and boundary conditions) using Problem = GetPropType<TypeTag, Properties::Problem>; auto problem = std::make_shared<Problem>(gridGeometry); // 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(gridGeometry->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>; const auto fileName = getParam<std::string>("Restart.File"); const auto pvName = createPVNameFunction<IOFields, PrimaryVariables, ModelTraits, FluidSystem>(); loadSolution(x, fileName, pvName, *gridGeometry); } else problem->applyInitialSolution(x); auto xOld = x; // the grid variables using GridVariables = GetPropType<TypeTag, Properties::GridVariables>; auto gridVariables = std::make_shared<GridVariables>(problem, gridGeometry); gridVariables->init(x); // intialize 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 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, gridGeometry, gridVariables, timeLoop, xOld); // the linear solver using LinearSolver = ILU0BiCGSTABBackend; auto linearSolver = std::make_shared<LinearSolver>(); //using LinearSolver = AMGBackend<TypeTag>; //auto linearSolver = std::make_shared<LinearSolver>(leafGridView, gridGeometry->dofMapper()); // the non-linear solver using NewtonSolver = NewtonSolver<Assembler, LinearSolver>; NewtonSolver nonLinearSolver(assembler, linearSolver); // time loop timeLoop->start(); do { // 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(); // report statistics of this time step timeLoop->reportTimeStep(); // set new dt as suggested by the newton solver timeLoop->setTimeStepSize(nonLinearSolver.suggestTimeStepSize(timeLoop->timeStepSize())); // write vtk output vtkWriter.write(timeLoop->time()); } 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; }
add_input_file_links(FILES params.input) dumux_add_test(NAME test_2p2c_waterpolymeroil_box LABELS porousmediumflow 2p2c SOURCES main.cc TIMEOUT 1500 COMPILE_DEFINITIONS TYPETAG=WaterPolymerOilBox ENABLECACHING=0 CMD_ARGS --script fuzzy --command "${CMAKE_CURRENT_BINARY_DIR}/test_2p2c_waterpolymeroil_box params.input -Problem.Name test_2p2c_waterpolymeroil_box") dumux_add_test(NAME test_2p2c_waterpolymeroil_tpfa LABELS porousmediumflow 2p2c SOURCES main.cc TIMEOUT 1500 COMPILE_DEFINITIONS TYPETAG=WaterPolymerOilCCTpfa ENABLECACHING=0 CMD_ARGS --script fuzzy --command "${CMAKE_CURRENT_BINARY_DIR}/test_2p2c_waterpolymeroil_tpfa params.input -Problem.Name test_2p2c_waterpolymeroil_tpfa")
_______________________________________________ Dumux mailing list Dumux@listserv.uni-stuttgart.de https://listserv.uni-stuttgart.de/mailman/listinfo/dumux