Merge pull request #3424 from bska/write-aquflux-rst-info
Add Restart File Output Support for Constant Flux Aquifers
This commit is contained in:
commit
553688b73e
@ -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
|
||||
@ -46,8 +47,9 @@ namespace Opm { namespace RestartIO { namespace Helpers {
|
||||
/// aquifer (or connection) in the various output arrays.
|
||||
///
|
||||
/// \param[in] aqConfig Aquifer configuration object. Keeps track
|
||||
/// of aquifer types (Carter-Tracy vs. Fetkovich) and provides
|
||||
/// read-only access to the individual aquifer objects.
|
||||
/// of aquifer types (Carter-Tracy, Fetkovich, constant flux &c)
|
||||
/// and provides read-only access to the individual aquifer
|
||||
/// objects.
|
||||
///
|
||||
/// \param[in] grid Simulation grid. Needed to map active to
|
||||
/// Cartesian cell indices and to extract (I,J,K) index tuples of
|
||||
@ -59,9 +61,18 @@ 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 vs. Fetkovich) and provides
|
||||
/// read-only access to the individual aquifer objects.
|
||||
/// 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
|
||||
@ -74,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.
|
||||
@ -184,6 +197,28 @@ namespace Opm { namespace RestartIO { namespace Helpers {
|
||||
/// Aggregate ACAQ array (Double Precision) for all analytic aquifer
|
||||
/// 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,
|
||||
const UnitSystem& usys);
|
||||
|
||||
void handleNumeric(const AquiferConfig& aqConfig,
|
||||
const data::Aquifers& aquData,
|
||||
const SummaryState& summaryState,
|
||||
const UnitSystem& usys);
|
||||
};
|
||||
|
||||
}}} // Opm::RestartIO::Helpers
|
||||
|
@ -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
|
||||
|
@ -26,15 +26,16 @@
|
||||
#include <opm/output/eclipse/VectorItems/aquifer.hpp>
|
||||
|
||||
#include <opm/input/eclipse/EclipseState/Aquifer/Aquancon.hpp>
|
||||
#include <opm/input/eclipse/EclipseState/Aquifer/AquiferConfig.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/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/Units/UnitSystem.hpp>
|
||||
|
||||
#include <opm/common/OpmLog/OpmLog.hpp>
|
||||
@ -60,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)
|
||||
@ -69,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)
|
||||
@ -101,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
|
||||
@ -133,6 +156,19 @@ namespace {
|
||||
};
|
||||
}
|
||||
|
||||
namespace Common
|
||||
{
|
||||
template <typename IAaqArray>
|
||||
void staticContrib(const int numActiveConn,
|
||||
IAaqArray& iaaq)
|
||||
{
|
||||
using Ix = VI::IAnalyticAquifer::index;
|
||||
|
||||
iaaq[Ix::NumAquiferConn] = numActiveConn;
|
||||
iaaq[Ix::Unknown_1] = 1; // Not characterised; =1 in all cases seen thus far.
|
||||
}
|
||||
} // Common
|
||||
|
||||
namespace CarterTracy
|
||||
{
|
||||
template <typename IAaqArray>
|
||||
@ -142,16 +178,28 @@ namespace {
|
||||
{
|
||||
using Ix = VI::IAnalyticAquifer::index;
|
||||
|
||||
iaaq[Ix::NumAquiferConn] = numActiveConn;
|
||||
Common::staticContrib(numActiveConn, iaaq);
|
||||
|
||||
iaaq[Ix::WatPropTable] = aquifer.pvttableID; // One-based (=AQUCT(10))
|
||||
|
||||
iaaq[Ix::CTInfluenceFunction] = aquifer.inftableID;
|
||||
iaaq[Ix::TypeRelated1] = VI::IAnalyticAquifer::Value::ModelType::CarterTracy;
|
||||
|
||||
iaaq[Ix::Unknown_1] = 1; // Not characterised; =1 in all cases seen thus far.
|
||||
}
|
||||
} // 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>
|
||||
@ -161,11 +209,10 @@ namespace {
|
||||
{
|
||||
using Ix = VI::IAnalyticAquifer::index;
|
||||
|
||||
iaaq[Ix::NumAquiferConn] = numActiveConn;
|
||||
iaaq[Ix::WatPropTable] = aquifer.pvttableID; // One-based (=AQUFETP(7))
|
||||
Common::staticContrib(numActiveConn, iaaq);
|
||||
|
||||
iaaq[Ix::WatPropTable] = aquifer.pvttableID; // One-based (=AQUFETP(7))
|
||||
iaaq[Ix::TypeRelated1] = VI::IAnalyticAquifer::Value::ModelType::Fetkovich;
|
||||
iaaq[Ix::Unknown_1] = 1; // Not characterised; =1 in all cases seen thus far.
|
||||
}
|
||||
} // Fetkovich
|
||||
} // IntegerAnalyticAquifer
|
||||
@ -208,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) }
|
||||
});
|
||||
@ -307,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,
|
||||
@ -351,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) }
|
||||
});
|
||||
@ -442,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,
|
||||
@ -515,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) }
|
||||
});
|
||||
@ -528,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) }
|
||||
@ -539,7 +615,7 @@ AggregateAquiferData(const InteHEAD::AquiferDims& aqDims,
|
||||
, singleprecAnalyticAquiferConn_{ SinglePrecAnalyticAquiferConn::allocate(aqDims) }
|
||||
, doubleprecAnalyticAquiferConn_{ DoublePrecAnalyticAquiferConn::allocate(aqDims) }
|
||||
{
|
||||
if (! aqConfig.hasAnalyticalAquifer()) {
|
||||
if (! aqConfig.connections().active()) {
|
||||
return;
|
||||
}
|
||||
|
||||
@ -569,39 +645,43 @@ 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)
|
||||
{
|
||||
FetkovichAquiferLoop(aqConfig, [this, &summaryState, &aquData, &usys]
|
||||
(const Aquifetp::AQUFETP_data& aquifer)
|
||||
{
|
||||
const auto aquIndex = static_cast<WindowedArray<int>::Idx>(aquifer.aquiferID - 1);
|
||||
if (! (aqConfig.active() || sched.hasAnalyticalAquifers())) {
|
||||
return;
|
||||
}
|
||||
|
||||
auto iaaq = this->integerAnalyticAq_[aquIndex];
|
||||
const auto nActiveConn = this->numActiveConn_[aquIndex];
|
||||
IntegerAnalyticAquifer::Fetkovich::staticContrib(aquifer, nActiveConn, iaaq);
|
||||
this->allocateDynamicBackingStorage(aqDims);
|
||||
|
||||
auto xaqPos = aquData.find(aquifer.aquiferID);
|
||||
if ((xaqPos != aquData.end()) &&
|
||||
xaqPos->second.typeData.is<data::AquiferType::Fetkovich>())
|
||||
{
|
||||
const auto& aquFetPData = xaqPos->second;
|
||||
this->maxActiveAnalyticAquiferID_ = aqDims.maxAquiferID;
|
||||
|
||||
auto saaq = this->singleprecAnalyticAq_[aquIndex];
|
||||
SinglePrecAnalyticAquifer::Fetkovich::staticContrib(aquifer, aquFetPData, usys, saaq);
|
||||
}
|
||||
this->handleFetkovich(aqConfig, aquData, summaryState, usys);
|
||||
this->handleCarterTracy(aqConfig, aquData, summaryState, usys);
|
||||
this->handleConstantFlux(aqConfig, sched, summaryState, usys);
|
||||
this->handleNumeric(aqConfig, aquData, summaryState, usys);
|
||||
}
|
||||
|
||||
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.aquiferID);
|
||||
};
|
||||
DoublePrecAnalyticAquifer::Fetkovich::dynamicContrib(sumVar, tot_influx, usys, xaaq);
|
||||
});
|
||||
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::
|
||||
handleCarterTracy(const AquiferConfig& aqConfig,
|
||||
const data::Aquifers& aquData,
|
||||
const SummaryState& summaryState,
|
||||
const UnitSystem& usys)
|
||||
{
|
||||
CarterTracyAquiferLoop(aqConfig, [this, &summaryState, &aquData, &usys]
|
||||
(const AquiferCT::AQUCT_data& aquifer)
|
||||
{
|
||||
@ -628,15 +708,91 @@ captureDynamicdAquiferData(const AquiferConfig& aqConfig,
|
||||
return getSummaryVariable(summaryState, vector, aquifer.aquiferID);
|
||||
};
|
||||
|
||||
DoublePrecAnalyticAquifer::CarterTracy::dynamicContrib(sumVar, aquCTData,
|
||||
tot_influx, usys, xaaq);
|
||||
DoublePrecAnalyticAquifer::CarterTracy::
|
||||
dynamicContrib(sumVar, aquCTData, tot_influx, usys, xaaq);
|
||||
}
|
||||
});
|
||||
}
|
||||
|
||||
// TODO: we should make the AQUFLUX aquifer here
|
||||
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,
|
||||
const data::Aquifers& aquData,
|
||||
const SummaryState& summaryState,
|
||||
const UnitSystem& usys)
|
||||
{
|
||||
FetkovichAquiferLoop(aqConfig, [this, &summaryState, &aquData, &usys]
|
||||
(const Aquifetp::AQUFETP_data& aquifer)
|
||||
{
|
||||
const auto aquIndex = static_cast<WindowedArray<int>::Idx>(aquifer.aquiferID - 1);
|
||||
|
||||
auto iaaq = this->integerAnalyticAq_[aquIndex];
|
||||
const auto nActiveConn = this->numActiveConn_[aquIndex];
|
||||
IntegerAnalyticAquifer::Fetkovich::staticContrib(aquifer, nActiveConn, iaaq);
|
||||
|
||||
auto xaqPos = aquData.find(aquifer.aquiferID);
|
||||
if ((xaqPos != aquData.end()) &&
|
||||
xaqPos->second.typeData.is<data::AquiferType::Fetkovich>())
|
||||
{
|
||||
const auto& aquFetPData = xaqPos->second;
|
||||
|
||||
auto saaq = this->singleprecAnalyticAq_[aquIndex];
|
||||
SinglePrecAnalyticAquifer::Fetkovich::
|
||||
staticContrib(aquifer, aquFetPData, 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.aquiferID);
|
||||
};
|
||||
DoublePrecAnalyticAquifer::Fetkovich::
|
||||
dynamicContrib(sumVar, tot_influx, usys, xaaq);
|
||||
});
|
||||
}
|
||||
|
||||
void
|
||||
Opm::RestartIO::Helpers::AggregateAquiferData::
|
||||
handleNumeric(const AquiferConfig& aqConfig,
|
||||
const data::Aquifers& aquData,
|
||||
const SummaryState& summaryState,
|
||||
const UnitSystem& usys)
|
||||
{
|
||||
numericAquiferLoop(aqConfig, [this, &summaryState, &aquData, &usys]
|
||||
(const int aquiferID, const std::size_t cellIndex, const NumericalAquiferCell& aqCell)
|
||||
(const int aquiferID,
|
||||
const std::size_t cellIndex,
|
||||
const NumericalAquiferCell& aqCell)
|
||||
{
|
||||
auto iaqn = this->integerNumericAq_[aqCell.record_id];
|
||||
IntegerNumericAquifer::staticContrib(aqCell, aquiferID, iaqn);
|
||||
|
@ -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