From 47521dca1d6c29eb9ae00da2cd408f2d010cc213 Mon Sep 17 00:00:00 2001 From: Andreas Lauser Date: Fri, 26 Jun 2015 14:25:25 +0200 Subject: [PATCH] add a multiplexer saturation function --- CMakeLists_files.cmake | 1 + opm/core/props/satfunc/SatFuncMultiplexer.hpp | 268 ++++++++++++++++++ 2 files changed, 269 insertions(+) create mode 100644 opm/core/props/satfunc/SatFuncMultiplexer.hpp diff --git a/CMakeLists_files.cmake b/CMakeLists_files.cmake index 453eea22..522cd8f3 100644 --- a/CMakeLists_files.cmake +++ b/CMakeLists_files.cmake @@ -362,6 +362,7 @@ list (APPEND PUBLIC_HEADER_FILES opm/core/props/rock/RockFromDeck.hpp opm/core/props/satfunc/SatFuncBase.hpp opm/core/props/satfunc/SatFuncGwseg.hpp + opm/core/props/satfunc/SatFuncMultiplexer.hpp opm/core/props/satfunc/SatFuncSimple.hpp opm/core/props/satfunc/SatFuncStone2.hpp opm/core/props/satfunc/SaturationPropsBasic.hpp diff --git a/opm/core/props/satfunc/SatFuncMultiplexer.hpp b/opm/core/props/satfunc/SatFuncMultiplexer.hpp new file mode 100644 index 00000000..4538e8a2 --- /dev/null +++ b/opm/core/props/satfunc/SatFuncMultiplexer.hpp @@ -0,0 +1,268 @@ +/* + Copyright 2015 Andreas Lauser + + This file is part of the Open Porous Media project (OPM). + + OPM is free software: you can redistribute it and/or modify + it under the terms of the GNU General Public License as published by + the Free Software Foundation, either version 3 of the License, or + (at your option) any later version. + + OPM is distributed in the hope that it will be useful, + but WITHOUT ANY WARRANTY; without even the implied warranty of + MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + GNU General Public License for more details. + + You should have received a copy of the GNU General Public License + along with OPM. If not, see . +*/ +/*! + * \file + * \copydoc Opm::SatFuncMultiplexer + */ +#ifndef OPM_SAT_FUNC_MULTIPLEXER_HPP +#define OPM_SAT_FUNC_MULTIPLEXER_HPP + +#include "SatFuncGwseg.hpp" +#include "SatFuncSimple.hpp" +#include "SatFuncStone2.hpp" + +#include + +#include + +namespace Opm +{ + +/*! + * \brief This is a multiplexer class which allows to saturation function to be used at + * runtime. + */ +class SatFuncMultiplexer +{ +public: + typedef NonuniformTableLinear TableType; + + enum SatFuncType { + Gwseg, // <- supposed to be the default + Stone2, + Simple + }; + +// this is a helper macro which helps to save us from RSI in the following +#define OPM_MULTIPLEXER_SATFUNC_CALL(codeToCall) \ + switch (satFuncType_) { \ + case Gwseg: { \ + typedef SatFuncGwseg SatFunc; \ + if (false) SatFunc dummyForWarning; \ + auto& satFunc = getGwseg(); \ + codeToCall; \ + break; \ + } \ + case Stone2: { \ + typedef SatFuncStone2 SatFunc; \ + if (false) SatFunc dummyForWarning; \ + auto& satFunc = getStone2(); \ + codeToCall; \ + break; \ + } \ + case Simple: { \ + typedef SatFuncSimple SatFunc; \ + if (false) SatFunc dummyForWarning; \ + auto& satFunc = getSimple(); \ + codeToCall; \ + break; \ + } \ + }; + + SatFuncMultiplexer() + : wasInitialized_(false) + {} + + ~SatFuncMultiplexer() + { + if (!wasInitialized_) + return; + + // call the destructor of the selected saturation function + OPM_MULTIPLEXER_SATFUNC_CALL(satFunc.~SatFunc()); + } + + /*! + * \brief Pick the correct saturation function type and initialize the object using + * an ECL deck. + */ + void initFromDeck(Opm::EclipseStateConstPtr eclState, + size_t tableIdx, + SatFuncType satFuncType) + { + auto phaseUsage = phaseUsageFromDeck(eclState); + + setSatFuncType(satFuncType); + + OPM_MULTIPLEXER_SATFUNC_CALL(satFunc.init(eclState, + tableIdx, + phaseUsage, + /*samples=*/0)); + } + + /*! + * \brief Returns the type of the actually selected saturation function. + */ + void setSatFuncType(SatFuncType newSatFuncType) + { + assert(!wasInitialized_); + + // set the type of the saturation function + satFuncType_ = newSatFuncType; + + // call the default constructor for the selected saturation function + OPM_MULTIPLEXER_SATFUNC_CALL(new(&satFunc) SatFunc()); + wasInitialized_ = true; + } + + /*! + * \brief Returns which saturation function is actually selected. + */ + SatFuncType satFuncType() const + { return satFuncType_; } + + /*! + * \brief Returns a pointer to the base saturation function. + * + * All underlying saturation functions derive from this class. It stores the stuff + * which is common for all saturation functions (e.g. the endpoint scaling + * parameters). + */ + const SatFuncBase& getSatFuncBase() const + { + switch (satFuncType()) { + case Gwseg: + return getGwseg(); + case Stone2: + return getStone2(); + case Simple: + return getSimple(); + } + OPM_THROW(std::logic_error, "Unhandled saturation function type"); + } + + SatFuncBase& getSatFuncBase() + { + return const_cast&>(static_cast(this)->getSatFuncBase()); + } + +// the strict aliasing compiler warnings need to be ignored here. This is safe because we +// deal with the alignment of the data ourselfs. +#pragma GCC diagnostic push +#pragma GCC diagnostic ignored "-Wstrict-aliasing" + /*! + * \brief Return the raw "Gwseg" saturation function object. + * + * If the saturation function type is not "Gwseg", an assertation is triggered for + * debug builds. + */ + SatFuncGwseg& getGwseg() + { + assert(satFuncType_ == Gwseg); + return *reinterpret_cast*>(satFuncsData_.gwseg); + } + + const SatFuncGwseg& getGwseg() const + { + assert(satFuncType_ == Gwseg); + return *reinterpret_cast*>(satFuncsData_.gwseg); + } + + /*! + * \brief Return the raw "Simple" saturation function object. + * + * If the saturation function type is not "Simple", an assertation is triggered for + * debug builds. + */ + SatFuncSimple& getSimple() + { + assert(satFuncType_ == Simple); + return *reinterpret_cast*>(satFuncsData_.simple); + } + + const SatFuncSimple& getSimple() const + { + assert(satFuncType_ == Simple); + return *reinterpret_cast*>(satFuncsData_.simple); + } + + /*! + * \brief Return the raw "Stone2" saturation function object. + * + * If the saturation function type is not "Stone2", an assertation is triggered for + * debug builds. + */ + SatFuncStone2& getStone2() + { + assert(satFuncType_ == Stone2); + return *reinterpret_cast*>(satFuncsData_.stone2); + } + + const SatFuncStone2& getStone2() const + { + assert(satFuncType_ == Stone2); + return *reinterpret_cast*>(satFuncsData_.stone2); + } +#pragma GCC diagnostic pop + + template + void evalKr(const FluidState& fluidState, double* kr) const + { OPM_MULTIPLEXER_SATFUNC_CALL(satFunc.evalKr(fluidState, kr)); } + + template + void evalKrDeriv(const FluidState& fluidState, double* kr, double* dkrds) const + { OPM_MULTIPLEXER_SATFUNC_CALL(satFunc.evalKrDeriv(fluidState, kr, dkrds)); } + + template + void evalPc(const FluidState& fluidState, double* pc) const + { OPM_MULTIPLEXER_SATFUNC_CALL(satFunc.evalPc(fluidState, pc)); } + + template + void evalPcDeriv(const FluidState& fluidState, double* pc, double* dpcds) const + { OPM_MULTIPLEXER_SATFUNC_CALL(satFunc.evalPcDeriv(fluidState, pc, dpcds)); } + + template + void evalKr(const FluidState& fluidState, double* kr, const EPSTransforms* epst) const + { OPM_MULTIPLEXER_SATFUNC_CALL(satFunc.evalKr(fluidState, kr, epst)); } + + template + void evalKr(const FluidState& fluidState, double* kr, const EPSTransforms* epst, const EPSTransforms* epst_hyst, const SatHyst* sat_hyst) const + { OPM_MULTIPLEXER_SATFUNC_CALL(satFunc.evalKr(fluidState, kr, epst, epst_hyst, sat_hyst)); } + + template + void evalKrDeriv(const FluidState& fluidState, double* kr, double* dkrds, const EPSTransforms* epst) const + { OPM_MULTIPLEXER_SATFUNC_CALL(satFunc.evalKrDeriv(fluidState, kr, dkrds, epst)); } + + template + void evalKrDeriv(const FluidState& fluidState, double* kr, double* dkrds, const EPSTransforms* epst, const EPSTransforms* epst_hyst, const SatHyst* sat_hyst) const + { OPM_MULTIPLEXER_SATFUNC_CALL(satFunc.evalKrDeriv(fluidState, kr, dkrds, epst, epst_hyst, sat_hyst)); } + + template + void evalPc(const FluidState& fluidState, double* pc, const EPSTransforms* epst) const + { OPM_MULTIPLEXER_SATFUNC_CALL(satFunc.evalPc(fluidState, pc, epst)); } + + template + void evalPcDeriv(const FluidState& fluidState, double* pc, double* dpcds, const EPSTransforms* epst) const + { OPM_MULTIPLEXER_SATFUNC_CALL(satFunc.evalPcDeriv(fluidState, pc, dpcds, epst)); } + +// undefine the helper macro here because we don't need it anymore +#undef OPM_MULTIPLEXER_SATFUNC_CALL + +private: + bool wasInitialized_; + SatFuncType satFuncType_; + union { + char gwseg[sizeof(SatFuncGwseg)]; + char simple[sizeof(SatFuncSimple)]; + char stone2[sizeof(SatFuncStone2)]; + } satFuncsData_ __attribute__((aligned(sizeof(double)))); +}; +} // namespace Opm + +#endif // OPM_SAT_FUNC_MULTIPLEXER_HPP