TemperatureModel.hpp
Go to the documentation of this file.
1// -*- mode: C++; tab-width: 4; indent-tabs-mode: nil; c-basic-offset: 4 -*-
2// vi: set et ts=4 sw=4 sts=4:
3/*
4 This file is part of the Open Porous Media project (OPM).
5
6 OPM is free software: you can redistribute it and/or modify
7 it under the terms of the GNU General Public License as published by
8 the Free Software Foundation, either version 2 of the License, or
9 (at your option) any later version.
10
11 OPM is distributed in the hope that it will be useful,
12 but WITHOUT ANY WARRANTY; without even the implied warranty of
13 MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
14 GNU General Public License for more details.
15
16 You should have received a copy of the GNU General Public License
17 along with OPM. If not, see <http://www.gnu.org/licenses/>.
18
19 Consult the COPYING file in the top-level source directory of this
20 module for the precise wording of the license and the list of
21 copyright holders.
22*/
28#ifndef OPM_TEMPERATURE_MODEL_HPP
29#define OPM_TEMPERATURE_MODEL_HPP
30
31#include <opm/common/OpmLog/OpmLog.hpp>
32
35
40
41#include <algorithm>
42#include <cassert>
43#include <cmath>
44#include <cstddef>
45#include <string>
46#include <vector>
47
48namespace Opm::Properties {
49
50template<class TypeTag, class MyTypeTag>
53};
54
55} // namespace Opm::Properties
56
57namespace Opm {
58
59template<typename Scalar, typename IndexTraits> class WellState;
60
66template <class TypeTag, bool enableTempV = getPropValue<TypeTag, Properties::EnergyModuleType>() == EnergyModules::SequentialImplicitThermal >
67class TemperatureModel : public GenericTemperatureModel<GetPropType<TypeTag, Properties::Grid>,
68 GetPropType<TypeTag, Properties::GridView>,
69 GetPropType<TypeTag, Properties::DofMapper>,
70 GetPropType<TypeTag, Properties::Stencil>,
71 GetPropType<TypeTag, Properties::FluidSystem>,
72 GetPropType<TypeTag, Properties::Scalar>>
73{
89 using TemperatureEvaluation = DenseAd::Evaluation<Scalar,1>;
94 using IndexTraits = typename FluidSystem::IndexTraitsType;
96
97 using EnergyMatrix = typename BaseType::EnergyMatrix;
98 using EnergyVector = typename BaseType::EnergyVector;
99
100 enum { numEq = getPropValue<TypeTag, Properties::NumEq>() };
101 enum { numPhases = FluidSystem::numPhases };
102 enum { waterPhaseIdx = FluidSystem::waterPhaseIdx };
103 enum { oilPhaseIdx = FluidSystem::oilPhaseIdx };
104 enum { gasPhaseIdx = FluidSystem::gasPhaseIdx };
105
106public:
107 explicit TemperatureModel(Simulator& simulator)
108 : BaseType(simulator.vanguard().gridView(),
109 simulator.vanguard().eclState(),
110 simulator.vanguard().cartesianIndexMapper(),
111 simulator.model().dofMapper())
112 , simulator_(simulator)
113 {}
114
115 void init()
116 {
117 const unsigned int numCells = simulator_.model().numTotalDof();
118 this->doInit(numCells);
119
120 if (!this->doTemp())
121 return;
122
123 // we need the storage term at start of the iteration (timeIdx = 1)
124 storage1_.resize(numCells);
125
126 // set the initial temperature
127 for (unsigned globI = 0; globI < numCells; ++globI) {
128 this->temperature_[globI] = simulator_.problem().initialFluidState(globI).temperature(0);
129 }
130 // keep a copy of the intensive quantities to simplify the update during
131 // the newton iterations
132 intQuants_.resize(numCells);
133
134 // find and store the overlap cells
135 const auto& elemMapper = simulator_.model().elementMapper();
137 }
138
140 {
141 if (!this->doTemp()) {
142 return;
143 }
144
145 // We copy the intensive quantities here to make it possible to update them
146 const unsigned int numCells = simulator_.model().numTotalDof();
147 for (unsigned globI = 0; globI < numCells; ++globI) {
148 intQuants_[globI] = simulator_.model().intensiveQuantities(globI, /*timeIdx*/ 0);
149 intQuants_[globI].updateTemperature_(simulator_.problem(), globI, /*timeIdx*/ 0);
150 intQuants_[globI].updateEnergyQuantities_(simulator_.problem(), globI, /*timeIdx*/ 0);
151 }
153
154 const int nw = simulator_.problem().wellModel().wellState().numWells();
155 this->energy_rates_.resize(nw, 0.0);
156 }
157
161 void endTimeStep(WellStateType& wellState)
162 {
163 if (!this->doTemp()) {
164 return;
165 }
166
167 // We copy the intensive quantities here to make it possible to update them
168 const unsigned int numCells = simulator_.model().numTotalDof();
169 for (unsigned globI = 0; globI < numCells; ++globI) {
170 intQuants_[globI] = simulator_.model().intensiveQuantities(globI, /*timeIdx*/ 0);
171 intQuants_[globI].updateTemperature_(simulator_.problem(), globI, /*timeIdx*/ 0);
172 intQuants_[globI].updateEnergyQuantities_(simulator_.problem(), globI, /*timeIdx*/ 0);
173 }
175
176 // update energy_rates
177 const int nw = wellState.numWells();
178 for (auto wellID = 0*nw; wellID < nw; ++wellID) {
179 auto& ws = wellState.well(wellID);
180 ws.energy_rate = this->energy_rates_[wellID];
181 }
182 }
183
188 template <class Restarter>
189 void serialize(Restarter&)
190 { /* not implemented */ }
191
198 template <class Restarter>
199 void deserialize(Restarter&)
200 { /* not implemented */ }
201
202protected:
204 {
205 // we need the storage term at start of the iteration (timeIdx = 1)
206 const unsigned int numCells = simulator_.model().numTotalDof();
207 #ifdef _OPENMP
208 #pragma omp parallel for
209 #endif
210 for (unsigned globI = 0; globI < numCells; ++globI) {
211 Scalar storage = 0.0;
212 computeStorageTerm(globI, storage);
213 storage1_[globI] = storage;
214 }
215 }
216
218 {
219 const int max_iter = 20;
220 const int min_iter = 1;
221 bool is_converged = false;
222 // solve using Newton
223 for (int iter = 0; iter < max_iter; ++iter) {
225 if (iter >= min_iter && converged(iter)) {
226 is_converged = true;
227 break;
228 }
230 }
231 if (!is_converged) {
232 const auto msg = fmt::format("Temperature model (TEMP): Newton did not converge after {} iterations. \n"
233 "The Simulator will continue to the next step with an unconverged solution.",max_iter);
234 OpmLog::debug(msg);
235 }
236 }
237
239 {
240 const unsigned int numCells = simulator_.model().numTotalDof();
241 EnergyVector dx(numCells);
242 bool conv = this->linearSolve_(*this->energyMatrix_, dx, this->energyVector_);
243 if (!conv) {
244 if (simulator_.gridView().comm().rank() == 0) {
245 OpmLog::warning("Temp model: Linear solver did not converge. Temperature values not updated.");
246 }
247 }
248 else {
249 for (unsigned globI = 0; globI < numCells; ++globI) {
250 this->temperature_[globI] -= std::clamp(dx[globI][0], -this->maxTempChange_, this->maxTempChange_);
251 intQuants_[globI].updateTemperature_(simulator_.problem(), globI, /*timeIdx*/ 0);
252 intQuants_[globI].updateEnergyQuantities_(simulator_.problem(), globI, /*timeIdx*/ 0);
253 }
254 }
255 }
256
257 bool converged(const int iter)
258 {
259 Scalar dt = simulator_.timeStepSize();
260 Scalar maxNorm = 0.0;
261 Scalar sumNorm = 0.0;
262 const auto tolerance_cnv_energy_strict = Parameters::Get<Parameters::ToleranceCnvEnergy<Scalar>>();
263 const auto& elemMapper = simulator_.model().elementMapper();
264 const IsNumericalAquiferCell isNumericalAquiferCell(simulator_.gridView().grid());
265 Scalar sum_pv = 0.0;
266 Scalar sum_pv_not_converged = 0.0;
267 for (const auto& elem : elements(simulator_.gridView(), Dune::Partitions::interior)) {
268 unsigned globI = elemMapper.index(elem);
269 const auto pvValue = simulator_.problem().referencePorosity(globI, /*timeIdx=*/0)
270 * simulator_.model().dofTotalVolume(globI);
271
272 const Scalar scaled_norm = dt * std::abs(this->energyVector_[globI])/ pvValue;
273 maxNorm = max(maxNorm, scaled_norm);
274 sumNorm += scaled_norm;
275 if (!isNumericalAquiferCell(elem)) {
276 if (scaled_norm > tolerance_cnv_energy_strict) {
277 sum_pv_not_converged += pvValue;
278 }
279 sum_pv += pvValue;
280 }
281 }
282 maxNorm = simulator_.gridView().comm().max(maxNorm);
283 sumNorm = simulator_.gridView().comm().sum(sumNorm);
284 sum_pv = simulator_.gridView().comm().sum(sum_pv);
285 sumNorm /= sum_pv;
286
287 // Use relaxed tolerance if the fraction of unconverged cells porevolume is less than relaxed_max_pv_fraction
288 sum_pv_not_converged = simulator_.gridView().comm().sum(sum_pv_not_converged);
289 Scalar relaxed_max_pv_fraction = Parameters::Get<Parameters::RelaxedMaxPvFraction<Scalar>>();
290 const bool relax = (sum_pv_not_converged / sum_pv) < relaxed_max_pv_fraction;
291 const auto tolerance_energy_balance = relax? Parameters::Get<Parameters::ToleranceEnergyBalanceRelaxed<Scalar>>():
293 const bool tolerance_cnv_energy = relax? Parameters::Get<Parameters::ToleranceCnvEnergyRelaxed<Scalar>>():
294 tolerance_cnv_energy_strict;
295
296 const auto msg = fmt::format("Temperature model (TEMP): Newton iter {}: "
297 "CNV(E): {:.1e}, EB: {:.1e}",
298 iter, maxNorm, sumNorm);
299 OpmLog::debug(msg);
300 if (maxNorm < tolerance_cnv_energy && sumNorm < tolerance_energy_balance) {
301 const auto msg2 = fmt::format("Temperature model (TEMP): Newton converged after {} iterations"
302 , iter);
303 OpmLog::debug(msg2);
304 return true;
305 }
306 return false;
307 }
308
309 template< class LhsEval>
310 void computeStorageTerm(unsigned globI, LhsEval& storage)
311 {
312 const auto& intQuants = intQuants_[globI];
313 const auto& poro = decay<LhsEval>(intQuants.porosity());
314 // accumulate the internal energy of the fluids
315 const auto& fs = intQuants.fluidState();
316 for (unsigned phaseIdx = 0; phaseIdx < numPhases; ++ phaseIdx) {
317 if (!FluidSystem::phaseIsActive(phaseIdx)) {
318 continue;
319 }
320
321 const auto& u = decay<LhsEval>(fs.internalEnergy(phaseIdx));
322 const auto& S = decay<LhsEval>(fs.saturation(phaseIdx));
323 const auto& rho = decay<LhsEval>(fs.density(phaseIdx));
324
325 storage += poro*S*u*rho;
326 }
327
328 // add the internal energy of the rock
329 const Scalar rockFraction = intQuants.rockFraction();
330 const auto& uRock = decay<LhsEval>(intQuants.rockInternalEnergy());
331 storage += rockFraction*uRock;
332 storage*= getPropValue<TypeTag, Properties::BlackOilEnergyScalingFactor>();
333 }
334
335 template < class ResidualNBInfo>
336 void computeFluxTerm(unsigned globI, unsigned globJ,
337 const ResidualNBInfo& res_nbinfo,
338 Evaluation& flux)
339 {
340 const IntensiveQuantities& intQuantsIn = intQuants_[globI];
341 const IntensiveQuantities& intQuantsEx = intQuants_[globJ];
342 RateVector tmp(0.0); //not used
343 RateVector darcyFlux(0.0);
344 LocalResidual::computeFlux(tmp, darcyFlux, globI, globJ, intQuantsIn, intQuantsEx,
345 res_nbinfo, simulator_.problem().moduleParams());
346 for (unsigned phaseIdx = 0; phaseIdx < numPhases; ++ phaseIdx) {
347 if (!FluidSystem::phaseIsActive(phaseIdx)) {
348 continue;
349 }
350
351 const unsigned activeCompIdx =
352 FluidSystem::canonicalToActiveCompIdx(FluidSystem::solventComponentIndex(phaseIdx));
353
354 bool inIsUp = darcyFlux[activeCompIdx] > 0;
355 const IntensiveQuantities& up = inIsUp ? intQuantsIn : intQuantsEx;
356 const auto& fs = up.fluidState();
357 if (inIsUp) {
358 flux += fs.enthalpy(phaseIdx)
359 * fs.density(phaseIdx)
360 * darcyFlux[activeCompIdx];
361 }
362 else {
363 flux += getValue(fs.enthalpy(phaseIdx))
364 * getValue(fs.density(phaseIdx))
365 * getValue(darcyFlux[activeCompIdx]);
366 }
367 }
368 flux *= getPropValue<TypeTag, Properties::BlackOilEnergyScalingFactor>();
369 }
370
371 template < class ResidualNBInfo>
372 void computeHeatFluxTerm(unsigned globI, unsigned globJ,
373 const ResidualNBInfo& res_nbinfo,
374 Evaluation& heatFlux)
375 {
376 const IntensiveQuantities& intQuantsIn = intQuants_[globI];
377 const IntensiveQuantities& intQuantsEx = intQuants_[globJ];
378 const Scalar inAlpha = simulator_.problem().thermalHalfTransmissibility(globI, globJ);
379 const Scalar outAlpha = simulator_.problem().thermalHalfTransmissibility(globJ, globI);
380 short interiorDofIdx = 0; // NB
381 short exteriorDofIdx = 1; // NB
382 EnergyModule::ExtensiveQuantities::updateEnergy(heatFlux,
383 interiorDofIdx, // focusDofIndex,
384 interiorDofIdx,
385 exteriorDofIdx,
386 intQuantsIn,
387 intQuantsEx,
388 intQuantsIn.fluidState(),
389 intQuantsEx.fluidState(),
390 inAlpha,
391 outAlpha,
392 res_nbinfo.faceArea);
393 heatFlux *= getPropValue<TypeTag, Properties::BlackOilEnergyScalingFactor>()*res_nbinfo.faceArea;
394 }
395
397 {
398 this->energyVector_ = 0.0;
399 (*this->energyMatrix_) = 0.0;
400 Scalar dt = simulator_.timeStepSize();
401 const unsigned int numCells = simulator_.model().numTotalDof();
402#ifdef _OPENMP
403#pragma omp parallel for
404#endif
405 for (unsigned globI = 0; globI < numCells; ++globI) {
406 Scalar volume = simulator_.model().dofTotalVolume(globI);
407 Scalar storefac = volume / dt;
408 Evaluation storage = 0.0;
409 computeStorageTerm(globI, storage);
410 this->energyVector_[globI] += storefac * ( getValue(storage) - storage1_[globI] );
411 (*this->energyMatrix_)[globI][globI][0][0] += storefac * storage.derivative(Indices::temperatureIdx);
412 }
413
414 const auto& neighborInfo = simulator_.model().linearizer().getNeighborInfo();
415#ifdef _OPENMP
416#pragma omp parallel for
417#endif
418 for (unsigned globI = 0; globI < numCells; ++globI) {
419 const auto& nbInfos = neighborInfo[globI];
420 for (const auto& nbInfo : nbInfos) {
421 unsigned globJ = nbInfo.neighbor;
422 assert(globJ != globI);
423
424 // compute convective flux
425 Evaluation flux = 0.0;
426 computeFluxTerm(globI, globJ, nbInfo.res_nbinfo, flux);
427 this->energyVector_[globI] += getValue(flux);
428 (*this->energyMatrix_)[globI][globI][0][0] += flux.derivative(Indices::temperatureIdx);
429 (*this->energyMatrix_)[globJ][globI][0][0] -= flux.derivative(Indices::temperatureIdx);
430
431 // compute conductive flux
432 Evaluation heatFlux = 0.0;
433 computeHeatFluxTerm(globI, globJ, nbInfo.res_nbinfo, heatFlux);
434 this->energyVector_[globI] += getValue(heatFlux);
435 (*this->energyMatrix_)[globI][globI][0][0] += heatFlux.derivative(Indices::temperatureIdx);
436 (*this->energyMatrix_)[globJ][globI][0][0] -= heatFlux.derivative(Indices::temperatureIdx);
437 }
438 }
439
440 // Well terms
441 const auto& wellPtrs = simulator_.problem().wellModel().localNonshutWells();
442 for (const auto& wellPtr : wellPtrs) {
443 this->assembleEquationWell(*wellPtr);
444 }
445
446 const auto& problem = simulator_.problem();
447
448 bool enableDriftCompensation = Parameters::Get<Parameters::EnableDriftCompensationTemp>();
449 if (enableDriftCompensation) {
450 for (unsigned globalDofIdx = 0; globalDofIdx < numCells; ++globalDofIdx) {
451 auto dofDriftRate = problem.drift()[globalDofIdx]/dt;
452 const auto& fs = intQuants_[globalDofIdx].fluidState();
453 for (unsigned phaseIdx = 0; phaseIdx < numPhases; ++ phaseIdx) {
454 const unsigned activeCompIdx =
455 FluidSystem::canonicalToActiveCompIdx(FluidSystem::solventComponentIndex(phaseIdx));
456 auto drift_hrate = dofDriftRate[activeCompIdx]*getValue(fs.enthalpy(phaseIdx)) * getValue(fs.density(phaseIdx)) / getValue(fs.invB(phaseIdx));
457 this->energyVector_[globalDofIdx] -= drift_hrate*getPropValue<TypeTag, Properties::BlackOilEnergyScalingFactor>();
458 }
459 }
460 }
461
462 if (simulator_.gridView().comm().size() > 1) {
463 // Set dirichlet conditions for overlapping cells
464 // loop over precalculated overlap rows and columns
465 for (const auto row : overlapRows_) {
466 // Zero out row.
467 (*this->energyMatrix_)[row] = 0.0;
468
469 //diagonal block set to diag(1.0).
470 (*this->energyMatrix_)[row][row][0][0] = 1.0;
471 }
472 }
473 }
474
475 template<class Well>
476 void assembleEquationWell(const Well& well)
477 {
478 const auto& eclWell = well.wellEcl();
479 std::size_t well_index = simulator_.problem().wellModel().wellState().index(well.name()).value();
480 const auto& ws = simulator_.problem().wellModel().wellState().well(well_index);
481 this->energy_rates_[well_index] = 0.0;
482 for (std::size_t i = 0; i < ws.perf_data.size(); ++i) {
483 const auto globI = ws.perf_data.cell_index[i];
484 auto fs = intQuants_[globI].fluidState(); //copy to make it possible to change the temp in the injector
485 for (unsigned phaseIdx = 0; phaseIdx < numPhases; ++ phaseIdx) {
486 if (!FluidSystem::phaseIsActive(phaseIdx)) {
487 continue;
488 }
489
490 Evaluation rate = well.volumetricSurfaceRateForConnection(globI, phaseIdx);
491 if (rate > 0 && eclWell.isInjector()) {
492 fs.setTemperature(eclWell.inj_temperature());
493 const auto& rho = FluidSystem::density(fs, phaseIdx, fs.pvtRegionIndex());
494 fs.setDensity(phaseIdx, rho);
495 const auto& h = FluidSystem::enthalpy(fs, phaseIdx, fs.pvtRegionIndex());
496 fs.setEnthalpy(phaseIdx, h);
497 rate *= getValue(fs.enthalpy(phaseIdx)) * getValue(fs.density(phaseIdx)) / getValue(fs.invB(phaseIdx));
498 } else {
499 const Evaluation d = 1.0 - fs.Rv() * fs.Rs();
500 if (phaseIdx == gasPhaseIdx && d > 0) {
501 const auto& oilrate = well.volumetricSurfaceRateForConnection(globI, oilPhaseIdx);
502 rate -= oilrate * getValue(fs.Rs());
503 rate /= d;
504 }
505 if (phaseIdx == oilPhaseIdx && d > 0) {
506 const auto& gasrate = well.volumetricSurfaceRateForConnection(globI, gasPhaseIdx);
507 rate -= gasrate * getValue(fs.Rv());
508 rate /= d;
509 }
510 rate *= fs.enthalpy(phaseIdx) * getValue(fs.density(phaseIdx)) / getValue(fs.invB(phaseIdx));
511 }
512 this->energy_rates_[well_index] += getValue(rate);
513 rate *= getPropValue<TypeTag, Properties::BlackOilEnergyScalingFactor>();
514 this->energyVector_[globI] -= getValue(rate);
515 (*this->energyMatrix_)[globI][globI][0][0] -= rate.derivative(Indices::temperatureIdx);
516 }
517 }
518 }
519
520 const Simulator& simulator_;
521 EnergyVector storage1_;
522 std::vector<IntensiveQuantities> intQuants_;
523 std::vector<int> overlapRows_;
524 std::vector<int> interiorRows_;
525};
526
527// need for the old linearizer
528template <class TypeTag>
529class TemperatureModel<TypeTag, false>
530{
534
535public:
537 { }
538
543 template <class Restarter>
544 void serialize(Restarter&)
545 { /* not implemented */ }
546
553 template <class Restarter>
554 void deserialize(Restarter&)
555 { /* not implemented */ }
556
557 void init() {}
559 const Scalar temperature(size_t /*globalIdx*/) const
560 {
561 return 273.15; // return 0C to make the compiler happy
562 }
563};
564
565} // namespace Opm
566
567#endif // OPM_TEMPERATURE_MODEL_HPP
Contains the high level supplements required to extend the black oil model by energy.
Definition: blackoilenergymodules.hh:60
Definition: GenericTemperatureModel.hpp:52
void beginTimeStep()
Definition: TemperatureModel.hpp:558
void init()
Definition: TemperatureModel.hpp:557
const Scalar temperature(size_t) const
Definition: TemperatureModel.hpp:559
void deserialize(Restarter &)
This method restores the complete state of the temperature from disk.
Definition: TemperatureModel.hpp:554
void serialize(Restarter &)
This method writes the complete state of all temperature to the hard disk.
Definition: TemperatureModel.hpp:544
TemperatureModel(Simulator &)
Definition: TemperatureModel.hpp:536
A class which handles sequential implicit solution of the energy equation as specified in by TEMP.
Definition: TemperatureModel.hpp:73
void serialize(Restarter &)
This method writes the complete state of all temperature to the hard disk.
Definition: TemperatureModel.hpp:189
void assembleEquationWell(const Well &well)
Definition: TemperatureModel.hpp:476
std::vector< int > interiorRows_
Definition: TemperatureModel.hpp:524
EnergyVector storage1_
Definition: TemperatureModel.hpp:521
bool converged(const int iter)
Definition: TemperatureModel.hpp:257
void computeHeatFluxTerm(unsigned globI, unsigned globJ, const ResidualNBInfo &res_nbinfo, Evaluation &heatFlux)
Definition: TemperatureModel.hpp:372
void computeStorageTerm(unsigned globI, LhsEval &storage)
Definition: TemperatureModel.hpp:310
void deserialize(Restarter &)
This method restores the complete state of the temperature from disk.
Definition: TemperatureModel.hpp:199
void endTimeStep(WellStateType &wellState)
Informs the temperature model that a time step has just been finished.
Definition: TemperatureModel.hpp:161
const Simulator & simulator_
Definition: TemperatureModel.hpp:520
void beginTimeStep()
Definition: TemperatureModel.hpp:139
void advanceTemperatureFields()
Definition: TemperatureModel.hpp:217
void updateStorageCache()
Definition: TemperatureModel.hpp:203
void assembleEquations()
Definition: TemperatureModel.hpp:396
void solveAndUpdate()
Definition: TemperatureModel.hpp:238
std::vector< IntensiveQuantities > intQuants_
Definition: TemperatureModel.hpp:522
void computeFluxTerm(unsigned globI, unsigned globJ, const ResidualNBInfo &res_nbinfo, Evaluation &flux)
Definition: TemperatureModel.hpp:336
std::vector< int > overlapRows_
Definition: TemperatureModel.hpp:523
TemperatureModel(Simulator &simulator)
Definition: TemperatureModel.hpp:107
void init()
Definition: TemperatureModel.hpp:115
Definition: WellState.hpp:66
int numWells() const
Definition: WellState.hpp:99
const SingleWellState< Scalar, IndexTraits > & well(std::size_t well_index) const
Definition: WellState.hpp:290
Provides data handles for parallel communication which operate on DOFs.
auto Get(bool errorIfNotRegistered=true)
Retrieve a runtime parameter.
Definition: parametersystem.hpp:187
Definition: blackoilmodel.hh:80
void findOverlapAndInterior(const Grid &grid, const Mapper &mapper, std::vector< int > &overlapRows, std::vector< int > &interiorRows)
Find the rows corresponding to overlap cells.
Definition: findOverlapRowsAndColumns.hpp:92
Definition: blackoilbioeffectsmodules.hh:43
typename Properties::Detail::GetPropImpl< TypeTag, Property >::type::type GetPropType
get the type alias defined in the property (equivalent to old macro GET_PROP_TYPE(....
Definition: propertysystem.hh:233
The Opm property system, traits with inheritance.
Definition: AquiferGridUtils.hpp:35
Definition: BlackoilModelParameters.hpp:61
Definition: TemperatureModel.hpp:51
a tag to mark properties as undefined
Definition: propertysystem.hh:38