mirror of
https://github.com/OPM/opm-simulators.git
synced 2025-01-12 01:11:55 -06:00
changed: ewoms/models/richards -> opm/models/richards
This commit is contained in:
parent
f558f5d98b
commit
88a5e1db06
@ -28,7 +28,7 @@
|
||||
#ifndef EWOMS_RICHARDS_LENS_PROBLEM_HH
|
||||
#define EWOMS_RICHARDS_LENS_PROBLEM_HH
|
||||
|
||||
#include <ewoms/models/richards/richardsmodel.hh>
|
||||
#include <opm/models/richards/richardsmodel.hh>
|
||||
|
||||
#include <opm/material/components/SimpleH2O.hpp>
|
||||
#include <opm/material/fluidsystems/LiquidPhase.hpp>
|
||||
|
165
opm/models/richards/richardsboundaryratevector.hh
Normal file
165
opm/models/richards/richardsboundaryratevector.hh
Normal file
@ -0,0 +1,165 @@
|
||||
// -*- mode: C++; tab-width: 4; indent-tabs-mode: nil; c-basic-offset: 4 -*-
|
||||
// vi: set et ts=4 sw=4 sts=4:
|
||||
/*
|
||||
This file is part of the Open Porous Media project (OPM).
|
||||
|
||||
OPM 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.
|
||||
|
||||
OPM 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 OPM. If not, see <http://www.gnu.org/licenses/>.
|
||||
|
||||
Consult the COPYING file in the top-level source directory of this
|
||||
module for the precise wording of the license and the list of
|
||||
copyright holders.
|
||||
*/
|
||||
/*!
|
||||
* \file
|
||||
*
|
||||
* \copydoc Opm::RichardsBoundaryRateVector
|
||||
*/
|
||||
#ifndef EWOMS_RICHARDS_BOUNDARY_RATE_VECTOR_HH
|
||||
#define EWOMS_RICHARDS_BOUNDARY_RATE_VECTOR_HH
|
||||
|
||||
#include <opm/material/common/Valgrind.hpp>
|
||||
#include <opm/material/constraintsolvers/NcpFlash.hpp>
|
||||
|
||||
#include "richardsintensivequantities.hh"
|
||||
|
||||
namespace Opm {
|
||||
|
||||
/*!
|
||||
* \ingroup RichardsModel
|
||||
*
|
||||
* \brief Implements a boundary vector for the fully implicit Richards model.
|
||||
*/
|
||||
template <class TypeTag>
|
||||
class RichardsBoundaryRateVector : public GET_PROP_TYPE(TypeTag, RateVector)
|
||||
{
|
||||
typedef typename GET_PROP_TYPE(TypeTag, RateVector) ParentType;
|
||||
typedef typename GET_PROP_TYPE(TypeTag, ExtensiveQuantities) ExtensiveQuantities;
|
||||
typedef typename GET_PROP_TYPE(TypeTag, FluidSystem) FluidSystem;
|
||||
typedef typename GET_PROP_TYPE(TypeTag, Scalar) Scalar;
|
||||
typedef typename GET_PROP_TYPE(TypeTag, Evaluation) Evaluation;
|
||||
typedef typename GET_PROP_TYPE(TypeTag, Indices) Indices;
|
||||
|
||||
enum { numEq = GET_PROP_VALUE(TypeTag, NumEq) };
|
||||
enum { contiEqIdx = Indices::contiEqIdx };
|
||||
enum { liquidPhaseIdx = GET_PROP_VALUE(TypeTag, LiquidPhaseIndex) };
|
||||
|
||||
typedef Opm::MathToolbox<Evaluation> Toolbox;
|
||||
|
||||
public:
|
||||
RichardsBoundaryRateVector() : ParentType()
|
||||
{}
|
||||
|
||||
/*!
|
||||
* \copydoc
|
||||
* ImmiscibleBoundaryRateVector::ImmiscibleBoundaryRateVector(Scalar)
|
||||
*/
|
||||
RichardsBoundaryRateVector(const Evaluation& value)
|
||||
: ParentType(value)
|
||||
{}
|
||||
|
||||
/*!
|
||||
* \copydoc ImmiscibleBoundaryRateVector::ImmiscibleBoundaryRateVector(const
|
||||
* ImmiscibleBoundaryRateVector& )
|
||||
*/
|
||||
RichardsBoundaryRateVector(const RichardsBoundaryRateVector& value) = default;
|
||||
RichardsBoundaryRateVector& operator=(const RichardsBoundaryRateVector& value) = default;
|
||||
|
||||
/*!
|
||||
* \copydoc ImmiscibleBoundaryRateVector::setFreeFlow
|
||||
*/
|
||||
template <class Context, class FluidState>
|
||||
void setFreeFlow(const Context& context, unsigned bfIdx, unsigned timeIdx, const FluidState& fluidState)
|
||||
{
|
||||
ExtensiveQuantities extQuants;
|
||||
extQuants.updateBoundary(context, bfIdx, timeIdx, fluidState);
|
||||
const auto& insideIntQuants = context.intensiveQuantities(bfIdx, timeIdx);
|
||||
unsigned focusDofIdx = context.focusDofIndex();
|
||||
unsigned interiorDofIdx = context.interiorScvIndex(bfIdx, timeIdx);
|
||||
|
||||
////////
|
||||
// advective fluxes of all components in all phases
|
||||
////////
|
||||
(*this) = Evaluation(0.0);
|
||||
|
||||
unsigned phaseIdx = liquidPhaseIdx;
|
||||
Evaluation density;
|
||||
if (fluidState.pressure(phaseIdx) > insideIntQuants.fluidState().pressure(phaseIdx)) {
|
||||
if (focusDofIdx == interiorDofIdx)
|
||||
density = fluidState.density(phaseIdx);
|
||||
else
|
||||
density = Opm::getValue(fluidState.density(phaseIdx));
|
||||
}
|
||||
else if (focusDofIdx == interiorDofIdx)
|
||||
density = insideIntQuants.fluidState().density(phaseIdx);
|
||||
else
|
||||
density = Opm::getValue(insideIntQuants.fluidState().density(phaseIdx));
|
||||
|
||||
// add advective flux of current component in current
|
||||
// phase
|
||||
(*this)[contiEqIdx] += extQuants.volumeFlux(phaseIdx) * density;
|
||||
|
||||
#ifndef NDEBUG
|
||||
for (unsigned i = 0; i < numEq; ++i) {
|
||||
Opm::Valgrind::CheckDefined((*this)[i]);
|
||||
}
|
||||
Opm::Valgrind::CheckDefined(*this);
|
||||
#endif
|
||||
}
|
||||
|
||||
/*!
|
||||
* \copydoc ImmiscibleBoundaryRateVector::setInFlow
|
||||
*/
|
||||
template <class Context, class FluidState>
|
||||
void setInFlow(const Context& context,
|
||||
unsigned bfIdx,
|
||||
unsigned timeIdx,
|
||||
const FluidState& fluidState)
|
||||
{
|
||||
this->setFreeFlow(context, bfIdx, timeIdx, fluidState);
|
||||
|
||||
// we only allow fluxes in the direction opposite to the outer unit normal
|
||||
for (unsigned eqIdx = 0; eqIdx < numEq; ++eqIdx) {
|
||||
Evaluation& val = this->operator[](eqIdx);
|
||||
val = Toolbox::min(0.0, val);
|
||||
}
|
||||
}
|
||||
|
||||
/*!
|
||||
* \copydoc ImmiscibleBoundaryRateVector::setOutFlow
|
||||
*/
|
||||
template <class Context, class FluidState>
|
||||
void setOutFlow(const Context& context,
|
||||
unsigned bfIdx,
|
||||
unsigned timeIdx,
|
||||
const FluidState& fluidState)
|
||||
{
|
||||
this->setFreeFlow(context, bfIdx, timeIdx, fluidState);
|
||||
|
||||
// we only allow fluxes in the same direction as the outer unit normal
|
||||
for (unsigned eqIdx = 0; eqIdx < numEq; ++eqIdx) {
|
||||
Evaluation& val = this->operator[](eqIdx);
|
||||
val = Toolbox::max(0.0, val);
|
||||
}
|
||||
}
|
||||
|
||||
/*!
|
||||
* \copydoc ImmiscibleBoundaryRateVector::setNoFlow
|
||||
*/
|
||||
void setNoFlow()
|
||||
{ (*this) = Evaluation(0.0); }
|
||||
};
|
||||
|
||||
} // namespace Opm
|
||||
|
||||
#endif
|
52
opm/models/richards/richardsextensivequantities.hh
Normal file
52
opm/models/richards/richardsextensivequantities.hh
Normal file
@ -0,0 +1,52 @@
|
||||
// -*- mode: C++; tab-width: 4; indent-tabs-mode: nil; c-basic-offset: 4 -*-
|
||||
// vi: set et ts=4 sw=4 sts=4:
|
||||
/*
|
||||
This file is part of the Open Porous Media project (OPM).
|
||||
|
||||
OPM 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.
|
||||
|
||||
OPM 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 OPM. If not, see <http://www.gnu.org/licenses/>.
|
||||
|
||||
Consult the COPYING file in the top-level source directory of this
|
||||
module for the precise wording of the license and the list of
|
||||
copyright holders.
|
||||
*/
|
||||
/*!
|
||||
* \file
|
||||
*
|
||||
* \copydoc Opm::RichardsExtensiveQuantities
|
||||
*/
|
||||
#ifndef EWOMS_RICHARDS_EXTENSIVE_QUANTITIES_HH
|
||||
#define EWOMS_RICHARDS_EXTENSIVE_QUANTITIES_HH
|
||||
|
||||
#include "richardsproperties.hh"
|
||||
|
||||
#include <opm/models/common/multiphasebaseextensivequantities.hh>
|
||||
|
||||
namespace Opm {
|
||||
|
||||
/*!
|
||||
* \ingroup RichardsModel
|
||||
* \ingroup ExtensiveQuantities
|
||||
*
|
||||
* \brief Calculates and stores the data which is required to
|
||||
* calculate the flux of fluid over a face of a finite volume.
|
||||
*/
|
||||
template <class TypeTag>
|
||||
class RichardsExtensiveQuantities
|
||||
: public MultiPhaseBaseExtensiveQuantities<TypeTag>
|
||||
{
|
||||
};
|
||||
|
||||
} // namespace Opm
|
||||
|
||||
#endif
|
52
opm/models/richards/richardsindices.hh
Normal file
52
opm/models/richards/richardsindices.hh
Normal file
@ -0,0 +1,52 @@
|
||||
// -*- mode: C++; tab-width: 4; indent-tabs-mode: nil; c-basic-offset: 4 -*-
|
||||
// vi: set et ts=4 sw=4 sts=4:
|
||||
/*
|
||||
This file is part of the Open Porous Media project (OPM).
|
||||
|
||||
OPM 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.
|
||||
|
||||
OPM 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 OPM. If not, see <http://www.gnu.org/licenses/>.
|
||||
|
||||
Consult the COPYING file in the top-level source directory of this
|
||||
module for the precise wording of the license and the list of
|
||||
copyright holders.
|
||||
*/
|
||||
/*!
|
||||
* \file
|
||||
*
|
||||
* \copydoc Opm::RichardsIndices
|
||||
*/
|
||||
#ifndef EWOMS_RICHARDS_INDICES_HH
|
||||
#define EWOMS_RICHARDS_INDICES_HH
|
||||
|
||||
namespace Opm {
|
||||
|
||||
/*!
|
||||
* \ingroup RichardsModel
|
||||
* \brief Indices for the primary variables/conservation equations of the
|
||||
* Richards model.
|
||||
*/
|
||||
struct RichardsIndices
|
||||
{
|
||||
//! Primary variable index for the wetting phase pressure
|
||||
static const int pressureWIdx = 0;
|
||||
|
||||
//! Equation index for the mass conservation of the wetting phase
|
||||
static const int contiEqIdx = 0;
|
||||
|
||||
//! The number of equations
|
||||
static const int numEq = 1;
|
||||
};
|
||||
|
||||
} // namespace Opm
|
||||
|
||||
#endif
|
199
opm/models/richards/richardsintensivequantities.hh
Normal file
199
opm/models/richards/richardsintensivequantities.hh
Normal file
@ -0,0 +1,199 @@
|
||||
// -*- mode: C++; tab-width: 4; indent-tabs-mode: nil; c-basic-offset: 4 -*-
|
||||
// vi: set et ts=4 sw=4 sts=4:
|
||||
/*
|
||||
This file is part of the Open Porous Media project (OPM).
|
||||
|
||||
OPM 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.
|
||||
|
||||
OPM 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 OPM. If not, see <http://www.gnu.org/licenses/>.
|
||||
|
||||
Consult the COPYING file in the top-level source directory of this
|
||||
module for the precise wording of the license and the list of
|
||||
copyright holders.
|
||||
*/
|
||||
/*!
|
||||
* \file
|
||||
*
|
||||
* \copydoc Opm::RichardsIntensiveQuantities
|
||||
*/
|
||||
#ifndef EWOMS_RICHARDS_INTENSIVE_QUANTITIES_HH
|
||||
#define EWOMS_RICHARDS_INTENSIVE_QUANTITIES_HH
|
||||
|
||||
#include "richardsproperties.hh"
|
||||
|
||||
#include <opm/material/fluidstates/ImmiscibleFluidState.hpp>
|
||||
|
||||
#include <dune/common/fvector.hh>
|
||||
#include <dune/common/fmatrix.hh>
|
||||
|
||||
namespace Opm {
|
||||
|
||||
/*!
|
||||
* \ingroup RichardsModel
|
||||
* \ingroup IntensiveQuantities
|
||||
*
|
||||
* \brief Intensive quantities required by the Richards model.
|
||||
*/
|
||||
template <class TypeTag>
|
||||
class RichardsIntensiveQuantities
|
||||
: public GET_PROP_TYPE(TypeTag, DiscIntensiveQuantities)
|
||||
, public GET_PROP_TYPE(TypeTag, FluxModule)::FluxIntensiveQuantities
|
||||
{
|
||||
typedef typename GET_PROP_TYPE(TypeTag, DiscIntensiveQuantities) ParentType;
|
||||
typedef typename GET_PROP_TYPE(TypeTag, Scalar) Scalar;
|
||||
typedef typename GET_PROP_TYPE(TypeTag, Evaluation) Evaluation;
|
||||
typedef typename GET_PROP_TYPE(TypeTag, FluidSystem) FluidSystem;
|
||||
typedef typename GET_PROP_TYPE(TypeTag, MaterialLaw) MaterialLaw;
|
||||
typedef typename GET_PROP_TYPE(TypeTag, ElementContext) ElementContext;
|
||||
typedef typename GET_PROP_TYPE(TypeTag, GridView) GridView;
|
||||
typedef typename GET_PROP_TYPE(TypeTag, FluxModule) FluxModule;
|
||||
|
||||
typedef typename GET_PROP_TYPE(TypeTag, Indices) Indices;
|
||||
enum { pressureWIdx = Indices::pressureWIdx };
|
||||
enum { numPhases = FluidSystem::numPhases };
|
||||
enum { liquidPhaseIdx = GET_PROP_VALUE(TypeTag, LiquidPhaseIndex) };
|
||||
enum { gasPhaseIdx = GET_PROP_VALUE(TypeTag, GasPhaseIndex) };
|
||||
enum { dimWorld = GridView::dimensionworld };
|
||||
|
||||
typedef typename FluxModule::FluxIntensiveQuantities FluxIntensiveQuantities;
|
||||
typedef Dune::FieldMatrix<Scalar, dimWorld, dimWorld> DimMatrix;
|
||||
typedef Dune::FieldVector<Scalar, numPhases> ScalarPhaseVector;
|
||||
typedef Dune::FieldVector<Evaluation, numPhases> PhaseVector;
|
||||
typedef Opm::MathToolbox<Evaluation> Toolbox;
|
||||
|
||||
public:
|
||||
//! The type returned by the fluidState() method
|
||||
typedef Opm::ImmiscibleFluidState<Evaluation, FluidSystem> FluidState;
|
||||
|
||||
RichardsIntensiveQuantities()
|
||||
{}
|
||||
|
||||
RichardsIntensiveQuantities(const RichardsIntensiveQuantities& other) = default;
|
||||
|
||||
RichardsIntensiveQuantities& operator=(const RichardsIntensiveQuantities& other) = default;
|
||||
|
||||
/*!
|
||||
* \copydoc IntensiveQuantities::update
|
||||
*/
|
||||
void update(const ElementContext& elemCtx, unsigned dofIdx, unsigned timeIdx)
|
||||
{
|
||||
ParentType::update(elemCtx, dofIdx, timeIdx);
|
||||
|
||||
const auto& T = elemCtx.problem().temperature(elemCtx, dofIdx, timeIdx);
|
||||
fluidState_.setTemperature(T);
|
||||
|
||||
// material law parameters
|
||||
const auto& problem = elemCtx.problem();
|
||||
const typename MaterialLaw::Params& materialParams =
|
||||
problem.materialLawParams(elemCtx, dofIdx, timeIdx);
|
||||
const auto& priVars = elemCtx.primaryVars(dofIdx, timeIdx);
|
||||
|
||||
/////////
|
||||
// calculate the pressures
|
||||
/////////
|
||||
|
||||
// first, we have to find the minimum capillary pressure (i.e. Sw = 0)
|
||||
fluidState_.setSaturation(liquidPhaseIdx, 1.0);
|
||||
fluidState_.setSaturation(gasPhaseIdx, 0.0);
|
||||
ScalarPhaseVector pC;
|
||||
MaterialLaw::capillaryPressures(pC, materialParams, fluidState_);
|
||||
|
||||
// non-wetting pressure can be larger than the
|
||||
// reference pressure if the medium is fully
|
||||
// saturated by the wetting phase
|
||||
const Evaluation& pW = priVars.makeEvaluation(pressureWIdx, timeIdx);
|
||||
Evaluation pN =
|
||||
Toolbox::max(elemCtx.problem().referencePressure(elemCtx, dofIdx, /*timeIdx=*/0),
|
||||
pW + (pC[gasPhaseIdx] - pC[liquidPhaseIdx]));
|
||||
|
||||
/////////
|
||||
// calculate the saturations
|
||||
/////////
|
||||
fluidState_.setPressure(liquidPhaseIdx, pW);
|
||||
fluidState_.setPressure(gasPhaseIdx, pN);
|
||||
|
||||
PhaseVector sat;
|
||||
MaterialLaw::saturations(sat, materialParams, fluidState_);
|
||||
fluidState_.setSaturation(liquidPhaseIdx, sat[liquidPhaseIdx]);
|
||||
fluidState_.setSaturation(gasPhaseIdx, sat[gasPhaseIdx]);
|
||||
|
||||
typename FluidSystem::template ParameterCache<Evaluation> paramCache;
|
||||
paramCache.updateAll(fluidState_);
|
||||
|
||||
// compute and set the wetting phase viscosity
|
||||
const Evaluation& mu = FluidSystem::viscosity(fluidState_, paramCache, liquidPhaseIdx);
|
||||
fluidState_.setViscosity(liquidPhaseIdx, mu);
|
||||
fluidState_.setViscosity(gasPhaseIdx, 1e-20);
|
||||
|
||||
// compute and set the wetting phase density
|
||||
const Evaluation& rho = FluidSystem::density(fluidState_, paramCache, liquidPhaseIdx);
|
||||
fluidState_.setDensity(liquidPhaseIdx, rho);
|
||||
fluidState_.setDensity(gasPhaseIdx, 1e-20);
|
||||
|
||||
// relperms
|
||||
MaterialLaw::relativePermeabilities(relativePermeability_, materialParams, fluidState_);
|
||||
|
||||
// mobilities
|
||||
for (unsigned phaseIdx = 0; phaseIdx < numPhases; ++phaseIdx)
|
||||
mobility_[phaseIdx] = relativePermeability_[phaseIdx]/fluidState_.viscosity(phaseIdx);
|
||||
|
||||
// porosity
|
||||
porosity_ = problem.porosity(elemCtx, dofIdx, timeIdx);
|
||||
|
||||
// intrinsic permeability
|
||||
intrinsicPerm_ = problem.intrinsicPermeability(elemCtx, dofIdx, timeIdx);
|
||||
|
||||
// update the quantities specific for the velocity model
|
||||
FluxIntensiveQuantities::update_(elemCtx, dofIdx, timeIdx);
|
||||
}
|
||||
|
||||
/*!
|
||||
* \copydoc ImmiscibleIntensiveQuantities::fluidState
|
||||
*/
|
||||
const FluidState& fluidState() const
|
||||
{ return fluidState_; }
|
||||
|
||||
/*!
|
||||
* \copydoc ImmiscibleIntensiveQuantities::porosity
|
||||
*/
|
||||
const Evaluation& porosity() const
|
||||
{ return porosity_; }
|
||||
|
||||
/*!
|
||||
* \copydoc ImmiscibleIntensiveQuantities::intrinsicPermeability
|
||||
*/
|
||||
const DimMatrix& intrinsicPermeability() const
|
||||
{ return intrinsicPerm_; }
|
||||
|
||||
/*!
|
||||
* \copydoc ImmiscibleIntensiveQuantities::relativePermeability
|
||||
*/
|
||||
const Evaluation& relativePermeability(unsigned phaseIdx) const
|
||||
{ return relativePermeability_[phaseIdx]; }
|
||||
|
||||
/*!
|
||||
* \copydoc ImmiscibleIntensiveQuantities::mobility
|
||||
*/
|
||||
const Evaluation& mobility(unsigned phaseIdx) const
|
||||
{ return mobility_[phaseIdx]; }
|
||||
|
||||
private:
|
||||
FluidState fluidState_;
|
||||
DimMatrix intrinsicPerm_;
|
||||
Evaluation relativePermeability_[numPhases];
|
||||
Evaluation mobility_[numPhases];
|
||||
Evaluation porosity_;
|
||||
};
|
||||
|
||||
} // namespace Opm
|
||||
|
||||
#endif
|
111
opm/models/richards/richardslocalresidual.hh
Normal file
111
opm/models/richards/richardslocalresidual.hh
Normal file
@ -0,0 +1,111 @@
|
||||
// -*- mode: C++; tab-width: 4; indent-tabs-mode: nil; c-basic-offset: 4 -*-
|
||||
// vi: set et ts=4 sw=4 sts=4:
|
||||
/*
|
||||
This file is part of the Open Porous Media project (OPM).
|
||||
|
||||
OPM 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.
|
||||
|
||||
OPM 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 OPM. If not, see <http://www.gnu.org/licenses/>.
|
||||
|
||||
Consult the COPYING file in the top-level source directory of this
|
||||
module for the precise wording of the license and the list of
|
||||
copyright holders.
|
||||
*/
|
||||
/*!
|
||||
* \file
|
||||
*
|
||||
* \copydoc Opm::RichardsLocalResidual
|
||||
*/
|
||||
#ifndef EWOMS_RICHARDS_LOCAL_RESIDUAL_HH
|
||||
#define EWOMS_RICHARDS_LOCAL_RESIDUAL_HH
|
||||
|
||||
#include "richardsintensivequantities.hh"
|
||||
|
||||
#include "richardsextensivequantities.hh"
|
||||
|
||||
namespace Opm {
|
||||
|
||||
/*!
|
||||
* \ingroup RichardsModel
|
||||
* \brief Element-wise calculation of the residual for the Richards model.
|
||||
*/
|
||||
template <class TypeTag>
|
||||
class RichardsLocalResidual : public GET_PROP_TYPE(TypeTag, DiscLocalResidual)
|
||||
{
|
||||
typedef typename GET_PROP_TYPE(TypeTag, EqVector) EqVector;
|
||||
typedef typename GET_PROP_TYPE(TypeTag, Evaluation) Evaluation;
|
||||
typedef typename GET_PROP_TYPE(TypeTag, RateVector) RateVector;
|
||||
typedef typename GET_PROP_TYPE(TypeTag, IntensiveQuantities) IntensiveQuantities;
|
||||
typedef typename GET_PROP_TYPE(TypeTag, ElementContext) ElementContext;
|
||||
typedef typename GET_PROP_TYPE(TypeTag, Indices) Indices;
|
||||
|
||||
enum { contiEqIdx = Indices::contiEqIdx };
|
||||
enum { liquidPhaseIdx = GET_PROP_VALUE(TypeTag, LiquidPhaseIndex) };
|
||||
enum { numEq = GET_PROP_VALUE(TypeTag, NumEq) };
|
||||
typedef Opm::MathToolbox<Evaluation> Toolbox;
|
||||
|
||||
public:
|
||||
/*!
|
||||
* \copydoc ImmiscibleLocalResidual::computeStorage
|
||||
*/
|
||||
template <class LhsEval>
|
||||
void computeStorage(Dune::FieldVector<LhsEval, numEq>& storage,
|
||||
const ElementContext& elemCtx,
|
||||
unsigned dofIdx,
|
||||
unsigned timeIdx) const
|
||||
{
|
||||
const IntensiveQuantities& intQuants = elemCtx.intensiveQuantities(dofIdx, timeIdx);
|
||||
|
||||
// partial time derivative of the wetting phase mass
|
||||
storage[contiEqIdx] =
|
||||
Toolbox::template decay<LhsEval>(intQuants.fluidState().density(liquidPhaseIdx))
|
||||
*Toolbox::template decay<LhsEval>(intQuants.fluidState().saturation(liquidPhaseIdx))
|
||||
*Toolbox::template decay<LhsEval>(intQuants.porosity());
|
||||
}
|
||||
|
||||
/*!
|
||||
* \copydoc ImmiscibleLocalResidual::computeFlux
|
||||
*/
|
||||
void computeFlux(RateVector& flux,
|
||||
const ElementContext& elemCtx,
|
||||
unsigned scvfIdx,
|
||||
unsigned timeIdx) const
|
||||
{
|
||||
const auto& extQuants = elemCtx.extensiveQuantities(scvfIdx, timeIdx);
|
||||
|
||||
unsigned focusDofIdx = elemCtx.focusDofIndex();
|
||||
unsigned upIdx = static_cast<unsigned>(extQuants.upstreamIndex(liquidPhaseIdx));
|
||||
|
||||
const IntensiveQuantities& up = elemCtx.intensiveQuantities(upIdx, timeIdx);
|
||||
|
||||
// compute advective mass flux of the liquid phase. This is slightly hacky
|
||||
// because it is specific to the element-centered finite volume method.
|
||||
const Evaluation& rho = up.fluidState().density(liquidPhaseIdx);
|
||||
if (focusDofIdx == upIdx)
|
||||
flux[contiEqIdx] = extQuants.volumeFlux(liquidPhaseIdx)*rho;
|
||||
else
|
||||
flux[contiEqIdx] = extQuants.volumeFlux(liquidPhaseIdx)*Toolbox::value(rho);
|
||||
}
|
||||
|
||||
/*!
|
||||
* \copydoc ImmiscibleLocalResidual::computeSource
|
||||
*/
|
||||
void computeSource(RateVector& source,
|
||||
const ElementContext& elemCtx,
|
||||
unsigned dofIdx,
|
||||
unsigned timeIdx) const
|
||||
{ elemCtx.problem().source(source, elemCtx, dofIdx, timeIdx); }
|
||||
};
|
||||
|
||||
} // namespace Opm
|
||||
|
||||
#endif
|
373
opm/models/richards/richardsmodel.hh
Normal file
373
opm/models/richards/richardsmodel.hh
Normal file
@ -0,0 +1,373 @@
|
||||
// -*- mode: C++; tab-width: 4; indent-tabs-mode: nil; c-basic-offset: 4 -*-
|
||||
// vi: set et ts=4 sw=4 sts=4:
|
||||
/*
|
||||
This file is part of the Open Porous Media project (OPM).
|
||||
|
||||
OPM 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.
|
||||
|
||||
OPM 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 OPM. If not, see <http://www.gnu.org/licenses/>.
|
||||
|
||||
Consult the COPYING file in the top-level source directory of this
|
||||
module for the precise wording of the license and the list of
|
||||
copyright holders.
|
||||
*/
|
||||
/*!
|
||||
* \file
|
||||
*
|
||||
* \copydoc Opm::RichardsModel
|
||||
*/
|
||||
#ifndef EWOMS_RICHARDS_MODEL_HH
|
||||
#define EWOMS_RICHARDS_MODEL_HH
|
||||
|
||||
#include <opm/material/densead/Math.hpp>
|
||||
|
||||
#include "richardsproperties.hh"
|
||||
#include "richardsindices.hh"
|
||||
#include "richardslocalresidual.hh"
|
||||
#include "richardsextensivequantities.hh"
|
||||
#include "richardsratevector.hh"
|
||||
#include "richardsboundaryratevector.hh"
|
||||
#include "richardsprimaryvariables.hh"
|
||||
#include "richardsintensivequantities.hh"
|
||||
#include "richardsnewtonmethod.hh"
|
||||
|
||||
#include <opm/models/common/multiphasebasemodel.hh>
|
||||
|
||||
#include <opm/material/components/NullComponent.hpp>
|
||||
#include <opm/material/fluidsystems/LiquidPhase.hpp>
|
||||
#include <opm/material/fluidsystems/GasPhase.hpp>
|
||||
#include <opm/material/fluidsystems/TwoPhaseImmiscibleFluidSystem.hpp>
|
||||
#include <opm/material/common/Unused.hpp>
|
||||
|
||||
#include <sstream>
|
||||
#include <string>
|
||||
|
||||
namespace Opm {
|
||||
template <class TypeTag>
|
||||
class RichardsModel;
|
||||
}
|
||||
|
||||
BEGIN_PROPERTIES
|
||||
|
||||
//! The type tag for problems discretized using the Richards model
|
||||
NEW_TYPE_TAG(Richards, INHERITS_FROM(MultiPhaseBaseModel));
|
||||
|
||||
//! By default, assume that the first phase is the liquid one
|
||||
SET_INT_PROP(Richards, LiquidPhaseIndex, 0);
|
||||
|
||||
//! By default, assume that the non-liquid phase is gaseos
|
||||
SET_INT_PROP(Richards, GasPhaseIndex, 1 - GET_PROP_VALUE(TypeTag, LiquidPhaseIndex));
|
||||
|
||||
/*!
|
||||
* \brief By default, assume that component which the liquid is made of has
|
||||
* the same index as the liquid phase.
|
||||
*
|
||||
* This is a convention which works for most fluid systems shipped
|
||||
* with eWoms by default, but it cannot generally correct because the
|
||||
* liquid can be composed of different components. (e.g., do you
|
||||
* prefer Ethanol of H2O??)
|
||||
*/
|
||||
SET_INT_PROP(Richards, LiquidComponentIndex, GET_PROP_VALUE(TypeTag, LiquidPhaseIndex));
|
||||
|
||||
//! By default, assume that the gas component is the other than the liquid one
|
||||
SET_INT_PROP(Richards, GasComponentIndex, 1 - GET_PROP_VALUE(TypeTag, LiquidComponentIndex));
|
||||
|
||||
//! The local residual operator
|
||||
SET_TYPE_PROP(Richards,
|
||||
LocalResidual,
|
||||
Opm::RichardsLocalResidual<TypeTag>);
|
||||
|
||||
//! The global model used
|
||||
SET_TYPE_PROP(Richards, Model, Opm::RichardsModel<TypeTag>);
|
||||
|
||||
//! the RateVector property
|
||||
SET_TYPE_PROP(Richards, RateVector, Opm::RichardsRateVector<TypeTag>);
|
||||
|
||||
//! the BoundaryRateVector property
|
||||
SET_TYPE_PROP(Richards, BoundaryRateVector, Opm::RichardsBoundaryRateVector<TypeTag>);
|
||||
|
||||
//! the PrimaryVariables property
|
||||
SET_TYPE_PROP(Richards, PrimaryVariables, Opm::RichardsPrimaryVariables<TypeTag>);
|
||||
|
||||
//! The class for the intensive quantities
|
||||
SET_TYPE_PROP(Richards, IntensiveQuantities, Opm::RichardsIntensiveQuantities<TypeTag>);
|
||||
|
||||
//! The class for the quantities required for the flux calculation
|
||||
SET_TYPE_PROP(Richards, ExtensiveQuantities, Opm::RichardsExtensiveQuantities<TypeTag>);
|
||||
|
||||
//! The class of the Newton method
|
||||
SET_TYPE_PROP(Richards, NewtonMethod, Opm::RichardsNewtonMethod<TypeTag>);
|
||||
|
||||
//! The class with all index definitions for the model
|
||||
SET_TYPE_PROP(Richards, Indices, Opm::RichardsIndices);
|
||||
|
||||
/*!
|
||||
* \brief The wetting phase used.
|
||||
*
|
||||
* By default we use the null-phase, i.e. this has to be defined by
|
||||
* the problem for the program to work. Please be aware that you
|
||||
* should be careful to use the Richards model in conjunction with
|
||||
* liquid non-wetting phases. This is only meaningful if the viscosity
|
||||
* of the liquid phase is _much_ lower than the viscosity of the
|
||||
* wetting phase.
|
||||
*/
|
||||
SET_PROP(Richards, WettingFluid)
|
||||
{
|
||||
private:
|
||||
typedef typename GET_PROP_TYPE(TypeTag, Scalar) Scalar;
|
||||
|
||||
public:
|
||||
typedef Opm::LiquidPhase<Scalar, Opm::NullComponent<Scalar> > type;
|
||||
};
|
||||
|
||||
/*!
|
||||
* \brief The non-wetting phase used.
|
||||
*
|
||||
* By default we use the null-phase, i.e. this has to be defined by
|
||||
* the problem for the program to work. This doed not need to be
|
||||
* specified by the problem for the Richards model to work because the
|
||||
* Richards model does not conserve the non-wetting phase.
|
||||
*/
|
||||
SET_PROP(Richards, NonWettingFluid)
|
||||
{
|
||||
private:
|
||||
typedef typename GET_PROP_TYPE(TypeTag, Scalar) Scalar;
|
||||
|
||||
public:
|
||||
typedef Opm::GasPhase<Scalar, Opm::NullComponent<Scalar> > type;
|
||||
};
|
||||
|
||||
/*!
|
||||
*\brief The fluid system used by the model.
|
||||
*
|
||||
* By default this uses the immiscible twophase fluid system. The
|
||||
* actual fluids used are specified using in the problem definition by
|
||||
* the WettingFluid and NonWettingFluid properties. Be aware that
|
||||
* using different fluid systems in conjunction with the Richards
|
||||
* model only makes very limited sense.
|
||||
*/
|
||||
SET_PROP(Richards, FluidSystem)
|
||||
{
|
||||
private:
|
||||
typedef typename GET_PROP_TYPE(TypeTag, Scalar) Scalar;
|
||||
typedef typename GET_PROP_TYPE(TypeTag, WettingFluid) WettingFluid;
|
||||
typedef typename GET_PROP_TYPE(TypeTag, NonWettingFluid) NonWettingFluid;
|
||||
|
||||
public:
|
||||
typedef Opm::TwoPhaseImmiscibleFluidSystem<Scalar, WettingFluid, NonWettingFluid> type;
|
||||
};
|
||||
|
||||
|
||||
END_PROPERTIES
|
||||
|
||||
namespace Opm {
|
||||
|
||||
/*!
|
||||
* \ingroup RichardsModel
|
||||
*
|
||||
* \brief This model implements a variant of the Richards equation for
|
||||
* quasi-twophase flow.
|
||||
*
|
||||
* In the unsaturated zone, Richards' equation is frequently used to
|
||||
* approximate the water distribution above the groundwater level. It
|
||||
* can be derived from the two-phase equations, i.e.
|
||||
* \f[
|
||||
* \frac{\partial\;\phi S_\alpha \rho_\alpha}{\partial t}
|
||||
* -
|
||||
* \mathrm{div} \left\{
|
||||
* \rho_\alpha \frac{k_{r\alpha}}{\mu_\alpha}\; \mathbf{K}\;
|
||||
* \mathbf{grad}\left[
|
||||
* p_\alpha - g\rho_\alpha
|
||||
* \right]
|
||||
* \right\}
|
||||
* =
|
||||
* q_\alpha,
|
||||
* \f]
|
||||
* where \f$\alpha \in \{w, n\}\f$ is the index of the fluid phase,
|
||||
* \f$\rho_\alpha\f$ is the fluid density, \f$S_\alpha\f$ is the fluid
|
||||
* saturation, \f$\phi\f$ is the porosity of the soil,
|
||||
* \f$k_{r\alpha}\f$ is the relative permeability for the fluid,
|
||||
* \f$\mu_\alpha\f$ is the fluid's dynamic viscosity, \f$\mathbf{K}\f$
|
||||
* is the intrinsic permeability tensor, \f$p_\alpha\f$ is the fluid
|
||||
* phase pressure and \f$g\f$ is the potential of the gravity field.
|
||||
*
|
||||
* In contrast to the "full" two-phase model, the Richards model
|
||||
* assumes that the non-wetting fluid is gas and that it thus exhibits
|
||||
* a much lower viscosity than the (liquid) wetting phase. (This
|
||||
* assumption is quite realistic in many applications: For example, at
|
||||
* atmospheric pressure and at room temperature, the viscosity of air
|
||||
* is only about \f$1\%\f$ of the viscosity of liquid water.) As a
|
||||
* consequence, the \f$\frac{k_{r\alpha}}{\mu_\alpha}\f$ term
|
||||
* typically is much larger for the gas phase than for the wetting
|
||||
* phase. Using this reasoning, the Richards model assumes that
|
||||
* \f$\frac{k_{rn}}{\mu_n}\f$ is infinitely large compared to the same
|
||||
* term of the liquid phase. This implies that the pressure of the gas
|
||||
* phase is equivalent to the static pressure distribution and that
|
||||
* therefore, mass conservation only needs to be considered for the
|
||||
* liquid phase.
|
||||
*
|
||||
* The model thus choses the absolute pressure of the wetting phase
|
||||
* \f$p_w\f$ as its only primary variable. The wetting phase
|
||||
* saturation is calculated using the inverse of the capillary
|
||||
* pressure, i.e.
|
||||
* \f[
|
||||
* S_w = p_c^{-1}(p_n - p_w)
|
||||
* \f]
|
||||
* holds, where \f$p_n\f$ is a reference pressure given by the
|
||||
* problem's \c referencePressure() method. Nota bene, that the last
|
||||
* step assumes that the capillary pressure-saturation curve can be
|
||||
* uniquely inverted, i.e. it is not possible to set the capillary
|
||||
* pressure to zero if the Richards model ought to be used!
|
||||
*/
|
||||
template <class TypeTag>
|
||||
class RichardsModel
|
||||
: public MultiPhaseBaseModel<TypeTag>
|
||||
{
|
||||
typedef MultiPhaseBaseModel<TypeTag> ParentType;
|
||||
|
||||
typedef typename GET_PROP_TYPE(TypeTag, Simulator) Simulator;
|
||||
|
||||
typedef typename GET_PROP_TYPE(TypeTag, Scalar) Scalar;
|
||||
typedef typename GET_PROP_TYPE(TypeTag, FluidSystem) FluidSystem;
|
||||
typedef typename GET_PROP_TYPE(TypeTag, Indices) Indices;
|
||||
|
||||
static const unsigned numPhases = FluidSystem::numPhases;
|
||||
static const unsigned numComponents = FluidSystem::numComponents;
|
||||
|
||||
static const unsigned liquidPhaseIdx = GET_PROP_VALUE(TypeTag, LiquidPhaseIndex);
|
||||
static const unsigned gasPhaseIdx = GET_PROP_VALUE(TypeTag, GasPhaseIndex);
|
||||
|
||||
static const unsigned liquidCompIdx = GET_PROP_VALUE(TypeTag, LiquidComponentIndex);
|
||||
static const unsigned gasCompIdx = GET_PROP_VALUE(TypeTag, GasComponentIndex);
|
||||
|
||||
|
||||
// some consistency checks
|
||||
static_assert(numPhases == 2,
|
||||
"Exactly two fluids are required for this model");
|
||||
static_assert(numComponents == 2,
|
||||
"Exactly two components are required for this model");
|
||||
static_assert(liquidPhaseIdx != gasPhaseIdx,
|
||||
"The liquid and the gas phases must be different");
|
||||
static_assert(liquidCompIdx != gasCompIdx,
|
||||
"The liquid and the gas components must be different");
|
||||
|
||||
public:
|
||||
RichardsModel(Simulator& simulator)
|
||||
: ParentType(simulator)
|
||||
{
|
||||
// the liquid phase must be liquid, the gas phase must be
|
||||
// gaseous. Think about it!
|
||||
assert(FluidSystem::isLiquid(liquidPhaseIdx));
|
||||
assert(!FluidSystem::isLiquid(gasPhaseIdx));
|
||||
}
|
||||
|
||||
/*!
|
||||
* \copydoc FvBaseDiscretization::registerParameters
|
||||
*/
|
||||
static void registerParameters()
|
||||
{
|
||||
ParentType::registerParameters();
|
||||
}
|
||||
|
||||
/*!
|
||||
* \copydoc FvBaseDiscretization::name
|
||||
*/
|
||||
static std::string name()
|
||||
{ return "richards"; }
|
||||
|
||||
/*!
|
||||
* \copydoc FvBaseDiscretization::primaryVarName
|
||||
*/
|
||||
std::string primaryVarName(unsigned pvIdx) const
|
||||
{
|
||||
std::ostringstream oss;
|
||||
if (pvIdx == Indices::pressureWIdx)
|
||||
oss << "pressure_" << FluidSystem::phaseName(liquidPhaseIdx);
|
||||
else
|
||||
assert(0);
|
||||
|
||||
return oss.str();
|
||||
}
|
||||
|
||||
/*!
|
||||
* \copydoc FvBaseDiscretization::eqName
|
||||
*/
|
||||
std::string eqName(unsigned eqIdx) const
|
||||
{
|
||||
std::ostringstream oss;
|
||||
if (eqIdx == Indices::contiEqIdx)
|
||||
oss << "continuity_" << FluidSystem::phaseName(liquidPhaseIdx);
|
||||
else
|
||||
assert(0);
|
||||
|
||||
return oss.str();
|
||||
}
|
||||
|
||||
/*!
|
||||
* \copydoc FvBaseDiscretization::primaryVarWeight
|
||||
*/
|
||||
Scalar primaryVarWeight(unsigned globalDofIdx OPM_UNUSED, unsigned pvIdx) const
|
||||
{
|
||||
if (Indices::pressureWIdx == pvIdx) {
|
||||
return 10 / referencePressure_;
|
||||
}
|
||||
|
||||
return 1;
|
||||
}
|
||||
|
||||
/*!
|
||||
* \copydoc FvBaseDiscretization::eqWeight
|
||||
*/
|
||||
Scalar eqWeight(unsigned globalDofIdx OPM_UNUSED, unsigned OPM_OPTIM_UNUSED eqIdx) const
|
||||
{
|
||||
unsigned OPM_OPTIM_UNUSED compIdx = eqIdx - Indices::contiEqIdx;
|
||||
assert(0 <= compIdx && compIdx <= FluidSystem::numPhases);
|
||||
|
||||
// make all kg equal
|
||||
return 1.0;
|
||||
}
|
||||
|
||||
/*!
|
||||
* \copydoc FvBaseDiscretization::updateBegin
|
||||
*/
|
||||
void updateBegin()
|
||||
{
|
||||
ParentType::updateBegin();
|
||||
|
||||
// find the a reference pressure. The first degree of freedom
|
||||
// might correspond to non-interior entities which would lead
|
||||
// to an undefined value, so we have to iterate...
|
||||
for (unsigned dofIdx = 0; dofIdx < this->numGridDof(); ++ dofIdx) {
|
||||
if (this->isLocalDof(dofIdx)) {
|
||||
referencePressure_ =
|
||||
this->solution(/*timeIdx=*/0)[dofIdx][/*pvIdx=*/Indices::pressureWIdx];
|
||||
break;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
/*!
|
||||
* \copydoc FvBaseDiscretization::phaseIsConsidered
|
||||
*/
|
||||
bool phaseIsConsidered(unsigned phaseIdx) const
|
||||
{ return phaseIdx == liquidPhaseIdx; }
|
||||
|
||||
void registerOutputModules_()
|
||||
{
|
||||
ParentType::registerOutputModules_();
|
||||
}
|
||||
|
||||
mutable Scalar referencePressure_;
|
||||
};
|
||||
} // namespace Opm
|
||||
|
||||
#endif
|
159
opm/models/richards/richardsnewtonmethod.hh
Normal file
159
opm/models/richards/richardsnewtonmethod.hh
Normal file
@ -0,0 +1,159 @@
|
||||
// -*- mode: C++; tab-width: 4; indent-tabs-mode: nil; c-basic-offset: 4 -*-
|
||||
// vi: set et ts=4 sw=4 sts=4:
|
||||
/*
|
||||
This file is part of the Open Porous Media project (OPM).
|
||||
|
||||
OPM 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.
|
||||
|
||||
OPM 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 OPM. If not, see <http://www.gnu.org/licenses/>.
|
||||
|
||||
Consult the COPYING file in the top-level source directory of this
|
||||
module for the precise wording of the license and the list of
|
||||
copyright holders.
|
||||
*/
|
||||
/*!
|
||||
* \file
|
||||
*
|
||||
* \copydoc Opm::RichardsNewtonMethod
|
||||
*/
|
||||
#ifndef EWOMS_RICHARDS_NEWTON_METHOD_HH
|
||||
#define EWOMS_RICHARDS_NEWTON_METHOD_HH
|
||||
|
||||
#include "richardsproperties.hh"
|
||||
|
||||
#include <opm/material/fluidstates/ImmiscibleFluidState.hpp>
|
||||
#include <opm/material/common/Unused.hpp>
|
||||
|
||||
#include <dune/common/fvector.hh>
|
||||
|
||||
namespace Opm {
|
||||
|
||||
/*!
|
||||
* \ingroup RichardsModel
|
||||
*
|
||||
* \brief A Richards model specific Newton method.
|
||||
*/
|
||||
template <class TypeTag>
|
||||
class RichardsNewtonMethod : public GET_PROP_TYPE(TypeTag, DiscNewtonMethod)
|
||||
{
|
||||
typedef typename GET_PROP_TYPE(TypeTag, DiscNewtonMethod) ParentType;
|
||||
|
||||
typedef typename GET_PROP_TYPE(TypeTag, Scalar) Scalar;
|
||||
typedef typename GET_PROP_TYPE(TypeTag, PrimaryVariables) PrimaryVariables;
|
||||
typedef typename GET_PROP_TYPE(TypeTag, EqVector) EqVector;
|
||||
typedef typename GET_PROP_TYPE(TypeTag, FluidSystem) FluidSystem;
|
||||
typedef typename GET_PROP_TYPE(TypeTag, MaterialLaw) MaterialLaw;
|
||||
typedef typename GET_PROP_TYPE(TypeTag, MaterialLawParams) MaterialLawParams;
|
||||
typedef typename GET_PROP_TYPE(TypeTag, Simulator) Simulator;
|
||||
typedef typename GET_PROP_TYPE(TypeTag, Linearizer) Linearizer;
|
||||
|
||||
typedef typename GET_PROP_TYPE(TypeTag, Indices) Indices;
|
||||
enum { pressureWIdx = Indices::pressureWIdx };
|
||||
enum { numPhases = FluidSystem::numPhases };
|
||||
enum { liquidPhaseIdx = GET_PROP_VALUE(TypeTag, LiquidPhaseIndex) };
|
||||
enum { gasPhaseIdx = GET_PROP_VALUE(TypeTag, GasPhaseIndex) };
|
||||
|
||||
typedef Dune::FieldVector<Scalar, numPhases> PhaseVector;
|
||||
|
||||
public:
|
||||
RichardsNewtonMethod(Simulator& simulator) : ParentType(simulator)
|
||||
{}
|
||||
|
||||
protected:
|
||||
friend NewtonMethod<TypeTag>;
|
||||
friend ParentType;
|
||||
|
||||
/*!
|
||||
* \copydoc FvBaseNewtonMethod::updatePrimaryVariables_
|
||||
*/
|
||||
void updatePrimaryVariables_(unsigned globalDofIdx,
|
||||
PrimaryVariables& nextValue,
|
||||
const PrimaryVariables& currentValue,
|
||||
const EqVector& update,
|
||||
const EqVector& currentResidual OPM_UNUSED)
|
||||
{
|
||||
// normal Newton-Raphson update
|
||||
nextValue = currentValue;
|
||||
nextValue -= update;
|
||||
|
||||
// do not clamp anything after 4 iterations
|
||||
if (this->numIterations_ > 4)
|
||||
return;
|
||||
|
||||
const auto& problem = this->simulator_.problem();
|
||||
|
||||
// calculate the old wetting phase saturation
|
||||
const MaterialLawParams& matParams =
|
||||
problem.materialLawParams(globalDofIdx, /*timeIdx=*/0);
|
||||
|
||||
Opm::ImmiscibleFluidState<Scalar, FluidSystem> fs;
|
||||
|
||||
// set the temperature
|
||||
Scalar T = problem.temperature(globalDofIdx, /*timeIdx=*/0);
|
||||
fs.setTemperature(T);
|
||||
|
||||
/////////
|
||||
// calculate the phase pressures of the previous iteration
|
||||
/////////
|
||||
|
||||
// first, we have to find the minimum capillary pressure
|
||||
// (i.e. Sw = 0)
|
||||
fs.setSaturation(liquidPhaseIdx, 1.0);
|
||||
fs.setSaturation(gasPhaseIdx, 0.0);
|
||||
PhaseVector pC;
|
||||
MaterialLaw::capillaryPressures(pC, matParams, fs);
|
||||
|
||||
// non-wetting pressure can be larger than the
|
||||
// reference pressure if the medium is fully
|
||||
// saturated by the wetting phase
|
||||
Scalar pWOld = currentValue[pressureWIdx];
|
||||
Scalar pNOld =
|
||||
std::max(problem.referencePressure(globalDofIdx, /*timeIdx=*/0),
|
||||
pWOld + (pC[gasPhaseIdx] - pC[liquidPhaseIdx]));
|
||||
|
||||
/////////
|
||||
// find the saturations of the previous iteration
|
||||
/////////
|
||||
fs.setPressure(liquidPhaseIdx, pWOld);
|
||||
fs.setPressure(gasPhaseIdx, pNOld);
|
||||
|
||||
PhaseVector satOld;
|
||||
MaterialLaw::saturations(satOld, matParams, fs);
|
||||
satOld[liquidPhaseIdx] = std::max<Scalar>(0.0, satOld[liquidPhaseIdx]);
|
||||
|
||||
/////////
|
||||
// find the wetting phase pressures which
|
||||
// corrospond to a 20% increase and a 20% decrease
|
||||
// of the wetting saturation
|
||||
/////////
|
||||
fs.setSaturation(liquidPhaseIdx, satOld[liquidPhaseIdx] - 0.2);
|
||||
fs.setSaturation(gasPhaseIdx, 1.0 - (satOld[liquidPhaseIdx] - 0.2));
|
||||
MaterialLaw::capillaryPressures(pC, matParams, fs);
|
||||
Scalar pwMin = pNOld - (pC[gasPhaseIdx] - pC[liquidPhaseIdx]);
|
||||
|
||||
fs.setSaturation(liquidPhaseIdx, satOld[liquidPhaseIdx] + 0.2);
|
||||
fs.setSaturation(gasPhaseIdx, 1.0 - (satOld[liquidPhaseIdx] + 0.2));
|
||||
MaterialLaw::capillaryPressures(pC, matParams, fs);
|
||||
Scalar pwMax = pNOld - (pC[gasPhaseIdx] - pC[liquidPhaseIdx]);
|
||||
|
||||
/////////
|
||||
// clamp the result to the minimum and the maximum
|
||||
// pressures we just calculated
|
||||
/////////
|
||||
Scalar pW = nextValue[pressureWIdx];
|
||||
pW = std::max(pwMin, std::min(pW, pwMax));
|
||||
nextValue[pressureWIdx] = pW;
|
||||
}
|
||||
};
|
||||
} // namespace Opm
|
||||
|
||||
#endif
|
193
opm/models/richards/richardsprimaryvariables.hh
Normal file
193
opm/models/richards/richardsprimaryvariables.hh
Normal file
@ -0,0 +1,193 @@
|
||||
// -*- mode: C++; tab-width: 4; indent-tabs-mode: nil; c-basic-offset: 4 -*-
|
||||
// vi: set et ts=4 sw=4 sts=4:
|
||||
/*
|
||||
This file is part of the Open Porous Media project (OPM).
|
||||
|
||||
OPM 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.
|
||||
|
||||
OPM 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 OPM. If not, see <http://www.gnu.org/licenses/>.
|
||||
|
||||
Consult the COPYING file in the top-level source directory of this
|
||||
module for the precise wording of the license and the list of
|
||||
copyright holders.
|
||||
*/
|
||||
/*!
|
||||
* \file
|
||||
*
|
||||
* \copydoc Opm::RichardsPrimaryVariables
|
||||
*/
|
||||
#ifndef EWOMS_RICHARDS_PRIMARY_VARIABLES_HH
|
||||
#define EWOMS_RICHARDS_PRIMARY_VARIABLES_HH
|
||||
|
||||
#include "richardsproperties.hh"
|
||||
|
||||
#include <opm/models/discretization/common/fvbaseprimaryvariables.hh>
|
||||
|
||||
#include <opm/material/constraintsolvers/ImmiscibleFlash.hpp>
|
||||
#include <opm/material/fluidstates/ImmiscibleFluidState.hpp>
|
||||
#include <opm/material/common/Valgrind.hpp>
|
||||
#include <opm/material/common/Unused.hpp>
|
||||
|
||||
#include <dune/common/fvector.hh>
|
||||
|
||||
namespace Opm {
|
||||
|
||||
/*!
|
||||
* \ingroup RichardsModel
|
||||
*
|
||||
* \brief Represents the primary variables used in the Richards model.
|
||||
*
|
||||
* This class is basically a Dune::FieldVector which can retrieve its
|
||||
* contents from an aribitatry fluid state.
|
||||
*/
|
||||
template <class TypeTag>
|
||||
class RichardsPrimaryVariables : public FvBasePrimaryVariables<TypeTag>
|
||||
{
|
||||
typedef FvBasePrimaryVariables<TypeTag> ParentType;
|
||||
typedef typename GET_PROP_TYPE(TypeTag, Scalar) Scalar;
|
||||
typedef typename GET_PROP_TYPE(TypeTag, Evaluation) Evaluation;
|
||||
typedef typename GET_PROP_TYPE(TypeTag, FluidSystem) FluidSystem;
|
||||
typedef typename GET_PROP_TYPE(TypeTag, MaterialLaw) MaterialLaw;
|
||||
typedef typename GET_PROP_TYPE(TypeTag, MaterialLawParams) MaterialLawParams;
|
||||
typedef typename GET_PROP_TYPE(TypeTag, IntensiveQuantities) EnergyModule;
|
||||
typedef typename GET_PROP_TYPE(TypeTag, Indices) Indices;
|
||||
|
||||
// primary variable indices
|
||||
enum { pressureWIdx = Indices::pressureWIdx };
|
||||
|
||||
enum { liquidPhaseIdx = GET_PROP_VALUE(TypeTag, LiquidPhaseIndex) };
|
||||
enum { gasPhaseIdx = GET_PROP_VALUE(TypeTag, GasPhaseIndex) };
|
||||
|
||||
enum { numPhases = GET_PROP_VALUE(TypeTag, NumPhases) };
|
||||
enum { numComponents = GET_PROP_VALUE(TypeTag, NumComponents) };
|
||||
|
||||
typedef Dune::FieldVector<Scalar, numComponents> ComponentVector;
|
||||
typedef Dune::FieldVector<Scalar, numPhases> PhaseVector;
|
||||
typedef typename Opm::MathToolbox<Evaluation> Toolbox;
|
||||
typedef Opm::ImmiscibleFlash<Scalar, FluidSystem> ImmiscibleFlash;
|
||||
|
||||
public:
|
||||
RichardsPrimaryVariables() : ParentType()
|
||||
{ Opm::Valgrind::SetUndefined(*this); }
|
||||
|
||||
/*!
|
||||
* \copydoc ImmisciblePrimaryVariables::ImmisciblePrimaryVariables(Scalar)
|
||||
*/
|
||||
RichardsPrimaryVariables(Scalar value) : ParentType(value)
|
||||
{}
|
||||
|
||||
/*!
|
||||
* \copydoc ImmisciblePrimaryVariables::ImmisciblePrimaryVariables(const
|
||||
* ImmisciblePrimaryVariables& )
|
||||
*/
|
||||
RichardsPrimaryVariables(const RichardsPrimaryVariables& value) = default;
|
||||
RichardsPrimaryVariables& operator=(const RichardsPrimaryVariables& value) = default;
|
||||
|
||||
/*!
|
||||
* \brief Set the primary variables with the wetting phase
|
||||
* pressure, saturation and temperature.
|
||||
*
|
||||
* \param T The temperature [K]
|
||||
* \param pw The pressure of the wetting phase [Pa]
|
||||
* \param Sw The saturation of the wetting phase []
|
||||
* \param matParams The capillary pressure law parameters
|
||||
*/
|
||||
void assignImmiscibleFromWetting(Scalar T, Scalar pw, Scalar Sw,
|
||||
const MaterialLawParams& matParams)
|
||||
{
|
||||
Opm::ImmiscibleFluidState<Scalar, FluidSystem> fs;
|
||||
|
||||
fs.setTemperature(T);
|
||||
fs.setSaturation(liquidPhaseIdx, Sw);
|
||||
fs.setSaturation(gasPhaseIdx, 1 - Sw);
|
||||
|
||||
// set phase pressures
|
||||
PhaseVector pC;
|
||||
MaterialLaw::capillaryPressures(pC, matParams, fs);
|
||||
|
||||
fs.setPressure(liquidPhaseIdx, pw);
|
||||
fs.setPressure(gasPhaseIdx, pw + (pC[gasPhaseIdx] - pC[liquidPhaseIdx]));
|
||||
|
||||
assignNaive(fs);
|
||||
}
|
||||
|
||||
/*!
|
||||
* \brief Set the primary variables with the non-wetting phase
|
||||
* pressure, saturation and temperature.
|
||||
*
|
||||
* \param T The temperature [K]
|
||||
* \param pn The pressure of the non-wetting phase [Pa]
|
||||
* \param Sn The saturation of the non-wetting phase []
|
||||
* \param matParams The capillary pressure law parameters
|
||||
*/
|
||||
void assignImmiscibleFromNonWetting(Scalar T, Scalar pn, Scalar Sn,
|
||||
const MaterialLawParams& matParams)
|
||||
{
|
||||
Opm::ImmiscibleFluidState<Scalar, FluidSystem> fs;
|
||||
|
||||
fs.setTemperature(T);
|
||||
fs.setSaturation(liquidPhaseIdx, 1 - Sn);
|
||||
fs.setSaturation(gasPhaseIdx, Sn);
|
||||
|
||||
// set phase pressures
|
||||
PhaseVector pC;
|
||||
MaterialLaw::capillaryPressures(pC, matParams, fs);
|
||||
|
||||
fs.setPressure(gasPhaseIdx, pn);
|
||||
fs.setPressure(gasPhaseIdx, pn + (pC[liquidPhaseIdx] - pC[gasPhaseIdx]));
|
||||
|
||||
assignNaive(fs);
|
||||
}
|
||||
|
||||
/*!
|
||||
* \copydoc ImmisciblePrimaryVariables::assignMassConservative
|
||||
*/
|
||||
template <class FluidState>
|
||||
void assignMassConservative(const FluidState& fluidState,
|
||||
const MaterialLawParams& matParams,
|
||||
bool isInEquilibrium OPM_UNUSED= false)
|
||||
{
|
||||
ComponentVector globalMolarities(0.0);
|
||||
for (unsigned compIdx = 0; compIdx < numComponents; ++compIdx) {
|
||||
for (unsigned phaseIdx = 0; phaseIdx < numPhases; ++phaseIdx) {
|
||||
globalMolarities[compIdx] +=
|
||||
fluidState.molarity(phaseIdx, compIdx) * fluidState.saturation(phaseIdx);
|
||||
}
|
||||
}
|
||||
|
||||
Opm::ImmiscibleFluidState<Scalar, FluidSystem> fsFlash;
|
||||
fsFlash.assign(fluidState);
|
||||
typename FluidSystem::ParameterCache paramCache;
|
||||
ImmiscibleFlash::template solve<MaterialLaw>(fsFlash, paramCache,
|
||||
matParams,
|
||||
globalMolarities);
|
||||
|
||||
assignNaive(fsFlash);
|
||||
}
|
||||
|
||||
/*!
|
||||
* \copydoc ImmisciblePrimaryVariables::assignNaive
|
||||
*/
|
||||
template <class FluidState>
|
||||
void assignNaive(const FluidState& fluidState)
|
||||
{
|
||||
// assign the phase temperatures. this is out-sourced to
|
||||
// the energy module
|
||||
EnergyModule::setPriVarTemperatures(*this, fluidState);
|
||||
|
||||
(*this)[pressureWIdx] = fluidState.pressure(liquidPhaseIdx);
|
||||
}
|
||||
};
|
||||
|
||||
} // namespace Opm
|
||||
|
||||
#endif
|
64
opm/models/richards/richardsproperties.hh
Normal file
64
opm/models/richards/richardsproperties.hh
Normal file
@ -0,0 +1,64 @@
|
||||
// -*- mode: C++; tab-width: 4; indent-tabs-mode: nil; c-basic-offset: 4 -*-
|
||||
// vi: set et ts=4 sw=4 sts=4:
|
||||
/*
|
||||
This file is part of the Open Porous Media project (OPM).
|
||||
|
||||
OPM 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.
|
||||
|
||||
OPM 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 OPM. If not, see <http://www.gnu.org/licenses/>.
|
||||
|
||||
Consult the COPYING file in the top-level source directory of this
|
||||
module for the precise wording of the license and the list of
|
||||
copyright holders.
|
||||
*/
|
||||
/*!
|
||||
* \file
|
||||
* \ingroup RichardsModel
|
||||
*
|
||||
* \brief Contains the property declarations for the Richards model.
|
||||
*/
|
||||
#ifndef EWOMS_RICHARDS_PROPERTIES_HH
|
||||
#define EWOMS_RICHARDS_PROPERTIES_HH
|
||||
|
||||
#include <opm/models/common/multiphasebaseproperties.hh>
|
||||
|
||||
// \{
|
||||
BEGIN_PROPERTIES
|
||||
|
||||
//! The fluid system used for the problem
|
||||
NEW_PROP_TAG(FluidSystem);
|
||||
|
||||
//! The fluid used as the wetting phase (by default, we set the fluid
|
||||
//! system to the immiscible one, which requires this property.)
|
||||
NEW_PROP_TAG(WettingFluid);
|
||||
|
||||
//! The fluid used as the non-wetting phase (by default, we set the
|
||||
//! fluid system to the immiscible one, which requires this property.)
|
||||
NEW_PROP_TAG(NonWettingFluid);
|
||||
|
||||
//! Index of the fluid which represents the wetting phase
|
||||
NEW_PROP_TAG(LiquidPhaseIndex);
|
||||
|
||||
//! Index of the fluid which represents the non-wetting phase
|
||||
NEW_PROP_TAG(GasPhaseIndex);
|
||||
|
||||
//! Index of the component which constitutes the liquid
|
||||
NEW_PROP_TAG(LiquidComponentIndex);
|
||||
|
||||
//! Index of the component which constitutes the gas
|
||||
NEW_PROP_TAG(GasComponentIndex);
|
||||
|
||||
// \}
|
||||
|
||||
END_PROPERTIES
|
||||
|
||||
#endif
|
146
opm/models/richards/richardsratevector.hh
Normal file
146
opm/models/richards/richardsratevector.hh
Normal file
@ -0,0 +1,146 @@
|
||||
// -*- mode: C++; tab-width: 4; indent-tabs-mode: nil; c-basic-offset: 4 -*-
|
||||
// vi: set et ts=4 sw=4 sts=4:
|
||||
/*
|
||||
This file is part of the Open Porous Media project (OPM).
|
||||
|
||||
OPM 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.
|
||||
|
||||
OPM 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 OPM. If not, see <http://www.gnu.org/licenses/>.
|
||||
|
||||
Consult the COPYING file in the top-level source directory of this
|
||||
module for the precise wording of the license and the list of
|
||||
copyright holders.
|
||||
*/
|
||||
/*!
|
||||
* \file
|
||||
*
|
||||
* \copydoc Opm::RichardsRateVector
|
||||
*/
|
||||
#ifndef EWOMS_RICHARDS_RATE_VECTOR_HH
|
||||
#define EWOMS_RICHARDS_RATE_VECTOR_HH
|
||||
|
||||
#include <dune/common/fvector.hh>
|
||||
|
||||
#include <opm/material/common/Valgrind.hpp>
|
||||
#include <opm/material/constraintsolvers/NcpFlash.hpp>
|
||||
|
||||
#include "richardsintensivequantities.hh"
|
||||
|
||||
namespace Opm {
|
||||
|
||||
/*!
|
||||
* \ingroup RichardsModel
|
||||
*
|
||||
* \brief Implements a vector representing mass, molar or volumetric rates.
|
||||
*
|
||||
* This class is basically a Dune::FieldVector which can be set using either mass, molar
|
||||
* or volumetric rates.
|
||||
*/
|
||||
template <class TypeTag>
|
||||
class RichardsRateVector
|
||||
: public Dune::FieldVector<typename GET_PROP_TYPE(TypeTag, Evaluation),
|
||||
GET_PROP_VALUE(TypeTag, NumEq)>
|
||||
{
|
||||
typedef typename GET_PROP_TYPE(TypeTag, Scalar) Scalar;
|
||||
typedef typename GET_PROP_TYPE(TypeTag, Evaluation) Evaluation;
|
||||
typedef typename GET_PROP_TYPE(TypeTag, FluidSystem) FluidSystem;
|
||||
typedef typename GET_PROP_TYPE(TypeTag, IntensiveQuantities) EnergyModule;
|
||||
typedef typename GET_PROP_TYPE(TypeTag, Indices) Indices;
|
||||
|
||||
enum { contiEqIdx = Indices::contiEqIdx };
|
||||
enum { liquidCompIdx = GET_PROP_VALUE(TypeTag, LiquidComponentIndex) };
|
||||
enum { numEq = GET_PROP_VALUE(TypeTag, NumEq) };
|
||||
|
||||
typedef Dune::FieldVector<Evaluation, numEq> ParentType;
|
||||
|
||||
public:
|
||||
RichardsRateVector() : ParentType()
|
||||
{ Opm::Valgrind::SetUndefined(*this); }
|
||||
|
||||
/*!
|
||||
* \copydoc ImmiscibleRateVector::ImmiscibleRateVector(Scalar)
|
||||
*/
|
||||
RichardsRateVector(const Evaluation& value)
|
||||
: ParentType(value)
|
||||
{}
|
||||
|
||||
/*!
|
||||
* \copydoc ImmiscibleRateVector::ImmiscibleRateVector(const
|
||||
* ImmiscibleRateVector& )
|
||||
*/
|
||||
RichardsRateVector(const RichardsRateVector& value)
|
||||
: ParentType(value)
|
||||
{}
|
||||
|
||||
/*!
|
||||
* \copydoc ImmiscibleRateVector::setMassRate
|
||||
*/
|
||||
void setMassRate(const ParentType& value)
|
||||
{ ParentType::operator=(value); }
|
||||
|
||||
/*!
|
||||
* \copydoc ImmiscibleRateVector::setMolarRate
|
||||
*/
|
||||
void setMolarRate(const ParentType& value)
|
||||
{
|
||||
// convert to mass rates
|
||||
ParentType::operator[](contiEqIdx) =
|
||||
value[contiEqIdx]*FluidSystem::molarMass(liquidCompIdx);
|
||||
}
|
||||
|
||||
/*!
|
||||
* \copydoc ImmiscibleRateVector::setEnthalpyRate
|
||||
*/
|
||||
template <class RhsEval>
|
||||
void setEnthalpyRate(const RhsEval& rate)
|
||||
{ EnergyModule::setEnthalpyRate(*this, rate); }
|
||||
|
||||
/*!
|
||||
* \copydoc ImmiscibleRateVector::setVolumetricRate
|
||||
*/
|
||||
template <class FluidState, class RhsEval>
|
||||
void setVolumetricRate(const FluidState& fluidState, unsigned phaseIdx, const RhsEval& volume)
|
||||
{
|
||||
(*this)[contiEqIdx] =
|
||||
fluidState.density(phaseIdx)
|
||||
* fluidState.massFraction(phaseIdx, liquidCompIdx)
|
||||
* volume;
|
||||
|
||||
EnergyModule::setEnthalpyRate(*this, fluidState, phaseIdx, volume);
|
||||
}
|
||||
|
||||
|
||||
/*!
|
||||
* \brief Assignment operator from a scalar or a function evaluation
|
||||
*/
|
||||
template <class RhsEval>
|
||||
RichardsRateVector& operator=(const RhsEval& value)
|
||||
{
|
||||
for (unsigned i=0; i < this->size(); ++i)
|
||||
(*this)[i] = value;
|
||||
return *this;
|
||||
}
|
||||
|
||||
/*!
|
||||
* \brief Assignment operator from another rate vector
|
||||
*/
|
||||
RichardsRateVector& operator=(const RichardsRateVector& other)
|
||||
{
|
||||
for (unsigned i=0; i < this->size(); ++i)
|
||||
(*this)[i] = other[i];
|
||||
return *this;
|
||||
}
|
||||
};
|
||||
|
||||
} // namespace Opm
|
||||
|
||||
#endif
|
Loading…
Reference in New Issue
Block a user