isolating the aquifer cells from the rest of the reservoir
by setting the transmissiblity associated with aquifer cells to be zero.
This commit is contained in:
@@ -48,6 +48,9 @@ public:
|
||||
bool operator==(const AquiferConfig& other);
|
||||
bool hasAquifer(const int aquID) const;
|
||||
|
||||
bool hasNumericalAquifer() const;
|
||||
const NumericalAquifers& numericalAquifers() const;
|
||||
|
||||
template<class Serializer>
|
||||
void serializeOp(Serializer& serializer)
|
||||
{
|
||||
|
||||
@@ -40,6 +40,8 @@ namespace Opm {
|
||||
const SingleNumericalAquifer& getAquifer(size_t aquifer_id) const;
|
||||
bool operator==(const NumericalAquifers& other) const;
|
||||
|
||||
std::array<std::set<size_t>, 3> transToRemove(const EclipseGrid& grid) const;
|
||||
|
||||
std::unordered_map<size_t, const NumericalAquiferCell*> allAquiferCells() const;
|
||||
|
||||
static NumericalAquifers serializeObject();
|
||||
|
||||
@@ -21,6 +21,7 @@
|
||||
#define OPM_SINGLENUMERICALAQUIFER_HPP
|
||||
|
||||
#include <vector>
|
||||
#include <set>
|
||||
|
||||
#include <opm/parser/eclipse/EclipseState/Aquifer/NumericalAquifer/NumericalAquiferConnection.hpp>
|
||||
#include <opm/parser/eclipse/EclipseState/Aquifer/NumericalAquifer/NumericalAquiferCell.hpp>
|
||||
@@ -41,6 +42,11 @@ namespace Opm {
|
||||
size_t numConnections() const;
|
||||
const NumericalAquiferCell* getCellPrt(size_t index) const;
|
||||
|
||||
// we remove the connection around the aquifer cells to isolate aquifer cells
|
||||
// from the other part of the reservoir
|
||||
// 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;
|
||||
|
||||
bool operator==(const SingleNumericalAquifer& other) const;
|
||||
|
||||
template<class Serializer>
|
||||
|
||||
@@ -122,11 +122,11 @@ namespace Opm {
|
||||
m_deckUnitSystem.serializeOp(serializer);
|
||||
m_inputNnc.serializeOp(serializer);
|
||||
m_gridDims.serializeOp(serializer);
|
||||
aquifer_config.serializeOp(serializer);
|
||||
m_simulationConfig.serializeOp(serializer);
|
||||
m_transMult.serializeOp(serializer);
|
||||
m_faults.serializeOp(serializer);
|
||||
serializer(m_title);
|
||||
aquifer_config.serializeOp(serializer);
|
||||
tracer_config.serializeOp(serializer);
|
||||
}
|
||||
|
||||
@@ -149,12 +149,12 @@ namespace Opm {
|
||||
NNC m_inputNnc;
|
||||
GridDims m_gridDims;
|
||||
FieldPropsManager field_props;
|
||||
AquiferConfig aquifer_config;
|
||||
SimulationConfig m_simulationConfig;
|
||||
TransMult m_transMult;
|
||||
|
||||
FaultCollection m_faults;
|
||||
std::string m_title;
|
||||
AquiferConfig aquifer_config;
|
||||
TracerConfig tracer_config;
|
||||
};
|
||||
}
|
||||
|
||||
@@ -32,6 +32,7 @@ class Deck;
|
||||
class FieldProps;
|
||||
class Phases;
|
||||
class TableManager;
|
||||
class NumericalAquifers;
|
||||
|
||||
class FieldPropsManager {
|
||||
|
||||
@@ -217,6 +218,9 @@ public:
|
||||
*/
|
||||
virtual void apply_tran(const std::string& keyword, std::vector<double>& tran_data) const;
|
||||
|
||||
void applyNumericalAquifer(const NumericalAquifers& aquifers);
|
||||
|
||||
|
||||
/*
|
||||
When using MPI the FieldPropsManager is typically only assembled on the
|
||||
root node and then distributed to the other nodes afterwards. These
|
||||
|
||||
@@ -80,4 +80,12 @@ bool AquiferConfig::hasAquifer(const int aquID) const {
|
||||
numerical_aquifers.hasAquifer(aquID);
|
||||
}
|
||||
|
||||
bool AquiferConfig::hasNumericalAquifer() const {
|
||||
return this->numerical_aquifers.numAquifer();
|
||||
}
|
||||
|
||||
const NumericalAquifers& AquiferConfig::numericalAquifers() const {
|
||||
return this->numerical_aquifers;
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
@@ -145,4 +145,15 @@ namespace Opm {
|
||||
}
|
||||
return cells;
|
||||
}
|
||||
|
||||
std::array<std::set<size_t>, 3> NumericalAquifers::transToRemove(const EclipseGrid& grid) const {
|
||||
std::array<std::set<size_t>, 3> trans;
|
||||
for (const auto& [id, aquifer] : this->m_aquifers) {
|
||||
auto trans_aquifer = aquifer.transToRemove(grid);
|
||||
for (size_t i = 0; i < 3; ++i) {
|
||||
trans[i].merge(trans_aquifer[i]);
|
||||
}
|
||||
}
|
||||
return trans;
|
||||
}
|
||||
}
|
||||
@@ -17,9 +17,12 @@
|
||||
along with OPM. If not, see <http://www.gnu.org/licenses/>.
|
||||
*/
|
||||
|
||||
#include <opm/parser/eclipse/EclipseState/Grid/EclipseGrid.hpp>
|
||||
|
||||
#include <opm/parser/eclipse/EclipseState/Aquifer/NumericalAquifer/NumericalAquiferConnection.hpp>
|
||||
#include <opm/parser/eclipse/EclipseState/Aquifer/NumericalAquifer/NumericalAquiferCell.hpp>
|
||||
#include <opm/parser/eclipse/EclipseState/Aquifer/NumericalAquifer/SingleNumericalAquifer.hpp>
|
||||
#include "../AquiferHelpers.hpp"
|
||||
|
||||
namespace Opm {
|
||||
SingleNumericalAquifer::SingleNumericalAquifer(const size_t aqu_id)
|
||||
@@ -52,4 +55,32 @@ namespace Opm {
|
||||
size_t SingleNumericalAquifer::numConnections() const {
|
||||
return this->connections_.size();
|
||||
}
|
||||
|
||||
std::array<std::set<size_t>, 3> SingleNumericalAquifer::transToRemove(const EclipseGrid& grid) const {
|
||||
std::array<std::set<size_t>, 3> trans;
|
||||
for (const auto& cell : this->cells_) {
|
||||
const size_t i = cell.I;
|
||||
const size_t j = cell.J;
|
||||
const size_t k = cell.K;
|
||||
if (AquiferHelpers::neighborCellInsideReservoirAndActive(grid, i, j, k, FaceDir::XPlus)) {
|
||||
trans[0].insert(cell.global_index);
|
||||
}
|
||||
if (AquiferHelpers::neighborCellInsideReservoirAndActive(grid, i, j, k, FaceDir::XMinus)) {
|
||||
trans[0].insert(grid.getGlobalIndex(i-1, j, k));
|
||||
}
|
||||
if (AquiferHelpers::neighborCellInsideReservoirAndActive(grid, i, j, k, FaceDir::YPlus)) {
|
||||
trans[1].insert(cell.global_index);
|
||||
}
|
||||
if (AquiferHelpers::neighborCellInsideReservoirAndActive(grid, i, j, k, FaceDir::YMinus)) {
|
||||
trans[1].insert(grid.getGlobalIndex(i, j-1, k));
|
||||
}
|
||||
if (AquiferHelpers::neighborCellInsideReservoirAndActive(grid, i, j, k, FaceDir::ZPlus)) {
|
||||
trans[2].insert(cell.global_index);
|
||||
}
|
||||
if (AquiferHelpers::neighborCellInsideReservoirAndActive(grid, i, j, k, FaceDir::ZMinus)) {
|
||||
trans[2].insert(grid.getGlobalIndex(i, j, k-1));
|
||||
}
|
||||
}
|
||||
return trans;
|
||||
}
|
||||
}
|
||||
|
||||
@@ -61,16 +61,20 @@ namespace Opm {
|
||||
m_inputNnc( m_inputGrid, deck),
|
||||
m_gridDims( deck ),
|
||||
field_props( deck, m_runspec.phases(), m_inputGrid, m_tables),
|
||||
aquifer_config(this->m_tables, this->m_inputGrid, deck, this->field_props),
|
||||
m_simulationConfig( m_eclipseConfig.getInitConfig().restartRequested(), deck, field_props),
|
||||
m_transMult( GridDims(deck), deck, field_props),
|
||||
tracer_config( m_deckUnitSystem, deck)
|
||||
{
|
||||
if (this->aquifer().hasNumericalAquifer()) {
|
||||
const auto& numerical_aquifer = this->aquifer().numericalAquifers();
|
||||
this->field_props.applyNumericalAquifer(numerical_aquifer);
|
||||
}
|
||||
|
||||
m_inputGrid.resetACTNUM(this->field_props.actnum());
|
||||
if( this->runspec().phases().size() < 3 )
|
||||
OpmLog::info(fmt::format("Only {} fluid phases are enabled", this->runspec().phases().size() ));
|
||||
|
||||
this->aquifer_config = AquiferConfig(this->m_tables, this->m_inputGrid, deck, this->field_props);
|
||||
|
||||
if (deck.hasKeyword( "TITLE" )) {
|
||||
const auto& titleKeyword = deck.getKeyword( "TITLE" );
|
||||
const auto& item = titleKeyword.getRecord( 0 ).getItem( 0 );
|
||||
|
||||
@@ -18,6 +18,9 @@
|
||||
#include <functional>
|
||||
#include <algorithm>
|
||||
#include <unordered_map>
|
||||
#include <array>
|
||||
#include <vector>
|
||||
#include <set>
|
||||
|
||||
#include <opm/common/utility/OpmInputError.hpp>
|
||||
|
||||
@@ -39,6 +42,7 @@
|
||||
#include <opm/parser/eclipse/EclipseState/Grid/SatfuncPropertyInitializers.hpp>
|
||||
#include <opm/parser/eclipse/EclipseState/Runspec.hpp>
|
||||
#include <opm/common/utility/Serializer.hpp>
|
||||
#include <opm/parser/eclipse/EclipseState/Aquifer/NumericalAquifer/NumericalAquifers.hpp>
|
||||
|
||||
#include "FieldProps.hpp"
|
||||
#include "Operate.hpp"
|
||||
@@ -1211,6 +1215,40 @@ 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) {
|
||||
this->updateTransWithNumericalAquifer(numerical_aquifers);
|
||||
}
|
||||
|
||||
void FieldProps::updateTransWithNumericalAquifer(const NumericalAquifers& numerical_aquifers) {
|
||||
const std::array<std::set<size_t>, 3> trans_to_remove = numerical_aquifers.transToRemove(*(this->grid_ptr));
|
||||
std::array<std::vector<Box::cell_index>, 3> index_lists;
|
||||
for (int i = 0; i < 3; ++i) {
|
||||
size_t num = 0;
|
||||
for (const auto& elem : trans_to_remove[i]) {
|
||||
const size_t active_index = this->grid_ptr->activeIndex(elem);
|
||||
index_lists[i].emplace_back(elem, active_index, num);
|
||||
num++;
|
||||
}
|
||||
}
|
||||
|
||||
const std::array<std::string, 3> trans_string {"TRANX", "TRANY", "TRANZ"};
|
||||
for (int i = 0; i < 3; ++i) {
|
||||
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);
|
||||
assert(tran_iter != this->tran.end());
|
||||
const std::string unique_name = tran_iter->second.next_name();
|
||||
const auto operation = Fieldprops::ScalarOperation::EQUAL;
|
||||
tran_iter->second.add_action(operation, unique_name);
|
||||
const auto kw_info = tran_iter->second.make_kw_info(operation);
|
||||
auto& field_data = this->init_get<double>(unique_name, kw_info);
|
||||
// setting the transmissiblity to be zero to remove the connection between specific cells
|
||||
FieldProps::apply(operation, field_data.data, field_data.value_status, 0.0, single_index_list);
|
||||
// TODO: not sure when we need the following. If we need, we also need to make a global_index_list;
|
||||
/* if (field_data.global_data)
|
||||
FieldProps::apply(operation, *field_data.global_data, *field_data.global_value_status, scalar_value, box.global_index_list()); */
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
template std::vector<bool> FieldProps::defaulted<int>(const std::string& keyword);
|
||||
|
||||
@@ -41,6 +41,7 @@ namespace Opm {
|
||||
class Deck;
|
||||
class EclipseGrid;
|
||||
class TableManager;
|
||||
class NumericalAquifers;
|
||||
|
||||
namespace Fieldprops
|
||||
{
|
||||
@@ -360,6 +361,11 @@ 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);
|
||||
// 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);
|
||||
|
||||
const std::string& default_region() const;
|
||||
|
||||
std::vector<int> actnum();
|
||||
|
||||
@@ -22,6 +22,7 @@
|
||||
#include <opm/parser/eclipse/EclipseState/Grid/FieldPropsManager.hpp>
|
||||
#include <opm/parser/eclipse/EclipseState/Runspec.hpp>
|
||||
#include <opm/common/utility/Serializer.hpp>
|
||||
#include <opm/parser/eclipse/EclipseState/Aquifer/NumericalAquifer/NumericalAquifers.hpp>
|
||||
|
||||
#include "FieldProps.hpp"
|
||||
|
||||
@@ -141,6 +142,10 @@ 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);
|
||||
}
|
||||
|
||||
template<class MapType>
|
||||
void apply_tran(const std::unordered_map<std::string, Fieldprops::TranCalculator>& tran,
|
||||
const MapType& double_data,
|
||||
|
||||
Reference in New Issue
Block a user