Skip to content

Commit

Permalink
Merge pull request #3378 from GitPaean/support_aquflux
Browse files Browse the repository at this point in the history
supporting the keyword AQUFLUX
  • Loading branch information
bska authored Feb 21, 2023
2 parents 55efa07 + affdea7 commit 4825a76
Show file tree
Hide file tree
Showing 17 changed files with 321 additions and 22 deletions.
2 changes: 2 additions & 0 deletions CMakeLists_files.cmake
Original file line number Diff line number Diff line change
Expand Up @@ -81,6 +81,7 @@ if(ENABLE_ECL_INPUT)
src/opm/input/eclipse/Python/Python.cpp
src/opm/input/eclipse/Schedule/Action/PyAction.cpp
src/opm/input/eclipse/EclipseState/Aquifer/AquiferConfig.cpp
src/opm/input/eclipse/EclipseState/Aquifer/AquiferFlux.cpp
src/opm/input/eclipse/EclipseState/Aquifer/AquiferCT.cpp
src/opm/input/eclipse/EclipseState/Aquifer/Aquifetp.cpp
src/opm/input/eclipse/EclipseState/Aquifer/Aquancon.cpp
Expand Down Expand Up @@ -1071,6 +1072,7 @@ if(ENABLE_ECL_INPUT)
opm/input/eclipse/EclipseState/EclipseConfig.hpp
opm/input/eclipse/EclipseState/Aquifer/Aquancon.hpp
opm/input/eclipse/EclipseState/Aquifer/AquiferConfig.hpp
opm/input/eclipse/EclipseState/Aquifer/AquiferFlux.hpp
opm/input/eclipse/EclipseState/Aquifer/AquiferCT.hpp
opm/input/eclipse/EclipseState/Aquifer/Aquifetp.hpp
opm/input/eclipse/EclipseState/Aquifer/NumericalAquifer/NumericalAquiferCell.hpp
Expand Down
15 changes: 14 additions & 1 deletion opm/input/eclipse/EclipseState/Aquifer/AquiferConfig.hpp
Original file line number Diff line number Diff line change
Expand Up @@ -23,10 +23,12 @@
#include <opm/input/eclipse/EclipseState/Aquifer/Aquancon.hpp>
#include <opm/input/eclipse/EclipseState/Aquifer/Aquifetp.hpp>
#include <opm/input/eclipse/EclipseState/Aquifer/AquiferCT.hpp>
#include <opm/input/eclipse/EclipseState/Aquifer/AquiferFlux.hpp>
#include <opm/input/eclipse/EclipseState/Aquifer/NumericalAquifer/NumericalAquifers.hpp>

#include <cstddef>
#include <vector>
#include <unordered_set>

