FlowProblemComp.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 Copyright 2024 SINTEF Digital
5
6 This file is part of the Open Porous Media project (OPM).
7
8 OPM is free software: you can redistribute it and/or modify
9 it under the terms of the GNU General Public License as published by
10 the Free Software Foundation, either version 2 of the License, or
11 (at your option) any later version.
12
13 OPM is distributed in the hope that it will be useful,
14 but WITHOUT ANY WARRANTY; without even the implied warranty of
15 MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
16 GNU General Public License for more details.
17
18 You should have received a copy of the GNU General Public License
19 along with OPM. If not, see <http://www.gnu.org/licenses/>.
20
21 Consult the COPYING file in the top-level source directory of this
22 module for the precise wording of the license and the list of
23 copyright holders.
24*/
30#ifndef OPM_FLOW_PROBLEM_COMP_HPP
31#define OPM_FLOW_PROBLEM_COMP_HPP
32
33
35#include <opm/material/fluidstates/CompositionalFluidState.hpp>
36
37#include <opm/material/thermal/EclThermalLawManager.hpp>
38
39
40#include <algorithm>
41#include <functional>
42#include <set>
43#include <string>
44#include <vector>
45
46namespace Opm {
47
54template <class TypeTag>
55class FlowProblemComp : public FlowProblem<TypeTag>
56{
57 // TODO: the naming of the Types will be adjusted
59
60 using typename FlowProblemType::Scalar;
61 using typename FlowProblemType::Simulator;
62 using typename FlowProblemType::GridView;
63 using typename FlowProblemType::FluidSystem;
64 using typename FlowProblemType::Vanguard;
65
66 // might not be needed
69
72
76
77 using typename FlowProblemType::Indices;
80 using typename FlowProblemType::Evaluation;
81 using typename FlowProblemType::MaterialLaw;
82 using typename FlowProblemType::RateVector;
83
84 using InitialFluidState = CompositionalFluidState<Scalar, FluidSystem>;
85
86public:
89
93 static void registerParameters()
94 {
96 }
97
98
102 explicit FlowProblemComp(Simulator& simulator)
103 : FlowProblemType(simulator)
104 {
105 }
106
111 {
112 // TODO: there should be room to remove duplication for this function,
113 // but there is relatively complicated logic in the function calls in this function
114 // some refactoring is needed for this function
115 FlowProblemType::finishInit();
116
117 auto& simulator = this->simulator();
118
119 auto finishTransmissibilities = [updated = false, this]() mutable {
120 if (updated) {
121 return;
122 }
123 this->transmissibilities_.finishInit(
124 [&vg = this->simulator().vanguard()](const unsigned int it) { return vg.gridIdxToEquilGridIdx(it); });
125 updated = true;
126 };
127
128 finishTransmissibilities();
129
130 const auto& eclState = simulator.vanguard().eclState();
131 const auto& schedule = simulator.vanguard().schedule();
132
133 // Set the start time of the simulation
134 simulator.setStartTime(schedule.getStartTime());
135 simulator.setEndTime(schedule.simTime(schedule.size() - 1));
136
137 // We want the episode index to be the same as the report step index to make
138 // things simpler, so we have to set the episode index to -1 because it is
139 // incremented by endEpisode(). The size of the initial time step and
140 // length of the initial episode is set to zero for the same reason.
141 simulator.setEpisodeIndex(-1);
142 simulator.setEpisodeLength(0.0);
143
144 // the "NOGRAV" keyword from Frontsim or setting the EnableGravity to false
145 // disables gravity, else the standard value of the gravity constant at sea level
146 // on earth is used
147 this->gravity_ = 0.0;
148 if (Parameters::Get<Parameters::EnableGravity>())
149 this->gravity_[dim - 1] = 9.80665;
150 if (!eclState.getInitConfig().hasGravity())
151 this->gravity_[dim - 1] = 0.0;
152
153 if (this->enableTuning_) {
154 // if support for the TUNING keyword is enabled, we get the initial time
155 // steping parameters from it instead of from command line parameters
156 const auto& tuning = schedule[0].tuning();
157 this->initialTimeStepSize_ = tuning.TSINIT.has_value() ? tuning.TSINIT.value() : -1.0;
158 this->maxTimeStepAfterWellEvent_ = tuning.TMAXWC;
159 }
160
161 this->initFluidSystem_();
162
163 if (FluidSystem::phaseIsActive(FluidSystem::oilPhaseIdx)
164 && FluidSystem::phaseIsActive(FluidSystem::gasPhaseIdx)) {
165 this->maxOilSaturation_.resize(this->model().numGridDof(), 0.0);
166 }
167
168 this->readRockParameters_(simulator.vanguard().cellCenterDepths(), [&simulator](const unsigned idx) {
169 std::array<int, dim> coords;
170 simulator.vanguard().cartesianCoordinate(idx, coords);
171 for (auto& c : coords) {
172 ++c;
173 }
174 return coords;
175 });
178
179 const auto& initconfig = eclState.getInitConfig();
180 if (initconfig.restartRequested())
182 else
183 this->readInitialCondition_();
184
186
187 if constexpr (getPropValue<TypeTag, Properties::EnablePolymer>()) {
188 const auto& vanguard = this->simulator().vanguard();
189 const auto& gridView = vanguard.gridView();
190 int numElements = gridView.size(/*codim=*/0);
191 this->polymer_.maxAdsorption.resize(numElements, 0.0);
192 }
193
194 /* readBoundaryConditions_();
195
196 // compute and set eq weights based on initial b values
197 computeAndSetEqWeights_();
198
199 if (enableDriftCompensation_) {
200 drift_.resize(this->model().numGridDof());
201 drift_ = 0.0;
202 } */
203
204 // TODO: check wether the following can work with compostional
205 if (enableVtkOutput_ && eclState.getIOConfig().initOnly()) {
206 simulator.setTimeStepSize(0.0);
208 }
209
210 // after finishing the initialization and writing the initial solution, we move
211 // to the first "real" episode/report step
212 // for restart the episode index and start is already set
213 if (!initconfig.restartRequested()) {
214 simulator.startNextEpisode(schedule.seconds(1));
215 simulator.setEpisodeIndex(0);
216 simulator.setTimeStepIndex(0);
217 }
218 }
219
225 template <class Context>
226 void boundary(BoundaryRateVector& values,
227 const Context& context,
228 unsigned spaceIdx,
229 unsigned /* timeIdx */) const
230 {
231 OPM_TIMEBLOCK_LOCAL(eclProblemBoundary);
232 if (!context.intersection(spaceIdx).boundary())
233 return;
234
235 values.setNoFlow();
236
237 if (this->nonTrivialBoundaryConditions()) {
238 throw std::logic_error("boundary condition is not supported by compostional modeling yet");
239 }
240 }
241
248 template <class Context>
249 void initial(PrimaryVariables& values, const Context& context, unsigned spaceIdx, unsigned timeIdx) const
250 {
251 const unsigned globalDofIdx = context.globalSpaceIndex(spaceIdx, timeIdx);
252 const auto& initial_fs = initialFluidStates_[globalDofIdx];
253 Opm::CompositionalFluidState<Evaluation, FluidSystem> fs;
254 using ComponentVector = Dune::FieldVector<Evaluation, numComponents>;
255 for (unsigned p = 0; p < numPhases; ++p) { // TODO: assuming the phaseidx continuous
256 ComponentVector evals;
257 auto& last_eval = evals[numComponents - 1];
258 last_eval = 1.;
259 for (unsigned c = 0; c < numComponents - 1; ++c) {
260 const auto val = initial_fs.moleFraction(p, c);
261 const Evaluation eval = Evaluation::createVariable(val, c + 1);
262 evals[c] = eval;
263 last_eval -= eval;
264 }
265 for (unsigned c = 0; c < numComponents; ++c) {
266 fs.setMoleFraction(p, c, evals[c]);
267 }
268
269 // pressure
270 const auto p_val = initial_fs.pressure(p);
271 fs.setPressure(p, Evaluation::createVariable(p_val, 0));
272
273 const auto sat_val = initial_fs.saturation(p);
274 fs.setSaturation(p, sat_val);
275
276 const auto temp_val = initial_fs.temperature(p);
277 fs.setTemperature(temp_val);
278 }
279
280 {
281 typename FluidSystem::template ParameterCache<Evaluation> paramCache;
282 paramCache.updatePhase(fs, FluidSystem::oilPhaseIdx);
283 paramCache.updatePhase(fs, FluidSystem::gasPhaseIdx);
284 fs.setDensity(FluidSystem::oilPhaseIdx, FluidSystem::density(fs, paramCache, FluidSystem::oilPhaseIdx));
285 fs.setDensity(FluidSystem::gasPhaseIdx, FluidSystem::density(fs, paramCache, FluidSystem::gasPhaseIdx));
286 fs.setViscosity(FluidSystem::oilPhaseIdx, FluidSystem::viscosity(fs, paramCache, FluidSystem::oilPhaseIdx));
287 fs.setViscosity(FluidSystem::gasPhaseIdx, FluidSystem::viscosity(fs, paramCache, FluidSystem::gasPhaseIdx));
288 }
289
290 // Set initial K and L
291 for (unsigned compIdx = 0; compIdx < numComponents; ++compIdx) {
292 const Evaluation Ktmp = fs.wilsonK_(compIdx);
293 fs.setKvalue(compIdx, Ktmp);
294 }
295
296 const Evaluation& Ltmp = -1.0;
297 fs.setLvalue(Ltmp);
298
299 values.assignNaive(fs);
300 }
301
302 void addToSourceDense(RateVector&, unsigned, unsigned) const override
303 {
304 // we do nothing for now
305 }
306
307 const InitialFluidState& initialFluidState(unsigned globalDofIdx) const
308 { return initialFluidStates_[globalDofIdx]; }
309
310 std::vector<InitialFluidState>& initialFluidStates()
311 { return initialFluidStates_; }
312
313 const std::vector<InitialFluidState>& initialFluidStates() const
314 { return initialFluidStates_; }
315
316 // TODO: do we need this one?
317 template<class Serializer>
318 void serializeOp(Serializer& serializer)
319 {
320 serializer(static_cast<FlowProblemType&>(*this));
321 }
322protected:
323
324 void updateExplicitQuantities_(int /* episodeIdx*/, int /* timeStepSize */, bool /* first_step_after_restart */) override
325 {
326 // we do nothing here for now
327 }
328
330 {
331 throw std::logic_error("Equilibration is not supported by compositional modeling yet");
332 }
333
335 {
336 throw std::logic_error("Restarting is not supported by compositional modeling yet");
337 }
338
340 {
341 readExplicitInitialConditionCompositional_();
342 }
343
345 {
346 const auto& simulator = this->simulator();
347 const auto& vanguard = simulator.vanguard();
348 const auto& eclState = vanguard.eclState();
349 const auto& fp = eclState.fieldProps();
350 // const bool has_xmf = fp.has_double("XMF");
351 assert(fp.has_double("XMF"));
352 // const bool has_ymf = fp.has_double("YMF");
353 assert(fp.has_double("YMF"));
354 const bool has_temp = fp.has_double("TEMPI");
355 const bool has_pressure = fp.has_double("PRESSURE");
356
357 // const bool has_gas = fp.has_double("SGAS");
358 assert(fp.has_double("SGAS"));
359 if (!has_pressure)
360 throw std::runtime_error("The ECL input file requires the presence of the PRESSURE "
361 "keyword if the model is initialized explicitly");
362
363 std::size_t numDof = this->model().numGridDof();
364
365 initialFluidStates_.resize(numDof);
366
367 std::vector<double> xmfData;
368 std::vector<double> ymfData;
369 std::vector<double> waterSaturationData;
370 std::vector<double> gasSaturationData;
371 std::vector<double> soilData;
372 std::vector<double> pressureData;
373 std::vector<double> tempiData;
374
375 if (waterPhaseIdx > 0 && Indices::numPhases > 1)
376 waterSaturationData = fp.get_double("SWAT");
377 else
378 waterSaturationData.resize(numDof);
379
380 pressureData = fp.get_double("PRESSURE");
381
382 assert(waterPhaseIdx < 0);
383
384 xmfData = fp.get_double("XMF");
385 ymfData = fp.get_double("YMF");
386 if (has_temp) {
387 tempiData = fp.get_double("TEMPI");
388 } else {
389 ; // TODO: throw?
390 }
391
392 if (gasPhaseIdx > 0) // && FluidSystem::phaseIsActive(oilPhaseIdx))
393 gasSaturationData = fp.get_double("SGAS");
394 else
395 gasSaturationData.resize(numDof);
396
397 // constexpr std::size_t num_comps = 3;
398
399 for (std::size_t dofIdx = 0; dofIdx < numDof; ++dofIdx) {
400 auto& dofFluidState = initialFluidStates_[dofIdx];
401 // dofFluidState.setPvtRegionIndex(pvtRegionIndex(dofIdx));
402
403 Scalar temperatureLoc = tempiData[dofIdx];
404 assert(std::isfinite(temperatureLoc) && temperatureLoc > 0);
405 dofFluidState.setTemperature(temperatureLoc);
406
407 if (gasPhaseIdx > 0) {
408 dofFluidState.setSaturation(FluidSystem::gasPhaseIdx,
409 gasSaturationData[dofIdx]);
410 }
411 if (oilPhaseIdx > 0) {
412 dofFluidState.setSaturation(FluidSystem::oilPhaseIdx,
413 1.0
414 - waterSaturationData[dofIdx]
415 - gasSaturationData[dofIdx]);
416 }
417
419 // set phase pressures
421 const Scalar pressure = pressureData[dofIdx]; // oil pressure (or gas pressure for water-gas system or water pressure for single phase)
422
423 // TODO: zero capillary pressure for now
424 const std::array<Scalar, numPhases> pc = {0};
425 for (unsigned phaseIdx = 0; phaseIdx < numPhases; ++phaseIdx) {
426 if (!FluidSystem::phaseIsActive(phaseIdx))
427 continue;
428
429 if (Indices::oilEnabled)
430 dofFluidState.setPressure(phaseIdx, pressure + (pc[phaseIdx] - pc[oilPhaseIdx]));
431 else if (Indices::gasEnabled)
432 dofFluidState.setPressure(phaseIdx, pressure + (pc[phaseIdx] - pc[gasPhaseIdx]));
433 else if (Indices::waterEnabled)
434 //single (water) phase
435 dofFluidState.setPressure(phaseIdx, pressure);
436 }
437
438 for (unsigned compIdx = 0; compIdx < numComponents; ++compIdx) {
439 const std::size_t data_idx = compIdx * numDof + dofIdx;
440 const Scalar xmf = xmfData[data_idx];
441 const Scalar ymf = ymfData[data_idx];
442
443 dofFluidState.setMoleFraction(FluidSystem::oilPhaseIdx, compIdx, xmf);
444 dofFluidState.setMoleFraction(FluidSystem::gasPhaseIdx, compIdx, ymf);
445 }
446 }
447 }
448
449private:
450
451 void handleSolventBC(const BCProp::BCFace& /* bc */, RateVector& /* rate */) const override
452 {
453 throw std::logic_error("solvent is disabled for compositional modeling and you're trying to add solvent to BC");
454 }
455
456 void handlePolymerBC(const BCProp::BCFace& /* bc */, RateVector& /* rate */) const override
457 {
458 throw std::logic_error("polymer is disabled for compositional modeling and you're trying to add polymer to BC");
459 }
460
461 std::vector<InitialFluidState> initialFluidStates_;
462
463 bool enableVtkOutput_;
464};
465
466} // namespace Opm
467
468#endif // OPM_FLOW_PROBLEM_COMP_HPP
void readRockParameters_(const std::vector< Scalar > &cellCenterDepths, std::function< std::array< int, 3 >(const unsigned)> ijkIndex)
Definition: FlowGenericProblem_impl.hpp:138
This problem simulates an input file given in the data format used by the commercial ECLiPSE simulato...
Definition: FlowProblemComp.hpp:56
const std::vector< InitialFluidState > & initialFluidStates() const
Definition: FlowProblemComp.hpp:313
void finishInit()
Called by the Opm::Simulator in order to initialize the problem.
Definition: FlowProblemComp.hpp:110
FlowProblemComp(Simulator &simulator)
Definition: FlowProblemComp.hpp:102
void readExplicitInitialCondition_() override
Definition: FlowProblemComp.hpp:339
void readExplicitInitialConditionCompositional_()
Definition: FlowProblemComp.hpp:344
std::vector< InitialFluidState > & initialFluidStates()
Definition: FlowProblemComp.hpp:310
void readEclRestartSolution_()
Definition: FlowProblemComp.hpp:334
const InitialFluidState & initialFluidState(unsigned globalDofIdx) const
Definition: FlowProblemComp.hpp:307
void boundary(BoundaryRateVector &values, const Context &context, unsigned spaceIdx, unsigned) const
Evaluate the boundary conditions for a boundary segment.
Definition: FlowProblemComp.hpp:226
void initial(PrimaryVariables &values, const Context &context, unsigned spaceIdx, unsigned timeIdx) const
Evaluate the initial value for a control volume.
Definition: FlowProblemComp.hpp:249
void readEquilInitialCondition_() override
Definition: FlowProblemComp.hpp:329
void serializeOp(Serializer &serializer)
Definition: FlowProblemComp.hpp:318
void updateExplicitQuantities_(int, int, bool) override
Definition: FlowProblemComp.hpp:324
void addToSourceDense(RateVector &, unsigned, unsigned) const override
Definition: FlowProblemComp.hpp:302
static void registerParameters()
Registers all available parameters for the problem and the model.
Definition: FlowProblemComp.hpp:93
This problem simulates an input file given in the data format used by the commercial ECLiPSE simulato...
Definition: FlowProblem.hpp:91
GetPropType< TypeTag, Properties::Evaluation > Evaluation
Definition: FlowProblem.hpp:153
@ numComponents
Definition: FlowProblem.hpp:113
unsigned pvtRegionIndex(const Context &context, unsigned spaceIdx, unsigned timeIdx) const
Returns the index of the relevant region for thermodynmic properties.
Definition: FlowProblem.hpp:813
Scalar porosity(const Context &context, unsigned spaceIdx, unsigned timeIdx) const
Definition: FlowProblem.hpp:668
GetPropType< TypeTag, Properties::Vanguard > Vanguard
Definition: FlowProblem.hpp:104
GetPropType< TypeTag, Properties::Scalar > Scalar
Definition: FlowProblem.hpp:98
GetPropType< TypeTag, Properties::RateVector > RateVector
Definition: FlowProblem.hpp:142
@ dim
Definition: FlowProblem.hpp:107
GetPropType< TypeTag, Properties::Indices > Indices
Definition: FlowProblem.hpp:154
@ gasPhaseIdx
Definition: FlowProblem.hpp:131
@ dimWorld
Definition: FlowProblem.hpp:108
GetPropType< TypeTag, Properties::Simulator > Simulator
Definition: FlowProblem.hpp:143
@ numPhases
Definition: FlowProblem.hpp:112
void readThermalParameters_()
Definition: FlowProblem.hpp:1349
@ waterPhaseIdx
Definition: FlowProblem.hpp:133
GetPropType< TypeTag, Properties::GridView > GridView
Definition: FlowProblem.hpp:99
static void registerParameters()
Registers all available parameters for the problem and the model.
Definition: FlowProblem.hpp:178
void updatePffDofData_()
Definition: FlowProblem.hpp:1461
GetPropType< TypeTag, Properties::PrimaryVariables > PrimaryVariables
Definition: FlowProblem.hpp:141
Vanguard::TransmissibilityType transmissibilities_
Definition: FlowProblem.hpp:1644
virtual void readInitialCondition_()
Definition: FlowProblem.hpp:1389
void writeOutput(bool verbose=true)
Write the requested quantities of the current solution into the output files.
Definition: FlowProblem.hpp:489
@ oilPhaseIdx
Definition: FlowProblem.hpp:132
GetPropType< TypeTag, Properties::FluidSystem > FluidSystem
Definition: FlowProblem.hpp:101
GetPropType< TypeTag, Properties::MaterialLaw > MaterialLaw
Definition: FlowProblem.hpp:151
void readMaterialParameters_()
Definition: FlowProblem.hpp:1315
Definition: blackoilboundaryratevector.hh:37
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