Add Restart File Output Support for Constant Flux Aquifers
We support constant flux aquifers (AQUFLUX keyword) entered both in the SOLUTION and in the SCHEDULE sections. The primary structural change is that we have to support analytic aquifers being introduced dynamically, whence the connection information (xCAQ) must be captured without knowing the full set of analytic aquifers. We therefore allocate those output arrays purely from the maximum sizes entered in the RUNSPEC section whereas we defer determining the maximum aquifer ID to the point of capturing the dynamic values. The xAAQ values for constant flux aquifers amount to a new aquifer type integer value (=2) in IAAQ[11] and the flux value in SAAQ[0].
This commit is contained in:
parent
53a7c2343a
commit
0adcc7dd07
@ -35,12 +35,13 @@ namespace Opm::RestartIO {
|
||||
} // Opm::RestartIO
|
||||
|
||||
namespace Opm {
|
||||
struct SingleAquiferFlux {
|
||||
struct SingleAquiferFlux
|
||||
{
|
||||
SingleAquiferFlux() = default;
|
||||
explicit SingleAquiferFlux(const DeckRecord& record);
|
||||
|
||||
// using id to create an inactive dummy aquifer
|
||||
explicit SingleAquiferFlux(int id);
|
||||
SingleAquiferFlux() = default;
|
||||
SingleAquiferFlux(int id, double flux, double sal, bool active_, double temp, double pres);
|
||||
|
||||
int id {0};
|
||||
@ -52,7 +53,7 @@ namespace Opm {
|
||||
|
||||
bool operator==(const SingleAquiferFlux& other) const;
|
||||
|
||||
template<class Serializer>
|
||||
template <class Serializer>
|
||||
void serializeOp(Serializer& serializer)
|
||||
{
|
||||
serializer(this->id);
|
||||
@ -66,12 +67,16 @@ namespace Opm {
|
||||
static SingleAquiferFlux serializationTestObject();
|
||||
};
|
||||
|
||||
class AquiferFlux {
|
||||
class AquiferFlux
|
||||
{
|
||||
public:
|
||||
using AquFluxs = std::unordered_map<int, SingleAquiferFlux>;
|
||||
|
||||
explicit AquiferFlux(const std::vector<const DeckKeyword*>& keywords);
|
||||
AquiferFlux() = default;
|
||||
explicit AquiferFlux(const std::vector<const DeckKeyword*>& keywords);
|
||||
|
||||
// Primarily for unit testing purposes.
|
||||
explicit AquiferFlux(const std::vector<SingleAquiferFlux>& aquifers);
|
||||
|
||||
void appendAqufluxSchedule(const std::unordered_set<int>& ids);
|
||||
|
||||
@ -86,15 +91,16 @@ namespace Opm {
|
||||
|
||||
void loadFromRestart(const RestartIO::RstAquifer& rst);
|
||||
|
||||
template<class Serializer>
|
||||
void serializeOp(Serializer& serializer) {
|
||||
template <class Serializer>
|
||||
void serializeOp(Serializer& serializer)
|
||||
{
|
||||
serializer(this->m_aquifers);
|
||||
}
|
||||
|
||||
static AquiferFlux serializationTestObject();
|
||||
|
||||
private:
|
||||
AquFluxs m_aquifers;
|
||||
AquFluxs m_aquifers{};
|
||||
};
|
||||
} // end of namespace Opm
|
||||
|
||||
|
@ -349,6 +349,11 @@ namespace Opm {
|
||||
|
||||
bool has_gpmaint() const;
|
||||
|
||||
bool hasAnalyticalAquifers() const
|
||||
{
|
||||
return ! this->aqufluxs.empty();
|
||||
}
|
||||
|
||||
/*********************************************************************/
|
||||
|
||||
ptr_member<GConSale> gconsale;
|
||||
|
@ -30,6 +30,7 @@
|
||||
namespace Opm {
|
||||
class AquiferConfig;
|
||||
class EclipseGrid;
|
||||
class ScheduleState;
|
||||
class SummaryState;
|
||||
class UnitSystem;
|
||||
} // Opm
|
||||
@ -60,11 +61,19 @@ namespace Opm { namespace RestartIO { namespace Helpers {
|
||||
/// Linearise dynamic information pertinent to analytic aquifers
|
||||
/// into internal arrays.
|
||||
///
|
||||
/// \param[in] aqDims Aquifer dimensions including number of active
|
||||
/// aquifers, maximum aquifer IDs, and number of data items per
|
||||
/// aquifer (or connection) in the various output arrays.
|
||||
///
|
||||
/// \param[in] aqConfig Aquifer configuration object. Keeps track
|
||||
/// of aquifer types (Carter-Tracy, Fetkovich, constant flux &c)
|
||||
/// and provides read-only access to the individual aquifer
|
||||
/// objects.
|
||||
///
|
||||
/// \param[in] sched Schedule state at particular report step.
|
||||
/// Keeps track of dynamically defined analytic aquifers, e.g.,
|
||||
/// the constant flux aquifers entered in the SCHEDULE section.
|
||||
///
|
||||
/// \param[in] aquData Dynamic aquifer data, including time
|
||||
/// constants, water mass densities, water viscosities, and
|
||||
/// initial aquifer pressures.
|
||||
@ -76,10 +85,12 @@ namespace Opm { namespace RestartIO { namespace Helpers {
|
||||
///
|
||||
/// \param[in] usys Unit system. Needed to convert quantities from
|
||||
/// internal to output units.
|
||||
void captureDynamicdAquiferData(const AquiferConfig& aqConfig,
|
||||
const data::Aquifers& aquData,
|
||||
const SummaryState& summaryState,
|
||||
const UnitSystem& usys);
|
||||
void captureDynamicAquiferData(const InteHEAD::AquiferDims& aqDims,
|
||||
const AquiferConfig& aqConfig,
|
||||
const ScheduleState& sched,
|
||||
const data::Aquifers& aquData,
|
||||
const SummaryState& summaryState,
|
||||
const UnitSystem& usys);
|
||||
|
||||
/// Retrieve the maximum active aquifer ID over all analytic
|
||||
/// aquifers.
|
||||
@ -187,11 +198,18 @@ namespace Opm { namespace RestartIO { namespace Helpers {
|
||||
/// connections. Separate array for each aquifer.
|
||||
std::vector<WindowedArray<double>> doubleprecAnalyticAquiferConn_;
|
||||
|
||||
void allocateDynamicBackingStorage(const InteHEAD::AquiferDims& aqDims);
|
||||
|
||||
void handleCarterTracy(const AquiferConfig& aqConfig,
|
||||
const data::Aquifers& aquData,
|
||||
const SummaryState& summaryState,
|
||||
const UnitSystem& usys);
|
||||
|
||||
void handleConstantFlux(const AquiferConfig& aqConfig,
|
||||
const ScheduleState& sched,
|
||||
const SummaryState& summaryState,
|
||||
const UnitSystem& usys);
|
||||
|
||||
void handleFetkovich(const AquiferConfig& aqConfig,
|
||||
const data::Aquifers& aquData,
|
||||
const SummaryState& summaryState,
|
||||
|
@ -30,8 +30,10 @@ namespace Opm {
|
||||
|
||||
class EclipseGrid;
|
||||
class EclipseState;
|
||||
class UnitSystem;
|
||||
class Phases;
|
||||
class ScheduleState;
|
||||
class UnitSystem;
|
||||
|
||||
}
|
||||
|
||||
namespace Opm { namespace RestartIO {
|
||||
@ -164,7 +166,7 @@ namespace Opm { namespace RestartIO {
|
||||
// Maximum aquifer ID across all of the model's analytic aquifers.
|
||||
int maxAquiferID {0};
|
||||
|
||||
// Number of numeric aquifer records (lines of AQUNUM data)
|
||||
// Number of numeric aquifer records (lines of AQUNUM data, AQUDIMS(1))
|
||||
int numNumericAquiferRecords {0};
|
||||
|
||||
// Number of data elements per aquifer in IAAQ array.
|
||||
@ -250,6 +252,10 @@ namespace Opm { namespace RestartIO {
|
||||
|
||||
InteHEAD::AquiferDims
|
||||
inferAquiferDimensions(const EclipseState& es);
|
||||
|
||||
InteHEAD::AquiferDims
|
||||
inferAquiferDimensions(const EclipseState& es,
|
||||
const ScheduleState& sched);
|
||||
}} // Opm::RestartIO
|
||||
|
||||
#endif // OPM_INTEHEAD_HEADER_INCLUDED
|
||||
|
@ -31,7 +31,7 @@ namespace Opm { namespace RestartIO { namespace Helpers { namespace VectorItems
|
||||
WatPropTable = 1, // PVT number (ACUCT(10) or AQUFETP(7))
|
||||
|
||||
CTInfluenceFunction = 9, // AQUCT(11)
|
||||
TypeRelated1 = 10, // =1 for CT, =0 for FETP
|
||||
TypeRelated1 = 10, // =0 for FETP, =1 for CT, =2 for FLUX
|
||||
|
||||
Unknown_1 = 11, // Unknown item. =1 in all cases seen thus far.
|
||||
};
|
||||
@ -40,6 +40,7 @@ namespace Opm { namespace RestartIO { namespace Helpers { namespace VectorItems
|
||||
enum ModelType : int {
|
||||
Fetkovich = 0,
|
||||
CarterTracy = 1,
|
||||
ConstantFlux = 2,
|
||||
};
|
||||
} // Value
|
||||
} // IAnalyticAquifer
|
||||
@ -96,6 +97,8 @@ namespace Opm { namespace RestartIO { namespace Helpers { namespace VectorItems
|
||||
enum index : std::vector<float>::size_type {
|
||||
Compressibility = 0, // Total aquifer compressibility (AQUCT(6), AQUFETP(5))
|
||||
|
||||
ConstFluxValue = 0, // Constant flux aquifer's flux value (AQUFLUX(2))
|
||||
|
||||
FetInitVol = 1, // Initial aquifer volume (AQUFETP(4))
|
||||
FetProdIndex = 2, // Aquifer productivity index (AQUFETP(6))
|
||||
FetTimeConstant = 3, // Fetkovich Aquifer time constant (Compressibility * InitVol / ProdIndex)
|
||||
|
@ -88,6 +88,13 @@ namespace Opm {
|
||||
}
|
||||
}
|
||||
|
||||
AquiferFlux::AquiferFlux(const std::vector<SingleAquiferFlux>& aquifers)
|
||||
{
|
||||
for (const auto& aquifer : aquifers) {
|
||||
this->m_aquifers.emplace(aquifer.id, aquifer);
|
||||
}
|
||||
}
|
||||
|
||||
bool AquiferFlux::operator==(const AquiferFlux& other) const {
|
||||
return this->m_aquifers == other.m_aquifers;
|
||||
}
|
||||
@ -118,4 +125,4 @@ namespace Opm {
|
||||
result.m_aquifers.insert({single_aquifer.id, single_aquifer});
|
||||
return result;
|
||||
}
|
||||
} // end of namespace Opm
|
||||
} // end of namespace Opm
|
||||
|
@ -28,10 +28,12 @@
|
||||
#include <opm/input/eclipse/EclipseState/Aquifer/Aquancon.hpp>
|
||||
#include <opm/input/eclipse/EclipseState/Aquifer/AquiferCT.hpp>
|
||||
#include <opm/input/eclipse/EclipseState/Aquifer/AquiferConfig.hpp>
|
||||
#include <opm/input/eclipse/EclipseState/Aquifer/AquiferFlux.hpp>
|
||||
#include <opm/input/eclipse/EclipseState/Aquifer/Aquifetp.hpp>
|
||||
#include <opm/input/eclipse/EclipseState/Grid/EclipseGrid.hpp>
|
||||
#include <opm/input/eclipse/EclipseState/Tables/FlatTable.hpp>
|
||||
|
||||
#include <opm/input/eclipse/Schedule/ScheduleState.hpp>
|
||||
#include <opm/input/eclipse/Schedule/SummaryState.hpp>
|
||||
|
||||
#include <opm/input/eclipse/Units/UnitSystem.hpp>
|
||||
@ -59,6 +61,11 @@ namespace {
|
||||
return summaryState.get(key, 0.0);
|
||||
}
|
||||
|
||||
std::size_t maxNumberOfAquifers(const Opm::RestartIO::InteHEAD::AquiferDims& aqDims)
|
||||
{
|
||||
return std::max(aqDims.maxNumAquifers, aqDims.numNumericAquiferRecords);
|
||||
}
|
||||
|
||||
template <typename AquiferCallBack>
|
||||
void CarterTracyAquiferLoop(const Opm::AquiferConfig& aqConfig,
|
||||
AquiferCallBack&& aquiferOp)
|
||||
@ -68,6 +75,27 @@ namespace {
|
||||
}
|
||||
}
|
||||
|
||||
template <typename AquiferCallBack>
|
||||
void ConstantFluxAquiferLoop(const Opm::AquiferConfig& aqConfig,
|
||||
const Opm::ScheduleState& sched,
|
||||
AquiferCallBack&& aquiferOp)
|
||||
{
|
||||
// Note: Loop 'aqConfig' before 'sched'. That way, dynamic settings
|
||||
// in 'sched' will override the static settings in 'aqConfig'.
|
||||
|
||||
for (const auto& aquifer : aqConfig.aquflux()) {
|
||||
if (aquifer.second.active) {
|
||||
aquiferOp(aquifer.second);
|
||||
}
|
||||
}
|
||||
|
||||
for (const auto& aquifer : sched.aqufluxs) {
|
||||
if (aquifer.second.active) {
|
||||
aquiferOp(aquifer.second);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
template <typename AquiferCallBack>
|
||||
void FetkovichAquiferLoop(const Opm::AquiferConfig& aqConfig,
|
||||
AquiferCallBack&& aquiferOp)
|
||||
@ -100,10 +128,6 @@ namespace {
|
||||
ConnectionCallBack&& connectionOp)
|
||||
{
|
||||
for (const auto& [aquiferID, connections] : aqConfig.connections().data()) {
|
||||
if ( !aqConfig.hasAnalyticalAquifer(int(aquiferID)) ) {
|
||||
continue;
|
||||
}
|
||||
|
||||
const auto tot_influx =
|
||||
std::accumulate(connections.begin(), connections.end(), 0.0,
|
||||
[](const double t, const Opm::Aquancon::AquancCell& connection) -> double
|
||||
@ -163,6 +187,19 @@ namespace {
|
||||
}
|
||||
} // CarterTracy
|
||||
|
||||
namespace ConstantFlux
|
||||
{
|
||||
template <typename IAaqArray>
|
||||
void staticContrib(const int numActiveConn, IAaqArray& iaaq)
|
||||
{
|
||||
namespace IAAQ = VI::IAnalyticAquifer;
|
||||
|
||||
Common::staticContrib(numActiveConn, iaaq);
|
||||
|
||||
iaaq[IAAQ::index::TypeRelated1] = IAAQ::Value::ModelType::ConstantFlux;
|
||||
}
|
||||
} // ConstantFlux
|
||||
|
||||
namespace Fetkovich
|
||||
{
|
||||
template <typename IAaqArray>
|
||||
@ -218,7 +255,7 @@ namespace {
|
||||
{
|
||||
using WA = Opm::RestartIO::Helpers::WindowedArray<int>;
|
||||
|
||||
return std::vector<WA>(aqDims.maxAquiferID, WA {
|
||||
return std::vector<WA>(maxNumberOfAquifers(aqDims), WA {
|
||||
WA::NumWindows{ static_cast<WA::Idx>(aqDims.maxNumActiveAquiferConn) },
|
||||
WA::WindowSize{ static_cast<WA::Idx>(aqDims.numIntConnElem) }
|
||||
});
|
||||
@ -317,6 +354,23 @@ namespace {
|
||||
}
|
||||
} // CarterTracy
|
||||
|
||||
namespace ConstantFlux {
|
||||
template <typename SAaqArray>
|
||||
void staticContrib(const Opm::SingleAquiferFlux& aquifer,
|
||||
const Opm::UnitSystem& usys,
|
||||
SAaqArray& saaq)
|
||||
{
|
||||
using M = Opm::UnitSystem::measure;
|
||||
using Ix = VI::SAnalyticAquifer::index;
|
||||
|
||||
auto q = usys.from_si(M::liquid_surface_rate, aquifer.flux);
|
||||
|
||||
// Unit hack: *to_si()* here since we don't have an area unit.
|
||||
saaq[Ix::ConstFluxValue] =
|
||||
usys.to_si(M::length, usys.to_si(M::length, q));
|
||||
}
|
||||
} // ConstantFlux
|
||||
|
||||
namespace Fetkovich {
|
||||
template <typename SAaqArray>
|
||||
void staticContrib(const Opm::Aquifetp::AQUFETP_data& aquifer,
|
||||
@ -361,7 +415,7 @@ namespace {
|
||||
{
|
||||
using WA = Opm::RestartIO::Helpers::WindowedArray<float>;
|
||||
|
||||
return std::vector<WA>(aqDims.maxAquiferID, WA {
|
||||
return std::vector<WA>(maxNumberOfAquifers(aqDims), WA {
|
||||
WA::NumWindows{ static_cast<WA::Idx>(aqDims.maxNumActiveAquiferConn) },
|
||||
WA::WindowSize{ static_cast<WA::Idx>(aqDims.numRealConnElem) }
|
||||
});
|
||||
@ -452,6 +506,18 @@ namespace {
|
||||
}
|
||||
} // CarterTracy
|
||||
|
||||
namespace ConstantFlux {
|
||||
template <typename SummaryVariable, typename XAaqArray>
|
||||
void dynamicContrib(SummaryVariable&& summaryVariable,
|
||||
const double tot_influx,
|
||||
const Opm::UnitSystem& usys,
|
||||
XAaqArray& xaaq)
|
||||
{
|
||||
Common::dynamicContrib(std::forward<SummaryVariable>(summaryVariable),
|
||||
tot_influx, usys, xaaq);
|
||||
}
|
||||
} // ConstantFlux
|
||||
|
||||
namespace Fetkovich {
|
||||
template <typename SummaryVariable, typename XAaqArray>
|
||||
void dynamicContrib(SummaryVariable&& summaryVariable,
|
||||
@ -525,7 +591,7 @@ namespace {
|
||||
{
|
||||
using WA = Opm::RestartIO::Helpers::WindowedArray<double>;
|
||||
|
||||
return std::vector<WA>(aqDims.maxAquiferID, WA {
|
||||
return std::vector<WA>(maxNumberOfAquifers(aqDims), WA {
|
||||
WA::NumWindows{ static_cast<WA::Idx>(aqDims.maxNumActiveAquiferConn) },
|
||||
WA::WindowSize{ static_cast<WA::Idx>(aqDims.numDoubConnElem) }
|
||||
});
|
||||
@ -538,8 +604,8 @@ AggregateAquiferData(const InteHEAD::AquiferDims& aqDims,
|
||||
const AquiferConfig& aqConfig,
|
||||
const EclipseGrid& grid)
|
||||
: maxActiveAnalyticAquiferID_ { aqDims.maxAquiferID }
|
||||
, numActiveConn_ ( aqDims.maxAquiferID, 0 )
|
||||
, totalInflux_ ( aqDims.maxAquiferID, 0.0 )
|
||||
, numActiveConn_ ( maxNumberOfAquifers(aqDims), 0 )
|
||||
, totalInflux_ ( maxNumberOfAquifers(aqDims), 0.0 )
|
||||
, integerAnalyticAq_ { IntegerAnalyticAquifer:: allocate(aqDims) }
|
||||
, singleprecAnalyticAq_ { SinglePrecAnalyticAquifer:: allocate(aqDims) }
|
||||
, doubleprecAnalyticAq_ { DoublePrecAnalyticAquifer:: allocate(aqDims) }
|
||||
@ -549,7 +615,7 @@ AggregateAquiferData(const InteHEAD::AquiferDims& aqDims,
|
||||
, singleprecAnalyticAquiferConn_{ SinglePrecAnalyticAquiferConn::allocate(aqDims) }
|
||||
, doubleprecAnalyticAquiferConn_{ DoublePrecAnalyticAquiferConn::allocate(aqDims) }
|
||||
{
|
||||
if (! aqConfig.hasAnalyticalAquifer()) {
|
||||
if (! aqConfig.connections().active()) {
|
||||
return;
|
||||
}
|
||||
|
||||
@ -579,20 +645,35 @@ AggregateAquiferData(const InteHEAD::AquiferDims& aqDims,
|
||||
|
||||
void
|
||||
Opm::RestartIO::Helpers::AggregateAquiferData::
|
||||
captureDynamicdAquiferData(const AquiferConfig& aqConfig,
|
||||
const data::Aquifers& aquData,
|
||||
const SummaryState& summaryState,
|
||||
const UnitSystem& usys)
|
||||
captureDynamicAquiferData(const InteHEAD::AquiferDims& aqDims,
|
||||
const AquiferConfig& aqConfig,
|
||||
const ScheduleState& sched,
|
||||
const data::Aquifers& aquData,
|
||||
const SummaryState& summaryState,
|
||||
const UnitSystem& usys)
|
||||
{
|
||||
if (! (aqConfig.active() || sched.hasAnalyticalAquifers())) {
|
||||
return;
|
||||
}
|
||||
|
||||
this->allocateDynamicBackingStorage(aqDims);
|
||||
|
||||
this->maxActiveAnalyticAquiferID_ = aqDims.maxAquiferID;
|
||||
|
||||
this->handleFetkovich(aqConfig, aquData, summaryState, usys);
|
||||
this->handleCarterTracy(aqConfig, aquData, summaryState, usys);
|
||||
this->handleConstantFlux(aqConfig, sched, summaryState, usys);
|
||||
this->handleNumeric(aqConfig, aquData, summaryState, usys);
|
||||
}
|
||||
|
||||
void
|
||||
Opm::RestartIO::Helpers::AggregateAquiferData::
|
||||
allocateDynamicBackingStorage(const InteHEAD::AquiferDims& aqDims)
|
||||
{
|
||||
this->integerAnalyticAq_ = IntegerAnalyticAquifer:: allocate(aqDims);
|
||||
this->singleprecAnalyticAq_ = SinglePrecAnalyticAquifer::allocate(aqDims);
|
||||
this->doubleprecAnalyticAq_ = DoublePrecAnalyticAquifer::allocate(aqDims);
|
||||
}
|
||||
|
||||
void
|
||||
Opm::RestartIO::Helpers::AggregateAquiferData::
|
||||
@ -633,6 +714,36 @@ handleCarterTracy(const AquiferConfig& aqConfig,
|
||||
});
|
||||
}
|
||||
|
||||
void
|
||||
Opm::RestartIO::Helpers::AggregateAquiferData::
|
||||
handleConstantFlux(const AquiferConfig& aqConfig,
|
||||
const ScheduleState& sched,
|
||||
const SummaryState& summaryState,
|
||||
const UnitSystem& usys)
|
||||
{
|
||||
ConstantFluxAquiferLoop(aqConfig, sched, [this, &usys, &summaryState]
|
||||
(const SingleAquiferFlux& aquifer)
|
||||
{
|
||||
const auto aquIndex = static_cast<WindowedArray<int>::Idx>(aquifer.id - 1);
|
||||
|
||||
auto iaaq = this->integerAnalyticAq_[aquIndex];
|
||||
const auto nActiveConn = this->numActiveConn_[aquIndex];
|
||||
IntegerAnalyticAquifer::ConstantFlux::staticContrib(nActiveConn, iaaq);
|
||||
|
||||
auto saaq = this->singleprecAnalyticAq_[aquIndex];
|
||||
SinglePrecAnalyticAquifer::ConstantFlux::staticContrib(aquifer, usys, saaq);
|
||||
|
||||
auto xaaq = this->doubleprecAnalyticAq_[aquIndex];
|
||||
const auto tot_influx = this->totalInflux_[aquIndex];
|
||||
auto sumVar = [&summaryState, &aquifer](const std::string& vector)
|
||||
{
|
||||
return getSummaryVariable(summaryState, vector, aquifer.id);
|
||||
};
|
||||
DoublePrecAnalyticAquifer::ConstantFlux::
|
||||
dynamicContrib(sumVar, tot_influx, usys, xaaq);
|
||||
});
|
||||
}
|
||||
|
||||
void
|
||||
Opm::RestartIO::Helpers::AggregateAquiferData::
|
||||
handleFetkovich(const AquiferConfig& aqConfig,
|
||||
|
@ -601,7 +601,7 @@ createInteHead(const EclipseState& es,
|
||||
.params_NWELZ (155 + num_water_tracer, 122 + 2*num_water_tracer, 130 + nxwelz_tracer_shift, 3) // n{isxz}welz: number of data elements per well in {ISXZ}WELL
|
||||
.params_NCON (25, 41, 58 + 5*num_water_tracer) // n{isx}conz: number of data elements per completion in ICON
|
||||
.params_GRPZ (getNGRPZ(nwgmax, ngmax, num_water_tracer, rspec))
|
||||
.aquiferDimensions (inferAquiferDimensions(es))
|
||||
.aquiferDimensions (inferAquiferDimensions(es, sched[lookup_step]))
|
||||
.stepParam (num_solver_steps, report_step)
|
||||
.tuningParam (getTuningPars(sched[lookup_step].tuning()))
|
||||
.liftOptParam (getLiftOptPar(sched, report_step, lookup_step))
|
||||
|
@ -149,14 +149,12 @@ EclipseIO::Impl::Impl( const EclipseState& eclipseState,
|
||||
, summary( eclipseState, summaryConfig, grid , schedule, base_name, writeEsmry )
|
||||
, output_enabled( eclipseState.getIOConfig().getOutputEnabled() )
|
||||
{
|
||||
const auto& aqConfig = this->es.aquifer();
|
||||
|
||||
if (aqConfig.hasAnalyticalAquifer() || aqConfig.hasNumericalAquifer()) {
|
||||
this->aquiferData = RestartIO::Helpers::AggregateAquiferData {
|
||||
RestartIO::inferAquiferDimensions(this->es),
|
||||
aqConfig,
|
||||
this->grid
|
||||
};
|
||||
if (const auto& aqConfig = this->es.aquifer();
|
||||
aqConfig.connections().active() || aqConfig.hasNumericalAquifer())
|
||||
{
|
||||
this->aquiferData
|
||||
.emplace(RestartIO::inferAquiferDimensions(this->es),
|
||||
aqConfig, this->grid);
|
||||
}
|
||||
}
|
||||
|
||||
|
@ -22,19 +22,24 @@
|
||||
|
||||
#include <opm/output/eclipse/VectorItems/intehead.hpp>
|
||||
|
||||
#include <opm/input/eclipse/EclipseState/Aquifer/AquiferConfig.hpp>
|
||||
#include <opm/input/eclipse/EclipseState/Aquifer/Aquancon.hpp>
|
||||
#include <opm/input/eclipse/EclipseState/Grid/EclipseGrid.hpp>
|
||||
#include <opm/input/eclipse/EclipseState/Aquifer/AquiferConfig.hpp>
|
||||
#include <opm/input/eclipse/EclipseState/Aquifer/AquiferFlux.hpp>
|
||||
#include <opm/input/eclipse/EclipseState/EclipseState.hpp>
|
||||
#include <opm/input/eclipse/Units/UnitSystem.hpp>
|
||||
#include <opm/input/eclipse/EclipseState/Grid/EclipseGrid.hpp>
|
||||
#include <opm/input/eclipse/EclipseState/Runspec.hpp>
|
||||
|
||||
#include <opm/input/eclipse/Schedule/ScheduleState.hpp>
|
||||
|
||||
#include <opm/input/eclipse/Units/UnitSystem.hpp>
|
||||
|
||||
#include <opm/common/utility/TimeService.hpp>
|
||||
|
||||
#include <algorithm>
|
||||
#include <chrono>
|
||||
#include <cmath>
|
||||
#include <ctime>
|
||||
#include <initializer_list>
|
||||
#include <numeric>
|
||||
#include <ratio>
|
||||
#include <utility>
|
||||
@ -881,11 +886,66 @@ Opm::RestartIO::getSimulationTimePoint(const std::time_t start,
|
||||
}
|
||||
|
||||
namespace {
|
||||
template <typename T, class A>
|
||||
int numUnique(std::vector<T, A> elems)
|
||||
{
|
||||
if (elems.empty()) { return 0; }
|
||||
if (elems.size() == 1) { return 1; }
|
||||
|
||||
std::sort(elems.begin(), elems.end());
|
||||
auto end = std::unique(elems.begin(), elems.end());
|
||||
|
||||
return std::distance(elems.begin(), end);
|
||||
}
|
||||
|
||||
int numberOfCarterTracyAquifers(const Opm::AquiferConfig& cfg)
|
||||
{
|
||||
return cfg.ct().size();
|
||||
}
|
||||
|
||||
int numberOfFetkovichAquifers(const Opm::AquiferConfig& cfg)
|
||||
{
|
||||
return cfg.fetp().size();
|
||||
}
|
||||
|
||||
int numberOfConstantFluxAquifers(const Opm::AquiferConfig& cfg)
|
||||
{
|
||||
return cfg.aquflux().size();
|
||||
}
|
||||
|
||||
int numberOfConstantFluxAquifers(const Opm::AquiferConfig& cfg,
|
||||
const Opm::ScheduleState& sched)
|
||||
{
|
||||
auto aquiferIDs = std::vector<int>{};
|
||||
aquiferIDs.reserve(numberOfConstantFluxAquifers(cfg)
|
||||
+ sched.aqufluxs.size());
|
||||
|
||||
for (const auto& [id, aq] : cfg.aquflux()) {
|
||||
if (aq.active) {
|
||||
aquiferIDs.push_back(id);
|
||||
}
|
||||
}
|
||||
|
||||
for (const auto& aq : sched.aqufluxs) {
|
||||
aquiferIDs.push_back(aq.first);
|
||||
}
|
||||
|
||||
return numUnique(std::move(aquiferIDs));
|
||||
}
|
||||
|
||||
int getNumberOfAnalyticAquifers(const Opm::AquiferConfig& cfg)
|
||||
{
|
||||
const auto numAnalyticAquifers = cfg.ct().size() + cfg.fetp().size() + cfg.aquflux().size();
|
||||
return numberOfCarterTracyAquifers(cfg)
|
||||
+ numberOfFetkovichAquifers(cfg)
|
||||
+ numberOfConstantFluxAquifers(cfg);
|
||||
}
|
||||
|
||||
return static_cast<int>(numAnalyticAquifers);
|
||||
int getNumberOfAnalyticAquifers(const Opm::AquiferConfig& cfg,
|
||||
const Opm::ScheduleState& sched)
|
||||
{
|
||||
return numberOfCarterTracyAquifers(cfg)
|
||||
+ numberOfFetkovichAquifers(cfg)
|
||||
+ numberOfConstantFluxAquifers(cfg, sched);
|
||||
}
|
||||
|
||||
int getMaximumNumberOfAnalyticAquifers(const Opm::Runspec& runspec)
|
||||
@ -910,14 +970,47 @@ namespace {
|
||||
return maxNumActiveConn;
|
||||
}
|
||||
|
||||
template <typename AquiferCollection>
|
||||
int maxAquID(const AquiferCollection& aquiferCollection)
|
||||
{
|
||||
return std::accumulate(aquiferCollection.begin(), aquiferCollection.end(), 0,
|
||||
[](const int maxID, const auto& aquiferData)
|
||||
{
|
||||
return std::max(maxID, aquiferData.aquiferID);
|
||||
});
|
||||
}
|
||||
|
||||
template <typename AquFluxIter>
|
||||
int maxAquID(AquFluxIter begin, AquFluxIter end)
|
||||
{
|
||||
auto maxIDPos =
|
||||
std::max_element(begin, end,
|
||||
[](const auto& aq1, const auto& aq2)
|
||||
{
|
||||
return aq1.first < aq2.first;
|
||||
});
|
||||
|
||||
return (maxIDPos == end) ? 0 : maxIDPos->first;
|
||||
}
|
||||
|
||||
int getMaximumAnalyticAquiferID(const Opm::AquiferConfig& cfg)
|
||||
{
|
||||
const auto& aquifer_ids = analyticAquiferIDs(cfg);
|
||||
if (!aquifer_ids.empty()) {
|
||||
return *max_element(std::begin(aquifer_ids), std::end(aquifer_ids));
|
||||
} else {
|
||||
return 0;
|
||||
}
|
||||
return std::max({
|
||||
maxAquID(cfg.ct()),
|
||||
maxAquID(cfg.fetp()),
|
||||
maxAquID(cfg.aquflux().begin(), cfg.aquflux().end())
|
||||
});
|
||||
}
|
||||
|
||||
int getMaximumAnalyticAquiferID(const int maxAquiferID,
|
||||
const Opm::ScheduleState& sched)
|
||||
{
|
||||
return std::max(maxAquiferID, maxAquID(sched.aqufluxs.begin(), sched.aqufluxs.end()));
|
||||
}
|
||||
|
||||
bool hasAnalyticalAquifer(const Opm::ScheduleState& sched)
|
||||
{
|
||||
return ! sched.aqufluxs.empty();
|
||||
}
|
||||
}
|
||||
|
||||
@ -946,3 +1039,19 @@ Opm::RestartIO::inferAquiferDimensions(const EclipseState& es)
|
||||
|
||||
return dim;
|
||||
}
|
||||
|
||||
Opm::RestartIO::InteHEAD::AquiferDims
|
||||
Opm::RestartIO::inferAquiferDimensions(const EclipseState& es,
|
||||
const ScheduleState& sched)
|
||||
{
|
||||
auto dim = inferAquiferDimensions(es);
|
||||
|
||||
if (const auto& cfg = es.aquifer();
|
||||
cfg.hasAnalyticalAquifer() || hasAnalyticalAquifer(sched))
|
||||
{
|
||||
dim.numAquifers = getNumberOfAnalyticAquifers(cfg, sched);
|
||||
dim.maxAquiferID = getMaximumAnalyticAquiferID(dim.maxAquiferID, sched);
|
||||
}
|
||||
|
||||
return dim;
|
||||
}
|
||||
|
@ -34,7 +34,6 @@
|
||||
#include <opm/output/eclipse/AggregateUDQData.hpp>
|
||||
#include <opm/output/eclipse/AggregateActionxData.hpp>
|
||||
#include <opm/output/eclipse/RestartValue.hpp>
|
||||
#include <opm/input/eclipse/EclipseState/TracerConfig.hpp>
|
||||
|
||||
#include <opm/output/eclipse/WriteRestartHelpers.hpp>
|
||||
|
||||
@ -43,16 +42,19 @@
|
||||
#include <opm/io/eclipse/OutputStream.hpp>
|
||||
#include <opm/io/eclipse/PaddedOutputString.hpp>
|
||||
|
||||
#include <opm/input/eclipse/Schedule/SummaryState.hpp>
|
||||
#include <opm/input/eclipse/EclipseState/Grid/EclipseGrid.hpp>
|
||||
#include <opm/input/eclipse/EclipseState/EclipseState.hpp>
|
||||
#include <opm/input/eclipse/EclipseState/Grid/EclipseGrid.hpp>
|
||||
#include <opm/input/eclipse/EclipseState/Tables/Eqldims.hpp>
|
||||
#include <opm/input/eclipse/EclipseState/TracerConfig.hpp>
|
||||
|
||||
#include <opm/input/eclipse/Schedule/Action/Actions.hpp>
|
||||
#include <opm/input/eclipse/Schedule/Network/ExtNetwork.hpp>
|
||||
#include <opm/input/eclipse/Schedule/Schedule.hpp>
|
||||
#include <opm/input/eclipse/Schedule/ScheduleState.hpp>
|
||||
#include <opm/input/eclipse/Schedule/SummaryState.hpp>
|
||||
#include <opm/input/eclipse/Schedule/Tuning.hpp>
|
||||
#include <opm/input/eclipse/Schedule/Well/Well.hpp>
|
||||
#include <opm/input/eclipse/Schedule/Well/WellConnections.hpp>
|
||||
#include <opm/input/eclipse/EclipseState/Tables/Eqldims.hpp>
|
||||
|
||||
#include <opm/common/OpmLog/OpmLog.hpp>
|
||||
|
||||
@ -463,16 +465,24 @@ namespace {
|
||||
rstFile.write("RAQN", aquiferData.getNumericAquiferDoublePrecData());
|
||||
}
|
||||
|
||||
void updateAndWriteAquiferData(const AquiferConfig& aqConfig,
|
||||
void updateAndWriteAquiferData(const EclipseState& es,
|
||||
const ScheduleState& sched,
|
||||
const data::Aquifers& aquData,
|
||||
const SummaryState& summaryState,
|
||||
const UnitSystem& usys,
|
||||
Helpers::AggregateAquiferData& aquiferData,
|
||||
EclIO::OutputStream::Restart& rstFile)
|
||||
{
|
||||
aquiferData.captureDynamicdAquiferData(aqConfig, aquData, summaryState, usys);
|
||||
const auto& aqConfig = es.aquifer();
|
||||
|
||||
if (aqConfig.hasAnalyticalAquifer()) {
|
||||
aquiferData.captureDynamicAquiferData(inferAquiferDimensions(es, sched),
|
||||
aqConfig,
|
||||
sched,
|
||||
aquData,
|
||||
summaryState,
|
||||
usys);
|
||||
|
||||
if (aqConfig.hasAnalyticalAquifer() || sched.hasAnalyticalAquifers()) {
|
||||
writeAnalyticAquiferData(aquiferData, rstFile);
|
||||
}
|
||||
|
||||
@ -506,9 +516,9 @@ namespace {
|
||||
}
|
||||
|
||||
// Write well and MSW data only when applicable (i.e., when present)
|
||||
const auto& wells = schedule.wellNames(sim_step);
|
||||
|
||||
if (! wells.empty()) {
|
||||
if (const auto& wells = schedule.wellNames(sim_step);
|
||||
! wells.empty())
|
||||
{
|
||||
const auto haveMSW =
|
||||
std::any_of(std::begin(wells), std::end(wells),
|
||||
[&schedule, sim_step](const std::string& well)
|
||||
@ -525,11 +535,16 @@ namespace {
|
||||
wells, wellSol, action_state, wtest_state, sumState, inteHD, rstFile);
|
||||
}
|
||||
|
||||
if ((es.aquifer().hasAnalyticalAquifer() || es.aquifer().hasNumericalAquifer()) &&
|
||||
aquiferData.has_value())
|
||||
if (const auto& aqCfg = es.aquifer();
|
||||
aqCfg.active() && aquiferData.has_value())
|
||||
{
|
||||
updateAndWriteAquiferData(es.aquifer(), aquDynData, sumState,
|
||||
schedule.getUnits(), aquiferData.value(), rstFile);
|
||||
updateAndWriteAquiferData(es,
|
||||
schedule[sim_step],
|
||||
aquDynData,
|
||||
sumState,
|
||||
schedule.getUnits(),
|
||||
aquiferData.value(),
|
||||
rstFile);
|
||||
}
|
||||
}
|
||||
|
||||
|
@ -31,15 +31,17 @@
|
||||
|
||||
#include <opm/input/eclipse/EclipseState/Aquifer/Aquancon.hpp>
|
||||
#include <opm/input/eclipse/EclipseState/Aquifer/AquiferCT.hpp>
|
||||
#include <opm/input/eclipse/EclipseState/Aquifer/Aquifetp.hpp>
|
||||
#include <opm/input/eclipse/EclipseState/Aquifer/AquiferFlux.hpp>
|
||||
#include <opm/input/eclipse/EclipseState/Aquifer/AquiferConfig.hpp>
|
||||
#include <opm/input/eclipse/EclipseState/Aquifer/AquiferFlux.hpp>
|
||||
#include <opm/input/eclipse/EclipseState/Aquifer/Aquifetp.hpp>
|
||||
#include <opm/input/eclipse/EclipseState/EclipseState.hpp>
|
||||
#include <opm/input/eclipse/EclipseState/Grid/EclipseGrid.hpp>
|
||||
#include <opm/input/eclipse/EclipseState/Grid/FaceDir.hpp>
|
||||
#include <opm/input/eclipse/Schedule/SummaryState.hpp>
|
||||
#include <opm/input/eclipse/EclipseState/Tables/FlatTable.hpp>
|
||||
|
||||
#include <opm/input/eclipse/Schedule/ScheduleState.hpp>
|
||||
#include <opm/input/eclipse/Schedule/SummaryState.hpp>
|
||||
|
||||
#include <opm/input/eclipse/Deck/Deck.hpp>
|
||||
#include <opm/input/eclipse/Parser/Parser.hpp>
|
||||
|
||||
@ -50,6 +52,7 @@
|
||||
#include <algorithm>
|
||||
#include <cstddef>
|
||||
#include <iterator>
|
||||
#include <string_view>
|
||||
#include <unordered_map>
|
||||
#include <utility>
|
||||
#include <vector>
|
||||
@ -100,6 +103,15 @@ namespace {
|
||||
return Opm::UnitSystem::newMETRIC().to_si(M::pressure, 1.0);
|
||||
}
|
||||
|
||||
double fluxUnit()
|
||||
{
|
||||
using M = Opm::UnitSystem::measure;
|
||||
const auto usys = Opm::UnitSystem::newMETRIC();
|
||||
|
||||
auto q = usys.to_si(M::liquid_surface_rate, 1.0);
|
||||
return usys.from_si(M::length, usys.from_si(M::length, q));
|
||||
}
|
||||
|
||||
double compressibilityUnit()
|
||||
{
|
||||
using M = Opm::UnitSystem::measure;
|
||||
@ -205,7 +217,7 @@ AQUTAB
|
||||
const auto cartCell1 = std::size_t{699}; // one-based IJK = (20,5,7)
|
||||
const auto cartCell2 = std::size_t{799}; // one-based IJK = (20,5,8)
|
||||
const auto cartCell3 = std::size_t{899}; // one-based IJK = (20,5,9)
|
||||
const auto effFaceArea = 4.0 * 0.2; // DY * DZ
|
||||
const auto effFaceArea = 4.0 * 0.2; // DY * DZ
|
||||
const auto influxCoeff = effFaceArea;
|
||||
|
||||
aquancon.addConnection(aquiferID, cartCell1, 1.0*influxCoeff, 6.0*effFaceArea, FDir::XMinus);
|
||||
@ -289,7 +301,8 @@ AQUTAB
|
||||
const auto effFaceArea = 4.0 * 0.2; // DY * DZ
|
||||
const auto influxCoeff = effFaceArea;
|
||||
|
||||
aquancon.addConnection(aquiferID, cartCell, influxCoeff, effFaceArea, FDir::YPlus);
|
||||
aquancon.addConnection(aquiferID, cartCell, influxCoeff,
|
||||
effFaceArea, FDir::YPlus);
|
||||
}
|
||||
|
||||
{
|
||||
@ -298,7 +311,8 @@ AQUTAB
|
||||
const auto effFaceArea = 4.0 * 0.2; // DY * DZ
|
||||
const auto influxCoeff = 1.0; // [m^2]
|
||||
|
||||
aquancon.addConnection(aquiferID, cartCell, influxCoeff, effFaceArea, FDir::ZPlus);
|
||||
aquancon.addConnection(aquiferID, cartCell, influxCoeff,
|
||||
effFaceArea, FDir::ZPlus);
|
||||
}
|
||||
}
|
||||
|
||||
@ -319,7 +333,8 @@ AQUTAB
|
||||
|
||||
auto& fetp = properties
|
||||
.emplace_back(aquiferID, pvtTable, prodIndex, compr,
|
||||
initialVolume, datumDepth, initialPressure, initialTemperature);
|
||||
initialVolume, datumDepth,
|
||||
initialPressure, initialTemperature);
|
||||
|
||||
fetp.finishInitialisation(waterProperties());
|
||||
}
|
||||
@ -332,7 +347,8 @@ AQUTAB
|
||||
|
||||
auto& fetp = properties
|
||||
.emplace_back(aquiferID, pvtTable, prodIndex, compr,
|
||||
initialVolume, datumDepth, initialPressure, initialTemperature);
|
||||
initialVolume, datumDepth,
|
||||
initialPressure, initialTemperature);
|
||||
|
||||
fetp.finishInitialisation(waterProperties());
|
||||
}
|
||||
@ -340,10 +356,47 @@ AQUTAB
|
||||
return Opm::Aquifetp(properties);
|
||||
}
|
||||
|
||||
Opm::AquiferFlux createAquiferFluxs() {
|
||||
// TODO: just for compilation for now, will complete it
|
||||
Opm::AquiferFlux aquifers;
|
||||
return aquifers;
|
||||
void connectConstantFluxAquifers(AquiferConnections& aquancon)
|
||||
{
|
||||
using FDir = Opm::FaceDir::DirEnum;
|
||||
|
||||
{
|
||||
const auto aquiferID = 3;
|
||||
const auto cartCell1 = std::size_t{680}; // one-based IJK = (1,5, 7)
|
||||
const auto cartCell2 = std::size_t{780}; // one-based IJK = (1,5, 8)
|
||||
const auto cartCell3 = std::size_t{880}; // one-based IJK = (1,5, 9)
|
||||
const auto cartCell4 = std::size_t{980}; // one-based IJK = (1,5,10)
|
||||
const auto effFaceArea = 5.0 * 0.2; // DX * DZ
|
||||
const auto influxCoeff = effFaceArea;
|
||||
|
||||
aquancon.addConnection(aquiferID, cartCell1, 1.0*influxCoeff, 6.0*effFaceArea, FDir::YPlus);
|
||||
aquancon.addConnection(aquiferID, cartCell2, 2.0*influxCoeff, 12.0*effFaceArea, FDir::YPlus);
|
||||
aquancon.addConnection(aquiferID, cartCell3, 3.0*influxCoeff, 18.0*effFaceArea, FDir::YPlus);
|
||||
aquancon.addConnection(aquiferID, cartCell4, 4.0*influxCoeff, 24.0*effFaceArea, FDir::YPlus);
|
||||
}
|
||||
|
||||
{
|
||||
const auto aquiferID = 5;
|
||||
const auto cartCell = std::size_t{490}; // one-based IJK = (11,5,5)
|
||||
const auto effFaceArea = 5.0 * 0.2; // DX * DZ
|
||||
const auto influxCoeff = 1.0; // [m^2]
|
||||
|
||||
aquancon.addConnection(aquiferID, cartCell, influxCoeff, effFaceArea, FDir::XPlus);
|
||||
}
|
||||
}
|
||||
|
||||
Opm::AquiferFlux createConstantFluxAquifers()
|
||||
{
|
||||
const auto uQ = fluxUnit();
|
||||
const auto uP = pressureUnit();
|
||||
const auto salt = 0.0;
|
||||
const auto temp = 300.0*temperatureUnit();
|
||||
const auto active = true;
|
||||
|
||||
return Opm::AquiferFlux { std::vector {
|
||||
Opm::SingleAquiferFlux { 3, 12.34*uQ, salt, active, temp, 234.5*uP },
|
||||
Opm::SingleAquiferFlux { 5, 43.21*uQ, salt, active, temp, 345.6*uP },
|
||||
}};
|
||||
}
|
||||
|
||||
Opm::AquiferConfig createAquiferConfig()
|
||||
@ -351,9 +404,28 @@ AQUTAB
|
||||
auto aquancon = AquiferConnections{};
|
||||
connectCarterTracy(aquancon);
|
||||
connectFetkovic(aquancon);
|
||||
connectConstantFluxAquifers(aquancon);
|
||||
|
||||
return {
|
||||
createFetkovich(), createCarterTracy(), createAquiferFluxs(), Opm::Aquancon(aquancon.getAllConnections())
|
||||
createFetkovich(),
|
||||
createCarterTracy(),
|
||||
createConstantFluxAquifers(),
|
||||
Opm::Aquancon { aquancon.getAllConnections() }
|
||||
};
|
||||
}
|
||||
|
||||
Opm::AquiferConfig createEmptyAquiferConfig()
|
||||
{
|
||||
auto aquancon = AquiferConnections{};
|
||||
connectCarterTracy(aquancon);
|
||||
connectFetkovic(aquancon);
|
||||
connectConstantFluxAquifers(aquancon);
|
||||
|
||||
return {
|
||||
Opm::Aquifetp{},
|
||||
Opm::AquiferCT{},
|
||||
Opm::AquiferFlux{},
|
||||
Opm::Aquancon { aquancon.getAllConnections() }
|
||||
};
|
||||
}
|
||||
|
||||
@ -429,15 +501,41 @@ END
|
||||
{
|
||||
auto aqDims = Opm::RestartIO::InteHEAD::AquiferDims{};
|
||||
|
||||
aqDims.numAquifers = 4; // 1, 2, 4, 6
|
||||
aqDims.numAquifers = 6; // 1, 2, 3, 4, 5, 6
|
||||
aqDims.maxNumAquifers = 10; // >= 6
|
||||
aqDims.maxNumAquiferConn = 5; // >= 3
|
||||
aqDims.maxNumActiveAquiferConn = 3; // ID = 1
|
||||
aqDims.maxNumAquiferConn = 5; // >= 4
|
||||
aqDims.maxNumActiveAquiferConn = 4; // ID = 3
|
||||
aqDims.maxAquiferID = 6;
|
||||
|
||||
return aqDims;
|
||||
}
|
||||
|
||||
Opm::RestartIO::InteHEAD::AquiferDims syntheticDynamicAquiferDimensionsSOLUTION()
|
||||
{
|
||||
auto aqDims = Opm::RestartIO::InteHEAD::AquiferDims{};
|
||||
|
||||
aqDims.numAquifers = 0;
|
||||
aqDims.maxNumAquifers = 10; // >= 5
|
||||
aqDims.maxNumAquiferConn = 5; // >= 4
|
||||
aqDims.maxNumActiveAquiferConn = 4; // ID = 3
|
||||
aqDims.maxAquiferID = 0;
|
||||
|
||||
return aqDims;
|
||||
}
|
||||
|
||||
Opm::RestartIO::InteHEAD::AquiferDims syntheticDynamicAquiferDimensionsSCHEDULE()
|
||||
{
|
||||
auto aqDims = Opm::RestartIO::InteHEAD::AquiferDims{};
|
||||
|
||||
aqDims.numAquifers = 2; // 3, 5
|
||||
aqDims.maxNumAquifers = 10; // >= 5
|
||||
aqDims.maxNumAquiferConn = 5; // >= 4
|
||||
aqDims.maxNumActiveAquiferConn = 4; // ID = 3
|
||||
aqDims.maxAquiferID = 5;
|
||||
|
||||
return aqDims;
|
||||
}
|
||||
|
||||
Opm::RestartIO::InteHEAD::AquiferDims syntheticNumericAquiferDimensions()
|
||||
{
|
||||
auto aqDims = Opm::RestartIO::InteHEAD::AquiferDims{};
|
||||
@ -527,10 +625,18 @@ AQUANCON
|
||||
state.update("AAQR:2", 222.333);
|
||||
state.update("AAQT:2", 333.444);
|
||||
|
||||
state.update("AAQP:3", 212.121);
|
||||
state.update("AAQR:3", 333.222);
|
||||
state.update("AAQT:3", 444.333);
|
||||
|
||||
state.update("AAQP:4", 555.444);
|
||||
state.update("AAQR:4", 333.222);
|
||||
state.update("AAQT:4", 222.111);
|
||||
|
||||
state.update("AAQP:5", 444.555);
|
||||
state.update("AAQR:5", 323.232);
|
||||
state.update("AAQT:5", 232.131);
|
||||
|
||||
state.update("AAQP:6", 456.123);
|
||||
state.update("AAQR:6", 34.567);
|
||||
state.update("AAQT:6", 4444.5555);
|
||||
@ -620,17 +726,38 @@ AQUANCON
|
||||
return aquiferValues;
|
||||
}
|
||||
|
||||
Opm::ScheduleState emptyScheduleState()
|
||||
{
|
||||
return {};
|
||||
}
|
||||
|
||||
Opm::ScheduleState dynamicAquFluxState()
|
||||
{
|
||||
auto sched = emptyScheduleState();
|
||||
const auto cfg = createAquiferConfig();
|
||||
|
||||
sched.aqufluxs.insert(cfg.aquflux().begin(),
|
||||
cfg.aquflux().end());
|
||||
|
||||
return sched;
|
||||
}
|
||||
|
||||
template <class Coll1, class Coll2>
|
||||
void check_is_close(const Coll1& coll1, const Coll2& coll2, const double tol)
|
||||
void check_is_close(const Coll1& coll1,
|
||||
const Coll2& coll2,
|
||||
const double tol,
|
||||
std::string_view context)
|
||||
{
|
||||
BOOST_REQUIRE_EQUAL(std::size(coll1), std::size(coll2));
|
||||
|
||||
if (coll1.empty()) { return; }
|
||||
|
||||
auto i = 0;
|
||||
auto c1 = std::begin(coll1);
|
||||
auto e1 = std::end (coll1);
|
||||
auto c2 = std::begin(coll2);
|
||||
for (; c1 != e1; ++c1, ++c2) {
|
||||
for (; c1 != e1; ++c1, ++c2, ++i) {
|
||||
BOOST_TEST_MESSAGE(context << '[' << i << ']');
|
||||
BOOST_CHECK_CLOSE(*c1, *c2, tol);
|
||||
}
|
||||
}
|
||||
@ -683,6 +810,8 @@ BOOST_AUTO_TEST_CASE(Static_Information_Analytic_Aquifers)
|
||||
20, 5, 8, 994, 3, 0, 0,
|
||||
// Connection 2
|
||||
20, 5, 9, 995, 5, 0, 0,
|
||||
// Connection 3 (nonexistent)
|
||||
0, 0, 0, 0, 0, 0, 0,
|
||||
};
|
||||
|
||||
const auto& icaq = aquiferData.getIntegerAquiferConnectionData(1);
|
||||
@ -699,11 +828,13 @@ BOOST_AUTO_TEST_CASE(Static_Information_Analytic_Aquifers)
|
||||
1.0f/3.0f, 2.0f,
|
||||
// Connection 2
|
||||
1.0f/2.0f, 3.0f,
|
||||
// Connection 3 (nonexistent)
|
||||
0.0f, 0.0f,
|
||||
};
|
||||
|
||||
const auto& scaq = aquiferData.getSinglePrecAquiferConnectionData(1);
|
||||
|
||||
check_is_close(scaq, expect, 1.0e-7);
|
||||
check_is_close(scaq, expect, 1.0e-7, "SCAQ:1");
|
||||
}
|
||||
|
||||
// ICAQ:2
|
||||
@ -715,6 +846,8 @@ BOOST_AUTO_TEST_CASE(Static_Information_Analytic_Aquifers)
|
||||
0, 0, 0, 0, 0, 0, 0,
|
||||
// Connection 2 (nonexistent)
|
||||
0, 0, 0, 0, 0, 0, 0,
|
||||
// Connection 3 (nonexistent)
|
||||
0, 0, 0, 0, 0, 0, 0,
|
||||
};
|
||||
|
||||
const auto& icaq = aquiferData.getIntegerAquiferConnectionData(2);
|
||||
@ -731,22 +864,26 @@ BOOST_AUTO_TEST_CASE(Static_Information_Analytic_Aquifers)
|
||||
0.0f, 0.0f,
|
||||
// Connection 2 (nonexistent)
|
||||
0.0f, 0.0f,
|
||||
// Connection 3 (nonexistent)
|
||||
0.0f, 0.0f,
|
||||
};
|
||||
|
||||
const auto& scaq = aquiferData.getSinglePrecAquiferConnectionData(2);
|
||||
|
||||
check_is_close(scaq, expect, 1.0e-7);
|
||||
check_is_close(scaq, expect, 1.0e-7, "SCAQ:2");
|
||||
}
|
||||
|
||||
// ICAQ:3 (not activated/connected)
|
||||
// ICAQ:3
|
||||
{
|
||||
const auto expect = std::vector<int> {
|
||||
// Connection 0
|
||||
0, 0, 0, 0, 0, 0, 0,
|
||||
1, 5, 7, 47, 4, 0, 0,
|
||||
// Connection 1
|
||||
0, 0, 0, 0, 0, 0, 0,
|
||||
1, 5, 8, 48, 4, 0, 0,
|
||||
// Connection 2
|
||||
0, 0, 0, 0, 0, 0, 0,
|
||||
1, 5, 9, 49, 4, 0, 0,
|
||||
// Connection 3
|
||||
1, 5, 10, 50, 4, 0, 0,
|
||||
};
|
||||
|
||||
const auto& icaq = aquiferData.getIntegerAquiferConnectionData(3);
|
||||
@ -754,20 +891,22 @@ BOOST_AUTO_TEST_CASE(Static_Information_Analytic_Aquifers)
|
||||
BOOST_CHECK_EQUAL_COLLECTIONS(icaq.begin(), icaq.end(), expect.begin(), expect.end());
|
||||
}
|
||||
|
||||
// SCAQ:3 (not activated/connected)
|
||||
// SCAQ:3
|
||||
{
|
||||
const auto expect = std::vector<float> {
|
||||
// Connection 0
|
||||
0.0f, 0.0f,
|
||||
1.0f/10.0f, 3.0f/5.0f,
|
||||
// Connection 1
|
||||
0.0f, 0.0f,
|
||||
1.0f/ 5.0f, 6.0f/5.0f,
|
||||
// Connection 2
|
||||
0.0f, 0.0f,
|
||||
3.0f/10.0f, 9.0f/5.0f,
|
||||
// Connection 3
|
||||
2.0f/ 5.0f, 12.0f/5.0f,
|
||||
};
|
||||
|
||||
const auto& scaq = aquiferData.getSinglePrecAquiferConnectionData(3);
|
||||
|
||||
check_is_close(scaq, expect, 1.0e-7);
|
||||
check_is_close(scaq, expect, 1.0e-7, "SCAQ:3");
|
||||
}
|
||||
|
||||
// ICAQ:4
|
||||
@ -779,6 +918,8 @@ BOOST_AUTO_TEST_CASE(Static_Information_Analytic_Aquifers)
|
||||
0, 0, 0, 0, 0, 0, 0,
|
||||
// Connection 2 (nonexistent)
|
||||
0, 0, 0, 0, 0, 0, 0,
|
||||
// Connection 3 (nonexistent)
|
||||
0, 0, 0, 0, 0, 0, 0,
|
||||
};
|
||||
|
||||
const auto& icaq = aquiferData.getIntegerAquiferConnectionData(4);
|
||||
@ -795,21 +936,25 @@ BOOST_AUTO_TEST_CASE(Static_Information_Analytic_Aquifers)
|
||||
0.0f, 0.0f,
|
||||
// Connection 2 (nonexistent)
|
||||
0.0f, 0.0f,
|
||||
// Connection 3 (nonexistent)
|
||||
0.0f, 0.0f,
|
||||
};
|
||||
|
||||
const auto& scaq = aquiferData.getSinglePrecAquiferConnectionData(4);
|
||||
|
||||
check_is_close(scaq, expect, 1.0e-7);
|
||||
check_is_close(scaq, expect, 1.0e-7, "SCAQ:4");
|
||||
}
|
||||
|
||||
// ICAQ:5 (not activated/connected)
|
||||
// ICAQ:5
|
||||
{
|
||||
const auto expect = std::vector<int> {
|
||||
// Connection 0
|
||||
11, 5, 5, 543, 2, 0, 0,
|
||||
// Connection 1 (nonexistent)
|
||||
0, 0, 0, 0, 0, 0, 0,
|
||||
// Connection 1
|
||||
// Connection 2 (nonexistent)
|
||||
0, 0, 0, 0, 0, 0, 0,
|
||||
// Connection 2
|
||||
// Connection 3 (nonexistent)
|
||||
0, 0, 0, 0, 0, 0, 0,
|
||||
};
|
||||
|
||||
@ -818,20 +963,22 @@ BOOST_AUTO_TEST_CASE(Static_Information_Analytic_Aquifers)
|
||||
BOOST_CHECK_EQUAL_COLLECTIONS(icaq.begin(), icaq.end(), expect.begin(), expect.end());
|
||||
}
|
||||
|
||||
// SCAQ:5 (not activated/connected)
|
||||
// SCAQ:5
|
||||
{
|
||||
const auto expect = std::vector<float> {
|
||||
// Connection 0
|
||||
1.0f, 1.0f,
|
||||
// Connection 1 (nonexistent)
|
||||
0.0f, 0.0f,
|
||||
// Connection 1
|
||||
// Connection 2 (nonexistent)
|
||||
0.0f, 0.0f,
|
||||
// Connection 2
|
||||
// Connection 3 (nonexistent)
|
||||
0.0f, 0.0f,
|
||||
};
|
||||
|
||||
const auto& scaq = aquiferData.getSinglePrecAquiferConnectionData(5);
|
||||
|
||||
check_is_close(scaq, expect, 1.0e-7);
|
||||
check_is_close(scaq, expect, 1.0e-7, "SCAQ:5");
|
||||
}
|
||||
|
||||
// ICAQ:6
|
||||
@ -843,6 +990,8 @@ BOOST_AUTO_TEST_CASE(Static_Information_Analytic_Aquifers)
|
||||
0, 0, 0, 0, 0, 0, 0,
|
||||
// Connection 2 (nonexistent)
|
||||
0, 0, 0, 0, 0, 0, 0,
|
||||
// Connection 3 (nonexistent)
|
||||
0, 0, 0, 0, 0, 0, 0,
|
||||
};
|
||||
|
||||
const auto& icaq = aquiferData.getIntegerAquiferConnectionData(6);
|
||||
@ -859,11 +1008,13 @@ BOOST_AUTO_TEST_CASE(Static_Information_Analytic_Aquifers)
|
||||
0.0f, 0.0f,
|
||||
// Connection 2 (nonexistent)
|
||||
0.0f, 0.0f,
|
||||
// Connection 3 (nonexistent)
|
||||
0.0f, 0.0f,
|
||||
};
|
||||
|
||||
const auto& scaq = aquiferData.getSinglePrecAquiferConnectionData(6);
|
||||
|
||||
check_is_close(scaq, expect, 1.0e-7);
|
||||
check_is_close(scaq, expect, 1.0e-7, "SCAQ:6");
|
||||
}
|
||||
}
|
||||
|
||||
@ -875,8 +1026,11 @@ BOOST_AUTO_TEST_CASE(Dynamic_Information_Analytic_Aquifers)
|
||||
auto aquiferData = Opm::RestartIO::Helpers::
|
||||
AggregateAquiferData{ aqDims, aqConfig, createGrid() };
|
||||
|
||||
aquiferData.captureDynamicdAquiferData(aqConfig, aquiferValues(aqConfig), sim_state(),
|
||||
Opm::UnitSystem::newMETRIC());
|
||||
aquiferData.captureDynamicAquiferData(aqDims, aqConfig,
|
||||
emptyScheduleState(),
|
||||
aquiferValues(aqConfig),
|
||||
sim_state(),
|
||||
Opm::UnitSystem::newMETRIC());
|
||||
|
||||
// IAAQ
|
||||
{
|
||||
@ -886,11 +1040,11 @@ BOOST_AUTO_TEST_CASE(Dynamic_Information_Analytic_Aquifers)
|
||||
// Aquifer 2
|
||||
1, 2, 0, 0, 0, 0, 0, 0, 0, 0, 0, 1, 0, 0, 0, 0, 0, 0,
|
||||
// Aquifer 3
|
||||
0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
|
||||
4, 0, 0, 0, 0, 0, 0, 0, 0, 0, 2, 1, 0, 0, 0, 0, 0, 0,
|
||||
// Aquifer 4
|
||||
1, 1, 0, 0, 0, 0, 0, 0, 0, 0, 0, 1, 0, 0, 0, 0, 0, 0,
|
||||
// Aquifer 5
|
||||
0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
|
||||
1, 0, 0, 0, 0, 0, 0, 0, 0, 0, 2, 1, 0, 0, 0, 0, 0, 0,
|
||||
// Aquifer 6
|
||||
1, 1, 0, 0, 0, 0, 0, 0, 0, 3, 1, 1, 0, 0, 0, 0, 0, 0,
|
||||
};
|
||||
@ -914,9 +1068,9 @@ BOOST_AUTO_TEST_CASE(Dynamic_Information_Analytic_Aquifers)
|
||||
0.0f, 0.0f, 0.0f, 0.0f, 0.0f, 0.0f, 0.0f, 0.0f, // 16..23 (40..47)
|
||||
|
||||
// Aquifer 3
|
||||
0.0f, 0.0f, 0.0f, 0.0f, 0.0f, 0.0f, 0.0f, 0.0f, // 0.. 7 (48..55)
|
||||
0.0f, 0.0f, 0.0f, 0.0f, 0.0f, 0.0f, 0.0f, 0.0f, // 8..15 (56..63)
|
||||
0.0f, 0.0f, 0.0f, 0.0f, 0.0f, 0.0f, 0.0f, 0.0f, // 16..23 (64..71)
|
||||
12.34f, 0.0f, 0.0f, 0.0f, 0.0f, 0.0f, 0.0f, 0.0f, // 0.. 7 (48..55)
|
||||
0.0f , 0.0f, 0.0f, 0.0f, 0.0f, 0.0f, 0.0f, 0.0f, // 8..15 (56..63)
|
||||
0.0f , 0.0f, 0.0f, 0.0f, 0.0f, 0.0f, 0.0f, 0.0f, // 16..23 (64..71)
|
||||
|
||||
// Aquifer 4
|
||||
1.5312e-4f, 2.0e10f, 910.0f, 3.365274725274725e+03f, 250.0f, 2000.0f, 0.0f, 0.0f, // 0.. 7 (72..79)
|
||||
@ -924,9 +1078,9 @@ BOOST_AUTO_TEST_CASE(Dynamic_Information_Analytic_Aquifers)
|
||||
0.0f, 0.0f, 0.0f, 0.0f, 0.0f, 0.0f, 0.0f, 0.0f, // 16..23 (88..95)
|
||||
|
||||
// Aquifer 5
|
||||
0.0f, 0.0f, 0.0f, 0.0f, 0.0f, 0.0f, 0.0f, 0.0f, // 0.. 7 ( 96..103)
|
||||
0.0f, 0.0f, 0.0f, 0.0f, 0.0f, 0.0f, 0.0f, 0.0f, // 8..15 (104..111)
|
||||
0.0f, 0.0f, 0.0f, 0.0f, 0.0f, 0.0f, 0.0f, 0.0f, // 16..23 (112..119)
|
||||
43.21f, 0.0f, 0.0f, 0.0f, 0.0f, 0.0f, 0.0f, 0.0f, // 0.. 7 ( 96..103)
|
||||
0.0f , 0.0f, 0.0f, 0.0f, 0.0f, 0.0f, 0.0f, 0.0f, // 8..15 (104..111)
|
||||
0.0f , 0.0f, 0.0f, 0.0f, 0.0f, 0.0f, 0.0f, 0.0f, // 16..23 (112..119)
|
||||
|
||||
// Aquifer 6
|
||||
3.0e-5f, 900.0f, 5000.0f, 0.3f, 269.0f, 2000.0f, 10.0f, 1.0f, // 0.. 7 (120..127)
|
||||
@ -936,7 +1090,7 @@ BOOST_AUTO_TEST_CASE(Dynamic_Information_Analytic_Aquifers)
|
||||
|
||||
const auto& saaq = aquiferData.getSinglePrecAquiferData();
|
||||
|
||||
check_is_close(saaq, expect, 1.0e-7);
|
||||
check_is_close(saaq, expect, 1.0e-7, "SAAQ");
|
||||
}
|
||||
|
||||
// XAAQ
|
||||
@ -949,13 +1103,13 @@ BOOST_AUTO_TEST_CASE(Dynamic_Information_Analytic_Aquifers)
|
||||
222.333, 121.212, 333.444, 0.8, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0,
|
||||
|
||||
// Aquifer 3
|
||||
0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0,
|
||||
333.222, 212.121, 444.333, 10.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0,
|
||||
|
||||
// Aquifer 4
|
||||
333.222, 555.444, 222.111, 1.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0,
|
||||
|
||||
// Aquifer 5
|
||||
0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0,
|
||||
323.232, 444.555, 232.131, 1.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0,
|
||||
|
||||
// Aquifer 6
|
||||
34.567, 456.123, 4444.5555, 1.0, 18.409712143375852, 458.0307, 0.0, 0.0, 100.321, 50.706,
|
||||
@ -963,7 +1117,7 @@ BOOST_AUTO_TEST_CASE(Dynamic_Information_Analytic_Aquifers)
|
||||
|
||||
const auto& xaaq = aquiferData.getDoublePrecAquiferData();
|
||||
|
||||
check_is_close(xaaq, expect, 1.0e-7);
|
||||
check_is_close(xaaq, expect, 1.0e-7, "XAAQ");
|
||||
}
|
||||
}
|
||||
|
||||
@ -972,7 +1126,8 @@ BOOST_AUTO_TEST_CASE(Dynamic_Information_Numeric_Aquifers)
|
||||
const auto aqDims = syntheticNumericAquiferDimensions();
|
||||
const auto aqConfig = createNumericAquiferConfig();
|
||||
|
||||
BOOST_REQUIRE_MESSAGE(aqConfig.hasNumericalAquifer(), "Aquifer configuration object must have numeric aquifers");
|
||||
BOOST_REQUIRE_MESSAGE(aqConfig.hasNumericalAquifer(),
|
||||
"Aquifer configuration object must have numeric aquifers");
|
||||
|
||||
auto aquiferData = Opm::RestartIO::Helpers::
|
||||
AggregateAquiferData{ aqDims, aqConfig, createGrid() };
|
||||
@ -987,10 +1142,11 @@ BOOST_AUTO_TEST_CASE(Dynamic_Information_Numeric_Aquifers)
|
||||
BOOST_CHECK_EQUAL(aquiferData.getNumericAquiferDoublePrecData().size(), 4u * 13);
|
||||
}
|
||||
|
||||
aquiferData.captureDynamicdAquiferData(aqConfig,
|
||||
numericAquiferValues(aqConfig),
|
||||
aqunum_sim_state(),
|
||||
Opm::UnitSystem::newMETRIC());
|
||||
aquiferData.captureDynamicAquiferData(aqDims, aqConfig,
|
||||
emptyScheduleState(),
|
||||
numericAquiferValues(aqConfig),
|
||||
aqunum_sim_state(),
|
||||
Opm::UnitSystem::newMETRIC());
|
||||
|
||||
// IAQN
|
||||
{
|
||||
@ -1022,7 +1178,321 @@ BOOST_AUTO_TEST_CASE(Dynamic_Information_Numeric_Aquifers)
|
||||
};
|
||||
|
||||
const auto& raqn = aquiferData.getNumericAquiferDoublePrecData();
|
||||
check_is_close(raqn, expect, 1.0e-10);
|
||||
check_is_close(raqn, expect, 1.0e-10, "RAQN");
|
||||
}
|
||||
}
|
||||
|
||||
BOOST_AUTO_TEST_CASE(Constant_Flux_Aquifer_SCHEDULE)
|
||||
{
|
||||
const auto aqConfig = createEmptyAquiferConfig();
|
||||
|
||||
BOOST_CHECK_MESSAGE(! aqConfig.active(), "Empty aquifer configuration object must not be active()");
|
||||
|
||||
auto aquiferData = Opm::RestartIO::Helpers::AggregateAquiferData {
|
||||
syntheticDynamicAquiferDimensionsSOLUTION(), aqConfig, createGrid()
|
||||
};
|
||||
|
||||
BOOST_CHECK_EQUAL(aquiferData.maximumActiveAnalyticAquiferID(), 0);
|
||||
|
||||
aquiferData.captureDynamicAquiferData(syntheticDynamicAquiferDimensionsSCHEDULE(),
|
||||
aqConfig, dynamicAquFluxState(),
|
||||
Opm::data::Aquifers{},
|
||||
sim_state(), Opm::UnitSystem::newMETRIC());
|
||||
|
||||
BOOST_CHECK_EQUAL(aquiferData.maximumActiveAnalyticAquiferID(), 5);
|
||||
|
||||
// ICAQ:1
|
||||
{
|
||||
const auto expect = std::vector<int> {
|
||||
// Connection 0
|
||||
20, 5, 7, 993, 1, 0, 0,
|
||||
// Connection 1
|
||||
20, 5, 8, 994, 3, 0, 0,
|
||||
// Connection 2
|
||||
20, 5, 9, 995, 5, 0, 0,
|
||||
// Connection 3 (nonexistent)
|
||||
0, 0, 0, 0, 0, 0, 0,
|
||||
};
|
||||
|
||||
const auto& icaq = aquiferData.getIntegerAquiferConnectionData(1);
|
||||
|
||||
BOOST_CHECK_EQUAL_COLLECTIONS(icaq.begin(), icaq.end(), expect.begin(), expect.end());
|
||||
}
|
||||
|
||||
// SCAQ:1
|
||||
{
|
||||
const auto expect = std::vector<float> {
|
||||
// Connection 0
|
||||
1.0f/6.0f, 1.0f,
|
||||
// Connection 1
|
||||
1.0f/3.0f, 2.0f,
|
||||
// Connection 2
|
||||
1.0f/2.0f, 3.0f,
|
||||
// Connection 3 (nonexistent)
|
||||
0.0f, 0.0f,
|
||||
};
|
||||
|
||||
const auto& scaq = aquiferData.getSinglePrecAquiferConnectionData(1);
|
||||
|
||||
check_is_close(scaq, expect, 1.0e-7, "SCAQ:1");
|
||||
}
|
||||
|
||||
// ICAQ:2
|
||||
{
|
||||
const auto expect = std::vector<int> {
|
||||
// Connection 0
|
||||
20, 1, 7, 955, 4, 0, 0,
|
||||
// Connection 1 (nonexistent)
|
||||
0, 0, 0, 0, 0, 0, 0,
|
||||
// Connection 2 (nonexistent)
|
||||
0, 0, 0, 0, 0, 0, 0,
|
||||
// Connection 3 (nonexistent)
|
||||
0, 0, 0, 0, 0, 0, 0,
|
||||
};
|
||||
|
||||
const auto& icaq = aquiferData.getIntegerAquiferConnectionData(2);
|
||||
|
||||
BOOST_CHECK_EQUAL_COLLECTIONS(icaq.begin(), icaq.end(), expect.begin(), expect.end());
|
||||
}
|
||||
|
||||
// SCAQ:2
|
||||
{
|
||||
const auto expect = std::vector<float> {
|
||||
// Connection 0
|
||||
1.0f, 1.0f,
|
||||
// Connection 1 (nonexistent)
|
||||
0.0f, 0.0f,
|
||||
// Connection 2 (nonexistent)
|
||||
0.0f, 0.0f,
|
||||
// Connection 3 (nonexistent)
|
||||
0.0f, 0.0f,
|
||||
};
|
||||
|
||||
const auto& scaq = aquiferData.getSinglePrecAquiferConnectionData(2);
|
||||
|
||||
check_is_close(scaq, expect, 1.0e-7, "SCAQ:2");
|
||||
}
|
||||
|
||||
// ICAQ:3
|
||||
{
|
||||
const auto expect = std::vector<int> {
|
||||
// Connection 0
|
||||
1, 5, 7, 47, 4, 0, 0,
|
||||
// Connection 1
|
||||
1, 5, 8, 48, 4, 0, 0,
|
||||
// Connection 2
|
||||
1, 5, 9, 49, 4, 0, 0,
|
||||
// Connection 3
|
||||
1, 5, 10, 50, 4, 0, 0,
|
||||
};
|
||||
|
||||
const auto& icaq = aquiferData.getIntegerAquiferConnectionData(3);
|
||||
|
||||
BOOST_CHECK_EQUAL_COLLECTIONS(icaq.begin(), icaq.end(), expect.begin(), expect.end());
|
||||
}
|
||||
|
||||
// SCAQ:3
|
||||
{
|
||||
const auto expect = std::vector<float> {
|
||||
// Connection 0
|
||||
1.0f/10.0f, 3.0f/5.0f,
|
||||
// Connection 1
|
||||
1.0f/ 5.0f, 6.0f/5.0f,
|
||||
// Connection 2
|
||||
3.0f/10.0f, 9.0f/5.0f,
|
||||
// Connection 3
|
||||
2.0f/ 5.0f, 12.0f/5.0f,
|
||||
};
|
||||
|
||||
const auto& scaq = aquiferData.getSinglePrecAquiferConnectionData(3);
|
||||
|
||||
check_is_close(scaq, expect, 1.0e-7, "SCAQ:3");
|
||||
}
|
||||
|
||||
// ICAQ:4
|
||||
{
|
||||
const auto expect = std::vector<int> {
|
||||
// Connection 0
|
||||
20, 1, 5, 953, 6, 0, 0,
|
||||
// Connection 1 (nonexistent)
|
||||
0, 0, 0, 0, 0, 0, 0,
|
||||
// Connection 2 (nonexistent)
|
||||
0, 0, 0, 0, 0, 0, 0,
|
||||
// Connection 3 (nonexistent)
|
||||
0, 0, 0, 0, 0, 0, 0,
|
||||
};
|
||||
|
||||
const auto& icaq = aquiferData.getIntegerAquiferConnectionData(4);
|
||||
|
||||
BOOST_CHECK_EQUAL_COLLECTIONS(icaq.begin(), icaq.end(), expect.begin(), expect.end());
|
||||
}
|
||||
|
||||
// SCAQ:4
|
||||
{
|
||||
const auto expect = std::vector<float> {
|
||||
// Connection 0
|
||||
1.0f, 0.8f,
|
||||
// Connection 1 (nonexistent)
|
||||
0.0f, 0.0f,
|
||||
// Connection 2 (nonexistent)
|
||||
0.0f, 0.0f,
|
||||
// Connection 3 (nonexistent)
|
||||
0.0f, 0.0f,
|
||||
};
|
||||
|
||||
const auto& scaq = aquiferData.getSinglePrecAquiferConnectionData(4);
|
||||
|
||||
check_is_close(scaq, expect, 1.0e-7, "SCAQ:4");
|
||||
}
|
||||
|
||||
// ICAQ:5
|
||||
{
|
||||
const auto expect = std::vector<int> {
|
||||
// Connection 0
|
||||
11, 5, 5, 543, 2, 0, 0,
|
||||
// Connection 1 (nonexistent)
|
||||
0, 0, 0, 0, 0, 0, 0,
|
||||
// Connection 2 (nonexistent)
|
||||
0, 0, 0, 0, 0, 0, 0,
|
||||
// Connection 3 (nonexistent)
|
||||
0, 0, 0, 0, 0, 0, 0,
|
||||
};
|
||||
|
||||
const auto& icaq = aquiferData.getIntegerAquiferConnectionData(5);
|
||||
|
||||
BOOST_CHECK_EQUAL_COLLECTIONS(icaq.begin(), icaq.end(), expect.begin(), expect.end());
|
||||
}
|
||||
|
||||
// SCAQ:5
|
||||
{
|
||||
const auto expect = std::vector<float> {
|
||||
// Connection 0
|
||||
1.0f, 1.0f,
|
||||
// Connection 1 (nonexistent)
|
||||
0.0f, 0.0f,
|
||||
// Connection 2 (nonexistent)
|
||||
0.0f, 0.0f,
|
||||
// Connection 3 (nonexistent)
|
||||
0.0f, 0.0f,
|
||||
};
|
||||
|
||||
const auto& scaq = aquiferData.getSinglePrecAquiferConnectionData(5);
|
||||
|
||||
check_is_close(scaq, expect, 1.0e-7, "SCAQ:5");
|
||||
}
|
||||
|
||||
// ICAQ:6
|
||||
{
|
||||
const auto expect = std::vector<int> {
|
||||
// Connection 0
|
||||
20, 4, 6, 982, 2, 0, 0,
|
||||
// Connection 1 (nonexistent)
|
||||
0, 0, 0, 0, 0, 0, 0,
|
||||
// Connection 2 (nonexistent)
|
||||
0, 0, 0, 0, 0, 0, 0,
|
||||
// Connection 3 (nonexistent)
|
||||
0, 0, 0, 0, 0, 0, 0,
|
||||
};
|
||||
|
||||
const auto& icaq = aquiferData.getIntegerAquiferConnectionData(6);
|
||||
|
||||
BOOST_CHECK_EQUAL_COLLECTIONS(icaq.begin(), icaq.end(), expect.begin(), expect.end());
|
||||
}
|
||||
|
||||
// SCAQ:6
|
||||
{
|
||||
const auto expect = std::vector<float> {
|
||||
// Connection 0
|
||||
1.0f, 0.8f,
|
||||
// Connection 1 (nonexistent)
|
||||
0.0f, 0.0f,
|
||||
// Connection 2 (nonexistent)
|
||||
0.0f, 0.0f,
|
||||
// Connection 3 (nonexistent)
|
||||
0.0f, 0.0f,
|
||||
};
|
||||
|
||||
const auto& scaq = aquiferData.getSinglePrecAquiferConnectionData(6);
|
||||
|
||||
check_is_close(scaq, expect, 1.0e-7, "SCAQ:6");
|
||||
}
|
||||
|
||||
// IAAQ
|
||||
{
|
||||
const auto expect = std::vector<int> {
|
||||
// Aquifer 1 (nonexistent)
|
||||
0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
|
||||
// Aquifer 2 (nonexistent)
|
||||
0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
|
||||
// Aquifer 3
|
||||
4, 0, 0, 0, 0, 0, 0, 0, 0, 0, 2, 1, 0, 0, 0, 0, 0, 0,
|
||||
// Aquifer 4 (nonexistent)
|
||||
0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
|
||||
// Aquifer 5
|
||||
1, 0, 0, 0, 0, 0, 0, 0, 0, 0, 2, 1, 0, 0, 0, 0, 0, 0,
|
||||
};
|
||||
|
||||
const auto& iaaq = aquiferData.getIntegerAquiferData();
|
||||
|
||||
BOOST_CHECK_EQUAL_COLLECTIONS(iaaq.begin(), iaaq.end(), expect.begin(), expect.end());
|
||||
}
|
||||
|
||||
// SAAQ
|
||||
{
|
||||
const auto expect = std::vector<float> {
|
||||
// Aquifer 1
|
||||
0.0f, 0.0f, 0.0f, 0.0f, 0.0f, 0.0f, 0.0f, 0.0f, // 0.. 7
|
||||
0.0f, 0.0f, 0.0f, 0.0f, 0.0f, 0.0f, 0.0f, 0.0f, // 8..15
|
||||
0.0f, 0.0f, 0.0f, 0.0f, 0.0f, 0.0f, 0.0f, 0.0f, // 16..23
|
||||
|
||||
// Aquifer 2
|
||||
0.0f, 0.0f, 0.0f, 0.0f, 0.0f, 0.0f, 0.0f, 0.0f, // 0.. 7 (24..38)
|
||||
0.0f, 0.0f, 0.0f, 0.0f, 0.0f, 0.0f, 0.0f, 0.0f, // 8..15 (32..39)
|
||||
0.0f, 0.0f, 0.0f, 0.0f, 0.0f, 0.0f, 0.0f, 0.0f, // 16..23 (40..47)
|
||||
|
||||
// Aquifer 3
|
||||
12.34f, 0.0f, 0.0f, 0.0f, 0.0f, 0.0f, 0.0f, 0.0f, // 0.. 7 (48..55)
|
||||
0.0f , 0.0f, 0.0f, 0.0f, 0.0f, 0.0f, 0.0f, 0.0f, // 8..15 (56..63)
|
||||
0.0f , 0.0f, 0.0f, 0.0f, 0.0f, 0.0f, 0.0f, 0.0f, // 16..23 (64..71)
|
||||
|
||||
// Aquifer 4
|
||||
0.0f, 0.0f, 0.0f, 0.0f, 0.0f, 0.0f, 0.0f, 0.0f, // 0.. 7 (72..79)
|
||||
0.0f, 0.0f, 0.0f, 0.0f, 0.0f, 0.0f, 0.0f, 0.0f, // 8..15 (80..87)
|
||||
0.0f, 0.0f, 0.0f, 0.0f, 0.0f, 0.0f, 0.0f, 0.0f, // 16..23 (88..95)
|
||||
|
||||
// Aquifer 5
|
||||
43.21f, 0.0f, 0.0f, 0.0f, 0.0f, 0.0f, 0.0f, 0.0f, // 0.. 7 ( 96..103)
|
||||
0.0f , 0.0f, 0.0f, 0.0f, 0.0f, 0.0f, 0.0f, 0.0f, // 8..15 (104..111)
|
||||
0.0f , 0.0f, 0.0f, 0.0f, 0.0f, 0.0f, 0.0f, 0.0f, // 16..23 (112..119)
|
||||
};
|
||||
|
||||
const auto& saaq = aquiferData.getSinglePrecAquiferData();
|
||||
|
||||
check_is_close(saaq, expect, 1.0e-7, "SAAQ");
|
||||
}
|
||||
|
||||
// XAAQ
|
||||
{
|
||||
const auto expect = std::vector<double> {
|
||||
// Aquifer 1
|
||||
0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0,
|
||||
|
||||
// Aquifer 2
|
||||
0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0,
|
||||
|
||||
// Aquifer 3
|
||||
333.222, 212.121, 444.333, 10.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0,
|
||||
|
||||
// Aquifer 4
|
||||
0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0,
|
||||
|
||||
// Aquifer 5
|
||||
323.232, 444.555, 232.131, 1.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0,
|
||||
};
|
||||
|
||||
const auto& xaaq = aquiferData.getDoublePrecAquiferData();
|
||||
|
||||
check_is_close(xaaq, expect, 1.0e-7, "XAAQ");
|
||||
}
|
||||
}
|
||||
|
||||
|
Loading…
Reference in New Issue
Block a user