52class FIBlackOilModel :
public BlackOilModel<TypeTag>
54 using ParentType = BlackOilModel<TypeTag>;
60 using Element =
typename GridView::template Codim<0>::Entity;
61 using ElementIterator =
typename GridView::template Codim<0>::Iterator;
70 static constexpr bool gridIsUnchanging =
71 std::is_same_v<GetPropType<TypeTag, Properties::Grid>, Dune::CpGrid>;
76 explicit FIBlackOilModel(Simulator& simulator)
77 : BlackOilModel<TypeTag>(simulator)
78 , element_chunks_(this->gridView_,
79 Dune::Partitions::all,
84 void invalidateAndUpdateIntensiveQuantities(
unsigned timeIdx)
const
86 this->invalidateIntensiveQuantitiesCache(timeIdx);
87 if constexpr (gridIsUnchanging) {
88 if constexpr (avoidElementContext) {
89 updateCachedIntQuants(timeIdx);
92 OPM_BEGIN_PARALLEL_TRY_CATCH();
94#pragma omp parallel for
96 for (
const auto& chunk : element_chunks_) {
97 ElementContext elemCtx(this->simulator_);
98 for (
const auto& elem : chunk) {
99 elemCtx.updatePrimaryStencil(elem);
100 elemCtx.updatePrimaryIntensiveQuantities(timeIdx);
103 OPM_END_PARALLEL_TRY_CATCH(
"invalidateAndUpdateIntensiveQuantities: state error",
104 this->simulator_.vanguard().grid().comm());
107 ElementContext elemCtx(this->simulator_);
108 for (
const auto& elem : elements(this->gridView_)) {
109 elemCtx.updatePrimaryStencil(elem);
110 elemCtx.updatePrimaryIntensiveQuantities(timeIdx);
115 void invalidateAndUpdateIntensiveQuantitiesOverlap(
unsigned timeIdx)
const
119 OPM_BEGIN_PARALLEL_TRY_CATCH()
124 ElementContext elemCtx(this->simulator_);
125 auto elemIt = threadedElemIt.beginParallel();
126 for (; !threadedElemIt.isFinished(elemIt); elemIt = threadedElemIt.increment()) {
127 if (elemIt->partitionType() != Dune::OverlapEntity) {
130 const Element& elem = *elemIt;
131 elemCtx.updatePrimaryStencil(elem);
133 const std::size_t numPrimaryDof = elemCtx.numPrimaryDof(timeIdx);
134 for (
unsigned dofIdx = 0; dofIdx < numPrimaryDof; ++dofIdx) {
135 const unsigned globalIndex = elemCtx.globalSpaceIndex(dofIdx, timeIdx);
136 this->setIntensiveQuantitiesCacheEntryValidity(globalIndex, timeIdx,
false);
139 elemCtx.updatePrimaryIntensiveQuantities(0);
142 OPM_END_PARALLEL_TRY_CATCH(
"InvalideAndUpdateIntensiveQuantitiesOverlap: state error",
143 this->simulator_.vanguard().grid().comm());
146 template <
class Gr
idSubDomain>
147 void invalidateAndUpdateIntensiveQuantities(
unsigned timeIdx,
const GridSubDomain& gridSubDomain)
const
150 using GridViewType =
decltype(gridSubDomain.view);
156 ElementContext elemCtx(this->simulator_);
157 auto elemIt = threadedElemIt.beginParallel();
158 for (; !threadedElemIt.isFinished(elemIt); elemIt = threadedElemIt.increment()) {
159 if (elemIt->partitionType() != Dune::InteriorEntity) {
162 const Element& elem = *elemIt;
163 elemCtx.updatePrimaryStencil(elem);
165 const std::size_t numPrimaryDof = elemCtx.numPrimaryDof(timeIdx);
166 for (
unsigned dofIdx = 0; dofIdx < numPrimaryDof; ++dofIdx) {
167 const unsigned globalIndex = elemCtx.globalSpaceIndex(dofIdx, timeIdx);
168 this->setIntensiveQuantitiesCacheEntryValidity(globalIndex, timeIdx,
false);
171 elemCtx.updatePrimaryIntensiveQuantities(0);
187 ParentType::updateFailed();
188 invalidateAndUpdateIntensiveQuantities(0);
192 const IntensiveQuantities& intensiveQuantities(
unsigned globalIdx,
unsigned timeIdx)
const
194 if (!this->enableIntensiveQuantityCache_) {
195 OPM_THROW(std::logic_error,
196 "Run without intensive quantites not enabled: "
197 "Use --enable-intensive-quantity=true");
200 assert(timeIdx < this->cachedIntensiveQuantityHistorySize());
201 const auto* intquant = this->cachedIntensiveQuantities(globalIdx, timeIdx);
203 OPM_THROW(std::logic_error,
"Intensive quantites need to be updated in code");
210 template <EclMultiplexerApproach ApproachArg>
211 using EMD = EclMultiplexerDispatch<ApproachArg>;
213 void updateCachedIntQuants(
const unsigned timeIdx)
const
216 switch (this->simulator_.problem().materialLawManager()->threePhaseApproach()) {
217 case EclMultiplexerApproach::Stone1:
218 updateCachedIntQuants1<EclMultiplexerDispatch<EclMultiplexerApproach::Stone1>>(timeIdx);
221 case EclMultiplexerApproach::Stone2:
222 updateCachedIntQuants1<EMD<EclMultiplexerApproach::Stone2>>(timeIdx);
225 case EclMultiplexerApproach::Default:
226 updateCachedIntQuants1<EMD<EclMultiplexerApproach::Default>>(timeIdx);
229 case EclMultiplexerApproach::TwoPhase:
230 updateCachedIntQuants1<EMD<EclMultiplexerApproach::TwoPhase>>(timeIdx);
233 case EclMultiplexerApproach::OnePhase:
234 updateCachedIntQuants1<EMD<EclMultiplexerApproach::OnePhase>>(timeIdx);
239 template <
class EMDArg>
240 void updateCachedIntQuants1(
const unsigned timeIdx)
const
243 if (this->simulator_.problem().materialLawManager()->satCurveIsAllPiecewiseLinear()) {
244 using PL = SatCurveMultiplexerDispatch<SatCurveMultiplexerApproach::PiecewiseLinear>;
245 updateCachedIntQuantsLoop<EMDArg, PL>(timeIdx);
248 updateCachedIntQuantsLoop<EMDArg>(timeIdx);
253 template <
class ...Args>
254 void updateCachedIntQuantsLoop(
const unsigned timeIdx)
const
256 const auto& elementMapper = this->simulator_.model().elementMapper();
258#pragma omp parallel for
260 for (
const auto& chunk : element_chunks_) {
261 for (
const auto& elem : chunk) {
262 this->
template updateSingleCachedIntQuantUnchecked<Args...>(elementMapper.index(elem), timeIdx);
267 template <
class ...Args>
268 void updateSingleCachedIntQuantUnchecked(
const unsigned globalIdx,
const unsigned timeIdx)
const
271 auto& intquant = this->intensiveQuantityCache_[timeIdx][globalIdx];
273 intquant.template update<Args...>(this->simulator_.problem(), this->solution(timeIdx)[globalIdx], globalIdx, timeIdx);
275 this->intensiveQuantityCacheUpToDate_[timeIdx][globalIdx] = 1;
278 ElementChunks<GridView, Dune::Partitions::All> element_chunks_;