mirror of
https://github.com/OPM/opm-simulators.git
synced 2025-02-25 18:55:30 -06:00
Merge pull request #4576 from bska/face-area-fraction
Calculate Local Face Area Fraction for Aquifer's Connections
This commit is contained in:
commit
675ce03e52
@ -87,17 +87,45 @@ public:
|
|||||||
BlackoilIndices::numPhases>;
|
BlackoilIndices::numPhases>;
|
||||||
|
|
||||||
// Constructor
|
// Constructor
|
||||||
AquiferAnalytical(int aqID,
|
AquiferAnalytical(const int aqID,
|
||||||
const std::vector<Aquancon::AquancCell>& connections,
|
const std::vector<Aquancon::AquancCell>& connections,
|
||||||
const Simulator& ebosSimulator)
|
const Simulator& ebosSimulator)
|
||||||
: AquiferInterface<TypeTag>(aqID, ebosSimulator)
|
: AquiferInterface<TypeTag>(aqID, ebosSimulator)
|
||||||
, connections_(connections)
|
, connections_(connections)
|
||||||
{
|
{
|
||||||
|
this->initializeConnectionMappings();
|
||||||
}
|
}
|
||||||
|
|
||||||
// Destructor
|
// Destructor
|
||||||
virtual ~AquiferAnalytical()
|
virtual ~AquiferAnalytical()
|
||||||
|
{}
|
||||||
|
|
||||||
|
void computeFaceAreaFraction(const std::vector<double>& total_face_area) override
|
||||||
{
|
{
|
||||||
|
assert (total_face_area.size() >= static_cast<std::vector<double>::size_type>(this->aquiferID()));
|
||||||
|
|
||||||
|
const auto tfa = total_face_area[this->aquiferID() - 1];
|
||||||
|
const auto eps_sqrt = std::sqrt(std::numeric_limits<double>::epsilon());
|
||||||
|
|
||||||
|
if (tfa < eps_sqrt) {
|
||||||
|
this->alphai_.assign(this->size(), Scalar{0});
|
||||||
|
}
|
||||||
|
else {
|
||||||
|
std::transform(this->faceArea_connected_.begin(),
|
||||||
|
this->faceArea_connected_.end(),
|
||||||
|
this->alphai_.begin(),
|
||||||
|
[tfa](const Scalar area)
|
||||||
|
{
|
||||||
|
return area / tfa;
|
||||||
|
});
|
||||||
|
}
|
||||||
|
|
||||||
|
this->area_fraction_ = this->totalFaceArea() / tfa;
|
||||||
|
}
|
||||||
|
|
||||||
|
double totalFaceArea() const override
|
||||||
|
{
|
||||||
|
return this->total_face_area_;
|
||||||
}
|
}
|
||||||
|
|
||||||
void initFromRestart(const data::Aquifers& aquiferSoln) override
|
void initFromRestart(const data::Aquifers& aquiferSoln) override
|
||||||
@ -108,8 +136,9 @@ public:
|
|||||||
|
|
||||||
this->assignRestartData(xaqPos->second);
|
this->assignRestartData(xaqPos->second);
|
||||||
|
|
||||||
this->W_flux_ = xaqPos->second.volume;
|
this->W_flux_ = xaqPos->second.volume * this->area_fraction_;
|
||||||
this->pa0_ = xaqPos->second.initPressure;
|
this->pa0_ = xaqPos->second.initPressure;
|
||||||
|
|
||||||
this->solution_set_from_restart_ = true;
|
this->solution_set_from_restart_ = true;
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -226,19 +255,17 @@ protected:
|
|||||||
void initQuantities()
|
void initQuantities()
|
||||||
{
|
{
|
||||||
// We reset the cumulative flux at the start of any simulation, so, W_flux = 0
|
// We reset the cumulative flux at the start of any simulation, so, W_flux = 0
|
||||||
if (!this->solution_set_from_restart_) {
|
if (! this->solution_set_from_restart_) {
|
||||||
W_flux_ = Scalar{0};
|
W_flux_ = Scalar{0};
|
||||||
}
|
}
|
||||||
|
|
||||||
// We next get our connections to the aquifer and initialize these quantities using the initialize_connections
|
this->initializeConnectionDepths();
|
||||||
// function
|
this->calculateAquiferCondition();
|
||||||
initializeConnections();
|
this->calculateAquiferConstants();
|
||||||
calculateAquiferCondition();
|
|
||||||
calculateAquiferConstants();
|
|
||||||
|
|
||||||
pressure_previous_.resize(this->connections_.size(), Scalar{0});
|
this->pressure_previous_.resize(this->size(), Scalar{0});
|
||||||
pressure_current_.resize(this->connections_.size(), Scalar{0});
|
this->pressure_current_.resize(this->size(), Scalar{0});
|
||||||
Qai_.resize(this->connections_.size(), Scalar{0});
|
this->Qai_.resize(this->size(), Scalar{0});
|
||||||
}
|
}
|
||||||
|
|
||||||
void updateCellPressure(std::vector<Eval>& pressure_water,
|
void updateCellPressure(std::vector<Eval>& pressure_water,
|
||||||
@ -257,54 +284,54 @@ protected:
|
|||||||
pressure_water.at(idx) = fs.pressure(this->phaseIdx_()).value();
|
pressure_water.at(idx) = fs.pressure(this->phaseIdx_()).value();
|
||||||
}
|
}
|
||||||
|
|
||||||
void initializeConnections()
|
void initializeConnectionMappings()
|
||||||
{
|
{
|
||||||
this->cell_depth_.resize(this->size(), this->aquiferDepth());
|
|
||||||
this->alphai_.resize(this->size(), 1.0);
|
this->alphai_.resize(this->size(), 1.0);
|
||||||
this->faceArea_connected_.resize(this->size(), Scalar{0});
|
this->faceArea_connected_.resize(this->size(), Scalar{0});
|
||||||
|
|
||||||
// Translate the C face tag into the enum used by opm-parser's TransMult class
|
// total_face_area_ is the sum of the areas connected to an aquifer
|
||||||
FaceDir::DirEnum faceDirection;
|
this->total_face_area_ = Scalar{0};
|
||||||
|
|
||||||
bool has_active_connection_on_proc = false;
|
|
||||||
|
|
||||||
// denom_face_areas is the sum of the areas connected to an aquifer
|
|
||||||
Scalar denom_face_areas{0};
|
|
||||||
this->cellToConnectionIdx_.resize(this->ebos_simulator_.gridView().size(/*codim=*/0), -1);
|
this->cellToConnectionIdx_.resize(this->ebos_simulator_.gridView().size(/*codim=*/0), -1);
|
||||||
const auto& gridView = this->ebos_simulator_.vanguard().gridView();
|
const auto& gridView = this->ebos_simulator_.vanguard().gridView();
|
||||||
for (std::size_t idx = 0; idx < this->size(); ++idx) {
|
for (std::size_t idx = 0; idx < this->size(); ++idx) {
|
||||||
const auto global_index = this->connections_[idx].global_index;
|
const auto global_index = this->connections_[idx].global_index;
|
||||||
const int cell_index = this->ebos_simulator_.vanguard().compressedIndex(global_index);
|
const int cell_index = this->ebos_simulator_.vanguard().compressedIndex(global_index);
|
||||||
|
if (cell_index < 0) {
|
||||||
|
continue;
|
||||||
|
}
|
||||||
|
|
||||||
auto elemIt = gridView.template begin</*codim=*/ 0>();
|
auto elemIt = gridView.template begin</*codim=*/ 0>();
|
||||||
if (cell_index > 0)
|
|
||||||
std::advance(elemIt, cell_index);
|
std::advance(elemIt, cell_index);
|
||||||
|
|
||||||
//the global_index is not part of this grid
|
// The global_index is not part of this grid
|
||||||
if ( cell_index < 0 || elemIt->partitionType() != Dune::InteriorEntity)
|
if (elemIt->partitionType() != Dune::InteriorEntity) {
|
||||||
continue;
|
continue;
|
||||||
|
}
|
||||||
has_active_connection_on_proc = true;
|
|
||||||
|
|
||||||
this->cellToConnectionIdx_[cell_index] = idx;
|
this->cellToConnectionIdx_[cell_index] = idx;
|
||||||
this->cell_depth_.at(idx) = this->ebos_simulator_.vanguard().cellCenterDepth(cell_index);
|
|
||||||
}
|
}
|
||||||
// get areas for all connections
|
|
||||||
ElementMapper elemMapper(gridView, Dune::mcmgElementLayout());
|
|
||||||
for (const auto& elem : elements(gridView)) {
|
|
||||||
unsigned cell_index = elemMapper.index(elem);
|
|
||||||
int idx = this->cellToConnectionIdx_[cell_index];
|
|
||||||
|
|
||||||
// only deal with connections given by the aquifer
|
// Translate the C face tag into the enum used by opm-parser's TransMult class
|
||||||
if( idx < 0)
|
FaceDir::DirEnum faceDirection;
|
||||||
|
|
||||||
|
// Get areas for all connections
|
||||||
|
const auto& elemMapper = this->ebos_simulator_.model().dofMapper();
|
||||||
|
for (const auto& elem : elements(gridView)) {
|
||||||
|
const unsigned cell_index = elemMapper.index(elem);
|
||||||
|
const int idx = this->cellToConnectionIdx_[cell_index];
|
||||||
|
|
||||||
|
// Only deal with connections given by the aquifer
|
||||||
|
if (idx < 0) {
|
||||||
continue;
|
continue;
|
||||||
|
}
|
||||||
|
|
||||||
for (const auto& intersection : intersections(gridView, elem)) {
|
for (const auto& intersection : intersections(gridView, elem)) {
|
||||||
// only deal with grid boundaries
|
// Only deal with grid boundaries
|
||||||
if (!intersection.boundary())
|
if (! intersection.boundary()) {
|
||||||
continue;
|
continue;
|
||||||
|
}
|
||||||
|
|
||||||
int insideFaceIdx = intersection.indexInInside();
|
switch (intersection.indexInInside()) {
|
||||||
switch (insideFaceIdx) {
|
|
||||||
case 0:
|
case 0:
|
||||||
faceDirection = FaceDir::XMinus;
|
faceDirection = FaceDir::XMinus;
|
||||||
break;
|
break;
|
||||||
@ -328,48 +355,38 @@ protected:
|
|||||||
"Internal error in initialization of aquifer.");
|
"Internal error in initialization of aquifer.");
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
if (faceDirection == this->connections_[idx].face_dir) {
|
if (faceDirection == this->connections_[idx].face_dir) {
|
||||||
this->faceArea_connected_[idx] = this->connections_[idx].influx_coeff;
|
this->faceArea_connected_[idx] = this->connections_[idx].influx_coeff;
|
||||||
break;
|
break;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
denom_face_areas += this->faceArea_connected_.at(idx);
|
|
||||||
}
|
|
||||||
|
|
||||||
const auto& comm = this->ebos_simulator_.vanguard().grid().comm();
|
this->total_face_area_ += this->faceArea_connected_.at(idx);
|
||||||
comm.sum(&denom_face_areas, 1);
|
|
||||||
const double eps_sqrt = std::sqrt(std::numeric_limits<double>::epsilon());
|
|
||||||
for (std::size_t idx = 0; idx < this->size(); ++idx) {
|
|
||||||
// Protect against division by zero NaNs.
|
|
||||||
this->alphai_.at(idx) = (denom_face_areas < eps_sqrt)
|
|
||||||
? Scalar{0}
|
|
||||||
: this->faceArea_connected_.at(idx) / denom_face_areas;
|
|
||||||
}
|
|
||||||
|
|
||||||
if (this->solution_set_from_restart_) {
|
|
||||||
this->rescaleProducedVolume(has_active_connection_on_proc);
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
void rescaleProducedVolume(const bool has_active_connection_on_proc)
|
void initializeConnectionDepths()
|
||||||
{
|
{
|
||||||
// Needed in parallel restart to approximate influence of aquifer
|
this->cell_depth_.resize(this->size(), this->aquiferDepth());
|
||||||
// being "owned" by a subset of the parallel processes. If the
|
|
||||||
// aquifer is fully owned by a single process--i.e., if all cells
|
|
||||||
// connecting to the aquifer are on a single process--then this_area
|
|
||||||
// is tot_area on that process and zero elsewhere.
|
|
||||||
|
|
||||||
const auto this_area = has_active_connection_on_proc
|
const auto& gridView = this->ebos_simulator_.vanguard().gridView();
|
||||||
? std::accumulate(this->alphai_.begin(),
|
for (std::size_t idx = 0; idx < this->size(); ++idx) {
|
||||||
this->alphai_.end(),
|
const int cell_index = this->ebos_simulator_.vanguard()
|
||||||
Scalar{0})
|
.compressedIndex(this->connections_[idx].global_index);
|
||||||
: Scalar{0};
|
if (cell_index < 0) {
|
||||||
|
continue;
|
||||||
|
}
|
||||||
|
|
||||||
const auto tot_area = this->ebos_simulator_.vanguard()
|
auto elemIt = gridView.template begin</*codim=*/ 0>();
|
||||||
.grid().comm().sum(this_area);
|
std::advance(elemIt, cell_index);
|
||||||
|
|
||||||
this->W_flux_ *= this_area / tot_area;
|
// The global_index is not part of this grid
|
||||||
|
if (elemIt->partitionType() != Dune::InteriorEntity) {
|
||||||
|
continue;
|
||||||
|
}
|
||||||
|
|
||||||
|
this->cell_depth_.at(idx) = this->ebos_simulator_.vanguard().cellCenterDepth(cell_index);
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
// This function is for calculating the aquifer properties from equilibrium state with the reservoir
|
// This function is for calculating the aquifer properties from equilibrium state with the reservoir
|
||||||
@ -433,9 +450,13 @@ protected:
|
|||||||
std::optional<Scalar> Ta0_{}; // initial aquifer temperature
|
std::optional<Scalar> Ta0_{}; // initial aquifer temperature
|
||||||
Scalar rhow_{};
|
Scalar rhow_{};
|
||||||
|
|
||||||
|
Scalar total_face_area_{};
|
||||||
|
Scalar area_fraction_{Scalar{1}};
|
||||||
|
|
||||||
Eval W_flux_;
|
Eval W_flux_;
|
||||||
|
|
||||||
bool solution_set_from_restart_ {false};
|
bool solution_set_from_restart_ {false};
|
||||||
|
bool has_active_connection_on_proc_{false};
|
||||||
};
|
};
|
||||||
|
|
||||||
} // namespace Opm
|
} // namespace Opm
|
||||||
|
@ -32,8 +32,10 @@
|
|||||||
#include <opm/material/densead/Evaluation.hpp>
|
#include <opm/material/densead/Evaluation.hpp>
|
||||||
|
|
||||||
#include <algorithm>
|
#include <algorithm>
|
||||||
|
#include <cassert>
|
||||||
#include <numeric>
|
#include <numeric>
|
||||||
#include <stdexcept>
|
#include <stdexcept>
|
||||||
|
#include <vector>
|
||||||
|
|
||||||
namespace Opm {
|
namespace Opm {
|
||||||
|
|
||||||
@ -58,7 +60,7 @@ public:
|
|||||||
, aquifer_data_ (aquifer)
|
, aquifer_data_ (aquifer)
|
||||||
, connection_flux_ (connections_.size(), Eval{0})
|
, connection_flux_ (connections_.size(), Eval{0})
|
||||||
{
|
{
|
||||||
this->initializeConnections();
|
this->total_face_area_ = this->initializeConnections();
|
||||||
}
|
}
|
||||||
|
|
||||||
static AquiferConstantFlux serializationTestObject(const Simulator& ebos_simulator)
|
static AquiferConstantFlux serializationTestObject(const Simulator& ebos_simulator)
|
||||||
@ -71,6 +73,19 @@ public:
|
|||||||
|
|
||||||
virtual ~AquiferConstantFlux() = default;
|
virtual ~AquiferConstantFlux() = default;
|
||||||
|
|
||||||
|
void computeFaceAreaFraction(const std::vector<double>& total_face_area) override
|
||||||
|
{
|
||||||
|
assert (total_face_area.size() >= static_cast<std::vector<double>::size_type>(this->aquiferID()));
|
||||||
|
|
||||||
|
this->area_fraction_ = this->totalFaceArea()
|
||||||
|
/ total_face_area[this->aquiferID() - 1];
|
||||||
|
}
|
||||||
|
|
||||||
|
double totalFaceArea() const override
|
||||||
|
{
|
||||||
|
return this->total_face_area_;
|
||||||
|
}
|
||||||
|
|
||||||
void updateAquifer(const SingleAquiferFlux& aquifer)
|
void updateAquifer(const SingleAquiferFlux& aquifer)
|
||||||
{
|
{
|
||||||
aquifer_data_ = aquifer;
|
aquifer_data_ = aquifer;
|
||||||
@ -149,9 +164,16 @@ private:
|
|||||||
std::vector<int> cellToConnectionIdx_{};
|
std::vector<int> cellToConnectionIdx_{};
|
||||||
double flux_rate_{};
|
double flux_rate_{};
|
||||||
double cumulative_flux_{};
|
double cumulative_flux_{};
|
||||||
|
double total_face_area_{0.0};
|
||||||
|
double area_fraction_{1.0};
|
||||||
|
|
||||||
|
double initializeConnections()
|
||||||
|
{
|
||||||
|
auto connected_face_area = 0.0;
|
||||||
|
|
||||||
|
this->cellToConnectionIdx_
|
||||||
|
.resize(this->ebos_simulator_.gridView().size(/*codim=*/0), -1);
|
||||||
|
|
||||||
void initializeConnections() {
|
|
||||||
this->cellToConnectionIdx_.resize(this->ebos_simulator_.gridView().size(/*codim=*/0), -1);
|
|
||||||
for (std::size_t idx = 0; idx < this->connections_.size(); ++idx) {
|
for (std::size_t idx = 0; idx < this->connections_.size(); ++idx) {
|
||||||
const auto global_index = this->connections_[idx].global_index;
|
const auto global_index = this->connections_[idx].global_index;
|
||||||
const int cell_index = this->ebos_simulator_.vanguard()
|
const int cell_index = this->ebos_simulator_.vanguard()
|
||||||
@ -162,11 +184,25 @@ private:
|
|||||||
}
|
}
|
||||||
|
|
||||||
this->cellToConnectionIdx_[cell_index] = idx;
|
this->cellToConnectionIdx_[cell_index] = idx;
|
||||||
|
|
||||||
|
connected_face_area += this->connections_[idx].effective_facearea;
|
||||||
}
|
}
|
||||||
|
|
||||||
// TODO: At the moment, we are using the effective_facearea from the
|
// TODO: At the moment, we are using the effective_facearea from the
|
||||||
// parser. Should we update the facearea here if the grid changed
|
// parser. Should we update the facearea here if the grid changed
|
||||||
// during the preprocessing?
|
// during the preprocessing?
|
||||||
|
|
||||||
|
return connected_face_area;
|
||||||
|
}
|
||||||
|
|
||||||
|
double computeFaceAreaFraction(const double connected_face_area) const
|
||||||
|
{
|
||||||
|
const auto tot_face_area = this->ebos_simulator_.vanguard()
|
||||||
|
.grid().comm().sum(connected_face_area);
|
||||||
|
|
||||||
|
return (tot_face_area > 0.0)
|
||||||
|
? connected_face_area / tot_face_area
|
||||||
|
: 0.0;
|
||||||
}
|
}
|
||||||
|
|
||||||
// TODO: this is a function from AquiferAnalytical
|
// TODO: this is a function from AquiferAnalytical
|
||||||
|
@ -58,6 +58,9 @@ public:
|
|||||||
|
|
||||||
virtual data::AquiferData aquiferData() const = 0;
|
virtual data::AquiferData aquiferData() const = 0;
|
||||||
|
|
||||||
|
virtual void computeFaceAreaFraction(const std::vector<double>& total_face_area) = 0;
|
||||||
|
virtual double totalFaceArea() const = 0;
|
||||||
|
|
||||||
template <class Context>
|
template <class Context>
|
||||||
void addToSource(RateVector& rates,
|
void addToSource(RateVector& rates,
|
||||||
const Context& context,
|
const Context& context,
|
||||||
|
@ -154,6 +154,14 @@ public:
|
|||||||
this->cumulative_flux_ = 0.;
|
this->cumulative_flux_ = 0.;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
void computeFaceAreaFraction(const std::vector<double>& /*total_face_area*/) override
|
||||||
|
{}
|
||||||
|
|
||||||
|
double totalFaceArea() const override
|
||||||
|
{
|
||||||
|
return 1.0;
|
||||||
|
}
|
||||||
|
|
||||||
template<class Serializer>
|
template<class Serializer>
|
||||||
void serializeOp(Serializer& serializer)
|
void serializeOp(Serializer& serializer)
|
||||||
{
|
{
|
||||||
|
@ -140,6 +140,8 @@ private:
|
|||||||
createAnalyticAquiferPointer(const AquiferData& aqData,
|
createAnalyticAquiferPointer(const AquiferData& aqData,
|
||||||
const int aquiferID,
|
const int aquiferID,
|
||||||
std::string_view aqType) const;
|
std::string_view aqType) const;
|
||||||
|
|
||||||
|
void computeConnectionAreaFraction() const;
|
||||||
};
|
};
|
||||||
|
|
||||||
|
|
||||||
|
@ -45,16 +45,22 @@ template <typename TypeTag>
|
|||||||
void
|
void
|
||||||
BlackoilAquiferModel<TypeTag>::initialSolutionApplied()
|
BlackoilAquiferModel<TypeTag>::initialSolutionApplied()
|
||||||
{
|
{
|
||||||
for (auto& aquifer : aquifers)
|
this->computeConnectionAreaFraction();
|
||||||
|
|
||||||
|
for (auto& aquifer : this->aquifers) {
|
||||||
aquifer->initialSolutionApplied();
|
aquifer->initialSolutionApplied();
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
template <typename TypeTag>
|
template <typename TypeTag>
|
||||||
void
|
void
|
||||||
BlackoilAquiferModel<TypeTag>::initFromRestart(const data::Aquifers& aquiferSoln)
|
BlackoilAquiferModel<TypeTag>::initFromRestart(const data::Aquifers& aquiferSoln)
|
||||||
{
|
{
|
||||||
for (auto& aquifer : this->aquifers)
|
this->computeConnectionAreaFraction();
|
||||||
|
|
||||||
|
for (auto& aquifer : this->aquifers) {
|
||||||
aquifer->initFromRestart(aquiferSoln);
|
aquifer->initFromRestart(aquiferSoln);
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
template <typename TypeTag>
|
template <typename TypeTag>
|
||||||
@ -67,6 +73,8 @@ BlackoilAquiferModel<TypeTag>::beginEpisode()
|
|||||||
// SCHEDULE setup in this section it is the beginning of a report step
|
// SCHEDULE setup in this section it is the beginning of a report step
|
||||||
|
|
||||||
this->createDynamicAquifers(this->simulator_.episodeIndex());
|
this->createDynamicAquifers(this->simulator_.episodeIndex());
|
||||||
|
|
||||||
|
this->computeConnectionAreaFraction();
|
||||||
}
|
}
|
||||||
|
|
||||||
template <typename TypeTag>
|
template <typename TypeTag>
|
||||||
@ -78,8 +86,9 @@ template <typename TypeTag>
|
|||||||
void
|
void
|
||||||
BlackoilAquiferModel<TypeTag>::beginTimeStep()
|
BlackoilAquiferModel<TypeTag>::beginTimeStep()
|
||||||
{
|
{
|
||||||
for (auto& aquifer : aquifers)
|
for (auto& aquifer : this->aquifers) {
|
||||||
aquifer->beginTimeStep();
|
aquifer->beginTimeStep();
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
template <typename TypeTag>
|
template <typename TypeTag>
|
||||||
@ -90,8 +99,9 @@ BlackoilAquiferModel<TypeTag>::addToSource(RateVector& rates,
|
|||||||
unsigned spaceIdx,
|
unsigned spaceIdx,
|
||||||
unsigned timeIdx) const
|
unsigned timeIdx) const
|
||||||
{
|
{
|
||||||
for (auto& aquifer : aquifers)
|
for (auto& aquifer : this->aquifers) {
|
||||||
aquifer->addToSource(rates, context, spaceIdx, timeIdx);
|
aquifer->addToSource(rates, context, spaceIdx, timeIdx);
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
template <typename TypeTag>
|
template <typename TypeTag>
|
||||||
@ -100,8 +110,9 @@ BlackoilAquiferModel<TypeTag>::addToSource(RateVector& rates,
|
|||||||
unsigned globalSpaceIdx,
|
unsigned globalSpaceIdx,
|
||||||
unsigned timeIdx) const
|
unsigned timeIdx) const
|
||||||
{
|
{
|
||||||
for (auto& aquifer : aquifers)
|
for (auto& aquifer : this->aquifers) {
|
||||||
aquifer->addToSource(rates, globalSpaceIdx, timeIdx);
|
aquifer->addToSource(rates, globalSpaceIdx, timeIdx);
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
template <typename TypeTag>
|
template <typename TypeTag>
|
||||||
@ -113,9 +124,10 @@ template <typename TypeTag>
|
|||||||
void
|
void
|
||||||
BlackoilAquiferModel<TypeTag>::endTimeStep()
|
BlackoilAquiferModel<TypeTag>::endTimeStep()
|
||||||
{
|
{
|
||||||
for (auto& aquifer : aquifers) {
|
|
||||||
aquifer->endTimeStep();
|
|
||||||
using NumAq = AquiferNumerical<TypeTag>;
|
using NumAq = AquiferNumerical<TypeTag>;
|
||||||
|
|
||||||
|
for (auto& aquifer : this->aquifers) {
|
||||||
|
aquifer->endTimeStep();
|
||||||
NumAq* num = dynamic_cast<NumAq*>(aquifer.get());
|
NumAq* num = dynamic_cast<NumAq*>(aquifer.get());
|
||||||
if (num)
|
if (num)
|
||||||
this->simulator_.vanguard().grid().comm().barrier();
|
this->simulator_.vanguard().grid().comm().barrier();
|
||||||
@ -159,8 +171,9 @@ template<typename TypeTag>
|
|||||||
data::Aquifers BlackoilAquiferModel<TypeTag>::aquiferData() const
|
data::Aquifers BlackoilAquiferModel<TypeTag>::aquiferData() const
|
||||||
{
|
{
|
||||||
data::Aquifers data;
|
data::Aquifers data;
|
||||||
for (const auto& aqu : this->aquifers)
|
for (const auto& aqu : this->aquifers) {
|
||||||
data.insert_or_assign(aqu->aquiferID(), aqu->aquiferData());
|
data.insert_or_assign(aqu->aquiferID(), aqu->aquiferData());
|
||||||
|
}
|
||||||
|
|
||||||
return data;
|
return data;
|
||||||
}
|
}
|
||||||
@ -170,7 +183,7 @@ template<class Serializer>
|
|||||||
void BlackoilAquiferModel<TypeTag>::
|
void BlackoilAquiferModel<TypeTag>::
|
||||||
serializeOp(Serializer& serializer)
|
serializeOp(Serializer& serializer)
|
||||||
{
|
{
|
||||||
for (auto& aiPtr : aquifers) {
|
for (auto& aiPtr : this->aquifers) {
|
||||||
auto* ct = dynamic_cast<AquiferCarterTracy<TypeTag>*>(aiPtr.get());
|
auto* ct = dynamic_cast<AquiferCarterTracy<TypeTag>*>(aiPtr.get());
|
||||||
auto* fetp = dynamic_cast<AquiferFetkovich<TypeTag>*>(aiPtr.get());
|
auto* fetp = dynamic_cast<AquiferFetkovich<TypeTag>*>(aiPtr.get());
|
||||||
auto* num = dynamic_cast<AquiferNumerical<TypeTag>*>(aiPtr.get());
|
auto* num = dynamic_cast<AquiferNumerical<TypeTag>*>(aiPtr.get());
|
||||||
@ -304,4 +317,26 @@ void BlackoilAquiferModel<TypeTag>::createDynamicAquifers(const int episode_inde
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
template <typename TypeTag>
|
||||||
|
void BlackoilAquiferModel<TypeTag>::computeConnectionAreaFraction() const
|
||||||
|
{
|
||||||
|
auto maxAquID =
|
||||||
|
std::accumulate(this->aquifers.begin(), this->aquifers.end(), 0,
|
||||||
|
[](const int aquID, const auto& aquifer)
|
||||||
|
{ return std::max(aquID, aquifer->aquiferID()); });
|
||||||
|
|
||||||
|
maxAquID = this->simulator_.vanguard().grid().comm().max(maxAquID);
|
||||||
|
|
||||||
|
auto totalConnArea = std::vector<double>(maxAquID, 0.0);
|
||||||
|
for (const auto& aquifer : this->aquifers) {
|
||||||
|
totalConnArea[aquifer->aquiferID() - 1] += aquifer->totalFaceArea();
|
||||||
|
}
|
||||||
|
|
||||||
|
this->simulator_.vanguard().grid().comm().sum(totalConnArea.data(), maxAquID);
|
||||||
|
|
||||||
|
for (auto& aquifer : this->aquifers) {
|
||||||
|
aquifer->computeFaceAreaFraction(totalConnArea);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
} // namespace Opm
|
} // namespace Opm
|
||||||
|
Loading…
Reference in New Issue
Block a user