20 #ifndef OPM_BLACKOILAQUIFERMODEL_IMPL_HEADER_INCLUDED 21 #define OPM_BLACKOILAQUIFERMODEL_IMPL_HEADER_INCLUDED 24 #ifndef OPM_BLACKOILAQUIFERMODEL_HEADER_INCLUDED 26 #include <opm/simulators/aquifers/BlackoilAquiferModel.hpp> 29 #include <opm/simulators/aquifers/AquiferConstantFlux.hpp> 31 #include <opm/common/ErrorMacros.hpp> 33 #include <fmt/format.h> 38 #include <string_view> 43 template <
typename TypeTag>
44 BlackoilAquiferModel<TypeTag>::BlackoilAquiferModel(Simulator& simulator)
45 : simulator_(simulator)
48 using Grid = std::remove_const_t<std::remove_reference_t<decltype(simulator.vanguard().grid())>>;
49 static_assert(SupportsFaceTag<Grid>::value,
"Grid has to support assumptions about face tag.");
54 template <
typename TypeTag>
56 BlackoilAquiferModel<TypeTag>::initialSolutionApplied()
58 this->computeConnectionAreaFraction();
60 for (
auto& aquifer : this->aquifers) {
61 aquifer->initialSolutionApplied();
65 template <
typename TypeTag>
67 BlackoilAquiferModel<TypeTag>::initFromRestart(
const data::Aquifers& aquiferSoln)
69 this->computeConnectionAreaFraction();
71 for (
auto& aquifer : this->aquifers) {
72 aquifer->initFromRestart(aquiferSoln);
76 template <
typename TypeTag>
78 BlackoilAquiferModel<TypeTag>::beginEpisode()
85 this->createDynamicAquifers(this->simulator_.episodeIndex());
87 this->computeConnectionAreaFraction();
90 template <
typename TypeTag>
92 BlackoilAquiferModel<TypeTag>::beginIteration()
95 template <
typename TypeTag>
97 BlackoilAquiferModel<TypeTag>::beginTimeStep()
99 for (
auto& aquifer : this->aquifers) {
100 aquifer->beginTimeStep();
104 template <
typename TypeTag>
105 template <
class Context>
107 BlackoilAquiferModel<TypeTag>::addToSource(RateVector& rates,
108 const Context& context,
110 unsigned timeIdx)
const 112 for (
auto& aquifer : this->aquifers) {
113 aquifer->addToSource(rates, context, spaceIdx, timeIdx);
117 template <
typename TypeTag>
119 BlackoilAquiferModel<TypeTag>::addToSource(RateVector& rates,
120 unsigned globalSpaceIdx,
121 unsigned timeIdx)
const 123 for (
auto& aquifer : this->aquifers) {
124 aquifer->addToSource(rates, globalSpaceIdx, timeIdx);
128 template <
typename TypeTag>
130 BlackoilAquiferModel<TypeTag>::endIteration()
133 template <
typename TypeTag>
135 BlackoilAquiferModel<TypeTag>::endTimeStep()
137 using NumAq = AquiferNumerical<TypeTag>;
139 for (
const auto& aquifer : this->aquifers) {
140 aquifer->endTimeStep();
141 const NumAq* num =
dynamic_cast<const NumAq*
>(aquifer.get());
143 this->simulator_.vanguard().grid().comm().barrier();
148 template <
typename TypeTag>
150 BlackoilAquiferModel<TypeTag>::endEpisode()
153 template <
typename TypeTag>
154 template <
class Restarter>
156 BlackoilAquiferModel<TypeTag>::serialize(Restarter& )
159 throw std::logic_error(
"BlackoilAquiferModel::serialize() is not yet implemented");
162 template <
typename TypeTag>
163 template <
class Restarter>
165 BlackoilAquiferModel<TypeTag>::deserialize(Restarter& )
168 throw std::logic_error(
"BlackoilAquiferModel::deserialize() is not yet implemented");
172 template <
typename TypeTag>
173 void BlackoilAquiferModel<TypeTag>::init()
175 if (this->simulator_.vanguard().eclState().aquifer().active()) {
176 this->initializeStaticAquifers();
179 if (this->needRestartDynamicAquifers()) {
180 this->initializeRestartDynamicAquifers();
184 template<
typename TypeTag>
185 data::Aquifers BlackoilAquiferModel<TypeTag>::aquiferData()
const 188 for (
const auto& aqu : this->aquifers) {
189 data.insert_or_assign(aqu->aquiferID(), aqu->aquiferData());
195 template<
typename TypeTag>
196 template<
class Serializer>
197 void BlackoilAquiferModel<TypeTag>::
198 serializeOp(Serializer& serializer)
200 for (
auto& aiPtr : this->aquifers) {
201 auto* ct =
dynamic_cast<AquiferCarterTracy<TypeTag>*
>(aiPtr.get());
202 auto* fetp =
dynamic_cast<AquiferFetkovich<TypeTag>*
>(aiPtr.get());
203 auto* num =
dynamic_cast<AquiferNumerical<TypeTag>*
>(aiPtr.get());
204 auto* flux =
dynamic_cast<AquiferConstantFlux<TypeTag>*
>(aiPtr.get());
214 OPM_THROW(std::logic_error,
"Error serializing BlackoilAquiferModel: unknown aquifer type");
219 template <
typename TypeTag>
220 void BlackoilAquiferModel<TypeTag>::initializeRestartDynamicAquifers()
222 const auto rstStep = this->simulator_.vanguard().eclState()
223 .getInitConfig().getRestartStep() - 1;
225 this->createDynamicAquifers(rstStep);
228 template <
typename TypeTag>
229 void 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));
274 template <
typename TypeTag>
275 bool 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();
288 template <
typename TypeTag>
289 template <
typename AquiferType,
typename AquiferData>
290 std::unique_ptr<AquiferType>
291 BlackoilAquiferModel<TypeTag>::
292 createAnalyticAquiferPointer(
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(fmt::runtime(
"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);
312 template <
typename TypeTag>
313 void 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::ranges::find_if(this->aquifers,
320 [Id =
id](
const auto& aquPtr)
321 {
return aquPtr->aquiferID() == Id; });
323 if (aquPos == std::end(this->aquifers)) {
326 auto aquFluxPtr = this->
template createAnalyticAquiferPointer
327 <AquiferConstantFlux<TypeTag>>(aquFlux, id,
"Constant Flux");
329 if (aquFluxPtr !=
nullptr) {
330 this->aquifers.push_back(std::move(aquFluxPtr));
334 auto aquFluxPtr =
dynamic_cast<AquiferConstantFlux<TypeTag>*
>(aquPos->get());
335 if (aquFluxPtr ==
nullptr) {
339 fmt::format(
"Aquifer {} is updated with constant flux " 340 "aquifer keyword AQUFLUX at report step {}, " 341 "while it might be specified to be a " 342 "different type of aquifer before this. " 343 "We do not support the conversion between " 344 "different types of aquifer.\n",
id, episode_index);
346 OPM_THROW(std::runtime_error, msg);
349 aquFluxPtr->updateAquifer(aquFlux);
354 template <
typename TypeTag>
355 void BlackoilAquiferModel<TypeTag>::computeConnectionAreaFraction()
const 358 std::accumulate(this->aquifers.begin(), this->aquifers.end(), 0,
359 [](
const int aquID,
const auto& aquifer)
360 {
return std::max(aquID, aquifer->aquiferID()); });
362 maxAquID = this->simulator_.vanguard().grid().comm().max(maxAquID);
364 auto totalConnArea = std::vector<Scalar>(maxAquID, 0.0);
365 for (
const auto& aquifer : this->aquifers) {
366 totalConnArea[aquifer->aquiferID() - 1] += aquifer->totalFaceArea();
369 this->simulator_.vanguard().grid().comm().sum(totalConnArea.data(), maxAquID);
371 for (
auto& aquifer : this->aquifers) {
372 aquifer->computeFaceAreaFraction(totalConnArea);
This file contains a set of helper functions used by VFPProd / VFPInj.
Definition: blackoilbioeffectsmodules.hh:45