addressing reviewing comments in OPM/opm-common#2252
This commit is contained in:
@@ -35,7 +35,7 @@ namespace Opm {
|
||||
NumericalAquifers() = default;
|
||||
NumericalAquifers(const Deck& deck, const EclipseGrid& grid, const FieldPropsManager& field_props);
|
||||
|
||||
size_t numAquifer() const;
|
||||
size_t size() const;
|
||||
bool hasAquifer(size_t aquifer_id) const;
|
||||
const SingleNumericalAquifer& getAquifer(size_t aquifer_id) const;
|
||||
const std::unordered_map <size_t, SingleNumericalAquifer>& aquifers() const;
|
||||
@@ -45,11 +45,9 @@ namespace Opm {
|
||||
|
||||
std::unordered_map<size_t, const NumericalAquiferCell*> allAquiferCells() const;
|
||||
|
||||
void updateCellProps(const EclipseGrid& grid,
|
||||
std::vector<double>& pore_volume,
|
||||
std::vector<int>& satnum,
|
||||
std::vector<int>& pvtnum) const;
|
||||
void appendNNC(const EclipseGrid& grid, const FieldPropsManager& fp, NNC& nnc) const;
|
||||
std::vector<NNCdata> aquiferNNCs(const EclipseGrid& grid, const FieldPropsManager& fp) const;
|
||||
|
||||
std::unordered_map<size_t, AquiferCellProps> aquiferCellProps() const;
|
||||
|
||||
static NumericalAquifers serializeObject();
|
||||
template <class Serializer>
|
||||
|
||||
@@ -28,8 +28,15 @@
|
||||
|
||||
namespace Opm {
|
||||
class NNC;
|
||||
class NNCdata;
|
||||
class FieldPropsManager;
|
||||
|
||||
struct AquiferCellProps {
|
||||
double pore_volume;
|
||||
int satnum;
|
||||
int pvtnum;
|
||||
};
|
||||
|
||||
class SingleNumericalAquifer {
|
||||
public:
|
||||
explicit SingleNumericalAquifer(const size_t aqu_id);
|
||||
@@ -50,15 +57,10 @@ namespace Opm {
|
||||
// the removing of the connection is done by make transmissiblities to be zero
|
||||
std::array<std::set<size_t>, 3> transToRemove(const EclipseGrid& grid) const;
|
||||
|
||||
// aquifer cells are still cells in the grid, but AQUNUM can modify the grid properties
|
||||
// in a relatively arbitrary way. As a result, related and field properties need to be updated
|
||||
// with the numerical aquifer keywords
|
||||
void updateCellProps(const EclipseGrid& grid,
|
||||
std::vector<double>& pore_volume,
|
||||
std::vector<int>& satnum,
|
||||
std::vector<int>& pvtnum) const;
|
||||
std::unordered_map<size_t, AquiferCellProps> aquiferCellProps() const;
|
||||
|
||||
void appendNNC(const EclipseGrid &grid, const FieldPropsManager &fp, NNC &nnc) const;
|
||||
void appendNNC(const EclipseGrid& grid, const FieldPropsManager& fp, NNC& nnc) const;
|
||||
std::vector<NNCdata> aquiferNNCs(const EclipseGrid& grid, const FieldPropsManager& fp) const;
|
||||
|
||||
bool operator==(const SingleNumericalAquifer& other) const;
|
||||
|
||||
@@ -78,8 +80,8 @@ namespace Opm {
|
||||
std::vector<NumericalAquiferCell> cells_;
|
||||
std::vector<NumericalAquiferConnection> connections_;
|
||||
|
||||
void appendCellNNC(NNC &nnc) const;
|
||||
void appendConnectionNNC(const EclipseGrid &grid, const FieldPropsManager &fp, NNC &nnc) const;
|
||||
std::vector<NNCdata> aquiferCellNNCs() const;
|
||||
std::vector<NNCdata> aquiferConnectionNNCs(const EclipseGrid &grid, const FieldPropsManager &fp) const;
|
||||
};
|
||||
}
|
||||
|
||||
|
||||
@@ -218,7 +218,7 @@ public:
|
||||
*/
|
||||
virtual void apply_tran(const std::string& keyword, std::vector<double>& tran_data) const;
|
||||
|
||||
void applyNumericalAquifer(const NumericalAquifers& aquifers);
|
||||
void apply_numerical_aquifers(const NumericalAquifers& aquifers);
|
||||
|
||||
|
||||
/*
|
||||
|
||||
@@ -52,7 +52,7 @@ AquiferConfig AquiferConfig::serializeObject()
|
||||
bool AquiferConfig::active() const {
|
||||
return this->aquiferct.size() > 0 ||
|
||||
this->aquifetp.size() > 0 ||
|
||||
this->numerical_aquifers.numAquifer() > 0;
|
||||
this->numerical_aquifers.size() > 0;
|
||||
}
|
||||
|
||||
bool AquiferConfig::operator==(const AquiferConfig& other) {
|
||||
@@ -81,7 +81,7 @@ bool AquiferConfig::hasAquifer(const int aquID) const {
|
||||
}
|
||||
|
||||
bool AquiferConfig::hasNumericalAquifer() const {
|
||||
return this->numerical_aquifers.numAquifer();
|
||||
return this->numerical_aquifers.size() > 0;
|
||||
}
|
||||
|
||||
const NumericalAquifers& AquiferConfig::numericalAquifers() const {
|
||||
|
||||
@@ -25,6 +25,7 @@
|
||||
#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/Aquifer/NumericalAquifer/NumericalAquiferCell.hpp>
|
||||
#include <opm/parser/eclipse/EclipseState/Aquifer/NumericalAquifer/NumericalAquifers.hpp>
|
||||
@@ -115,7 +116,7 @@ namespace Opm {
|
||||
return this->m_aquifers == other.m_aquifers;
|
||||
}
|
||||
|
||||
size_t NumericalAquifers::numAquifer() const {
|
||||
size_t NumericalAquifers::size() const {
|
||||
return this->m_aquifers.size();
|
||||
}
|
||||
|
||||
@@ -157,24 +158,25 @@ namespace Opm {
|
||||
return trans;
|
||||
}
|
||||
|
||||
void NumericalAquifers::updateCellProps(const EclipseGrid& grid,
|
||||
std::vector<double>& pore_volume,
|
||||
std::vector<int>& satnum,
|
||||
std::vector<int>& pvtnum) const {
|
||||
for (const auto& [id, aquifer]: this->m_aquifers) {
|
||||
aquifer.updateCellProps(grid, pore_volume, satnum, pvtnum);
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
void NumericalAquifers::appendNNC(const EclipseGrid& grid, const FieldPropsManager& fp, NNC& nnc) const {
|
||||
for (const auto& [id, aquifer]: this->m_aquifers) {
|
||||
aquifer.appendNNC(grid, fp, nnc);
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
const std::unordered_map<size_t, SingleNumericalAquifer>& NumericalAquifers::aquifers() const {
|
||||
return this->m_aquifers;
|
||||
}
|
||||
|
||||
std::unordered_map<size_t, AquiferCellProps> NumericalAquifers::aquiferCellProps() const {
|
||||
std::unordered_map<size_t, AquiferCellProps> cell_props;
|
||||
for ([[maybe_unused]]const auto& [id, aquifer] : this->m_aquifers ) {
|
||||
auto aqu_cell_props = aquifer.aquiferCellProps();
|
||||
cell_props.insert(aqu_cell_props.begin(), aqu_cell_props.end());
|
||||
}
|
||||
return cell_props;
|
||||
}
|
||||
|
||||
std::vector<NNCdata> NumericalAquifers::aquiferNNCs(const EclipseGrid& grid, const FieldPropsManager& fp) const {
|
||||
std::vector<NNCdata> nncs;
|
||||
for ([[maybe_unused]] const auto& [id, aquifer] : this->m_aquifers) {
|
||||
auto aqu_nncs = aquifer.aquiferNNCs(grid, fp);
|
||||
nncs.insert(nncs.end(), aqu_nncs.begin(), aqu_nncs.end());
|
||||
}
|
||||
return nncs;
|
||||
}
|
||||
}
|
||||
@@ -86,24 +86,29 @@ namespace Opm {
|
||||
return trans;
|
||||
}
|
||||
|
||||
void SingleNumericalAquifer::updateCellProps(const EclipseGrid& grid,
|
||||
std::vector<double>& pore_volume,
|
||||
std::vector<int>& satnum,
|
||||
std::vector<int>& pvtnum) const {
|
||||
size_t SingleNumericalAquifer::id() const {
|
||||
return this->id_;
|
||||
}
|
||||
|
||||
std::unordered_map<size_t, AquiferCellProps> SingleNumericalAquifer::aquiferCellProps() const {
|
||||
std::unordered_map<size_t, AquiferCellProps> aqucellprops;
|
||||
for (const auto& cell : this->cells_) {
|
||||
const size_t activel_index = grid.activeIndex(cell.global_index);
|
||||
pore_volume[activel_index] = cell.poreVolume();
|
||||
satnum[activel_index] = cell.sattable;
|
||||
pvtnum[activel_index] = cell.pvttable;
|
||||
aqucellprops.emplace(std::make_pair(cell.global_index,
|
||||
AquiferCellProps{cell.poreVolume(), cell.sattable, cell.pvttable}));
|
||||
}
|
||||
return aqucellprops;
|
||||
}
|
||||
|
||||
void SingleNumericalAquifer::appendNNC(const EclipseGrid& grid, const FieldPropsManager &fp, NNC& nnc) const {
|
||||
this->appendCellNNC(nnc);
|
||||
this->appendConnectionNNC(grid, fp, nnc);
|
||||
std::vector<NNCdata>
|
||||
SingleNumericalAquifer::aquiferNNCs(const EclipseGrid& grid, const FieldPropsManager& fp) const {
|
||||
auto nncs = this->aquiferCellNNCs();
|
||||
auto con_nncs = this->aquiferConnectionNNCs(grid, fp);
|
||||
nncs.insert(nncs.end(), con_nncs.begin(), con_nncs.end());
|
||||
return nncs;
|
||||
}
|
||||
|
||||
void SingleNumericalAquifer::appendCellNNC(NNC& nnc) const {
|
||||
std::vector<NNCdata> SingleNumericalAquifer::aquiferCellNNCs() const {
|
||||
std::vector<NNCdata> nncs;
|
||||
// aquifer cells are connected to each other through NNCs to form the aquifer
|
||||
for (size_t i = 0; i < this->cells_.size() - 1; ++i) {
|
||||
const double trans1 = this->cells_[i].transmissiblity();
|
||||
@@ -111,11 +116,14 @@ namespace Opm {
|
||||
const double tran = 1. / (1. / trans1 + 1. / trans2);
|
||||
const size_t gc1 = this->cells_[i].global_index;
|
||||
const size_t gc2 = this->cells_[i + 1].global_index;
|
||||
nnc.addNNC(gc1, gc2, tran);
|
||||
nncs.emplace_back(gc1, gc2, tran);
|
||||
}
|
||||
return nncs;
|
||||
}
|
||||
|
||||
void SingleNumericalAquifer::appendConnectionNNC(const EclipseGrid& grid, const FieldPropsManager &fp, NNC& nnc) const {
|
||||
std::vector<NNCdata>
|
||||
SingleNumericalAquifer::aquiferConnectionNNCs(const EclipseGrid& grid, const FieldPropsManager& fp) const {
|
||||
std::vector<NNCdata> nncs;
|
||||
// aquifer connections are connected to aquifer cells through NNCs
|
||||
const std::vector<double>& ntg = fp.get_double("NTG");
|
||||
const auto& cell1 = this->cells_[0];
|
||||
@@ -153,11 +161,8 @@ namespace Opm {
|
||||
const double trans_con = 2 * cell_perm * face_area * ntg[grid.activeIndex(con.global_index)] / d;
|
||||
|
||||
const double tran = trans_con * trans_cell / (trans_con + trans_cell) * con.trans_multipler;
|
||||
nnc.addNNC(gc1, gc2, tran);
|
||||
nncs.emplace_back(gc1, gc2, tran);
|
||||
}
|
||||
}
|
||||
|
||||
size_t SingleNumericalAquifer::id() const {
|
||||
return this->id_;
|
||||
return nncs;
|
||||
}
|
||||
}
|
||||
|
||||
@@ -68,8 +68,15 @@ namespace Opm {
|
||||
{
|
||||
if (this->aquifer().hasNumericalAquifer()) {
|
||||
const auto& numerical_aquifer = this->aquifer().numericalAquifers();
|
||||
this->field_props.applyNumericalAquifer(numerical_aquifer);
|
||||
numerical_aquifer.appendNNC(this->m_inputGrid, this->field_props, this->m_inputNnc);
|
||||
// update field_props for numerical aquifer cells, and set the transmissiblity related to aquifer cells to
|
||||
// be zero
|
||||
this->field_props.apply_numerical_aquifers(numerical_aquifer);
|
||||
|
||||
// add NNCs between aquifer cells and first aquifer cell and aquifer connections
|
||||
const auto& aquifer_nncs = numerical_aquifer.aquiferNNCs(this->m_inputGrid, this->field_props);
|
||||
for (const auto& nnc_data : aquifer_nncs) {
|
||||
this->m_inputNnc.addNNC(nnc_data.cell1, nnc_data.cell2, nnc_data.trans);
|
||||
}
|
||||
}
|
||||
|
||||
m_inputGrid.resetACTNUM(this->field_props.actnum());
|
||||
|
||||
@@ -1215,14 +1215,21 @@ bool FieldProps::tran_active(const std::string& keyword) const {
|
||||
return calculator != this->tran.end() && calculator->second.size() > 0;
|
||||
}
|
||||
|
||||
void FieldProps::applyNumericalAquifers(const NumericalAquifers& numerical_aquifers) {
|
||||
void FieldProps::apply_numerical_aquifers(const NumericalAquifers& numerical_aquifers) {
|
||||
// TODO: ideally, we should also update the cell_depth, but it is not used for later
|
||||
// in the simulator. So we do not update it here.
|
||||
// Maybe also cell volume? Not sure whether it is used later
|
||||
auto& porv_data = this->init_get<double>("PORV").data;
|
||||
auto& satnum_data = this->int_data["SATNUM"].data;
|
||||
auto& pvtnum_data = this->int_data["PVTNUM"].data;
|
||||
numerical_aquifers.updateCellProps(*(this->grid_ptr), porv_data, satnum_data, pvtnum_data);
|
||||
|
||||
const auto& aqu_cell_props = numerical_aquifers.aquiferCellProps();
|
||||
for (const auto& [global_index, cellprop] : aqu_cell_props) {
|
||||
const size_t active_index = this->grid_ptr->activeIndex(global_index);
|
||||
porv_data[active_index] = cellprop.pore_volume;
|
||||
satnum_data[active_index] = cellprop.satnum;
|
||||
pvtnum_data[active_index] = cellprop.pvtnum;
|
||||
}
|
||||
|
||||
this->updateTransWithNumericalAquifer(numerical_aquifers);
|
||||
}
|
||||
@@ -1244,6 +1251,10 @@ void FieldProps::updateTransWithNumericalAquifer(const NumericalAquifers& numeri
|
||||
const std::string& target_kw = trans_string[i];
|
||||
const std::vector<Box::cell_index>& single_index_list = index_lists[i];
|
||||
auto tran_iter = this->tran.find(target_kw);
|
||||
if (tran_iter == this->tran.end()) {
|
||||
const std::string msg = trans_string[i] + " TranCalculator could not be found when applying numerical aquifer";
|
||||
throw std::logic_error(msg);
|
||||
}
|
||||
assert(tran_iter != this->tran.end());
|
||||
const std::string unique_name = tran_iter->second.next_name();
|
||||
const auto operation = Fieldprops::ScalarOperation::EQUAL;
|
||||
|
||||
@@ -361,7 +361,7 @@ public:
|
||||
FieldProps(const Deck& deck, const Phases& phases, const EclipseGrid& grid, const TableManager& table_arg);
|
||||
void reset_actnum(const std::vector<int>& actnum);
|
||||
|
||||
void applyNumericalAquifers(const NumericalAquifers& numerical_aquifers);
|
||||
void apply_numerical_aquifers(const NumericalAquifers& numerical_aquifers);
|
||||
// set the transmissiblities around the numerical aquifer cells to be zero, so we can isolate them
|
||||
// from the other reservoir cells
|
||||
void updateTransWithNumericalAquifer(const NumericalAquifers& numerical_aquifer);
|
||||
|
||||
@@ -142,8 +142,8 @@ bool FieldPropsManager::tran_active(const std::string& keyword) const {
|
||||
return this->fp->tran_active(keyword);
|
||||
}
|
||||
|
||||
void FieldPropsManager::applyNumericalAquifer(const NumericalAquifers& aquifers) {
|
||||
return this->fp->applyNumericalAquifers(aquifers);
|
||||
void FieldPropsManager::apply_numerical_aquifers(const NumericalAquifers& aquifers) {
|
||||
return this->fp->apply_numerical_aquifers(aquifers);
|
||||
}
|
||||
|
||||
template<class MapType>
|
||||
|
||||
@@ -617,7 +617,7 @@ BOOST_AUTO_TEST_CASE(NumericalAquiferTest){
|
||||
|
||||
const Opm::NumericalAquifers num_aqu{numaquifer_deck, grid, ecl_state.fieldProps()};
|
||||
BOOST_CHECK(num_aqu.hasAquifer(1));
|
||||
BOOST_CHECK(num_aqu.numAquifer() == 1);
|
||||
BOOST_CHECK(num_aqu.size() == 1);
|
||||
const auto all_aquifer_cells = num_aqu.allAquiferCells();
|
||||
BOOST_CHECK(all_aquifer_cells.count(0) > 0);
|
||||
BOOST_CHECK(all_aquifer_cells.count(2) > 0);
|
||||
|
||||
Reference in New Issue
Block a user