diff --git a/CHANGELOG.md b/CHANGELOG.md
index 2499c7d10a66f10ff0368123b0eacfd60cef5407..b63ae12313d943975a1cd895e5f5e27f5db54f2c 100644
--- a/CHANGELOG.md
+++ b/CHANGELOG.md
@@ -9,6 +9,8 @@ Differences Between DuMux 3.6 and DuMux 3.5
### Improvements and Enhancements
+- __Components__: Fixed a bug in `TabularizedComponent` that caused data races in multithreaded applications
+
- __Discretization__: There is now defaults for `FluxVariablesCache` and `FluxVariablesCacheFiller` for box/cctpfa/ccmpfa/staggered
that implement an empty cache (i.e. nothing is cached for the flux variables).
diff --git a/dumux/material/components/benzene.hh b/dumux/material/components/benzene.hh
index 01e2728bb74a2dd254ad6dbb21629f5288052411..4139d3c2acadadbac9742cd6bee21037c14f1127 100644
--- a/dumux/material/components/benzene.hh
+++ b/dumux/material/components/benzene.hh
@@ -59,6 +59,30 @@ public:
static constexpr Scalar molarMass()
{ return 0.07811; }
+ /*!
+ * \brief Returns true if the gas phase is assumed to be compressible
+ */
+ static constexpr bool gasIsCompressible()
+ { return true; }
+
+ /*!
+ * \brief Returns true if the liquid phase is assumed to be compressible
+ */
+ static constexpr bool liquidIsCompressible()
+ { return false; }
+
+ /*!
+ * \brief Returns true if the gas phase viscosity is constant
+ */
+ static constexpr bool gasViscosityIsConstant()
+ { return true; }
+
+ /*!
+ * \brief Returns true if the liquid phase viscosity is constant
+ */
+ static constexpr bool liquidViscosityIsConstant()
+ { return true; }
+
/*!
* \brief The density of benzene steam at a given pressure and temperature \f$\mathrm{[kg/m^3]}\f$.
*
diff --git a/dumux/material/components/simpleh2o.hh b/dumux/material/components/simpleh2o.hh
index 418a340970102bb677a48f53d50db7c162decf33..fe1bb60ba78d8cfa467d1accfeb0e060f8e24d60 100644
--- a/dumux/material/components/simpleh2o.hh
+++ b/dumux/material/components/simpleh2o.hh
@@ -217,13 +217,13 @@ public:
{ return false; }
/*!
- * \brief Returns true if the gas phase viscostiy is constant
+ * \brief Returns true if the gas phase viscosity is constant
*/
static constexpr bool gasViscosityIsConstant()
{ return true; }
/*!
- * \brief Returns true if the liquid phase viscostiy is constant
+ * \brief Returns true if the liquid phase viscosity is constant
*/
static constexpr bool liquidViscosityIsConstant()
{ return true; }
diff --git a/dumux/material/components/tabulatedcomponent.hh b/dumux/material/components/tabulatedcomponent.hh
index ce347e84643e589bd49adab14a11ccb05f0f8ab8..742ef7a6696fa2862189a0662c5fc1626ed8ea18 100644
--- a/dumux/material/components/tabulatedcomponent.hh
+++ b/dumux/material/components/tabulatedcomponent.hh
@@ -34,16 +34,23 @@
#include
#include
#include
+#include
+#include
+
+#include
#include
+#include
+#include
#include
-namespace Dumux {
-namespace Components {
+namespace Dumux::Components {
// forward declaration
template
class TabulatedComponent;
-} // end namespace Components
+} // end namespace Dumux::Components
+
+namespace Dumux {
//! component traits for tabulated component
template
@@ -60,13 +67,65 @@ struct ComponentTraits, RawComponent>::value;
};
+} // end namespace Dumux
-namespace Components {
+namespace Dumux::Components::Detail {
+struct DisableStaticAssert {};
+} // end namespace Dumux::Components::Detail
+
+namespace Dumux {
+template<> struct AlwaysFalse : public std::true_type {};
+}// end namespace Dumux
+
+namespace Dumux::Components::Detail {
+
+template using CompHasNoLiquidEnthalpy = decltype(C::template liquidEnthalpy(0.0, 0.0));
+template using CompHasNoLiquidDensity = decltype(C::template liquidDensity(0.0, 0.0));
+template using CompHasNoLiquidThermalCond = decltype(C::template liquidThermalConductivity(0.0, 0.0));
+template using CompHasNoLiquidHeatCapacity = decltype(C::template liquidHeatCapacity(0.0, 0.0));
+template using CompHasNoLiquidViscosity = decltype(C::template liquidViscosity(0.0, 0.0));
+template using CompHasLiquidPressure = decltype(C::liquidPressure(0.0, 0.0));
+
+template using CompHasNoGasEnthalpy = decltype(C::template gasEnthalpy(0.0, 0.0));
+template using CompHasNoGasDensity = decltype(C::template gasDensity(0.0, 0.0));
+template using CompHasNoGasThermalCond = decltype(C::template gasThermalConductivity(0.0, 0.0));
+template using CompHasNoGasHeatCapacity = decltype(C::template gasHeatCapacity(0.0, 0.0));
+template using CompHasNoGasViscosity = decltype(C::template gasViscosity(0.0, 0.0));
+template using CompHasGasPressure = decltype(C::gasPressure(0.0, 0.0));
+
+template constexpr inline bool hasLiquidEnthalpy()
+{ return !Dune::Std::is_detected::value && ComponentTraits::hasLiquidState; }
+template constexpr inline bool hasLiquidDensity()
+{ return !Dune::Std::is_detected::value && ComponentTraits::hasLiquidState; }
+template constexpr inline bool hasLiquidThermalConductivity()
+{ return !Dune::Std::is_detected::value && ComponentTraits::hasLiquidState; }
+template constexpr inline bool hasLiquidHeatCapacity()
+{ return !Dune::Std::is_detected::value && ComponentTraits::hasLiquidState; }
+template constexpr inline bool hasLiquidViscosity()
+{ return !Dune::Std::is_detected::value && ComponentTraits::hasLiquidState; }
+template constexpr inline bool hasLiquidPressure()
+{ return Dune::Std::is_detected::value && ComponentTraits::hasLiquidState; }
+
+template constexpr inline bool hasGasEnthalpy()
+{ return !Dune::Std::is_detected::value && ComponentTraits::hasGasState; }
+template constexpr inline bool hasGasDensity()
+{ return !Dune::Std::is_detected::value && ComponentTraits::hasGasState; }
+template constexpr inline bool hasGasThermalConductivity()
+{ return !Dune::Std::is_detected::value && ComponentTraits::hasGasState; }
+template constexpr inline bool hasGasHeatCapacity()
+{ return !Dune::Std::is_detected::value && ComponentTraits::hasGasState; }
+template constexpr inline bool hasGasViscosity()
+{ return !Dune::Std::is_detected::value && ComponentTraits::hasGasState; }
+template constexpr inline bool hasGasPressure()
+{ return Dune::Std::is_detected::value && ComponentTraits::hasGasState; }
+
+} // end namespace Dumux::Components::Detail
+
+namespace Dumux::Components {
/*!
* \ingroup Components
- * \brief Tabulates all thermodynamic properties of a given
- * untabulated chemical species.
+ * \brief Tabulates all thermodynamic properties of a given component
*
* At the moment, this class can only handle the sub-critical fluids
* since it tabulates along the vapor pressure curve.
@@ -80,6 +139,7 @@ namespace Components {
template
class TabulatedComponent
{
+ using ThisType = TabulatedComponent;
public:
//! export scalar type
using Scalar = typename RawComponent::Scalar;
@@ -106,7 +166,11 @@ public:
pressMin_ = pressMin;
pressMax_ = pressMax;
nPress_ = nPress;
- nDensity_ = nPress_;
+ nDensity_ = nPress;
+
+#ifndef NDEBUG
+ warningPrinted_ = false;
+#endif
std::cout << "-------------------------------------------------------------------------\n"
<< "Initializing tables for the " << RawComponent::name()
@@ -121,49 +185,86 @@ public:
assert(std::numeric_limits::has_quiet_NaN);
const auto NaN = std::numeric_limits::quiet_NaN();
+ // initialize vapor pressure array depending on useVaporPressure
vaporPressure_.resize(nTemp_, NaN);
- minGasDensity_.resize(nTemp_, NaN);
- maxGasDensity_.resize(nTemp_, NaN);
- minLiquidDensity_.resize(nTemp_, NaN);
- maxLiquidDensity_.resize(nTemp_, NaN);
-
- const std::size_t numEntriesTp = nTemp_*nPress_; // = nTemp_*nDensity_
- gasEnthalpy_.resize(numEntriesTp, NaN);
- liquidEnthalpy_.resize(numEntriesTp, NaN);
- gasHeatCapacity_.resize(numEntriesTp, NaN);
- liquidHeatCapacity_.resize(numEntriesTp, NaN);
- gasDensity_.resize(numEntriesTp, NaN);
- liquidDensity_.resize(numEntriesTp, NaN);
- gasViscosity_.resize(numEntriesTp, NaN);
- liquidViscosity_.resize(numEntriesTp, NaN);
- gasThermalConductivity_.resize(numEntriesTp, NaN);
- liquidThermalConductivity_.resize(numEntriesTp, NaN);
- gasPressure_.resize(numEntriesTp, NaN);
- liquidPressure_.resize(numEntriesTp, NaN);
-
- // reset all flags
- minMaxLiquidDensityInitialized_ = false;
- minMaxGasDensityInitialized_ = false;
- gasEnthalpyInitialized_ = false;
- liquidEnthalpyInitialized_ = false;
- gasHeatCapacityInitialized_ = false;
- liquidHeatCapacityInitialized_ = false;
- gasDensityInitialized_ = false;
- liquidDensityInitialized_ = false;
- gasViscosityInitialized_ = false;
- liquidViscosityInitialized_ = false;
- gasThermalConductivityInitialized_ = false;
- liquidThermalConductivityInitialized_ = false;
- gasPressureInitialized_ = false;
- liquidPressureInitialized_ = false;
-
- //! initialize vapor pressure array depending on useVaporPressure
initVaporPressure_();
-#ifndef NDEBUG
+ if constexpr (ComponentTraits::hasGasState)
+ {
+ minGasDensity_.resize(nTemp_, NaN);
+ maxGasDensity_.resize(nTemp_, NaN);
+ const std::size_t numEntriesTp = nTemp_*nPress_;
+ gasEnthalpy_.resize(numEntriesTp, NaN);
+ gasHeatCapacity_.resize(numEntriesTp, NaN);
+ gasDensity_.resize(numEntriesTp, NaN);
+ gasViscosity_.resize(numEntriesTp, NaN);
+ gasThermalConductivity_.resize(numEntriesTp, NaN);
+
+ if constexpr (RawComponent::gasIsCompressible())
+ gasPressure_.resize(numEntriesTp, NaN);
+
+ minMaxGasDensityInitialized_ = false;
+ gasEnthalpyInitialized_ = false;
+ gasHeatCapacityInitialized_ = false;
+ gasDensityInitialized_ = false;
+ gasViscosityInitialized_ = false;
+ gasThermalConductivityInitialized_ = false;
+ gasPressureInitialized_ = false;
+ }
+
+ if constexpr (ComponentTraits::hasLiquidState)
+ {
+ minLiquidDensity_.resize(nTemp_, NaN);
+ maxLiquidDensity_.resize(nTemp_, NaN);
+
+ const std::size_t numEntriesTp = nTemp_*nPress_;
+ liquidEnthalpy_.resize(numEntriesTp, NaN);
+ liquidHeatCapacity_.resize(numEntriesTp, NaN);
+ liquidDensity_.resize(numEntriesTp, NaN);
+ liquidViscosity_.resize(numEntriesTp, NaN);
+ liquidThermalConductivity_.resize(numEntriesTp, NaN);
+
+ if constexpr (RawComponent::liquidIsCompressible())
+ liquidPressure_.resize(numEntriesTp, NaN);
+
+ // reset all flags
+ minMaxLiquidDensityInitialized_ = false;
+ liquidEnthalpyInitialized_ = false;
+ liquidHeatCapacityInitialized_ = false;
+ liquidDensityInitialized_ = false;
+ liquidViscosityInitialized_ = false;
+ liquidThermalConductivityInitialized_ = false;
+ liquidPressureInitialized_ = false;
+ }
+
+ // in the multithreaded case precompute all array because lazy-loading
+ // leads to potential data races
+ if constexpr (!Multithreading::isSerial())
+ {
+ if constexpr (ComponentTraits::hasGasState)
+ {
+ minMaxGasDensityInitialized_ = tabularizeMinMaxGasDensity_();
+ gasPressureInitialized_ = tabularizeGasPressure_();
+ gasEnthalpyInitialized_ = tabularizeGasEnthalpy_();
+ gasHeatCapacityInitialized_ = tabularizeGasHeatCapacity_();
+ gasDensityInitialized_ = tabularizeGasDensity_();
+ gasViscosityInitialized_ = tabularizeGasViscosity_();
+ gasThermalConductivityInitialized_ = tabularizeGasThermalConductivity_();
+ }
+
+ if constexpr (ComponentTraits::hasLiquidState)
+ {
+ minMaxLiquidDensityInitialized_ = tabularizeMinMaxLiquidDensity_();
+ liquidPressureInitialized_ = tabularizeLiquidPressure_();
+ liquidEnthalpyInitialized_ = tabularizeLiquidEnthalpy_();
+ liquidHeatCapacityInitialized_ = tabularizeLiquidHeatCapacity_();
+ liquidDensityInitialized_ = tabularizeLiquidDensity_();
+ liquidViscosityInitialized_ = tabularizeLiquidViscosity_();
+ liquidThermalConductivityInitialized_ = tabularizeLiquidThermalConductivity_();
+ }
+ }
+
initialized_ = true;
- warningPrinted_ = false;
-#endif
}
/*!
@@ -242,12 +343,15 @@ public:
using std::isnan;
if (isnan(result))
{
- if (!gasEnthalpyInitialized_)
+ if constexpr (Multithreading::isSerial())
{
- auto gasEnth = [] (auto T, auto p) { return RawComponent::gasEnthalpy(T, p); };
- initTPArray_(gasEnth, minGasPressure_, maxGasPressure_, gasEnthalpy_);
- gasEnthalpyInitialized_ = true;
- return gasEnthalpy(temperature, pressure);
+ // lazy tabularization
+ if (!gasEnthalpyInitialized_)
+ {
+ gasEnthalpyInitialized_ = tabularizeGasEnthalpy_();
+ if (gasEnthalpyInitialized_)
+ return gasEnthalpy(temperature, pressure);
+ }
}
printWarning_("gasEnthalpy", temperature, pressure);
@@ -269,12 +373,15 @@ public:
using std::isnan;
if (isnan(result))
{
- if (!liquidEnthalpyInitialized_)
+ if constexpr (Multithreading::isSerial())
{
- auto liqEnth = [] (auto T, auto p) { return RawComponent::liquidEnthalpy(T, p); };
- initTPArray_(liqEnth, minLiquidPressure_, maxLiquidPressure_, liquidEnthalpy_);
- liquidEnthalpyInitialized_ = true;
- return liquidEnthalpy(temperature, pressure);
+ // lazy tabularization
+ if (!liquidEnthalpyInitialized_)
+ {
+ liquidEnthalpyInitialized_ = tabularizeLiquidEnthalpy_();
+ if (liquidEnthalpyInitialized_)
+ return liquidEnthalpy(temperature, pressure);
+ }
}
printWarning_("liquidEnthalpy", temperature, pressure);
@@ -296,12 +403,15 @@ public:
using std::isnan;
if (isnan(result))
{
- if (!gasHeatCapacityInitialized_)
+ if constexpr (Multithreading::isSerial())
{
- auto gasHC = [] (auto T, auto p) { return RawComponent::gasHeatCapacity(T, p); };
- initTPArray_(gasHC, minGasPressure_, maxGasPressure_, gasHeatCapacity_);
- gasHeatCapacityInitialized_ = true;
- return gasHeatCapacity(temperature, pressure);
+ // lazy tabularization
+ if (!gasHeatCapacityInitialized_)
+ {
+ gasHeatCapacityInitialized_ = tabularizeGasHeatCapacity_();
+ if (gasHeatCapacityInitialized_)
+ return gasHeatCapacity(temperature, pressure);
+ }
}
printWarning_("gasHeatCapacity", temperature, pressure);
@@ -323,12 +433,15 @@ public:
using std::isnan;
if (isnan(result))
{
- if (!liquidHeatCapacityInitialized_)
+ if constexpr (Multithreading::isSerial())
{
- auto liqHC = [] (auto T, auto p) { return RawComponent::liquidHeatCapacity(T, p); };
- initTPArray_(liqHC, minLiquidPressure_, maxLiquidPressure_, liquidHeatCapacity_);
- liquidHeatCapacityInitialized_ = true;
- return liquidHeatCapacity(temperature, pressure);
+ // lazy tabularization
+ if (!liquidHeatCapacityInitialized_)
+ {
+ liquidHeatCapacityInitialized_ = tabularizeLiquidHeatCapacity_();
+ if (liquidHeatCapacityInitialized_)
+ return liquidHeatCapacity(temperature, pressure);
+ }
}
printWarning_("liquidHeatCapacity", temperature, pressure);
@@ -367,24 +480,24 @@ public:
*/
static Scalar gasPressure(Scalar temperature, Scalar density)
{
- //! make sure the minimum/maximum densities have been computed
- if (!minMaxGasDensityInitialized_)
+ if constexpr (Multithreading::isSerial())
{
- auto gasRho = [] (auto T, auto p) { return RawComponent::gasDensity(T, p); };
- initMinMaxRhoArray_(gasRho, minGasPressure_, maxGasPressure_, minGasDensity_, maxGasDensity_);
- minMaxGasDensityInitialized_ = true;
+ if (!minMaxGasDensityInitialized_)
+ minMaxGasDensityInitialized_ = tabularizeMinMaxGasDensity_();
}
Scalar result = interpolateTRho_(gasPressure_, temperature, density, densityGasIdx_);
using std::isnan;
if (isnan(result))
{
- if (!gasPressureInitialized_)
+ if constexpr (Multithreading::isSerial())
{
- auto gasPFunc = [] (auto T, auto rho) { return RawComponent::gasPressure(T, rho); };
- initPressureArray_(gasPressure_, gasPFunc, minGasDensity_, maxGasDensity_);
- gasPressureInitialized_ = true;
- return gasPressure(temperature, density);
+ if (!gasPressureInitialized_)
+ {
+ gasPressureInitialized_ = tabularizeGasPressure_();
+ if (gasPressureInitialized_)
+ return gasPressure(temperature, density);
+ }
}
printWarning_("gasPressure", temperature, density);
@@ -401,24 +514,25 @@ public:
*/
static Scalar liquidPressure(Scalar temperature, Scalar density)
{
- //! make sure the minimum/maximum densities have been computed
- if (!minMaxLiquidDensityInitialized_)
+ if constexpr (Multithreading::isSerial())
{
- auto liqRho = [] (auto T, auto p) { return RawComponent::liquidDensity(T, p); };
- initMinMaxRhoArray_(liqRho, minLiquidPressure_, maxLiquidPressure_, minLiquidDensity_, maxLiquidDensity_);
- minMaxLiquidDensityInitialized_ = true;
+ if (!minMaxLiquidDensityInitialized_)
+ minMaxLiquidDensityInitialized_ = tabularizeMinMaxLiquidDensity_();
}
Scalar result = interpolateTRho_(liquidPressure_, temperature, density, densityLiquidIdx_);
using std::isnan;
if (isnan(result))
{
- if (!liquidPressureInitialized_)
+ if constexpr (Multithreading::isSerial())
{
- auto liqPFunc = [] (auto T, auto rho) { return RawComponent::liquidPressure(T, rho); };
- initPressureArray_(liquidPressure_, liqPFunc, minLiquidDensity_, maxLiquidDensity_);
- liquidPressureInitialized_ = true;
- return liquidPressure(temperature, density);
+ // lazy tabularization
+ if (!liquidPressureInitialized_)
+ {
+ liquidPressureInitialized_ = tabularizeLiquidPressure_();
+ if (liquidPressureInitialized_)
+ return liquidPressure(temperature, density);
+ }
}
printWarning_("liquidPressure", temperature, density);
@@ -460,12 +574,15 @@ public:
using std::isnan;
if (isnan(result))
{
- if (!gasDensityInitialized_)
+ if constexpr (Multithreading::isSerial())
{
- auto gasRho = [] (auto T, auto p) { return RawComponent::gasDensity(T, p); };
- initTPArray_(gasRho, minGasPressure_, maxGasPressure_, gasDensity_);
- gasDensityInitialized_ = true;
- return gasDensity(temperature, pressure);
+ // lazy tabularization
+ if (!gasDensityInitialized_)
+ {
+ gasDensityInitialized_ = tabularizeGasDensity_();
+ if (gasDensityInitialized_)
+ return gasDensity(temperature, pressure);
+ }
}
printWarning_("gasDensity", temperature, pressure);
@@ -499,16 +616,15 @@ public:
using std::isnan;
if (isnan(result))
{
- if (!liquidDensityInitialized_)
+ if constexpr (Multithreading::isSerial())
{
- // TODO: we could get rid of the lambdas and pass the functor irectly. But,
- // currently Brine is a component (and not a fluid system) expecting a
- // third argument with a default, which cannot be wrapped in a function pointer.
- // For this reason we have to wrap this into a lambda here.
- auto liqRho = [] (auto T, auto p) { return RawComponent::liquidDensity(T, p); };
- initTPArray_(liqRho, minLiquidPressure_, maxLiquidPressure_, liquidDensity_);
- liquidDensityInitialized_ = true;
- return liquidDensity(temperature, pressure);
+ // lazy tabularization
+ if (!liquidDensityInitialized_)
+ {
+ liquidDensityInitialized_ = tabularizeLiquidDensity_();
+ if (liquidDensityInitialized_)
+ return liquidDensity(temperature, pressure);
+ }
}
printWarning_("liquidDensity", temperature, pressure);
@@ -542,12 +658,15 @@ public:
using std::isnan;
if (isnan(result))
{
- if (!gasViscosityInitialized_)
+ if constexpr (Multithreading::isSerial())
{
- auto gasVisc = [] (auto T, auto p) { return RawComponent::gasViscosity(T, p); };
- initTPArray_(gasVisc, minGasPressure_, maxGasPressure_, gasViscosity_);
- gasViscosityInitialized_ = true;
- return gasViscosity(temperature, pressure);
+ // lazy tabularization
+ if (!gasViscosityInitialized_)
+ {
+ gasViscosityInitialized_ = tabularizeGasViscosity_();
+ if (gasViscosityInitialized_)
+ return gasViscosity(temperature, pressure);
+ }
}
printWarning_("gasViscosity", temperature, pressure);
@@ -569,12 +688,15 @@ public:
using std::isnan;
if (isnan(result))
{
- if (!liquidViscosityInitialized_)
+ if constexpr (Multithreading::isSerial())
{
- auto liqVisc = [] (auto T, auto p) { return RawComponent::liquidViscosity(T, p); };
- initTPArray_(liqVisc, minLiquidPressure_, maxLiquidPressure_, liquidViscosity_);
- liquidViscosityInitialized_ = true;
- return liquidViscosity(temperature, pressure);
+ // lazy tabularization
+ if (!liquidViscosityInitialized_)
+ {
+ liquidViscosityInitialized_ = tabularizeLiquidViscosity_();
+ if (liquidViscosityInitialized_)
+ return liquidViscosity(temperature, pressure);
+ }
}
printWarning_("liquidViscosity",temperature, pressure);
@@ -596,12 +718,15 @@ public:
using std::isnan;
if (isnan(result))
{
- if (!gasThermalConductivityInitialized_)
+ if constexpr (Multithreading::isSerial())
{
- auto gasTC = [] (auto T, auto p) { return RawComponent::gasThermalConductivity(T, p); };
- initTPArray_(gasTC, minGasPressure_, maxGasPressure_, gasThermalConductivity_);
- gasThermalConductivityInitialized_ = true;
- return gasThermalConductivity(temperature, pressure);
+ // lazy tabularization
+ if (!gasThermalConductivityInitialized_)
+ {
+ gasThermalConductivityInitialized_ = tabularizeGasThermalConductivity_();
+ if (gasThermalConductivityInitialized_)
+ return gasThermalConductivity(temperature, pressure);
+ }
}
printWarning_("gasThermalConductivity", temperature, pressure);
@@ -623,12 +748,15 @@ public:
using std::isnan;
if (isnan(result))
{
- if (!liquidThermalConductivityInitialized_)
+ if constexpr (Multithreading::isSerial())
{
- auto liqTC = [] (auto T, auto p) { return RawComponent::liquidThermalConductivity(T, p); };
- initTPArray_(liqTC, minLiquidPressure_, maxLiquidPressure_, liquidThermalConductivity_);
- liquidThermalConductivityInitialized_ = true;
- return liquidThermalConductivity(temperature, pressure);
+ // lazy tabularization
+ if (!liquidThermalConductivityInitialized_)
+ {
+ liquidThermalConductivityInitialized_ = tabularizeLiquidThermalConductivity_();
+ if (liquidThermalConductivityInitialized_)
+ return liquidThermalConductivity(temperature, pressure);
+ }
}
printWarning_("liquidThermalConductivity", temperature, pressure);
@@ -664,11 +792,11 @@ private:
static void initVaporPressure_()
{
// fill the temperature-pressure arrays
- for (unsigned iT = 0; iT < nTemp_; ++ iT)
+ Dumux::parallelFor(nTemp_, [&](std::size_t iT)
{
Scalar temperature = iT * (tempMax_ - tempMin_)/(nTemp_ - 1) + tempMin_;
vaporPressure_[iT] = RawComponent::vaporPressure(temperature);
- }
+ });
}
//! if !useVaporPressure, do nothing here
@@ -692,18 +820,18 @@ private:
template
static void initTPArray_(PropFunc&& f, MinPFunc&& minP, MaxPFunc&& maxP, std::vector& values)
{
- for (unsigned iT = 0; iT < nTemp_; ++ iT)
+ Dumux::parallelFor(nTemp_, [&](std::size_t iT)
{
Scalar temperature = iT * (tempMax_ - tempMin_)/(nTemp_ - 1) + tempMin_;
Scalar pMax = maxP(iT);
Scalar pMin = minP(iT);
- for (unsigned iP = 0; iP < nPress_; ++ iP)
+ for (std::size_t iP = 0; iP < nPress_; ++ iP)
{
Scalar pressure = iP * (pMax - pMin)/(nPress_ - 1) + pMin;
values[iT + iP*nTemp_] = f(temperature, pressure);
}
- }
+ });
}
/*!
@@ -728,7 +856,7 @@ private:
std::vector& rhoMin,
std::vector& rhoMax)
{
- for (unsigned iT = 0; iT < nTemp_; ++ iT)
+ Dumux::parallelFor(nTemp_, [&](std::size_t iT)
{
Scalar temperature = iT * (tempMax_ - tempMin_)/(nTemp_ - 1) + tempMin_;
@@ -737,7 +865,7 @@ private:
rhoMax[iT] = rho(temperature, maxP(iT + 1));
else
rhoMax[iT] = rho(temperature, maxP(iT));
- }
+ });
}
/*!
@@ -755,18 +883,18 @@ private:
const std::vector& rhoMin,
const std::vector& rhoMax)
{
- for (unsigned iT = 0; iT < nTemp_; ++ iT)
+ Dumux::parallelFor(nTemp_, [&](std::size_t iT)
{
Scalar temperature = iT * (tempMax_ - tempMin_)/(nTemp_ - 1) + tempMin_;
- for (unsigned iRho = 0; iRho < nDensity_; ++ iRho)
+ for (std::size_t iRho = 0; iRho < nDensity_; ++ iRho)
{
Scalar density = Scalar(iRho)/(nDensity_ - 1)
* (rhoMax[iT] - rhoMin[iT])
+ rhoMin[iT];
pressure[iT + iRho*nTemp_] = p(temperature, density);
}
- }
+ });
}
//! returns an interpolated value depending on temperature
@@ -776,7 +904,7 @@ private:
if (alphaT < 0 || alphaT >= nTemp_ - 1)
return std::numeric_limits::quiet_NaN();
- unsigned iT = (unsigned) alphaT;
+ const auto iT = static_cast(alphaT);
alphaT -= iT;
return values[iT ]*(1 - alphaT) +
@@ -792,16 +920,15 @@ private:
if (alphaT < 0 || alphaT >= nTemp_ - 1) {
return std::numeric_limits::quiet_NaN();
}
- using std::min;
- using std::max;
- unsigned iT = max(0, min(nTemp_ - 2, (int) alphaT));
+ using std::clamp;
+ const auto iT = clamp(static_cast(alphaT), 0, nTemp_ - 2);
alphaT -= iT;
Scalar alphaP1 = getPIdx(p, iT);
Scalar alphaP2 = getPIdx(p, iT + 1);
- unsigned iP1 = max(0, min(nPress_ - 2, (int) alphaP1));
- unsigned iP2 = max(0, min(nPress_ - 2, (int) alphaP2));
+ const auto iP1 = clamp(static_cast(alphaP1), 0, nPress_ - 2);
+ const auto iP2 = clamp(static_cast(alphaP2), 0, nPress_ - 2);
alphaP1 -= iP1;
alphaP2 -= iP2;
@@ -827,16 +954,15 @@ private:
template
static Scalar interpolateTRho_(const std::vector& values, Scalar T, Scalar rho, GetRhoIdx&& rhoIdx)
{
- using std::min;
- using std::max;
+ using std::clamp;
Scalar alphaT = tempIdx_(T);
- unsigned iT = max(0, min(nTemp_ - 2, (int) alphaT));
+ const auto iT = clamp(static_cast(alphaT), 0, nTemp_ - 2);
alphaT -= iT;
Scalar alphaP1 = rhoIdx(rho, iT);
Scalar alphaP2 = rhoIdx(rho, iT + 1);
- unsigned iP1 = max(0, min(nDensity_ - 2, (int) alphaP1));
- unsigned iP2 = max(0, min(nDensity_ - 2, (int) alphaP2));
+ const auto iP1 = clamp(static_cast(alphaP1), 0, nDensity_ - 2);
+ const auto iP2 = clamp(static_cast(alphaP2), 0, nDensity_ - 2);
alphaP1 -= iP1;
alphaP2 -= iP2;
@@ -853,7 +979,7 @@ private:
}
//! returns the index of an entry in a pressure field
- static Scalar pressLiquidIdx_(Scalar pressure, unsigned tempIdx)
+ static Scalar pressLiquidIdx_(Scalar pressure, std::size_t tempIdx)
{
Scalar plMin = minLiquidPressure_(tempIdx);
Scalar plMax = maxLiquidPressure_(tempIdx);
@@ -862,7 +988,7 @@ private:
}
//! returns the index of an entry in a temperature field
- static Scalar pressGasIdx_(Scalar pressure, unsigned tempIdx)
+ static Scalar pressGasIdx_(Scalar pressure, std::size_t tempIdx)
{
Scalar pgMin = minGasPressure_(tempIdx);
Scalar pgMax = maxGasPressure_(tempIdx);
@@ -871,7 +997,7 @@ private:
}
//! returns the index of an entry in a density field
- static Scalar densityLiquidIdx_(Scalar density, unsigned tempIdx)
+ static Scalar densityLiquidIdx_(Scalar density, std::size_t tempIdx)
{
Scalar densityMin = minLiquidDensity_[tempIdx];
Scalar densityMax = maxLiquidDensity_[tempIdx];
@@ -879,14 +1005,14 @@ private:
}
//! returns the index of an entry in a density field
- static Scalar densityGasIdx_(Scalar density, unsigned tempIdx)
+ static Scalar densityGasIdx_(Scalar density, std::size_t tempIdx)
{
Scalar densityMin = minGasDensity_[tempIdx];
Scalar densityMax = maxGasDensity_[tempIdx];
return (nDensity_ - 1) * (density - densityMin)/(densityMax - densityMin);
}
- //! returns the minimum tabulized liquid pressure at a given temperature index
+ //! returns the minimum tabularized liquid pressure at a given temperature index
static Scalar minLiquidPressure_(int tempIdx)
{
using std::max;
@@ -896,7 +1022,7 @@ private:
return max(pressMin_, vaporPressure_[tempIdx] / 1.1);
}
- //! returns the maximum tabulized liquid pressure at a given temperature index
+ //! returns the maximum tabularized liquid pressure at a given temperature index
static Scalar maxLiquidPressure_(int tempIdx)
{
using std::max;
@@ -906,7 +1032,7 @@ private:
return max(pressMax_, vaporPressure_[tempIdx] * 1.1);
}
- //! returns the minimum tabulized gas pressure at a given temperature index
+ //! returns the minimum tabularized gas pressure at a given temperature index
static Scalar minGasPressure_(int tempIdx)
{
using std::min;
@@ -916,7 +1042,7 @@ private:
return min(pressMin_, vaporPressure_[tempIdx] / 1.1 );
}
- //! returns the maximum tabulized gas pressure at a given temperature index
+ //! returns the maximum tabularized gas pressure at a given temperature index
static Scalar maxGasPressure_(int tempIdx)
{
using std::min;
@@ -926,9 +1052,198 @@ private:
return min(pressMax_, vaporPressure_[tempIdx] * 1.1);
}
-#ifndef NDEBUG
+ template
+ static bool tabularizeGasEnthalpy_()
+ {
+ if constexpr (Detail::hasGasEnthalpy())
+ {
+ auto gasEnth = [] (auto T, auto p) { return RC::gasEnthalpy(T, p); };
+ initTPArray_(gasEnth, minGasPressure_, maxGasPressure_, gasEnthalpy_);
+ return true;
+ }
+
+ return false;
+ }
+
+ template
+ static bool tabularizeLiquidEnthalpy_()
+ {
+ if constexpr (Detail::hasLiquidEnthalpy())
+ {
+ auto liqEnth = [] (auto T, auto p) { return RC::liquidEnthalpy(T, p); };
+ initTPArray_(liqEnth, minLiquidPressure_, maxLiquidPressure_, liquidEnthalpy_);
+ return true;
+ }
+
+ return false;
+ }
+
+ template
+ static bool tabularizeGasHeatCapacity_()
+ {
+ if constexpr (Detail::hasGasHeatCapacity())
+ {
+ auto gasHC = [] (auto T, auto p) { return RC::gasHeatCapacity(T, p); };
+ initTPArray_(gasHC, minGasPressure_, maxGasPressure_, gasHeatCapacity_);
+ return true;
+ }
+
+ return false;
+ }
+
+ template
+ static bool tabularizeLiquidHeatCapacity_()
+ {
+ if constexpr (Detail::hasLiquidHeatCapacity())
+ {
+ auto liqHC = [] (auto T, auto p) { return RC::liquidHeatCapacity(T, p); };
+ initTPArray_(liqHC, minLiquidPressure_, maxLiquidPressure_, liquidHeatCapacity_);
+ return true;
+ }
+
+ return false;
+ }
+
+ template
+ static bool tabularizeMinMaxGasDensity_()
+ {
+ if constexpr (Detail::hasGasDensity())
+ {
+ auto gasRho = [] (auto T, auto p) { return RC::gasDensity(T, p); };
+ initMinMaxRhoArray_(gasRho, minGasPressure_, maxGasPressure_, minGasDensity_, maxGasDensity_);
+ return true;
+ }
+
+ return false;
+ }
+
+ template
+ static bool tabularizeMinMaxLiquidDensity_()
+ {
+ if constexpr (Detail::hasGasEnthalpy())
+ {
+ auto liqRho = [] (auto T, auto p) { return RC::liquidDensity(T, p); };
+ initMinMaxRhoArray_(liqRho, minLiquidPressure_, maxLiquidPressure_, minLiquidDensity_, maxLiquidDensity_);
+ return true;
+ }
+
+ return false;
+ }
+
+ template
+ static bool tabularizeGasPressure_()
+ {
+ // pressure is only defined if the gas is compressible (this is usually the case)
+ if constexpr (Detail::hasGasPressure() && RC::gasIsCompressible())
+ {
+ auto gasPFunc = [] (auto T, auto rho) { return RC::gasPressure(T, rho); };
+ initPressureArray_(gasPressure_, gasPFunc, minGasDensity_, maxGasDensity_);
+ return true;
+ }
+
+ return false;
+ }
+
+ template
+ static bool tabularizeLiquidPressure_()
+ {
+ // pressure is only defined if the liquid is compressible (this is often not the case)
+ if constexpr (Detail::hasLiquidPressure() && RC::liquidIsCompressible())
+ {
+ auto liqPFunc = [] (auto T, auto rho) { return RC::liquidPressure(T, rho); };
+ initPressureArray_(liquidPressure_, liqPFunc, minLiquidDensity_, maxLiquidDensity_);
+ return true;
+ }
+
+ return false;
+ }
+
+ template
+ static bool tabularizeGasDensity_()
+ {
+ if constexpr (Detail::hasGasDensity())
+ {
+ auto gasRho = [] (auto T, auto p) { return RC::gasDensity(T, p); };
+ initTPArray_(gasRho, minGasPressure_, maxGasPressure_, gasDensity_);
+ return true;
+ }
+
+ return false;
+ }
+
+ template
+ static bool tabularizeLiquidDensity_()
+ {
+ if constexpr (Detail::hasLiquidDensity())
+ {
+ // TODO: we could get rid of the lambdas and pass the functor directly. But,
+ // currently Brine is a component (and not a fluid system) expecting a
+ // third argument with a default, which cannot be wrapped in a function pointer.
+ // For this reason we have to wrap this into a lambda here.
+ auto liqRho = [] (auto T, auto p) { return RC::liquidDensity(T, p); };
+ initTPArray_(liqRho, minLiquidPressure_, maxLiquidPressure_, liquidDensity_);
+ return true;
+ }
+
+ return false;
+ }
+
+ template
+ static bool tabularizeGasViscosity_()
+ {
+ if constexpr (Detail::hasGasViscosity())
+ {
+ auto gasVisc = [] (auto T, auto p) { return RC::gasViscosity(T, p); };
+ initTPArray_(gasVisc, minGasPressure_, maxGasPressure_, gasViscosity_);
+ return true;
+ }
+
+ return false;
+ }
+
+ template
+ static bool tabularizeLiquidViscosity_()
+ {
+ if constexpr (Detail::hasLiquidViscosity())
+ {
+ auto liqVisc = [] (auto T, auto p) { return RC::liquidViscosity(T, p); };
+ initTPArray_(liqVisc, minLiquidPressure_, maxLiquidPressure_, liquidViscosity_);
+ return true;
+ }
+
+ return false;
+ }
+
+ template
+ static bool tabularizeGasThermalConductivity_()
+ {
+ if constexpr (Detail::hasGasThermalConductivity())
+ {
+ auto gasTC = [] (auto T, auto p) { return RC::gasThermalConductivity(T, p); };
+ initTPArray_(gasTC, minGasPressure_, maxGasPressure_, gasThermalConductivity_);
+ return true;
+ }
+
+ return false;
+ }
+
+ template
+ static bool tabularizeLiquidThermalConductivity_()
+ {
+ if constexpr (Detail::hasLiquidThermalConductivity())
+ {
+ auto liqTC = [] (auto T, auto p) { return RC::liquidThermalConductivity(T, p); };
+ initTPArray_(liqTC, minLiquidPressure_, maxLiquidPressure_, liquidThermalConductivity_);
+ return true;
+ }
+
+ return false;
+ }
+
// specifies whether the table was initialized
static bool initialized_;
+
+#ifndef NDEBUG
// specifies whether some warning was printed
static bool warningPrinted_;
#endif
@@ -979,21 +1294,22 @@ private:
// temperature, pressure and density ranges
static Scalar tempMin_;
static Scalar tempMax_;
- static unsigned nTemp_;
+ static std::size_t nTemp_;
static Scalar pressMin_;
static Scalar pressMax_;
- static unsigned nPress_;
+ static std::size_t nPress_;
static Scalar densityMin_;
static Scalar densityMax_;
- static unsigned nDensity_;
+ static std::size_t nDensity_;
};
-#ifndef NDEBUG
+
template
bool TabulatedComponent::initialized_ = false;
+#ifndef NDEBUG
template
bool TabulatedComponent::warningPrinted_ = false;
#endif
@@ -1066,19 +1382,19 @@ typename RawComponent::Scalar TabulatedComponent
template
typename RawComponent::Scalar TabulatedComponent::tempMax_;
template
-unsigned TabulatedComponent::nTemp_;
+std::size_t TabulatedComponent::nTemp_;
template
typename RawComponent::Scalar TabulatedComponent::pressMin_;
template
typename RawComponent::Scalar TabulatedComponent::pressMax_;
template
-unsigned TabulatedComponent::nPress_;
+std::size_t TabulatedComponent::nPress_;
template
typename RawComponent::Scalar TabulatedComponent::densityMin_;
template
typename RawComponent::Scalar TabulatedComponent::densityMax_;
template
-unsigned TabulatedComponent::nDensity_;
+std::size_t TabulatedComponent::nDensity_;
// forward declaration
template
@@ -1088,8 +1404,6 @@ struct IsAqueous;
template
struct IsAqueous> : public IsAqueous {};
-} // end namespace Components
-
-} // end namespace Dumux
+} // end namespace Dumux::Components
#endif
diff --git a/dumux/material/fluidsystems/h2on2.hh b/dumux/material/fluidsystems/h2on2.hh
index e75b3ffe12e483ea817a6926dfb47ff8a55427d9..ccbae655f0218007b21b633b76d0dee35367992b 100644
--- a/dumux/material/fluidsystems/h2on2.hh
+++ b/dumux/material/fluidsystems/h2on2.hh
@@ -347,11 +347,8 @@ public:
std::cout << " - use N2 heat conductivity as gas mixture heat conductivity: " << std::boolalpha << Policy::useN2HeatConductivityAsGasMixtureHeatConductivity() << "\n";
std::cout << " - use ideal gas heat capacities: " << std::boolalpha << Policy::useIdealGasHeatCapacities() << std::endl;
- if (H2O::isTabulated)
- {
- TabulatedH2O::init(tempMin, tempMax, nTemp,
- pressMin, pressMax, nPress);
- }
+ if constexpr (H2O::isTabulated)
+ H2O::init(tempMin, tempMax, nTemp, pressMin, pressMax, nPress);
}
using Base::density;
diff --git a/test/material/tabulation/test_tabulation.cc b/test/material/tabulation/test_tabulation.cc
index 8c12d7d36fa5280452b9d4804d169b9e9a5a785f..7265ab56ef61cabfc54e9f32094780e6d32b8da4 100644
--- a/test/material/tabulation/test_tabulation.cc
+++ b/test/material/tabulation/test_tabulation.cc
@@ -30,6 +30,8 @@
#include
+#include
+
#include
#include
#include
@@ -68,6 +70,9 @@ int main(int argc, char *argv[])
using namespace Dumux;
using Scalar = double;
+ // initialize MPI+X (tabulation uses multithreading features)
+ Dumux::initialize(argc, argv);
+
// test IapwsH2O in detail
{
using IapwsH2O = Components::H2O;
@@ -89,7 +94,7 @@ int main(int argc, char *argv[])
std::cout << "Checking tabulation\n";
const int m = nTemp*3;
const int n = nPress*3;
- for (int i = 0; i < m; ++i)
+ Dumux::parallelFor(m, [&](int i)
{
const Scalar T = tempMin + (tempMax - tempMin)*Scalar(i)/Scalar(m-1);
checkEquality("vaporPressure", TabulatedH2O::vaporPressure(T), IapwsH2O::vaporPressure(T), eps);
@@ -120,8 +125,7 @@ int main(int argc, char *argv[])
}
-
- }
+ });
}
// test if other components can be tabulated
@@ -135,7 +139,7 @@ int main(int argc, char *argv[])
Components::TabulatedComponent, false>::init(273, 275, 3, 1e5, 1e6, 3);
Components::TabulatedComponent, false>::init(273, 275, 3, 1e5, 1e6, 3);
Components::TabulatedComponent, false>::init(273, 275, 3, 1e5, 1e6, 3);
- Components::TabulatedComponent>::init(273, 275, 3, 1e5, 1e6, 3);
+ Components::TabulatedComponent>::init(273.15, 275, 3, 1e5, 1e6, 3);
Components::TabulatedComponent>::init(273, 275, 3, 1e5, 1e6, 3);
Components::TabulatedComponent>::init(273, 275, 3, 1e5, 1e6, 3);
Components::TabulatedComponent>::init(273, 275, 3, 1e5, 1e6, 3);
diff --git a/test/porousmediumflow/1p/compressible/instationary/problem.hh b/test/porousmediumflow/1p/compressible/instationary/problem.hh
index bb5f6c99c81c0a044d60fae549c03a98fe018421..d904cc1b2e5f96eab5ad671ce2b1c4614f7df791 100644
--- a/test/porousmediumflow/1p/compressible/instationary/problem.hh
+++ b/test/porousmediumflow/1p/compressible/instationary/problem.hh
@@ -55,8 +55,8 @@ public:
OnePTestProblem(std::shared_ptr gridGeometry)
: ParentType(gridGeometry)
{
- Components::TabulatedComponent>::init(272.15, 294.15, 10,
- 1.0e4, 1.0e6, 200);
+ Components::TabulatedComponent>
+ ::init(273.15, 294.15, 10, 1.0e4, 1.0e6, 200);
}
/*!
diff --git a/test/porousmediumflow/1p/compressible/stationary/problem.hh b/test/porousmediumflow/1p/compressible/stationary/problem.hh
index 4560eba4d10ef33ced725a5b38f19eafbc394aa3..d0b8353493e7f4e6f62448880a9b9040aab8fbde 100644
--- a/test/porousmediumflow/1p/compressible/stationary/problem.hh
+++ b/test/porousmediumflow/1p/compressible/stationary/problem.hh
@@ -58,7 +58,7 @@ public:
: ParentType(gridGeometry)
{
Components::TabulatedComponent>
- ::init(272.15, 294.15, 10, 1.0e4, 1.0e6, 200);
+ ::init(273.15, 294.15, 10, 1.0e4, 1.0e6, 200);
}
/*!