/* 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