namespace Opm {
class TableManager;
Expand All @@ -43,21 +45,30 @@ namespace Opm {

class AquiferConfig {
public:

AquiferConfig() = default;
AquiferConfig(const TableManager& tables, const EclipseGrid& grid,
const Deck& deck, const FieldPropsManager& field_props);
AquiferConfig(const Aquifetp& fetp, const AquiferCT& ct, const Aquancon& conn);
AquiferConfig(const Aquifetp& fetp, const AquiferCT& ct, const AquiferFlux& aqufluxs, const Aquancon& conn);
void load_connections(const Deck& deck, const EclipseGrid& grid);

void pruneDeactivatedAquiferConnections(const std::vector<std::size_t>& deactivated_cells);
void loadFromRestart(const RestartIO::RstAquifer& aquifers,
const TableManager& tables);

// there might be some aquifers (AQUFLUX only for now) are opened through
// SCHEDULE section while not specified in the SOLUTION section.
// We create dummy aquifers in the AquiferConfig to make sure we are aware of them
// when we handle the SUMMARY section.
// Since those aquifers are not active, basically we only need the id information
void appendAqufluxSchedule(const std::unordered_set<int>& ids);

static AquiferConfig serializationTestObject();

bool active() const;
const AquiferCT& ct() const;
const Aquifetp& fetp() const;
const AquiferFlux& aquflux() const;
const Aquancon& connections() const;
bool operator==(const AquiferConfig& other) const;
bool hasAquifer(const int aquID) const;
Expand All @@ -74,12 +85,14 @@ class AquiferConfig {
serializer(aquifetp);
serializer(aquiferct);
serializer(aqconn);
serializer(aquiferflux);
serializer(numerical_aquifers);
}

private:
Aquifetp aquifetp{};
AquiferCT aquiferct{};
AquiferFlux aquiferflux{};
mutable NumericalAquifers numerical_aquifers{};
Aquancon aqconn{};
};
Expand Down
101 changes: 101 additions & 0 deletions opm/input/eclipse/EclipseState/Aquifer/AquiferFlux.hpp
Original file line number Diff line number Diff line change
@@ -0,0 +1,101 @@
/*
Copyright (C) 2023 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/>.
*/

#ifndef OPM_AQUIFERFLUX_HPP
#define OPM_AQUIFERFLUX_HPP

#include <optional>
#include <unordered_map>
#include <unordered_set>
#include <vector>

namespace Opm {
class DeckKeyword;
class DeckRecord;
}

namespace Opm::RestartIO {
class RstAquifer;
} // Opm::RestartIO

namespace Opm {
struct SingleAquiferFlux {
explicit SingleAquiferFlux(const DeckRecord& record);

// using id to create an inactive dummy aquifer
explicit SingleAquiferFlux(int id);
SingleAquiferFlux() = default;
SingleAquiferFlux(int id, double flux, double sal, bool active_, double temp, double pres);

int id {0};
double flux {0.};
double salt_concentration {0.};
bool active {false};
std::optional<double> temperature;
std::optional<double> datum_pressure;

bool operator==(const SingleAquiferFlux& other) const;

template<class Serializer>
void serializeOp(Serializer& serializer)
{
serializer(this->id);
serializer(this->flux);
serializer(this->salt_concentration);
serializer(this->active);
serializer(this->temperature);
serializer(this->datum_pressure);
}

static SingleAquiferFlux serializationTestObject();
};

class AquiferFlux {
public:
using AquFluxs = std::unordered_map<int, SingleAquiferFlux>;

explicit AquiferFlux(const std::vector<const DeckKeyword*>& keywords);
AquiferFlux() = default;

void appendAqufluxSchedule(const std::unordered_set<int>& ids);

bool hasAquifer(int id) const;

bool operator==(const AquiferFlux& other) const;

size_t size() const;

AquFluxs::const_iterator begin() const;
AquFluxs::const_iterator end() const;

void loadFromRestart(const RestartIO::RstAquifer& rst);

template<class Serializer>
void serializeOp(Serializer& serializer) {
serializer(this->m_aquifers);
}

static AquiferFlux serializationTestObject();

private:
AquFluxs m_aquifers;
};
} // end of namespace Opm

#endif //OPM_AQUIFERFLUX_HPP
5 changes: 5 additions & 0 deletions opm/input/eclipse/EclipseState/EclipseState.hpp
Original file line number Diff line number Diff line change
Expand Up @@ -112,6 +112,11 @@ namespace Opm {
void reset_actnum(const std::vector<int>& new_actnum);
void pruneDeactivatedAquiferConnections(const std::vector<std::size_t>& deactivated_cells);
void loadRestartAquifers(const RestartIO::RstAquifer& aquifers);
// TODO: it is possible that the aquifer are opened through SCHEDULE and not specified in the SOLUTION section
// For the ease of the implementation, we create inactive aquifer in the AquiferConfig.
// At the moment, it only works for Constant Flux Aquifers(AQUFLUX) as indicated by the function name
// When we know and decide to handle the same for AQUFETP and AQUCT, this part will be refactored
void appendAqufluxSchedule(const std::unordered_set<int>& ids);

template<class Serializer>
void serializeOp(Serializer& serializer)
Expand Down
3 changes: 3 additions & 0 deletions opm/input/eclipse/Schedule/Schedule.hpp
Original file line number Diff line number Diff line change
Expand Up @@ -261,6 +261,8 @@ namespace Opm
const Well& getWell(std::size_t well_index, std::size_t timeStep) const;
const Well& getWell(const std::string& wellName, std::size_t timeStep) const;
const Well& getWellatEnd(const std::string& well_name) const;
// get the list of the constant flux aquifer specified in the whole schedule
std::unordered_set<int> getAquiferFluxSchedule() const;
std::vector<Well> getWells(std::size_t timeStep) const;
std::vector<Well> getWellsatEnd() const;
void shut_well(const std::string& well_name, std::size_t report_step);
Expand Down Expand Up @@ -675,6 +677,7 @@ namespace Opm

void handleAQUCT (HandlerContext&);
void handleAQUFETP (HandlerContext&);
void handleAQUFLUX (HandlerContext&);
void handleBRANPROP (HandlerContext&);
void handleCOMPDAT (HandlerContext&);
void handleCOMPLUMP (HandlerContext&);
Expand Down
4 changes: 4 additions & 0 deletions opm/input/eclipse/Schedule/ScheduleState.hpp
Original file line number Diff line number Diff line change
Expand Up @@ -30,6 +30,7 @@
#include <opm/common/utility/TimeService.hpp>

#include <opm/input/eclipse/EclipseState/Runspec.hpp>
#include <opm/input/eclipse/EclipseState/Aquifer/AquiferFlux.hpp>
#include <opm/input/eclipse/Schedule/Well/PAvg.hpp>
#include <opm/input/eclipse/Schedule/Tuning.hpp>
#include <opm/input/eclipse/Schedule/OilVaporizationProperties.hpp>
Expand Down Expand Up @@ -474,6 +475,8 @@ namespace Opm {
map_member<int, VFPInjTable> vfpinj;
map_member<std::string, Group> groups;
map_member<std::string, Well> wells;
// constant flux aquifers
std::unordered_map<int, SingleAquiferFlux> aqufluxs;
std::unordered_map<std::string, double> target_wellpi;
std::optional<NextStep> next_tstep;

Expand Down Expand Up @@ -501,6 +504,7 @@ namespace Opm {
serializer(m_message_limits);
serializer(m_whistctl_mode);
serializer(target_wellpi);
serializer(aqufluxs);
}


Expand Down
24 changes: 22 additions & 2 deletions src/opm/input/eclipse/EclipseState/Aquifer/AquiferConfig.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -18,6 +18,7 @@
*/


#include <opm/input/eclipse/Deck/DeckSection.hpp>
#include <opm/input/eclipse/EclipseState/Aquifer/AquiferConfig.hpp>
#include <opm/input/eclipse/EclipseState/Tables/TableManager.hpp>
#include <opm/input/eclipse/EclipseState/Grid/EclipseGrid.hpp>
Expand All @@ -33,14 +34,17 @@ AquiferConfig::AquiferConfig(const TableManager& tables,
const FieldPropsManager& field_props)
: aquifetp(tables, deck)
, aquiferct(tables, deck)
, aquiferflux(SOLUTIONSection(deck).getKeywordList("AQUFLUX"))
, numerical_aquifers(deck, grid, field_props)
{}

AquiferConfig::AquiferConfig(const Aquifetp& fetp,
const AquiferCT& ct,
const AquiferFlux& aqufluxs,
const Aquancon& conn)
: aquifetp(fetp)
, aquiferct(ct)
, aquiferflux(aqufluxs)
, aqconn(conn)
{}

Expand All @@ -61,6 +65,7 @@ void AquiferConfig::loadFromRestart(const RestartIO::RstAquifer& aquifers,
{
this->aquifetp.loadFromRestart(aquifers, tables);
this->aquiferct.loadFromRestart(aquifers, tables);
this->aquiferflux.loadFromRestart(aquifers);
this->aqconn.loadFromRestart(aquifers);
}

Expand All @@ -70,6 +75,7 @@ AquiferConfig AquiferConfig::serializationTestObject()
result.aquifetp = Aquifetp::serializationTestObject();
result.aquiferct = AquiferCT::serializationTestObject();
result.aqconn = Aquancon::serializationTestObject();
result.aquiferflux = AquiferFlux::serializationTestObject();
result.numerical_aquifers = NumericalAquifers::serializationTestObject();

return result;
Expand All @@ -83,6 +89,7 @@ bool AquiferConfig::active() const {
bool AquiferConfig::operator==(const AquiferConfig& other) const {
return this->aquifetp == other.aquifetp &&
this->aquiferct == other.aquiferct &&
this->aquiferflux == other.aquiferflux &&
this->aqconn == other.aqconn &&
this->numerical_aquifers == other.numerical_aquifers;
}
Expand All @@ -99,14 +106,19 @@ const Aquancon& AquiferConfig::connections() const {
return this->aqconn;
}

const AquiferFlux& AquiferConfig::aquflux() const {
return this->aquiferflux;
}

bool AquiferConfig::hasAquifer(const int aquID) const {
return this->hasAnalyticalAquifer(aquID) ||
numerical_aquifers.hasAquifer(aquID);
}

bool AquiferConfig::hasAnalyticalAquifer(const int aquID) const {
return aquifetp.hasAquifer(aquID) ||
aquiferct.hasAquifer(aquID);
aquiferct.hasAquifer(aquID) ||
aquiferflux.hasAquifer(aquID);
}

bool AquiferConfig::hasNumericalAquifer() const {
Expand All @@ -123,11 +135,16 @@ NumericalAquifers& AquiferConfig::mutableNumericalAquifers() const {

bool AquiferConfig::hasAnalyticalAquifer() const {
return (this->aquiferct.size() > std::size_t{0})
|| (this->aquifetp.size() > std::size_t{0});
|| (this->aquifetp.size() > std::size_t{0})
|| (this->aquiferflux.size() > std::size_t{0});
}

void AquiferConfig::appendAqufluxSchedule(const std::unordered_set<int>& ids) {
this->aquiferflux.appendAqufluxSchedule(ids);
}

} // end of namespace Opm

std::vector<int> Opm::analyticAquiferIDs(const AquiferConfig& cfg)
{
auto aquiferIDs = std::vector<int>{};
Expand All @@ -141,6 +158,9 @@ std::vector<int> Opm::analyticAquiferIDs(const AquiferConfig& cfg)
for (const auto& aquifer : cfg.fetp())
aquiferIDs.push_back(aquifer.aquiferID);

for (const auto& aquifer : cfg.aquflux())
aquiferIDs.push_back(aquifer.second.id);

std::sort(aquiferIDs.begin(), aquiferIDs.end());

return aquiferIDs;
Expand Down
Loading

0 comments on commit 4825a76

Please sign in to comment.