OutputBlackoilModule.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*/
27#ifndef OPM_OUTPUT_BLACK_OIL_MODULE_HPP
28#define OPM_OUTPUT_BLACK_OIL_MODULE_HPP
29
30#include <dune/common/fvector.hh>
31
33
34#include <opm/common/Exceptions.hpp>
35#include <opm/common/TimingMacros.hpp>
36#include <opm/common/OpmLog/OpmLog.hpp>
37
38#include <opm/input/eclipse/EclipseState/SummaryConfig/SummaryConfig.hpp>
39
40#include <opm/material/common/Valgrind.hpp>
41#include <opm/material/fluidmatrixinteractions/EclEpsScalingPoints.hpp>
42#include <opm/material/fluidstates/BlackOilFluidState.hpp>
43#include <opm/material/fluidsystems/BlackOilFluidSystem.hpp>
44
49
50#include <opm/output/data/Cells.hpp>
51#include <opm/output/eclipse/EclipseIO.hpp>
52#include <opm/output/eclipse/Inplace.hpp>
53
56
57#include <algorithm>
58#include <array>
59#include <cassert>
60#include <cstddef>
61#include <functional>
62#include <stdexcept>
63#include <string>
64#include <type_traits>
65#include <utility>
66#include <vector>
67
68namespace Opm::Parameters {
69
70struct ForceDisableFluidInPlaceOutput { static constexpr bool value = false; };
71struct ForceDisableResvFluidInPlaceOutput { static constexpr bool value = false; };
72
73} // namespace Opm::Parameters
74
75namespace Opm
76{
77
78// forward declaration
79template <class TypeTag>
81
88template <class TypeTag>
89class OutputBlackOilModule : public GenericOutputBlackoilModule<GetPropType<TypeTag, Properties::FluidSystem>>
90{
101 using Element = typename GridView::template Codim<0>::Entity;
102 using ElementIterator = typename GridView::template Codim<0>::Iterator;
105 using Dir = FaceDir::DirEnum;
106
107 enum { conti0EqIdx = Indices::conti0EqIdx };
108 enum { numPhases = FluidSystem::numPhases };
109 enum { oilPhaseIdx = FluidSystem::oilPhaseIdx };
110 enum { gasPhaseIdx = FluidSystem::gasPhaseIdx };
111 enum { waterPhaseIdx = FluidSystem::waterPhaseIdx };
112 enum { gasCompIdx = FluidSystem::gasCompIdx };
113 enum { oilCompIdx = FluidSystem::oilCompIdx };
114 enum { waterCompIdx = FluidSystem::waterCompIdx };
115 enum { enableEnergy = getPropValue<TypeTag, Properties::EnableEnergy>() };
116
117public:
118 template <class CollectDataToIORankType>
119 OutputBlackOilModule(const Simulator& simulator,
120 const SummaryConfig& smryCfg,
121 const CollectDataToIORankType& collectToIORank)
122 : BaseType(simulator.vanguard().eclState(),
123 simulator.vanguard().schedule(),
124 smryCfg,
125 simulator.vanguard().summaryState(),
127 getPropValue<TypeTag, Properties::EnableEnergy>(),
128 getPropValue<TypeTag, Properties::EnableTemperature>(),
129 getPropValue<TypeTag, Properties::EnableMech>(),
130 getPropValue<TypeTag, Properties::EnableSolvent>(),
131 getPropValue<TypeTag, Properties::EnablePolymer>(),
132 getPropValue<TypeTag, Properties::EnableFoam>(),
133 getPropValue<TypeTag, Properties::EnableBrine>(),
134 getPropValue<TypeTag, Properties::EnableSaltPrecipitation>(),
135 getPropValue<TypeTag, Properties::EnableExtbo>(),
136 getPropValue<TypeTag, Properties::EnableMICP>())
137 , simulator_(simulator)
138 {
139 for (auto& region_pair : this->regions_) {
140 this->createLocalRegion_(region_pair.second);
141 }
142
143 auto isCartIdxOnThisRank = [&collectToIORank](const int idx) {
144 return collectToIORank.isCartIdxOnThisRank(idx);
145 };
146
147 this->setupBlockData(isCartIdxOnThisRank);
148
150 Parameters::Get<Parameters::ForceDisableFluidInPlaceOutput>();
151
153 Parameters::Get<Parameters::ForceDisableResvFluidInPlaceOutput>();
154
155 if (! Parameters::Get<Parameters::OwnerCellsFirst>()) {
156 const std::string msg = "The output code does not support --owner-cells-first=false.";
157 if (collectToIORank.isIORank()) {
158 OpmLog::error(msg);
159 }
160 OPM_THROW_NOLOG(std::runtime_error, msg);
161 }
162
163 if (smryCfg.match("[FB]PP[OGW]") || smryCfg.match("RPP[OGW]*")) {
164 auto rset = this->eclState_.fieldProps().fip_regions();
165 rset.push_back("PVTNUM");
166
167 // Note: We explicitly use decltype(auto) here because the
168 // default scheme (-> auto) will deduce an undesirable type. We
169 // need the "reference to vector" semantics in this instance.
171 .emplace(this->simulator_.gridView().comm(),
172 FluidSystem::numPhases, rset,
173 [fp = std::cref(this->eclState_.fieldProps())]
174 (const std::string& rsetName) -> decltype(auto)
175 { return fp.get().get_int(rsetName); });
176 }
177 }
178
182 static void registerParameters()
183 {
184 Parameters::Register<Parameters::ForceDisableFluidInPlaceOutput>
185 ("Do not print fluid-in-place values after each report step "
186 "even if requested by the deck.");
187 Parameters::Register<Parameters::ForceDisableResvFluidInPlaceOutput>
188 ("Do not print reservoir volumes values after each report step "
189 "even if requested by the deck.");
190 }
191
196 void
197 allocBuffers(const unsigned bufferSize,
198 const unsigned reportStepNum,
199 const bool substep,
200 const bool log,
201 const bool isRestart)
202 {
203 if (! std::is_same<Discretization, EcfvDiscretization<TypeTag>>::value) {
204 return;
205 }
206
207 const auto& problem = this->simulator_.problem();
208
209 this->doAllocBuffers(bufferSize,
210 reportStepNum,
211 substep,
212 log,
213 isRestart,
214 problem.vapparsActive(std::max(simulator_.episodeIndex(), 0)),
215 problem.materialLawManager()->enablePCHysteresis(),
216 problem.materialLawManager()->enableNonWettingHysteresis(),
217 problem.materialLawManager()->enableWettingHysteresis(),
218 problem.tracerModel().numTracers(),
219 problem.tracerModel().enableSolTracers(),
220 problem.eclWriter()->getOutputNnc().size());
221 }
222
223 void processElementMech(const ElementContext& elemCtx)
224 {
225 if constexpr (getPropValue<TypeTag, Properties::EnableMech>()) {
226 const auto& problem = elemCtx.simulator().problem();
227 const auto& model = problem.geoMechModel();
228 for (unsigned dofIdx = 0; dofIdx < elemCtx.numPrimaryDof(/*timeIdx=*/0); ++dofIdx) {
229 unsigned globalDofIdx = elemCtx.globalSpaceIndex(dofIdx, /*timeIdx=*/0);
230 if (!this->mechPotentialForce_.empty()) {
231 // assume all mechanical things should be written
232 this->mechPotentialForce_[globalDofIdx] = model.mechPotentialForce(globalDofIdx);
233 this->mechPotentialPressForce_[globalDofIdx] = model.mechPotentialPressForce(globalDofIdx);
234 this->mechPotentialTempForce_[globalDofIdx] = model.mechPotentialTempForce(globalDofIdx);
235
236 this->dispX_[globalDofIdx] = model.disp(globalDofIdx, 0);
237 this->dispY_[globalDofIdx] = model.disp(globalDofIdx, 1);
238 this->dispZ_[globalDofIdx] = model.disp(globalDofIdx, 2);
239 this->stressXX_[globalDofIdx] = model.stress(globalDofIdx, 0);
240 this->stressYY_[globalDofIdx] = model.stress(globalDofIdx, 1);
241 this->stressZZ_[globalDofIdx] = model.stress(globalDofIdx, 2);
242 // voight notation
243 this->stressXY_[globalDofIdx] = model.stress(globalDofIdx, 5);
244 this->stressXZ_[globalDofIdx] = model.stress(globalDofIdx, 4);
245 this->stressYZ_[globalDofIdx] = model.stress(globalDofIdx, 3);
246
247 this->strainXX_[globalDofIdx] = model.strain(globalDofIdx, 0);
248 this->strainYY_[globalDofIdx] = model.strain(globalDofIdx, 1);
249 this->strainZZ_[globalDofIdx] = model.strain(globalDofIdx, 2);
250 // voight notation
251 this->strainXY_[globalDofIdx] = model.strain(globalDofIdx, 5);
252 this->strainXZ_[globalDofIdx] = model.strain(globalDofIdx, 4);
253 this->strainYZ_[globalDofIdx] = model.strain(globalDofIdx, 3);
254
255
256 this->delstressXX_[globalDofIdx] = model.delstress(globalDofIdx, 0);
257 this->delstressYY_[globalDofIdx] = model.delstress(globalDofIdx, 1);
258 this->delstressZZ_[globalDofIdx] = model.delstress(globalDofIdx, 2);
259 // voight notation
260 this->delstressXY_[globalDofIdx] = model.delstress(globalDofIdx, 5);
261 this->delstressXZ_[globalDofIdx] = model.delstress(globalDofIdx, 4);
262 this->delstressYZ_[globalDofIdx] = model.delstress(globalDofIdx, 3);
263 }
264 }
265 }
266 }
267
272 void processElement(const ElementContext& elemCtx)
273 {
274 OPM_TIMEBLOCK_LOCAL(processElement);
275 if (!std::is_same<Discretization, EcfvDiscretization<TypeTag>>::value)
276 return;
277
278 const auto& problem = elemCtx.simulator().problem();
279 const auto& modelResid = elemCtx.simulator().model().linearizer().residual();
280 for (unsigned dofIdx = 0; dofIdx < elemCtx.numPrimaryDof(/*timeIdx=*/0); ++dofIdx) {
281 const auto& intQuants = elemCtx.intensiveQuantities(dofIdx, /*timeIdx=*/0);
282 const auto& fs = intQuants.fluidState();
283
284 using FluidState = std::remove_cv_t<std::remove_reference_t<decltype(fs)>>;
285
286 const unsigned globalDofIdx = elemCtx.globalSpaceIndex(dofIdx, /*timeIdx=*/0);
287 const unsigned pvtRegionIdx = elemCtx.primaryVars(dofIdx, /*timeIdx=*/0).pvtRegionIndex();
288
289 for (unsigned phaseIdx = 0; phaseIdx < numPhases; ++phaseIdx) {
290 if (this->saturation_[phaseIdx].empty())
291 continue;
292
293 this->saturation_[phaseIdx][globalDofIdx] = getValue(fs.saturation(phaseIdx));
294 Valgrind::CheckDefined(this->saturation_[phaseIdx][globalDofIdx]);
295 }
296
297 if (this->regionAvgDensity_.has_value()) {
298 // Note: We intentionally exclude effects of rock
299 // compressibility by using referencePorosity() here.
300 const auto porv = intQuants.referencePorosity()
301 * elemCtx.simulator().model().dofTotalVolume(globalDofIdx);
302
303 this->aggregateAverageDensityContributions_(fs, globalDofIdx,
304 static_cast<double>(porv));
305 }
306
307 if (!this->fluidPressure_.empty()) {
308 if (FluidSystem::phaseIsActive(oilPhaseIdx)) {
309 // Output oil pressure as default
310 this->fluidPressure_[globalDofIdx] = getValue(fs.pressure(oilPhaseIdx));
311 } else if (FluidSystem::phaseIsActive(gasPhaseIdx)) {
312 // Output gas if oil is not present
313 this->fluidPressure_[globalDofIdx] = getValue(fs.pressure(gasPhaseIdx));
314 } else {
315 // Output water if neither oil nor gas is present
316 this->fluidPressure_[globalDofIdx] = getValue(fs.pressure(waterPhaseIdx));
317 }
318 Valgrind::CheckDefined(this->fluidPressure_[globalDofIdx]);
319 }
320
321 if (!this->temperature_.empty()) {
322 this->temperature_[globalDofIdx] = getValue(fs.temperature(oilPhaseIdx));
323 Valgrind::CheckDefined(this->temperature_[globalDofIdx]);
324 }
325 if (!this->gasDissolutionFactor_.empty()) {
326 Scalar SoMax = elemCtx.problem().maxOilSaturation(globalDofIdx);
327 this->gasDissolutionFactor_[globalDofIdx]
328 = FluidSystem::template saturatedDissolutionFactor<FluidState, Scalar>(
329 fs, oilPhaseIdx, pvtRegionIdx, SoMax);
330 Valgrind::CheckDefined(this->gasDissolutionFactor_[globalDofIdx]);
331 }
332 if (!this->oilVaporizationFactor_.empty()) {
333 Scalar SoMax = elemCtx.problem().maxOilSaturation(globalDofIdx);
334 this->oilVaporizationFactor_[globalDofIdx]
335 = FluidSystem::template saturatedDissolutionFactor<FluidState, Scalar>(
336 fs, gasPhaseIdx, pvtRegionIdx, SoMax);
337 Valgrind::CheckDefined(this->oilVaporizationFactor_[globalDofIdx]);
338 }
339 if (!this->gasDissolutionFactorInWater_.empty()) {
340 Scalar SwMax = elemCtx.problem().maxWaterSaturation(globalDofIdx);
341 this->gasDissolutionFactorInWater_[globalDofIdx]
342 = FluidSystem::template saturatedDissolutionFactor<FluidState, Scalar>(
343 fs, waterPhaseIdx, pvtRegionIdx, SwMax);
344 Valgrind::CheckDefined(this->gasDissolutionFactorInWater_[globalDofIdx]);
345 }
346 if (!this->waterVaporizationFactor_.empty()) {
347 this->waterVaporizationFactor_[globalDofIdx]
348 = FluidSystem::template saturatedVaporizationFactor<FluidState, Scalar>(
349 fs, gasPhaseIdx, pvtRegionIdx);
350 Valgrind::CheckDefined(this->waterVaporizationFactor_[globalDofIdx]);
351 }
352 if (!this->gasFormationVolumeFactor_.empty()) {
353 this->gasFormationVolumeFactor_[globalDofIdx] = 1.0
354 / FluidSystem::template inverseFormationVolumeFactor<FluidState, Scalar>(
355 fs, gasPhaseIdx, pvtRegionIdx);
356 Valgrind::CheckDefined(this->gasFormationVolumeFactor_[globalDofIdx]);
357 }
358 if (!this->saturatedOilFormationVolumeFactor_.empty()) {
359 this->saturatedOilFormationVolumeFactor_[globalDofIdx] = 1.0
360 / FluidSystem::template saturatedInverseFormationVolumeFactor<FluidState, Scalar>(
361 fs, oilPhaseIdx, pvtRegionIdx);
362 Valgrind::CheckDefined(this->saturatedOilFormationVolumeFactor_[globalDofIdx]);
363 }
364 if (!this->oilSaturationPressure_.empty()) {
365 this->oilSaturationPressure_[globalDofIdx]
366 = FluidSystem::template saturationPressure<FluidState, Scalar>(fs, oilPhaseIdx, pvtRegionIdx);
367 Valgrind::CheckDefined(this->oilSaturationPressure_[globalDofIdx]);
368 }
369
370 if (!this->rs_.empty()) {
371 this->rs_[globalDofIdx] = getValue(fs.Rs());
372 Valgrind::CheckDefined(this->rs_[globalDofIdx]);
373 }
374 if (!this->rsw_.empty()) {
375 this->rsw_[globalDofIdx] = getValue(fs.Rsw());
376 Valgrind::CheckDefined(this->rsw_[globalDofIdx]);
377 }
378
379 if (!this->rv_.empty()) {
380 this->rv_[globalDofIdx] = getValue(fs.Rv());
381 Valgrind::CheckDefined(this->rv_[globalDofIdx]);
382 }
383 if (!this->pcgw_.empty()) {
384 this->pcgw_[globalDofIdx] = getValue(fs.pressure(gasPhaseIdx)) - getValue(fs.pressure(waterPhaseIdx));
385 Valgrind::CheckDefined(this->pcgw_[globalDofIdx]);
386 }
387 if (!this->pcow_.empty()) {
388 this->pcow_[globalDofIdx] = getValue(fs.pressure(oilPhaseIdx)) - getValue(fs.pressure(waterPhaseIdx));
389 Valgrind::CheckDefined(this->pcow_[globalDofIdx]);
390 }
391 if (!this->pcog_.empty()) {
392 this->pcog_[globalDofIdx] = getValue(fs.pressure(gasPhaseIdx)) - getValue(fs.pressure(oilPhaseIdx));
393 Valgrind::CheckDefined(this->pcog_[globalDofIdx]);
394 }
395
396 if (!this->rvw_.empty()) {
397 this->rvw_[globalDofIdx] = getValue(fs.Rvw());
398 Valgrind::CheckDefined(this->rvw_[globalDofIdx]);
399 }
400
401 for (unsigned phaseIdx = 0; phaseIdx < numPhases; ++phaseIdx) {
402 if (this->invB_[phaseIdx].empty())
403 continue;
404
405 this->invB_[phaseIdx][globalDofIdx] = getValue(fs.invB(phaseIdx));
406 Valgrind::CheckDefined(this->invB_[phaseIdx][globalDofIdx]);
407 }
408
409 for (unsigned phaseIdx = 0; phaseIdx < numPhases; ++phaseIdx) {
410 if (this->density_[phaseIdx].empty())
411 continue;
412
413 this->density_[phaseIdx][globalDofIdx] = getValue(fs.density(phaseIdx));
414 Valgrind::CheckDefined(this->density_[phaseIdx][globalDofIdx]);
415 }
416
417 for (unsigned phaseIdx = 0; phaseIdx < numPhases; ++phaseIdx) {
418 if (this->viscosity_[phaseIdx].empty())
419 continue;
420
421 if (!this->extboX_.empty() && phaseIdx == oilPhaseIdx)
422 this->viscosity_[phaseIdx][globalDofIdx] = getValue(intQuants.oilViscosity());
423 else if (!this->extboX_.empty() && phaseIdx == gasPhaseIdx)
424 this->viscosity_[phaseIdx][globalDofIdx] = getValue(intQuants.gasViscosity());
425 else
426 this->viscosity_[phaseIdx][globalDofIdx] = getValue(fs.viscosity(phaseIdx));
427 Valgrind::CheckDefined(this->viscosity_[phaseIdx][globalDofIdx]);
428 }
429
430 for (unsigned phaseIdx = 0; phaseIdx < numPhases; ++phaseIdx) {
431 if (this->relativePermeability_[phaseIdx].empty())
432 continue;
433
434 this->relativePermeability_[phaseIdx][globalDofIdx]
435 = getValue(intQuants.relativePermeability(phaseIdx));
436 Valgrind::CheckDefined(this->relativePermeability_[phaseIdx][globalDofIdx]);
437 }
438
439 if (!this->drsdtcon_.empty()) {
440 this->drsdtcon_[globalDofIdx] = problem.drsdtcon(globalDofIdx, elemCtx.simulator().episodeIndex());
441 }
442
443 if (!this->sSol_.empty()) {
444 this->sSol_[globalDofIdx] = intQuants.solventSaturation().value();
445 }
446
447 if (!this->rswSol_.empty()) {
448 this->rswSol_[globalDofIdx] = intQuants.rsSolw().value();
449 }
450
451 if (!this->cPolymer_.empty()) {
452 this->cPolymer_[globalDofIdx] = intQuants.polymerConcentration().value();
453 }
454
455 if (!this->cFoam_.empty()) {
456 this->cFoam_[globalDofIdx] = intQuants.foamConcentration().value();
457 }
458
459 if (!this->cSalt_.empty()) {
460 this->cSalt_[globalDofIdx] = fs.saltConcentration().value();
461 }
462
463 if (!this->pSalt_.empty()) {
464 this->pSalt_[globalDofIdx] = intQuants.saltSaturation().value();
465 }
466
467 if (!this->permFact_.empty()) {
468 this->permFact_[globalDofIdx] = intQuants.permFactor().value();
469 }
470
471 if (!this->extboX_.empty()) {
472 this->extboX_[globalDofIdx] = intQuants.xVolume().value();
473 }
474
475 if (!this->extboY_.empty()) {
476 this->extboY_[globalDofIdx] = intQuants.yVolume().value();
477 }
478
479 if (!this->extboZ_.empty()) {
480 this->extboZ_[globalDofIdx] = intQuants.zFraction().value();
481 }
482
483 if (!this->rPorV_.empty()) {
484 const auto totVolume = elemCtx.simulator().model().dofTotalVolume(globalDofIdx);
485 this->rPorV_[globalDofIdx] = totVolume * intQuants.porosity().value();
486 }
487
488 if (!this->mFracCo2_.empty()) {
489 const Scalar stdVolOil = getValue(fs.saturation(oilPhaseIdx)) * getValue(fs.invB(oilPhaseIdx))
490 + getValue(fs.saturation(gasPhaseIdx)) * getValue(fs.invB(gasPhaseIdx)) * getValue(fs.Rv());
491 const Scalar stdVolGas = getValue(fs.saturation(gasPhaseIdx)) * getValue(fs.invB(gasPhaseIdx))
492 * (1.0 - intQuants.yVolume().value())
493 + getValue(fs.saturation(oilPhaseIdx)) * getValue(fs.invB(oilPhaseIdx)) * getValue(fs.Rs())
494 * (1.0 - intQuants.xVolume().value());
495 const Scalar stdVolCo2 = getValue(fs.saturation(gasPhaseIdx)) * getValue(fs.invB(gasPhaseIdx))
496 * intQuants.yVolume().value()
497 + getValue(fs.saturation(oilPhaseIdx)) * getValue(fs.invB(oilPhaseIdx)) * getValue(fs.Rs())
498 * intQuants.xVolume().value();
499 const Scalar rhoO = FluidSystem::referenceDensity(gasPhaseIdx, pvtRegionIdx);
500 const Scalar rhoG = FluidSystem::referenceDensity(gasPhaseIdx, pvtRegionIdx);
501 const Scalar rhoCO2 = intQuants.zRefDensity();
502 const Scalar stdMassTotal = 1.0e-10 + stdVolOil * rhoO + stdVolGas * rhoG + stdVolCo2 * rhoCO2;
503 this->mFracOil_[globalDofIdx] = stdVolOil * rhoO / stdMassTotal;
504 this->mFracGas_[globalDofIdx] = stdVolGas * rhoG / stdMassTotal;
505 this->mFracCo2_[globalDofIdx] = stdVolCo2 * rhoCO2 / stdMassTotal;
506 }
507
508 if (!this->cMicrobes_.empty()) {
509 this->cMicrobes_[globalDofIdx] = intQuants.microbialConcentration().value();
510 }
511
512 if (!this->cOxygen_.empty()) {
513 this->cOxygen_[globalDofIdx] = intQuants.oxygenConcentration().value();
514 }
515
516 if (!this->cUrea_.empty()) {
517 this->cUrea_[globalDofIdx] = 10
518 * intQuants.ureaConcentration()
519 .value(); // Reescaling back the urea concentration (see WellInterface_impl.hpp)
520 }
521
522 if (!this->cBiofilm_.empty()) {
523 this->cBiofilm_[globalDofIdx] = intQuants.biofilmConcentration().value();
524 }
525
526 if (!this->cCalcite_.empty()) {
527 this->cCalcite_[globalDofIdx] = intQuants.calciteConcentration().value();
528 }
529
530 if (!this->bubblePointPressure_.empty()) {
531 try {
532 this->bubblePointPressure_[globalDofIdx]
533 = getValue(FluidSystem::bubblePointPressure(fs, intQuants.pvtRegionIndex()));
534 } catch (const NumericalProblem&) {
535 const auto cartesianIdx = elemCtx.simulator().vanguard().cartesianIndex(globalDofIdx);
536 this->failedCellsPb_.push_back(cartesianIdx);
537 }
538 }
539
540 if (!this->dewPointPressure_.empty()) {
541 try {
542 this->dewPointPressure_[globalDofIdx]
543 = getValue(FluidSystem::dewPointPressure(fs, intQuants.pvtRegionIndex()));
544 } catch (const NumericalProblem&) {
545 const auto cartesianIdx = elemCtx.simulator().vanguard().cartesianIndex(globalDofIdx);
546 this->failedCellsPd_.push_back(cartesianIdx);
547 }
548 }
549
550 if (!this->minimumOilPressure_.empty())
551 this->minimumOilPressure_[globalDofIdx]
552 = std::min(getValue(fs.pressure(oilPhaseIdx)), problem.minOilPressure(globalDofIdx));
553
554 if (!this->overburdenPressure_.empty())
555 this->overburdenPressure_[globalDofIdx] = problem.overburdenPressure(globalDofIdx);
556
557 if (!this->rockCompPorvMultiplier_.empty())
558 this->rockCompPorvMultiplier_[globalDofIdx]
559 = problem.template rockCompPoroMultiplier<Scalar>(intQuants, globalDofIdx);
560
561 if (!this->rockCompTransMultiplier_.empty())
562 this->rockCompTransMultiplier_[globalDofIdx]
563 = problem.template rockCompTransMultiplier<Scalar>(intQuants, globalDofIdx);
564
565 const auto& matLawManager = problem.materialLawManager();
566 if (matLawManager->enableHysteresis()) {
567 if (FluidSystem::phaseIsActive(oilPhaseIdx)
568 && FluidSystem::phaseIsActive(waterPhaseIdx)) {
569 Scalar somax;
570 Scalar swmax;
571 Scalar swmin;
572
573 matLawManager->oilWaterHysteresisParams(
574 somax, swmax, swmin, globalDofIdx);
575
576 if (matLawManager->enableNonWettingHysteresis()) {
577 if (!this->soMax_.empty()) {
578 this->soMax_[globalDofIdx] = somax;
579 }
580 }
581 if (matLawManager->enableWettingHysteresis()) {
582 if (!this->swMax_.empty()) {
583 this->swMax_[globalDofIdx] = swmax;
584 }
585 }
586 if (matLawManager->enablePCHysteresis()) {
587 if (!this->swmin_.empty()) {
588 this->swmin_[globalDofIdx] = swmin;
589 }
590 }
591 }
592
593 if (FluidSystem::phaseIsActive(oilPhaseIdx)
594 && FluidSystem::phaseIsActive(gasPhaseIdx)) {
595 Scalar sgmax;
596 Scalar shmax;
597 Scalar somin;
598 matLawManager->gasOilHysteresisParams(
599 sgmax, shmax, somin, globalDofIdx);
600
601 if (matLawManager->enableNonWettingHysteresis()) {
602 if (!this->sgmax_.empty()) {
603 this->sgmax_[globalDofIdx] = sgmax;
604 }
605 }
606 if (matLawManager->enableWettingHysteresis()) {
607 if (!this->shmax_.empty()) {
608 this->shmax_[globalDofIdx] = shmax;
609 }
610 }
611 if (matLawManager->enablePCHysteresis()) {
612 if (!this->somin_.empty()) {
613 this->somin_[globalDofIdx] = somin;
614 }
615 }
616 }
617 } else {
618
619 if (!this->soMax_.empty())
620 this->soMax_[globalDofIdx]
621 = std::max(getValue(fs.saturation(oilPhaseIdx)), problem.maxOilSaturation(globalDofIdx));
622
623 if (!this->swMax_.empty())
624 this->swMax_[globalDofIdx]
625 = std::max(getValue(fs.saturation(waterPhaseIdx)), problem.maxWaterSaturation(globalDofIdx));
626
627 }
628 if (!this->ppcw_.empty()) {
629 this->ppcw_[globalDofIdx] = matLawManager->oilWaterScaledEpsInfoDrainage(globalDofIdx).maxPcow;
630 // printf("ppcw_[%d] = %lg\n", globalDofIdx, ppcw_[globalDofIdx]);
631 }
632
633 // hack to make the intial output of rs and rv Ecl compatible.
634 // For cells with swat == 1 Ecl outputs; rs = rsSat and rv=rvSat, in all but the initial step
635 // where it outputs rs and rv values calculated by the initialization. To be compatible we overwrite
636 // rs and rv with the values computed in the initially.
637 // Volume factors, densities and viscosities need to be recalculated with the updated rs and rv values.
638 if ((elemCtx.simulator().episodeIndex() < 0) &&
639 FluidSystem::phaseIsActive(oilPhaseIdx) &&
640 FluidSystem::phaseIsActive(gasPhaseIdx))
641 {
642 const auto& fsInitial = problem.initialFluidState(globalDofIdx);
643
644 // use initial rs and rv values
645 if (!this->rv_.empty())
646 this->rv_[globalDofIdx] = fsInitial.Rv();
647
648 if (!this->rs_.empty())
649 this->rs_[globalDofIdx] = fsInitial.Rs();
650
651 if (!this->rsw_.empty())
652 this->rsw_[globalDofIdx] = fsInitial.Rsw();
653
654 if (!this->rvw_.empty())
655 this->rvw_[globalDofIdx] = fsInitial.Rvw();
656
657 // re-compute the volume factors, viscosities and densities if asked for
658 if (!this->density_[oilPhaseIdx].empty())
659 this->density_[oilPhaseIdx][globalDofIdx]
660 = FluidSystem::density(fsInitial, oilPhaseIdx, intQuants.pvtRegionIndex());
661
662 if (!this->density_[gasPhaseIdx].empty())
663 this->density_[gasPhaseIdx][globalDofIdx]
664 = FluidSystem::density(fsInitial, gasPhaseIdx, intQuants.pvtRegionIndex());
665
666 if (!this->invB_[oilPhaseIdx].empty())
667 this->invB_[oilPhaseIdx][globalDofIdx]
668 = FluidSystem::inverseFormationVolumeFactor(fsInitial, oilPhaseIdx, intQuants.pvtRegionIndex());
669
670 if (!this->invB_[gasPhaseIdx].empty())
671 this->invB_[gasPhaseIdx][globalDofIdx]
672 = FluidSystem::inverseFormationVolumeFactor(fsInitial, gasPhaseIdx, intQuants.pvtRegionIndex());
673
674 if (!this->viscosity_[oilPhaseIdx].empty())
675 this->viscosity_[oilPhaseIdx][globalDofIdx]
676 = FluidSystem::viscosity(fsInitial, oilPhaseIdx, intQuants.pvtRegionIndex());
677
678 if (!this->viscosity_[gasPhaseIdx].empty())
679 this->viscosity_[gasPhaseIdx][globalDofIdx]
680 = FluidSystem::viscosity(fsInitial, gasPhaseIdx, intQuants.pvtRegionIndex());
681 }
682
683 // Adding Well RFT data
684 const auto cartesianIdx = elemCtx.simulator().vanguard().cartesianIndex(globalDofIdx);
685 if (this->oilConnectionPressures_.count(cartesianIdx) > 0) {
686 this->oilConnectionPressures_[cartesianIdx] = getValue(fs.pressure(oilPhaseIdx));
687 }
688 if (this->waterConnectionSaturations_.count(cartesianIdx) > 0) {
689 this->waterConnectionSaturations_[cartesianIdx] = getValue(fs.saturation(waterPhaseIdx));
690 }
691 if (this->gasConnectionSaturations_.count(cartesianIdx) > 0) {
692 this->gasConnectionSaturations_[cartesianIdx] = getValue(fs.saturation(gasPhaseIdx));
693 }
694
695 // tracers
696 const auto& tracerModel = simulator_.problem().tracerModel();
697 if (! this->freeTracerConcentrations_.empty()) {
698 for (int tracerIdx = 0; tracerIdx < tracerModel.numTracers(); ++tracerIdx) {
699 if (this->freeTracerConcentrations_[tracerIdx].empty()) {
700 continue;
701 }
702 this->freeTracerConcentrations_[tracerIdx][globalDofIdx] =
703 tracerModel.freeTracerConcentration(tracerIdx, globalDofIdx);
704 }
705 }
706 if (! this->solTracerConcentrations_.empty()) {
707 for (int tracerIdx = 0; tracerIdx < tracerModel.numTracers(); ++tracerIdx) {
708 if (this->solTracerConcentrations_[tracerIdx].empty()) {
709 continue;
710 }
711 this->solTracerConcentrations_[tracerIdx][globalDofIdx] =
712 tracerModel.solTracerConcentration(tracerIdx, globalDofIdx);
713
714 }
715 }
716
717 // output residual
718 for ( int phaseIdx = 0; phaseIdx < numPhases; ++phaseIdx )
719 {
720 if (!this->residual_[phaseIdx].empty()) {
721 const unsigned activeCompIdx = Indices::canonicalToActiveComponentIndex(FluidSystem::solventComponentIndex(phaseIdx));
722 this->residual_[phaseIdx][globalDofIdx] = modelResid[globalDofIdx][activeCompIdx];
723 }
724 }
725 }
726 }
727
728 void processElementFlows(const ElementContext& elemCtx)
729 {
730 OPM_TIMEBLOCK_LOCAL(processElementBlockData);
731 if (!std::is_same_v<Discretization, EcfvDiscretization<TypeTag>>)
732 return;
733
734 const auto& problem = elemCtx.simulator().problem();
735 for (unsigned dofIdx = 0; dofIdx < elemCtx.numPrimaryDof(/*timeIdx=*/0); ++dofIdx) {
736
737 unsigned globalDofIdx = elemCtx.globalSpaceIndex(dofIdx, /*timeIdx=*/0);
738 if (!problem.model().linearizer().getFlowsInfo().empty()) {
739 const auto& flowsInf = problem.model().linearizer().getFlowsInfo();
740 auto flowsInfos = flowsInf[globalDofIdx];
741 for (auto& flowsInfo : flowsInfos) {
742 if (flowsInfo.faceId >= 0) {
743 if (!this->flows_[flowsInfo.faceId][gasCompIdx].empty()) {
744 this->flows_[flowsInfo.faceId][gasCompIdx][globalDofIdx]
745 = flowsInfo.flow[conti0EqIdx + Indices::canonicalToActiveComponentIndex(gasCompIdx)];
746 }
747 if (!this->flows_[flowsInfo.faceId][oilCompIdx].empty()) {
748 this->flows_[flowsInfo.faceId][oilCompIdx][globalDofIdx]
749 = flowsInfo.flow[conti0EqIdx + Indices::canonicalToActiveComponentIndex(oilCompIdx)];
750 }
751 if (!this->flows_[flowsInfo.faceId][waterCompIdx].empty()) {
752 this->flows_[flowsInfo.faceId][waterCompIdx][globalDofIdx]
753 = flowsInfo.flow[conti0EqIdx + Indices::canonicalToActiveComponentIndex(waterCompIdx)];
754 }
755 }
756 if (flowsInfo.faceId == -2) {
757 if (!this->flowsn_[gasCompIdx].indices.empty()) {
758 this->flowsn_[gasCompIdx].indices[flowsInfo.nncId] = flowsInfo.nncId;
759 this->flowsn_[gasCompIdx].values[flowsInfo.nncId]
760 = flowsInfo.flow[conti0EqIdx + Indices::canonicalToActiveComponentIndex(gasCompIdx)];
761 }
762 if (!this->flowsn_[oilCompIdx].indices.empty()) {
763 this->flowsn_[oilCompIdx].indices[flowsInfo.nncId] = flowsInfo.nncId;
764 this->flowsn_[oilCompIdx].values[flowsInfo.nncId]
765 = flowsInfo.flow[conti0EqIdx + Indices::canonicalToActiveComponentIndex(oilCompIdx)];
766 }
767 if (!this->flowsn_[waterCompIdx].indices.empty()) {
768 this->flowsn_[waterCompIdx].indices[flowsInfo.nncId] = flowsInfo.nncId;
769 this->flowsn_[waterCompIdx].values[flowsInfo.nncId]
770 = flowsInfo.flow[conti0EqIdx + Indices::canonicalToActiveComponentIndex(waterCompIdx)];
771 }
772 }
773 }
774 }
775
776 // flores
777 if (!problem.model().linearizer().getFloresInfo().empty()) {
778 const auto& floresInf = problem.model().linearizer().getFloresInfo();
779 auto floresInfos =floresInf[globalDofIdx];
780 for (auto& floresInfo : floresInfos) {
781 if (floresInfo.faceId >= 0) {
782 if (!this->flores_[floresInfo.faceId][gasCompIdx].empty()) {
783 this->flores_[floresInfo.faceId][gasCompIdx][globalDofIdx]
784 = floresInfo.flow[conti0EqIdx + Indices::canonicalToActiveComponentIndex(gasCompIdx)];
785 }
786 if (!this->flores_[floresInfo.faceId][oilCompIdx].empty()) {
787 this->flores_[floresInfo.faceId][oilCompIdx][globalDofIdx]
788 = floresInfo.flow[conti0EqIdx + Indices::canonicalToActiveComponentIndex(oilCompIdx)];
789 }
790 if (!this->flores_[floresInfo.faceId][waterCompIdx].empty()) {
791 this->flores_[floresInfo.faceId][waterCompIdx][globalDofIdx]
792 = floresInfo.flow[conti0EqIdx + Indices::canonicalToActiveComponentIndex(waterCompIdx)];
793 }
794 }
795
796 if (floresInfo.faceId == -2) {
797 if (!this->floresn_[gasCompIdx].indices.empty()) {
798 this->floresn_[gasCompIdx].indices[floresInfo.nncId] = floresInfo.nncId;
799 this->floresn_[gasCompIdx].values[floresInfo.nncId]
800 = floresInfo.flow[conti0EqIdx + Indices::canonicalToActiveComponentIndex(gasCompIdx)];
801 }
802 if (!this->floresn_[oilCompIdx].indices.empty()) {
803 this->floresn_[oilCompIdx].indices[floresInfo.nncId] = floresInfo.nncId;
804 this->floresn_[oilCompIdx].values[floresInfo.nncId]
805 = floresInfo.flow[conti0EqIdx + Indices::canonicalToActiveComponentIndex(oilCompIdx)];
806 }
807 if (!this->floresn_[waterCompIdx].indices.empty()) {
808 this->floresn_[waterCompIdx].indices[floresInfo.nncId] = floresInfo.nncId;
809 this->floresn_[waterCompIdx].values[floresInfo.nncId]
810 = floresInfo.flow[conti0EqIdx + Indices::canonicalToActiveComponentIndex(waterCompIdx)];
811 }
812 }
813 }
814 }
815 }
816 }
817
818 void processElementBlockData(const ElementContext& elemCtx)
819 {
820 OPM_TIMEBLOCK_LOCAL(processElementBlockData);
821 if (!std::is_same<Discretization, EcfvDiscretization<TypeTag>>::value)
822 return;
823
824 const auto& problem = elemCtx.simulator().problem();
825 for (unsigned dofIdx = 0; dofIdx < elemCtx.numPrimaryDof(/*timeIdx=*/0); ++dofIdx) {
826 // Adding block data
827 const auto globalDofIdx = elemCtx.globalSpaceIndex(dofIdx, /*timeIdx=*/0);
828 const auto cartesianIdx = elemCtx.simulator().vanguard().cartesianIndex(globalDofIdx);
829 const auto& intQuants = elemCtx.intensiveQuantities(dofIdx, /*timeIdx=*/0);
830 const auto& fs = intQuants.fluidState();
831 for (auto& val : this->blockData_) {
832 const auto& key = val.first;
833 assert(key.second > 0);
834
835 const auto cartesianIdxBlock = static_cast<std::remove_cv_t<
836 std::remove_reference_t<decltype(cartesianIdx)>>>(key.second - 1);
837
838 if (cartesianIdx == cartesianIdxBlock) {
839 if ((key.first == "BWSAT") || (key.first == "BSWAT"))
840 val.second = getValue(fs.saturation(waterPhaseIdx));
841 else if ((key.first == "BGSAT") || (key.first == "BSGAS"))
842 val.second = getValue(fs.saturation(gasPhaseIdx));
843 else if ((key.first == "BOSAT") || (key.first == "BSOIL"))
844 val.second = getValue(fs.saturation(oilPhaseIdx));
845 else if (key.first == "BNSAT")
846 val.second = intQuants.solventSaturation().value();
847 else if ((key.first == "BPR") || (key.first == "BPRESSUR")) {
848 if (FluidSystem::phaseIsActive(oilPhaseIdx))
849 val.second = getValue(fs.pressure(oilPhaseIdx));
850 else if (FluidSystem::phaseIsActive(gasPhaseIdx))
851 val.second = getValue(fs.pressure(gasPhaseIdx));
852 else if (FluidSystem::phaseIsActive(waterPhaseIdx))
853 val.second = getValue(fs.pressure(waterPhaseIdx));
854 }
855 else if ((key.first == "BTCNFHEA") || (key.first == "BTEMP")) {
856 if (FluidSystem::phaseIsActive(oilPhaseIdx))
857 val.second = getValue(fs.temperature(oilPhaseIdx));
858 else if (FluidSystem::phaseIsActive(gasPhaseIdx))
859 val.second = getValue(fs.temperature(gasPhaseIdx));
860 else if (FluidSystem::phaseIsActive(waterPhaseIdx))
861 val.second = getValue(fs.temperature(waterPhaseIdx));
862 }
863 else if (key.first == "BWKR" || key.first == "BKRW")
864 val.second = getValue(intQuants.relativePermeability(waterPhaseIdx));
865 else if (key.first == "BGKR" || key.first == "BKRG")
866 val.second = getValue(intQuants.relativePermeability(gasPhaseIdx));
867 else if (key.first == "BOKR" || key.first == "BKRO")
868 val.second = getValue(intQuants.relativePermeability(oilPhaseIdx));
869 else if (key.first == "BKROG") {
870 const auto& materialParams = problem.materialLawParams(elemCtx, dofIdx, /* timeIdx = */ 0);
871 const auto krog
872 = MaterialLaw::template relpermOilInOilGasSystem<Evaluation>(materialParams, fs);
873 val.second = getValue(krog);
874 }
875 else if (key.first == "BKROW") {
876 const auto& materialParams = problem.materialLawParams(elemCtx, dofIdx, /* timeIdx = */ 0);
877 const auto krow
878 = MaterialLaw::template relpermOilInOilWaterSystem<Evaluation>(materialParams, fs);
879 val.second = getValue(krow);
880 }
881 else if (key.first == "BWPC")
882 val.second = getValue(fs.pressure(oilPhaseIdx)) - getValue(fs.pressure(waterPhaseIdx));
883 else if (key.first == "BGPC")
884 val.second = getValue(fs.pressure(gasPhaseIdx)) - getValue(fs.pressure(oilPhaseIdx));
885 else if (key.first == "BWPR")
886 val.second = getValue(fs.pressure(waterPhaseIdx));
887 else if (key.first == "BGPR")
888 val.second = getValue(fs.pressure(gasPhaseIdx));
889 else if (key.first == "BVWAT" || key.first == "BWVIS")
890 val.second = getValue(fs.viscosity(waterPhaseIdx));
891 else if (key.first == "BVGAS" || key.first == "BGVIS")
892 val.second = getValue(fs.viscosity(gasPhaseIdx));
893 else if (key.first == "BVOIL" || key.first == "BOVIS")
894 val.second = getValue(fs.viscosity(oilPhaseIdx));
895 else if ((key.first == "BODEN") || (key.first == "BDENO"))
896 val.second = getValue(fs.density(oilPhaseIdx));
897 else if ((key.first == "BGDEN") || (key.first == "BDENG"))
898 val.second = getValue(fs.density(gasPhaseIdx));
899 else if ((key.first == "BWDEN") || (key.first == "BDENW"))
900 val.second = getValue(fs.density(waterPhaseIdx));
901 else if ((key.first == "BRPV") ||
902 (key.first == "BOPV") ||
903 (key.first == "BWPV") ||
904 (key.first == "BGPV"))
905 {
906 if (key.first == "BRPV") {
907 val.second = 1.0;
908 }
909 else if (key.first == "BOPV") {
910 val.second = getValue(fs.saturation(oilPhaseIdx));
911 }
912 else if (key.first == "BWPV") {
913 val.second = getValue(fs.saturation(waterPhaseIdx));
914 }
915 else {
916 val.second = getValue(fs.saturation(gasPhaseIdx));
917 }
918
919 // Include active pore-volume.
920 val.second *= getValue(intQuants.porosity())
921 * elemCtx.simulator().model().dofTotalVolume(globalDofIdx);
922 }
923 else if (key.first == "BRS")
924 val.second = getValue(fs.Rs());
925 else if (key.first == "BRV")
926 val.second = getValue(fs.Rv());
927 else if ((key.first == "BOIP") || (key.first == "BOIPL") || (key.first == "BOIPG") ||
928 (key.first == "BGIP") || (key.first == "BGIPL") || (key.first == "BGIPG") ||
929 (key.first == "BWIP"))
930 {
931 if ((key.first == "BOIP") || (key.first == "BOIPL")) {
932 val.second = getValue(fs.invB(oilPhaseIdx)) * getValue(fs.saturation(oilPhaseIdx));
933
934 if (key.first == "BOIP") {
935 val.second += getValue(fs.Rv()) * getValue(fs.invB(gasPhaseIdx))
936 * getValue(fs.saturation(gasPhaseIdx));
937 }
938 }
939 else if (key.first == "BOIPG") {
940 val.second = getValue(fs.Rv()) * getValue(fs.invB(gasPhaseIdx))
941 * getValue(fs.saturation(gasPhaseIdx));
942 }
943 else if ((key.first == "BGIP") || (key.first == "BGIPG")) {
944 val.second = getValue(fs.invB(gasPhaseIdx)) * getValue(fs.saturation(gasPhaseIdx));
945
946 if (key.first == "BGIP") {
947 if (!FluidSystem::phaseIsActive(oilPhaseIdx)) {
948 val.second += getValue(fs.Rsw()) * getValue(fs.invB(waterPhaseIdx))
949 * getValue(fs.saturation(waterPhaseIdx));
950 }
951 else {
952 val.second += getValue(fs.Rs()) * getValue(fs.invB(oilPhaseIdx))
953 * getValue(fs.saturation(oilPhaseIdx));
954 }
955 }
956 }
957 else if (key.first == "BGIPL") {
958 if (!FluidSystem::phaseIsActive(oilPhaseIdx)) {
959 val.second = getValue(fs.Rsw()) * getValue(fs.invB(waterPhaseIdx))
960 * getValue(fs.saturation(waterPhaseIdx));
961 }
962 else {
963 val.second = getValue(fs.Rs()) * getValue(fs.invB(oilPhaseIdx))
964 * getValue(fs.saturation(oilPhaseIdx));
965 }
966 }
967 else { // BWIP
968 val.second = getValue(fs.invB(waterPhaseIdx)) * getValue(fs.saturation(waterPhaseIdx));
969 }
970
971 // Include active pore-volume.
972 val.second *= elemCtx.simulator().model().dofTotalVolume(globalDofIdx)
973 * getValue(intQuants.porosity());
974 }
975 else if ((key.first == "BPPO") ||
976 (key.first == "BPPG") ||
977 (key.first == "BPPW"))
978 {
980
981 if (key.first == "BPPO") {
982 phase.ix = oilPhaseIdx;
983 }
984 else if (key.first == "BPPG") {
985 phase.ix = gasPhaseIdx;
986 }
987 else { // BPPW
988 phase.ix = waterPhaseIdx;
989 }
990
991 // Note different region handling here. FIPNUM is
992 // one-based, but we need zero-based lookup in
993 // DatumDepth. On the other hand, pvtRegionIndex is
994 // zero-based but we need one-based lookup in
995 // RegionPhasePoreVolAverage.
996
997 // Subtract one to convert FIPNUM to region index.
998 const auto datum = this->eclState_.getSimulationConfig()
999 .datumDepths()(this->regions_["FIPNUM"][dofIdx] - 1);
1000
1001 // Add one to convert region index to region ID.
1002 const auto region = RegionPhasePoreVolAverage::Region {
1003 elemCtx.primaryVars(dofIdx, /*timeIdx=*/0).pvtRegionIndex() + 1
1004 };
1005
1006 const auto density = this->regionAvgDensity_
1007 ->value("PVTNUM", phase, region);
1008
1009 const auto press = getValue(fs.pressure(phase.ix));
1010 const auto grav =
1011 elemCtx.problem().gravity()[GridView::dimensionworld - 1];
1012 const auto dz = problem.dofCenterDepth(globalDofIdx) - datum;
1013
1014 val.second = press - density*dz*grav;
1015 }
1016 else if ((key.first == "BFLOWI") ||
1017 (key.first == "BFLOWJ") ||
1018 (key.first == "BFLOWK"))
1019 {
1020 auto dir = FaceDir::ToIntersectionIndex(Dir::XPlus);
1021
1022 if (key.first == "BFLOWJ") {
1023 dir = FaceDir::ToIntersectionIndex(Dir::YPlus);
1024 }
1025 else if (key.first == "BFLOWK") {
1026 dir = FaceDir::ToIntersectionIndex(Dir::ZPlus);
1027 }
1028
1029 val.second = this->flows_[dir][waterCompIdx][globalDofIdx];
1030 }
1031 else {
1032 std::string logstring = "Keyword '";
1033 logstring.append(key.first);
1034 logstring.append("' is unhandled for output to summary file.");
1035 OpmLog::warning("Unhandled output keyword", logstring);
1036 }
1037 }
1038 }
1039 }
1040 }
1041
1070 template <class ActiveIndex, class CartesianIndex>
1071 void processFluxes(const ElementContext& elemCtx,
1072 ActiveIndex&& activeIndex,
1073 CartesianIndex&& cartesianIndex)
1074 {
1075 OPM_TIMEBLOCK_LOCAL(processFluxes);
1076 const auto identifyCell = [&activeIndex, &cartesianIndex](const Element& elem)
1078 {
1079 const auto cellIndex = activeIndex(elem);
1080
1081 return {
1082 static_cast<int>(cellIndex),
1083 cartesianIndex(cellIndex),
1084 elem.partitionType() == Dune::InteriorEntity
1085 };
1086 };
1087
1088 const auto timeIdx = 0u;
1089 const auto& stencil = elemCtx.stencil(timeIdx);
1090 const auto numInteriorFaces = elemCtx.numInteriorFaces(timeIdx);
1091
1092 for (auto scvfIdx = 0 * numInteriorFaces; scvfIdx < numInteriorFaces; ++scvfIdx) {
1093 const auto& face = stencil.interiorFace(scvfIdx);
1094 const auto left = identifyCell(stencil.element(face.interiorIndex()));
1095 const auto right = identifyCell(stencil.element(face.exteriorIndex()));
1096
1097 const auto rates = this->
1098 getComponentSurfaceRates(elemCtx, face.area(), scvfIdx, timeIdx);
1099
1100 this->interRegionFlows_.addConnection(left, right, rates);
1101 }
1102 }
1103
1109 {
1110 // Inter-region flow rates. Note: ".clear()" prepares to accumulate
1111 // contributions per bulk connection between FIP regions.
1112 this->interRegionFlows_.clear();
1113 }
1114
1119 {
1121 }
1122
1127 {
1128 return this->interRegionFlows_;
1129 }
1130
1131 template <class FluidState>
1132 void assignToFluidState(FluidState& fs, unsigned elemIdx) const
1133 {
1134 for (unsigned phaseIdx = 0; phaseIdx < numPhases; ++phaseIdx) {
1135 if (this->saturation_[phaseIdx].empty())
1136 continue;
1137
1138 fs.setSaturation(phaseIdx, this->saturation_[phaseIdx][elemIdx]);
1139 }
1140
1141 if (!this->fluidPressure_.empty()) {
1142 // this assumes that capillary pressures only depend on the phase saturations
1143 // and possibly on temperature. (this is always the case for ECL problems.)
1144 std::array<Scalar, numPhases> pc = {0};
1145 const MaterialLawParams& matParams = simulator_.problem().materialLawParams(elemIdx);
1146 MaterialLaw::capillaryPressures(pc, matParams, fs);
1147 Valgrind::CheckDefined(this->fluidPressure_[elemIdx]);
1148 Valgrind::CheckDefined(pc);
1149 assert(FluidSystem::phaseIsActive(oilPhaseIdx));
1150 for (unsigned phaseIdx = 0; phaseIdx < numPhases; ++phaseIdx) {
1151 if (!FluidSystem::phaseIsActive(phaseIdx))
1152 continue;
1153
1154 fs.setPressure(phaseIdx, this->fluidPressure_[elemIdx] + (pc[phaseIdx] - pc[oilPhaseIdx]));
1155 }
1156 }
1157
1158 if (!this->temperature_.empty())
1159 fs.setTemperature(this->temperature_[elemIdx]);
1160 if (!this->rs_.empty())
1161 fs.setRs(this->rs_[elemIdx]);
1162 if (!this->rsw_.empty())
1163 fs.setRsw(this->rsw_[elemIdx]);
1164 if (!this->rv_.empty())
1165 fs.setRv(this->rv_[elemIdx]);
1166 if (!this->rvw_.empty())
1167 fs.setRvw(this->rvw_[elemIdx]);
1168 }
1169
1170 void initHysteresisParams(Simulator& simulator, unsigned elemIdx) const
1171 {
1172 if (!this->soMax_.empty())
1173 simulator.problem().setMaxOilSaturation(elemIdx, this->soMax_[elemIdx]);
1174
1175 if (simulator.problem().materialLawManager()->enableHysteresis()) {
1176 auto matLawManager = simulator.problem().materialLawManager();
1177
1178 if (FluidSystem::phaseIsActive(oilPhaseIdx)
1179 && FluidSystem::phaseIsActive(waterPhaseIdx)) {
1180 Scalar somax = 2.0;
1181 Scalar swmax = -2.0;
1182 Scalar swmin = 2.0;
1183
1184 if (matLawManager->enableNonWettingHysteresis()) {
1185 if (!this->soMax_.empty()) {
1186 somax = this->soMax_[elemIdx];
1187 }
1188 }
1189 if (matLawManager->enableWettingHysteresis()) {
1190 if (!this->swMax_.empty()) {
1191 swmax = this->swMax_[elemIdx];
1192 }
1193 }
1194 if (matLawManager->enablePCHysteresis()) {
1195 if (!this->swmin_.empty()) {
1196 swmin = this->swmin_[elemIdx];
1197 }
1198 }
1199 matLawManager->setOilWaterHysteresisParams(
1200 somax, swmax, swmin, elemIdx);
1201 }
1202 if (FluidSystem::phaseIsActive(oilPhaseIdx)
1203 && FluidSystem::phaseIsActive(gasPhaseIdx)) {
1204 Scalar sgmax = 2.0;
1205 Scalar shmax = -2.0;
1206 Scalar somin = 2.0;
1207
1208 if (matLawManager->enableNonWettingHysteresis()) {
1209 if (!this->sgmax_.empty()) {
1210 sgmax = this->sgmax_[elemIdx];
1211 }
1212 }
1213 if (matLawManager->enableWettingHysteresis()) {
1214 if (!this->shmax_.empty()) {
1215 shmax = this->shmax_[elemIdx];
1216 }
1217 }
1218 if (matLawManager->enablePCHysteresis()) {
1219 if (!this->somin_.empty()) {
1220 somin = this->somin_[elemIdx];
1221 }
1222 }
1223 matLawManager->setGasOilHysteresisParams(
1224 sgmax, shmax, somin, elemIdx);
1225 }
1226
1227 }
1228
1229 if (simulator_.vanguard().eclState().fieldProps().has_double("SWATINIT")) {
1230 simulator.problem().materialLawManager()
1231 ->applyRestartSwatInit(elemIdx, this->ppcw_[elemIdx]);
1232 }
1233 }
1234
1235 void updateFluidInPlace(const ElementContext& elemCtx)
1236 {
1237 for (unsigned dofIdx = 0; dofIdx < elemCtx.numPrimaryDof(/*timeIdx=*/0); ++dofIdx) {
1238 updateFluidInPlace_(elemCtx, dofIdx);
1239 }
1240 }
1241
1242 void updateFluidInPlace(const unsigned globalDofIdx,
1243 const IntensiveQuantities& intQuants,
1244 const double totVolume)
1245 {
1246 this->updateFluidInPlace_(globalDofIdx, intQuants, totVolume);
1247 }
1248
1249private:
1250 bool isDefunctParallelWell(std::string wname) const override
1251 {
1252 if (simulator_.gridView().comm().size() == 1)
1253 return false;
1254 const auto& parallelWells = simulator_.vanguard().parallelWells();
1255 std::pair<std::string, bool> value {wname, true};
1256 auto candidate = std::lower_bound(parallelWells.begin(), parallelWells.end(), value);
1257 return candidate == parallelWells.end() || *candidate != value;
1258 }
1259
1260 void updateFluidInPlace_(const ElementContext& elemCtx, const unsigned dofIdx)
1261 {
1262 const auto& intQuants = elemCtx.intensiveQuantities(dofIdx, /*timeIdx=*/0);
1263 const unsigned globalDofIdx = elemCtx.globalSpaceIndex(dofIdx, /*timeIdx=*/0);
1264 const auto totVolume = elemCtx.simulator().model().dofTotalVolume(globalDofIdx);
1265
1266 this->updateFluidInPlace_(globalDofIdx, intQuants, totVolume);
1267 }
1268
1269 void updateFluidInPlace_(const unsigned globalDofIdx,
1270 const IntensiveQuantities& intQuants,
1271 const double totVolume)
1272 {
1273 OPM_TIMEBLOCK_LOCAL(updateFluidInPlace);
1274
1275 this->updateTotalVolumesAndPressures_(globalDofIdx, intQuants, totVolume);
1276
1277 if (this->computeFip_) {
1278 this->updatePhaseInplaceVolumes_(globalDofIdx, intQuants, totVolume);
1279 }
1280 }
1281
1282 void createLocalRegion_(std::vector<int>& region)
1283 {
1284 std::size_t elemIdx = 0;
1285 for (const auto& elem : elements(simulator_.gridView())) {
1286 if (elem.partitionType() != Dune::InteriorEntity) {
1287 region[elemIdx] = 0;
1288 }
1289
1290 ++elemIdx;
1291 }
1292 }
1293
1294 template <typename FluidState>
1295 void aggregateAverageDensityContributions_(const FluidState& fs,
1296 const unsigned int globalDofIdx,
1297 const double porv)
1298 {
1299 auto pvCellValue = RegionPhasePoreVolAverage::CellValue{};
1300 pvCellValue.porv = porv;
1301
1302 for (auto phaseIdx = 0*FluidSystem::numPhases;
1303 phaseIdx < FluidSystem::numPhases; ++phaseIdx)
1304 {
1305 if (! FluidSystem::phaseIsActive(phaseIdx)) {
1306 continue;
1307 }
1308
1309 pvCellValue.value = getValue(fs.density(phaseIdx));
1310 pvCellValue.sat = getValue(fs.saturation(phaseIdx));
1311
1312 this->regionAvgDensity_
1313 ->addCell(globalDofIdx,
1314 RegionPhasePoreVolAverage::Phase { phaseIdx },
1315 pvCellValue);
1316 }
1317 }
1318
1334 data::InterRegFlowMap::FlowRates
1335 getComponentSurfaceRates(const ElementContext& elemCtx,
1336 const Scalar faceArea,
1337 const std::size_t scvfIdx,
1338 const std::size_t timeIdx) const
1339 {
1340 using Component = data::InterRegFlowMap::Component;
1341
1342 auto rates = data::InterRegFlowMap::FlowRates {};
1343
1344 const auto& extQuant = elemCtx.extensiveQuantities(scvfIdx, timeIdx);
1345
1346 const auto alpha = getValue(extQuant.extrusionFactor()) * faceArea;
1347
1348 if (FluidSystem::phaseIsActive(oilPhaseIdx)) {
1349 const auto& up = elemCtx
1350 .intensiveQuantities(extQuant.upstreamIndex(oilPhaseIdx), timeIdx);
1351
1352 using FluidState = std::remove_cv_t<std::remove_reference_t<
1353 decltype(up.fluidState())>>;
1354
1355 const auto pvtReg = up.pvtRegionIndex();
1356
1357 const auto bO = getValue(getInvB_<FluidSystem, FluidState, Scalar>
1358 (up.fluidState(), oilPhaseIdx, pvtReg));
1359
1360 const auto qO = alpha * bO * getValue(extQuant.volumeFlux(oilPhaseIdx));
1361
1362 rates[Component::Oil] += qO;
1363
1364 if (FluidSystem::phaseIsActive(gasPhaseIdx)) {
1365 const auto Rs = getValue(
1366 BlackOil::getRs_<FluidSystem, FluidState, Scalar>
1367 (up.fluidState(), pvtReg));
1368
1369 rates[Component::Gas] += qO * Rs;
1370 rates[Component::Disgas] += qO * Rs;
1371 }
1372 }
1373
1374 if (FluidSystem::phaseIsActive(gasPhaseIdx)) {
1375 const auto& up = elemCtx
1376 .intensiveQuantities(extQuant.upstreamIndex(gasPhaseIdx), timeIdx);
1377
1378 using FluidState = std::remove_cv_t<std::remove_reference_t<
1379 decltype(up.fluidState())>>;
1380
1381 const auto pvtReg = up.pvtRegionIndex();
1382
1383 const auto bG = getValue(getInvB_<FluidSystem, FluidState, Scalar>
1384 (up.fluidState(), gasPhaseIdx, pvtReg));
1385
1386 const auto qG = alpha * bG * getValue(extQuant.volumeFlux(gasPhaseIdx));
1387
1388 rates[Component::Gas] += qG;
1389
1390 if (FluidSystem::phaseIsActive(oilPhaseIdx)) {
1391 const auto Rv = getValue(
1392 BlackOil::getRv_<FluidSystem, FluidState, Scalar>
1393 (up.fluidState(), pvtReg));
1394
1395 rates[Component::Oil] += qG * Rv;
1396 rates[Component::Vapoil] += qG * Rv;
1397 }
1398 }
1399
1400 if (FluidSystem::phaseIsActive(waterPhaseIdx)) {
1401 const auto& up = elemCtx
1402 .intensiveQuantities(extQuant.upstreamIndex(waterPhaseIdx), timeIdx);
1403
1404 using FluidState = std::remove_cv_t<std::remove_reference_t<
1405 decltype(up.fluidState())>>;
1406
1407 const auto pvtReg = up.pvtRegionIndex();
1408
1409 const auto bW = getValue(getInvB_<FluidSystem, FluidState, Scalar>
1410 (up.fluidState(), waterPhaseIdx, pvtReg));
1411
1412 rates[Component::Water] +=
1413 alpha * bW * getValue(extQuant.volumeFlux(waterPhaseIdx));
1414 }
1415
1416 return rates;
1417 }
1418
1419 template <typename FluidState>
1420 Scalar hydroCarbonFraction(const FluidState& fs) const
1421 {
1422 if (this->eclState_.runspec().co2Storage()) {
1423 // CO2 storage: Hydrocarbon volume is full pore-volume.
1424 return 1.0;
1425 }
1426
1427 // Common case. Hydrocarbon volume is fraction occupied by actual
1428 // hydrocarbons.
1429 auto hydrocarbon = Scalar {0};
1430 if (FluidSystem::phaseIsActive(oilPhaseIdx)) {
1431 hydrocarbon += getValue(fs.saturation(oilPhaseIdx));
1432 }
1433
1434 if (FluidSystem::phaseIsActive(gasPhaseIdx)) {
1435 hydrocarbon += getValue(fs.saturation(gasPhaseIdx));
1436 }
1437
1438 return hydrocarbon;
1439 }
1440
1441 void updateTotalVolumesAndPressures_(const unsigned globalDofIdx,
1442 const IntensiveQuantities& intQuants,
1443 const double totVolume)
1444 {
1445 const auto& fs = intQuants.fluidState();
1446
1447 const double pv = totVolume * intQuants.porosity().value();
1448 const auto hydrocarbon = this->hydroCarbonFraction(fs);
1449
1450 if (! this->hydrocarbonPoreVolume_.empty()) {
1451 this->fip_[Inplace::Phase::PoreVolume][globalDofIdx] =
1452 totVolume * intQuants.referencePorosity();
1453
1454 this->dynamicPoreVolume_[globalDofIdx] = pv;
1455 this->hydrocarbonPoreVolume_[globalDofIdx] = pv * hydrocarbon;
1456 }
1457
1458 if (!this->pressureTimesHydrocarbonVolume_.empty() &&
1459 !this->pressureTimesPoreVolume_.empty())
1460 {
1461 assert(this->hydrocarbonPoreVolume_.size() == this->pressureTimesHydrocarbonVolume_.size());
1462 assert(this->fip_[Inplace::Phase::PoreVolume].size() == this->pressureTimesPoreVolume_.size());
1463
1464 if (FluidSystem::phaseIsActive(oilPhaseIdx)) {
1465 this->pressureTimesPoreVolume_[globalDofIdx] =
1466 getValue(fs.pressure(oilPhaseIdx)) * pv;
1467
1468 this->pressureTimesHydrocarbonVolume_[globalDofIdx] =
1469 this->pressureTimesPoreVolume_[globalDofIdx] * hydrocarbon;
1470 }
1471 else if (FluidSystem::phaseIsActive(gasPhaseIdx)) {
1472 this->pressureTimesPoreVolume_[globalDofIdx] =
1473 getValue(fs.pressure(gasPhaseIdx)) * pv;
1474
1475 this->pressureTimesHydrocarbonVolume_[globalDofIdx] =
1476 this->pressureTimesPoreVolume_[globalDofIdx] * hydrocarbon;
1477 }
1478 else if (FluidSystem::phaseIsActive(waterPhaseIdx)) {
1479 this->pressureTimesPoreVolume_[globalDofIdx] =
1480 getValue(fs.pressure(waterPhaseIdx)) * pv;
1481 }
1482 }
1483 }
1484
1485 void updatePhaseInplaceVolumes_(const unsigned globalDofIdx,
1486 const IntensiveQuantities& intQuants,
1487 const double totVolume)
1488 {
1489 std::array<Scalar, FluidSystem::numPhases> fip {};
1490 std::array<Scalar, FluidSystem::numPhases> fipr{}; // at reservoir condition
1491
1492 const auto& fs = intQuants.fluidState();
1493 const auto pv = totVolume * intQuants.porosity().value();
1494
1495 for (unsigned phaseIdx = 0; phaseIdx < FluidSystem::numPhases; ++phaseIdx) {
1496 if (!FluidSystem::phaseIsActive(phaseIdx)) {
1497 continue;
1498 }
1499
1500 const auto b = getValue(fs.invB(phaseIdx));
1501 const auto s = getValue(fs.saturation(phaseIdx));
1502
1503 fipr[phaseIdx] = s * pv;
1504 fip [phaseIdx] = b * fipr[phaseIdx];
1505 }
1506
1507 this->updateInplaceVolumesSurface(globalDofIdx, fip);
1508 this->updateInplaceVolumesReservoir(globalDofIdx, fs, fipr);
1509
1510 if (FluidSystem::phaseIsActive(oilPhaseIdx) &&
1511 FluidSystem::phaseIsActive(gasPhaseIdx))
1512 {
1513 this->updateOilGasDistribution(globalDofIdx, fs, fip);
1514 }
1515
1516 if (FluidSystem::phaseIsActive(waterPhaseIdx) &&
1517 FluidSystem::phaseIsActive(gasPhaseIdx))
1518 {
1519 this->updateGasWaterDistribution(globalDofIdx, fs, fip);
1520 }
1521
1522 if (FluidSystem::phaseIsActive(gasPhaseIdx) &&
1523 (!this->fip_[Inplace::Phase::CO2InGasPhaseInMob].empty() ||
1524 !this->fip_[Inplace::Phase::CO2InGasPhaseMob].empty() ||
1525 !this->fip_[Inplace::Phase::CO2MassInGasPhaseInMob].empty() ||
1526 !this->fip_[Inplace::Phase::CO2MassInGasPhaseMob].empty() ||
1527 !this->fip_[Inplace::Phase::CO2Mass].empty() ||
1528 !this->fip_[Inplace::Phase::CO2MassInGasPhase].empty() ||
1529 !this->fip_[Inplace::Phase::CO2InGasPhaseInMobKrg].empty() ||
1530 !this->fip_[Inplace::Phase::CO2InGasPhaseMobKrg].empty() ||
1531 !this->fip_[Inplace::Phase::CO2MassInGasPhaseInMobKrg].empty() ||
1532 !this->fip_[Inplace::Phase::CO2MassInGasPhaseMobKrg].empty() ||
1533 !this->fip_[Inplace::Phase::CO2MassInGasPhaseEffectiveTrapped].empty() ||
1534 !this->fip_[Inplace::Phase::CO2MassInGasPhaseEffectiveUnTrapped].empty() ||
1535 !this->fip_[Inplace::Phase::CO2MassInGasPhaseMaximumTrapped].empty() ||
1536 !this->fip_[Inplace::Phase::CO2MassInGasPhaseMaximumUnTrapped].empty()))
1537 {
1538 this->updateCO2InGas(globalDofIdx, pv, intQuants);
1539 }
1540
1541 if ((!this->fip_[Inplace::Phase::CO2InWaterPhase].empty() ||
1542 !this->fip_[Inplace::Phase::CO2MassInWaterPhase].empty() ||
1543 !this->fip_[Inplace::Phase::CO2Mass].empty()) &&
1544 (FluidSystem::phaseIsActive(waterPhaseIdx) ||
1545 FluidSystem::phaseIsActive(oilPhaseIdx)))
1546 {
1547 this->updateCO2InWater(globalDofIdx, pv, fs);
1548 }
1549 }
1550
1551 template <typename FIPArray>
1552 void updateInplaceVolumesSurface(const unsigned globalDofIdx,
1553 const FIPArray& fip)
1554 {
1555 if (FluidSystem::phaseIsActive(oilPhaseIdx) &&
1556 !this->fip_[Inplace::Phase::OIL].empty())
1557 {
1558 this->fip_[Inplace::Phase::OIL][globalDofIdx] = fip[oilPhaseIdx];
1559 }
1560
1561 if (FluidSystem::phaseIsActive(oilPhaseIdx) &&
1562 !this->fip_[Inplace::Phase::OilInLiquidPhase].empty())
1563 {
1564 this->fip_[Inplace::Phase::OilInLiquidPhase][globalDofIdx] = fip[oilPhaseIdx];
1565 }
1566
1567 if (FluidSystem::phaseIsActive(gasPhaseIdx) &&
1568 !this->fip_[Inplace::Phase::GAS].empty())
1569 {
1570 this->fip_[Inplace::Phase::GAS][globalDofIdx] = fip[gasPhaseIdx];
1571 }
1572
1573 if (FluidSystem::phaseIsActive(gasPhaseIdx) &&
1574 !this->fip_[Inplace::Phase::GasInGasPhase].empty())
1575 {
1576 this->fip_[Inplace::Phase::GasInGasPhase][globalDofIdx] = fip[gasPhaseIdx];
1577 }
1578
1579 if (FluidSystem::phaseIsActive(waterPhaseIdx) &&
1580 !this->fip_[Inplace::Phase::WATER].empty())
1581 {
1582 this->fip_[Inplace::Phase::WATER][globalDofIdx] = fip[waterPhaseIdx];
1583 }
1584 }
1585
1586 template <typename FluidState, typename FIPArray>
1587 void updateInplaceVolumesReservoir(const unsigned globalDofIdx,
1588 const FluidState& fs,
1589 const FIPArray& fipr)
1590 {
1591 if (FluidSystem::phaseIsActive(oilPhaseIdx) &&
1592 !this->fip_[Inplace::Phase::OilResVolume].empty())
1593 {
1594 this->fip_[Inplace::Phase::OilResVolume][globalDofIdx] = fipr[oilPhaseIdx];
1595 }
1596
1597 if (FluidSystem::phaseIsActive(gasPhaseIdx) &&
1598 !this->fip_[Inplace::Phase::GasResVolume].empty())
1599 {
1600 this->fip_[Inplace::Phase::GasResVolume][globalDofIdx] = fipr[gasPhaseIdx];
1601 }
1602
1603 if (FluidSystem::phaseIsActive(waterPhaseIdx) &&
1604 !this->fip_[Inplace::Phase::WaterResVolume].empty())
1605 {
1606 this->fip_[Inplace::Phase::WaterResVolume][globalDofIdx] = fipr[waterPhaseIdx];
1607 }
1608
1609 if (FluidSystem::phaseIsActive(waterPhaseIdx) &&
1610 !this->fip_[Inplace::Phase::SALT].empty())
1611 {
1612 this->fip_[Inplace::Phase::SALT][globalDofIdx] =
1613 fipr[waterPhaseIdx] * fs.saltConcentration().value();
1614 }
1615 }
1616
1617 template <typename FluidState, typename FIPArray>
1618 void updateOilGasDistribution(const unsigned globalDofIdx,
1619 const FluidState& fs,
1620 const FIPArray& fip)
1621 {
1622 // Gas dissolved in oil and vaporized oil
1623 const auto gasInPlaceLiquid = getValue(fs.Rs()) * fip[oilPhaseIdx];
1624 const auto oilInPlaceGas = getValue(fs.Rv()) * fip[gasPhaseIdx];
1625
1626 if (!this->fip_[Inplace::Phase::GasInLiquidPhase].empty()) {
1627 this->fip_[Inplace::Phase::GasInLiquidPhase][globalDofIdx] = gasInPlaceLiquid;
1628 }
1629
1630 if (!this->fip_[Inplace::Phase::OilInGasPhase].empty()) {
1631 this->fip_[Inplace::Phase::OilInGasPhase][globalDofIdx] = oilInPlaceGas;
1632 }
1633
1634 // Add dissolved gas and vaporized oil to total Fip
1635 if (!this->fip_[Inplace::Phase::OIL].empty()) {
1636 this->fip_[Inplace::Phase::OIL][globalDofIdx] += oilInPlaceGas;
1637 }
1638
1639 if (!this->fip_[Inplace::Phase::GAS].empty()) {
1640 this->fip_[Inplace::Phase::GAS][globalDofIdx] += gasInPlaceLiquid;
1641 }
1642 }
1643
1644 template <typename FluidState, typename FIPArray>
1645 void updateGasWaterDistribution(const unsigned globalDofIdx,
1646 const FluidState& fs,
1647 const FIPArray& fip)
1648 {
1649 // Gas dissolved in water and vaporized water
1650 const auto gasInPlaceWater = getValue(fs.Rsw()) * fip[waterPhaseIdx];
1651 const auto waterInPlaceGas = getValue(fs.Rvw()) * fip[gasPhaseIdx];
1652
1653 if (!this->fip_[Inplace::Phase::WaterInGasPhase].empty()) {
1654 this->fip_[Inplace::Phase::WaterInGasPhase][globalDofIdx] = waterInPlaceGas;
1655 }
1656
1657 if (!this->fip_[Inplace::Phase::WaterInWaterPhase].empty()) {
1658 this->fip_[Inplace::Phase::WaterInWaterPhase][globalDofIdx] = fip[waterPhaseIdx];
1659 }
1660
1661 // For water+gas cases the gas in water is added to the GIPL value
1662 if (!this->fip_[Inplace::Phase::GasInLiquidPhase].empty() &&
1663 !FluidSystem::phaseIsActive(oilPhaseIdx))
1664 {
1665 this->fip_[Inplace::Phase::GasInLiquidPhase][globalDofIdx] = gasInPlaceWater;
1666 }
1667
1668 // Add dissolved gas and vaporized water to total Fip
1669 if (!this->fip_[Inplace::Phase::WATER].empty()) {
1670 this->fip_[Inplace::Phase::WATER][globalDofIdx] += waterInPlaceGas;
1671 }
1672
1673 if (!this->fip_[Inplace::Phase::GAS].empty()) {
1674 this->fip_[Inplace::Phase::GAS][globalDofIdx] += gasInPlaceWater;
1675 }
1676 }
1677
1678 template <typename IntensiveQuantities>
1679 void updateCO2InGas(const unsigned globalDofIdx,
1680 const double pv,
1681 const IntensiveQuantities& intQuants)
1682 {
1683 const auto& scaledDrainageInfo = this->simulator_.problem().materialLawManager()
1684 ->oilWaterScaledEpsInfoDrainage(globalDofIdx);
1685
1686 const auto& fs = intQuants.fluidState();
1687 Scalar sgcr = scaledDrainageInfo.Sgcr;
1688 if (this->simulator_.problem().materialLawManager()->enableHysteresis()) {
1689 const auto& matParams = simulator_.problem().materialLawParams(globalDofIdx);
1690 sgcr = MaterialLaw::trappedGasSaturation(matParams, /*maximumTrapping*/false);
1691 }
1692
1693 const Scalar sg = getValue(fs.saturation(gasPhaseIdx));
1694 const Scalar rhog = getValue(fs.density(gasPhaseIdx));
1695 const Scalar xgW = FluidSystem::phaseIsActive(waterPhaseIdx)
1696 ? FluidSystem::convertRvwToXgW(getValue(fs.Rvw()), fs.pvtRegionIndex())
1697 : FluidSystem::convertRvToXgO(getValue(fs.Rv()), fs.pvtRegionIndex());
1698
1699 const Scalar mM = FluidSystem::molarMass(gasCompIdx, fs.pvtRegionIndex());
1700 const Scalar massGas = (1 - xgW) * pv * rhog;
1701 if (!this->fip_[Inplace::Phase::CO2Mass].empty()) {
1702 this->fip_[Inplace::Phase::CO2Mass][globalDofIdx] = massGas * sg;
1703 }
1704
1705 if (!this->fip_[Inplace::Phase::CO2MassInGasPhase].empty()) {
1706 this->fip_[Inplace::Phase::CO2MassInGasPhase][globalDofIdx] = massGas * sg;
1707 }
1708
1709 if (!this->fip_[Inplace::Phase::CO2InGasPhaseInMob].empty()) {
1710 const Scalar imMobileGas = massGas / mM * std::min(sgcr , sg);
1711 this->fip_[Inplace::Phase::CO2InGasPhaseInMob][globalDofIdx] = imMobileGas;
1712 }
1713
1714 if (!this->fip_[Inplace::Phase::CO2InGasPhaseMob].empty()) {
1715 const Scalar mobileGas = massGas / mM * std::max(Scalar{0.0}, sg - sgcr);
1716 this->fip_[Inplace::Phase::CO2InGasPhaseMob][globalDofIdx] = mobileGas;
1717 }
1718
1719 if (!this->fip_[Inplace::Phase::CO2InGasPhaseInMobKrg].empty()) {
1720 if (sgcr >= sg) {
1721 const Scalar imMobileGasKrg = massGas / mM * sg;
1722 this->fip_[Inplace::Phase::CO2InGasPhaseInMobKrg][globalDofIdx] = imMobileGasKrg;
1723 } else {
1724 this->fip_[Inplace::Phase::CO2InGasPhaseInMobKrg][globalDofIdx] = 0;
1725 }
1726 }
1727
1728 if (!this->fip_[Inplace::Phase::CO2InGasPhaseMobKrg].empty()) {
1729 if (sg > sgcr) {
1730 const Scalar mobileGasKrg = massGas / mM * sg;
1731 this->fip_[Inplace::Phase::CO2InGasPhaseMobKrg][globalDofIdx] = mobileGasKrg;
1732 } else {
1733 this->fip_[Inplace::Phase::CO2InGasPhaseMobKrg][globalDofIdx] = 0;
1734 }
1735 }
1736
1737 if (!this->fip_[Inplace::Phase::CO2MassInGasPhaseInMob].empty()) {
1738 const Scalar imMobileMassGas = massGas * std::min(sgcr , sg);
1739 this->fip_[Inplace::Phase::CO2MassInGasPhaseInMob][globalDofIdx] = imMobileMassGas;
1740 }
1741
1742 if (!this->fip_[Inplace::Phase::CO2MassInGasPhaseMob].empty()) {
1743 const Scalar mobileMassGas = massGas * std::max(Scalar{0.0}, sg - sgcr);
1744 this->fip_[Inplace::Phase::CO2MassInGasPhaseMob][globalDofIdx] = mobileMassGas;
1745 }
1746
1747 if (!this->fip_[Inplace::Phase::CO2MassInGasPhaseInMobKrg].empty()) {
1748 if (sgcr >= sg) {
1749 const Scalar imMobileMassGasKrg = massGas * sg;
1750 this->fip_[Inplace::Phase::CO2MassInGasPhaseInMobKrg][globalDofIdx] = imMobileMassGasKrg;
1751 } else {
1752 this->fip_[Inplace::Phase::CO2MassInGasPhaseInMobKrg][globalDofIdx] = 0;
1753 }
1754 }
1755
1756 if (!this->fip_[Inplace::Phase::CO2MassInGasPhaseMobKrg].empty()) {
1757 if (sg > sgcr) {
1758 const Scalar mobileMassGasKrg = massGas * sg;
1759 this->fip_[Inplace::Phase::CO2MassInGasPhaseMobKrg][globalDofIdx] = mobileMassGasKrg;
1760 } else {
1761 this->fip_[Inplace::Phase::CO2MassInGasPhaseMobKrg][globalDofIdx] = 0;
1762 }
1763 }
1764
1765 if (!this->fip_[Inplace::Phase::CO2MassInGasPhaseMaximumTrapped].empty() ||
1766 !this->fip_[Inplace::Phase::CO2MassInGasPhaseMaximumUnTrapped].empty() ) {
1767 Scalar trappedGasSaturation = scaledDrainageInfo.Sgcr;
1768 if (this->simulator_.problem().materialLawManager()->enableHysteresis()) {
1769 const auto& matParams = simulator_.problem().materialLawParams(globalDofIdx);
1770 // Get the maximum trapped gas saturation
1771 trappedGasSaturation = MaterialLaw::trappedGasSaturation(matParams, /*maximumTrapping*/true);
1772 }
1773 if (!this->fip_[Inplace::Phase::CO2MassInGasPhaseMaximumTrapped].empty()) {
1774 const Scalar imMobileMassGas = massGas * std::min(trappedGasSaturation , sg);
1775 this->fip_[Inplace::Phase::CO2MassInGasPhaseMaximumTrapped][globalDofIdx] = imMobileMassGas;
1776 }
1777 if (!this->fip_[Inplace::Phase::CO2MassInGasPhaseMaximumUnTrapped].empty()) {
1778 const Scalar mobileMassGas = massGas * std::max(Scalar{0.0}, sg - trappedGasSaturation);
1779 this->fip_[Inplace::Phase::CO2MassInGasPhaseMaximumUnTrapped][globalDofIdx] = mobileMassGas;
1780 }
1781 }
1782
1783 if (!this->fip_[Inplace::Phase::CO2MassInGasPhaseEffectiveTrapped].empty() ||
1784 !this->fip_[Inplace::Phase::CO2MassInGasPhaseEffectiveUnTrapped].empty()) {
1785 Scalar trappedGasSaturation = scaledDrainageInfo.Sgcr;
1786 if (this->simulator_.problem().materialLawManager()->enableHysteresis()) {
1787 const auto& matParams = simulator_.problem().materialLawParams(globalDofIdx);
1788 const double krg = getValue(intQuants.relativePermeability(gasPhaseIdx));
1789 trappedGasSaturation = MaterialLaw::strandedGasSaturation(matParams, sg, krg);
1790 }
1791 if (!this->fip_[Inplace::Phase::CO2MassInGasPhaseEffectiveTrapped].empty()) {
1792 const Scalar imMobileMassGas = massGas * std::min(trappedGasSaturation , sg);
1793 this->fip_[Inplace::Phase::CO2MassInGasPhaseEffectiveTrapped][globalDofIdx] = imMobileMassGas;
1794 }
1795 if (!this->fip_[Inplace::Phase::CO2MassInGasPhaseEffectiveUnTrapped].empty()) {
1796 const Scalar mobileMassGas = massGas * std::max(Scalar{0.0}, sg - trappedGasSaturation);
1797 this->fip_[Inplace::Phase::CO2MassInGasPhaseEffectiveUnTrapped][globalDofIdx] = mobileMassGas;
1798 }
1799 }
1800 }
1801
1802 template <typename FluidState>
1803 void updateCO2InWater(const unsigned globalDofIdx,
1804 const double pv,
1805 const FluidState& fs)
1806 {
1807 const auto co2InWater = FluidSystem::phaseIsActive(oilPhaseIdx)
1808 ? this->co2InWaterFromOil(fs, pv)
1809 : this->co2InWaterFromWater(fs, pv);
1810
1811 const Scalar mM = FluidSystem::molarMass(gasCompIdx, fs.pvtRegionIndex());
1812 if (!this->fip_[Inplace::Phase::CO2Mass].empty()) {
1813 this->fip_[Inplace::Phase::CO2Mass][globalDofIdx] += co2InWater * mM;
1814 }
1815 if (!this->fip_[Inplace::Phase::CO2MassInWaterPhase].empty()) {
1816 this->fip_[Inplace::Phase::CO2MassInWaterPhase][globalDofIdx] = co2InWater * mM;
1817 }
1818 if (!this->fip_[Inplace::Phase::CO2InWaterPhase].empty()) {
1819 this->fip_[Inplace::Phase::CO2InWaterPhase][globalDofIdx] = co2InWater;
1820 }
1821 }
1822
1823 template <typename FluidState>
1824 Scalar co2InWaterFromWater(const FluidState& fs, const double pv) const
1825 {
1826 const double rhow = getValue(fs.density(waterPhaseIdx));
1827 const double sw = getValue(fs.saturation(waterPhaseIdx));
1828 const double xwG = FluidSystem::convertRswToXwG(getValue(fs.Rsw()), fs.pvtRegionIndex());
1829
1830 const Scalar mM = FluidSystem::molarMass(gasCompIdx, fs.pvtRegionIndex());
1831
1832 return xwG * pv * rhow * sw / mM;
1833 }
1834
1835 template <typename FluidState>
1836 Scalar co2InWaterFromOil(const FluidState& fs, const double pv) const
1837 {
1838 const double rhoo = getValue(fs.density(oilPhaseIdx));
1839 const double so = getValue(fs.saturation(oilPhaseIdx));
1840 const double xoG = FluidSystem::convertRsToXoG(getValue(fs.Rs()), fs.pvtRegionIndex());
1841
1842 const Scalar mM = FluidSystem::molarMass(gasCompIdx, fs.pvtRegionIndex());
1843
1844 return xoG * pv * rhoo * so / mM;
1845 }
1846
1847 const Simulator& simulator_;
1848};
1849
1850} // namespace Opm
1851
1852#endif // OPM_OUTPUT_BLACK_OIL_MODULE_HPP
Declares the properties required by the black oil model.
The base class for the element-centered finite-volume discretization scheme.
Definition: ecfvdiscretization.hh:147
Definition: GenericOutputBlackoilModule.hpp:61
ScalarBuffer mFracCo2_
Definition: GenericOutputBlackoilModule.hpp:478
ScalarBuffer strainXY_
Definition: GenericOutputBlackoilModule.hpp:528
std::map< std::pair< std::string, int >, double > blockData_
Definition: GenericOutputBlackoilModule.hpp:552
std::array< ScalarBuffer, numPhases > relativePermeability_
Definition: GenericOutputBlackoilModule.hpp:536
ScalarBuffer dispY_
Definition: GenericOutputBlackoilModule.hpp:511
ScalarBuffer delstressXZ_
Definition: GenericOutputBlackoilModule.hpp:523
ScalarBuffer fluidPressure_
Definition: GenericOutputBlackoilModule.hpp:457
ScalarBuffer mFracGas_
Definition: GenericOutputBlackoilModule.hpp:477
ScalarBuffer strainYZ_
Definition: GenericOutputBlackoilModule.hpp:530
ScalarBuffer extboX_
Definition: GenericOutputBlackoilModule.hpp:473
std::array< ScalarBuffer, numPhases > density_
Definition: GenericOutputBlackoilModule.hpp:534
ScalarBuffer saturatedOilFormationVolumeFactor_
Definition: GenericOutputBlackoilModule.hpp:494
ScalarBuffer cBiofilm_
Definition: GenericOutputBlackoilModule.hpp:499
ScalarBuffer overburdenPressure_
Definition: GenericOutputBlackoilModule.hpp:463
ScalarBuffer gasDissolutionFactorInWater_
Definition: GenericOutputBlackoilModule.hpp:488
ScalarBuffer delstressYZ_
Definition: GenericOutputBlackoilModule.hpp:524
const EclipseState & eclState_
Definition: GenericOutputBlackoilModule.hpp:384
ScalarBuffer delstressZZ_
Definition: GenericOutputBlackoilModule.hpp:521
ScalarBuffer swmin_
Definition: GenericOutputBlackoilModule.hpp:484
ScalarBuffer rockCompPorvMultiplier_
Definition: GenericOutputBlackoilModule.hpp:492
ScalarBuffer dewPointPressure_
Definition: GenericOutputBlackoilModule.hpp:491
bool forceDisableFipresvOutput_
Definition: GenericOutputBlackoilModule.hpp:406
ScalarBuffer mechPotentialPressForce_
Definition: GenericOutputBlackoilModule.hpp:507
std::vector< ScalarBuffer > freeTracerConcentrations_
Definition: GenericOutputBlackoilModule.hpp:538
std::vector< ScalarBuffer > solTracerConcentrations_
Definition: GenericOutputBlackoilModule.hpp:539
std::vector< int > failedCellsPb_
Definition: GenericOutputBlackoilModule.hpp:448
std::unordered_map< Inplace::Phase, ScalarBuffer > fip_
Definition: GenericOutputBlackoilModule.hpp:441
ScalarBuffer permFact_
Definition: GenericOutputBlackoilModule.hpp:472
ScalarBuffer rsw_
Definition: GenericOutputBlackoilModule.hpp:460
ScalarBuffer pcog_
Definition: GenericOutputBlackoilModule.hpp:503
std::optional< RegionPhasePoreVolAverage > regionAvgDensity_
Definition: GenericOutputBlackoilModule.hpp:559
ScalarBuffer dispZ_
Definition: GenericOutputBlackoilModule.hpp:512
std::array< ScalarBuffer, numPhases > invB_
Definition: GenericOutputBlackoilModule.hpp:533
ScalarBuffer pSalt_
Definition: GenericOutputBlackoilModule.hpp:471
ScalarBuffer stressZZ_
Definition: GenericOutputBlackoilModule.hpp:515
std::map< std::size_t, Scalar > waterConnectionSaturations_
Definition: GenericOutputBlackoilModule.hpp:550
ScalarBuffer cFoam_
Definition: GenericOutputBlackoilModule.hpp:469
ScalarBuffer bubblePointPressure_
Definition: GenericOutputBlackoilModule.hpp:490
ScalarBuffer temperature_
Definition: GenericOutputBlackoilModule.hpp:458
ScalarBuffer ppcw_
Definition: GenericOutputBlackoilModule.hpp:485
std::array< FlowsData< double >, 3 > floresn_
Definition: GenericOutputBlackoilModule.hpp:546
ScalarBuffer stressYZ_
Definition: GenericOutputBlackoilModule.hpp:518
ScalarBuffer rockCompTransMultiplier_
Definition: GenericOutputBlackoilModule.hpp:495
ScalarBuffer stressXZ_
Definition: GenericOutputBlackoilModule.hpp:517
ScalarBuffer mechPotentialForce_
Definition: GenericOutputBlackoilModule.hpp:506
ScalarBuffer dynamicPoreVolume_
Definition: GenericOutputBlackoilModule.hpp:455
ScalarBuffer minimumOilPressure_
Definition: GenericOutputBlackoilModule.hpp:493
ScalarBuffer gasFormationVolumeFactor_
Definition: GenericOutputBlackoilModule.hpp:451
std::array< ScalarBuffer, numPhases > residual_
Definition: GenericOutputBlackoilModule.hpp:541
ScalarBuffer shmax_
Definition: GenericOutputBlackoilModule.hpp:482
ScalarBuffer strainYY_
Definition: GenericOutputBlackoilModule.hpp:526
ScalarBuffer oilSaturationPressure_
Definition: GenericOutputBlackoilModule.hpp:464
InterRegFlowMap interRegionFlows_
Definition: GenericOutputBlackoilModule.hpp:390
ScalarBuffer pcgw_
Definition: GenericOutputBlackoilModule.hpp:501
ScalarBuffer cPolymer_
Definition: GenericOutputBlackoilModule.hpp:468
ScalarBuffer cCalcite_
Definition: GenericOutputBlackoilModule.hpp:500
void setupBlockData(std::function< bool(int)> isCartIdxOnThisRank)
ScalarBuffer rvw_
Definition: GenericOutputBlackoilModule.hpp:462
std::array< ScalarBuffer, numPhases > saturation_
Definition: GenericOutputBlackoilModule.hpp:532
std::unordered_map< std::string, std::vector< int > > regions_
Definition: GenericOutputBlackoilModule.hpp:442
std::array< std::array< ScalarBuffer, numPhases >, 6 > flores_
Definition: GenericOutputBlackoilModule.hpp:544
ScalarBuffer rPorV_
Definition: GenericOutputBlackoilModule.hpp:456
ScalarBuffer oilVaporizationFactor_
Definition: GenericOutputBlackoilModule.hpp:487
std::vector< int > failedCellsPd_
Definition: GenericOutputBlackoilModule.hpp:449
std::array< FlowsData< double >, 3 > flowsn_
Definition: GenericOutputBlackoilModule.hpp:547
ScalarBuffer rs_
Definition: GenericOutputBlackoilModule.hpp:459
ScalarBuffer extboZ_
Definition: GenericOutputBlackoilModule.hpp:475
ScalarBuffer drsdtcon_
Definition: GenericOutputBlackoilModule.hpp:465
ScalarBuffer sSol_
Definition: GenericOutputBlackoilModule.hpp:466
ScalarBuffer stressYY_
Definition: GenericOutputBlackoilModule.hpp:514
ScalarBuffer delstressXY_
Definition: GenericOutputBlackoilModule.hpp:522
ScalarBuffer strainXZ_
Definition: GenericOutputBlackoilModule.hpp:529
void doAllocBuffers(unsigned bufferSize, unsigned reportStepNum, const bool substep, const bool log, const bool isRestart, const bool vapparsActive, const bool enablePCHysteresis, const bool enableNonWettingHysteresis, const bool enableWettingHysteresis, unsigned numTracers, const std::vector< bool > &enableSolTracers, unsigned numOutputNnc)
ScalarBuffer pressureTimesPoreVolume_
Definition: GenericOutputBlackoilModule.hpp:453
ScalarBuffer dispX_
Definition: GenericOutputBlackoilModule.hpp:510
ScalarBuffer gasDissolutionFactor_
Definition: GenericOutputBlackoilModule.hpp:486
ScalarBuffer strainZZ_
Definition: GenericOutputBlackoilModule.hpp:527
ScalarBuffer stressXX_
Definition: GenericOutputBlackoilModule.hpp:513
std::array< ScalarBuffer, numPhases > viscosity_
Definition: GenericOutputBlackoilModule.hpp:535
bool forceDisableFipOutput_
Definition: GenericOutputBlackoilModule.hpp:405
std::array< std::array< ScalarBuffer, numPhases >, 6 > flows_
Definition: GenericOutputBlackoilModule.hpp:543
ScalarBuffer soMax_
Definition: GenericOutputBlackoilModule.hpp:479
ScalarBuffer sgmax_
Definition: GenericOutputBlackoilModule.hpp:481
std::map< std::size_t, Scalar > oilConnectionPressures_
Definition: GenericOutputBlackoilModule.hpp:549
ScalarBuffer stressXY_
Definition: GenericOutputBlackoilModule.hpp:516
ScalarBuffer strainXX_
Definition: GenericOutputBlackoilModule.hpp:525
ScalarBuffer somin_
Definition: GenericOutputBlackoilModule.hpp:483
ScalarBuffer hydrocarbonPoreVolume_
Definition: GenericOutputBlackoilModule.hpp:452
ScalarBuffer cOxygen_
Definition: GenericOutputBlackoilModule.hpp:497
ScalarBuffer delstressXX_
Definition: GenericOutputBlackoilModule.hpp:519
ScalarBuffer waterVaporizationFactor_
Definition: GenericOutputBlackoilModule.hpp:489
ScalarBuffer cSalt_
Definition: GenericOutputBlackoilModule.hpp:470
ScalarBuffer rv_
Definition: GenericOutputBlackoilModule.hpp:461
ScalarBuffer pcow_
Definition: GenericOutputBlackoilModule.hpp:502
std::map< std::size_t, Scalar > gasConnectionSaturations_
Definition: GenericOutputBlackoilModule.hpp:551
ScalarBuffer mechPotentialTempForce_
Definition: GenericOutputBlackoilModule.hpp:508
ScalarBuffer delstressYY_
Definition: GenericOutputBlackoilModule.hpp:520
ScalarBuffer cUrea_
Definition: GenericOutputBlackoilModule.hpp:498
ScalarBuffer swMax_
Definition: GenericOutputBlackoilModule.hpp:480
ScalarBuffer cMicrobes_
Definition: GenericOutputBlackoilModule.hpp:496
ScalarBuffer mFracOil_
Definition: GenericOutputBlackoilModule.hpp:476
ScalarBuffer pressureTimesHydrocarbonVolume_
Definition: GenericOutputBlackoilModule.hpp:454
ScalarBuffer rswSol_
Definition: GenericOutputBlackoilModule.hpp:467
ScalarBuffer extboY_
Definition: GenericOutputBlackoilModule.hpp:474
Inter-region flow accumulation maps for all region definition arrays.
Definition: InterRegFlows.hpp:179
void addConnection(const Cell &source, const Cell &destination, const data::InterRegFlowMap::FlowRates &rates)
void clear()
Clear all internal buffers, but preserve allocated capacity.
Output module for the results black oil model writing in ECL binary format.
Definition: OutputBlackoilModule.hpp:90
static void registerParameters()
Register all run-time parameters for the Vtk output module.
Definition: OutputBlackoilModule.hpp:182
void processElement(const ElementContext &elemCtx)
Modify the internal buffers according to the intensive quanties relevant for an element.
Definition: OutputBlackoilModule.hpp:272
void initializeFluxData()
Prepare for capturing connection fluxes, particularly to account for inter-region flows.
Definition: OutputBlackoilModule.hpp:1108
void allocBuffers(const unsigned bufferSize, const unsigned reportStepNum, const bool substep, const bool log, const bool isRestart)
Allocate memory for the scalar fields we would like to write to ECL output files.
Definition: OutputBlackoilModule.hpp:197
void processFluxes(const ElementContext &elemCtx, ActiveIndex &&activeIndex, CartesianIndex &&cartesianIndex)
Capture connection fluxes, particularly to account for inter-region flows.
Definition: OutputBlackoilModule.hpp:1071
OutputBlackOilModule(const Simulator &simulator, const SummaryConfig &smryCfg, const CollectDataToIORankType &collectToIORank)
Definition: OutputBlackoilModule.hpp:119
void assignToFluidState(FluidState &fs, unsigned elemIdx) const
Definition: OutputBlackoilModule.hpp:1132
void initHysteresisParams(Simulator &simulator, unsigned elemIdx) const
Definition: OutputBlackoilModule.hpp:1170
void updateFluidInPlace(const ElementContext &elemCtx)
Definition: OutputBlackoilModule.hpp:1235
void processElementFlows(const ElementContext &elemCtx)
Definition: OutputBlackoilModule.hpp:728
const InterRegFlowMap & getInterRegFlows() const
Get read-only access to collection of inter-region flows.
Definition: OutputBlackoilModule.hpp:1126
void processElementBlockData(const ElementContext &elemCtx)
Definition: OutputBlackoilModule.hpp:818
void processElementMech(const ElementContext &elemCtx)
Definition: OutputBlackoilModule.hpp:223
void finalizeFluxData()
Finalize capturing connection fluxes.
Definition: OutputBlackoilModule.hpp:1118
void updateFluidInPlace(const unsigned globalDofIdx, const IntensiveQuantities &intQuants, const double totVolume)
Definition: OutputBlackoilModule.hpp:1242
Declare the properties used by the infrastructure code of the finite volume discretizations.
Definition: blackoilnewtonmethodparams.hpp:31
Definition: blackoilboundaryratevector.hh:37
std::string moduleVersionName()
constexpr auto getPropValue()
get the value data member of a property
Definition: propertysystem.hh:242
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:235
This file provides the infrastructure to retrieve run-time parameters.
The Opm property system, traits with inheritance.
Minimal characteristics of a cell from a simulation grid.
Definition: InterRegFlows.hpp:50
Definition: OutputBlackoilModule.hpp:70
static constexpr bool value
Definition: OutputBlackoilModule.hpp:70
Definition: OutputBlackoilModule.hpp:71
static constexpr bool value
Definition: OutputBlackoilModule.hpp:71
Compile-time disambiguation type for phases.
Definition: RegionPhasePVAverage.hpp:59
unsigned int ix
Phase index.
Definition: RegionPhasePVAverage.hpp:61
Compile-time disambiguation type for regions.
Definition: RegionPhasePVAverage.hpp:66