28#ifndef OPM_TRACER_MODEL_HPP
29#define OPM_TRACER_MODEL_HPP
31#include <opm/common/OpmLog/OpmLog.hpp>
32#include <opm/common/TimingMacros.hpp>
34#include <opm/input/eclipse/EclipseState/Aquifer/AquiferConfig.hpp>
35#include <opm/input/eclipse/Schedule/Well/Well.hpp>
36#include <opm/input/eclipse/Schedule/Well/WellConnections.hpp>
38#include <opm/grid/utility/ElementChunks.hpp>
53#include <unordered_map>
56#include <fmt/format.h>
60template<
class TypeTag,
class MyTypeTag>
74template <
class TypeTag>
76 GetPropType<TypeTag, Properties::GridView>,
77 GetPropType<TypeTag, Properties::DofMapper>,
78 GetPropType<TypeTag, Properties::Stencil>,
79 GetPropType<TypeTag, Properties::FluidSystem>,
80 GetPropType<TypeTag, Properties::Scalar>>
98 using TracerEvaluation = DenseAd::Evaluation<Scalar,1>;
104 enum { numEq = getPropValue<TypeTag, Properties::NumEq>() };
105 enum { numPhases = FluidSystem::numPhases };
106 enum { waterPhaseIdx = FluidSystem::waterPhaseIdx };
107 enum { oilPhaseIdx = FluidSystem::oilPhaseIdx };
108 enum { gasPhaseIdx = FluidSystem::gasPhaseIdx };
112 :
BaseType(simulator.vanguard().gridView(),
113 simulator.vanguard().eclState(),
114 simulator.vanguard().cartesianIndexMapper(),
115 simulator.model().dofMapper(),
116 simulator.vanguard().cellCentroids())
118 ,
tbatch({waterPhaseIdx, oilPhaseIdx, gasPhaseIdx})
147 gasPhaseIdx, oilPhaseIdx, waterPhaseIdx);
154 for (std::size_t tracerIdx = 0; tracerIdx < this->
tracerPhaseIdx_.size(); ++tracerIdx) {
156 if (! FluidSystem::phaseIsActive(FluidSystem::waterPhaseIdx)){
157 throw std::runtime_error(
"Water tracer specified for non-water fluid system: " +
158 this->
name(tracerIdx));
163 else if (this->
tracerPhaseIdx_[tracerIdx] == FluidSystem::oilPhaseIdx) {
164 if (! FluidSystem::phaseIsActive(FluidSystem::oilPhaseIdx)){
165 throw std::runtime_error(
"Oil tracer specified for non-oil fluid system: " +
166 this->
name(tracerIdx));
171 else if (this->
tracerPhaseIdx_[tracerIdx] == FluidSystem::gasPhaseIdx) {
172 if (! FluidSystem::phaseIsActive(FluidSystem::gasPhaseIdx)){
173 throw std::runtime_error(
"Gas tracer specified for non-gas fluid system: " +
174 this->
name(tracerIdx));
193 for (
auto& tr : this->
tbatch) {
194 if (tr.numTracer() != 0) {
199 tr.mat = std::make_unique<TracerMatrix>(*base);
206 const auto& comm =
simulator_.vanguard().grid().comm();
208 if (comm.rank() == 0) {
209 global_logger.logMessages();
219 OPM_TIMEBLOCK(tracerUpdateCache);
232 OPM_TIMEBLOCK(tracerAdvance);
240 template <
class Restarter>
250 template <
class Restarter>
254 template<
class Serializer>
257 serializer(
static_cast<BaseType&
>(*
this));
267 template<TracerTypeIdx Index>
269 const unsigned globalDofIdx,
270 const unsigned timeIdx)
const
272 const auto& intQuants =
simulator_.model().intensiveQuantities(globalDofIdx, timeIdx);
273 const auto& fs = intQuants.fluidState();
274 constexpr Scalar min_volume = 1e-10;
277 return std::max(decay<Scalar>(fs.saturation(tracerPhaseIdx)) *
278 decay<Scalar>(fs.invB(tracerPhaseIdx)) *
279 decay<Scalar>(intQuants.porosity()),
283 if (tracerPhaseIdx == FluidSystem::oilPhaseIdx && FluidSystem::enableVaporizedOil()) {
284 return std::max(decay<Scalar>(fs.saturation(FluidSystem::gasPhaseIdx)) *
285 decay<Scalar>(fs.invB(FluidSystem::gasPhaseIdx)) *
286 decay<Scalar>(fs.Rv()) *
287 decay<Scalar>(intQuants.porosity()),
292 else if (tracerPhaseIdx == FluidSystem::gasPhaseIdx && FluidSystem::enableDissolvedGas()) {
293 return std::max(decay<Scalar>(fs.saturation(FluidSystem::oilPhaseIdx)) *
294 decay<Scalar>(fs.invB(FluidSystem::oilPhaseIdx)) *
295 decay<Scalar>(fs.Rs()) *
296 decay<Scalar>(intQuants.porosity()),
304 template<TracerTypeIdx Index>
305 std::pair<TracerEvaluation, bool>
307 const ElementContext& elemCtx,
308 const unsigned scvfIdx,
309 const unsigned timeIdx)
const
311 const auto& stencil = elemCtx.stencil(timeIdx);
312 const auto& scvf = stencil.interiorFace(scvfIdx);
314 const auto& extQuants = elemCtx.extensiveQuantities(scvfIdx, timeIdx);
315 const unsigned inIdx = extQuants.interiorIndex();
321 upIdx = extQuants.upstreamIndex(tracerPhaseIdx);
322 const auto& intQuants = elemCtx.intensiveQuantities(upIdx, timeIdx);
323 const auto& fs = intQuants.fluidState();
324 v = decay<Scalar>(extQuants.volumeFlux(tracerPhaseIdx)) *
325 decay<Scalar>(fs.invB(tracerPhaseIdx));
327 if (tracerPhaseIdx == FluidSystem::oilPhaseIdx && FluidSystem::enableVaporizedOil()) {
328 upIdx = extQuants.upstreamIndex(FluidSystem::gasPhaseIdx);
330 const auto& intQuants = elemCtx.intensiveQuantities(upIdx, timeIdx);
331 const auto& fs = intQuants.fluidState();
332 v = decay<Scalar>(fs.invB(FluidSystem::gasPhaseIdx)) *
333 decay<Scalar>(extQuants.volumeFlux(FluidSystem::gasPhaseIdx)) *
334 decay<Scalar>(fs.Rv());
337 else if (tracerPhaseIdx == FluidSystem::gasPhaseIdx && FluidSystem::enableDissolvedGas()) {
338 upIdx = extQuants.upstreamIndex(FluidSystem::oilPhaseIdx);
340 const auto& intQuants = elemCtx.intensiveQuantities(upIdx, timeIdx);
341 const auto& fs = intQuants.fluidState();
342 v = decay<Scalar>(fs.invB(FluidSystem::oilPhaseIdx)) *
343 decay<Scalar>(extQuants.volumeFlux(FluidSystem::oilPhaseIdx)) *
344 decay<Scalar>(fs.Rs());
352 const Scalar A = scvf.area();
353 return inIdx == upIdx
354 ? std::pair{A * v * variable<TracerEvaluation>(1.0, 0),
true}
355 : std::pair{A * v,
false};
358 template<TracerTypeIdx Index,
class TrRe>
366 return tr.storageOfTimeIndex1_[tIdx][I][
Index];
368 return computeVolume_<Index>(tr.phaseIdx_, I1, 1) *
369 tr.concentration_[tIdx][I1][
Index];
375 const ElementContext& elemCtx,
376 const Scalar scvVolume,
382 if (tr.numTracer() == 0) {
386 const TracerEvaluation fVol = computeVolume_<Free>(tr.phaseIdx_, I, 0) * variable<TracerEvaluation>(1.0, 0);
387 const TracerEvaluation sVol = computeVolume_<Solution>(tr.phaseIdx_, I, 0) * variable<TracerEvaluation>(1.0, 0);
388 dVol_[
Solution][tr.phaseIdx_][I] += sVol.value() * scvVolume -
vol1_[1][tr.phaseIdx_][I];
389 dVol_[
Free][tr.phaseIdx_][I] += fVol.value() * scvVolume -
vol1_[0][tr.phaseIdx_][I];
390 for (
int tIdx = 0; tIdx < tr.numTracer(); ++tIdx) {
392 const Scalar fStorageOfTimeIndex0 = fVol.value() * tr.concentration_[tIdx][I][
Free];
393 const Scalar fLocalStorage = (fStorageOfTimeIndex0 - storage1_<Free>(tr, tIdx, I, I1,
394 elemCtx.enableStorageCache())) * scvVolume / dt;
395 tr.residual_[tIdx][I][
Free] += fLocalStorage;
398 const Scalar sStorageOfTimeIndex0 = sVol.value() * tr.concentration_[tIdx][I][
Solution];
399 const Scalar sLocalStorage = (sStorageOfTimeIndex0 - storage1_<Solution>(tr, tIdx, I, I1,
400 elemCtx.enableStorageCache())) * scvVolume / dt;
401 tr.residual_[tIdx][I][
Solution] += sLocalStorage;
405 (*tr.mat)[I][I][
Free][
Free] += fVol.derivative(0) * scvVolume/dt;
411 const ElementContext& elemCtx,
417 if (tr.numTracer() == 0) {
421 const auto& [fFlux, isUpF] = computeFlux_<Free>(tr.phaseIdx_, elemCtx, scvfIdx, 0);
422 const auto& [sFlux, isUpS] = computeFlux_<Solution>(tr.phaseIdx_, elemCtx, scvfIdx, 0);
424 dVol_[
Free][tr.phaseIdx_][I] += fFlux.value() * dt;
425 const int fGlobalUpIdx = isUpF ? I : J;
426 const int sGlobalUpIdx = isUpS ? I : J;
427 for (
int tIdx = 0; tIdx < tr.numTracer(); ++tIdx) {
429 tr.residual_[tIdx][I][
Free] += fFlux.value()*tr.concentration_[tIdx][fGlobalUpIdx][
Free];
430 tr.residual_[tIdx][I][
Solution] += sFlux.value()*tr.concentration_[tIdx][sGlobalUpIdx][
Solution];
435 (*tr.mat)[J][I][
Free][
Free] = -fFlux.derivative(0);
436 (*tr.mat)[I][I][
Free][
Free] += fFlux.derivative(0);
444 template<
class TrRe,
class Well>
448 if (tr.numTracer() == 0) {
452 const auto& eclWell = well.wellEcl();
458 auto* mswTracerRate = eclWell.isMultiSegment()
461 for (
int tIdx = 0; tIdx < tr.numTracer(); ++tIdx) {
462 tracerRate[tr.idx_[tIdx]] = {this->
name(tr.idx_[tIdx]), 0.0};
463 freeTracerRate[tr.idx_[tIdx]] = {this->
wellfname(tr.idx_[tIdx]), 0.0};
464 solTracerRate[tr.idx_[tIdx]] = {this->
wellsname(tr.idx_[tIdx]), 0.0};
465 if (eclWell.isMultiSegment()) {
466 auto& wtr = mswTracerRate->at(tr.idx_[tIdx]) = {this->
name(tr.idx_[tIdx])};;
467 wtr.rate.reserve(eclWell.getConnections().size());
468 for (std::size_t i = 0; i < eclWell.getConnections().size(); ++i) {
469 wtr.rate.emplace(eclWell.getConnections().get(i).segment(), 0.0);
474 std::vector<Scalar> wtracer(tr.numTracer());
475 for (
int tIdx = 0; tIdx < tr.numTracer(); ++tIdx) {
477 simulator_.problem().wellModel().summaryState());
481 const auto& ws =
simulator_.problem().wellModel().wellState().well(well.name());
482 const auto well_eff = well.wellEfficiencyFactor();
483 for (std::size_t i = 0; i < ws.perf_data.size(); ++i) {
484 const auto I = ws.perf_data.cell_index[i];
485 const Scalar rate = well.volumetricSurfaceRateForConnection(I, tr.phaseIdx_);
488 if (tr.phaseIdx_ == FluidSystem::oilPhaseIdx && FluidSystem::enableVaporizedOil()) {
489 rate_s = ws.perf_data.phase_mixing_rates[i][ws.vaporized_oil] * well_eff;
491 else if (tr.phaseIdx_ == FluidSystem::gasPhaseIdx && FluidSystem::enableDissolvedGas()) {
492 rate_s = ws.perf_data.phase_mixing_rates[i][ws.dissolved_gas] * well_eff;
498 const Scalar rate_f = rate - rate_s;
500 for (
int tIdx = 0; tIdx < tr.numTracer(); ++tIdx) {
501 const Scalar delta = rate_f * wtracer[tIdx];
503 tr.residual_[tIdx][I][
Free] -= delta;
507 tracerRate[tr.idx_[tIdx]].rate += delta;
508 freeTracerRate[tr.idx_[tIdx]].rate += delta;
509 if (eclWell.isMultiSegment()) {
510 (*mswTracerRate)[tr.idx_[tIdx]].rate[eclWell.getConnections().get(i).segment()] += delta;
513 dVol_[
Free][tr.phaseIdx_][I] -= rate_f * dt;
515 else if (rate_f < 0) {
516 for (
int tIdx = 0; tIdx < tr.numTracer(); ++tIdx) {
517 const Scalar delta = rate_f * wtracer[tIdx];
520 tracerRate[tr.idx_[tIdx]].rate += delta;
521 freeTracerRate[tr.idx_[tIdx]].rate += delta;
524 tr.residual_[tIdx][I][
Free] -= rate_f * tr.concentration_[tIdx][I][
Free];
526 dVol_[
Free][tr.phaseIdx_][I] -= rate_f * dt;
529 (*tr.mat)[I][I][
Free][
Free] -= rate_f * variable<TracerEvaluation>(1.0, 0).derivative(0);
532 for (
int tIdx = 0; tIdx < tr.numTracer(); ++tIdx) {
534 tr.residual_[tIdx][I][
Solution] -= rate_s * tr.concentration_[tIdx][I][
Solution];
539 (*tr.mat)[I][I][
Solution][
Solution] -= rate_s * variable<TracerEvaluation>(1.0, 0).derivative(0);
549 if (tr.numTracer() == 0) {
554 if (tr.phaseIdx_ == FluidSystem::waterPhaseIdx ||
555 (tr.phaseIdx_ == FluidSystem::gasPhaseIdx && !FluidSystem::enableDissolvedGas()) ||
556 (tr.phaseIdx_ == FluidSystem::oilPhaseIdx && !FluidSystem::enableVaporizedOil()))
562 const Scalar& dfVol =
dVol_[
Free][tr.phaseIdx_][I];
565 for (
int tIdx = 0; tIdx < tr.numTracer(); ++tIdx) {
567 const auto delta = (dfVol / dt) * tr.concentration_[tIdx][I][
Free];
568 tr.residual_[tIdx][I][
Free] -= delta;
569 tr.residual_[tIdx][I][
Solution] += delta;
572 const auto delta = (dsVol / dt) * tr.concentration_[tIdx][I][
Solution];
573 tr.residual_[tIdx][I][
Free] += delta;
574 tr.residual_[tIdx][I][
Solution] -= delta;
580 const auto delta = (dfVol / dt) * variable<TracerEvaluation>(1.0, 0).derivative(0);
581 (*tr.mat)[I][I][
Free][
Free] -= delta;
585 const auto delta = (dsVol / dt) * variable<TracerEvaluation>(1.0, 0).derivative(0);
602 OPM_TIMEBLOCK(tracerAssemble);
604 if (tr.numTracer() != 0) {
606 for (
int tIdx = 0; tIdx < tr.numTracer(); ++tIdx) {
607 tr.residual_[tIdx] = 0.0;
621 const auto& wellPtrs =
simulator_.problem().wellModel().localNonshutWells();
626 for (
const auto& wellPtr : wellPtrs) {
628 const auto& eclWell = wellPtr->wellEcl();
632 auto* mswTracerRate = eclWell.isMultiSegment()
649 #pragma omp parallel for
653 const Scalar dt = elemCtx.simulator().timeStepSize();
655 for (
const auto& elem : chunk) {
656 elemCtx.updateStencil(elem);
657 const std::size_t I = elemCtx.globalSpaceIndex( 0, 0);
659 if (elem.partitionType() != Dune::InteriorEntity) {
663 for (
const auto& tr :
tbatch) {
664 if (tr.numTracer() != 0) {
665 (*tr.mat)[I][I][0][0] = 1.;
666 (*tr.mat)[I][I][1][1] = 1.;
671 elemCtx.updateAllIntensiveQuantities();
672 elemCtx.updateAllExtensiveQuantities();
674 const Scalar extrusionFactor =
675 elemCtx.intensiveQuantities( 0, 0).extrusionFactor();
676 Valgrind::CheckDefined(extrusionFactor);
677 assert(isfinite(extrusionFactor));
678 assert(extrusionFactor > 0.0);
679 const Scalar scvVolume =
680 elemCtx.stencil(0).subControlVolume( 0).volume() * extrusionFactor;
681 const std::size_t I1 = elemCtx.globalSpaceIndex( 0, 1);
686 if (tr.numTracer() == 0) {
692 const std::size_t numInteriorFaces = elemCtx.numInteriorFaces(0);
693 for (
unsigned scvfIdx = 0; scvfIdx < numInteriorFaces; scvfIdx++) {
694 const auto& face = elemCtx.stencil(0).interiorFace(scvfIdx);
695 const unsigned j = face.exteriorIndex();
696 const unsigned J = elemCtx.globalSpaceIndex( j, 0);
698 if (tr.numTracer() == 0) {
707 if (tr.numTracer() == 0) {
716 "assembleTracerEquations() failed: ",
721 if (tr.numTracer() == 0) {
726 simulator_.gridView().communicate(handle, Dune::InteriorBorder_All_Interface,
727 Dune::ForwardCommunication);
731 template<TracerTypeIdx Index,
class TrRe>
733 const Scalar scvVolume,
734 const unsigned globalDofIdx)
736 const Scalar vol1 = computeVolume_<Index>(tr.phaseIdx_, globalDofIdx, 0);
737 vol1_[
Index][tr.phaseIdx_][globalDofIdx] = vol1 * scvVolume;
738 dVol_[
Index][tr.phaseIdx_][globalDofIdx] = 0.0;
739 for (
int tIdx = 0; tIdx < tr.numTracer(); ++tIdx) {
740 tr.storageOfTimeIndex1_[tIdx][globalDofIdx][
Index] =
741 vol1 * tr.concentrationInitial_[tIdx][globalDofIdx][
Index];
748 if (tr.numTracer() != 0) {
749 tr.concentrationInitial_ = tr.concentration_;
755 #pragma omp parallel for
760 for (
const auto& elem : chunk) {
761 elemCtx.updatePrimaryStencil(elem);
762 elemCtx.updatePrimaryIntensiveQuantities(0);
763 const Scalar extrusionFactor = elemCtx.intensiveQuantities( 0, 0).extrusionFactor();
764 const Scalar scvVolume = elemCtx.stencil(0).subControlVolume( 0).volume() * extrusionFactor;
765 const unsigned globalDofIdx = elemCtx.globalSpaceIndex(0, 0);
768 if (tr.numTracer() == 0) {
773 updateElem<Free>(tr, scvVolume, globalDofIdx);
774 updateElem<Solution>(tr, scvVolume, globalDofIdx);
780 template<TracerTypeIdx Index,
class TrRe>
782 const std::vector<TracerVector>& dx,
785 const unsigned globalDofIdx,
786 std::vector<TracerVectorSingle>& sc)
788 constexpr Scalar tol_gas_sat = 1e-6;
789 tr.concentration_[tIdx][globalDofIdx][
Index] -= dx[tIdx][globalDofIdx][
Index];
790 if (tr.concentration_[tIdx][globalDofIdx][
Index] < 0.0 || S < tol_gas_sat) {
791 tr.concentration_[tIdx][globalDofIdx][
Index] = 0.0;
793 sc[tr.idx_[tIdx]][globalDofIdx] = tr.concentration_[tIdx][globalDofIdx][
Index];
796 template<TracerTypeIdx Index,
class TrRe>
807 for (
int tIdx = 0; tIdx < tr.numTracer(); ++tIdx) {
809 const Scalar delta = rate * tr.concentration_[tIdx][I][
Index];
810 tracerRate[tr.idx_[tIdx]].rate += delta;
811 splitRate[tr.idx_[tIdx]].rate += delta;
812 if (eclWell.isMultiSegment()) {
813 (*mswTracerRate)[tr.idx_[tIdx]].rate[eclWell.getConnections().get(i).segment()] += delta;
820 const auto& wellPtrs =
simulator_.problem().wellModel().localNonshutWells();
821 for (
const auto& wellPtr : wellPtrs) {
822 const auto& eclWell = wellPtr->wellEcl();
823 const auto well_seq_index = eclWell.seqIndex();
824 const auto inv_well_eff_factor = 1.0 / std::max(Scalar{1.0e-10}, wellPtr->wellEfficiencyFactor());
827 wtr.
rate *= inv_well_eff_factor;
830 wtr.
rate *= inv_well_eff_factor;
833 wtr.
rate *= inv_well_eff_factor;
835 if (eclWell.isMultiSegment()) {
837 std::ranges::for_each(wtr.
rate, [&](
auto& item) {
838 item.second *= inv_well_eff_factor;
849 const auto& aquifer_cfg = this->
eclState_.aquifer();
850 if (!aquifer_cfg.active()) {
854 const auto& specs = aquifer_cfg.aquiferTracers();
859 std::unordered_map<std::string, int> tracer_name_to_idx;
860 for (
int tracerIdx = 0; tracerIdx < this->
numTracers(); ++tracerIdx) {
861 tracer_name_to_idx.emplace(this->
name(tracerIdx), tracerIdx);
865 for (
const auto& spec : specs) {
866 if (!aquifer_cfg.hasAnalyticalAquifer(spec.aquifer_id)) {
870 const auto tracer_pos = tracer_name_to_idx.find(spec.tracer_name);
871 if (tracer_pos == tracer_name_to_idx.end()) {
872 if (
simulator_.vanguard().grid().comm().rank() == 0) {
873 deferredLogger.
warning(fmt::format(
"AQANTRC tracer '{}' is not declared in TRACER",
879 if (!aquifer_cfg.connections().hasAquiferConnections(spec.aquifer_id)) {
883 const int tracerIdx = tracer_pos->second;
886 for (
const auto& conn : aquifer_cfg.connections().getConnections(spec.aquifer_id)) {
887 const int cellIdx = vanguard.compressedIndex(conn.global_index);
905 const auto& aquiferModel =
simulator_.problem().aquiferModel();
911 const Scalar rate = aquiferModel.cachedConnectionInfluxRate(cellIdx);
912 if (rate == Scalar{0}) {
916 const unsigned I = cellIdx;
917 const Scalar rate_f = rate;
919 for (
const auto& spec : specs) {
920 if (spec.phaseIdx != tr.phaseIdx_) {
925 for (
int tIdx = 0; tIdx < tr.numTracer(); ++tIdx) {
926 if (tr.idx_[tIdx] == spec.tracerIdx) {
936 const Scalar delta = rate_f * spec.concentration;
937 tr.residual_[localTIdx][I][
Free] -= delta;
938 dVol_[
Free][tr.phaseIdx_][I] -= rate_f * dt;
940 else if (rate_f < 0) {
941 tr.residual_[localTIdx][I][
Free] -= rate_f * tr.concentration_[localTIdx][I][
Free];
942 dVol_[
Free][tr.phaseIdx_][I] -= rate_f * dt;
943 (*tr.mat)[I][I][
Free][
Free] -= rate_f * variable<TracerEvaluation>(1.0, 0).derivative(0);
954 if (tr.numTracer() == 0) {
960 std::vector<TracerVector> dx(tr.concentration_);
961 for (
int tIdx = 0; tIdx < tr.numTracer(); ++tIdx) {
967 OpmLog::warning(
"### Tracer model: Linear solver did not converge. ###");
970 OPM_TIMEBLOCK(tracerPost);
972 for (
int tIdx = 0; tIdx < tr.numTracer(); ++tIdx) {
973 for (std::size_t globalDofIdx = 0; globalDofIdx < tr.concentration_[tIdx].size(); ++globalDofIdx) {
976 const auto& intQuants =
simulator_.model().intensiveQuantities(globalDofIdx, 0);
977 const auto& fs = intQuants.fluidState();
978 const Scalar Sf = decay<Scalar>(fs.saturation(tr.phaseIdx_));
981 if (tr.phaseIdx_ == FluidSystem::gasPhaseIdx && FluidSystem::enableDissolvedGas()) {
982 Ss = decay<Scalar>(fs.saturation(FluidSystem::oilPhaseIdx));
984 else if (tr.phaseIdx_ == FluidSystem::oilPhaseIdx && FluidSystem::enableVaporizedOil()) {
985 Ss = decay<Scalar>(fs.saturation(FluidSystem::gasPhaseIdx));
994 const auto& wellPtrs =
simulator_.problem().wellModel().localNonshutWells();
995 for (
const auto& wellPtr : wellPtrs) {
996 const auto& eclWell = wellPtr->wellEcl();
999 if (!eclWell.isProducer()) {
1003 Scalar rateWellPos = 0.0;
1004 Scalar rateWellNeg = 0.0;
1005 const std::size_t well_index =
simulator_.problem().wellModel().wellState().index(eclWell.name()).value();
1006 const auto& ws =
simulator_.problem().wellModel().wellState().well(well_index);
1010 auto* mswTracerRate = eclWell.isMultiSegment() ? &this->
mSwTracerRate_[eclWell.seqIndex()] :
nullptr;
1011 const auto well_eff = wellPtr->wellEfficiencyFactor();
1012 for (std::size_t i = 0; i < ws.perf_data.size(); ++i) {
1013 const auto I = ws.perf_data.cell_index[i];
1014 const Scalar rate = wellPtr->volumetricSurfaceRateForConnection(I, tr.phaseIdx_);
1017 if (tr.phaseIdx_ == FluidSystem::oilPhaseIdx && FluidSystem::enableVaporizedOil()) {
1018 rate_s = ws.perf_data.phase_mixing_rates[i][ws.vaporized_oil]*well_eff;
1020 else if (tr.phaseIdx_ == FluidSystem::gasPhaseIdx && FluidSystem::enableDissolvedGas()) {
1021 rate_s = ws.perf_data.phase_mixing_rates[i][ws.dissolved_gas]*well_eff;
1027 const Scalar rate_f = rate - rate_s;
1028 assignRates<Free>(tr, eclWell, i, I, rate_f,
1029 tracerRate, mswTracerRate, freeTracerRate);
1030 assignRates<Solution>(tr, eclWell, i, I, rate_s,
1031 tracerRate, mswTracerRate, solTracerRate);
1034 rateWellNeg += rate;
1037 rateWellPos += rate;
1046 const Scalar official_well_rate_total =
1047 simulator_.problem().wellModel().wellState().well(well_index).surface_rates[tr.phaseIdx_];
1049 const Scalar rateWellTotal = official_well_rate_total;
1051 if (rateWellTotal > rateWellNeg) {
1052 constexpr Scalar bucketPrDay = 10.0 / (1000. * 3600. * 24.);
1053 const Scalar factor = (rateWellTotal < -bucketPrDay) ? rateWellTotal / rateWellNeg : 0.0;
1054 for (
int tIdx = 0; tIdx < tr.numTracer(); ++tIdx) {
1055 tracerRate[tIdx].rate *= factor;
1073 template <
typename TV>
1082 std::unique_ptr<TracerMatrix>
mat;
1093 result.
idx_ = {1,2,3};
1102 template<
class Serializer>
1112 {
return idx_.size(); }
1116 const int numGridDof = concentration.size();
1117 idx_.emplace_back(idx);
1125 std::array<TracerBatch<TracerVector>,numPhases>
tbatch;
1129 std::array<std::array<std::vector<Scalar>,numPhases>,2>
vol1_;
1130 std::array<std::array<std::vector<Scalar>,numPhases>,2>
dVol_;
#define OPM_END_PARALLEL_TRY_CATCH_LOG(obptc_logger, obptc_prefix, obptc_output, comm)
Catch exception, log, and throw in a parallel try-catch clause.
Definition: DeferredLoggingErrorHelpers.hpp:202
#define OPM_BEGIN_PARALLEL_TRY_CATCH()
Macro to setup the try of a parallel try-catch.
Definition: DeferredLoggingErrorHelpers.hpp:158
A datahandle sending data located in multiple vectors.
Definition: DeferredLogger.hpp:57
void warning(const std::string &tag, const std::string &message)
Definition: GenericTracerModel.hpp:56
Opm::GenericTracerModel< GetPropType< TypeTag, Properties::Grid >, GetPropType< TypeTag, Properties::GridView >, GetPropType< TypeTag, Properties::DofMapper >, GetPropType< TypeTag, Properties::Stencil >, GetPropType< TypeTag, Properties::FluidSystem >, GetPropType< TypeTag, Properties::Scalar > >::numTracers int numTracers() const
Return the number of tracers considered by the tracerModel.
Definition: GenericTracerModel_impl.hpp:162
Opm::GenericTracerModel< GetPropType< TypeTag, Properties::Grid >, GetPropType< TypeTag, Properties::GridView >, GetPropType< TypeTag, Properties::DofMapper >, GetPropType< TypeTag, Properties::Stencil >, GetPropType< TypeTag, Properties::FluidSystem >, GetPropType< TypeTag, Properties::Scalar > >::doInit void doInit(bool rst, std::size_t numGridDof, std::size_t gasPhaseIdx, std::size_t oilPhaseIdx, std::size_t waterPhaseIdx)
Initialize all internal data structures needed by the tracer module.
Definition: GenericTracerModel_impl.hpp:227
Opm::GenericTracerModel< GetPropType< TypeTag, Properties::Grid >, GetPropType< TypeTag, Properties::GridView >, GetPropType< TypeTag, Properties::DofMapper >, GetPropType< TypeTag, Properties::Stencil >, GetPropType< TypeTag, Properties::FluidSystem >, GetPropType< TypeTag, Properties::Scalar > >::tracerConcentration_ std::vector< TracerVector > tracerConcentration_
Definition: GenericTracerModel.hpp:158
Opm::GenericTracerModel< GetPropType< TypeTag, Properties::Grid >, GetPropType< TypeTag, Properties::GridView >, GetPropType< TypeTag, Properties::DofMapper >, GetPropType< TypeTag, Properties::Stencil >, GetPropType< TypeTag, Properties::FluidSystem >, GetPropType< TypeTag, Properties::Scalar > >::tracerPhaseIdx_ std::vector< int > tracerPhaseIdx_
Definition: GenericTracerModel.hpp:156
Opm::GenericTracerModel< GetPropType< TypeTag, Properties::Grid >, GetPropType< TypeTag, Properties::GridView >, GetPropType< TypeTag, Properties::DofMapper >, GetPropType< TypeTag, Properties::Stencil >, GetPropType< TypeTag, Properties::FluidSystem >, GetPropType< TypeTag, Properties::Scalar > >::wellFreeTracerRate_ std::unordered_map< int, std::vector< WellTracerRate< GetPropType< TypeTag, Properties::Scalar > > > > wellFreeTracerRate_
Definition: GenericTracerModel.hpp:165
Opm::GenericTracerModel< GetPropType< TypeTag, Properties::Grid >, GetPropType< TypeTag, Properties::GridView >, GetPropType< TypeTag, Properties::DofMapper >, GetPropType< TypeTag, Properties::Stencil >, GetPropType< TypeTag, Properties::FluidSystem >, GetPropType< TypeTag, Properties::Scalar > >::wellTracerRate_ std::unordered_map< int, std::vector< WellTracerRate< GetPropType< TypeTag, Properties::Scalar > > > > wellTracerRate_
Definition: GenericTracerModel.hpp:164
Opm::GenericTracerModel< GetPropType< TypeTag, Properties::Grid >, GetPropType< TypeTag, Properties::GridView >, GetPropType< TypeTag, Properties::DofMapper >, GetPropType< TypeTag, Properties::Stencil >, GetPropType< TypeTag, Properties::FluidSystem >, GetPropType< TypeTag, Properties::Scalar > >::mSwTracerRate_ std::unordered_map< int, std::vector< MSWellTracerRate< GetPropType< TypeTag, Properties::Scalar > > > > mSwTracerRate_
Definition: GenericTracerModel.hpp:168
Opm::GenericTracerModel< GetPropType< TypeTag, Properties::Grid >, GetPropType< TypeTag, Properties::GridView >, GetPropType< TypeTag, Properties::DofMapper >, GetPropType< TypeTag, Properties::Stencil >, GetPropType< TypeTag, Properties::FluidSystem >, GetPropType< TypeTag, Properties::Scalar > >::eclState_ const EclipseState & eclState_
Definition: GenericTracerModel.hpp:152
Opm::GenericTracerModel< GetPropType< TypeTag, Properties::Grid >, GetPropType< TypeTag, Properties::GridView >, GetPropType< TypeTag, Properties::DofMapper >, GetPropType< TypeTag, Properties::Stencil >, GetPropType< TypeTag, Properties::FluidSystem >, GetPropType< TypeTag, Properties::Scalar > >::wellfname std::string wellfname(int tracerIdx) const
Definition: GenericTracerModel_impl.hpp:183
Opm::GenericTracerModel< GetPropType< TypeTag, Properties::Grid >, GetPropType< TypeTag, Properties::GridView >, GetPropType< TypeTag, Properties::DofMapper >, GetPropType< TypeTag, Properties::Stencil >, GetPropType< TypeTag, Properties::FluidSystem >, GetPropType< TypeTag, Properties::Scalar > >::name const std::string & name(int tracerIdx) const
Return the tracer name.
Definition: GenericTracerModel_impl.hpp:220
Opm::GenericTracerModel< GetPropType< TypeTag, Properties::Grid >, GetPropType< TypeTag, Properties::GridView >, GetPropType< TypeTag, Properties::DofMapper >, GetPropType< TypeTag, Properties::Stencil >, GetPropType< TypeTag, Properties::FluidSystem >, GetPropType< TypeTag, Properties::Scalar > >::wellsname std::string wellsname(int tracerIdx) const
Definition: GenericTracerModel_impl.hpp:190
Opm::GenericTracerModel< GetPropType< TypeTag, Properties::Grid >, GetPropType< TypeTag, Properties::GridView >, GetPropType< TypeTag, Properties::DofMapper >, GetPropType< TypeTag, Properties::Stencil >, GetPropType< TypeTag, Properties::FluidSystem >, GetPropType< TypeTag, Properties::Scalar > >::freeTracerConcentration_ std::vector< TracerVectorSingle > freeTracerConcentration_
Definition: GenericTracerModel.hpp:160
Opm::GenericTracerModel< GetPropType< TypeTag, Properties::Grid >, GetPropType< TypeTag, Properties::GridView >, GetPropType< TypeTag, Properties::DofMapper >, GetPropType< TypeTag, Properties::Stencil >, GetPropType< TypeTag, Properties::FluidSystem >, GetPropType< TypeTag, Properties::Scalar > >::TracerVector Dune::BlockVector< Dune::FieldVector< GetPropType< TypeTag, Properties::Scalar >, 2 > > TracerVector
Definition: GenericTracerModel.hpp:60
Opm::GenericTracerModel< GetPropType< TypeTag, Properties::Grid >, GetPropType< TypeTag, Properties::GridView >, GetPropType< TypeTag, Properties::DofMapper >, GetPropType< TypeTag, Properties::Stencil >, GetPropType< TypeTag, Properties::FluidSystem >, GetPropType< TypeTag, Properties::Scalar > >::TracerTypeIdx TracerTypeIdx
Tracer type index.
Definition: GenericTracerModel.hpp:146
Opm::GenericTracerModel< GetPropType< TypeTag, Properties::Grid >, GetPropType< TypeTag, Properties::GridView >, GetPropType< TypeTag, Properties::DofMapper >, GetPropType< TypeTag, Properties::Stencil >, GetPropType< TypeTag, Properties::FluidSystem >, GetPropType< TypeTag, Properties::Scalar > >::Free @ Free
Definition: GenericTracerModel.hpp:147
Opm::GenericTracerModel< GetPropType< TypeTag, Properties::Grid >, GetPropType< TypeTag, Properties::GridView >, GetPropType< TypeTag, Properties::DofMapper >, GetPropType< TypeTag, Properties::Stencil >, GetPropType< TypeTag, Properties::FluidSystem >, GetPropType< TypeTag, Properties::Scalar > >::Solution @ Solution
Definition: GenericTracerModel.hpp:148
Opm::GenericTracerModel< GetPropType< TypeTag, Properties::Grid >, GetPropType< TypeTag, Properties::GridView >, GetPropType< TypeTag, Properties::DofMapper >, GetPropType< TypeTag, Properties::Stencil >, GetPropType< TypeTag, Properties::FluidSystem >, GetPropType< TypeTag, Properties::Scalar > >::linearSolveBatchwise_ bool linearSolveBatchwise_(const TracerMatrix &M, std::vector< TracerVector > &x, std::vector< TracerVector > &b)
Definition: GenericTracerModel_impl.hpp:444
Opm::GenericTracerModel< GetPropType< TypeTag, Properties::Grid >, GetPropType< TypeTag, Properties::GridView >, GetPropType< TypeTag, Properties::DofMapper >, GetPropType< TypeTag, Properties::Stencil >, GetPropType< TypeTag, Properties::FluidSystem >, GetPropType< TypeTag, Properties::Scalar > >::TracerMatrix Dune::BCRSMatrix< Opm::MatrixBlock< GetPropType< TypeTag, Properties::Scalar >, 2, 2 > > TracerMatrix
Definition: GenericTracerModel.hpp:59
Opm::GenericTracerModel< GetPropType< TypeTag, Properties::Grid >, GetPropType< TypeTag, Properties::GridView >, GetPropType< TypeTag, Properties::DofMapper >, GetPropType< TypeTag, Properties::Stencil >, GetPropType< TypeTag, Properties::FluidSystem >, GetPropType< TypeTag, Properties::Scalar > >::solTracerConcentration_ std::vector< TracerVectorSingle > solTracerConcentration_
Definition: GenericTracerModel.hpp:161
Opm::GenericTracerModel< GetPropType< TypeTag, Properties::Grid >, GetPropType< TypeTag, Properties::GridView >, GetPropType< TypeTag, Properties::DofMapper >, GetPropType< TypeTag, Properties::Stencil >, GetPropType< TypeTag, Properties::FluidSystem >, GetPropType< TypeTag, Properties::Scalar > >::currentConcentration_ GetPropType< TypeTag, Properties::Scalar > currentConcentration_(const Well &eclWell, const std::string &trName, const SummaryState &summaryState) const
Definition: GenericTracerModel_impl.hpp:211
Opm::GenericTracerModel< GetPropType< TypeTag, Properties::Grid >, GetPropType< TypeTag, Properties::GridView >, GetPropType< TypeTag, Properties::DofMapper >, GetPropType< TypeTag, Properties::Stencil >, GetPropType< TypeTag, Properties::FluidSystem >, GetPropType< TypeTag, Properties::Scalar > >::TracerVectorSingle Dune::BlockVector< Dune::FieldVector< GetPropType< TypeTag, Properties::Scalar >, 1 > > TracerVectorSingle
Definition: GenericTracerModel.hpp:58
Opm::GenericTracerModel< GetPropType< TypeTag, Properties::Grid >, GetPropType< TypeTag, Properties::GridView >, GetPropType< TypeTag, Properties::DofMapper >, GetPropType< TypeTag, Properties::Stencil >, GetPropType< TypeTag, Properties::FluidSystem >, GetPropType< TypeTag, Properties::Scalar > >::tracerMatrix_ std::unique_ptr< TracerMatrix > tracerMatrix_
Definition: GenericTracerModel.hpp:159
Opm::GenericTracerModel< GetPropType< TypeTag, Properties::Grid >, GetPropType< TypeTag, Properties::GridView >, GetPropType< TypeTag, Properties::DofMapper >, GetPropType< TypeTag, Properties::Stencil >, GetPropType< TypeTag, Properties::FluidSystem >, GetPropType< TypeTag, Properties::Scalar > >::wellSolTracerRate_ std::unordered_map< int, std::vector< WellTracerRate< GetPropType< TypeTag, Properties::Scalar > > > > wellSolTracerRate_
Definition: GenericTracerModel.hpp:166
static unsigned maxThreads()
Return the maximum number of threads of the current process.
Definition: threadmanager.hpp:66
A class which handles tracers as specified in by ECL.
Definition: TracerModel.hpp:81
void updateStorageCache()
Definition: TracerModel.hpp:745
std::array< std::array< std::vector< Scalar >, numPhases >, 2 > vol1_
Definition: TracerModel.hpp:1129
void convertEffectiveRatesToRawRates()
Definition: TracerModel.hpp:819
TracerBatch< TracerVector > & oil_
Definition: TracerModel.hpp:1127
void advanceTracerFields()
Definition: TracerModel.hpp:949
void init(bool rst)
Definition: TracerModel.hpp:144
void assembleTracerEquationSource(TrRe &tr, const Scalar dt, unsigned I)
Definition: TracerModel.hpp:545
TracerModel(Simulator &simulator)
Definition: TracerModel.hpp:111
void assignRates(const TrRe &tr, const Well &eclWell, const std::size_t i, const std::size_t I, const Scalar rate, std::vector< WellTracerRate< Scalar > > &tracerRate, std::vector< MSWellTracerRate< Scalar > > *mswTracerRate, std::vector< WellTracerRate< Scalar > > &splitRate)
Definition: TracerModel.hpp:797
void copyForOutput(TrRe &tr, const std::vector< TracerVector > &dx, const Scalar S, const unsigned tIdx, const unsigned globalDofIdx, std::vector< TracerVectorSingle > &sc)
Definition: TracerModel.hpp:781
void assembleTracerEquationFlux(TrRe &tr, const ElementContext &elemCtx, unsigned scvfIdx, unsigned I, unsigned J, const Scalar dt)
Definition: TracerModel.hpp:410
void assembleTracerEquationWell(TrRe &tr, const Well &well)
Definition: TracerModel.hpp:445
void updateElem(TrRe &tr, const Scalar scvVolume, const unsigned globalDofIdx)
Definition: TracerModel.hpp:732
Scalar computeVolume_(const int tracerPhaseIdx, const unsigned globalDofIdx, const unsigned timeIdx) const
Definition: TracerModel.hpp:268
void assembleTracerEquationAquifer_(TrRe &tr)
Definition: TracerModel.hpp:899
typename BaseType::TracerTypeIdx TracerTypeIdx
Definition: TracerModel.hpp:262
void assembleTracerEquationVolume(TrRe &tr, const ElementContext &elemCtx, const Scalar scvVolume, const Scalar dt, unsigned I, unsigned I1)
Definition: TracerModel.hpp:374
Scalar storage1_(const TrRe &tr, const unsigned tIdx, const unsigned I, const unsigned I1, const bool cache)
Definition: TracerModel.hpp:359
void serialize(Restarter &)
This method writes the complete state of all tracer to the hard disk.
Definition: TracerModel.hpp:241
TracerBatch< TracerVector > & gas_
Definition: TracerModel.hpp:1128
void assembleTracerEquations_()
Definition: TracerModel.hpp:591
std::array< TracerBatch< TracerVector >, numPhases > tbatch
Definition: TracerModel.hpp:1125
void buildAquiferTracerConnections_(DeferredLogger &deferredLogger)
Definition: TracerModel.hpp:845
std::pair< TracerEvaluation, bool > computeFlux_(const int tracerPhaseIdx, const ElementContext &elemCtx, const unsigned scvfIdx, const unsigned timeIdx) const
Definition: TracerModel.hpp:306
void beginTimeStep()
Definition: TracerModel.hpp:213
void serializeOp(Serializer &serializer)
Definition: TracerModel.hpp:255
void prepareTracerBatches()
Definition: TracerModel.hpp:150
std::unordered_map< unsigned, std::vector< AquiferTracerCellSpec > > aquifer_tracer_cells_
Definition: TracerModel.hpp:1139
std::array< std::array< std::vector< Scalar >, numPhases >, 2 > dVol_
Definition: TracerModel.hpp:1130
ElementChunks< GridView, Dune::Partitions::All > element_chunks_
Definition: TracerModel.hpp:1131
TracerBatch< TracerVector > & wat_
Definition: TracerModel.hpp:1126
void endTimeStep()
Informs the tracer model that a time step has just been finished.
Definition: TracerModel.hpp:226
Simulator & simulator_
Definition: TracerModel.hpp:1063
void deserialize(Restarter &)
This method restores the complete state of the tracer from disk.
Definition: TracerModel.hpp:251
A data handle sending multiple data store in vectors attached to cells.
Definition: VectorVectorDataHandle.hpp:50
int Index
The type of an index of a degree of freedom.
Definition: overlaptypes.hh:44
Definition: blackoilmodel.hh:75
Definition: blackoilbioeffectsmodules.hh:45
Opm::DeferredLogger gatherDeferredLogger(const Opm::DeferredLogger &local_deferredlogger, Parallel::Communication communicator)
Create a global log combining local logs.
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: WellTracerRate.hpp:60
std::unordered_map< int, Scalar > rate
Definition: WellTracerRate.hpp:62
Definition: TracerModel.hpp:61
a tag to mark properties as undefined
Definition: propertysystem.hh:38
Definition: TracerModel.hpp:1133
int phaseIdx
Definition: TracerModel.hpp:1135
Scalar concentration
Definition: TracerModel.hpp:1136
int tracerIdx
Definition: TracerModel.hpp:1134
Definition: TracerModel.hpp:1075
const int phaseIdx_
Definition: TracerModel.hpp:1077
void addTracer(const int idx, const TV &concentration)
Definition: TracerModel.hpp:1114
bool operator==(const TracerBatch &rhs) const
Definition: TracerModel.hpp:1084
static TracerBatch serializationTestObject()
Definition: TracerModel.hpp:1090
std::vector< TV > concentrationInitial_
Definition: TracerModel.hpp:1078
void serializeOp(Serializer &serializer)
Definition: TracerModel.hpp:1103
TracerBatch(int phaseIdx=0)
Definition: TracerModel.hpp:1109
int numTracer() const
Definition: TracerModel.hpp:1111
std::vector< int > idx_
Definition: TracerModel.hpp:1076
std::unique_ptr< TracerMatrix > mat
Definition: TracerModel.hpp:1082
std::vector< TV > storageOfTimeIndex1_
Definition: TracerModel.hpp:1080
std::vector< TV > residual_
Definition: TracerModel.hpp:1081
std::vector< TV > concentration_
Definition: TracerModel.hpp:1079
Definition: WellTracerRate.hpp:33
Scalar rate
Definition: WellTracerRate.hpp:35