Merge pull request #2477 from bska/count-aqunum-records
Track AQUNUM Records for Restart Purposes
This commit is contained in:
commit
f259f78788
@ -20,6 +20,7 @@
|
||||
#ifndef OPM_NUMERICALAQUIFERCELL_HPP
|
||||
#define OPM_NUMERICALAQUIFERCELL_HPP
|
||||
|
||||
#include <cstddef>
|
||||
#include <optional>
|
||||
|
||||
namespace Opm {
|
||||
@ -28,19 +29,20 @@ namespace Opm {
|
||||
class FieldPropsManager;
|
||||
|
||||
struct NumericalAquiferCell {
|
||||
NumericalAquiferCell(const DeckRecord&, const EclipseGrid&, const FieldPropsManager&);
|
||||
NumericalAquiferCell(const std::size_t record_id_, const DeckRecord&, const EclipseGrid&, const FieldPropsManager&);
|
||||
NumericalAquiferCell() = default;
|
||||
size_t aquifer_id;
|
||||
size_t I, J, K;
|
||||
double area;
|
||||
double length;
|
||||
double porosity;
|
||||
double permeability;
|
||||
double depth;
|
||||
std::optional<double> init_pressure;
|
||||
int pvttable;
|
||||
int sattable;
|
||||
size_t global_index;
|
||||
std::size_t aquifer_id{};
|
||||
std::size_t I{}, J{}, K{};
|
||||
double area{};
|
||||
double length{};
|
||||
double porosity{};
|
||||
double permeability{};
|
||||
double depth{};
|
||||
std::optional<double> init_pressure{};
|
||||
int pvttable{};
|
||||
int sattable{};
|
||||
std::size_t global_index{};
|
||||
std::size_t record_id{};
|
||||
|
||||
double cellVolume() const;
|
||||
double poreVolume() const;
|
||||
@ -62,6 +64,7 @@ namespace Opm {
|
||||
serializer(this->pvttable);
|
||||
serializer(this->sattable);
|
||||
serializer(this->global_index);
|
||||
serializer(this->record_id);
|
||||
}
|
||||
};
|
||||
}
|
||||
|
@ -20,8 +20,10 @@
|
||||
#ifndef OPM_NUMERICALAQUIFERS_HPP
|
||||
#define OPM_NUMERICALAQUIFERS_HPP
|
||||
|
||||
#include <unordered_map>
|
||||
#include <map>
|
||||
#include <unordered_map>
|
||||
|
||||
#include <stddef.h>
|
||||
|
||||
#include <opm/parser/eclipse/EclipseState/Aquifer/NumericalAquifer/SingleNumericalAquifer.hpp>
|
||||
|
||||
@ -36,6 +38,7 @@ namespace Opm {
|
||||
NumericalAquifers() = default;
|
||||
NumericalAquifers(const Deck& deck, const EclipseGrid& grid, const FieldPropsManager& field_props);
|
||||
|
||||
int numRecords() const { return static_cast<int>(this->m_num_records); }
|
||||
size_t size() const;
|
||||
bool hasAquifer(size_t aquifer_id) const;
|
||||
const SingleNumericalAquifer& getAquifer(size_t aquifer_id) const;
|
||||
@ -59,10 +62,12 @@ namespace Opm {
|
||||
void serializeOp(Serializer& serializer)
|
||||
{
|
||||
serializer.map(this->m_aquifers);
|
||||
serializer(this->m_num_records);
|
||||
}
|
||||
|
||||
private:
|
||||
std::map<size_t, SingleNumericalAquifer> m_aquifers;
|
||||
std::map<size_t, SingleNumericalAquifer> m_aquifers{};
|
||||
size_t m_num_records{0};
|
||||
|
||||
void addAquiferCell(const NumericalAquiferCell& aqu_cell);
|
||||
};
|
||||
|
@ -27,21 +27,24 @@
|
||||
namespace Opm {
|
||||
|
||||
using AQUNUM = ParserKeywords::AQUNUM;
|
||||
NumericalAquiferCell::NumericalAquiferCell(const DeckRecord& record, const EclipseGrid& grid, const FieldPropsManager& field_props)
|
||||
: aquifer_id( record.getItem<AQUNUM::AQUIFER_ID>().get<int>(0) )
|
||||
, I ( record.getItem<AQUNUM::I>().get<int>(0) - 1 )
|
||||
, J ( record.getItem<AQUNUM::J>().get<int>(0) - 1 )
|
||||
, K ( record.getItem<AQUNUM::K>().get<int>(0) - 1 )
|
||||
, area (record.getItem<AQUNUM::CROSS_SECTION>().getSIDouble(0) )
|
||||
, length ( record.getItem<AQUNUM::LENGTH>().getSIDouble(0) )
|
||||
, permeability( record.getItem<AQUNUM::PERM>().getSIDouble(0) )
|
||||
NumericalAquiferCell::NumericalAquiferCell(const std::size_t record_id_,
|
||||
const DeckRecord& record,
|
||||
const EclipseGrid& grid,
|
||||
const FieldPropsManager& field_props)
|
||||
: aquifer_id( record.getItem<AQUNUM::AQUIFER_ID>().get<int>(0) )
|
||||
, I ( record.getItem<AQUNUM::I>().get<int>(0) - 1 )
|
||||
, J ( record.getItem<AQUNUM::J>().get<int>(0) - 1 )
|
||||
, K ( record.getItem<AQUNUM::K>().get<int>(0) - 1 )
|
||||
, area (record.getItem<AQUNUM::CROSS_SECTION>().getSIDouble(0) )
|
||||
, length ( record.getItem<AQUNUM::LENGTH>().getSIDouble(0) )
|
||||
, permeability( record.getItem<AQUNUM::PERM>().getSIDouble(0) )
|
||||
{
|
||||
const auto& poro = field_props.get_double("PORO");
|
||||
const auto& pvtnum = field_props.get_int("PVTNUM");
|
||||
const auto& satnum = field_props.get_int("SATNUM");
|
||||
|
||||
this->global_index = grid.getGlobalIndex(I, J, K);
|
||||
const size_t active_index = grid.activeIndex(this->global_index);
|
||||
const std::size_t active_index = grid.activeIndex(this->global_index);
|
||||
|
||||
if ( !record.getItem<AQUNUM::PORO>().defaultApplied(0) ) {
|
||||
this->porosity = record.getItem<AQUNUM::PORO>().getSIDouble(0);
|
||||
@ -70,6 +73,8 @@ namespace Opm {
|
||||
} else {
|
||||
this->sattable = satnum[active_index];
|
||||
}
|
||||
|
||||
this->record_id = record_id_;
|
||||
}
|
||||
|
||||
double NumericalAquiferCell::cellVolume() const {
|
||||
@ -89,7 +94,8 @@ namespace Opm {
|
||||
this->init_pressure == other.init_pressure &&
|
||||
this->pvttable == other.pvttable &&
|
||||
this->sattable == other.sattable &&
|
||||
this->global_index == other.global_index;
|
||||
this->global_index == other.global_index &&
|
||||
this->record_id == other.record_id;
|
||||
}
|
||||
|
||||
double NumericalAquiferCell::poreVolume() const {
|
||||
|
@ -17,38 +17,42 @@
|
||||
along with OPM. If not, see <http://www.gnu.org/licenses/>.
|
||||
*/
|
||||
|
||||
#include <opm/parser/eclipse/Parser/ParserKeywords/A.hpp>
|
||||
#include <opm/parser/eclipse/EclipseState/Aquifer/NumericalAquifer/NumericalAquifers.hpp>
|
||||
|
||||
#include <opm/parser/eclipse/EclipseState/Aquifer/NumericalAquifer/NumericalAquiferCell.hpp>
|
||||
#include <opm/parser/eclipse/EclipseState/Aquifer/NumericalAquifer/SingleNumericalAquifer.hpp>
|
||||
|
||||
#include <opm/parser/eclipse/EclipseState/Grid/NNC.hpp>
|
||||
#include <opm/parser/eclipse/EclipseState/Grid/EclipseGrid.hpp>
|
||||
|
||||
#include <fmt/format.h>
|
||||
#include <opm/common/utility/OpmInputError.hpp>
|
||||
#include <opm/common/OpmLog/OpmLog.hpp>
|
||||
#include <opm/common/OpmLog/KeywordLocation.hpp>
|
||||
|
||||
#include <opm/parser/eclipse/Deck/Deck.hpp>
|
||||
#include <opm/parser/eclipse/EclipseState/Grid/NNC.hpp>
|
||||
#include <opm/parser/eclipse/EclipseState/Grid/EclipseGrid.hpp>
|
||||
|
||||
#include <opm/parser/eclipse/EclipseState/Aquifer/NumericalAquifer/NumericalAquiferCell.hpp>
|
||||
#include <opm/parser/eclipse/EclipseState/Aquifer/NumericalAquifer/NumericalAquifers.hpp>
|
||||
#include <opm/parser/eclipse/EclipseState/Aquifer/NumericalAquifer/SingleNumericalAquifer.hpp>
|
||||
#include <opm/parser/eclipse/Parser/ParserKeywords/A.hpp>
|
||||
|
||||
#include <set>
|
||||
#include <fmt/format.h>
|
||||
|
||||
#include <cstddef>
|
||||
#include <unordered_set>
|
||||
|
||||
namespace Opm {
|
||||
|
||||
NumericalAquifers::NumericalAquifers(const Deck& deck, const EclipseGrid& grid,
|
||||
const FieldPropsManager& field_props) {
|
||||
const FieldPropsManager& field_props)
|
||||
{
|
||||
using AQUNUM=ParserKeywords::AQUNUM;
|
||||
if ( !deck.hasKeyword<AQUNUM>() ) return;
|
||||
|
||||
std::set<size_t> cells;
|
||||
std::unordered_set<std::size_t> cells;
|
||||
// there might be multiple keywords of keyword AQUNUM, it is not totally
|
||||
// clear about the rules here. For now, we take care of all the keywords
|
||||
const auto& aqunum_keywords = deck.getKeywordList<AQUNUM>();
|
||||
for (const auto& keyword : aqunum_keywords) {
|
||||
for (const auto& record : *keyword) {
|
||||
const NumericalAquiferCell aqu_cell(record, grid, field_props);
|
||||
const NumericalAquiferCell aqu_cell(this->m_num_records++, record, grid, field_props);
|
||||
if (cells.count(aqu_cell.global_index) > 0) {
|
||||
auto error = fmt::format("Numerical aquifer cell at ({}, {}, {}) is declared more than once",
|
||||
aqu_cell.I + 1, aqu_cell.J + 1, aqu_cell.K + 1);
|
||||
@ -115,7 +119,8 @@ namespace Opm {
|
||||
}
|
||||
|
||||
bool NumericalAquifers::operator==(const NumericalAquifers& other) const {
|
||||
return this->m_aquifers == other.m_aquifers;
|
||||
return (this->m_aquifers == other.m_aquifers)
|
||||
&& (this->m_num_records == other.m_num_records);
|
||||
}
|
||||
|
||||
size_t NumericalAquifers::size() const {
|
||||
@ -196,4 +201,4 @@ namespace Opm {
|
||||
aquifer.postProcessConnections(grid, actnum);
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
@ -25,6 +25,8 @@ along with OPM. If not, see <http://www.gnu.org/licenses/>.
|
||||
#include <opm/parser/eclipse/EclipseState/Aquifer/Aquifetp.hpp>
|
||||
#include <opm/parser/eclipse/EclipseState/Aquifer/AquiferConfig.hpp>
|
||||
|
||||
#include <opm/parser/eclipse/Units/Units.hpp>
|
||||
|
||||
using namespace Opm;
|
||||
|
||||
|
||||
@ -717,6 +719,64 @@ BOOST_AUTO_TEST_CASE(NumericalAquiferTest){
|
||||
const Opm::EclipseGrid& grid = ecl_state.getInputGrid();
|
||||
|
||||
Opm::NumericalAquifers num_aqu{numaquifer_deck, grid, ecl_state.fieldProps()};
|
||||
|
||||
BOOST_CHECK_EQUAL(num_aqu.numRecords(), 3);
|
||||
{
|
||||
const auto mD = unit::convert::from(1.0, prefix::milli*unit::darcy);
|
||||
|
||||
const auto* c1 = num_aqu.getAquifer(1).getCellPrt(0);
|
||||
const auto* c2 = num_aqu.getAquifer(1).getCellPrt(1);
|
||||
const auto* c3 = num_aqu.getAquifer(1).getCellPrt(2);
|
||||
|
||||
BOOST_CHECK_EQUAL(c1->record_id, std::size_t{0});
|
||||
BOOST_CHECK_EQUAL(c1->I, std::size_t{0});
|
||||
BOOST_CHECK_EQUAL(c1->J, std::size_t{0});
|
||||
BOOST_CHECK_EQUAL(c1->K, std::size_t{0});
|
||||
|
||||
BOOST_CHECK_CLOSE(c1->area, 1.0e6, 1.0e-10);
|
||||
BOOST_CHECK_CLOSE(c1->length, 10.0e3, 1.0e-10);
|
||||
BOOST_CHECK_CLOSE(c1->porosity, 0.25, 1.0e-10);
|
||||
BOOST_CHECK_CLOSE(c1->permeability, 400*mD, 1.0e-10);
|
||||
BOOST_CHECK_CLOSE(c1->depth, 2585.0, 1.0e-10);
|
||||
BOOST_CHECK_MESSAGE(c1->init_pressure.has_value(), "Cell 1 must have an initial pressure");
|
||||
BOOST_CHECK_CLOSE(c1->init_pressure.value(), 285.0*unit::barsa, 1.0e-10);
|
||||
BOOST_CHECK_EQUAL(c1->pvttable, 2);
|
||||
BOOST_CHECK_EQUAL(c1->sattable, 2);
|
||||
BOOST_CHECK_EQUAL(c1->global_index, 0);
|
||||
|
||||
BOOST_CHECK_EQUAL(c2->record_id, std::size_t{1});
|
||||
BOOST_CHECK_EQUAL(c2->I, std::size_t{2});
|
||||
BOOST_CHECK_EQUAL(c2->J, std::size_t{0});
|
||||
BOOST_CHECK_EQUAL(c2->K, std::size_t{0});
|
||||
|
||||
BOOST_CHECK_CLOSE(c2->area, 1.5e6, 1.0e-10);
|
||||
BOOST_CHECK_CLOSE(c2->length, 20.0e3, 1.0e-10);
|
||||
BOOST_CHECK_CLOSE(c2->porosity, 0.24, 1.0e-10);
|
||||
BOOST_CHECK_CLOSE(c2->permeability, 600*mD, 1.0e-10);
|
||||
BOOST_CHECK_CLOSE(c2->depth, 2585.0, 1.0e-10);
|
||||
BOOST_CHECK_MESSAGE(c2->init_pressure.has_value(), "Cell 2 must have an initial pressure");
|
||||
BOOST_CHECK_CLOSE(c2->init_pressure.value(), 285.0*unit::barsa, 1.0e-10);
|
||||
BOOST_CHECK_EQUAL(c2->pvttable, 3);
|
||||
BOOST_CHECK_EQUAL(c2->sattable, 1);
|
||||
BOOST_CHECK_EQUAL(c2->global_index, 2);
|
||||
|
||||
BOOST_CHECK_EQUAL(c3->record_id, std::size_t{2});
|
||||
BOOST_CHECK_EQUAL(c3->I, std::size_t{3});
|
||||
BOOST_CHECK_EQUAL(c3->J, std::size_t{0});
|
||||
BOOST_CHECK_EQUAL(c3->K, std::size_t{0});
|
||||
|
||||
BOOST_CHECK_CLOSE(c3->area, 2.0e6, 1.0e-10);
|
||||
BOOST_CHECK_CLOSE(c3->length, 30.0e3, 1.0e-10);
|
||||
BOOST_CHECK_CLOSE(c3->porosity, 0.25, 1.0e-10);
|
||||
BOOST_CHECK_CLOSE(c3->permeability, 700*mD, 1.0e-10);
|
||||
BOOST_CHECK_CLOSE(c3->depth, 2585.0, 1.0e-10);
|
||||
BOOST_CHECK_MESSAGE(c3->init_pressure.has_value(), "Cell 3 must have an initial pressure");
|
||||
BOOST_CHECK_CLOSE(c3->init_pressure.value(), 285.0*unit::barsa, 1.0e-10);
|
||||
BOOST_CHECK_EQUAL(c3->pvttable, 1);
|
||||
BOOST_CHECK_EQUAL(c3->sattable, 3);
|
||||
BOOST_CHECK_EQUAL(c3->global_index, 3);
|
||||
}
|
||||
|
||||
// using processed actnum for numerical aquifer connection generation
|
||||
std::vector<int> new_actnum(360, 1);
|
||||
new_actnum[0] = 0;
|
||||
|
Loading…
Reference in New Issue
Block a user