/*
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 .
*/
#ifndef OPM_AQUIFERCONSTANTFLUX_HPP
#define OPM_AQUIFERCONSTANTFLUX_HPP
#include
#include
#include
#include
#include
#include
#include
#include
#include
#include
namespace Opm {
template
class AquiferConstantFlux : public AquiferInterface
{
public:
using RateVector = GetPropType;
using Simulator = GetPropType;
using ElementMapper = GetPropType;
using FluidSystem = GetPropType;
using BlackoilIndices = GetPropType;
static constexpr int numEq = BlackoilIndices::numEq;
using Eval = DenseAd::Evaluation;
AquiferConstantFlux(const std::vector& connections,
const Simulator& ebos_simulator,
const SingleAquiferFlux& aquifer)
: AquiferInterface(aquifer.id, ebos_simulator)
, connections_ (connections)
, aquifer_data_ (aquifer)
, connection_flux_ (connections_.size(), Eval{0})
{
this->initializeConnections();
}
static AquiferConstantFlux serializationTestObject(const Simulator& ebos_simulator)
{
AquiferConstantFlux result({}, ebos_simulator, {});
result.cumulative_flux_ = 1.0;
return result;
}
virtual ~AquiferConstantFlux() = default;
void updateAquifer(const SingleAquiferFlux& aquifer)
{
aquifer_data_ = aquifer;
}
void initFromRestart(const data::Aquifers& /* aquiferSoln */) override {
}
void initialSolutionApplied() override {
}
void beginTimeStep() override
{}
void endTimeStep() override
{
this->flux_rate_ = this->totalFluxRate();
this->cumulative_flux_ +=
this->flux_rate_ * this->ebos_simulator_.timeStepSize();
}
data::AquiferData aquiferData() const override
{
data::AquiferData data;
data.aquiferID = this->aquifer_data_.id;
// Pressure for constant flux aquifer is 0
data.pressure = 0.0;
data.fluxRate = this->totalFluxRate();
data.volume = this->cumulative_flux_;
// not totally sure whether initPressure matters
data.initPressure = 0.0;
return data;
}
void addToSource(RateVector& rates,
const unsigned cellIdx,
[[maybe_unused]] const unsigned timeIdx) override
{
const int idx = this->cellToConnectionIdx_[cellIdx];
if (idx < 0) {
return;
}
const auto& model = this->ebos_simulator_.model();
const auto fw = this->aquifer_data_.flux;
this->connection_flux_[idx] = fw * this->connections_[idx].effective_facearea;
rates[BlackoilIndices::conti0EqIdx + compIdx_()]
+= this->connection_flux_[idx] / model.dofTotalVolume(cellIdx);
}
template
void serializeOp(Serializer& serializer)
{
serializer(cumulative_flux_);
}
bool operator==(const AquiferConstantFlux& rhs) const
{
return this->cumulative_flux_ == rhs.cumulative_flux_;
}
private:
const std::vector& connections_;
SingleAquiferFlux aquifer_data_;
std::vector connection_flux_{};
std::vector cellToConnectionIdx_{};
double flux_rate_{};
double cumulative_flux_{};
void initializeConnections() {
this->cellToConnectionIdx_.resize(this->ebos_simulator_.gridView().size(/*codim=*/0), -1);
for (std::size_t idx = 0; idx < this->connections_.size(); ++idx) {
const auto global_index = this->connections_[idx].global_index;
const int cell_index = this->ebos_simulator_.vanguard()
.compressedIndexForInterior(global_index);
if (cell_index < 0) {
continue;
}
this->cellToConnectionIdx_[cell_index] = idx;
}
// TODO: At the moment, we are using the effective_facearea from the
// parser. Should we update the facearea here if the grid changed
// during the preprocessing?
}
// TODO: this is a function from AquiferAnalytical
int compIdx_() const
{
if (this->co2store_())
return FluidSystem::oilCompIdx;
return FluidSystem::waterCompIdx;
}
double totalFluxRate() const
{
return std::accumulate(this->connection_flux_.begin(),
this->connection_flux_.end(), 0.0,
[](const double rate, const auto& q)
{
return rate + getValue(q);
});
}
};
} // namespace Opm
#endif //OPM_AQUIFERCONSTANTFLUX_HPP