multiplexer saturation function: get rid of the pesky union and the reinterpret_cast
basically, we now store a pointer to the base class and convert this to the concrete incarnation of the saturation function. the only disadvantage of this is that it requires to allocate the concrete objects dynamically, i.e., there's another layer of indirection. On the plus side it saves a few bytes per object and it makes things quite a bit simpler, so it is a win IMO. thanks to [at]atgeirr for suggesting this.
This commit is contained in:
parent
388578f5ba
commit
8ccf1b3dbe
@ -77,6 +77,8 @@ namespace Opm
|
|||||||
class SatFuncBase : public BlackoilPhases
|
class SatFuncBase : public BlackoilPhases
|
||||||
{
|
{
|
||||||
public:
|
public:
|
||||||
|
virtual ~SatFuncBase() {};
|
||||||
|
|
||||||
void init(Opm::EclipseStateConstPtr eclipseState,
|
void init(Opm::EclipseStateConstPtr eclipseState,
|
||||||
const int table_num,
|
const int table_num,
|
||||||
const PhaseUsage phase_usg,
|
const PhaseUsage phase_usg,
|
||||||
|
@ -31,6 +31,8 @@
|
|||||||
|
|
||||||
#include <opm/parser/eclipse/EclipseState/EclipseState.hpp>
|
#include <opm/parser/eclipse/EclipseState/EclipseState.hpp>
|
||||||
|
|
||||||
|
#include <memory>
|
||||||
|
|
||||||
namespace Opm
|
namespace Opm
|
||||||
{
|
{
|
||||||
|
|
||||||
@ -50,43 +52,41 @@ public:
|
|||||||
};
|
};
|
||||||
|
|
||||||
// this is a helper macro which helps to save us from RSI in the following
|
// this is a helper macro which helps to save us from RSI in the following
|
||||||
#define OPM_MULTIPLEXER_SATFUNC_CALL(codeToCall) \
|
#define OPM_MULTIPLEXER_CONST const
|
||||||
|
#define OPM_MULTIPLEXER_NON_CONST
|
||||||
|
#define OPM_MULTIPLEXER_SATFUNC_CALL(codeToCall, CONST) \
|
||||||
switch (satFuncType_) { \
|
switch (satFuncType_) { \
|
||||||
case Gwseg: { \
|
case Gwseg: { \
|
||||||
typedef SatFuncGwseg<TableType> SatFunc; \
|
typedef SatFuncGwseg<TableType> SatFunc; \
|
||||||
if (false) SatFunc dummyForWarning; \
|
__attribute__((unused)) CONST SatFunc& satFunc = \
|
||||||
auto& satFunc = getGwseg(); \
|
*static_cast<SatFunc*>(satFunc_.get()); \
|
||||||
codeToCall; \
|
codeToCall; \
|
||||||
break; \
|
break; \
|
||||||
} \
|
} \
|
||||||
case Stone2: { \
|
case Stone2: { \
|
||||||
typedef SatFuncStone2<TableType> SatFunc; \
|
typedef SatFuncStone2<TableType> SatFunc; \
|
||||||
if (false) SatFunc dummyForWarning; \
|
__attribute__((unused)) CONST SatFunc& satFunc = \
|
||||||
auto& satFunc = getStone2(); \
|
*static_cast<SatFunc*>(satFunc_.get()); \
|
||||||
codeToCall; \
|
codeToCall; \
|
||||||
break; \
|
break; \
|
||||||
} \
|
} \
|
||||||
case Simple: { \
|
case Simple: { \
|
||||||
typedef SatFuncSimple<TableType> SatFunc; \
|
typedef SatFuncSimple<TableType> SatFunc; \
|
||||||
if (false) SatFunc dummyForWarning; \
|
__attribute__((unused)) CONST SatFunc& satFunc = \
|
||||||
auto& satFunc = getSimple(); \
|
*static_cast<SatFunc*>(satFunc_.get()); \
|
||||||
codeToCall; \
|
codeToCall; \
|
||||||
break; \
|
break; \
|
||||||
} \
|
} \
|
||||||
};
|
};
|
||||||
|
|
||||||
SatFuncMultiplexer()
|
SatFuncMultiplexer()
|
||||||
: wasInitialized_(false)
|
{}
|
||||||
|
|
||||||
|
SatFuncMultiplexer(const SatFuncMultiplexer&)
|
||||||
{}
|
{}
|
||||||
|
|
||||||
~SatFuncMultiplexer()
|
~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
|
* \brief Pick the correct saturation function type and initialize the object using
|
||||||
@ -103,7 +103,7 @@ public:
|
|||||||
OPM_MULTIPLEXER_SATFUNC_CALL(satFunc.init(eclState,
|
OPM_MULTIPLEXER_SATFUNC_CALL(satFunc.init(eclState,
|
||||||
tableIdx,
|
tableIdx,
|
||||||
phaseUsage,
|
phaseUsage,
|
||||||
/*samples=*/0));
|
/*samples=*/0), OPM_MULTIPLEXER_NON_CONST);
|
||||||
}
|
}
|
||||||
|
|
||||||
/*!
|
/*!
|
||||||
@ -111,14 +111,27 @@ public:
|
|||||||
*/
|
*/
|
||||||
void setSatFuncType(SatFuncType newSatFuncType)
|
void setSatFuncType(SatFuncType newSatFuncType)
|
||||||
{
|
{
|
||||||
assert(!wasInitialized_);
|
|
||||||
|
|
||||||
// set the type of the saturation function
|
// set the type of the saturation function
|
||||||
satFuncType_ = newSatFuncType;
|
satFuncType_ = newSatFuncType;
|
||||||
|
|
||||||
// call the default constructor for the selected saturation function
|
// call the default constructor for the selected saturation function
|
||||||
OPM_MULTIPLEXER_SATFUNC_CALL(new(&satFunc) SatFunc());
|
switch (satFuncType_) {
|
||||||
wasInitialized_ = true;
|
case Gwseg: {
|
||||||
|
typedef SatFuncGwseg<TableType> SatFunc;
|
||||||
|
satFunc_.reset(new SatFunc);
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
case Stone2: {
|
||||||
|
typedef SatFuncStone2<TableType> SatFunc;
|
||||||
|
satFunc_.reset(new SatFunc);
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
case Simple: {
|
||||||
|
typedef SatFuncSimple<TableType> SatFunc;
|
||||||
|
satFunc_.reset(new SatFunc);
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
/*!
|
/*!
|
||||||
@ -135,27 +148,11 @@ public:
|
|||||||
* parameters).
|
* parameters).
|
||||||
*/
|
*/
|
||||||
const SatFuncBase<TableType>& getSatFuncBase() const
|
const SatFuncBase<TableType>& getSatFuncBase() const
|
||||||
{
|
{ return *satFunc_; }
|
||||||
switch (satFuncType()) {
|
|
||||||
case Gwseg:
|
|
||||||
return getGwseg();
|
|
||||||
case Stone2:
|
|
||||||
return getStone2();
|
|
||||||
case Simple:
|
|
||||||
return getSimple();
|
|
||||||
}
|
|
||||||
OPM_THROW(std::logic_error, "Unhandled saturation function type");
|
|
||||||
}
|
|
||||||
|
|
||||||
SatFuncBase<TableType>& getSatFuncBase()
|
SatFuncBase<TableType>& getSatFuncBase()
|
||||||
{
|
{ return *satFunc_; }
|
||||||
return const_cast<SatFuncBase<TableType>&>(static_cast<const SatFuncMultiplexer*>(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.
|
* \brief Return the raw "Gwseg" saturation function object.
|
||||||
*
|
*
|
||||||
@ -165,13 +162,13 @@ public:
|
|||||||
SatFuncGwseg<TableType>& getGwseg()
|
SatFuncGwseg<TableType>& getGwseg()
|
||||||
{
|
{
|
||||||
assert(satFuncType_ == Gwseg);
|
assert(satFuncType_ == Gwseg);
|
||||||
return *reinterpret_cast<SatFuncGwseg<TableType>*>(satFuncsData_.gwseg);
|
return *static_cast<SatFuncGwseg<TableType>*>(satFunc_.get());
|
||||||
}
|
}
|
||||||
|
|
||||||
const SatFuncGwseg<TableType>& getGwseg() const
|
const SatFuncGwseg<TableType>& getGwseg() const
|
||||||
{
|
{
|
||||||
assert(satFuncType_ == Gwseg);
|
assert(satFuncType_ == Gwseg);
|
||||||
return *reinterpret_cast<const SatFuncGwseg<TableType>*>(satFuncsData_.gwseg);
|
return *static_cast<const SatFuncGwseg<TableType>*>(satFunc_.get());
|
||||||
}
|
}
|
||||||
|
|
||||||
/*!
|
/*!
|
||||||
@ -183,13 +180,13 @@ public:
|
|||||||
SatFuncSimple<TableType>& getSimple()
|
SatFuncSimple<TableType>& getSimple()
|
||||||
{
|
{
|
||||||
assert(satFuncType_ == Simple);
|
assert(satFuncType_ == Simple);
|
||||||
return *reinterpret_cast<SatFuncSimple<TableType>*>(satFuncsData_.simple);
|
return *static_cast<SatFuncSimple<TableType>*>(satFunc_.get());
|
||||||
}
|
}
|
||||||
|
|
||||||
const SatFuncSimple<TableType>& getSimple() const
|
const SatFuncSimple<TableType>& getSimple() const
|
||||||
{
|
{
|
||||||
assert(satFuncType_ == Simple);
|
assert(satFuncType_ == Simple);
|
||||||
return *reinterpret_cast<const SatFuncSimple<TableType>*>(satFuncsData_.simple);
|
return *static_cast<const SatFuncSimple<TableType>*>(satFunc_.get());
|
||||||
}
|
}
|
||||||
|
|
||||||
/*!
|
/*!
|
||||||
@ -201,67 +198,63 @@ public:
|
|||||||
SatFuncStone2<TableType>& getStone2()
|
SatFuncStone2<TableType>& getStone2()
|
||||||
{
|
{
|
||||||
assert(satFuncType_ == Stone2);
|
assert(satFuncType_ == Stone2);
|
||||||
return *reinterpret_cast<SatFuncStone2<TableType>*>(satFuncsData_.stone2);
|
return *static_cast<SatFuncStone2<TableType>*>(satFunc_.get());
|
||||||
}
|
}
|
||||||
|
|
||||||
const SatFuncStone2<TableType>& getStone2() const
|
const SatFuncStone2<TableType>& getStone2() const
|
||||||
{
|
{
|
||||||
assert(satFuncType_ == Stone2);
|
assert(satFuncType_ == Stone2);
|
||||||
return *reinterpret_cast<const SatFuncStone2<TableType>*>(satFuncsData_.stone2);
|
return *static_cast<const SatFuncStone2<TableType>*>(satFunc_.get());
|
||||||
}
|
}
|
||||||
#pragma GCC diagnostic pop
|
|
||||||
|
|
||||||
template <class FluidState>
|
template <class FluidState>
|
||||||
void evalKr(const FluidState& fluidState, double* kr) const
|
void evalKr(const FluidState& fluidState, double* kr) const
|
||||||
{ OPM_MULTIPLEXER_SATFUNC_CALL(satFunc.evalKr(fluidState, kr)); }
|
{ OPM_MULTIPLEXER_SATFUNC_CALL(satFunc.evalKr(fluidState, kr), OPM_MULTIPLEXER_CONST); }
|
||||||
|
|
||||||
template <class FluidState>
|
template <class FluidState>
|
||||||
void evalKrDeriv(const FluidState& fluidState, double* kr, double* dkrds) const
|
void evalKrDeriv(const FluidState& fluidState, double* kr, double* dkrds) const
|
||||||
{ OPM_MULTIPLEXER_SATFUNC_CALL(satFunc.evalKrDeriv(fluidState, kr, dkrds)); }
|
{ OPM_MULTIPLEXER_SATFUNC_CALL(satFunc.evalKrDeriv(fluidState, kr, dkrds), OPM_MULTIPLEXER_CONST); }
|
||||||
|
|
||||||
template <class FluidState>
|
template <class FluidState>
|
||||||
void evalPc(const FluidState& fluidState, double* pc) const
|
void evalPc(const FluidState& fluidState, double* pc) const
|
||||||
{ OPM_MULTIPLEXER_SATFUNC_CALL(satFunc.evalPc(fluidState, pc)); }
|
{ OPM_MULTIPLEXER_SATFUNC_CALL(satFunc.evalPc(fluidState, pc), OPM_MULTIPLEXER_CONST); }
|
||||||
|
|
||||||
template <class FluidState>
|
template <class FluidState>
|
||||||
void evalPcDeriv(const FluidState& fluidState, double* pc, double* dpcds) const
|
void evalPcDeriv(const FluidState& fluidState, double* pc, double* dpcds) const
|
||||||
{ OPM_MULTIPLEXER_SATFUNC_CALL(satFunc.evalPcDeriv(fluidState, pc, dpcds)); }
|
{ OPM_MULTIPLEXER_SATFUNC_CALL(satFunc.evalPcDeriv(fluidState, pc, dpcds), OPM_MULTIPLEXER_CONST); }
|
||||||
|
|
||||||
template <class FluidState>
|
template <class FluidState>
|
||||||
void evalKr(const FluidState& fluidState, double* kr, const EPSTransforms* epst) const
|
void evalKr(const FluidState& fluidState, double* kr, const EPSTransforms* epst) const
|
||||||
{ OPM_MULTIPLEXER_SATFUNC_CALL(satFunc.evalKr(fluidState, kr, epst)); }
|
{ OPM_MULTIPLEXER_SATFUNC_CALL(satFunc.evalKr(fluidState, kr, epst), OPM_MULTIPLEXER_CONST); }
|
||||||
|
|
||||||
template <class FluidState>
|
template <class FluidState>
|
||||||
void evalKr(const FluidState& fluidState, double* kr, const EPSTransforms* epst, const EPSTransforms* epst_hyst, const SatHyst* sat_hyst) const
|
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)); }
|
{ OPM_MULTIPLEXER_SATFUNC_CALL(satFunc.evalKr(fluidState, kr, epst, epst_hyst, sat_hyst), OPM_MULTIPLEXER_CONST); }
|
||||||
|
|
||||||
template <class FluidState>
|
template <class FluidState>
|
||||||
void evalKrDeriv(const FluidState& fluidState, double* kr, double* dkrds, const EPSTransforms* epst) const
|
void evalKrDeriv(const FluidState& fluidState, double* kr, double* dkrds, const EPSTransforms* epst) const
|
||||||
{ OPM_MULTIPLEXER_SATFUNC_CALL(satFunc.evalKrDeriv(fluidState, kr, dkrds, epst)); }
|
{ OPM_MULTIPLEXER_SATFUNC_CALL(satFunc.evalKrDeriv(fluidState, kr, dkrds, epst), OPM_MULTIPLEXER_CONST); }
|
||||||
|
|
||||||
template <class FluidState>
|
template <class FluidState>
|
||||||
void evalKrDeriv(const FluidState& fluidState, double* kr, double* dkrds, const EPSTransforms* epst, const EPSTransforms* epst_hyst, const SatHyst* sat_hyst) const
|
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)); }
|
{ OPM_MULTIPLEXER_SATFUNC_CALL(satFunc.evalKrDeriv(fluidState, kr, dkrds, epst, epst_hyst, sat_hyst), OPM_MULTIPLEXER_CONST); }
|
||||||
|
|
||||||
template <class FluidState>
|
template <class FluidState>
|
||||||
void evalPc(const FluidState& fluidState, double* pc, const EPSTransforms* epst) const
|
void evalPc(const FluidState& fluidState, double* pc, const EPSTransforms* epst) const
|
||||||
{ OPM_MULTIPLEXER_SATFUNC_CALL(satFunc.evalPc(fluidState, pc, epst)); }
|
{ OPM_MULTIPLEXER_SATFUNC_CALL(satFunc.evalPc(fluidState, pc, epst), OPM_MULTIPLEXER_CONST); }
|
||||||
|
|
||||||
template <class FluidState>
|
template <class FluidState>
|
||||||
void evalPcDeriv(const FluidState& fluidState, double* pc, double* dpcds, const EPSTransforms* epst) const
|
void evalPcDeriv(const FluidState& fluidState, double* pc, double* dpcds, const EPSTransforms* epst) const
|
||||||
{ OPM_MULTIPLEXER_SATFUNC_CALL(satFunc.evalPcDeriv(fluidState, pc, dpcds, epst)); }
|
{ OPM_MULTIPLEXER_SATFUNC_CALL(satFunc.evalPcDeriv(fluidState, pc, dpcds, epst), OPM_MULTIPLEXER_CONST); }
|
||||||
|
|
||||||
// undefine the helper macro here because we don't need it anymore
|
// undefine the helper macro here because we don't need it anymore
|
||||||
#undef OPM_MULTIPLEXER_SATFUNC_CALL
|
#undef OPM_MULTIPLEXER_SATFUNC_CALL
|
||||||
|
#undef OPM_MULTIPLEXER_NON_CONST
|
||||||
|
#undef OPM_MULTIPLEXER_CONST
|
||||||
|
|
||||||
private:
|
private:
|
||||||
bool wasInitialized_;
|
|
||||||
SatFuncType satFuncType_;
|
SatFuncType satFuncType_;
|
||||||
union {
|
std::unique_ptr<SatFuncBase<TableType> > satFunc_;
|
||||||
char gwseg[sizeof(SatFuncGwseg<TableType>)];
|
|
||||||
char simple[sizeof(SatFuncSimple<TableType>)];
|
|
||||||
char stone2[sizeof(SatFuncStone2<TableType>)];
|
|
||||||
} satFuncsData_ __attribute__((aligned(sizeof(double))));
|
|
||||||
};
|
};
|
||||||
} // namespace Opm
|
} // namespace Opm
|
||||||
|
|
||||||
|
Loading…
Reference in New Issue
Block a user