22#ifndef OPM_BLACKOILAQUIFERMODEL_HEADER_INCLUDED
24#define OPM_BLACKOILAQUIFERMODEL_IMPL_HEADER_INCLUDED
25#include <opm/simulators/aquifers/BlackoilAquiferModel.hpp>
28#include <opm/simulators/aquifers/AquiferConstantFlux.hpp>
30#include <opm/common/ErrorMacros.hpp>
32#include <fmt/format.h>
42template <
typename TypeTag>
43BlackoilAquiferModel<TypeTag>::BlackoilAquiferModel(Simulator& simulator)
44 : simulator_(simulator)
47 using Grid = std::remove_const_t<std::remove_reference_t<
decltype(simulator.vanguard().grid())>>;
48 static_assert(SupportsFaceTag<Grid>::value,
"Grid has to support assumptions about face tag.");
53template <
typename TypeTag>
55BlackoilAquiferModel<TypeTag>::initialSolutionApplied()
57 this->computeConnectionAreaFraction();
59 for (
auto& aquifer : this->aquifers) {
60 aquifer->initialSolutionApplied();
64template <
typename TypeTag>
66BlackoilAquiferModel<TypeTag>::initFromRestart(
const data::Aquifers& aquiferSoln)
68 this->computeConnectionAreaFraction();
70 for (
auto& aquifer : this->aquifers) {
71 aquifer->initFromRestart(aquiferSoln);
75template <
typename TypeTag>
77BlackoilAquiferModel<TypeTag>::beginEpisode()
84 this->createDynamicAquifers(this->simulator_.episodeIndex());
86 this->computeConnectionAreaFraction();
89template <
typename TypeTag>
91BlackoilAquiferModel<TypeTag>::beginIteration()
94template <
typename TypeTag>
96BlackoilAquiferModel<TypeTag>::beginTimeStep()
98 for (
auto& aquifer : this->aquifers) {
99 aquifer->beginTimeStep();
103template <
typename TypeTag>
104template <
class Context>
106BlackoilAquiferModel<TypeTag>::addToSource(RateVector& rates,
107 const Context& context,
109 unsigned timeIdx)
const
111 for (
auto& aquifer : this->aquifers) {
112 aquifer->addToSource(rates, context, spaceIdx, timeIdx);
116template <
typename TypeTag>
118BlackoilAquiferModel<TypeTag>::addToSource(RateVector& rates,
119 unsigned globalSpaceIdx,
120 unsigned timeIdx)
const
122 for (
auto& aquifer : this->aquifers) {
123 aquifer->addToSource(rates, globalSpaceIdx, timeIdx);
127template <
typename TypeTag>
129BlackoilAquiferModel<TypeTag>::endIteration()
132template <
typename TypeTag>
134BlackoilAquiferModel<TypeTag>::endTimeStep()
136 using NumAq = AquiferNumerical<TypeTag>;
138 for (
auto& aquifer : this->aquifers) {
139 aquifer->endTimeStep();
140 NumAq* num =
dynamic_cast<NumAq*
>(aquifer.get());
142 this->simulator_.vanguard().grid().comm().barrier();
146template <
typename TypeTag>
148BlackoilAquiferModel<TypeTag>::endEpisode()
151template <
typename TypeTag>
152template <
class Restarter>
154BlackoilAquiferModel<TypeTag>::serialize(Restarter& )
157 throw std::logic_error(
"BlackoilAquiferModel::serialize() is not yet implemented");
160template <
typename TypeTag>
161template <
class Restarter>
163BlackoilAquiferModel<TypeTag>::deserialize(Restarter& )
166 throw std::logic_error(
"BlackoilAquiferModel::deserialize() is not yet implemented");
170template <
typename TypeTag>
171void BlackoilAquiferModel<TypeTag>::init()
173 if (this->simulator_.vanguard().eclState().aquifer().active()) {
174 this->initializeStaticAquifers();
177 if (this->needRestartDynamicAquifers()) {
178 this->initializeRestartDynamicAquifers();
182template<
typename TypeTag>
183data::Aquifers BlackoilAquiferModel<TypeTag>::aquiferData()
const
186 for (
const auto& aqu : this->aquifers) {
187 data.insert_or_assign(aqu->aquiferID(), aqu->aquiferData());
193template<
typename TypeTag>
194template<
class Serializer>
195void BlackoilAquiferModel<TypeTag>::
196serializeOp(Serializer& serializer)
198 for (
auto& aiPtr : this->aquifers) {
199 auto* ct =
dynamic_cast<AquiferCarterTracy<TypeTag>*
>(aiPtr.get());
200 auto* fetp =
dynamic_cast<AquiferFetkovich<TypeTag>*
>(aiPtr.get());
201 auto* num =
dynamic_cast<AquiferNumerical<TypeTag>*
>(aiPtr.get());
202 auto* flux =
dynamic_cast<AquiferConstantFlux<TypeTag>*
>(aiPtr.get());
212 OPM_THROW(std::logic_error,
"Error serializing BlackoilAquiferModel: unknown aquifer type");
217template <
typename TypeTag>
218void BlackoilAquiferModel<TypeTag>::initializeRestartDynamicAquifers()
220 const auto rstStep = this->simulator_.vanguard().eclState()
221 .getInitConfig().getRestartStep() - 1;
223 this->createDynamicAquifers(rstStep);
226template <
typename TypeTag>
227void BlackoilAquiferModel<TypeTag>::initializeStaticAquifers()
229 const auto& aquifer =
230 this->simulator_.vanguard().eclState().aquifer();
232 for (
const auto& aquCT : aquifer.ct()) {
233 auto aquCTPtr = this->
template createAnalyticAquiferPointer
234 <AquiferCarterTracy<TypeTag>>(aquCT, aquCT.aquiferID,
"Carter-Tracy");
236 if (aquCTPtr !=
nullptr) {
237 this->aquifers.push_back(std::move(aquCTPtr));
241 for (
const auto& aquFetp : aquifer.fetp()) {
242 auto aquFetpPtr = this->
template createAnalyticAquiferPointer
243 <AquiferFetkovich<TypeTag>>(aquFetp, aquFetp.aquiferID,
"Fetkovich");
245 if (aquFetpPtr !=
nullptr) {
246 this->aquifers.push_back(std::move(aquFetpPtr));
250 for (
const auto& [
id, aquFlux] : aquifer.aquflux()) {
252 if (! aquFlux.active) {
continue; }
254 auto aquFluxPtr = this->
template createAnalyticAquiferPointer
255 <AquiferConstantFlux<TypeTag>>(aquFlux, id,
"Constant Flux");
257 if (aquFluxPtr !=
nullptr) {
258 this->aquifers.push_back(std::move(aquFluxPtr));
262 if (aquifer.hasNumericalAquifer()) {
263 for (
const auto& aquNum : aquifer.numericalAquifers().aquifers()) {
264 auto aquNumPtr = std::make_unique<AquiferNumerical<TypeTag>>
265 (aquNum.second, this->simulator_);
267 this->aquifers.push_back(std::move(aquNumPtr));
272template <
typename TypeTag>
273bool BlackoilAquiferModel<TypeTag>::needRestartDynamicAquifers()
const
275 const auto& initconfig =
276 this->simulator_.vanguard().eclState().getInitConfig();
278 if (! initconfig.restartRequested()) {
282 return this->simulator_.vanguard()
283 .schedule()[initconfig.getRestartStep() - 1].hasAnalyticalAquifers();
286template <
typename TypeTag>
287template <
typename AquiferType,
typename AquiferData>
288std::unique_ptr<AquiferType>
289BlackoilAquiferModel<TypeTag>::
290createAnalyticAquiferPointer(
const AquiferData& aqData,
292 std::string_view aqType)
const
294 const auto& connections =
295 this->simulator_.vanguard().eclState().aquifer().connections();
297 if (! connections.hasAquiferConnections(aquiferID)) {
298 const auto msg = fmt::format(
"No valid connections for {} aquifer {}. "
299 "Aquifer {} will be ignored.",
300 aqType, aquiferID, aquiferID);
301 OpmLog::warning(msg);
306 return std::make_unique<AquiferType>
307 (connections.getConnections(aquiferID), this->simulator_, aqData);
310template <
typename TypeTag>
311void BlackoilAquiferModel<TypeTag>::createDynamicAquifers(
const int episode_index)
313 const auto& sched = this->simulator_.vanguard().schedule()[episode_index];
315 for (
const auto& [
id, aquFlux] : sched.aqufluxs) {
317 std::find_if(std::begin(this->aquifers),
318 std::end(this->aquifers),
319 [
id =
id](
const auto& aquPtr)
321 return aquPtr->aquiferID() == id;
324 if (aquPos == std::end(this->aquifers)) {
327 auto aquFluxPtr = this->
template createAnalyticAquiferPointer
328 <AquiferConstantFlux<TypeTag>>(aquFlux, id,
"Constant Flux");
330 if (aquFluxPtr !=
nullptr) {
331 this->aquifers.push_back(std::move(aquFluxPtr));
335 auto aquFluxPtr =
dynamic_cast<AquiferConstantFlux<TypeTag>*
>(aquPos->get());
336 if (aquFluxPtr ==
nullptr) {
340 fmt::format(
"Aquifer {} is updated with constant flux "
341 "aquifer keyword AQUFLUX at report step {}, "
342 "while it might be specified to be a "
343 "different type of aquifer before this. "
344 "We do not support the conversion between "
345 "different types of aquifer.\n",
id, episode_index);
347 OPM_THROW(std::runtime_error, msg);
350 aquFluxPtr->updateAquifer(aquFlux);
355template <
typename TypeTag>
356void BlackoilAquiferModel<TypeTag>::computeConnectionAreaFraction()
const
359 std::accumulate(this->aquifers.begin(), this->aquifers.end(), 0,
360 [](
const int aquID,
const auto& aquifer)
361 { return std::max(aquID, aquifer->aquiferID()); });
363 maxAquID = this->simulator_.vanguard().grid().comm().max(maxAquID);
365 auto totalConnArea = std::vector<Scalar>(maxAquID, 0.0);
366 for (
const auto& aquifer : this->aquifers) {
367 totalConnArea[aquifer->aquiferID() - 1] += aquifer->totalFaceArea();
370 this->simulator_.vanguard().grid().comm().sum(totalConnArea.data(), maxAquID);
372 for (
auto& aquifer : this->aquifers) {
373 aquifer->computeFaceAreaFraction(totalConnArea);
This file contains a set of helper functions used by VFPProd / VFPInj.
Definition blackoilboundaryratevector.hh:37