From b56e9025d99b3cac32b352525a3c740510f8591c Mon Sep 17 00:00:00 2001 From: Holger Class <holger.class@iws.uni-stuttgart.de> Date: Fri, 8 Jul 2011 12:49:49 +0000 Subject: [PATCH] git-svn-id: svn://svn.iws.uni-stuttgart.de/DUMUX/dumux/trunk@6164 2fb0f335-1f38-0410-981e-8018bf24f1b0 --- test/boxmodels/2p2cni/infiltrationproblem.hh | 405 +++++++++++++++++++ 1 file changed, 405 insertions(+) create mode 100644 test/boxmodels/2p2cni/infiltrationproblem.hh diff --git a/test/boxmodels/2p2cni/infiltrationproblem.hh b/test/boxmodels/2p2cni/infiltrationproblem.hh new file mode 100644 index 0000000000..53a8afad7f --- /dev/null +++ b/test/boxmodels/2p2cni/infiltrationproblem.hh @@ -0,0 +1,405 @@ +/***************************************************************************** + * Copyright (C) 2011 by Holger Class * + * Institute of Hydraulic Engineering * + * University of Stuttgart, Germany * + * email: <givenname>.<name>@iws.uni-stuttgart.de * + * * + * This program is free software: you can redistribute it and/or modify * + * it under the terms of the GNU General Public License as published by * + * the Free Software Foundation, either version 2 of the License, or * + * (at your option) any later version. * + * * + * This program is distributed in the hope that it will be useful, * + * but WITHOUT ANY WARRANTY; without even the implied warranty of * + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the * + * GNU General Public License for more details. * + * * + * You should have received a copy of the GNU General Public License * + * along with this program. If not, see <http://www.gnu.org/licenses/>. * + *****************************************************************************/ +/*! + * \file + * + * \brief Non-isothermal gas injection problem where a gas (e.g. air) + * is injected into a fully water saturated medium. + */ +#ifndef DUMUX_INFILTRATIONPROBLEM_HH +#define DUMUX_INFILTRATIONPROBLEM_HH + +#include <dune/grid/io/file/dgfparser/dgfug.hh> +#include <dune/grid/io/file/dgfparser/dgfs.hh> +#include <dune/grid/io/file/dgfparser/dgfyasp.hh> + +#include <dumux/material/fluidsystems/holle_h20_air_mesitylene_system.hh> + +#include <dumux/boxmodels/holle3p3c/holle3p3cmodel.hh> + +#include "infiltrationspatialparameters.hh" + +#define ISOTHERMAL 0 + +namespace Dumux +{ +template <class TypeTag> +class InfiltrationProblem; + +namespace Properties +{ +NEW_TYPE_TAG(InfiltrationProblem, INHERITS_FROM(BoxHolleThreePThreeC)); + +// Set the grid type +SET_PROP(InfiltrationProblem, Grid) +{ + typedef Dune::YaspGrid<2> type; +}; + +#if HAVE_DUNE_PDELAB +SET_PROP(InfiltrationProblem, LocalFEMSpace) +{ + typedef typename GET_PROP_TYPE(TypeTag, PTAG(Scalar)) Scalar; + typedef typename GET_PROP_TYPE(TypeTag, PTAG(GridView)) GridView; + enum{dim = GridView::dimension}; + +public: + typedef Dune::PDELab::Q1LocalFiniteElementMap<Scalar,Scalar,dim> type; // for cubes +// typedef Dune::PDELab::P1LocalFiniteElementMap<Scalar,Scalar,dim> type; // for simplices +}; +#endif // HAVE_DUNE_PDELAB + +// Set the problem property +SET_PROP(InfiltrationProblem, Problem) +{ + typedef Dumux::InfiltrationProblem<TypeTag> type; +}; + +// Set the wetting phase +SET_TYPE_PROP(InfiltrationProblem, FluidSystem, Dumux::Holle_H2O_Air_Mesitylene_System<TypeTag>); + +// Set the spatial parameters +SET_TYPE_PROP(InfiltrationProblem, + SpatialParameters, + Dumux::InfiltrationSpatialParameters<TypeTag>); + +// Enable gravity +SET_BOOL_PROP(InfiltrationProblem, EnableGravity, true); + +// Use forward differences instead of central differences +SET_INT_PROP(InfiltrationProblem, NumericDifferenceMethod, 0); + +// Write newton convergence +SET_BOOL_PROP(InfiltrationProblem, NewtonWriteConvergence, true); + +//! Set the formulation +SET_INT_PROP(InfiltrationProblem, Formulation, HolleThreePThreeCFormulation::pgSwSn); +} + + +/*! + * \ingroup HolleTHreePThreeCBoxModel + * + * */ +template <class TypeTag > +class InfiltrationProblem : public HolleThreePThreeCProblem<TypeTag> +{ + typedef typename GET_PROP_TYPE(TypeTag, PTAG(Scalar)) Scalar; + typedef typename GET_PROP_TYPE(TypeTag, PTAG(GridView)) GridView; + typedef typename GET_PROP_TYPE(TypeTag, PTAG(Model)) Model; + typedef typename GridView::Grid Grid; + + typedef InfiltrationProblem<TypeTag> ThisType; + typedef HolleThreePThreeCProblem<TypeTag> ParentType; + + typedef typename GET_PROP_TYPE(TypeTag, PTAG(MaterialLaw)) MaterialLaw; + typedef typename GET_PROP_TYPE(TypeTag, PTAG(MaterialLawParams)) MaterialLawParams; + + + // copy some indices for convenience + typedef typename GET_PROP_TYPE(TypeTag, PTAG(HolleThreePThreeCIndices)) Indices; + enum { + numEq = GET_PROP_VALUE(TypeTag, PTAG(NumEq)), + + pressureIdx = Indices::pressureIdx, + switch1Idx = Indices::switch1Idx, + switch2Idx = Indices::switch2Idx, +// #if !ISOTHERMAL +// temperatureIdx = Indices::temperatureIdx, +// energyEqIdx = Indices::energyEqIdx, +// #endif + + // Phase State + threePhases = Indices::threePhases, + wPhaseOnly = Indices::wPhaseOnly, + gnPhaseOnly = Indices::gnPhaseOnly, + wnPhaseOnly = Indices::wnPhaseOnly, + gPhaseOnly = Indices::gPhaseOnly, + wgPhaseOnly = Indices::wgPhaseOnly, + + // Grid and world dimension + dim = GridView::dimension, + dimWorld = GridView::dimensionworld, + }; + + + typedef typename GET_PROP_TYPE(TypeTag, PTAG(PrimaryVariables)) PrimaryVariables; + typedef typename GET_PROP_TYPE(TypeTag, PTAG(BoundaryTypes)) BoundaryTypes; + typedef typename GET_PROP_TYPE(TypeTag, PTAG(TimeManager)) TimeManager; + + typedef typename GridView::template Codim<0>::Entity Element; + typedef typename GridView::template Codim<dim>::Entity Vertex; + typedef typename GridView::Intersection Intersection; + + typedef typename GET_PROP_TYPE(TypeTag, PTAG(FVElementGeometry)) FVElementGeometry; + typedef typename GET_PROP_TYPE(TypeTag, PTAG(FluidSystem)) FluidSystem; + + typedef Dune::FieldVector<Scalar, dim> LocalPosition; + typedef Dune::FieldVector<Scalar, dimWorld> GlobalPosition; + +public: + /*! + * \brief The constructor + * + * \param timeManager The time manager + * \param gridView The grid view + */ + InfiltrationProblem(TimeManager &timeManager, const GridView &gridView) + : ParentType(timeManager, gridView) + { + FluidSystem::init(); + } + + /*! + * \name Problem parameters + */ + // \{ + + /*! + * \brief The problem name. + * + * This is used as a prefix for files generated by the simulation. + */ + const char *name() const + { return "infiltration"; } + + /*! + * \brief Returns the temperature within the domain. + * + * \param element The element + * \param fvElemGeom The finite-volume geometry in the box scheme + * \param scvIdx The local vertex index (SCV index) + * + * This problem assumes a temperature of 10 degrees Celsius. + */ + Scalar temperature(const Element &element, + const FVElementGeometry &fvElemGeom, + int scvIdx) const + { + return (273.15 + 10.0); // -> Temperatur 10°C + }; + + // \} + + /*! + * \name Boundary conditions + */ + // \{ + + /*! + * \brief Specifies which kind of boundary condition should be + * used for which equation on a given boundary segment. + * + * \param values The boundary types for the conservation equations + * \param vertex The vertex for which the boundary type is set + */ + void boundaryTypes(BoundaryTypes &values, const Vertex &vertex) const + { + const GlobalPosition globalPos = vertex.geometry().center(); + + if(globalPos[0] > 125. - eps_) + values.setAllDirichlet(); + else if(globalPos[0] < eps_) + values.setAllDirichlet(); + else + values.setAllNeumann(); + +//#if !ISOTHERMAL +// values.setDirichlet(temperatureIdx, energyEqIdx); +//#endif + } + + /*! + * \brief Evaluate the boundary conditions for a dirichlet + * boundary segment. + * + * \param values The dirichlet values for the primary variables + * \param vertex The vertex for which the boundary type is set + * + * For this method, the \a values parameter stores primary variables. + */ + void dirichlet(PrimaryVariables &values, const Vertex &vertex) const + { + const GlobalPosition globalPos = vertex.geometry().center(); + + Scalar y = globalPos[1]; + Scalar Sw, Swr=0.12, Sgr=0.03; + + if(y >5. ) + { + Scalar pc = 9.81 * 1000.0 * (y - 5); /*capillary Eq.*/ + if (pc < 0.0) pc = 0.0; + + Sw = invertPCGW_(pc, + this->spatialParameters().materialLawParams()); + if (Sw < Swr) Sw = Swr; + if (Sw > 1.-Sgr) Sw = 1.-Sgr; + + values[pressureIdx] = 1e5 ; + values[switch1Idx] = Sw; + values[switch2Idx] = 0.001; + }else { + values[pressureIdx] = 1e5 + 9.81 * 1000.0 * (5 - y); + values[switch1Idx] = 1.-Sgr; + values[switch2Idx] = 0.001; + } + + //initial_(values, globalPos, element); + //const MaterialLawParams& materialParams = this->spatialParameters().materialLawParams();; + //MaterialLaw::pCGW(materialParams, 1.0); + } + + /*! + * \brief Evaluate the boundary conditions for a neumann + * boundary segment. + * + * \param values The neumann values for the conservation equations + * \param element The finite element + * \param fvElemGeom The finite-volume geometry in the box scheme + * \param is The intersection between element and boundary + * \param scvIdx The local vertex index + * \param boundaryFaceIdx The index of the boundary face + * + * For this method, the \a values parameter stores the mass flux + * in normal direction of each phase. Negative values mean influx. + */ + using ParentType::neumann; + void neumann(PrimaryVariables &values, + const Element &element, + const FVElementGeometry &fvElemGeom, + const Intersection &is, + int scvIdx, + int boundaryFaceIdx) const + { + const GlobalPosition &globalPos = element.geometry().corner(scvIdx); + values = 0; + + // negative values for injection + if ((globalPos[0] <= 80.+eps_) && (globalPos[0] >= 75.+eps_) && (globalPos[1] >= 10.-eps_)) + { + values[Indices::contiWEqIdx] = -0.0; + values[Indices::contiCEqIdx] = -1.2e-4; + values[Indices::contiAEqIdx] = -0.0; + } + } + + // \} + + /*! + * \name Volume terms + */ + // \{ + + /*! + * \brief Evaluate the initial value for a control volume. + * + * \param values The initial values for the primary variables + * \param element The finite element + * \param fvElemGeom The finite-volume geometry in the box scheme + * \param scvIdx The local vertex index + * + * For this method, the \a values parameter stores primary + * variables. + */ + void initial(PrimaryVariables &values, + const Element &element, + const FVElementGeometry &fvElemGeom, + int scvIdx) const + { + const GlobalPosition &globalPos = element.geometry().corner(scvIdx); + + initial_(values, globalPos, element); + } + + /*! + * \brief Return the initial phase state inside a control volume. + * + * \param vert The vertex + * \param globalIdx The index of the global vertex + * \param globalPos The global position + */ + int initialPhasePresence(const Vertex &vert, + int &globalIdx, + const GlobalPosition &globalPos) const + { + return threePhases; + } + +private: + // internal method for the initial condition (reused for the + // dirichlet conditions!) + void initial_(PrimaryVariables &values, + const GlobalPosition &globalPos, const Element &element) const + { + Scalar y = globalPos[1]; + Scalar Sw, Swr=0.12, Sgr=0.03; + + if(y >5. ) + { + Scalar pc = 9.81 * 1000.0 * (y - 5); /*capillary Eq.*/ + if (pc < 0.0) pc = 0.0; + + Sw = invertPCGW_(pc, + this->spatialParameters().materialLawParams()); + if (Sw < Swr) Sw = Swr; + if (Sw > 1.-Sgr) Sw = 1.-Sgr; + + values[pressureIdx] = 1e5 ; + values[switch1Idx] = Sw; + values[switch2Idx] = 0.001; + }else { + values[pressureIdx] = 1e5 + 9.81 * 1000.0 * (5 - y); + values[switch1Idx] = 1.-Sgr; + values[switch2Idx] = 0.001; + } + } + + static Scalar invertPCGW_(Scalar pcIn, const MaterialLawParams &pcParams) + { + Scalar lower,upper; + int k; + int maxIt = 50; + Scalar bisLimit = 1.; + Scalar Sw, pcGW; + lower=0.0; upper=1.0; + for (k=1; k<=25; k++) + { + Sw = 0.5*(upper+lower); + pcGW = MaterialLaw::pCGW(pcParams, Sw); + Scalar delta = pcGW-pcIn; + if (delta<0.) delta*=-1.; + if (delta<bisLimit) + { + return(Sw); + } + if (k==maxIt) { + return(Sw); + } + if (pcGW>pcIn) lower=Sw; + else upper=Sw; + } + return(Sw); + } + + static const Scalar eps_ = 1e-6; +}; +} //end namespace + +#endif -- GitLab