PyFluidState_impl.hpp
Go to the documentation of this file.
1/*
2 Copyright 2023 Equinor ASA.
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 3 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#include <fmt/format.h>
20
21namespace Opm::Pybind {
22
23template <class TypeTag>
25PyFluidState(Simulator* simulator) : simulator_(simulator)
26{
27
28}
29
30// Public methods alphabetically sorted
31// ------------------------------------
32
33template <class TypeTag>
34std::vector<int>
36getPrimaryVarMeaning(const std::string& variable) const
37{
38 Model& model = this->simulator_->model();
39 auto& sol = model.solution(/*timeIdx*/0);
40 auto size = model.numGridDof();
41 std::vector<int> array(size);
42 for (unsigned dof_idx = 0; dof_idx < size; ++dof_idx) {
43 auto primary_vars = sol[dof_idx];
44 array[dof_idx] = getVariableMeaning_(primary_vars, variable);
45 }
46 return array;
47}
48
49template <class TypeTag>
50std::map<std::string, int>
52getPrimaryVarMeaningMap(const std::string& variable) const
53{
54 if (variable.compare("pressure") == 0) {
55 return {{ "Po", static_cast<int>(PrimaryVariables::PressureMeaning::Po) },
56 { "Pw", static_cast<int>(PrimaryVariables::PressureMeaning::Pw) },
57 { "Pg", static_cast<int>(PrimaryVariables::PressureMeaning::Pg) }};
58 }
59 else if (variable.compare("water") == 0) {
60 return {{ "Sw", static_cast<int>(PrimaryVariables::WaterMeaning::Sw) },
61 { "Rvw", static_cast<int>(PrimaryVariables::WaterMeaning::Rvw) },
62 { "Rsw", static_cast<int>(PrimaryVariables::WaterMeaning::Rsw) },
63 { "Disabled", static_cast<int>(PrimaryVariables::WaterMeaning::Disabled) }};
64 }
65 else if (variable.compare("gas") == 0) {
66 return {{ "Sg", static_cast<int>(PrimaryVariables::GasMeaning::Sg) },
67 { "Rs", static_cast<int>(PrimaryVariables::GasMeaning::Rs) },
68 { "Rv", static_cast<int>(PrimaryVariables::GasMeaning::Rv) },
69 { "Disabled", static_cast<int>(PrimaryVariables::GasMeaning::Disabled) }};
70 }
71 else if (variable.compare("brine") == 0) {
72 return {{ "Cs", static_cast<int>(PrimaryVariables::BrineMeaning::Cs) },
73 { "Sp", static_cast<int>(PrimaryVariables::BrineMeaning::Sp) },
74 { "Disabled", static_cast<int>(PrimaryVariables::BrineMeaning::Disabled) }};
75 }
76 else {
77 const std::string msg = fmt::format(
78 "Unknown variable meaning '{}': Expected pressure, water, gas, or brine", variable);
79 throw std::runtime_error(msg);
80 }
81}
82
83/* Meaning of the primary variables: Sw, Sg, po, pg, Rs, Rv
84 * 1. Sw_po_Sg -> threephase case
85 * 2. Sw_po_Rs -> water + oil case
86 * 3. Sw_pg_Rv -> water + gas case
87 */
88
89/* Variables:
90 Sw = Water saturation,
91 So = Oil saturation,
92 Sg = Gas saturation,
93 pw = Water pressure,
94 po = Oil pressure,
95 pg = Gas pressure,
96 Rs = The solution gas oil ratio: The amount of gas dissolved in the oil
97 Rv = The oil vaporization factor of the gas phase
98 invB = The inverse formation volume factor of a fluid phase
99 rho_w = Water density,
100 rho_o = Oil density,
101 rho_g = Gas density,
102 mu_w = Water viscosity,
103 mu_o = Oil viscosity,
104 mu_g = Gas viscosity,
105 kr_w = Water relperm,
106 kr_o = Oil relperm,
107 kr_g = Gas relperm,
108 */
109template <class TypeTag>
110std::vector<double>
112getFluidStateVariable(const std::string& name) const
113{
114 Model& model = this->simulator_->model();
115 auto size = model.numGridDof();
116 std::vector<double> array(size);
117 const auto& grid_view = this->simulator_->vanguard().gridView();
118 /* NOTE: grid_view.size(0) should give the same value as
119 * model.numGridDof()
120 */
121 ElementContext elem_ctx(*this->simulator_);
122 auto var_type = getVariableType_(name);
123 for (const auto& elem : elements(grid_view, Dune::Partitions::interior)) {
124 elem_ctx.updatePrimaryStencil(elem);
125 elem_ctx.updatePrimaryIntensiveQuantities(/*timeIdx=*/0);
126 for (unsigned dof_idx = 0; dof_idx < elem_ctx.numPrimaryDof(/*timeIdx=*/0); ++dof_idx) {
127 const auto& int_quants = elem_ctx.intensiveQuantities(dof_idx, /*timeIdx=*/0);
128 const auto& fs = int_quants.fluidState();
129 unsigned global_dof_idx = elem_ctx.globalSpaceIndex(dof_idx, /*timeIdx=*/0);
130 array[global_dof_idx] = getVariableValue_(fs, var_type, name);
131 }
132 }
133 return array;
134}
135
136template <class TypeTag>
137std::vector<double>
139getPrimaryVariable(const std::string& idx_name) const
140{
141 std::size_t primary_var_idx = getPrimaryVarIndex_(idx_name);
142 Model& model = this->simulator_->model();
143 auto& sol = model.solution(/*timeIdx*/0);
144 auto size = model.numGridDof();
145 std::vector<double> array(size);
146 for (unsigned dof_idx = 0; dof_idx < size; ++dof_idx) {
147 auto primary_vars = sol[dof_idx];
148 array[dof_idx] = primary_vars[primary_var_idx];
149 }
150 return array;
151}
152
153template <class TypeTag>
154void
156setPrimaryVariable(const std::string& idx_name, const double* data, std::size_t size)
157{
158 std::size_t primary_var_idx = getPrimaryVarIndex_(idx_name);
159 Model& model = this->simulator_->model();
160 auto& sol = model.solution(/*timeIdx*/0);
161 auto model_size = model.numGridDof();
162 if (model_size != size) {
163 const std::string msg = fmt::format(
164 "Cannot set primary variable. Expected array of size {} but got array of size: {}",
165 model_size, size);
166 throw std::runtime_error(msg);
167 }
168 for (unsigned dof_idx = 0; dof_idx < size; ++dof_idx) {
169 auto& primary_vars = sol[dof_idx];
170 primary_vars[primary_var_idx] = data[dof_idx];
171 }
172}
173
174// Private methods alphabetically sorted
175// -------------------------------------
176
177template <class TypeTag>
178std::size_t
180getPrimaryVarIndex_(const std::string &idx_name) const
181{
182 if (idx_name.compare("pressure") == 0) {
183 return Indices::pressureSwitchIdx;
184 }
185 else if (idx_name.compare("water_saturation") == 0) {
186 return Indices::waterSwitchIdx;
187 }
188 else if (idx_name.compare("composition") == 0) {
189 return Indices::compositionSwitchIdx;
190 }
191 else {
192 const std::string msg = fmt::format("Unknown primary variable index name: {}", idx_name);
193 throw std::runtime_error(msg);
194 }
195}
196
197template <class TypeTag>
198int
199PyFluidState<TypeTag>::
200getVariableMeaning_(PrimaryVariables& primary_vars, const std::string& variable) const
201{
202 if (variable.compare("pressure") == 0) {
203 return static_cast<int>(primary_vars.primaryVarsMeaningPressure());
204 }
205 else if(variable.compare("water") == 0) {
206 return static_cast<int>(primary_vars.primaryVarsMeaningWater());
207 }
208 else if (variable.compare("gas") == 0) {
209 return static_cast<int>(primary_vars.primaryVarsMeaningGas());
210 }
211 else if (variable.compare("brine") == 0) {
212 return static_cast<int>(primary_vars.primaryVarsMeaningBrine());
213 }
214 else {
215 const std::string msg = fmt::format(
216 "Unknown variable meaning '{}': Expected pressure, water, gas, or brine", variable);
217 throw std::runtime_error(msg);
218 }
219}
220
221template <class TypeTag>
222typename PyFluidState<TypeTag>::VariableType
223PyFluidState<TypeTag>::
224getVariableType_(const std::string& name) const
225{
226 static std::map<std::string, VariableType> variable_type_map =
227 {
228 {"Sw", VariableType::Sw},
229 {"Sg", VariableType::Sg},
230 {"So", VariableType::So},
231 {"pw", VariableType::pw},
232 {"pg", VariableType::pg},
233 {"po", VariableType::po},
234 {"Rs", VariableType::Rs},
235 {"Rv", VariableType::Rv},
236 {"rho_w", VariableType::rho_w},
237 {"rho_g", VariableType::rho_g},
238 {"rho_o", VariableType::rho_o},
239 {"T", VariableType::T}
240 };
241
242 if (variable_type_map.count(name) == 0) {
243 variableNotFoundError_(name);
244 }
245 return variable_type_map.at(name);
246}
247
248template <class TypeTag>
249template <class FluidState>
250double
251PyFluidState<TypeTag>::
252getVariableValue_(FluidState& fs, VariableType var_type, const std::string& name) const
253{
254 double value;
255 switch(var_type) {
256 case VariableType::pw :
257 value = Opm::getValue(
258 fs.pressure(FluidSystem::waterPhaseIdx));
259 break;
260 case VariableType::pg :
261 value = Opm::getValue(
262 fs.pressure(FluidSystem::gasPhaseIdx));
263 break;
264 case VariableType::po :
265 value = Opm::getValue(
266 fs.pressure(FluidSystem::oilPhaseIdx));
267 break;
268 case VariableType::rho_w :
269 value = Opm::getValue(
270 fs.density(FluidSystem::waterPhaseIdx));
271 break;
272 case VariableType::rho_g :
273 value = Opm::getValue(
274 fs.density(FluidSystem::gasPhaseIdx));
275 break;
276 case VariableType::rho_o :
277 value = Opm::getValue(
278 fs.density(FluidSystem::oilPhaseIdx));
279 break;
280 case VariableType::Rs :
281 value = Opm::getValue(fs.Rs());
282 break;
283 case VariableType::Rv :
284 value = Opm::getValue(fs.Rv());
285 break;
286 case VariableType::Sw :
287 value = Opm::getValue(
288 fs.saturation(FluidSystem::waterPhaseIdx));
289 break;
290 case VariableType::Sg :
291 value = Opm::getValue(
292 fs.saturation(FluidSystem::gasPhaseIdx));
293 break;
294 case VariableType::So :
295 value = Opm::getValue(
296 fs.saturation(FluidSystem::oilPhaseIdx));
297 break;
298 case VariableType::T :
299 value = Opm::getValue(
300 fs.temperature(FluidSystem::waterPhaseIdx));
301 break;
302 default:
303 variableNotFoundError_(name);
304 }
305 return value;
306}
307
308template <class TypeTag>
309void
310PyFluidState<TypeTag>::
311variableNotFoundError_(const std::string& name) const
312{
313 const std::string msg = fmt::format("Access to variable '{}' is not implemented yet!", name);
314 throw std::runtime_error(msg);
315}
316
317} // namespace Opm::Pybind
Definition: PyFluidState.hpp:35
std::map< std::string, int > getPrimaryVarMeaningMap(const std::string &variable) const
Definition: PyFluidState_impl.hpp:52
PyFluidState(Simulator *simulator)
Definition: PyFluidState_impl.hpp:25
std::vector< double > getFluidStateVariable(const std::string &name) const
Definition: PyFluidState_impl.hpp:112
std::vector< int > getPrimaryVarMeaning(const std::string &variable) const
Definition: PyFluidState_impl.hpp:36
void setPrimaryVariable(const std::string &idx_name, const double *data, std::size_t size)
Definition: PyFluidState_impl.hpp:156
std::vector< double > getPrimaryVariable(const std::string &idx_name) const
Definition: PyFluidState_impl.hpp:139
Definition: Pybind11Exporter.hpp:11