opm-common/tests/test_AggregateAquiferData.cpp
Bård Skaflestad 0adcc7dd07 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].
2023-03-16 10:32:43 +01:00

1500 lines
48 KiB
C++

/*
Copyright 2021 Equinor
This file is part of the Open Porous Media project (OPM).
OPM is free software: you can redistribute it and/or modify
it under the terms of the GNU General Public License as published by
the Free Software Foundation, either version 3 of the License, or
(at your option) any later version.
OPM is distributed in the hope that it will be useful,
but WITHOUT ANY WARRANTY; without even the implied warranty of
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
GNU General Public License for more details.
You should have received a copy of the GNU General Public License
along with OPM. If not, see <http://www.gnu.org/licenses/>.
*/
#define BOOST_TEST_MODULE Aggregate_Aquifer_Data
#include <boost/test/unit_test.hpp>
#include <opm/output/eclipse/AggregateAquiferData.hpp>
#include <opm/output/data/Aquifer.hpp>
#include <opm/output/eclipse/InteHEAD.hpp>
#include <opm/output/eclipse/VectorItems/aquifer.hpp>
#include <opm/output/eclipse/WriteRestartHelpers.hpp>
#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/EclipseState.hpp>
#include <opm/input/eclipse/EclipseState/Grid/EclipseGrid.hpp>
#include <opm/input/eclipse/EclipseState/Grid/FaceDir.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>
#include <opm/input/eclipse/Units/UnitSystem.hpp>
#include <opm/common/utility/TimeService.hpp>
#include <algorithm>
#include <cstddef>
#include <iterator>
#include <string_view>
#include <unordered_map>
#include <utility>
#include <vector>
namespace {
class AquiferConnections
{
public:
using Connections = std::vector<Opm::Aquancon::AquancCell>;
using AllConnections = std::unordered_map<int, Connections>;
void addConnection(const int aquiferID,
const std::size_t cartesianCell,
const double influxCoefficient,
const double effectiveFaceArea,
const Opm::FaceDir::DirEnum direction)
{
this->all_connections_[aquiferID]
.emplace_back(aquiferID, cartesianCell, influxCoefficient,
effectiveFaceArea, direction);
}
const AllConnections& getAllConnections() const
{
return this->all_connections_;
}
private:
AllConnections all_connections_;
};
double prodIndexUnit()
{
using M = Opm::UnitSystem::measure;
return Opm::UnitSystem::newMETRIC().to_si(M::liquid_productivity_index, 1.0);
}
double temperatureUnit()
{
using M = Opm::UnitSystem::measure;
return Opm::UnitSystem::newMETRIC().to_si(M::temperature, 1.0);
}
double pressureUnit()
{
using M = Opm::UnitSystem::measure;
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;
return Opm::UnitSystem::newMETRIC().from_si(M::pressure, 1.0);
}
double volumeUnit()
{
using M = Opm::UnitSystem::measure;
return Opm::UnitSystem::newMETRIC().to_si(M::liquid_surface_volume, 1.0);
}
double depthUnit()
{
using M = Opm::UnitSystem::measure;
return Opm::UnitSystem::newMETRIC().to_si(M::length, 1.0);
}
double permeabilityUnit()
{
using M = Opm::UnitSystem::measure;
return Opm::UnitSystem::newMETRIC().to_si(M::permeability, 1.0);
}
Opm::TableManager waterProperties()
{
const auto deck = Opm::Parser{}.parseString(R"(RUNSPEC
TABDIMS
1 2 50 60 2 60 /
AQUDIMS
1* 1* 3 100 3 1000 /
PROPS
PVTW
279.0 1.038 5.0E-05 0.318 0.0001 /
279.0 1.038 5.0E-05 0.118 0.0001 /
DENSITY
856.50000 1053.0 0.85204 /
856.50000 1033.0 0.85204 /
AQUTAB
0.01 0.112
1000.00 666.982 /
0.01 0.112
1000.00 250.578 /
)");
return Opm::TableManager { deck };
}
std::pair<std::vector<double>, std::vector<double>> CTInfluenceFunction_1()
{
return {
std::vector<double> { // tD
0.010, 0.050, 0.100, 0.150, 0.200, 0.250, 0.300, 0.400,
0.500, 0.600, 0.700, 0.800, 0.900, 1.000, 1.500, 2.000,
2.500, 3.000, 4.000, 5.000, 6.000, 7.000, 8.000, 9.000,
10.00, 15.00, 20.00, 25.00, 30.00, 40.00, 50.00, 60.00,
70.00, 80.00, 90.00, 100.0, 150.0, 200.0, 250.0, 300.0,
400.0, 500.0, 600.0, 700.0, 800.0, 900.0, 1000,
}
,
std::vector<double> { // pD
0.112, 0.229, 0.315, 0.376, 0.424, 0.469, 0.503, 0.564,
0.616, 0.659, 0.702, 0.735, 0.772, 0.802, 0.927, 1.020,
1.101, 1.169, 1.275, 1.362, 1.436, 1.500, 1.556, 1.604,
1.651, 1.829, 1.960, 2.067, 2.147, 2.282, 2.388, 2.476,
2.550, 2.615, 2.672, 2.723, 2.921, 3.064, 3.173, 3.263,
3.406, 3.516, 3.608, 3.684, 3.750, 3.809, 3.86,
}
};
}
std::pair<std::vector<double>, std::vector<double>> CTInfluenceFunction_3()
{
return {
std::vector<double> { // tD
0.01, 0.05, 0.10, 0.15, 0.20, 0.25, 0.30, 0.40, 0.50, 0.52,
0.54, 0.56, 0.60, 0.65, 0.70, 0.75, 0.80, 0.85, 0.90, 0.95,
1.00, 1.20, 1.40, 1.60, 2.00, 3.00, 4.00, 5.00, 10.00,
20.00, 30.00, 50.00, 100.00, 200.00, 300.00, 500.00,
1000.00,
},
std::vector<double> { // pD
0.112, 0.229, 0.315, 0.376, 0.424, 0.469, 0.503, 0.564, 0.616,
0.627, 0.636, 0.645, 0.662, 0.683, 0.703, 0.721, 0.740, 0.758,
0.776, 0.791, 0.806, 0.865, 0.920, 0.973, 1.076, 1.328, 1.578,
1.828, 3.078, 5.578, 8.078, 13.078, 25.578, 50.578, 75.578,
125.578, 250.578,
}
};
}
void connectCarterTracy(AquiferConnections& aquancon)
{
using FDir = Opm::FaceDir::DirEnum;
{
const auto aquiferID = 1;
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 influxCoeff = effFaceArea;
aquancon.addConnection(aquiferID, cartCell1, 1.0*influxCoeff, 6.0*effFaceArea, FDir::XMinus);
aquancon.addConnection(aquiferID, cartCell2, 2.0*influxCoeff, 12.0*effFaceArea, FDir::YMinus);
aquancon.addConnection(aquiferID, cartCell3, 3.0*influxCoeff, 18.0*effFaceArea, FDir::ZMinus);
}
{
const auto aquiferID = 6;
const auto cartCell = std::size_t{579}; // one-based IJK = (20,4,6)
const auto effFaceArea = 4.0 * 0.2; // DY * DZ
const auto influxCoeff = 1.0; // [m^2]
aquancon.addConnection(aquiferID, cartCell, influxCoeff, effFaceArea, FDir::XPlus);
}
}
Opm::AquiferCT createCarterTracy()
{
const auto porosity = 0.3;
const auto compr = 3.0e-5*compressibilityUnit();
const auto datumDepth = 2000.0*depthUnit();
const auto initialPressure = 269.0*pressureUnit();
const auto initialTemperature = 50*temperatureUnit();
const auto angle = 360.0; // degrees
const auto thickness = 10.0*depthUnit();
auto properties = std::vector<Opm::AquiferCT::AQUCT_data>{};
{
const auto aquiferID = 1;
const auto influenceFunction = 1;
const auto pvtTable = 2;
const auto ro = 800.0*depthUnit();
const auto ka = 1000.0*permeabilityUnit();
const auto& [tD, pD] = CTInfluenceFunction_1();
auto& ct = properties
.emplace_back(aquiferID, influenceFunction, pvtTable,
porosity, datumDepth, compr, ro, ka,
thickness, angle / 360.0, initialPressure, initialTemperature);
ct.dimensionless_time = tD;
ct.dimensionless_pressure = pD;
ct.finishInitialisation(waterProperties());
}
{
const auto aquiferID = 6;
const auto influenceFunction = 3;
const auto pvtTable = 1;
const auto ro = 900.0*depthUnit();
const auto ka = 5000.0*permeabilityUnit();
const auto& [tD, pD] = CTInfluenceFunction_3();
auto& ct = properties
.emplace_back(aquiferID, influenceFunction, pvtTable,
porosity, datumDepth, compr, ro, ka,
thickness, angle / 360.0, initialPressure, initialTemperature);
ct.dimensionless_time = tD;
ct.dimensionless_pressure = pD;
ct.finishInitialisation(waterProperties());
}
return Opm::AquiferCT(properties);
}
void connectFetkovic(AquiferConnections& aquancon)
{
using FDir = Opm::FaceDir::DirEnum;
{
const auto aquiferID = 2;
const auto cartCell = std::size_t{619}; // one-based IJK = (20,1,7)
const auto effFaceArea = 4.0 * 0.2; // DY * DZ
const auto influxCoeff = effFaceArea;
aquancon.addConnection(aquiferID, cartCell, influxCoeff,
effFaceArea, FDir::YPlus);
}
{
const auto aquiferID = 4;
const auto cartCell = std::size_t{419}; // one-based IJK = (20,1,5)
const auto effFaceArea = 4.0 * 0.2; // DY * DZ
const auto influxCoeff = 1.0; // [m^2]
aquancon.addConnection(aquiferID, cartCell, influxCoeff,
effFaceArea, FDir::ZPlus);
}
}
Opm::Aquifetp createFetkovich()
{
const auto compr = 1.5312e-4*compressibilityUnit();
const auto datumDepth = 2000.0*depthUnit();
const auto initialPressure = 250.0*pressureUnit();
const auto initialTemperature = 20*temperatureUnit();
auto properties = std::vector<Opm::Aquifetp::AQUFETP_data>{};
{
const auto aquiferID = 2;
const auto pvtTable = 2;
const auto prodIndex = 495.0*prodIndexUnit();
const auto initialVolume = 5.0e+10*volumeUnit();
auto& fetp = properties
.emplace_back(aquiferID, pvtTable, prodIndex, compr,
initialVolume, datumDepth,
initialPressure, initialTemperature);
fetp.finishInitialisation(waterProperties());
}
{
const auto aquiferID = 4;
const auto pvtTable = 1;
const auto prodIndex = 910.0*prodIndexUnit();
const auto initialVolume = 2.0e+10*volumeUnit();
auto& fetp = properties
.emplace_back(aquiferID, pvtTable, prodIndex, compr,
initialVolume, datumDepth,
initialPressure, initialTemperature);
fetp.finishInitialisation(waterProperties());
}
return Opm::Aquifetp(properties);
}
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()
{
auto aquancon = AquiferConnections{};
connectCarterTracy(aquancon);
connectFetkovic(aquancon);
connectConstantFluxAquifers(aquancon);
return {
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() }
};
}
Opm::AquiferConfig createNumericAquiferConfig()
{
const auto deck = Opm::Parser{}.parseString(R"(
START -- 0
10 MAY 2007 /
RUNSPEC
DIMENS
10 10 10 /
REGDIMS
3/
AQUDIMS
4 4 1* 1* 3 200 1* 1* /
GRID
DXV
10*400 /
DYV
10*400 /
DZV
10*400 /
TOPS
100*2202 /
PERMX
1000*0.25 /
COPY
PERMX PERMY /
PERMX PERMZ /
/
PORO
1000*0.15 /
AQUNUM
--ID I J K Area Len Phi K Depth P0 PVT SAT
1 1 1 1 15000 5000 0.3 30 2700 285 /
1 2 1 1 160000 6000 0.4 400 2705 295 1* 3 /
1 3 1 1 150000 7000 0.5 5000 2710 1* 2 /
2 4 1 1 140000 9000 0.3 300 2715 250 2 3 / aq cell
/
AQUCON
-- # I1 I2 J1 J2 K1 K2 Face
1 1 1 16 18 19 20 'I-' /
1 2 2 16 18 19 20 'I-' /
1 3 3 16 18 19 20 'I-' /
2 4 4 16 18 19 20 'I-' /
/
END
)");
return Opm::EclipseState { deck }.aquifer();
}
Opm::EclipseGrid createGrid()
{
auto grid = Opm::EclipseGrid { 20, 5, 10, 5.0, 4.0, 0.2 };
auto actnum = std::vector<int>(grid.getCartesianSize(), 1);
actnum[grid.getGlobalIndex( 1, 1, 1)] = 0;
actnum[grid.getGlobalIndex( 2, 1, 1)] = 0;
actnum[grid.getGlobalIndex(19, 1, 6)] = 0;
actnum[grid.getGlobalIndex(19, 2, 6)] = 0;
grid.resetACTNUM(actnum);
return grid;
}
Opm::RestartIO::InteHEAD::AquiferDims syntheticAquiferDimensions()
{
auto aqDims = Opm::RestartIO::InteHEAD::AquiferDims{};
aqDims.numAquifers = 6; // 1, 2, 3, 4, 5, 6
aqDims.maxNumAquifers = 10; // >= 6
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{};
aqDims.numNumericAquiferRecords = 4;
return aqDims;
}
Opm::RestartIO::InteHEAD::AquiferDims parseAquiferDimensions()
{
const auto deck = Opm::Parser{}.parseString(R"(RUNSPEC
DIMENS
20 5 10 /
AQUDIMS
-- MXNAQN MXNAQC NIFTBL NRIFTB NANAQU NNCAMAX
4 4 5 100 5 1000 /
GRID
DXV
20*100.0 /
DYV
5*50.0 /
DZV
10*10.0 /
DEPTHZ
126*2000.0 /
PORO
1000*0.25 /
EQUALS
'PORO' 0.0 2 3 2 2 2 2 /
'PORO' 0.0 20 20 2 3 7 7 /
/
AQUNUM
4 1 1 1 15000 5000 0.3 30 2700 / aq cell
5 2 1 1 150000 9000 0.3 30 2700 / aq cell
6 3 1 1 150000 9000 0.3 30 2700 / aq cell
7 4 1 1 150000 9000 0.3 30 2700 / aq cell
/
AQUCON
-- # I1 I2 J1 J2 K1 K2 Face
4 1 1 16 18 19 20 'I-' / connecting cells
5 2 2 16 18 19 20 'I-' / connecting cells
6 3 3 16 18 19 20 'I-' / connecting cells
7 4 4 16 18 19 20 'I-' / connecting cells
/
SOLUTION
AQUFETP
-- Aqu depth Pr vol Comp PI PVTW
2 2000.0 250.0 5.0E+10 1.5312E-4 495 2 /
4 2000.0 250.0 2.0E+10 1.5312E-4 910 1 /
/
AQUANCON
-- Aq# I1 I2 J1 J2 K1 K2 FACE
2 20 20 1 5 7 9 'I+' 1* 1.0 NO /
4 20 20 1 5 5 6 'I+' 1.0 1.0 NO /
/
)");
const auto es = Opm::EclipseState{ deck };
return Opm::RestartIO::inferAquiferDimensions(es);
}
Opm::SummaryState sim_state()
{
auto state = Opm::SummaryState{Opm::TimeService::now()};
state.update("AAQP:1", 123.456);
state.update("AAQR:1", 234.567);
state.update("AAQT:1", 3456.789);
state.update("AAQPD:1", 4.567);
state.update("AAQTD:1", 50.607);
state.update("AAQP:2", 121.212);
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);
state.update("AAQPD:6", 50.706);
state.update("AAQTD:6", 100.321);
return state;
}
Opm::SummaryState aqunum_sim_state()
{
auto state = Opm::SummaryState{Opm::TimeService::now()};
state.update("ANQP:1", 123.456);
state.update("ANQR:1", 234.567);
state.update("ANQT:1", 3456.789);
state.update("ANQP:2", 121.212);
state.update("ANQR:2", 222.333);
state.update("ANQT:2", 333.444);
return state;
}
Opm::data::Aquifers aquiferValues(const Opm::AquiferConfig& aquConfig)
{
auto aquiferValues = Opm::data::Aquifers{};
for (const auto& aquct : aquConfig.ct()) {
auto& aquifer = aquiferValues[aquct.aquiferID];
aquifer.aquiferID = aquct.aquiferID;
aquifer.initPressure = aquct.initial_pressure.value();
aquifer.datumDepth = aquct.datum_depth;
auto* aquCT = aquifer.typeData.create<Opm::data::AquiferType::CarterTracy>();
aquCT->timeConstant = aquct.timeConstant();
aquCT->influxConstant = aquct.influxConstant();
aquCT->waterDensity = aquct.waterDensity();
aquCT->waterViscosity = aquct.waterViscosity();
}
for (const auto& aqufetp : aquConfig.fetp()) {
auto& aquifer = aquiferValues[aqufetp.aquiferID];
aquifer.aquiferID = aqufetp.aquiferID;
aquifer.initPressure = aqufetp.initial_pressure.value();
aquifer.datumDepth = aqufetp.datum_depth;
auto* aquFet = aquifer.typeData.create<Opm::data::AquiferType::Fetkovich>();
aquFet->initVolume = aqufetp.initial_watvolume;
aquFet->prodIndex = aqufetp.prod_index;
aquFet->timeConstant = aqufetp.timeConstant();
}
return aquiferValues;
}
Opm::data::Aquifers numericAquiferValues(const Opm::AquiferConfig& aquConfig)
{
const auto equilibratedAquiferCellPressure = 300.0*pressureUnit();
auto aquiferValues = Opm::data::Aquifers{};
for (const auto& [aquiferID, aquNum] : aquConfig.numericalAquifers().aquifers()) {
const auto numCells = aquNum.numCells();
auto& aquifer = aquiferValues[aquiferID];
aquifer.aquiferID = static_cast<int>(aquiferID);
auto* aquNumData = aquifer.typeData.create<Opm::data::AquiferType::Numerical>();
aquNumData->initPressure.reserve(numCells);
for (auto cellIndex = 0*numCells; cellIndex < numCells; ++cellIndex) {
const auto* aqCell = aquNum.getCellPrt(cellIndex);
const auto p0 = aqCell->init_pressure.has_value()
? aqCell->init_pressure.value()
: equilibratedAquiferCellPressure;
aquNumData->initPressure.push_back(p0);
}
}
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,
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, ++i) {
BOOST_TEST_MESSAGE(context << '[' << i << ']');
BOOST_CHECK_CLOSE(*c1, *c2, tol);
}
}
} // namespace
BOOST_AUTO_TEST_SUITE(Aggregate_Aquifer_Data)
BOOST_AUTO_TEST_CASE(AquiferDimensions)
{
const auto aqDims = parseAquiferDimensions();
BOOST_CHECK_EQUAL(aqDims.numAquifers, 2); // 2 unique aquifer IDs (2 and 4)
BOOST_CHECK_EQUAL(aqDims.maxNumAquifers, 5); // AQUDIMS(5)
BOOST_CHECK_EQUAL(aqDims.maxNumAquiferConn, 1000); // AQUDIMS(6)
BOOST_CHECK_EQUAL(aqDims.maxNumActiveAquiferConn, 13); // In aquifer ID 2
BOOST_CHECK_EQUAL(aqDims.maxAquiferID, 4); // Maximum aquifer ID
BOOST_CHECK_EQUAL(aqDims.numNumericAquiferRecords, 4); // Number of lines of AQUNUM data
// # Data items per analytic aquifer
BOOST_CHECK_EQUAL(aqDims.numIntAquiferElem, 18); // # Integer
BOOST_CHECK_EQUAL(aqDims.numRealAquiferElem, 24); // # Single precision
BOOST_CHECK_EQUAL(aqDims.numDoubAquiferElem, 10); // # Double precision
// # Data items per analytic aquifer *connection*
BOOST_CHECK_EQUAL(aqDims.numIntConnElem, 7); // # Integer
BOOST_CHECK_EQUAL(aqDims.numRealConnElem, 2); // # Single precision
BOOST_CHECK_EQUAL(aqDims.numDoubConnElem, 4); // # Double precision
// # Data items per numeric aquifer
BOOST_CHECK_EQUAL(aqDims.numNumericAquiferIntElem, 10); // # Integer
BOOST_CHECK_EQUAL(aqDims.numNumericAquiferDoubleElem, 13); // # Double precision
}
BOOST_AUTO_TEST_CASE(Static_Information_Analytic_Aquifers)
{
const auto aqDims = syntheticAquiferDimensions();
const auto aqConfig = createAquiferConfig();
const auto aquiferData = Opm::RestartIO::Helpers::
AggregateAquiferData{ aqDims, aqConfig, createGrid() };
BOOST_CHECK_EQUAL(aquiferData.maximumActiveAnalyticAquiferID(), 6);
// 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");
}
}
BOOST_AUTO_TEST_CASE(Dynamic_Information_Analytic_Aquifers)
{
const auto aqDims = syntheticAquiferDimensions();
const auto aqConfig = createAquiferConfig();
auto aquiferData = Opm::RestartIO::Helpers::
AggregateAquiferData{ aqDims, aqConfig, createGrid() };
aquiferData.captureDynamicAquiferData(aqDims, aqConfig,
emptyScheduleState(),
aquiferValues(aqConfig),
sim_state(),
Opm::UnitSystem::newMETRIC());
// IAAQ
{
const auto expect = std::vector<int> {
// Aquifer 1
3, 2, 0, 0, 0, 0, 0, 0, 0, 1, 1, 1, 0, 0, 0, 0, 0, 0,
// Aquifer 2
1, 2, 0, 0, 0, 0, 0, 0, 0, 0, 0, 1, 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
1, 1, 0, 0, 0, 0, 0, 0, 0, 0, 0, 1, 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,
// Aquifer 6
1, 1, 0, 0, 0, 0, 0, 0, 0, 3, 1, 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
3.0e-5f, 800.0f, 1000.0f, 0.3f, 269.0f, 2000.0f, 10.0f, 1.0f, // 0.. 7
994.6857f, 0.117882f, 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
1.5312e-4f, 5.0e10f, 495.0f, 1.546666666666667e+04f, 250.0f, 2000.0f, 0.0f, 0.0f, // 0.. 7 (24..31)
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
1.5312e-4f, 2.0e10f, 910.0f, 3.365274725274725e+03f, 250.0f, 2000.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)
// Aquifer 6
3.0e-5f, 900.0f, 5000.0f, 0.3f, 269.0f, 2000.0f, 10.0f, 1.0f, // 0.. 7 (120..127)
1013.943893f, 0.317682f, 0.0f, 0.0f, 0.0f, 0.0f, 0.0f, 0.0f, // 8..15 (128..135)
0.0f, 0.0f, 0.0f, 0.0f, 0.0f, 0.0f, 0.0f, 0.0f, // 16..23 (136..143)
};
const auto& saaq = aquiferData.getSinglePrecAquiferData();
check_is_close(saaq, expect, 1.0e-7, "SAAQ");
}
// XAAQ
{
const auto expect = std::vector<double> {
// Aquifer 1
234.567, 123.456, 3456.789, 4.8, 12.558192939329325, 361.9008, 0.0, 0.0, 50.607, 4.567,
// Aquifer 2
222.333, 121.212, 333.444, 0.8, 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
333.222, 555.444, 222.111, 1.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,
// Aquifer 6
34.567, 456.123, 4444.5555, 1.0, 18.409712143375852, 458.0307, 0.0, 0.0, 100.321, 50.706,
};
const auto& xaaq = aquiferData.getDoublePrecAquiferData();
check_is_close(xaaq, expect, 1.0e-7, "XAAQ");
}
}
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");
auto aquiferData = Opm::RestartIO::Helpers::
AggregateAquiferData{ aqDims, aqConfig, createGrid() };
{
BOOST_CHECK_EQUAL(aquiferData.maximumActiveAnalyticAquiferID(), 0);
BOOST_CHECK_MESSAGE(aquiferData.getIntegerAquiferData().empty(), "IAAQ must be empty");
BOOST_CHECK_MESSAGE(aquiferData.getSinglePrecAquiferData().empty(), "SAAQ must be empty");
BOOST_CHECK_MESSAGE(aquiferData.getDoublePrecAquiferData().empty(), "XAAQ must be empty");
BOOST_CHECK_EQUAL(aquiferData.getNumericAquiferIntegerData().size(), 4u * 10);
BOOST_CHECK_EQUAL(aquiferData.getNumericAquiferDoublePrecData().size(), 4u * 13);
}
aquiferData.captureDynamicAquiferData(aqDims, aqConfig,
emptyScheduleState(),
numericAquiferValues(aqConfig),
aqunum_sim_state(),
Opm::UnitSystem::newMETRIC());
// IAQN
{
const auto expect = std::vector<int> {
1, 1, 1, 1, 1, 1, 0, 0, 0, 0, // 0.. 9 (record 0)
1, 2, 1, 1, 1, 3, 0, 0, 0, 0, // 10..19 (record 1)
1, 3, 1, 1, 2, 1, 0, 0, 0, 0, // 20..29 (record 2)
2, 4, 1, 1, 2, 3, 0, 0, 0, 0, // 30..39 (record 3)
};
const auto& iaqn = aquiferData.getNumericAquiferIntegerData();
BOOST_CHECK_EQUAL_COLLECTIONS(iaqn.begin(), iaqn.end(), expect.begin(), expect.end());
}
// RAQN
{
const auto pv = std::vector<double> {
15.0e3 * 5.0e3 * 0.3,
160.0e3 * 6.0e3 * 0.4,
150.0e3 * 7.0e3 * 0.5,
140.0e3 * 9.0e3 * 0.3,
};
const auto expect = std::vector<double> {
15.0e3, 5.0e3, 0.3, 30.0, 2700.0, 285.0, 1.0, 1.0, 1.0, pv[0], 234.567, 3456.789, 123.456, // 0..12 (record 0)
160.0e3, 6.0e3, 0.4, 400.0, 2705.0, 295.0, 1.0, 1.0, 1.0, pv[1], 0.0 , 0.0 , 0.0 , // 13..25 (record 1)
150.0e3, 7.0e3, 0.5, 5000.0, 2710.0, 300.0, 1.0, 1.0, 1.0, pv[2], 0.0 , 0.0 , 0.0 , // 26..38 (record 2)
140.0e3, 9.0e3, 0.3, 300.0, 2715.0, 250.0, 1.0, 1.0, 1.0, pv[3], 222.333, 333.444, 121.212, // 39..51 (record 3)
};
const auto& raqn = aquiferData.getNumericAquiferDoublePrecData();
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");
}
}
BOOST_AUTO_TEST_SUITE_END()