OutputExtractor.hpp
Go to the documentation of this file.
1// -*- mode: C++; tab-width: 4; indent-tabs-mode: nil; c-basic-offset: 4 -*-
2// vi: set et ts=4 sw=4 sts=4:
3/*
4 This file is part of the Open Porous Media project (OPM).
5
6 OPM is free software: you can redistribute it and/or modify
7 it under the terms of the GNU General Public License as published by
8 the Free Software Foundation, either version 2 of the License, or
9 (at your option) any later version.
10
11 OPM is distributed in the hope that it will be useful,
12 but WITHOUT ANY WARRANTY; without even the implied warranty of
13 MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
14 GNU General Public License for more details.
15
16 You should have received a copy of the GNU General Public License
17 along with OPM. If not, see <http://www.gnu.org/licenses/>.
18
19 Consult the COPYING file in the top-level source directory of this
20 module for the precise wording of the license and the list of
21 copyright holders.
22*/
27#ifndef OPM_OUTPUT_EXTRACTORS_HPP
28#define OPM_OUTPUT_EXTRACTORS_HPP
29
30#include <opm/common/OpmLog/OpmLog.hpp>
31#include <opm/common/utility/Visitor.hpp>
32#include <opm/common/utility/VoigtArray.hpp>
33
34#include <opm/material/common/Valgrind.hpp>
35
40
41#include <algorithm>
42#include <array>
43#include <optional>
44#include <span>
45#include <unordered_map>
46#include <set>
47#include <variant>
48#include <vector>
49
50#include <fmt/format.h>
51
52namespace Opm::detail {
53
55template<class TypeTag>
57{
60 using FluidState = typename IntensiveQuantities::FluidState;
62 static constexpr int numPhases = FluidSystem::numPhases;
63
66 {
73 };
74
76 struct Context
77 {
78 unsigned globalDofIdx;
79 unsigned pvtRegionIdx;
81 const FluidState& fs;
84 };
85
87 using AssignFunc = std::function<void(const Context&)>;
88
91 using ScalarFunc = std::function<Scalar(const Context&)>;
92
95 using PhaseFunc = std::function<Scalar(const unsigned /*phase*/, const Context&)>;
96
97 using ScalarBuffer = std::vector<Scalar>;
98 using PhaseArray = std::array<ScalarBuffer,numPhases>;
99
102 {
105 };
106
109 {
112 };
113
115 struct Entry
116 {
117 std::variant<AssignFunc, ScalarEntry, PhaseEntry> data;
118 bool condition = true;
119 };
120
122 template<std::size_t size>
123 static std::vector<Entry> removeInactive(std::array<Entry,size>& input)
124 {
125 // Setup active extractors
126 std::vector<Entry> filtered_extractors;
127 filtered_extractors.reserve(input.size());
128 std::copy_if(std::move_iterator(input.begin()),
129 std::move_iterator(input.end()),
130 std::back_inserter(filtered_extractors),
131 [](const Entry& e)
132 {
133 if (!e.condition) {
134 return false;
135 }
136 return std::visit(VisitorOverloadSet{
137 [](const AssignFunc&)
138 {
139 return true;
140 },
141 [](const ScalarEntry& v)
142 {
143 return !v.data->empty();
144 },
145 [](const PhaseEntry& v)
146 {
147 return std::ranges::any_of(*v.data,
148 [](const auto& ve)
149 { return !ve.empty(); });
150 }
151 }, e.data);
152 });
153
154 return filtered_extractors;
155 }
156
160 static void process(const Context& ectx,
161 const std::vector<Entry>& extractors)
162 {
163 std::ranges::for_each(extractors,
164 [&ectx](const auto& entry)
165 {
166 std::visit(VisitorOverloadSet{
167 [&ectx](const ScalarEntry& v)
168 {
169 auto& array = *v.data;
170 array[ectx.globalDofIdx] = v.extract(ectx);
171 Valgrind::CheckDefined(array[ectx.globalDofIdx]);
172 },
173 [&ectx](const PhaseEntry& v)
174 {
175 std::ranges::for_each(*v.data,
176 [phaseIdx = 0, &ectx, &v](auto& array) mutable
177 {
178 if (!array.empty()) {
179 array[ectx.globalDofIdx] = v.extract(phaseIdx, ectx);
180 Valgrind::CheckDefined(array[ectx.globalDofIdx]);
181 }
182 ++phaseIdx;
183 });
184 },
185 [&ectx](const typename Extractor::AssignFunc& extract)
186 { extract(ectx); },
187 }, entry.data);
188 });
189 }
190};
191
193template<class TypeTag>
195{
199 using FluidState = typename IntensiveQuantities::FluidState;
201 static constexpr int numPhases = FluidSystem::numPhases;
202 static constexpr int oilPhaseIdx = FluidSystem::oilPhaseIdx;
203 static constexpr int gasPhaseIdx = FluidSystem::gasPhaseIdx;
204 static constexpr int waterPhaseIdx = FluidSystem::waterPhaseIdx;
205
207 struct Context
208 {
209 unsigned globalDofIdx;
210 unsigned dofIdx;
211 const FluidState& fs;
214 };
215
217 using AssignFunc = std::function<void(const Context&)>;
218
221 using ScalarFunc = std::function<Scalar(const Context&)>;
222
225 using PhaseFunc = std::function<Scalar(const unsigned /*phase*/, const Context&)>;
226
228 {
230 std::variant<std::string_view, std::vector<std::string_view>> kw;
231
234 };
235
237 {
239 std::variant<std::array<std::string_view, numPhases>,
240 std::array<std::array<std::string_view, numPhases>, 2>> kw;
241
244 };
245
248 using TensorFunc = std::function<Scalar(const VoigtIndex, const Context&)>;
249
251 {
255 std::string_view kw;
256
259 };
260
262 using Entry = std::variant<ScalarEntry, PhaseEntry, TensorEntry>;
263
265 struct Exec
266 {
268 Exec(double* d, ScalarFunc&& e)
269 : data(d), extract(std::move(e))
270 {}
271
272 double* data;
274 };
275
277 using ExecMap = std::unordered_map<int, std::vector<Exec>>;
278
287 static std::optional<ScalarFunc>
288 makeExtractor(const std::string_view base_kw,
289 const std::span<const Entry> handlers)
290 {
291 using PhaseViewArray = std::array<std::string_view, numPhases>;
292 using StringViewVec = std::vector<std::string_view>;
293
294 // Suffix table position must equal the VoigtIndex enum value
295 // (XX = 0, YY = 1, ZZ = 2, YZ = 3, XZ = 4, XY = 5).
296 static constexpr auto voigtSuffixes = std::array<std::string_view, 6>{
297 "XX", "YY", "ZZ", "YZ", "XZ", "XY",
298 };
299
300 unsigned phase{};
301 unsigned voigt{};
302 const auto handler_info =
303 std::ranges::find_if(
304 handlers,
305 [&base_kw, &phase, &voigt](const auto& handler)
306 {
307 // Tensor keywords are matched as base name + Voigt
308 // component suffix, without building the names.
309 if (const auto* tensor = std::get_if<TensorEntry>(&handler)) {
310 if (base_kw.size() != tensor->kw.size() + 2 ||
311 !base_kw.starts_with(tensor->kw))
312 {
313 return false;
314 }
315 const auto pos =
316 std::ranges::find(voigtSuffixes,
317 base_kw.substr(tensor->kw.size()));
318 if (pos == voigtSuffixes.end()) {
319 return false;
320 }
321 voigt = std::distance(voigtSuffixes.begin(), pos);
322 return true;
323 }
324
325 // Extract list of keyword names from handler
326 const auto gen_handlers =
327 std::visit(VisitorOverloadSet{
328 [](const ScalarEntry& entry)
329 {
330 return std::visit(VisitorOverloadSet{
331 [](const std::string_view& kw) -> StringViewVec
332 {
333 return {kw};
334 },
335 [](const StringViewVec& kws) -> StringViewVec
336 { return kws; }
337 }, entry.kw);
338 },
339 [](const PhaseEntry& entry)
340 {
341 return std::visit(VisitorOverloadSet{
342 [](const PhaseViewArray& data)
343 {
344 return StringViewVec{data.begin(), data.end()};
345 },
346 [](const std::array<PhaseViewArray,2>& data)
347 {
348 StringViewVec res;
349 res.reserve(2*numPhases);
350 res.insert(res.end(),
351 data[0].begin(),
352 data[0].end());
353 res.insert(res.end(),
354 data[1].begin(),
355 data[1].end());
356 return res;
357 }
358 }, entry.kw);
359 },
360 [](const TensorEntry&) -> StringViewVec
361 {
362 // handled by the prefix/suffix match above
363 return {};
364 }
365 }, handler);
366
367 const auto found_handler =
368 std::ranges::find(gen_handlers, base_kw);
369 if (found_handler != gen_handlers.end()) {
370 phase = std::distance(gen_handlers.begin(), found_handler) % numPhases;
371 }
372 return found_handler != gen_handlers.end();
373 }
374 );
375
376 if (handler_info == handlers.end()) {
377 return std::nullopt;
378 }
379
380 return std::visit(VisitorOverloadSet{
381 [](const ScalarEntry& e) -> ScalarFunc
382 {
383 return e.extract;
384 },
385 [phase](const PhaseEntry& e) -> ScalarFunc
386 {
387 return [phase, extract = e.extract]
388 (const Context& ectx)
389 {
390 static constexpr auto phaseMap = std::array{
391 waterPhaseIdx,
392 oilPhaseIdx,
393 gasPhaseIdx,
394 };
395 return extract(phaseMap[phase], ectx);
396 };
397 },
398 [voigt](const TensorEntry& e) -> ScalarFunc
399 {
400 return [voigt, extract = e.extract]
401 (const Context& ectx)
402 {
403 return extract(static_cast<VoigtIndex>(voigt), ectx);
404 };
405 }
406 }, *handler_info);
407 }
408
410 static ExecMap setupExecMap(std::map<std::pair<std::string, int>, double>& blockData,
411 const std::span<const Entry> handlers)
412 {
413 ExecMap extractors;
414
415 std::ranges::for_each(
416 blockData,
417 [&handlers, &extractors](auto& bd_info)
418 {
419 const auto& [key, cell] = bd_info.first;
420 if (auto extract = makeExtractor(std::string_view{key}, handlers)) {
421 extractors[cell - 1].emplace_back(&bd_info.second, std::move(*extract));
422 }
423 else {
424 OpmLog::warning("Unhandled output keyword",
425 fmt::format("Keyword '{}' is unhandled for output "
426 "to summary file.", key));
427 }
428 }
429 );
430
431 return extractors;
432 }
433
435 static void process(const std::vector<Exec>& blockExtractors,
436 const Context& ectx)
437 {
438 std::ranges::for_each(blockExtractors,
439 [&ectx](auto& bdata)
440 { *bdata.data = bdata.extract(ectx); });
441 }
442
450 using LgrExecMap = std::unordered_map<int,
451 std::unordered_map<int,
452 std::vector<Exec>>>;
453
463 static LgrExecMap setupLgrExecMap(std::map<std::tuple<std::string,int,int>,
464 double>& lgrBlockData,
465 const std::span<const Entry> handlers)
466 {
467 LgrExecMap extractors;
468
469 std::ranges::for_each(
470 lgrBlockData,
471 [&handlers, &extractors](auto& bd_info)
472 {
473 const auto& [lgr_kw, level, localCart] = bd_info.first;
474 // LB* keywords mirror the global B* names; drop the leading
475 // 'L' so the shared handler lookup sees "BPR", "BOSAT", ...
476 const auto base_kw = std::string_view{lgr_kw}.substr(1);
477 if (auto extract = makeExtractor(base_kw, handlers)) {
478 extractors[level][localCart].emplace_back(&bd_info.second, std::move(*extract));
479 }
480 else {
481 OpmLog::warning("Unhandled LGR output keyword",
482 fmt::format("Keyword '{}' (LGR mirror of '{}') is "
483 "unhandled for output to summary file.",
484 lgr_kw, base_kw));
485 }
486 }
487 );
488
489 return extractors;
490 }
491};
492
493} // namespace Opm::detail
494
495#endif // OPM_OUTPUT_EXTRACTORS_HPP
Defines a type tags and some fundamental properties all models.
Declare the properties used by the infrastructure code of the finite volume discretizations.
Defines the common properties required by the porous medium multi-phase models.
if(!linsolver_)
Definition: FlexibleSolver_impl.hpp:326
Definition: elasticitylocalresidualtpsa.hpp:46
typename Properties::Detail::GetPropImpl< TypeTag, Property >::type::type GetPropType
get the type alias defined in the property (equivalent to old macro GET_PROP_TYPE(....
Definition: propertysystem.hh:233
The Opm property system, traits with inheritance.
Context passed to element extractor functions.
Definition: OutputExtractor.hpp:208
const FluidState & fs
Fluid state for cell.
Definition: OutputExtractor.hpp:211
const ElementContext & elemCtx
Definition: OutputExtractor.hpp:213
const IntensiveQuantities & intQuants
Intensive quantities for cell.
Definition: OutputExtractor.hpp:212
unsigned dofIdx
Definition: OutputExtractor.hpp:210
unsigned globalDofIdx
Global degree-of-freedom index.
Definition: OutputExtractor.hpp:209
Descriptor for extractor execution.
Definition: OutputExtractor.hpp:266
double * data
Where to store output data.
Definition: OutputExtractor.hpp:272
ScalarFunc extract
Extraction function to call.
Definition: OutputExtractor.hpp:273
Exec(double *d, ScalarFunc &&e)
Move constructor.
Definition: OutputExtractor.hpp:268
Definition: OutputExtractor.hpp:237
PhaseFunc extract
Associated extraction lambda.
Definition: OutputExtractor.hpp:243
std::variant< std::array< std::string_view, numPhases >, std::array< std::array< std::string_view, numPhases >, 2 > > kw
One or two lists of names for the keyword for each phase.
Definition: OutputExtractor.hpp:240
Definition: OutputExtractor.hpp:228
std::variant< std::string_view, std::vector< std::string_view > > kw
A single name or a list of names for the keyword.
Definition: OutputExtractor.hpp:230
ScalarFunc extract
Associated extraction lamda.
Definition: OutputExtractor.hpp:233
Definition: OutputExtractor.hpp:251
TensorFunc extract
Associated extraction lambda.
Definition: OutputExtractor.hpp:258
std::string_view kw
Definition: OutputExtractor.hpp:255
Wrapping struct holding types used for block-level data extraction.
Definition: OutputExtractor.hpp:195
std::variant< ScalarEntry, PhaseEntry, TensorEntry > Entry
Descriptor for extractors.
Definition: OutputExtractor.hpp:262
std::unordered_map< int, std::vector< Exec > > ExecMap
A map of extraction executors, keyed by cartesian cell index.
Definition: OutputExtractor.hpp:277
GetPropType< TypeTag, Properties::ElementContext > ElementContext
Definition: OutputExtractor.hpp:196
typename IntensiveQuantities::FluidState FluidState
Definition: OutputExtractor.hpp:199
static LgrExecMap setupLgrExecMap(std::map< std::tuple< std::string, int, int >, double > &lgrBlockData, const std::span< const Entry > handlers)
Setup an LGR-cell extractor executor map.
Definition: OutputExtractor.hpp:463
std::function< Scalar(const unsigned, const Context &)> PhaseFunc
Definition: OutputExtractor.hpp:225
static ExecMap setupExecMap(std::map< std::pair< std::string, int >, double > &blockData, const std::span< const Entry > handlers)
Setup an extractor executor map from a map of evaluations to perform.
Definition: OutputExtractor.hpp:410
std::function< Scalar(const VoigtIndex, const Context &)> TensorFunc
Definition: OutputExtractor.hpp:248
GetPropType< TypeTag, Properties::FluidSystem > FluidSystem
Definition: OutputExtractor.hpp:200
static std::optional< ScalarFunc > makeExtractor(const std::string_view base_kw, const std::span< const Entry > handlers)
Resolve a block-summary keyword to its bound extraction lambda.
Definition: OutputExtractor.hpp:288
std::function< Scalar(const Context &)> ScalarFunc
Definition: OutputExtractor.hpp:221
std::unordered_map< int, std::unordered_map< int, std::vector< Exec > > > LgrExecMap
Definition: OutputExtractor.hpp:452
GetPropType< TypeTag, Properties::IntensiveQuantities > IntensiveQuantities
Definition: OutputExtractor.hpp:197
GetPropType< TypeTag, Properties::Scalar > Scalar
Definition: OutputExtractor.hpp:198
static void process(const std::vector< Exec > &blockExtractors, const Context &ectx)
Process a list of block extractors.
Definition: OutputExtractor.hpp:435
std::function< void(const Context &)> AssignFunc
Callback for extractors handling their own assignements.
Definition: OutputExtractor.hpp:217
Context passed to extractor functions.
Definition: OutputExtractor.hpp:77
const HysteresisParams & hParams
Hysteresis parameters for cell.
Definition: OutputExtractor.hpp:83
const IntensiveQuantities & intQuants
Intensive quantities for cell.
Definition: OutputExtractor.hpp:82
unsigned globalDofIdx
Global degree-of-freedom index.
Definition: OutputExtractor.hpp:78
const FluidState & fs
Fluid state for cell.
Definition: OutputExtractor.hpp:81
int episodeIndex
Current report step.
Definition: OutputExtractor.hpp:80
unsigned pvtRegionIdx
pvt region for dof
Definition: OutputExtractor.hpp:79
Descriptor for extractors.
Definition: OutputExtractor.hpp:116
bool condition
Additional condition for enabling extractor.
Definition: OutputExtractor.hpp:118
std::variant< AssignFunc, ScalarEntry, PhaseEntry > data
Extractor.
Definition: OutputExtractor.hpp:117
Struct holding hysteresis parameters.
Definition: OutputExtractor.hpp:66
Scalar somin
Min oil saturation.
Definition: OutputExtractor.hpp:72
Scalar swmin
Min water saturation.
Definition: OutputExtractor.hpp:69
Scalar swmax
Max water saturation.
Definition: OutputExtractor.hpp:68
Scalar shmax
Max something.
Definition: OutputExtractor.hpp:71
Scalar sgmax
Max gas saturation.
Definition: OutputExtractor.hpp:70
Scalar somax
Max oil saturation.
Definition: OutputExtractor.hpp:67
A phase buffer extractor descriptor.
Definition: OutputExtractor.hpp:109
PhaseArray * data
Array of buffers to store data in.
Definition: OutputExtractor.hpp:110
PhaseFunc extract
Function to call for extraction.
Definition: OutputExtractor.hpp:111
A scalar extractor descriptor.
Definition: OutputExtractor.hpp:102
ScalarBuffer * data
Buffer to store data in.
Definition: OutputExtractor.hpp:103
ScalarFunc extract
Function to call for extraction.
Definition: OutputExtractor.hpp:104
Wrapping struct holding types used for element-level data extraction.
Definition: OutputExtractor.hpp:57
std::array< ScalarBuffer, numPhases > PhaseArray
An array of buffers, one for each phase.
Definition: OutputExtractor.hpp:98
GetPropType< TypeTag, Properties::Scalar > Scalar
Definition: OutputExtractor.hpp:59
std::vector< Scalar > ScalarBuffer
A scalar buffer.
Definition: OutputExtractor.hpp:97
std::function< void(const Context &)> AssignFunc
Callback for extractors handling their own assignements.
Definition: OutputExtractor.hpp:87
GetPropType< TypeTag, Properties::FluidSystem > FluidSystem
Definition: OutputExtractor.hpp:61
std::function< Scalar(const unsigned, const Context &)> PhaseFunc
Definition: OutputExtractor.hpp:95
GetPropType< TypeTag, Properties::IntensiveQuantities > IntensiveQuantities
Definition: OutputExtractor.hpp:58
std::function< Scalar(const Context &)> ScalarFunc
Definition: OutputExtractor.hpp:91
static void process(const Context &ectx, const std::vector< Entry > &extractors)
Process the given extractor entries.
Definition: OutputExtractor.hpp:160
typename IntensiveQuantities::FluidState FluidState
Definition: OutputExtractor.hpp:60
static std::vector< Entry > removeInactive(std::array< Entry, size > &input)
Obtain vector of active extractors from an array of extractors.
Definition: OutputExtractor.hpp:123
static constexpr int numPhases
Definition: OutputExtractor.hpp:62