20#ifndef OPM_BLACKOILAQUIFERMODEL_IMPL_HEADER_INCLUDED
21#define OPM_BLACKOILAQUIFERMODEL_IMPL_HEADER_INCLUDED
24#ifndef OPM_BLACKOILAQUIFERMODEL_HEADER_INCLUDED
31#include <opm/common/ErrorMacros.hpp>
33#include <fmt/format.h>
43template <
typename TypeTag>
45 : simulator_(simulator)
48 using Grid = std::remove_const_t<std::remove_reference_t<
decltype(simulator.vanguard().grid())>>;
54template <
typename TypeTag>
58 this->computeConnectionAreaFraction();
60 for (
auto& aquifer : this->aquifers) {
61 aquifer->initialSolutionApplied();
65template <
typename TypeTag>
69 this->computeConnectionAreaFraction();
71 for (
auto& aquifer : this->aquifers) {
72 aquifer->initFromRestart(aquiferSoln);
76template <
typename TypeTag>
85 this->createDynamicAquifers(this->simulator_.episodeIndex());
87 this->computeConnectionAreaFraction();
90template <
typename TypeTag>
95template <
typename TypeTag>
99 for (
auto& aquifer : this->aquifers) {
100 aquifer->beginTimeStep();
104template <
typename TypeTag>
105template <
class Context>
108 const Context& context,
110 unsigned timeIdx)
const
112 for (
auto& aquifer : this->aquifers) {
113 aquifer->addToSource(rates, context, spaceIdx, timeIdx);
117template <
typename TypeTag>
120 unsigned globalSpaceIdx,
121 unsigned timeIdx)
const
123 for (
auto& aquifer : this->aquifers) {
124 aquifer->addToSource(rates, globalSpaceIdx, timeIdx);
128template <
typename TypeTag>
133template <
typename TypeTag>
139 for (
const auto& aquifer : this->aquifers) {
141 const NumAq* num =
dynamic_cast<const NumAq*
>(aquifer.get());
143 this->simulator_.vanguard().grid().comm().barrier();
148template <
typename TypeTag>
153template <
typename TypeTag>
154template <
class Restarter>
159 throw std::logic_error(
"BlackoilAquiferModel::serialize() is not yet implemented");
162template <
typename TypeTag>
163template <
class Restarter>
168 throw std::logic_error(
"BlackoilAquiferModel::deserialize() is not yet implemented");
172template <
typename TypeTag>
175 if (this->simulator_.vanguard().eclState().aquifer().active()) {
176 this->initializeStaticAquifers();
179 if (this->needRestartDynamicAquifers()) {
180 this->initializeRestartDynamicAquifers();
184template<
typename TypeTag>
188 for (
const auto& aqu : this->aquifers) {
189 data.insert_or_assign(aqu->aquiferID(), aqu->aquiferData());
195template<
typename TypeTag>
196template<
class Serializer>
200 for (
auto& aiPtr : this->aquifers) {
214 OPM_THROW(std::logic_error,
"Error serializing BlackoilAquiferModel: unknown aquifer type");
219template <
typename TypeTag>
222 const auto rstStep = this->simulator_.vanguard().eclState()
223 .getInitConfig().getRestartStep() - 1;
225 this->createDynamicAquifers(rstStep);
228template <
typename TypeTag>
229void BlackoilAquiferModel<TypeTag>::initializeStaticAquifers()
231 const auto& aquifer =
232 this->simulator_.vanguard().eclState().aquifer();
234 for (
const auto& aquCT : aquifer.ct()) {
235 auto aquCTPtr = this->
template createAnalyticAquiferPointer
236 <AquiferCarterTracy<TypeTag>>(aquCT, aquCT.aquiferID,
"Carter-Tracy");
238 if (aquCTPtr !=
nullptr) {
239 this->aquifers.push_back(std::move(aquCTPtr));
243 for (
const auto& aquFetp : aquifer.fetp()) {
244 auto aquFetpPtr = this->
template createAnalyticAquiferPointer
245 <AquiferFetkovich<TypeTag>>(aquFetp, aquFetp.aquiferID,
"Fetkovich");
247 if (aquFetpPtr !=
nullptr) {
248 this->aquifers.push_back(std::move(aquFetpPtr));
252 for (
const auto& [
id, aquFlux] : aquifer.aquflux()) {
254 if (! aquFlux.active) {
continue; }
256 auto aquFluxPtr = this->
template createAnalyticAquiferPointer
257 <AquiferConstantFlux<TypeTag>>(aquFlux, id,
"Constant Flux");
259 if (aquFluxPtr !=
nullptr) {
260 this->aquifers.push_back(std::move(aquFluxPtr));
264 if (aquifer.hasNumericalAquifer()) {
265 for (
const auto& aquNum : aquifer.numericalAquifers().aquifers()) {
266 auto aquNumPtr = std::make_unique<AquiferNumerical<TypeTag>>
267 (aquNum.second, this->simulator_);
269 this->aquifers.push_back(std::move(aquNumPtr));
274template <
typename TypeTag>
275bool BlackoilAquiferModel<TypeTag>::needRestartDynamicAquifers()
const
277 const auto& initconfig =
278 this->simulator_.vanguard().eclState().getInitConfig();
280 if (! initconfig.restartRequested()) {
284 return this->simulator_.vanguard()
285 .schedule()[initconfig.getRestartStep() - 1].hasAnalyticalAquifers();
288template <
typename TypeTag>
289template <
typename AquiferType,
typename AquiferData>
290std::unique_ptr<AquiferType>
291BlackoilAquiferModel<TypeTag>::
292createAnalyticAquiferPointer(
const AquiferData& aqData,
294 std::string_view aqType)
const
296 const auto& connections =
297 this->simulator_.vanguard().eclState().aquifer().connections();
299 if (! connections.hasAquiferConnections(aquiferID)) {
300 const auto msg = fmt::format(
"No valid connections for {} aquifer {}. "
301 "Aquifer {} will be ignored.",
302 aqType, aquiferID, aquiferID);
303 OpmLog::warning(msg);
308 return std::make_unique<AquiferType>
309 (connections.getConnections(aquiferID), this->simulator_, aqData);
312template <
typename TypeTag>
313void BlackoilAquiferModel<TypeTag>::createDynamicAquifers(
const int episode_index)
315 const auto& sched = this->simulator_.vanguard().schedule()[episode_index];
317 for (
const auto& [
id, aquFlux] : sched.aqufluxs) {
319 std::find_if(std::begin(this->aquifers),
320 std::end(this->aquifers),
321 [Id =
id](
const auto& aquPtr)
323 return aquPtr->aquiferID() == Id;
326 if (aquPos == std::end(this->aquifers)) {
329 auto aquFluxPtr = this->
template createAnalyticAquiferPointer
330 <AquiferConstantFlux<TypeTag>>(aquFlux, id,
"Constant Flux");
332 if (aquFluxPtr !=
nullptr) {
333 this->aquifers.push_back(std::move(aquFluxPtr));
337 auto aquFluxPtr =
dynamic_cast<AquiferConstantFlux<TypeTag>*
>(aquPos->get());
338 if (aquFluxPtr ==
nullptr) {
342 fmt::format(
"Aquifer {} is updated with constant flux "
343 "aquifer keyword AQUFLUX at report step {}, "
344 "while it might be specified to be a "
345 "different type of aquifer before this. "
346 "We do not support the conversion between "
347 "different types of aquifer.\n",
id, episode_index);
349 OPM_THROW(std::runtime_error, msg);
352 aquFluxPtr->updateAquifer(aquFlux);
357template <
typename TypeTag>
358void BlackoilAquiferModel<TypeTag>::computeConnectionAreaFraction()
const
361 std::accumulate(this->aquifers.begin(), this->aquifers.end(), 0,
362 [](
const int aquID,
const auto& aquifer)
363 { return std::max(aquID, aquifer->aquiferID()); });
365 maxAquID = this->simulator_.vanguard().grid().comm().max(maxAquID);
367 auto totalConnArea = std::vector<Scalar>(maxAquID, 0.0);
368 for (
const auto& aquifer : this->aquifers) {
369 totalConnArea[aquifer->aquiferID() - 1] += aquifer->totalFaceArea();
372 this->simulator_.vanguard().grid().comm().sum(totalConnArea.data(), maxAquID);
374 for (
auto& aquifer : this->aquifers) {
375 aquifer->computeFaceAreaFraction(totalConnArea);
Definition: AquiferCarterTracy.hpp:42
Definition: AquiferConstantFlux.hpp:39
Definition: AquiferFetkovich.hpp:38
Definition: AquiferNumerical.hpp:45
void endTimeStep() override
Definition: AquiferNumerical.hpp:129
Class for handling the blackoil aquifer model.
Definition: BlackoilAquiferModel.hpp:50
void beginTimeStep()
Definition: BlackoilAquiferModel_impl.hpp:97
void initFromRestart(const data::Aquifers &aquiferSoln)
Definition: BlackoilAquiferModel_impl.hpp:67
BlackoilAquiferModel(Simulator &simulator)
Definition: BlackoilAquiferModel_impl.hpp:44
void init()
Definition: BlackoilAquiferModel_impl.hpp:173
void endEpisode()
Definition: BlackoilAquiferModel_impl.hpp:150
void endTimeStep()
Definition: BlackoilAquiferModel_impl.hpp:135
void serializeOp(Serializer &serializer)
Definition: BlackoilAquiferModel_impl.hpp:198
void deserialize(Restarter &res)
Definition: BlackoilAquiferModel_impl.hpp:165
data::Aquifers aquiferData() const
Definition: BlackoilAquiferModel_impl.hpp:185
void serialize(Restarter &res)
Definition: BlackoilAquiferModel_impl.hpp:156
void beginIteration()
Definition: BlackoilAquiferModel_impl.hpp:92
void addToSource(RateVector &rates, const Context &context, unsigned spaceIdx, unsigned timeIdx) const
Definition: BlackoilAquiferModel_impl.hpp:107
void initialSolutionApplied()
Definition: BlackoilAquiferModel_impl.hpp:56
void endIteration()
Definition: BlackoilAquiferModel_impl.hpp:130
void beginEpisode()
Definition: BlackoilAquiferModel_impl.hpp:78
Definition: SupportsFaceTag.hpp:34
Definition: blackoilboundaryratevector.hh:39