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:
Kai Bao
2021-01-28 21:13:49 +01:00
parent c9908df914
commit 7628d7e13b
12 changed files with 122 additions and 4 deletions

View File

@@ -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)
{

View File

@@ -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();

View File

@@ -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>

View File

@@ -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;
};
}

View File

@@ -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

View File

@@ -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;
}
}

View File

@@ -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;
}
}

View File

@@ -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;
}
}

View File

@@ -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 );

View File

@@ -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);

View File

@@ -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();

View File

@@ -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,