Merge pull request #1452 from joakim-hove/eclstate-aquifer-aquancon

Eclstate aquifer aquancon
This commit is contained in:
Kai Bao
2020-02-18 11:08:14 +01:00
committed by GitHub
12 changed files with 709 additions and 823 deletions

View File

@@ -287,10 +287,7 @@ if(ENABLE_ECL_INPUT)
list(APPEND TEST_SOURCE_FILES
tests/parser/ACTIONX.cpp
tests/parser/ADDREGTests.cpp
tests/parser/AquiferCTTests.cpp
tests/parser/AquifetpTests.cpp
tests/parser/AqudimsTests.cpp
tests/parser/AquanconTests.cpp
tests/parser/AquiferTests.cpp
tests/parser/BoxTests.cpp
tests/parser/ColumnSchemaTests.cpp
tests/parser/ConnectionTests.cpp

View File

@@ -26,7 +26,10 @@
implement the analytical aquifer models in OPM Flow.
*/
#include <unordered_map>
#include <opm/parser/eclipse/EclipseState/Grid/EclipseGrid.hpp>
#include <opm/parser/eclipse/EclipseState/Grid/FaceDir.hpp>
#include <opm/parser/eclipse/Parser/ParserKeywords/A.hpp>
#include <opm/parser/eclipse/Deck/Deck.hpp>
#include <opm/parser/eclipse/Deck/DeckItem.hpp>
@@ -34,44 +37,54 @@
#include <opm/parser/eclipse/Deck/DeckKeyword.hpp>
namespace Opm {
namespace{
struct AquanconRecord;
}
class Aquancon {
public:
struct AquanconOutput{
int aquiferID;
std::vector<size_t> global_index;
std::vector<std::shared_ptr<double>> influx_coeff; // Size = size(global_index)
std::vector<double> influx_multiplier; // Size = size(global_index)
std::vector<int> reservoir_face_dir; // Size = size(global_index)
std::vector<int> record_index;
};
struct AquancCell {
int aquiferID;
std::size_t global_index;
std::pair<bool, double> influx_coeff;
double influx_mult;
FaceDir::DirEnum face_dir;
AquancCell(int aquiferID_arg, std::size_t gi, const std::pair<bool, double>& ic, double im, FaceDir::DirEnum fd) :
aquiferID(aquiferID_arg),
global_index(gi),
influx_coeff(ic),
influx_mult(im),
face_dir(fd)
{}
AquancCell() = default;
bool operator==(const AquancCell& other) const {
return this->aquiferID == other.aquiferID &&
this->global_index == other.global_index &&
this->influx_coeff == other.influx_coeff &&
this->influx_mult == other.influx_mult &&
this->face_dir == other.face_dir;
}
};
Aquancon() = default;
Aquancon(const EclipseGrid& grid, const Deck& deck);
Aquancon(const std::unordered_map<int, std::vector<Aquancon::AquancCell>>& data);
const std::vector<Aquancon::AquanconOutput>& getAquOutput() const;
const std::unordered_map<int, std::vector<Aquancon::AquancCell>>& data() const;
bool operator==(const Aquancon& other) const;
bool active() const;
const std::vector<Aquancon::AquancCell> operator[](int aquiferID) const;
private:
static std::vector<Aquancon::AquanconOutput> logic_application(const std::vector<Aquancon::AquanconOutput>& original_vector);
static void collate_function(std::vector<Aquancon::AquanconOutput>& output_vector,
std::vector<Opm::AquanconRecord>& m_aqurecord,
const std::vector<int>& m_aquiferID_per_record, int m_maxAquID);
static void convert_record_id_to_aquifer_id(std::vector<int>& record_indices_matching_id, int i,
const std::vector<int>& m_aquiferID_per_record);
// for a cell to be inside reservoir, its indices need to be within the reservoir grid dimension range,
// and it needs to be active
static bool cellInsideReservoirAndActive(const EclipseGrid& grid, int i, int j, int k);
static bool neighborCellInsideReservoirAndActive(const EclipseGrid& grid, int i, int j, int k, FaceDir::DirEnum faceDir);
std::vector<Aquancon::AquanconOutput> m_aquoutput;
std::unordered_map<int, std::vector<Aquancon::AquancCell>> cells;
};
}

View File

@@ -47,6 +47,23 @@ namespace Opm {
struct AQUCT_data{
AQUCT_data(const DeckRecord& record, const TableManager& tables);
AQUCT_data() = default;
AQUCT_data(int aqID,
int infID,
int pvtID,
double phi_aq_,
double d0_,
double C_t_,
double r_o_,
double k_a_,
double c1_,
double h_,
double theta_,
double c2_,
const std::pair<bool, double>& p0_,
const std::vector<double>& td_,
const std::vector<double>& pi_,
const std::vector<int>& cell_id_);
int aquiferID;
int inftableID, pvttableID;
@@ -67,7 +84,7 @@ namespace Opm {
bool operator==(const AQUCT_data& other) const;
};
AquiferCT() = default;
AquiferCT(const TableManager& tables, const Deck& deck);
AquiferCT(const std::vector<AquiferCT::AQUCT_data>& data);

View File

@@ -38,6 +38,8 @@ class Aquifetp {
struct AQUFETP_data{
AQUFETP_data(const DeckRecord& record);
AQUFETP_data() = default;
AQUFETP_data(int aquiferID_, int pvttableID_, double J_, double C_t_, double V0_, double d0_, const std::pair<bool, double>& p0_);
bool operator==(const AQUFETP_data& other) const;
int aquiferID;
@@ -49,6 +51,7 @@ class Aquifetp {
std::pair<bool, double> p0;
};
Aquifetp() = default;
Aquifetp(const Deck& deck);
Aquifetp(const std::vector<Aquifetp::AQUFETP_data>& data);
const std::vector<Aquifetp::AQUFETP_data>& data() const;

View File

@@ -18,107 +18,100 @@
*/
#include <opm/parser/eclipse/EclipseState/Grid/FaceDir.hpp>
#include <opm/parser/eclipse/EclipseState/Aquancon.hpp>
#include <unordered_map>
#include <utility>
#include <algorithm>
#include <iterator>
#include <iostream>
namespace Opm {
namespace{
struct AquanconRecord{
std::vector<size_t> global_index_per_record;
// Variables constants
std::vector<std::shared_ptr<double>> influx_coeff_per_record; //Aquifer influx coefficient
std::vector<double> influx_mult_per_record; //Aquifer influx coefficient Multiplier
// Cell face to connect aquifer to
std::vector<int> face_per_record;
std::vector<int> record_index_per_record;
};
namespace{
void add_cell(std::unordered_map<std::size_t, Aquancon::AquancCell>& work, Aquancon::AquancCell cell) {
auto cell_iter = work.find(cell.global_index);
if (cell_iter == work.end())
work.insert( std::make_pair(cell.global_index, std::move(cell)));
else {
auto& prev_cell = cell_iter->second;
if (prev_cell.aquiferID == cell.aquiferID) {
if (prev_cell.influx_coeff.first != cell.influx_coeff.first)
throw std::invalid_argument("Can not combine defaulted and not defaulted influx coefficient");
if (prev_cell.influx_coeff.first) {
if (cell.influx_coeff.second == 0)
prev_cell.influx_coeff.second = 0;
else
prev_cell.influx_coeff.second += cell.influx_coeff.second;
}
} else {
std::string msg = "Cell with global index: " + std::to_string(cell.global_index) + " is already connected to Aquifer: " + std::to_string(prev_cell.aquiferID);
throw std::invalid_argument( msg );
}
}
}
}
Aquancon::Aquancon(const EclipseGrid& grid, const Deck& deck)
{
if (!deck.hasKeyword("AQUANCON"))
return;
std::unordered_map<std::size_t, Aquancon::AquancCell> work;
for (std::size_t iaq = 0; iaq < deck.count("AQUANCON"); iaq++) {
const auto& aquanconKeyword = deck.getKeyword("AQUANCON", iaq);
for (const auto& aquanconRecord : aquanconKeyword) {
const int aquiferID = aquanconRecord.getItem("AQUIFER_ID").get<int>(0);
const int i1 = aquanconRecord.getItem("I1").get<int>(0) - 1;
const int i2 = aquanconRecord.getItem("I2").get<int>(0) - 1;
const int j1 = aquanconRecord.getItem("J1").get<int>(0) - 1;
const int j2 = aquanconRecord.getItem("J2").get<int>(0) - 1;
const int k1 = aquanconRecord.getItem("K1").get<int>(0) - 1;
const int k2 = aquanconRecord.getItem("K2").get<int>(0) - 1;
const double influx_mult = aquanconRecord.getItem("INFLUX_MULT").getSIDouble(0);
const FaceDir::DirEnum faceDir
= FaceDir::FromString(aquanconRecord.getItem("FACE").getTrimmedString(0));
std::vector<Opm::AquanconRecord> aqurecords;
// Aquifer ID per record
std::vector<int> aquiferID_per_record;
int m_maxAquID = 0;
const std::string& str_inside_reservoir
= aquanconRecord.getItem("CONNECT_ADJOINING_ACTIVE_CELL").getTrimmedString(0);
const bool allow_aquifer_inside_reservoir = DeckItem::to_bool(str_inside_reservoir);
const auto& aquanconKeyword = deck.getKeyword("AQUANCON");
// Resize the parameter vector container based on row entries in aquancon
aqurecords.resize(aquanconKeyword.size());
aquiferID_per_record.resize(aquanconKeyword.size());
// Loop over the cartesian indices to convert to the global grid index
for (int k = k1; k <= k2; k++) {
for (int j = j1; j <= j2; j++) {
for (int i = i1; i <= i2; i++) {
if (grid.cellActive(i, j, k)) { // the cell itself needs to be active
if (allow_aquifer_inside_reservoir
|| !neighborCellInsideReservoirAndActive(grid, i, j, k, faceDir)) {
std::pair<bool, double> influx_coeff = std::make_pair(false, 0);
auto global_index = grid.getGlobalIndex(i, j, k);
if (aquanconRecord.getItem("INFLUX_COEFF").hasValue(0))
influx_coeff = std::make_pair(
true, aquanconRecord.getItem("INFLUX_COEFF").getSIDouble(0));
for (size_t aquanconRecordIdx = 0; aquanconRecordIdx < aquanconKeyword.size(); ++aquanconRecordIdx)
{
const auto& aquanconRecord = aquanconKeyword.getRecord(aquanconRecordIdx);
aquiferID_per_record[aquanconRecordIdx] = aquanconRecord.getItem("AQUIFER_ID").template get<int>(0);
// offset the indices
const int i1 = aquanconRecord.getItem("I1").template get<int>(0) - 1;
const int i2 = aquanconRecord.getItem("I2").template get<int>(0) - 1;
const int j1 = aquanconRecord.getItem("J1").template get<int>(0) - 1;
const int j2 = aquanconRecord.getItem("J2").template get<int>(0) - 1;
const int k1 = aquanconRecord.getItem("K1").template get<int>(0) - 1;
const int k2 = aquanconRecord.getItem("K2").template get<int>(0) - 1;
m_maxAquID = (m_maxAquID < aquiferID_per_record[aquanconRecordIdx] )?
aquiferID_per_record[aquanconRecordIdx] : m_maxAquID;
const FaceDir::DirEnum faceDir = FaceDir::FromString(aquanconRecord.getItem("FACE").getTrimmedString(0));
// whether allow aquifer connections to locate inside reservoir
const std::string& str_inside_reservoir = aquanconRecord.getItem("CONNECT_ADJOINING_ACTIVE_CELL").getTrimmedString(0);
// not sure whether we should give a warning when input other than "YES" or "NO"
const bool allow_aquifer_inside_reservoir = str_inside_reservoir == "YES" ? true : false;
auto& aqurecord = aqurecords[aquanconRecordIdx];
// Loop over the cartesian indices to convert to the global grid index
for (int k = k1; k <= k2; k++) {
for (int j = j1; j <= j2; j++) {
for (int i = i1; i <= i2; i++) {
if ( grid.cellActive(i, j, k) ) { // the cell itself needs to be active
if ( allow_aquifer_inside_reservoir
|| !neighborCellInsideReservoirAndActive(grid, i, j, k, faceDir) ) {
aqurecord.global_index_per_record.push_back(grid.getGlobalIndex(i, j, k));
}
AquancCell cell(aquiferID, global_index, influx_coeff, influx_mult, faceDir);
add_cell(work, cell);
}
}
}
}
}
}
const size_t global_index_per_record_size = aqurecord.global_index_per_record.size();
aqurecord.influx_coeff_per_record.resize(global_index_per_record_size, nullptr);
if (aquanconRecord.getItem("INFLUX_COEFF").hasValue(0))
{
const double influx_coeff = aquanconRecord.getItem("INFLUX_COEFF").getSIDouble(0);
for (auto& influx: aqurecord.influx_coeff_per_record)
{
influx.reset(new double(influx_coeff));
}
}
const double influx_mult = aquanconRecord.getItem("INFLUX_MULT").getSIDouble(0);
aqurecord.influx_mult_per_record.resize(global_index_per_record_size, influx_mult);
aqurecord.face_per_record.resize(global_index_per_record_size, faceDir);
aqurecord.record_index_per_record.resize(global_index_per_record_size, aquanconRecordIdx);
}
// Collate_function
collate_function(m_aquoutput, aqurecords, aquiferID_per_record, m_maxAquID);
for (const auto& gi_cell : work) {
const auto& cell = gi_cell.second;
// Logic for grid connection applied here
m_aquoutput = logic_application(m_aquoutput);
this->cells[cell.aquiferID].emplace_back(std::move(cell));
}
}
const std::vector<Aquancon::AquancCell> Aquancon::operator[](int aquiferID) const {
return this->cells.at( aquiferID );
}
bool Aquancon::cellInsideReservoirAndActive(const Opm::EclipseGrid& grid, const int i, const int j, const int k)
{
if ( i < 0 || j < 0 || k < 0
@@ -153,167 +146,22 @@ namespace Opm {
}
}
// This function is used to convert from a per record vector to a per aquifer ID vector.
void Aquancon::collate_function(std::vector<Aquancon::AquanconOutput>& output_vector,
std::vector<Opm::AquanconRecord>& aqurecords,
const std::vector<int>& aquiferID_per_record,
const int m_maxAquID)
{
output_vector.resize(m_maxAquID);
// Find record indices at which the aquifer ids are located in
for (int i = 1; i <= m_maxAquID; ++i)
{
std::vector<int> result_id;
convert_record_id_to_aquifer_id(result_id, i, aquiferID_per_record);
Aquancon::Aquancon(const std::unordered_map<int, std::vector<Aquancon::AquancCell>>& data) :
cells(data)
{}
// We add the aquifer id into each element of output_vector
output_vector.at(i - 1).aquiferID = i;
for ( auto record_index_matching_id : result_id)
{
// This is for the global indices
output_vector.at(i - 1).global_index.insert(
output_vector.at(i - 1).global_index.end(),
aqurecords.at(record_index_matching_id).global_index_per_record.begin(),
aqurecords.at(record_index_matching_id).global_index_per_record.end()
);
// This is for the influx_coeff
output_vector.at(i - 1).influx_coeff.insert(
output_vector.at(i - 1).influx_coeff.end(),
aqurecords.at(record_index_matching_id).influx_coeff_per_record.begin(),
aqurecords.at(record_index_matching_id).influx_coeff_per_record.end()
);
// This is for the influx_multiplier
output_vector.at(i - 1).influx_multiplier.insert(
output_vector.at(i - 1).influx_multiplier.end(),
aqurecords.at(record_index_matching_id).influx_mult_per_record.begin(),
aqurecords.at(record_index_matching_id).influx_mult_per_record.end()
);
// This is for the reservoir_face_dir
output_vector.at(i - 1).reservoir_face_dir.insert(
output_vector.at(i - 1).reservoir_face_dir.end(),
aqurecords.at(record_index_matching_id).face_per_record.begin(),
aqurecords.at(record_index_matching_id).face_per_record.end()
);
// This is for the record index in order for us to know which one is updated
output_vector.at(i - 1).record_index.insert(
output_vector.at(i - 1).record_index.end(),
aqurecords.at(record_index_matching_id).record_index_per_record.begin(),
aqurecords.at(record_index_matching_id).record_index_per_record.end()
);
}
}
const std::unordered_map<int, std::vector<Aquancon::AquancCell>>& Aquancon::data() const {
return this->cells;
}
std::vector<Aquancon::AquanconOutput> Aquancon::logic_application(const std::vector<Aquancon::AquanconOutput>& original_vector)
{
std::vector<Aquancon::AquanconOutput> output_vector = original_vector;
// Create a local struct to couple each element for easy sorting
struct pair_elements
{
size_t global_index;
std::shared_ptr<double> influx_coeff;
double influx_multiplier;
int reservoir_face_dir;
int record_index;
};
// Iterate through each aquifer IDs (This is because each element in the original vector represents an aquifer ID)
for (auto aquconvec = output_vector.begin(); aquconvec != output_vector.end(); ++aquconvec)
{
// Create a working buffer
std::vector<pair_elements> working_buffer;
for (size_t i = 0; i < aquconvec->global_index.size(); ++i )
working_buffer.push_back( { aquconvec->global_index[i],
aquconvec->influx_coeff[i],
aquconvec->influx_multiplier[i],
aquconvec->reservoir_face_dir[i],
aquconvec->record_index[i]});
// Sort by ascending order the working_buffer vector in order of priority:
// 1) global_index, then 2) record_index
std::sort( working_buffer.begin(),
working_buffer.end(),
[](pair_elements& element1, pair_elements& element2) -> bool
{
if (element1.global_index == element2.global_index)
{
return element1.record_index < element2.record_index;
}
else
return element1.global_index < element2.global_index;
}
);
// We then proceed to obtain unique elements of the global_index, and we apply the
// following behaviour (as mentioned in the Eclipse 2014.1 Reference Manual p.345):
// If a reservoir cell is defined more than once, its previous value for the
// aquifer influx coefficient is added to the present value.
auto i2 = std::unique( working_buffer.begin(),
working_buffer.end(),
[](pair_elements& element1, pair_elements& element2) -> bool
{
// Not entirely clear for the manual; but it would seem
// natural that this equality check also included the face?
if (element1.global_index == element2.global_index)
{
if (element1.influx_coeff && element2.influx_coeff)
*(element1.influx_coeff) += *(element2.influx_coeff);
else {
if (element1.influx_coeff || element2.influx_coeff)
throw std::invalid_argument("Sorry - can not combine defaulted and not default AQUANCON records");
}
return true;
}
return false;
}
);
working_buffer.resize( std::distance(working_buffer.begin(),i2) );
// We now resize and fill the output_vector elements
aquconvec->global_index.resize(working_buffer.size());
aquconvec->influx_coeff.resize(working_buffer.size());
aquconvec->influx_multiplier.resize(working_buffer.size());
aquconvec->reservoir_face_dir.resize(working_buffer.size());
aquconvec->record_index.resize(working_buffer.size());
for (size_t i = 0; i < working_buffer.size(); ++i)
{
aquconvec->global_index.at(i) = working_buffer.at(i).global_index;
aquconvec->influx_coeff.at(i) = working_buffer.at(i).influx_coeff;
aquconvec->influx_multiplier.at(i) = working_buffer.at(i).influx_multiplier;
aquconvec->reservoir_face_dir.at(i) = working_buffer.at(i).reservoir_face_dir;
aquconvec->record_index.at(i) = working_buffer.at(i).record_index;
}
}
return output_vector;
bool Aquancon::operator==(const Aquancon& other) const {
return this->cells == other.cells;
}
void Aquancon::convert_record_id_to_aquifer_id(std::vector<int>& record_indices_matching_id,
const int i, const std::vector<int>& aquiferID_per_record)
{
auto it = std::find_if( aquiferID_per_record.begin(), aquiferID_per_record.end(),
[&](int id) {
return id == i;
}
);
while (it != aquiferID_per_record.end()) {
record_indices_matching_id.emplace_back(std::distance(aquiferID_per_record.begin(), it));
it = std::find_if(std::next(it), aquiferID_per_record.end(), [&](int id){return id == i;});
}
}
const std::vector<Aquancon::AquanconOutput>& Aquancon::getAquOutput() const
{
return m_aquoutput;
bool Aquancon::active() const {
return !this->cells.empty();
}
}

View File

@@ -83,6 +83,7 @@ bool AquiferCT::AQUCT_data::operator==(const AquiferCT::AQUCT_data& other) const
this->inftableID == other.inftableID &&
this->pvttableID == other.pvttableID &&
this->phi_aq == other.phi_aq &&
this->d0 == other.d0 &&
this->C_t == other.C_t &&
this->r_o == other.r_o &&
this->k_a == other.k_a &&
@@ -96,6 +97,40 @@ bool AquiferCT::AQUCT_data::operator==(const AquiferCT::AQUCT_data& other) const
this->cell_id == other.cell_id;
}
AquiferCT::AQUCT_data::AQUCT_data(int aqID,
int infID,
int pvtID,
double phi_aq_,
double d0_,
double C_t_,
double r_o_,
double k_a_,
double c1_,
double h_,
double theta_,
double c2_,
const std::pair<bool, double>& p0_,
const std::vector<double>& td_,
const std::vector<double>& pi_,
const std::vector<int>& cell_id_) :
aquiferID(aqID),
inftableID(infID),
pvttableID(pvtID),
phi_aq(phi_aq_),
d0(d0_),
C_t(C_t_),
r_o(r_o_),
k_a(k_a_),
c1(c1_),
h(h_),
theta(theta_),
c2(c2_),
p0(p0_),
td(td_),
pi(pi_),
cell_id(cell_id_)
{}
AquiferCT::AquiferCT(const TableManager& tables, const Deck& deck)
{
using AQUCT = ParserKeywords::AQUCT;

View File

@@ -52,6 +52,18 @@ bool Aquifetp::AQUFETP_data::operator==(const Aquifetp::AQUFETP_data& other) con
this->p0 == other.p0;
}
Aquifetp::AQUFETP_data::AQUFETP_data(int aquiferID_, int pvttableID_, double J_, double C_t_, double V0_, double d0_, const std::pair<bool, double>& p0_) :
aquiferID(aquiferID_),
pvttableID(pvttableID_),
J(J_),
C_t(C_t_),
V0(V0_),
d0(d0_),
p0(p0_)
{}
Aquifetp::Aquifetp(const std::vector<Aquifetp::AQUFETP_data>& data) :
m_aqufetp(data)
{}

View File

@@ -1,230 +0,0 @@
/*
Copyright 2017 TNO.
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 AquanconTest
#include <boost/test/unit_test.hpp>
#include <opm/parser/eclipse/Parser/Parser.hpp>
#include <opm/parser/eclipse/EclipseState/Aquancon.hpp>
using namespace Opm;
inline Deck createAQUANCONDeck_DEFAULT_INFLUX2() {
const char *deckData =
"DIMENS\n"
"3 3 3 /\n"
"\n"
"GRID\n"
"\n"
"ACTNUM\n"
" 0 8*1 0 8*1 0 8*1 /\n"
"DXV\n"
"1 1 1 /\n"
"\n"
"DYV\n"
"1 1 1 /\n"
"\n"
"DZV\n"
"1 1 1 /\n"
"\n"
"TOPS\n"
"9*100 /\n"
"\n"
"PORO\n"
" 27*0.15 /\n"
"SOLUTION\n"
"\n"
"AQUANCON\n"
" 1 2 2 1 1 1 1 J- 1.0 /\n"
" 1 2 2 1 1 1 1 J- /\n"
"/ \n";
Parser parser;
return parser.parseString(deckData);
}
inline Deck createAQUANCONDeck_DEFAULT_INFLUX1() {
const char *deckData =
"DIMENS\n"
"3 3 3 /\n"
"\n"
"GRID\n"
"\n"
"ACTNUM\n"
" 0 8*1 0 8*1 0 8*1 /\n"
"DXV\n"
"1 1 1 /\n"
"\n"
"DYV\n"
"1 1 1 /\n"
"\n"
"DZV\n"
"1 1 1 /\n"
"\n"
"TOPS\n"
"9*100 /\n"
"PORO\n"
" 27*0.15 /\n"
"\n"
"SOLUTION\n"
"\n"
"AQUANCON\n"
" 1 1 1 1 1 1 1 J- /\n"
" 1 1 1 1 1 1 1 J- /\n"
"/ \n";
Parser parser;
return parser.parseString(deckData);
}
inline Deck createAQUANCONDeck() {
const char *deckData =
"DIMENS\n"
"3 3 3 /\n"
"\n"
"GRID\n"
"\n"
"ACTNUM\n"
" 0 8*1 0 8*1 0 8*1 /\n"
"DXV\n"
"1 1 1 /\n"
"\n"
"DYV\n"
"1 1 1 /\n"
"\n"
"DZV\n"
"1 1 1 /\n"
"\n"
"TOPS\n"
"9*100 /\n"
"\n"
"PORO\n"
" 27*0.15 /\n"
"SOLUTION\n"
"\n"
"AQUANCON\n"
" 1 1 1 1 1 1 1 J- 1.0 1.0 NO /\n"
" 1 1 3 1 3 3 3 I+ 0.5 1.0 NO /\n"
" 1 1 3 1 3 3 3 J+ 0.75 1.0 NO /\n"
" 1 1 3 1 3 3 3 J- 2.75 1.0 NO /\n"
" 1 2 3 2 3 1 1 I+ 2.75 1.0 NO /\n"
"/ \n";
Parser parser;
return parser.parseString(deckData);
}
inline std::vector<Aquancon::AquanconOutput> init_aquancon(){
auto deck = createAQUANCONDeck();
EclipseState eclState( deck );
Aquancon aqucon( eclState.getInputGrid(), deck);
std::vector<Aquancon::AquanconOutput> aquifers = aqucon.getAquOutput();
return aquifers;
}
inline std::vector<Aquancon::AquanconOutput> fill_result(){
auto deck = createAQUANCONDeck();
EclipseState eclState( deck );
Aquancon aqucon( eclState.getInputGrid(), deck);
std::vector<Aquancon::AquanconOutput> aquifers = aqucon.getAquOutput();
return aquifers;
}
BOOST_AUTO_TEST_CASE(AquanconTest){
std::vector< Aquancon::AquanconOutput > aquifers = init_aquancon();
std::vector< Aquancon::AquanconOutput > expected_output = fill_result();
BOOST_CHECK_EQUAL(aquifers.size(), expected_output.size());
for (size_t i = 0; i < aquifers.size(); ++i)
{
BOOST_CHECK_EQUAL_COLLECTIONS( aquifers.at(i).global_index.begin(), aquifers.at(i).global_index.end(),
expected_output.at(i).global_index.begin(), expected_output.at(i).global_index.end() );
BOOST_CHECK_EQUAL_COLLECTIONS( aquifers.at(i).influx_multiplier.begin(), aquifers.at(i).influx_multiplier.end(),
expected_output.at(i).influx_multiplier.begin(), expected_output.at(i).influx_multiplier.end() );
BOOST_CHECK_EQUAL_COLLECTIONS( aquifers.at(i).reservoir_face_dir.begin(), aquifers.at(i).reservoir_face_dir.end(),
expected_output.at(i).reservoir_face_dir.begin(), expected_output.at(i).reservoir_face_dir.end() );
BOOST_CHECK_EQUAL_COLLECTIONS( aquifers.at(i).record_index.begin(), aquifers.at(i).record_index.end(),
expected_output.at(i).record_index.begin(), expected_output.at(i).record_index.end() );
}
}
BOOST_AUTO_TEST_CASE(AquanconTest_DEFAULT_INFLUX) {
auto deck1 = createAQUANCONDeck_DEFAULT_INFLUX1();
EclipseState eclState1( deck1 );
BOOST_CHECK_NO_THROW(Aquancon( eclState1.getInputGrid(), deck1));
auto deck2 = createAQUANCONDeck_DEFAULT_INFLUX2();
EclipseState eclState2( deck2 );
BOOST_CHECK_THROW(Aquancon( eclState2.getInputGrid(), deck2), std::invalid_argument);
}
// allowing aquifer exists inside the reservoir
inline Deck createAQUANCONDeck_ALLOW_INSIDE_AQUAN_OR_NOT() {
const char *deckData =
"DIMENS\n"
"3 3 3 /\n"
"\n"
"GRID\n"
"\n"
"ACTNUM\n"
" 0 8*1 0 8*1 0 8*1 /\n"
"DXV\n"
"1 1 1 /\n"
"\n"
"DYV\n"
"1 1 1 /\n"
"\n"
"DZV\n"
"1 1 1 /\n"
"\n"
"TOPS\n"
"9*100 /\n"
"\n"
"PORO\n"
" 27*0.15 /\n"
"SOLUTION\n"
"\n"
"AQUFETP\n"
" 1 20.0 1000.0 2000. 0.000001 200.0 /\n"
" 2 20.0 1000.0 2000. 0.000001 200.0 /\n"
"/\n"
"AQUANCON\n"
" 1 1 1 1 1 1 1 J- 2* YES /\n"
" 1 2 2 1 1 1 1 J- 2* YES /\n"
" 1 2 2 2 2 1 1 J- 2* YES /\n"
" 2 1 1 1 1 3 3 J- 2* NO /\n"
" 2 2 2 1 1 3 3 J- 2* NO /\n"
" 2 2 2 2 2 3 3 J- 2* NO /\n"
"/ \n";
Parser parser;
return parser.parseString(deckData);
}
BOOST_AUTO_TEST_CASE(AquanconTest_ALLOW_AQUIFER_INSIDE_OR_NOT) {
auto deck = createAQUANCONDeck_ALLOW_INSIDE_AQUAN_OR_NOT();
const EclipseState eclState( deck );
const Aquancon aqucon( eclState.getInputGrid(), deck);
const std::vector<Aquancon::AquanconOutput>& aquifer_cons = aqucon.getAquOutput();
BOOST_CHECK_EQUAL(aquifer_cons[0].global_index.size(), 2);
BOOST_CHECK_EQUAL(aquifer_cons[1].global_index.size(), 1);
}

View File

@@ -1,35 +0,0 @@
/*
Copyright (C) 2017 TNO
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 AQUDIMS_TESTS
#include <boost/test/unit_test.hpp>
#include <opm/parser/eclipse/EclipseState/Tables/Aqudims.hpp>
BOOST_AUTO_TEST_CASE(TEST_CREATE) {
Opm::Aqudims aqudims;
BOOST_CHECK_EQUAL( aqudims.getNumAqunum() , 1 );
BOOST_CHECK_EQUAL( aqudims.getNumConnectionNumericalAquifer() , 1 );
BOOST_CHECK_EQUAL( aqudims.getNumInfluenceTablesCT() , 1 );
BOOST_CHECK_EQUAL( aqudims.getNumRowsInfluenceTable() , 36 );
BOOST_CHECK_EQUAL( aqudims.getNumAnalyticAquifers() , 1 );
BOOST_CHECK_EQUAL( aqudims.getNumRowsAquancon() , 1 );
BOOST_CHECK_EQUAL( aqudims.getNumAquiferLists() , 0 );
BOOST_CHECK_EQUAL( aqudims.getNumAnalyticAquifersSingleList() , 0 );
}

View File

@@ -1,134 +0,0 @@
/*
Copyright 2017 TNO.
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 AquiferCTTest
#include <boost/test/unit_test.hpp>
#include <opm/parser/eclipse/Parser/Parser.hpp>
#include <opm/parser/eclipse/EclipseState/AquiferCT.hpp>
using namespace Opm;
inline Deck createAquiferCTDeck() {
const char *deckData =
"DIMENS\n"
"3 3 3 /\n"
"\n"
"AQUDIMS\n"
"1* 1* 2 100 1 1000 /\n"
"GRID\n"
"\n"
"ACTNUM\n"
" 0 8*1 0 8*1 0 8*1 /\n"
"DXV\n"
"1 1 1 /\n"
"\n"
"DYV\n"
"1 1 1 /\n"
"\n"
"DZV\n"
"1 1 1 /\n"
"\n"
"TOPS\n"
"9*100 /\n"
"\n"
"PORO\n"
" 27*0.15 /\n"
"PROPS\n"
"AQUTAB\n"
" 0.01 0.112 \n"
" 0.05 0.229 /\n"
"SOLUTION\n"
"\n"
"AQUCT\n"
" 1 2000.0 1.5 100 .3 3.0e-5 330 10 360.0 1 2 /\n"
"/ \n";
Parser parser;
return parser.parseString(deckData);
}
inline Deck createAquiferCTDeckDefaultP0() {
const char *deckData =
"DIMENS\n"
"3 3 3 /\n"
"\n"
"AQUDIMS\n"
"1* 1* 2 100 1 1000 /\n"
"GRID\n"
"\n"
"ACTNUM\n"
" 0 8*1 0 8*1 0 8*1 /\n"
"DXV\n"
"1 1 1 /\n"
"\n"
"DYV\n"
"1 1 1 /\n"
"\n"
"DZV\n"
"1 1 1 /\n"
"\n"
"TOPS\n"
"9*100 /\n"
"\n"
"PORO\n"
" 27*0.15 /\n"
"PROPS\n"
"AQUTAB\n"
" 0.01 0.112 \n"
" 0.05 0.229 /\n"
"SOLUTION\n"
"\n"
"AQUCT\n"
" 1 2000.0 1* 100 .3 3.0e-5 330 10 360.0 1 2 /\n"
"/ \n";
Parser parser;
return parser.parseString(deckData);
}
AquiferCT init_aquiferct(const Deck& deck){
EclipseState eclState( deck );
return AquiferCT(eclState.getTableManager(), deck);
}
BOOST_AUTO_TEST_CASE(AquiferCTTest){
auto deck = createAquiferCTDeck();
{
auto aquiferct = init_aquiferct(deck);
for (const auto& it : aquiferct){
BOOST_CHECK_EQUAL(it.aquiferID , 1);
BOOST_CHECK_EQUAL(it.phi_aq , 0.3);
BOOST_CHECK_EQUAL(it.inftableID , 2);
BOOST_CHECK(it.p0.first == true);
BOOST_CHECK_CLOSE(it.p0.second, 1.5e5, 1e-6);
}
BOOST_CHECK_EQUAL(aquiferct.size(), 1);
}
auto deck_default_p0 = createAquiferCTDeckDefaultP0();
{
auto aquiferct = init_aquiferct(deck_default_p0);
for (const auto& it : aquiferct){
BOOST_CHECK_EQUAL(it.aquiferID , 1);
BOOST_CHECK_EQUAL(it.phi_aq , 0.3);
BOOST_CHECK_EQUAL(it.inftableID , 2);
BOOST_CHECK(it.p0.first == false);
}
auto data = aquiferct.data();
AquiferCT aq2(data);
BOOST_CHECK( aq2 == aquiferct );
}
}

View File

@@ -0,0 +1,523 @@
/*
Copyright 2017 TNO.
Copyright 2020 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 AquiferCTTest
#include <boost/test/unit_test.hpp>
#include <opm/parser/eclipse/Parser/Parser.hpp>
#include <opm/parser/eclipse/EclipseState/Aquancon.hpp>
#include <opm/parser/eclipse/EclipseState/AquiferCT.hpp>
#include <opm/parser/eclipse/EclipseState/Aquifetp.hpp>
using namespace Opm;
inline Deck createAquiferCTDeck() {
const char *deckData =
"DIMENS\n"
"3 3 3 /\n"
"\n"
"AQUDIMS\n"
"1* 1* 2 100 1 1000 /\n"
"GRID\n"
"\n"
"ACTNUM\n"
" 0 8*1 0 8*1 0 8*1 /\n"
"DXV\n"
"1 1 1 /\n"
"\n"
"DYV\n"
"1 1 1 /\n"
"\n"
"DZV\n"
"1 1 1 /\n"
"\n"
"TOPS\n"
"9*100 /\n"
"\n"
"PORO\n"
" 27*0.15 /\n"
"PROPS\n"
"AQUTAB\n"
" 0.01 0.112 \n"
" 0.05 0.229 /\n"
"SOLUTION\n"
"\n"
"AQUCT\n"
" 1 2000.0 1.5 100 .3 3.0e-5 330 10 360.0 1 2 /\n"
"/ \n";
Parser parser;
return parser.parseString(deckData);
}
inline Deck createAquiferCTDeckDefaultP0() {
const char *deckData =
"DIMENS\n"
"3 3 3 /\n"
"\n"
"AQUDIMS\n"
"1* 1* 2 100 1 1000 /\n"
"GRID\n"
"\n"
"ACTNUM\n"
" 0 8*1 0 8*1 0 8*1 /\n"
"DXV\n"
"1 1 1 /\n"
"\n"
"DYV\n"
"1 1 1 /\n"
"\n"
"DZV\n"
"1 1 1 /\n"
"\n"
"TOPS\n"
"9*100 /\n"
"\n"
"PORO\n"
" 27*0.15 /\n"
"PROPS\n"
"AQUTAB\n"
" 0.01 0.112 \n"
" 0.05 0.229 /\n"
"SOLUTION\n"
"\n"
"AQUCT\n"
" 1 2000.0 1* 100 .3 3.0e-5 330 10 360.0 1 2 /\n"
"/ \n";
Parser parser;
return parser.parseString(deckData);
}
AquiferCT init_aquiferct(const Deck& deck){
EclipseState eclState( deck );
return AquiferCT(eclState.getTableManager(), deck);
}
BOOST_AUTO_TEST_CASE(AquiferCTTest){
auto deck = createAquiferCTDeck();
{
auto aquiferct = init_aquiferct(deck);
for (const auto& it : aquiferct){
BOOST_CHECK_EQUAL(it.aquiferID , 1);
BOOST_CHECK_EQUAL(it.phi_aq , 0.3);
BOOST_CHECK_EQUAL(it.inftableID , 2);
BOOST_CHECK(it.p0.first == true);
BOOST_CHECK_CLOSE(it.p0.second, 1.5e5, 1e-6);
}
BOOST_CHECK_EQUAL(aquiferct.size(), 1);
}
auto deck_default_p0 = createAquiferCTDeckDefaultP0();
{
auto aquiferct = init_aquiferct(deck_default_p0);
for (const auto& it : aquiferct){
BOOST_CHECK_EQUAL(it.aquiferID , 1);
BOOST_CHECK_EQUAL(it.phi_aq , 0.3);
BOOST_CHECK_EQUAL(it.inftableID , 2);
BOOST_CHECK(it.p0.first == false);
}
auto data = aquiferct.data();
AquiferCT aq2(data);
BOOST_CHECK( aq2 == aquiferct );
}
}
inline Deck createAQUANCONDeck_DEFAULT_INFLUX2() {
const char *deckData =
"DIMENS\n"
"3 3 3 /\n"
"\n"
"GRID\n"
"\n"
"ACTNUM\n"
" 0 8*1 0 8*1 0 8*1 /\n"
"DXV\n"
"1 1 1 /\n"
"\n"
"DYV\n"
"1 1 1 /\n"
"\n"
"DZV\n"
"1 1 1 /\n"
"\n"
"TOPS\n"
"9*100 /\n"
"\n"
"PORO\n"
" 27*0.15 /\n"
"SOLUTION\n"
"\n"
"AQUANCON\n"
" 1 2 2 1 1 1 1 J- 1.0 /\n"
" 1 2 2 1 1 1 1 J- /\n"
"/ \n";
Parser parser;
return parser.parseString(deckData);
}
inline Deck createAQUANCONDeck_DEFAULT_INFLUX1() {
const char *deckData =
"DIMENS\n"
"3 3 3 /\n"
"\n"
"GRID\n"
"\n"
"ACTNUM\n"
" 0 8*1 0 8*1 0 8*1 /\n"
"DXV\n"
"1 1 1 /\n"
"\n"
"DYV\n"
"1 1 1 /\n"
"\n"
"DZV\n"
"1 1 1 /\n"
"\n"
"TOPS\n"
"9*100 /\n"
"PORO\n"
" 27*0.15 /\n"
"\n"
"SOLUTION\n"
"\n"
"AQUANCON\n"
" 1 1 3 1 1 1 1 J- /\n"
"/\n"
"AQUANCON\n"
" 2 1 1 2 2 1 1 J- /\n"
"/ \n";
Parser parser;
return parser.parseString(deckData);
}
inline Deck createAQUANCONDeck_DEFAULT_ILLEGAL() {
const char *deckData =
"DIMENS\n"
"3 3 3 /\n"
"\n"
"GRID\n"
"\n"
"ACTNUM\n"
" 0 8*1 0 8*1 0 8*1 /\n"
"DXV\n"
"1 1 1 /\n"
"\n"
"DYV\n"
"1 1 1 /\n"
"\n"
"DZV\n"
"1 1 1 /\n"
"\n"
"TOPS\n"
"9*100 /\n"
"PORO\n"
" 27*0.15 /\n"
"\n"
"SOLUTION\n"
"\n"
"AQUANCON\n"
" 1 1 3 1 1 1 1 J- /\n"
"/\n"
"AQUANCON\n"
" 2 1 2 1 2 1 1 J- /\n"
"/ \n";
Parser parser;
return parser.parseString(deckData);
}
inline Deck createAQUANCONDeck() {
const char *deckData =
"DIMENS\n"
"3 3 3 /\n"
"\n"
"GRID\n"
"\n"
"ACTNUM\n"
" 0 8*1 0 8*1 0 8*1 /\n"
"DXV\n"
"1 1 1 /\n"
"\n"
"DYV\n"
"1 1 1 /\n"
"\n"
"DZV\n"
"1 1 1 /\n"
"\n"
"TOPS\n"
"9*100 /\n"
"\n"
"PORO\n"
" 27*0.15 /\n"
"SOLUTION\n"
"\n"
"AQUANCON\n"
" 1 1 1 1 1 1 1 J- 1.0 1.0 NO /\n"
" 1 1 3 1 3 3 3 I+ 0.5 1.0 NO /\n"
" 1 1 3 1 3 3 3 J+ 0.75 1.0 NO /\n"
" 1 1 3 1 3 3 3 J- 2.75 1.0 NO /\n"
" 1 2 3 2 3 1 1 I+ 2.75 1.0 NO /\n"
"/ \n";
Parser parser;
return parser.parseString(deckData);
}
BOOST_AUTO_TEST_CASE(AquanconTest_DEFAULT_INFLUX) {
auto deck1 = createAQUANCONDeck_DEFAULT_INFLUX1();
EclipseState eclState1( deck1 );
Aquancon aqcon(eclState1.getInputGrid(), deck1);
const auto& cells_aq1 = aqcon[1];
/*
The cells I = 0..2 are connected to aquifer 1; cell I==0 is inactive and
not counted here ==> a total of 2 cells are connected to aquifer 1.
*/
BOOST_CHECK_EQUAL(cells_aq1.size(), 2);
const auto& cells_aq2 = aqcon[2];
BOOST_CHECK_EQUAL(cells_aq2.size(), 1);
BOOST_CHECK(aqcon.active());
auto deck2 = createAQUANCONDeck_DEFAULT_INFLUX2();
EclipseState eclState2( deck2 );
BOOST_CHECK_THROW(Aquancon( eclState2.getInputGrid(), deck2), std::invalid_argument);
// The cell (2,1,1) is attached to both aquifer 1 and aquifer 2 - that is illegal.
auto deck3 = createAQUANCONDeck_DEFAULT_ILLEGAL();
EclipseState eclState3( deck3 );
BOOST_CHECK_THROW(Aquancon( eclState3.getInputGrid(), deck3), std::invalid_argument);
}
// allowing aquifer exists inside the reservoir
inline Deck createAQUANCONDeck_ALLOW_INSIDE_AQUAN_OR_NOT() {
const char *deckData =
"DIMENS\n"
"3 3 3 /\n"
"\n"
"GRID\n"
"\n"
"ACTNUM\n"
" 0 8*1 0 8*1 0 8*1 /\n"
"DXV\n"
"1 1 1 /\n"
"\n"
"DYV\n"
"1 1 1 /\n"
"\n"
"DZV\n"
"1 1 1 /\n"
"\n"
"TOPS\n"
"9*100 /\n"
"\n"
"PORO\n"
" 27*0.15 /\n"
"SOLUTION\n"
"\n"
"AQUFETP\n"
" 1 20.0 1000.0 2000. 0.000001 200.0 /\n"
" 2 20.0 1000.0 2000. 0.000001 200.0 /\n"
"/\n"
"AQUANCON\n"
" 1 1 1 1 1 1 1 J- 2* YES /\n"
" 1 2 2 1 1 1 1 J- 2* YES /\n"
" 1 2 2 2 2 1 1 J- 2* YES /\n"
" 2 1 1 1 1 3 3 J- 2* NO /\n"
" 2 2 2 1 1 3 3 J- 2* NO /\n"
" 2 2 2 2 2 3 3 J- 2* NO /\n"
"/ \n";
Parser parser;
return parser.parseString(deckData);
}
BOOST_AUTO_TEST_CASE(AquanconTest_ALLOW_AQUIFER_INSIDE_OR_NOT) {
auto deck = createAQUANCONDeck_ALLOW_INSIDE_AQUAN_OR_NOT();
const EclipseState eclState( deck );
const Aquancon aqucon( eclState.getInputGrid(), deck);
const auto& data = aqucon.data();
const Aquancon aq2(data);
BOOST_CHECK(aqucon == aq2);
auto cells1 = aqucon[1];
auto cells2 = aqucon[2];
BOOST_CHECK_EQUAL(cells1.size() , 2);
BOOST_CHECK_EQUAL(cells2.size() , 1);
}
inline Deck createAquifetpDeck() {
const char *deckData =
"DIMENS\n"
"3 3 3 /\n"
"\n"
"AQUDIMS\n"
"1* 1* 2 100 1 1000 /\n"
"GRID\n"
"\n"
"ACTNUM\n"
" 0 8*1 0 8*1 0 8*1 /\n"
"DXV\n"
"1 1 1 /\n"
"\n"
"DYV\n"
"1 1 1 /\n"
"\n"
"DZV\n"
"1 1 1 /\n"
"\n"
"TOPS\n"
"9*100 /\n"
"\n"
"PROPS\n"
"AQUTAB\n"
" 0.01 0.112 \n"
" 0.05 0.229 /\n"
"SOLUTION\n"
"\n"
"AQUFETP\n"
"1 70000.0 4.0e3 2.0e9 1.0e-5 500 1 0 0 /\n"
"/\n";
Parser parser;
return parser.parseString(deckData);
}
inline Deck createNullAquifetpDeck(){
const char *deckData =
"DIMENS\n"
"3 3 3 /\n"
"\n"
"AQUDIMS\n"
"1* 1* 2 100 1 1000 /\n"
"GRID\n"
"\n"
"ACTNUM\n"
" 0 8*1 0 8*1 0 8*1 /\n"
"DXV\n"
"1 1 1 /\n"
"\n"
"DYV\n"
"1 1 1 /\n"
"\n"
"DZV\n"
"1 1 1 /\n"
"\n"
"TOPS\n"
"9*100 /\n"
"\n"
"PROPS\n"
"AQUTAB\n"
" 0.01 0.112 \n"
" 0.05 0.229 /\n"
"SOLUTION\n"
;
Parser parser;
return parser.parseString(deckData);
}
inline Deck createAquifetpDeck_defaultPressure(){
const char *deckData =
"DIMENS\n"
"3 3 3 /\n"
"\n"
"AQUDIMS\n"
"1* 1* 2 100 1 1000 /\n"
"GRID\n"
"\n"
"ACTNUM\n"
" 0 8*1 0 8*1 0 8*1 /\n"
"DXV\n"
"1 1 1 /\n"
"\n"
"DYV\n"
"1 1 1 /\n"
"\n"
"DZV\n"
"1 1 1 /\n"
"\n"
"TOPS\n"
"9*100 /\n"
"\n"
"PROPS\n"
"AQUTAB\n"
" 0.01 0.112 \n"
" 0.05 0.229 /\n"
"SOLUTION\n"
"\n"
"AQUFETP\n"
"1 70000.0 1* 2.0e9 1.0e-5 500 1 0 0 /\n"
"/\n";
Parser parser;
return parser.parseString(deckData);
}
inline Aquifetp init_aquifetp(Deck& deck){
Aquifetp aqufetp(deck);
return aqufetp;
}
BOOST_AUTO_TEST_CASE(AquifetpTest){
auto aqufetp_deck = createAquifetpDeck();
const auto& aquifetp = init_aquifetp(aqufetp_deck);
for (const auto& it : aquifetp){
BOOST_CHECK_EQUAL(it.aquiferID , 1);
BOOST_CHECK_EQUAL(it.V0, 2.0e9);
BOOST_CHECK_EQUAL(it.J, 500/86400e5);
BOOST_CHECK( it.p0.first );
}
const auto& data = aquifetp.data();
Aquifetp aq2(data);
BOOST_CHECK(aq2 == aquifetp);
auto aqufetp_deck_null = createNullAquifetpDeck();
const auto& aquifetp_null = init_aquifetp(aqufetp_deck_null);
BOOST_CHECK_EQUAL(aquifetp_null.size(), 0);
auto aqufetp_deck_default = createAquifetpDeck_defaultPressure();
const auto& aquifetp_default = init_aquifetp(aqufetp_deck_default);
for (const auto& it : aquifetp_default){
BOOST_CHECK_EQUAL(it.aquiferID , 1);
BOOST_CHECK_EQUAL(it.V0, 2.0e9);
BOOST_CHECK_EQUAL(it.J, 500/86400e5);
BOOST_CHECK( !it.p0.first );
}
}
BOOST_AUTO_TEST_CASE(TEST_CREATE) {
Opm::Aqudims aqudims;
BOOST_CHECK_EQUAL( aqudims.getNumAqunum() , 1 );
BOOST_CHECK_EQUAL( aqudims.getNumConnectionNumericalAquifer() , 1 );
BOOST_CHECK_EQUAL( aqudims.getNumInfluenceTablesCT() , 1 );
BOOST_CHECK_EQUAL( aqudims.getNumRowsInfluenceTable() , 36 );
BOOST_CHECK_EQUAL( aqudims.getNumAnalyticAquifers() , 1 );
BOOST_CHECK_EQUAL( aqudims.getNumRowsAquancon() , 1 );
BOOST_CHECK_EQUAL( aqudims.getNumAquiferLists() , 0 );
BOOST_CHECK_EQUAL( aqudims.getNumAnalyticAquifersSingleList() , 0 );
}

View File

@@ -1,163 +0,0 @@
/*
Copyright 2017 TNO.
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 AquifetpTests
#include <boost/test/unit_test.hpp>
#include <opm/parser/eclipse/Parser/Parser.hpp>
#include <opm/parser/eclipse/EclipseState/Aquifetp.hpp>
using namespace Opm;
inline Deck createAquifetpDeck() {
const char *deckData =
"DIMENS\n"
"3 3 3 /\n"
"\n"
"AQUDIMS\n"
"1* 1* 2 100 1 1000 /\n"
"GRID\n"
"\n"
"ACTNUM\n"
" 0 8*1 0 8*1 0 8*1 /\n"
"DXV\n"
"1 1 1 /\n"
"\n"
"DYV\n"
"1 1 1 /\n"
"\n"
"DZV\n"
"1 1 1 /\n"
"\n"
"TOPS\n"
"9*100 /\n"
"\n"
"PROPS\n"
"AQUTAB\n"
" 0.01 0.112 \n"
" 0.05 0.229 /\n"
"SOLUTION\n"
"\n"
"AQUFETP\n"
"1 70000.0 4.0e3 2.0e9 1.0e-5 500 1 0 0 /\n"
"/\n";
Parser parser;
return parser.parseString(deckData);
}
inline Deck createNullAquifetpDeck(){
const char *deckData =
"DIMENS\n"
"3 3 3 /\n"
"\n"
"AQUDIMS\n"
"1* 1* 2 100 1 1000 /\n"
"GRID\n"
"\n"
"ACTNUM\n"
" 0 8*1 0 8*1 0 8*1 /\n"
"DXV\n"
"1 1 1 /\n"
"\n"
"DYV\n"
"1 1 1 /\n"
"\n"
"DZV\n"
"1 1 1 /\n"
"\n"
"TOPS\n"
"9*100 /\n"
"\n"
"PROPS\n"
"AQUTAB\n"
" 0.01 0.112 \n"
" 0.05 0.229 /\n"
"SOLUTION\n"
;
Parser parser;
return parser.parseString(deckData);
}
inline Deck createAquifetpDeck_defaultPressure(){
const char *deckData =
"DIMENS\n"
"3 3 3 /\n"
"\n"
"AQUDIMS\n"
"1* 1* 2 100 1 1000 /\n"
"GRID\n"
"\n"
"ACTNUM\n"
" 0 8*1 0 8*1 0 8*1 /\n"
"DXV\n"
"1 1 1 /\n"
"\n"
"DYV\n"
"1 1 1 /\n"
"\n"
"DZV\n"
"1 1 1 /\n"
"\n"
"TOPS\n"
"9*100 /\n"
"\n"
"PROPS\n"
"AQUTAB\n"
" 0.01 0.112 \n"
" 0.05 0.229 /\n"
"SOLUTION\n"
"\n"
"AQUFETP\n"
"1 70000.0 1* 2.0e9 1.0e-5 500 1 0 0 /\n"
"/\n";
Parser parser;
return parser.parseString(deckData);
}
inline Aquifetp init_aquifetp(Deck& deck){
Aquifetp aqufetp(deck);
return aqufetp;
}
BOOST_AUTO_TEST_CASE(AquifetpTest){
auto aqufetp_deck = createAquifetpDeck();
const auto& aquifetp = init_aquifetp(aqufetp_deck);
for (const auto& it : aquifetp){
BOOST_CHECK_EQUAL(it.aquiferID , 1);
BOOST_CHECK_EQUAL(it.V0, 2.0e9);
BOOST_CHECK_EQUAL(it.J, 500/86400e5);
BOOST_CHECK( it.p0.first );
}
const auto& data = aquifetp.data();
Aquifetp aq2(data);
BOOST_CHECK(aq2 == aquifetp);
auto aqufetp_deck_null = createNullAquifetpDeck();
const auto& aquifetp_null = init_aquifetp(aqufetp_deck_null);
BOOST_CHECK_EQUAL(aquifetp_null.size(), 0);
auto aqufetp_deck_default = createAquifetpDeck_defaultPressure();
const auto& aquifetp_default = init_aquifetp(aqufetp_deck_default);
for (const auto& it : aquifetp_default){
BOOST_CHECK_EQUAL(it.aquiferID , 1);
BOOST_CHECK_EQUAL(it.V0, 2.0e9);
BOOST_CHECK_EQUAL(it.J, 500/86400e5);
BOOST_CHECK( !it.p0.first );
}
}