21#include <opm/simulators/aquifers/AquiferConstantFlux.hpp>
23#include <opm/common/ErrorMacros.hpp>
25#include <fmt/format.h>
35template <
typename TypeTag>
36BlackoilAquiferModel<TypeTag>::BlackoilAquiferModel(Simulator& simulator)
37 : simulator_(simulator)
40 using Grid = std::remove_const_t<std::remove_reference_t<
decltype(simulator.vanguard().grid())>>;
41 static_assert(SupportsFaceTag<Grid>::value,
"Grid has to support assumptions about face tag.");
46template <
typename TypeTag>
48BlackoilAquiferModel<TypeTag>::initialSolutionApplied()
50 this->computeConnectionAreaFraction();
52 for (
auto& aquifer : this->aquifers) {
53 aquifer->initialSolutionApplied();
57template <
typename TypeTag>
59BlackoilAquiferModel<TypeTag>::initFromRestart(
const data::Aquifers& aquiferSoln)
61 this->computeConnectionAreaFraction();
63 for (
auto& aquifer : this->aquifers) {
64 aquifer->initFromRestart(aquiferSoln);
68template <
typename TypeTag>
70BlackoilAquiferModel<TypeTag>::beginEpisode()
77 this->createDynamicAquifers(this->simulator_.episodeIndex());
79 this->computeConnectionAreaFraction();
82template <
typename TypeTag>
84BlackoilAquiferModel<TypeTag>::beginIteration()
87template <
typename TypeTag>
89BlackoilAquiferModel<TypeTag>::beginTimeStep()
91 for (
auto& aquifer : this->aquifers) {
92 aquifer->beginTimeStep();
96template <
typename TypeTag>
97template <
class Context>
99BlackoilAquiferModel<TypeTag>::addToSource(RateVector& rates,
100 const Context& context,
102 unsigned timeIdx)
const
104 for (
auto& aquifer : this->aquifers) {
105 aquifer->addToSource(rates, context, spaceIdx, timeIdx);
109template <
typename TypeTag>
111BlackoilAquiferModel<TypeTag>::addToSource(RateVector& rates,
112 unsigned globalSpaceIdx,
113 unsigned timeIdx)
const
115 for (
auto& aquifer : this->aquifers) {
116 aquifer->addToSource(rates, globalSpaceIdx, timeIdx);
120template <
typename TypeTag>
122BlackoilAquiferModel<TypeTag>::endIteration()
125template <
typename TypeTag>
127BlackoilAquiferModel<TypeTag>::endTimeStep()
129 using NumAq = AquiferNumerical<TypeTag>;
131 for (
auto& aquifer : this->aquifers) {
132 aquifer->endTimeStep();
133 NumAq* num =
dynamic_cast<NumAq*
>(aquifer.get());
135 this->simulator_.vanguard().grid().comm().barrier();
139template <
typename TypeTag>
141BlackoilAquiferModel<TypeTag>::endEpisode()
144template <
typename TypeTag>
145template <
class Restarter>
147BlackoilAquiferModel<TypeTag>::serialize(Restarter& )
150 throw std::logic_error(
"BlackoilAquiferModel::serialize() is not yet implemented");
153template <
typename TypeTag>
154template <
class Restarter>
156BlackoilAquiferModel<TypeTag>::deserialize(Restarter& )
159 throw std::logic_error(
"BlackoilAquiferModel::deserialize() is not yet implemented");
163template <
typename TypeTag>
164void BlackoilAquiferModel<TypeTag>::init()
166 if (this->simulator_.vanguard().eclState().aquifer().active()) {
167 this->initializeStaticAquifers();
170 if (this->needRestartDynamicAquifers()) {
171 this->initializeRestartDynamicAquifers();
175template<
typename TypeTag>
176data::Aquifers BlackoilAquiferModel<TypeTag>::aquiferData()
const
179 for (
const auto& aqu : this->aquifers) {
180 data.insert_or_assign(aqu->aquiferID(), aqu->aquiferData());
186template<
typename TypeTag>
187template<
class Serializer>
188void BlackoilAquiferModel<TypeTag>::
189serializeOp(Serializer& serializer)
191 for (
auto& aiPtr : this->aquifers) {
192 auto* ct =
dynamic_cast<AquiferCarterTracy<TypeTag>*
>(aiPtr.get());
193 auto* fetp =
dynamic_cast<AquiferFetkovich<TypeTag>*
>(aiPtr.get());
194 auto* num =
dynamic_cast<AquiferNumerical<TypeTag>*
>(aiPtr.get());
195 auto* flux =
dynamic_cast<AquiferConstantFlux<TypeTag>*
>(aiPtr.get());
205 OPM_THROW(std::logic_error,
"Error serializing BlackoilAquiferModel: unknown aquifer type");
210template <
typename TypeTag>
211void BlackoilAquiferModel<TypeTag>::initializeRestartDynamicAquifers()
213 const auto rstStep = this->simulator_.vanguard().eclState()
214 .getInitConfig().getRestartStep() - 1;
216 this->createDynamicAquifers(rstStep);
219template <
typename TypeTag>
220void BlackoilAquiferModel<TypeTag>::initializeStaticAquifers()
222 const auto& aquifer =
223 this->simulator_.vanguard().eclState().aquifer();
225 for (
const auto& aquCT : aquifer.ct()) {
226 auto aquCTPtr = this->
template createAnalyticAquiferPointer
227 <AquiferCarterTracy<TypeTag>>(aquCT, aquCT.aquiferID,
"Carter-Tracy");
229 if (aquCTPtr !=
nullptr) {
230 this->aquifers.push_back(std::move(aquCTPtr));
234 for (
const auto& aquFetp : aquifer.fetp()) {
235 auto aquFetpPtr = this->
template createAnalyticAquiferPointer
236 <AquiferFetkovich<TypeTag>>(aquFetp, aquFetp.aquiferID,
"Fetkovich");
238 if (aquFetpPtr !=
nullptr) {
239 this->aquifers.push_back(std::move(aquFetpPtr));
243 for (
const auto& [
id, aquFlux] : aquifer.aquflux()) {
245 if (! aquFlux.active) {
continue; }
247 auto aquFluxPtr = this->
template createAnalyticAquiferPointer
248 <AquiferConstantFlux<TypeTag>>(aquFlux, id,
"Constant Flux");
250 if (aquFluxPtr !=
nullptr) {
251 this->aquifers.push_back(std::move(aquFluxPtr));
255 if (aquifer.hasNumericalAquifer()) {
256 for (
const auto& aquNum : aquifer.numericalAquifers().aquifers()) {
257 auto aquNumPtr = std::make_unique<AquiferNumerical<TypeTag>>
258 (aquNum.second, this->simulator_);
260 this->aquifers.push_back(std::move(aquNumPtr));
265template <
typename TypeTag>
266bool BlackoilAquiferModel<TypeTag>::needRestartDynamicAquifers()
const
268 const auto& initconfig =
269 this->simulator_.vanguard().eclState().getInitConfig();
271 if (! initconfig.restartRequested()) {
275 return this->simulator_.vanguard()
276 .schedule()[initconfig.getRestartStep() - 1].hasAnalyticalAquifers();
279template <
typename TypeTag>
280template <
typename AquiferType,
typename AquiferData>
281std::unique_ptr<AquiferType>
282BlackoilAquiferModel<TypeTag>::
283createAnalyticAquiferPointer(
const AquiferData& aqData,
285 std::string_view aqType)
const
287 const auto& connections =
288 this->simulator_.vanguard().eclState().aquifer().connections();
290 if (! connections.hasAquiferConnections(aquiferID)) {
291 const auto msg = fmt::format(
"No valid connections for {} aquifer {}. "
292 "Aquifer {} will be ignored.",
293 aqType, aquiferID, aquiferID);
294 OpmLog::warning(msg);
299 return std::make_unique<AquiferType>
300 (connections.getConnections(aquiferID), this->simulator_, aqData);
303template <
typename TypeTag>
304void BlackoilAquiferModel<TypeTag>::createDynamicAquifers(
const int episode_index)
306 const auto& sched = this->simulator_.vanguard().schedule()[episode_index];
308 for (
const auto& [
id, aquFlux] : sched.aqufluxs) {
310 std::find_if(std::begin(this->aquifers),
311 std::end(this->aquifers),
312 [
id =
id](
const auto& aquPtr)
314 return aquPtr->aquiferID() ==
id;
317 if (aquPos == std::end(this->aquifers)) {
320 auto aquFluxPtr = this->
template createAnalyticAquiferPointer
321 <AquiferConstantFlux<TypeTag>>(aquFlux, id,
"Constant Flux");
323 if (aquFluxPtr !=
nullptr) {
324 this->aquifers.push_back(std::move(aquFluxPtr));
328 auto aquFluxPtr =
dynamic_cast<AquiferConstantFlux<TypeTag>*
>(aquPos->get());
329 if (aquFluxPtr ==
nullptr) {
333 fmt::format(
"Aquifer {} is updated with constant flux "
334 "aquifer keyword AQUFLUX at report step {}, "
335 "while it might be specified to be a "
336 "different type of aquifer before this. "
337 "We do not support the conversion between "
338 "different types of aquifer.\n",
id, episode_index);
340 OPM_THROW(std::runtime_error, msg);
343 aquFluxPtr->updateAquifer(aquFlux);
348template <
typename TypeTag>
349void BlackoilAquiferModel<TypeTag>::computeConnectionAreaFraction()
const
352 std::accumulate(this->aquifers.begin(), this->aquifers.end(), 0,
353 [](
const int aquID,
const auto& aquifer)
354 { return std::max(aquID, aquifer->aquiferID()); });
356 maxAquID = this->simulator_.vanguard().grid().comm().max(maxAquID);
358 auto totalConnArea = std::vector<double>(maxAquID, 0.0);
359 for (
const auto& aquifer : this->aquifers) {
360 totalConnArea[aquifer->aquiferID() - 1] += aquifer->totalFaceArea();
363 this->simulator_.vanguard().grid().comm().sum(totalConnArea.data(), maxAquID);
365 for (
auto& aquifer : this->aquifers) {
366 aquifer->computeFaceAreaFraction(totalConnArea);
This file contains a set of helper functions used by VFPProd / VFPInj.
Definition BlackoilPhases.hpp:27