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