mirror of
https://github.com/OPM/opm-simulators.git
synced 2024-12-29 10:40:59 -06:00
606 lines
22 KiB
C++
606 lines
22 KiB
C++
// -*- 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::FvBaseElementContext
|
|
*/
|
|
#ifndef EWOMS_FV_BASE_ELEMENT_CONTEXT_HH
|
|
#define EWOMS_FV_BASE_ELEMENT_CONTEXT_HH
|
|
|
|
#include "fvbaseproperties.hh"
|
|
|
|
#include <opm/models/discretization/common/linearizationtype.hh>
|
|
#include <opm/models/utils/alignedallocator.hh>
|
|
|
|
#include <dune/common/fvector.hh>
|
|
|
|
#include <vector>
|
|
|
|
namespace Opm {
|
|
|
|
/*!
|
|
* \ingroup FiniteVolumeDiscretizations
|
|
*
|
|
* \brief This class stores an array of IntensiveQuantities objects, one
|
|
* intensive quantities object for each of the element's vertices
|
|
*/
|
|
template<class TypeTag>
|
|
class FvBaseElementContext
|
|
{
|
|
using Implementation = GetPropType<TypeTag, Properties::ElementContext>;
|
|
|
|
using Scalar = GetPropType<TypeTag, Properties::Scalar>;
|
|
using PrimaryVariables = GetPropType<TypeTag, Properties::PrimaryVariables>;
|
|
using IntensiveQuantities = GetPropType<TypeTag, Properties::IntensiveQuantities>;
|
|
using ExtensiveQuantities = GetPropType<TypeTag, Properties::ExtensiveQuantities>;
|
|
|
|
// the history size of the time discretization in number of steps
|
|
enum { timeDiscHistorySize = getPropValue<TypeTag, Properties::TimeDiscHistorySize>() };
|
|
|
|
struct DofStore_ {
|
|
IntensiveQuantities intensiveQuantities[timeDiscHistorySize];
|
|
const PrimaryVariables* priVars[timeDiscHistorySize];
|
|
const IntensiveQuantities *thermodynamicHint[timeDiscHistorySize];
|
|
};
|
|
using DofVarsVector = std::vector<DofStore_>;
|
|
using ExtensiveQuantitiesVector = std::vector<ExtensiveQuantities>;
|
|
|
|
using Simulator = GetPropType<TypeTag, Properties::Simulator>;
|
|
using Problem = GetPropType<TypeTag, Properties::Problem>;
|
|
using Model = GetPropType<TypeTag, Properties::Model>;
|
|
using Stencil = GetPropType<TypeTag, Properties::Stencil>;
|
|
using GradientCalculator = GetPropType<TypeTag, Properties::GradientCalculator>;
|
|
using SolutionVector = GetPropType<TypeTag, Properties::SolutionVector>;
|
|
|
|
using GridView = GetPropType<TypeTag, Properties::GridView>;
|
|
using Element = typename GridView::template Codim<0>::Entity;
|
|
|
|
static const unsigned dimWorld = GridView::dimensionworld;
|
|
static const unsigned numEq = getPropValue<TypeTag, Properties::NumEq>();
|
|
|
|
using CoordScalar = typename GridView::ctype;
|
|
using GlobalPosition = Dune::FieldVector<CoordScalar, dimWorld>;
|
|
|
|
// we don't allow copies of element contexts!
|
|
FvBaseElementContext(const FvBaseElementContext& ) = delete;
|
|
|
|
public:
|
|
/*!
|
|
* \brief The constructor.
|
|
*/
|
|
explicit FvBaseElementContext(const Simulator& simulator)
|
|
: gridView_(simulator.gridView())
|
|
, stencil_(gridView_, simulator.model().dofMapper() )
|
|
{
|
|
// remember the simulator object
|
|
simulatorPtr_ = &simulator;
|
|
enableStorageCache_ = EWOMS_GET_PARAM(TypeTag, bool, EnableStorageCache);
|
|
stashedDofIdx_ = -1;
|
|
focusDofIdx_ = -1;
|
|
}
|
|
|
|
static void *operator new(size_t size)
|
|
{ return aligned_alloc(alignof(FvBaseElementContext), size); }
|
|
|
|
static void operator delete(void *ptr)
|
|
{ aligned_free(ptr); }
|
|
|
|
/*!
|
|
* \brief Construct all volume and extensive quantities of an element
|
|
* from scratch.
|
|
*
|
|
* \param elem The DUNE Codim<0> entity for which the volume
|
|
* variables ought to be calculated
|
|
*/
|
|
void updateAll(const Element& elem)
|
|
{
|
|
asImp_().updateStencil(elem);
|
|
asImp_().updateAllIntensiveQuantities();
|
|
asImp_().updateAllExtensiveQuantities();
|
|
}
|
|
|
|
/*!
|
|
* \brief Compute the finite volume geometry for an element.
|
|
*
|
|
* \param elem The grid element for which the finite volume geometry ought to be
|
|
* computed.
|
|
*/
|
|
void updateStencil(const Element& elem)
|
|
{
|
|
// remember the current element
|
|
elemPtr_ = &elem;
|
|
|
|
// update the stencil. the center gradients are quite expensive to calculate and
|
|
// most models don't need them, so that we only do this if the model explicitly
|
|
// enables them
|
|
stencil_.update(elem);
|
|
|
|
// resize the arrays containing the flux and the volume variables
|
|
dofVars_.resize(stencil_.numDof());
|
|
extensiveQuantities_.resize(stencil_.numInteriorFaces());
|
|
}
|
|
|
|
/*!
|
|
* \brief Update the primary topological part of the stencil, but nothing else.
|
|
*
|
|
* \param elem The grid element for which the finite volume geometry ought to be
|
|
* computed.
|
|
*/
|
|
void updatePrimaryStencil(const Element& elem)
|
|
{
|
|
// remember the current element
|
|
elemPtr_ = &elem;
|
|
|
|
// update the finite element geometry
|
|
stencil_.updatePrimaryTopology(elem);
|
|
|
|
dofVars_.resize(stencil_.numPrimaryDof());
|
|
}
|
|
|
|
/*!
|
|
* \brief Update the topological part of the stencil, but nothing else.
|
|
*
|
|
* \param elem The grid element for which the finite volume geometry ought to be
|
|
* computed.
|
|
*/
|
|
void updateStencilTopology(const Element& elem)
|
|
{
|
|
// remember the current element
|
|
elemPtr_ = &elem;
|
|
|
|
// update the finite element geometry
|
|
stencil_.updateTopology(elem);
|
|
}
|
|
|
|
/*!
|
|
* \brief Compute the intensive quantities of all sub-control volumes of the current
|
|
* element for all time indices.
|
|
*/
|
|
void updateAllIntensiveQuantities()
|
|
{
|
|
if (!enableStorageCache_) {
|
|
// if the storage cache is disabled, we need to calculate the storage term
|
|
// from scratch, i.e. we need the intensive quantities of all of the history.
|
|
for (unsigned timeIdx = 0; timeIdx < timeDiscHistorySize; ++ timeIdx)
|
|
asImp_().updateIntensiveQuantities(timeIdx);
|
|
}
|
|
else
|
|
// if the storage cache is enabled, we only need to recalculate the storage
|
|
// term for the most recent point of history (i.e., for the current iterative
|
|
// solution)
|
|
asImp_().updateIntensiveQuantities(/*timeIdx=*/0);
|
|
}
|
|
|
|
/*!
|
|
* \brief Compute the intensive quantities of all sub-control volumes of the current
|
|
* element for a single time index.
|
|
*
|
|
* \param timeIdx The index of the solution vector used by the time discretization.
|
|
*/
|
|
void updateIntensiveQuantities(unsigned timeIdx)
|
|
{ updateIntensiveQuantities_(timeIdx, numDof(timeIdx)); }
|
|
|
|
/*!
|
|
* \brief Compute the intensive quantities of all sub-control volumes of the current
|
|
* element for a single time index.
|
|
*
|
|
* \param timeIdx The index of the solution vector used by the time discretization.
|
|
*/
|
|
void updatePrimaryIntensiveQuantities(unsigned timeIdx)
|
|
{ updateIntensiveQuantities_(timeIdx, numPrimaryDof(timeIdx)); }
|
|
|
|
/*!
|
|
* \brief Compute the intensive quantities of a single sub-control volume of the
|
|
* current element for a single time index.
|
|
*
|
|
* \param priVars The PrimaryVariables which should be used to calculate the
|
|
* intensive quantities.
|
|
* \param dofIdx The local index in the current element of the sub-control volume
|
|
* which should be updated.
|
|
* \param timeIdx The index of the solution vector used by the time discretization.
|
|
*/
|
|
void updateIntensiveQuantities(const PrimaryVariables& priVars, unsigned dofIdx, unsigned timeIdx)
|
|
{ asImp_().updateSingleIntQuants_(priVars, dofIdx, timeIdx); }
|
|
|
|
/*!
|
|
* \brief Compute the extensive quantities of all sub-control volume
|
|
* faces of the current element for all time indices.
|
|
*/
|
|
void updateAllExtensiveQuantities()
|
|
{ asImp_().updateExtensiveQuantities(/*timeIdx=*/0); }
|
|
|
|
/*!
|
|
* \brief Compute the extensive quantities of all sub-control volume
|
|
* faces of the current element for a single time index.
|
|
*
|
|
* \param timeIdx The index of the solution vector used by the
|
|
* time discretization.
|
|
*/
|
|
void updateExtensiveQuantities(unsigned timeIdx)
|
|
{
|
|
gradientCalculator_.prepare(/*context=*/asImp_(), timeIdx);
|
|
|
|
for (unsigned fluxIdx = 0; fluxIdx < numInteriorFaces(timeIdx); fluxIdx++) {
|
|
extensiveQuantities_[fluxIdx].update(/*context=*/asImp_(),
|
|
/*localIndex=*/fluxIdx,
|
|
timeIdx);
|
|
}
|
|
}
|
|
|
|
/*!
|
|
* \brief Sets the degree of freedom on which the simulator is currently "focused" on
|
|
*
|
|
* I.e., in the case of automatic differentiation, all derivatives are with regard to
|
|
* the primary variables of that degree of freedom. Only "primary" DOFs can be
|
|
* focused on.
|
|
*/
|
|
void setFocusDofIndex(unsigned dofIdx)
|
|
{ focusDofIdx_ = dofIdx; }
|
|
|
|
/*!
|
|
* \brief Returns the degree of freedom on which the simulator is currently "focused" on
|
|
*
|
|
* \copydetails setFocusDof()
|
|
*/
|
|
unsigned focusDofIndex() const
|
|
{ return focusDofIdx_; }
|
|
|
|
/*!
|
|
* \brief Returns the linearization type.
|
|
*
|
|
* \copydetails setLinearizationType()
|
|
*/
|
|
LinearizationType linearizationType() const
|
|
{ return this->model().linearizer().getLinearizationType(); }
|
|
|
|
/*!
|
|
* \brief Return a reference to the simulator.
|
|
*/
|
|
const Simulator& simulator() const
|
|
{ return *simulatorPtr_; }
|
|
|
|
/*!
|
|
* \brief Return a reference to the problem.
|
|
*/
|
|
const Problem& problem() const
|
|
{ return simulatorPtr_->problem(); }
|
|
|
|
/*!
|
|
* \brief Return a reference to the model.
|
|
*/
|
|
const Model& model() const
|
|
{ return simulatorPtr_->model(); }
|
|
|
|
/*!
|
|
* \brief Return a reference to the grid view.
|
|
*/
|
|
const GridView& gridView() const
|
|
{ return gridView_; }
|
|
|
|
/*!
|
|
* \brief Return the current element.
|
|
*/
|
|
const Element& element() const
|
|
{ return *elemPtr_; }
|
|
|
|
/*!
|
|
* \brief Return the number of sub-control volumes of the current element.
|
|
*/
|
|
size_t numDof(unsigned timeIdx) const
|
|
{ return stencil(timeIdx).numDof(); }
|
|
|
|
/*!
|
|
* \brief Return the number of primary degrees of freedom of the current element.
|
|
*/
|
|
size_t numPrimaryDof(unsigned timeIdx) const
|
|
{ return stencil(timeIdx).numPrimaryDof(); }
|
|
|
|
/*!
|
|
* \brief Return the number of non-boundary faces which need to be
|
|
* considered for the flux apporixmation.
|
|
*/
|
|
size_t numInteriorFaces(unsigned timeIdx) const
|
|
{ return stencil(timeIdx).numInteriorFaces(); }
|
|
|
|
/*!
|
|
* \brief Return the number of boundary faces which need to be
|
|
* considered for the flux apporixmation.
|
|
*/
|
|
size_t numBoundaryFaces(unsigned timeIdx) const
|
|
{ return stencil(timeIdx).numBoundaryFaces(); }
|
|
|
|
/*!
|
|
* \brief Return the current finite element geometry.
|
|
*
|
|
* \param timeIdx The index of the solution vector used by the
|
|
* time discretization.
|
|
*/
|
|
const Stencil& stencil(unsigned) const
|
|
{ return stencil_; }
|
|
|
|
/*!
|
|
* \brief Return the position of a local entities in global coordinates
|
|
*
|
|
* \param dofIdx The local index of the degree of freedom
|
|
* in the current element.
|
|
* \param timeIdx The index of the solution vector used by the
|
|
* time discretization.
|
|
*/
|
|
decltype(auto) pos(unsigned dofIdx, unsigned) const
|
|
{ return stencil_.subControlVolume(dofIdx).globalPos(); }
|
|
|
|
/*!
|
|
* \brief Return the global spatial index for a sub-control volume
|
|
*
|
|
* \param dofIdx The local index of the degree of freedom
|
|
* in the current element.
|
|
* \param timeIdx The index of the solution vector used by the
|
|
* time discretization.
|
|
*/
|
|
unsigned globalSpaceIndex(unsigned dofIdx, unsigned timeIdx) const
|
|
{ return stencil(timeIdx).globalSpaceIndex(dofIdx); }
|
|
|
|
|
|
/*!
|
|
* \brief Return the element-local volume associated with a degree of freedom
|
|
*
|
|
* In the case of the vertex-centered finite volume method, this is different from
|
|
* the total volume because a finite volume usually spans multiple elements...
|
|
*
|
|
* \param dofIdx The local index of the degree of freedom in the current element.
|
|
* \param timeIdx The index of the solution vector used by the time discretization.
|
|
*/
|
|
Scalar dofVolume(unsigned dofIdx, unsigned timeIdx) const
|
|
{ return stencil(timeIdx).subControlVolume(dofIdx).volume(); }
|
|
|
|
/*!
|
|
* \brief Return the total volume associated with a degree of freedom
|
|
*
|
|
* "Total" means the volume controlled by a degree of freedom disregarding the
|
|
* element. (For example in the vertex-centered finite volume method, a control
|
|
* volume typically encompasses parts of multiple elements.)
|
|
*
|
|
* \param dofIdx The local index of the degree of freedom in the current element.
|
|
* \param timeIdx The index of the solution vector used by the time discretization.
|
|
*/
|
|
Scalar dofTotalVolume(unsigned dofIdx, unsigned timeIdx) const
|
|
{ return model().dofTotalVolume(globalSpaceIndex(dofIdx, timeIdx)); }
|
|
|
|
/*!
|
|
* \brief Returns whether the current element is on the domain's
|
|
* boundary.
|
|
*/
|
|
bool onBoundary() const
|
|
{ return element().hasBoundaryIntersections(); }
|
|
|
|
/*!
|
|
* \brief Return a reference to the intensive quantities of a
|
|
* sub-control volume at a given time.
|
|
*
|
|
* If the time step index is not given, return the volume
|
|
* variables for the current time.
|
|
*
|
|
* \param dofIdx The local index of the degree of freedom in the current element.
|
|
* \param timeIdx The index of the solution vector used by the time discretization.
|
|
*/
|
|
const IntensiveQuantities& intensiveQuantities(unsigned dofIdx, unsigned timeIdx) const
|
|
{
|
|
#ifndef NDEBUG
|
|
assert(dofIdx < numDof(timeIdx));
|
|
|
|
if (enableStorageCache_ && timeIdx != 0 && problem().recycleFirstIterationStorage())
|
|
throw std::logic_error("If caching of the storage term is enabled, only the intensive quantities "
|
|
"for the most-recent substep (i.e. time index 0) are available!");
|
|
#endif
|
|
|
|
return dofVars_[dofIdx].intensiveQuantities[timeIdx];
|
|
}
|
|
|
|
/*!
|
|
* \brief Return the thermodynamic hint for a given local index.
|
|
*
|
|
* \sa Discretization::thermodynamicHint(int, int)
|
|
*
|
|
* \param dofIdx The local index of the degree of freedom in the current element.
|
|
* \param timeIdx The index of the solution vector used by the time discretization.
|
|
*/
|
|
const IntensiveQuantities *thermodynamicHint(unsigned dofIdx, unsigned timeIdx) const
|
|
{
|
|
assert(dofIdx < numDof(timeIdx));
|
|
return dofVars_[dofIdx].thermodynamicHint[timeIdx];
|
|
}
|
|
/*!
|
|
* \copydoc intensiveQuantities()
|
|
*/
|
|
IntensiveQuantities& intensiveQuantities(unsigned dofIdx, unsigned timeIdx)
|
|
{
|
|
assert(dofIdx < numDof(timeIdx));
|
|
return dofVars_[dofIdx].intensiveQuantities[timeIdx];
|
|
}
|
|
|
|
/*!
|
|
* \brief Return the primary variables for a given local index.
|
|
*
|
|
* \param dofIdx The local index of the degree of freedom
|
|
* in the current element.
|
|
* \param timeIdx The index of the solution vector used by the
|
|
* time discretization.
|
|
*/
|
|
const PrimaryVariables& primaryVars(unsigned dofIdx, unsigned timeIdx) const
|
|
{
|
|
assert(dofIdx < numDof(timeIdx));
|
|
return *dofVars_[dofIdx].priVars[timeIdx];
|
|
}
|
|
|
|
/*!
|
|
* \brief Returns true if no intensive quanties are stashed
|
|
*
|
|
* In most cases quantities are stashed only if a partial derivative is to be
|
|
* calculated via finite difference methods.
|
|
*/
|
|
bool haveStashedIntensiveQuantities() const
|
|
{ return stashedDofIdx_ != -1; }
|
|
|
|
/*!
|
|
* \brief Return the (local) index of the DOF for which the primary variables were
|
|
* stashed
|
|
*
|
|
* If none, then this returns -1.
|
|
*/
|
|
int stashedDofIdx() const
|
|
{ return stashedDofIdx_; }
|
|
|
|
/*!
|
|
* \brief Stash the intensive quantities for a degree of freedom on internal memory.
|
|
*
|
|
* \param dofIdx The local index of the degree of freedom in the current element.
|
|
*/
|
|
void stashIntensiveQuantities(unsigned dofIdx)
|
|
{
|
|
assert(dofIdx < numDof(/*timeIdx=*/0));
|
|
|
|
intensiveQuantitiesStashed_ = dofVars_[dofIdx].intensiveQuantities[/*timeIdx=*/0];
|
|
priVarsStashed_ = *dofVars_[dofIdx].priVars[/*timeIdx=*/0];
|
|
stashedDofIdx_ = static_cast<int>(dofIdx);
|
|
}
|
|
|
|
/*!
|
|
* \brief Restores the intensive quantities for a degree of freedom from internal memory.
|
|
*
|
|
* \param dofIdx The local index of the degree of freedom in the current element.
|
|
*/
|
|
void restoreIntensiveQuantities(unsigned dofIdx)
|
|
{
|
|
dofVars_[dofIdx].priVars[/*timeIdx=*/0] = &priVarsStashed_;
|
|
dofVars_[dofIdx].intensiveQuantities[/*timeIdx=*/0] = intensiveQuantitiesStashed_;
|
|
stashedDofIdx_ = -1;
|
|
}
|
|
|
|
/*!
|
|
* \brief Return a reference to the gradient calculation class of
|
|
* the chosen spatial discretization.
|
|
*/
|
|
const GradientCalculator& gradientCalculator() const
|
|
{ return gradientCalculator_; }
|
|
|
|
/*!
|
|
* \brief Return a reference to the extensive quantities of a
|
|
* sub-control volume face.
|
|
*
|
|
* \param fluxIdx The local index of the sub-control volume face for which the
|
|
* extensive quantities are requested
|
|
* \param timeIdx The index of the solution vector used by the time discretization.
|
|
*/
|
|
const ExtensiveQuantities& extensiveQuantities(unsigned fluxIdx, unsigned) const
|
|
{ return extensiveQuantities_[fluxIdx]; }
|
|
|
|
/*!
|
|
* \brief Returns true iff the cache for the storage term ought to be used for this context.
|
|
*
|
|
* If it is used, intensive quantities can only be accessed for the most recent time
|
|
* index. (time index 0.)
|
|
*/
|
|
bool enableStorageCache() const
|
|
{ return enableStorageCache_; }
|
|
|
|
/*!
|
|
* \brief Specifies if the cache for the storage term ought to be used for this context.
|
|
*/
|
|
void setEnableStorageCache(bool yesno)
|
|
{ enableStorageCache_ = yesno; }
|
|
|
|
private:
|
|
Implementation& asImp_()
|
|
{ return *static_cast<Implementation*>(this); }
|
|
|
|
const Implementation& asImp_() const
|
|
{ return *static_cast<const Implementation*>(this); }
|
|
|
|
protected:
|
|
/*!
|
|
* \brief Update the first 'n' intensive quantities objects from the primary variables.
|
|
*
|
|
* This method considers the intensive quantities cache.
|
|
*/
|
|
void updateIntensiveQuantities_(unsigned timeIdx, size_t numDof)
|
|
{
|
|
// update the intensive quantities for the whole history
|
|
const SolutionVector& globalSol = model().solution(timeIdx);
|
|
|
|
// update the non-gradient quantities
|
|
for (unsigned dofIdx = 0; dofIdx < numDof; dofIdx++) {
|
|
unsigned globalIdx = globalSpaceIndex(dofIdx, timeIdx);
|
|
const PrimaryVariables& dofSol = globalSol[globalIdx];
|
|
dofVars_[dofIdx].priVars[timeIdx] = &dofSol;
|
|
|
|
dofVars_[dofIdx].thermodynamicHint[timeIdx] =
|
|
model().thermodynamicHint(globalIdx, timeIdx);
|
|
|
|
const auto *cachedIntQuants = model().cachedIntensiveQuantities(globalIdx, timeIdx);
|
|
if (cachedIntQuants) {
|
|
dofVars_[dofIdx].intensiveQuantities[timeIdx] = *cachedIntQuants;
|
|
}
|
|
else {
|
|
updateSingleIntQuants_(dofSol, dofIdx, timeIdx);
|
|
model().updateCachedIntensiveQuantities(dofVars_[dofIdx].intensiveQuantities[timeIdx],
|
|
globalIdx,
|
|
timeIdx);
|
|
}
|
|
}
|
|
}
|
|
|
|
void updateSingleIntQuants_(const PrimaryVariables& priVars, unsigned dofIdx, unsigned timeIdx)
|
|
{
|
|
#ifndef NDEBUG
|
|
if (enableStorageCache_ && timeIdx != 0 && problem().recycleFirstIterationStorage())
|
|
throw std::logic_error("If caching of the storage term is enabled, only the intensive quantities "
|
|
"for the most-recent substep (i.e. time index 0) are available!");
|
|
#endif
|
|
|
|
dofVars_[dofIdx].priVars[timeIdx] = &priVars;
|
|
dofVars_[dofIdx].intensiveQuantities[timeIdx].update(/*context=*/asImp_(), dofIdx, timeIdx);
|
|
}
|
|
|
|
IntensiveQuantities intensiveQuantitiesStashed_;
|
|
PrimaryVariables priVarsStashed_;
|
|
|
|
GradientCalculator gradientCalculator_;
|
|
|
|
std::vector<DofStore_, aligned_allocator<DofStore_, alignof(DofStore_)> > dofVars_;
|
|
std::vector<ExtensiveQuantities, aligned_allocator<ExtensiveQuantities, alignof(ExtensiveQuantities)> > extensiveQuantities_;
|
|
|
|
const Simulator *simulatorPtr_;
|
|
const Element *elemPtr_;
|
|
const GridView gridView_;
|
|
Stencil stencil_;
|
|
|
|
int stashedDofIdx_;
|
|
int focusDofIdx_;
|
|
bool enableStorageCache_;
|
|
};
|
|
|
|
} // namespace Opm
|
|
|
|
#endif
|