opm-common
Loading...
Searching...
No Matches
checkFluidSystem.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_CHECK_FLUIDSYSTEM_HPP
28#define OPM_CHECK_FLUIDSYSTEM_HPP
29
30#include <opm/common/utility/DemangledType.hpp>
31
32// include all fluid systems in opm-material
42#include <opm/input/eclipse/EclipseState/Compositional/CompositionalConfig.hpp>
43
44// include all fluid states
51
52#include <iostream>
53#include <string>
54#include <tuple>
55
60template <class ValueT,
61 class FluidSystem,
63class HairSplittingFluidState
64 : protected BaseFluidState
65{
66public:
67 static constexpr int numPhases = FluidSystem::numPhases;
68 static constexpr int numComponents = FluidSystem::numComponents;
69
70 using ValueType = ValueT;
71
72 HairSplittingFluidState()
73 {
74 // initially, do not allow anything
75 allowTemperature(false);
76 allowPressure(false);
77 allowComposition(false);
78 allowDensity(false);
79
80 // do not allow accessing any phase
81 restrictToPhase(1000);
82 }
83
84 void allowTemperature(bool yesno)
85 { allowTemperature_ = yesno; }
86
87 void allowPressure(bool yesno)
88 { allowPressure_ = yesno; }
89
90 void allowComposition(bool yesno)
91 { allowComposition_ = yesno; }
92
93 void allowDensity(bool yesno)
94 { allowDensity_ = yesno; }
95
96 void restrictToPhase(int phaseIdx)
97 { restrictPhaseIdx_ = phaseIdx; }
98
99 BaseFluidState& base()
100 { return *static_cast<BaseFluidState*>(this); }
101
102 const BaseFluidState& base() const
103 { return *static_cast<const BaseFluidState*>(this); }
104
105 auto temperature(unsigned phaseIdx) const
106 -> decltype(this->base().temperature(phaseIdx))
107 {
108 assert(allowTemperature_);
109 assert(restrictPhaseIdx_ < 0 || restrictPhaseIdx_ == static_cast<int>(phaseIdx));
110 return this->base().temperature(phaseIdx);
111 }
112
113 auto pressure(unsigned phaseIdx) const
114 -> decltype(this->base().pressure(phaseIdx))
115 {
116 assert(allowPressure_);
117 assert(restrictPhaseIdx_ < 0 || restrictPhaseIdx_ == static_cast<int>(phaseIdx));
118 return this->base().pressure(phaseIdx);
119 }
120
121 auto moleFraction(unsigned phaseIdx, unsigned compIdx) const
122 -> decltype(this->base().moleFraction(phaseIdx, compIdx))
123 {
124 assert(allowComposition_);
125 assert(restrictPhaseIdx_ < 0 || restrictPhaseIdx_ == static_cast<int>(phaseIdx));
126 return this->base().moleFraction(phaseIdx, compIdx);
127 }
128
129 auto massFraction(unsigned phaseIdx, unsigned compIdx) const
130 -> decltype(this->base().massFraction(phaseIdx, compIdx))
131 {
132 assert(allowComposition_);
133 assert(restrictPhaseIdx_ < 0 || restrictPhaseIdx_ == static_cast<int>(phaseIdx));
134 return this->base().massFraction(phaseIdx, compIdx);
135 }
136
137 auto averageMolarMass(unsigned phaseIdx) const
138 -> decltype(this->base().averageMolarMass(phaseIdx))
139 {
140 assert(allowComposition_);
141 assert(restrictPhaseIdx_ < 0 || restrictPhaseIdx_ == static_cast<int>(phaseIdx));
142 return this->base().averageMolarMass(phaseIdx);
143 }
144
145 auto molarity(unsigned phaseIdx, unsigned compIdx) const
146 -> decltype(this->base().molarity(phaseIdx, compIdx))
147 {
148 assert(allowDensity_ && allowComposition_);
149 assert(restrictPhaseIdx_ < 0 || restrictPhaseIdx_ == static_cast<int>(phaseIdx));
150 return this->base().molarity(phaseIdx, compIdx);
151 }
152
153 auto molarDensity(unsigned phaseIdx) const
154 -> decltype(this->base().molarDensity(phaseIdx))
155 {
156 assert(allowDensity_);
157 assert(restrictPhaseIdx_ < 0 || restrictPhaseIdx_ == static_cast<int>(phaseIdx));
158 return this->base().molarDensity(phaseIdx);
159 }
160
161 auto molarVolume(unsigned phaseIdx) const
162 -> decltype(this->base().molarVolume(phaseIdx))
163 {
164 assert(allowDensity_);
165 assert(restrictPhaseIdx_ < 0 || restrictPhaseIdx_ == static_cast<int>(phaseIdx));
166 return this->base().molarVolume(phaseIdx);
167 }
168
169 auto density(unsigned phaseIdx) const
170 -> decltype(this->base().density(phaseIdx))
171 {
172 assert(allowDensity_);
173 assert(restrictPhaseIdx_ < 0 || restrictPhaseIdx_ == static_cast<int>(phaseIdx));
174 return this->base().density(phaseIdx);
175 }
176
177 auto saturation(unsigned phaseIdx) const
178 -> decltype(this->base().saturation(phaseIdx))
179 {
180 assert(false);
181 return this->base().saturation(phaseIdx);
182 }
183
184 auto fugacity(unsigned phaseIdx, unsigned compIdx) const
185 -> decltype(this->base().fugacity(phaseIdx, compIdx))
186 {
187 assert(false);
188 return this->base().fugacity(phaseIdx, compIdx);
189 }
190
191 auto fugacityCoefficient(unsigned phaseIdx, unsigned compIdx) const
192 -> decltype(this->base().fugacityCoefficient(phaseIdx, compIdx))
193 {
194 assert(false);
195 return this->base().fugacityCoefficient(phaseIdx, compIdx);
196 }
197
198 auto enthalpy(unsigned phaseIdx) const
199 -> decltype(this->base().enthalpy(phaseIdx))
200 {
201 assert(false);
202 return this->base().enthalpy(phaseIdx);
203 }
204
205 auto internalEnergy(unsigned phaseIdx) const
206 -> decltype(this->base().internalEnergy(phaseIdx))
207 {
208 assert(false);
209 return this->base().internalEnergy(phaseIdx);
210 }
211
212 auto viscosity(unsigned phaseIdx) const
213 -> decltype(this->base().viscosity(phaseIdx))
214 {
215 assert(false);
216 return this->base().viscosity(phaseIdx);
217 }
218
219 auto compressFactor(unsigned phaseIdx) const
220 -> decltype(this->base().compressFactor(phaseIdx))
221 {
222 return this->base().compressFactor(phaseIdx);
223 }
224
225private:
226 bool allowSaturation_{false};
227 bool allowTemperature_{false};
228 bool allowPressure_{false};
229 bool allowComposition_{false};
230 bool allowDensity_{false};
231 int restrictPhaseIdx_{};
232};
233
234template <class ValueType, class BaseFluidState>
235void checkFluidState(const BaseFluidState& fs)
236{
237 // fluid states must be copy-able
238 [[maybe_unused]] BaseFluidState tmpFs(fs);
239 tmpFs = fs;
240
241 // a fluid state must provide a checkDefined() method
242 fs.checkDefined();
243
244 // fluid states must export the types which they use as value types
245 using FsValueType = typename BaseFluidState::ValueType;
246 static_assert(std::is_same<FsValueType, ValueType>::value,
247 "Fluid states must export the type they are given as value type in an unmodified way");
248
249 // make sure the fluid state provides all mandatory methods
250 while (false) {
251 std::ignore = fs.temperature(/*phaseIdx=*/0);
252 std::ignore = fs.pressure(/*phaseIdx=*/0);
253 std::ignore = fs.moleFraction(/*phaseIdx=*/0, /*compIdx=*/0);
254 std::ignore = fs.massFraction(/*phaseIdx=*/0, /*compIdx=*/0);
255 std::ignore = fs.averageMolarMass(/*phaseIdx=*/0);
256 std::ignore = fs.molarity(/*phaseIdx=*/0, /*compIdx=*/0);
257 std::ignore = fs.molarDensity(/*phaseIdx=*/0);
258 std::ignore = fs.molarVolume(/*phaseIdx=*/0);
259 std::ignore = fs.density(/*phaseIdx=*/0);
260 std::ignore = fs.saturation(/*phaseIdx=*/0);
261 std::ignore = fs.fugacity(/*phaseIdx=*/0, /*compIdx=*/0);
262 std::ignore = fs.fugacityCoefficient(/*phaseIdx=*/0, /*compIdx=*/0);
263 // Note that we will no longer require that a fluid system
264 // supports enthalpy and internalEnergy compile time.
265 // The commented-out checks below only confirmed that there
266 // was a function that could be compiled, not that it actually
267 // made sense (usually empty but throwing functions).
268 // It is better to make such things compile errors rather than
269 // runtime errors.
270 // std::ignore = fs.enthalpy(/*phaseIdx=*/0);
271 // std::ignore = fs.internalEnergy(/*phaseIdx=*/0);
272 std::ignore = fs.viscosity(/*phaseIdx=*/0);
273 };
274}
275
276template<typename ParameterCache, class Scalar, class FluidSystem>
277ParameterCache initParamCache()
278{
279 constexpr bool is_same = std::is_same<ParameterCache, Opm::PTFlashParameterCache<Scalar, FluidSystem>>::value;
280 if constexpr (is_same) {
281 using EOSType = Opm::CompositionalConfig::EOSType;
282 ParameterCache paramCache(EOSType::PR);
283 return paramCache;
284 }
285 else {
286 ParameterCache paramCache;
287 return paramCache;
288 }
289}
290
294template <class Scalar, class FluidSystem, class RhsEval, class LhsEval>
296{
297 std::cout << "Testing fluid system '"
299 << ", RhsEval = " << Opm::getDemangledType<RhsEval>()
300 << ", LhsEval = " << Opm::getDemangledType<LhsEval>() << "'\n";
301
302 // make sure the fluid system provides the number of phases and
303 // the number of components
304 static constexpr int numPhases = FluidSystem::numPhases;
305 static constexpr int numComponents = FluidSystem::numComponents;
306
308 FluidState fs;
309 fs.allowTemperature(true);
310 fs.allowPressure(true);
311 fs.allowComposition(true);
312 fs.restrictToPhase(-1);
313
314 // initialize memory the fluid state
315 fs.base().setTemperature(273.15 + 20.0);
316 for (int phaseIdx = 0; phaseIdx < numPhases; ++ phaseIdx) {
317 fs.base().setPressure(phaseIdx, 1e5);
318 fs.base().setSaturation(phaseIdx, 1.0/numPhases);
319 for (int compIdx = 0; compIdx < numComponents; ++ compIdx) {
320 fs.base().setMoleFraction(phaseIdx, compIdx, 1.0/numComponents);
321 }
322 }
323
324 static_assert(std::is_same<typename FluidSystem::Scalar, Scalar>::value,
325 "The type used for floating point used by the fluid system must be the same"
326 " as the one passed to the checkFluidSystem() function");
327
328 // check whether the parameter cache adheres to the API
329 typedef typename FluidSystem::template ParameterCache<LhsEval> ParameterCache;
330
331 ParameterCache paramCache = initParamCache<ParameterCache, LhsEval, FluidSystem>();
332 try { paramCache.updateAll(fs); } catch (...) {};
333 try { paramCache.updateAll(fs, /*except=*/ParameterCache::None); } catch (...) {};
334 try { paramCache.updateAll(fs, /*except=*/ParameterCache::Temperature | ParameterCache::Pressure | ParameterCache::Composition); } catch (...) {};
335 try { paramCache.updateAllPressures(fs); } catch (...) {};
336
337 for (unsigned phaseIdx = 0; phaseIdx < numPhases; ++phaseIdx) {
338 fs.restrictToPhase(static_cast<int>(phaseIdx));
339 try { paramCache.updatePhase(fs, phaseIdx); } catch (...) {};
340 try { paramCache.updatePhase(fs, phaseIdx, /*except=*/ParameterCache::None); } catch (...) {};
341 try { paramCache.updatePhase(fs, phaseIdx, /*except=*/ParameterCache::Temperature | ParameterCache::Pressure | ParameterCache::Composition); } catch (...) {};
342 try { paramCache.updateTemperature(fs, phaseIdx); } catch (...) {};
343 try { paramCache.updatePressure(fs, phaseIdx); } catch (...) {};
344 try { paramCache.updateComposition(fs, phaseIdx); } catch (...) {};
345 try { paramCache.updateSingleMoleFraction(fs, phaseIdx, /*compIdx=*/0); } catch (...) {};
346 }
347
348 // some value to make sure the return values of the fluid system
349 // are convertible to scalars
350 LhsEval val = 0.0;
351 Scalar scalarVal = 0.0;
352
353 scalarVal = 2*scalarVal; // get rid of GCC warning (only occurs with paranoid warning flags)
354 val = 2*val; // get rid of GCC warning (only occurs with paranoid warning flags)
355
356 // actually check the fluid system API
357 try { FluidSystem::init(); } catch (...) {};
358 for (unsigned phaseIdx = 0; phaseIdx < numPhases; ++ phaseIdx) {
359 fs.restrictToPhase(static_cast<int>(phaseIdx));
360 fs.allowPressure(FluidSystem::isCompressible(phaseIdx));
361 fs.allowComposition(true);
362 fs.allowDensity(false);
363 try { [[maybe_unused]] auto tmpVal = FluidSystem::density(fs, paramCache, phaseIdx); static_assert(std::is_same<decltype(tmpVal), RhsEval>::value, "The default return value must be the value type used by the fluid state!"); } catch (...) {};
364 try { val = FluidSystem::template density<FluidState, LhsEval>(fs, paramCache, phaseIdx); } catch (...) {};
365 try { scalarVal = FluidSystem::template density<FluidState, Scalar>(fs, paramCache, phaseIdx); } catch (...) {};
366
367 fs.allowPressure(true);
368 fs.allowDensity(true);
369 try { [[maybe_unused]] auto tmpVal = FluidSystem::viscosity(fs, paramCache, phaseIdx); static_assert(std::is_same<decltype(tmpVal), RhsEval>::value, "The default return value must be the value type used by the fluid state!"); } catch (...) {};
370 try { [[maybe_unused]] auto tmpVal = FluidSystem::enthalpy(fs, paramCache, phaseIdx); static_assert(std::is_same<decltype(tmpVal), RhsEval>::value, "The default return value must be the value type used by the fluid state!"); } catch (...) {};
371 try { [[maybe_unused]] auto tmpVal = FluidSystem::heatCapacity(fs, paramCache, phaseIdx); static_assert(std::is_same<decltype(tmpVal), RhsEval>::value, "The default return value must be the value type used by the fluid state!"); } catch (...) {};
372 try { [[maybe_unused]] auto tmpVal = FluidSystem::thermalConductivity(fs, paramCache, phaseIdx); static_assert(std::is_same<decltype(tmpVal), RhsEval>::value, "The default return value must be the value type used by the fluid state!"); } catch (...) {};
373 try { val = FluidSystem::template viscosity<FluidState, LhsEval>(fs, paramCache, phaseIdx); } catch (...) {};
374 try { val = FluidSystem::template enthalpy<FluidState, LhsEval>(fs, paramCache, phaseIdx); } catch (...) {};
375 try { val = FluidSystem::template heatCapacity<FluidState, LhsEval>(fs, paramCache, phaseIdx); } catch (...) {};
376 try { val = FluidSystem::template thermalConductivity<FluidState, LhsEval>(fs, paramCache, phaseIdx); } catch (...) {};
377 try { scalarVal = FluidSystem::template viscosity<FluidState, Scalar>(fs, paramCache, phaseIdx); } catch (...) {};
378 try { scalarVal = FluidSystem::template enthalpy<FluidState, Scalar>(fs, paramCache, phaseIdx); } catch (...) {};
379 try { scalarVal = FluidSystem::template heatCapacity<FluidState, Scalar>(fs, paramCache, phaseIdx); } catch (...) {};
380 try { scalarVal = FluidSystem::template thermalConductivity<FluidState, Scalar>(fs, paramCache, phaseIdx); } catch (...) {};
381
382 for (unsigned compIdx = 0; compIdx < numComponents; ++ compIdx) {
383 fs.allowComposition(!FluidSystem::isIdealMixture(phaseIdx));
384 try { [[maybe_unused]] auto tmpVal = FluidSystem::fugacityCoefficient(fs, paramCache, phaseIdx, compIdx); static_assert(std::is_same<decltype(tmpVal), RhsEval>::value, "The default return value must be the value type used by the fluid state!"); } catch (...) {};
385 try { val = FluidSystem::template fugacityCoefficient<FluidState, LhsEval>(fs, paramCache, phaseIdx, compIdx); } catch (...) {};
386 try { scalarVal = FluidSystem::template fugacityCoefficient<FluidState, Scalar>(fs, paramCache, phaseIdx, compIdx); } catch (...) {};
387 fs.allowComposition(true);
388 try { [[maybe_unused]] auto tmpVal = FluidSystem::diffusionCoefficient(fs, paramCache, phaseIdx, compIdx); static_assert(std::is_same<decltype(tmpVal), RhsEval>::value, "The default return value must be the value type used by the fluid state!"); } catch (...) {};
389 try { val = FluidSystem::template diffusionCoefficient<FluidState, LhsEval>(fs, paramCache, phaseIdx, compIdx); } catch (...) {};
390 try { scalarVal = FluidSystem::template fugacityCoefficient<FluidState, Scalar>(fs, paramCache, phaseIdx, compIdx); } catch (...) {};
391 }
392 }
393
394 // test for phaseName(), isLiquid() and isIdealGas()
395 for (unsigned phaseIdx = 0; phaseIdx < numPhases; ++ phaseIdx) {
396 [[maybe_unused]] std::string name{FluidSystem::phaseName(phaseIdx)};
397 std::ignore = FluidSystem::isLiquid(phaseIdx);
398 std::ignore = FluidSystem::isIdealGas(phaseIdx);
399 }
400
401 // test for molarMass() and componentName()
402 for (unsigned compIdx = 0; compIdx < numComponents; ++ compIdx) {
403 std::ignore = FluidSystem::molarMass(compIdx);
404 std::string{FluidSystem::componentName(compIdx)};
405 }
406}
407
408#endif
Represents all relevant thermodynamic quantities of a multi-phase, multi-component fluid system assum...
A fluid system with a liquid and a gaseous phase and water and air as components.
A fluid system with water, gas and NAPL as phases and water, air and mesitylene (DNAPL) as components...
A fluid system with water, gas and NAPL as phases and water, air and NAPL (contaminant) as components...
A two-phase fluid system with water and nitrogen as components.
A liquid-phase-only fluid system with water and nitrogen as components.
Represents all relevant thermodynamic quantities of a multi-phase, multi-component fluid system assum...
Represents all relevant thermodynamic quantities of a multi-phase, multi-component fluid system not a...
Specifies the parameter cache used by the SPE-5 fluid system.
This is a fluid state which allows to set the fluid pressures and takes all other quantities from an ...
This is a fluid state which allows to set the fluid saturations and takes all other quantities from a...
A fluid system for single phase models.
The fluid system for the oil, gas and water phases of the SPE5 problem.
This is a fluid state which allows to set the fluid temperatures and takes all other quantities from ...
A fluid system for two-phase models assuming immiscibility and thermodynamic equilibrium.
void checkFluidSystem()
Checks whether a fluid system adheres to the specification.
Definition checkFluidSystem.hpp:295
This is a fluid state which makes sure that only the quantities allowed are accessed.
Definition checkFluidSystem.hpp:65
Represents all relevant thermodynamic quantities of a multi-phase, multi-component fluid system assum...
Definition CompositionalFluidState.hpp:53
std::string getDemangledType()
Returns demangled information of a type.
Definition DemangledType.hpp:35