CollectDataOnIORank_impl.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*/
23
24#ifndef OPM_COLLECT_DATA_ON_IO_RANK_IMPL_HPP
25#define OPM_COLLECT_DATA_ON_IO_RANK_IMPL_HPP
26
28
29#include <dune/common/version.hh>
30#include <dune/grid/common/gridenums.hh>
31#include <dune/grid/common/mcmgmapper.hh>
32#include <dune/grid/common/partitionset.hh>
33
34#include <opm/grid/common/CartesianIndexMapper.hpp>
35
36#include <algorithm>
37#include <cassert>
38#include <concepts>
39#include <cstddef>
40#include <ranges>
41#include <stdexcept>
42#include <string>
43#include <tuple>
44#include <type_traits>
45#include <utility>
46#include <vector>
47
48namespace Opm {
49
50// global id
52{
53 int globalId_;
54 int localIndex_;
55 bool isInterior_;
56
57public:
59 : globalId_(-1)
60 , localIndex_(-1)
61 , isInterior_(true)
62 {}
63 void setGhost()
64 { isInterior_ = false; }
65
66 void setId(int globalId)
67 { globalId_ = globalId; }
69 { localIndex_ = localIndex; }
70
71 int localIndex () const
72 { return localIndex_; }
73 int id () const
74 { return globalId_; }
75 bool isInterior() const
76 { return isInterior_; }
77};
78
79using IndexMapType = std::vector<int>;
80using IndexMapStorageType = std::vector<IndexMapType>;
81using P2PCommunicatorType = Dune::Point2PointCommunicator<Dune::SimpleMessageBuffer>;
83class DistributeIndexMapping : public P2PCommunicatorType::DataHandleInterface
84{
85protected:
86 const std::vector<int>& distributedGlobalIndex_;
89 std::map<int, int> globalPosition_;
90 std::set<int>& recv_;
91 std::vector<int>& ranks_;
92
93public:
94 DistributeIndexMapping(const std::vector<int>& globalIndex,
95 const std::vector<int>& distributedGlobalIndex,
96 IndexMapType& localIndexMap,
97 IndexMapStorageType& indexMaps,
98 std::vector<int>& ranks,
99 std::set<int>& recv,
100 bool isIORank)
101 : distributedGlobalIndex_(distributedGlobalIndex)
102 , localIndexMap_(localIndexMap)
103 , indexMaps_(indexMaps)
105 , recv_(recv)
106 , ranks_(ranks)
107 {
108 std::size_t size = globalIndex.size();
109 // create mapping globalIndex --> localIndex
110 if ( isIORank ) // ioRank
111 for (std::size_t index = 0; index < size; ++index)
112 globalPosition_.insert(std::make_pair(globalIndex[index], index));
113
114 // we need to create a mapping from local to global
115 if (!indexMaps_.empty()) {
116 if (isIORank)
117 ranks_.resize(size, -1);
118 // for the ioRank create a localIndex to index in global state map
119 IndexMapType& indexMap = indexMaps_.back();
120 std::size_t localSize = localIndexMap_.size();
121 indexMap.resize(localSize);
122 for (std::size_t i = 0; i < localSize; ++i)
123 {
125 indexMap[i] = id;
126 }
127 }
128 }
129
131 {
132 if (!indexMaps_.size())
133 return;
134
135 if ( ranks_.size() )
136 {
137 auto rankIt = recv_.begin();
138 // translate index maps from global cartesian to index
139 for (auto& indexMap: indexMaps_)
140 {
141 int rank = 0;
142 if (rankIt != recv_.end())
143 rank = *rankIt;
144
145 for (auto&& entry: indexMap)
146 {
147 auto candidate = globalPosition_.find(entry);
148 assert(candidate != globalPosition_.end());
149 entry = candidate->second;
150 // Using max should be backwards compatible
151 ranks_[entry] = std::max(ranks_[entry], rank);
152 }
153 if (rankIt != recv_.end())
154 ++rankIt;
155 }
156 #ifndef NDEBUG
157 for (const auto& rank: ranks_)
158 assert(rank>=0);
159 #endif
160 }
161 }
162
163 void pack(int link, MessageBufferType& buffer)
164 {
165 // we should only get one link
166 if (link != 0)
167 throw std::logic_error("link in method pack is not 0 as execpted");
168
169 // pack all interior global cell id's
170 int size = localIndexMap_.size();
171 buffer.write(size);
172
173 for (int index = 0; index < size; ++index) {
174 int globalIdx = distributedGlobalIndex_[localIndexMap_[index]];
175 buffer.write(globalIdx);
176 }
177 }
178
179 void unpack(int link, MessageBufferType& buffer)
180 {
181 // get index map for current link
182 IndexMapType& indexMap = indexMaps_[link];
183 assert(!globalPosition_.empty());
184
185 // unpack all interior global cell id's
186 int numCells = 0;
187 buffer.read(numCells);
188 indexMap.resize(numCells);
189 for (int index = 0; index < numCells; ++index) {
190 buffer.read(indexMap[index]);
191 }
192 }
193};
194
195
197template<class EquilMapper, class Mapper>
199{
200public:
201 ElementIndexScatterHandle(const EquilMapper& sendMapper, const Mapper& recvMapper, std::vector<int>& elementIndices)
202 : sendMapper_(sendMapper), recvMapper_(recvMapper), elementIndices_(elementIndices)
203 {}
204 using DataType = int;
205 bool fixedSize(int /*dim*/, int /*codim*/)
206 {
207 return true;
208 }
209
210 template<class T>
211 std::size_t size(const T&)
212 {
213 return 1;
214 }
215 template<class B, class T>
216 void gather(B& buffer, const T& t)
217 {
218 buffer.write(sendMapper_.index(t));
219 }
220 template<class B, class T>
221 void scatter(B& buffer, const T& t, std::size_t)
222 {
223 buffer.read(elementIndices_[recvMapper_.index(t)]);
224 }
225
226 bool contains(int dim, int codim)
227 {
228 return dim==3 && codim==0;
229 }
230private:
231 const EquilMapper& sendMapper_;
232 const Mapper& recvMapper_;
233 std::vector<int>& elementIndices_;
234};
235
237template<class Mapper>
239{
240public:
241 ElementIndexHandle(const Mapper& mapper, std::vector<int>& elementIndices)
242 : mapper_(mapper), elementIndices_(elementIndices)
243 {}
244 using DataType = int;
245 bool fixedSize(int /*dim*/, int /*codim*/)
246 {
247 return true;
248 }
249
250 template<class T>
251 std::size_t size(const T&)
252 {
253 return 1;
254 }
255 template<class B, class T>
256 void gather(B& buffer, const T& t)
257 {
258 buffer.write(elementIndices_[mapper_.index(t)]);
259 }
260 template<class B, class T>
261 void scatter(B& buffer, const T& t, std::size_t)
262 {
263 buffer.read(elementIndices_[mapper_.index(t)]);
264 }
265
266 bool contains(int dim, int codim)
267 {
268 return dim==3 && codim==0;
269 }
270private:
271 const Mapper& mapper_;
272 std::vector<int>& elementIndices_;
273};
274
275class PackUnPackCellData : public P2PCommunicatorType::DataHandleInterface
276{
277 const data::Solution& localCellData_;
278 data::Solution& globalCellData_;
279
280 const IndexMapType& localIndexMap_;
281 const IndexMapStorageType& indexMaps_;
282
283public:
284 PackUnPackCellData(const data::Solution& localCellData,
285 data::Solution& globalCellData,
286 const IndexMapType& localIndexMap,
287 const IndexMapStorageType& indexMaps,
288 std::size_t globalSize,
289 bool isIORank)
290 : localCellData_(localCellData)
291 , globalCellData_(globalCellData)
292 , localIndexMap_(localIndexMap)
293 , indexMaps_(indexMaps)
294 {
295 if (isIORank) {
296 // add missing data to global cell data
297 for (const auto& pair : localCellData_) {
298 const std::string& key = pair.first;
299 std::size_t containerSize = globalSize;
300 [[maybe_unused]] auto ret = globalCellData_.insert(key, pair.second.dim,
301 std::vector<double>(containerSize),
302 pair.second.target);
303 assert(ret.second);
304 }
305
306 MessageBufferType buffer;
307 pack(0, buffer);
308
309 // the last index map is the local one
310 doUnpack(indexMaps.back(), buffer);
311 }
312 }
313
314 // pack all data associated with link
315 void pack(int link, MessageBufferType& buffer)
316 {
317 // we should only get one link
318 if (link != 0)
319 throw std::logic_error("link in method pack is not 0 as expected");
320
321 // write all cell data registered in local state
322 for (const auto& pair : localCellData_) {
323 const auto& data = pair.second.data<double>();
324
325 // write all data from local data to buffer
326 write(buffer, localIndexMap_, data);
327 }
328 }
329
330 void doUnpack(const IndexMapType& indexMap, MessageBufferType& buffer)
331 {
332 // we loop over the data as
333 // its order governs the order the data got received.
334 for (auto& pair : localCellData_) {
335 const std::string& key = pair.first;
336 auto& data = globalCellData_.data<double>(key);
337
338 //write all data from local cell data to buffer
339 read(buffer, indexMap, data);
340 }
341 }
342
343 // unpack all data associated with link
344 void unpack(int link, MessageBufferType& buffer)
345 { doUnpack(indexMaps_[link], buffer); }
346
347protected:
348 template <class Vector>
350 const IndexMapType& localIndexMap,
351 const Vector& vector,
352 unsigned int offset = 0,
353 unsigned int stride = 1) const
354 {
355 unsigned int size = localIndexMap.size();
356 buffer.write(size);
357 assert(vector.size() >= stride * size);
358 for (unsigned int i=0; i<size; ++i)
359 {
360 unsigned int index = localIndexMap[i] * stride + offset;
361 assert(index < vector.size());
362 buffer.write(vector[index]);
363 }
364 }
365
366 template <class Vector>
368 const IndexMapType& indexMap,
369 Vector& vector,
370 unsigned int offset = 0,
371 unsigned int stride = 1) const
372 {
373 unsigned int size = 0;
374 buffer.read(size);
375 assert(size == indexMap.size());
376 for (unsigned int i=0; i<size; ++i) {
377 unsigned int index = indexMap[i] * stride + offset;
378 assert(index < vector.size());
379 buffer.read(vector[index]);
380 }
381 }
382};
383
384class PackUnPackWellData : public P2PCommunicatorType::DataHandleInterface
385{
386 const data::Wells& localWellData_;
387 data::Wells& globalWellData_;
388
389public:
390 PackUnPackWellData(const data::Wells& localWellData,
391 data::Wells& globalWellData,
392 bool isIORank)
393 : localWellData_(localWellData)
394 , globalWellData_(globalWellData)
395 {
396 if (isIORank) {
397 MessageBufferType buffer;
398 pack(0, buffer);
399
400 // pass a dummy_link to satisfy virtual class
401 int dummyLink = -1;
402 unpack(dummyLink, buffer);
403 }
404 }
405
406 // pack all data associated with link
407 void pack(int link, MessageBufferType& buffer)
408 {
409 // we should only get one link
410 if (link != 0)
411 throw std::logic_error("link in method pack is not 0 as expected");
412
413 localWellData_.write(buffer);
414 }
415
416 // unpack all data associated with link
417 void unpack(int /*link*/, MessageBufferType& buffer)
418 { globalWellData_.read(buffer); }
419
420};
421
422class PackUnPackGroupAndNetworkValues : public P2PCommunicatorType::DataHandleInterface
423{
424 const data::GroupAndNetworkValues& localGroupAndNetworkData_;
425 data::GroupAndNetworkValues& globalGroupAndNetworkData_;
426
427public:
428 PackUnPackGroupAndNetworkValues(const data::GroupAndNetworkValues& localGroupAndNetworkData,
429 data::GroupAndNetworkValues& globalGroupAndNetworkData,
430 const bool isIORank)
431 : localGroupAndNetworkData_ (localGroupAndNetworkData)
432 , globalGroupAndNetworkData_(globalGroupAndNetworkData)
433 {
434 if (! isIORank) { return; }
435
436 MessageBufferType buffer;
437 this->pack(0, buffer);
438
439 // pass a dummy_link to satisfy virtual class
440 const int dummyLink = -1;
441 this->unpack(dummyLink, buffer);
442 }
443
444 // pack all data associated with link
445 void pack(int link, MessageBufferType& buffer)
446 {
447 // we should only get one link
448 if (link != 0) {
449 throw std::logic_error {
450 "link in method pack is not 0 as expected"
451 };
452 }
453
454 // write all group and network (node/branch) data
455 this->localGroupAndNetworkData_.write(buffer);
456 }
457
458 // unpack all data associated with link
459 void unpack(int /*link*/, MessageBufferType& buffer)
460 { this->globalGroupAndNetworkData_.read(buffer); }
461};
462
463// Shared serialisation for the block-summary gather handles. The global B* map is
464// keyed by std::pair<keyword, cartesian-index>; the LGR LB* map by
465// std::tuple<keyword, level, level-local-cartesian-index>. std::apply serialises
466// either key shape: write the map size, then every key field (pair or tuple) followed
467// by the value -- one body, thin per-key callers (mirrors the producer-side
468// makeExtractor de-duplication).
469// Constrain the container to a map-like type (key_type/mapped_type +
470// insert_or_assign) rather than hard-coding std::map/std::unordered_map.
471template <typename C>
473 std::ranges::input_range<C> &&
474 requires {
475 typename C::key_type;
476 typename C::mapped_type;
477 } &&
478 requires (C& container,
479 const typename C::key_type& key,
480 typename C::mapped_type value)
481 {
482 { container.insert_or_assign(key, std::move(value)) };
483 };
484
485// range_value_t of a map is std::pair<const Key, Value>, so first_type is
486// const-qualified; strip the const so the unpack side can fill a writable key.
487template <MapLikeContainer C>
488using KeyTypeOf = std::remove_const_t<typename std::ranges::range_value_t<C>::first_type>;
489
490template <MapLikeContainer C>
491using MappedTypeOf = typename std::ranges::range_value_t<C>::second_type;
492
493template <MapLikeContainer KeyedMap, class MessageBufferType>
494void packKeyedBlockMap(const KeyedMap& localData, MessageBufferType& buffer)
495{
496 const unsigned int size = localData.size();
497 buffer.write(size);
498 for (const auto& [key, value] : localData) {
499 std::apply([&buffer](const auto&... field) { (buffer.write(field), ...); }, key);
500 buffer.write(value);
501 }
502}
503
504template <MapLikeContainer KeyedMap, class MessageBufferType>
505void unpackKeyedBlockMap(KeyedMap& globalData, MessageBufferType& buffer)
506{
507 unsigned int size = 0;
508 buffer.read(size);
509
510 // std::map has no reserve(); the probe compiles the call out for it, but keeps
511 // the helper correct should a hashed container be substituted later.
512 if constexpr (requires (KeyedMap& m, std::size_t n) { m.reserve(n); }) {
513 globalData.reserve(globalData.size() + size);
514 }
515
516 for (unsigned int i = 0; i < size; ++i) {
518 std::apply([&buffer](auto&... field) { (buffer.read(field), ...); }, key);
519
521 buffer.read(value);
522
523 // Duplicate keys are not expected here -- they would mean two ranks claim
524 // the same cell. Were one to occur, insert_or_assign() overwrites (last
525 // wins) and try_emplace() would keep the first; we overwrite.
526 globalData.insert_or_assign(std::move(key), std::move(value));
527 }
528}
529
530class PackUnPackBlockData : public P2PCommunicatorType::DataHandleInterface
531{
532 const std::map<std::pair<std::string, int>, double>& localBlockData_;
533 std::map<std::pair<std::string, int>, double>& globalBlockValues_;
534
535public:
536 PackUnPackBlockData(const std::map<std::pair<std::string, int>, double>& localBlockData,
537 std::map<std::pair<std::string, int>, double>& globalBlockValues,
538 bool isIORank)
539 : localBlockData_(localBlockData)
540 , globalBlockValues_(globalBlockValues)
541 {
542 if (isIORank) {
543 MessageBufferType buffer;
544 pack(0, buffer);
545
546 // pass a dummyLink to satisfy virtual class
547 int dummyLink = -1;
548 unpack(dummyLink, buffer);
549 }
550 }
551
552 // pack all data associated with link
553 void pack(int link, MessageBufferType& buffer)
554 {
555 // we should only get one link
556 if (link != 0)
557 throw std::logic_error("link in method pack is not 0 as expected");
558
559 packKeyedBlockMap(localBlockData_, buffer);
560 }
561
562 // unpack all data associated with link
563 void unpack(int /*link*/, MessageBufferType& buffer)
564 {
565 unpackKeyedBlockMap(globalBlockValues_, buffer);
566 }
567};
568
569class PackUnPackLgrBlockData : public P2PCommunicatorType::DataHandleInterface
570{
571 const std::map<std::tuple<std::string, int, int>, double>& localLgrBlockData_;
572 std::map<std::tuple<std::string, int, int>, double>& globalLgrBlockValues_;
573
574public:
575 PackUnPackLgrBlockData(const std::map<std::tuple<std::string, int, int>, double>& localLgrBlockData,
576 std::map<std::tuple<std::string, int, int>, double>& globalLgrBlockValues,
577 bool isIORank)
578 : localLgrBlockData_(localLgrBlockData)
579 , globalLgrBlockValues_(globalLgrBlockValues)
580 {
581 if (isIORank) {
582 MessageBufferType buffer;
583 pack(0, buffer);
584
585 // pass a dummyLink to satisfy virtual class
586 int dummyLink = -1;
587 unpack(dummyLink, buffer);
588 }
589 }
590
591 // pack all data associated with link
592 void pack(int link, MessageBufferType& buffer)
593 {
594 // we should only get one link
595 if (link != 0) {
596 throw std::logic_error("link in method pack is not 0 as expected");
597 }
598
599 packKeyedBlockMap(localLgrBlockData_, buffer);
600 }
601
602 // unpack all data associated with link
603 void unpack(int /*link*/, MessageBufferType& buffer)
604 {
605 unpackKeyedBlockMap(globalLgrBlockValues_, buffer);
606 }
607};
608
609class PackUnPackWBPData : public P2PCommunicatorType::DataHandleInterface
610{
611 const data::WellBlockAveragePressures& localWBPData_;
612 data::WellBlockAveragePressures& globalWBPValues_;
613
614public:
615 PackUnPackWBPData(const data::WellBlockAveragePressures& localWBPData,
616 data::WellBlockAveragePressures& globalWBPValues,
617 const bool isIORank)
618 : localWBPData_ (localWBPData)
619 , globalWBPValues_(globalWBPValues)
620 {
621 if (! isIORank) {
622 return;
623 }
624
625 MessageBufferType buffer;
626 pack(0, buffer);
627
628 // Pass a dummy link to satisfy base class API requirement
629 const int dummyLink = -1;
630 unpack(dummyLink, buffer);
631 }
632
633 // Pack all data associated with link
634 void pack(int link, MessageBufferType& buffer)
635 {
636 // We should only get one link
637 if (link != 0) {
638 throw std::logic_error {
639 "link (" + std::to_string(link) +
640 ") in method pack() is not 0 as expected"
641 };
642 }
643
644 // Write all local, per-well, WBP data
645 this->localWBPData_.write(buffer);
646 }
647
648 // Unpack all data associated with link
649 void unpack([[maybe_unused]] const int link,
650 MessageBufferType& buffer)
651 {
652 this->globalWBPValues_.read(buffer);
653 }
654};
655
656class PackUnPackWellTestState : public P2PCommunicatorType::DataHandleInterface
657{
658public:
659 PackUnPackWellTestState(const WellTestState& localWTestState,
660 WellTestState& globalWTestState,
661 bool isIORank)
662 : local_(localWTestState)
663 , global_(globalWTestState)
664 {
665 if (isIORank) {
666 MessageBufferType buffer;
667 pack(0, buffer);
668
669 // pass a dummyLink to satisfy virtual class
670 int dummyLink = -1;
671 unpack(dummyLink, buffer);
672 }
673 }
674
675 void pack(int link, MessageBufferType& buffer) {
676 if (link != 0)
677 throw std::logic_error("link in method pack is not 0 as expected");
678 this->local_.pack(buffer);
679 }
680
681 void unpack(int, MessageBufferType& buffer) {
682 this->global_.unpack(buffer);
683 }
684
685private:
686 const WellTestState& local_;
687 WellTestState& global_;
688};
689
690class PackUnPackAquiferData : public P2PCommunicatorType::DataHandleInterface
691{
692 const data::Aquifers& localAquiferData_;
693 data::Aquifers& globalAquiferData_;
694
695public:
696 PackUnPackAquiferData(const data::Aquifers& localAquiferData,
697 data::Aquifers& globalAquiferData,
698 bool isIORank)
699 : localAquiferData_(localAquiferData)
700 , globalAquiferData_(globalAquiferData)
701 {
702 if (isIORank) {
703 MessageBufferType buffer;
704 pack(0, buffer);
705
706 // pass a dummyLink to satisfy virtual class
707 int dummyLink = -1;
708 unpack(dummyLink, buffer);
709 }
710 }
711
712 // pack all data associated with link
713 void pack(int link, MessageBufferType& buffer)
714 {
715 // we should only get one link
716 if (link != 0)
717 throw std::logic_error("link in method pack is not 0 as expected");
718
719 int size = localAquiferData_.size();
720 buffer.write(size);
721 for (const auto& [key, data] : localAquiferData_) {
722 buffer.write(key);
723 data.write(buffer);
724 }
725 }
726
727 // unpack all data associated with link
728 void unpack(int /*link*/, MessageBufferType& buffer)
729 {
730 int size;
731 buffer.read(size);
732 for (int i = 0; i < size; ++i) {
733 int key;
734 buffer.read(key);
735 data::AquiferData data;
736 data.read(buffer);
737
738 auto& aq = this->globalAquiferData_[key];
739
740 this->unpackCommon(data, aq);
741
742 if (auto const* aquFet = data.typeData.get<data::AquiferType::Fetkovich>();
743 aquFet != nullptr)
744 {
745 this->unpackAquFet(*aquFet, aq);
746 }
747 else if (auto const* aquCT = data.typeData.get<data::AquiferType::CarterTracy>();
748 aquCT != nullptr)
749 {
750 this->unpackCarterTracy(*aquCT, aq);
751 }
752 else if (auto const* aquNum = data.typeData.get<data::AquiferType::Numerical>();
753 aquNum != nullptr)
754 {
755 this->unpackNumericAquifer(*aquNum, aq);
756 }
757 }
758 }
759
760private:
761 void unpackCommon(const data::AquiferData& data, data::AquiferData& aq)
762 {
763 aq.aquiferID = std::max(aq.aquiferID, data.aquiferID);
764 aq.pressure = std::max(aq.pressure, data.pressure);
765 aq.initPressure = std::max(aq.initPressure, data.initPressure);
766 aq.datumDepth = std::max(aq.datumDepth, data.datumDepth);
767 aq.fluxRate += data.fluxRate;
768 aq.volume += data.volume;
769 }
770
771 void unpackAquFet(const data::FetkovichData& aquFet, data::AquiferData& aq)
772 {
773 if (! aq.typeData.is<data::AquiferType::Fetkovich>()) {
774 auto* tData = aq.typeData.create<data::AquiferType::Fetkovich>();
775 *tData = aquFet;
776 }
777 else {
778 const auto& src = aquFet;
779 auto& dst = *aq.typeData.getMutable<data::AquiferType::Fetkovich>();
780
781 dst.initVolume = std::max(dst.initVolume , src.initVolume);
782 dst.prodIndex = std::max(dst.prodIndex , src.prodIndex);
783 dst.timeConstant = std::max(dst.timeConstant, src.timeConstant);
784 }
785 }
786
787 void unpackCarterTracy(const data::CarterTracyData& aquCT, data::AquiferData& aq)
788 {
789 if (! aq.typeData.is<data::AquiferType::CarterTracy>()) {
790 auto* tData = aq.typeData.create<data::AquiferType::CarterTracy>();
791 *tData = aquCT;
792 }
793 else {
794 const auto& src = aquCT;
795 auto& dst = *aq.typeData.getMutable<data::AquiferType::CarterTracy>();
796
797 dst.timeConstant = std::max(dst.timeConstant , src.timeConstant);
798 dst.influxConstant = std::max(dst.influxConstant, src.influxConstant);
799 dst.waterDensity = std::max(dst.waterDensity , src.waterDensity);
800 dst.waterViscosity = std::max(dst.waterViscosity, src.waterViscosity);
801
802 dst.dimensionless_time = std::max(dst.dimensionless_time , src.dimensionless_time);
803 dst.dimensionless_pressure = std::max(dst.dimensionless_pressure, src.dimensionless_pressure);
804 }
805 }
806
807 void unpackNumericAquifer(const data::NumericAquiferData& aquNum, data::AquiferData& aq)
808 {
809 if (! aq.typeData.is<data::AquiferType::Numerical>()) {
810 auto* tData = aq.typeData.create<data::AquiferType::Numerical>();
811 *tData = aquNum;
812 }
813 else {
814 const auto& src = aquNum;
815 auto& dst = *aq.typeData.getMutable<data::AquiferType::Numerical>();
816
817 std::ranges::transform(src.initPressure, dst.initPressure, dst.initPressure.begin(),
818 [](const double p0_1, const double p0_2)
819 { return std::max(p0_1, p0_2); });
820 }
821 }
822};
823
824class PackUnpackInterRegFlows : public P2PCommunicatorType::DataHandleInterface
825{
826 const InterRegFlowMap& localInterRegFlows_;
827 InterRegFlowMap& globalInterRegFlows_;
828
829public:
830 PackUnpackInterRegFlows(const InterRegFlowMap& localInterRegFlows,
831 InterRegFlowMap& globalInterRegFlows,
832 const bool isIORank)
833 : localInterRegFlows_(localInterRegFlows)
834 , globalInterRegFlows_(globalInterRegFlows)
835 {
836 if (! isIORank) { return; }
837
838 MessageBufferType buffer;
839 this->pack(0, buffer);
840
841 // pass a dummy_link to satisfy virtual class
842 const int dummyLink = -1;
843 this->unpack(dummyLink, buffer);
844 }
845
846 // pack all data associated with link
847 void pack(int link, MessageBufferType& buffer)
848 {
849 // we should only get one link
850 if (link != 0) {
851 throw std::logic_error {
852 "link in method pack is not 0 as expected"
853 };
854 }
855
856 // write all inter-region flow data
857 this->localInterRegFlows_.write(buffer);
858 }
859
860 // unpack all data associated with link
861 void unpack(int /*link*/, MessageBufferType& buffer)
862 { this->globalInterRegFlows_.read(buffer); }
863};
864
865class PackUnpackFlows : public P2PCommunicatorType::DataHandleInterface
866{
867 const std::array<FlowsData<double>, 3>& localFlows_;
868 std::array<FlowsData<double>, 3>& globalFlows_;
869
870public:
871 PackUnpackFlows(const std::array<FlowsData<double>, 3> & localFlows,
872 std::array<FlowsData<double>, 3>& globalFlows,
873 const bool isIORank)
874 : localFlows_(localFlows)
875 , globalFlows_(globalFlows)
876 {
877 if (! isIORank) { return; }
878
879 MessageBufferType buffer;
880 this->pack(0, buffer);
881
882 // pass a dummy_link to satisfy virtual class
883 const int dummyLink = -1;
884 this->unpack(dummyLink, buffer);
885 }
886
887 void pack(int link, MessageBufferType& buffer)
888 {
889 if (link != 0)
890 throw std::logic_error("link in method pack is not 0 as expected");
891 for (int i = 0; i < 3; ++i) {
892 const auto& name = localFlows_[i].name;
893 buffer.write(name);
894 const std::size_t size = localFlows_[i].indices.size();
895 buffer.write(size);
896 for (std::size_t j = 0; j < size; ++j) {
897 const auto& nncIdx = localFlows_[i].indices[j];
898 buffer.write(nncIdx);
899 const auto& flows = localFlows_[i].values[j];
900 buffer.write(flows);
901 }
902 }
903 }
904
905 void unpack(int /*link*/, MessageBufferType& buffer)
906 {
907 for (int i = 0; i < 3; ++i) {
908 std::string name;
909 buffer.read(name);
910 globalFlows_[i].name = name;
911 std::size_t size = 0;
912 buffer.read(size);
913 for (unsigned int j = 0; j < size; ++j) {
914 int nncIdx;
915 double data;
916 buffer.read(nncIdx);
917 buffer.read(data);
918 if (nncIdx < 0)
919 continue;
920 // This array is initialized in the collect(...) method below
921 globalFlows_[i].values[nncIdx] = data;
922 }
923 }
924 }
925};
926
927template <class Grid, class EquilGrid, class GridView>
929CollectDataOnIORank(const Grid& grid, const EquilGrid* equilGrid,
930 const GridView& localGridView,
931 const Dune::CartesianIndexMapper<Grid>& cartMapper,
932 const Dune::CartesianIndexMapper<EquilGrid>* equilCartMapper,
933 const std::set<std::string>& fipRegionsInterregFlow)
934 : toIORankComm_(grid.comm())
935 , globalInterRegFlows_(InterRegFlowMap::createMapFromNames({
936 fipRegionsInterregFlow.begin(),
937 fipRegionsInterregFlow.end()
938 }))
939{
940 // Build index maps only when reordering is needed; skip in parallel runs for CpGrid with LGRs
941 if ((!needsReordering && !isParallel()) || (isParallel() && (grid.maxLevel()>0)))
942 return;
943
944 const CollectiveCommunication& comm = grid.comm();
945
946 {
947 std::set<int> send, recv;
948 using EquilGridView = typename EquilGrid::LeafGridView;
949 typename std::is_same<Grid, EquilGrid>::type isSameGrid;
950
951 typedef Dune::MultipleCodimMultipleGeomTypeMapper<GridView> ElementMapper;
952 ElementMapper elemMapper(localGridView, Dune::mcmgElementLayout());
953 sortedCartesianIdx_.reserve(localGridView.size(0));
954
955 for (const auto& elem : elements(localGridView, Dune::Partitions::interior))
956 {
957 auto idx = elemMapper.index(elem);
958 sortedCartesianIdx_.push_back(cartMapper.cartesianIndex(idx));
959 }
960
961 std::ranges::sort(sortedCartesianIdx_);
962 localIdxToGlobalIdx_.resize(localGridView.size(0), -1);
963
964 // the I/O rank receives from all other ranks
965 if (isIORank()) {
966 // We need a mapping from local to global grid, here we
967 // use equilGrid which represents a view on the global grid
968 // reserve memory
969 const std::size_t globalSize = equilGrid->leafGridView().size(0);
970 globalCartesianIndex_.resize(globalSize, -1);
971 const EquilGridView equilGridView = equilGrid->leafGridView();
972
973 using EquilElementMapper = Dune::MultipleCodimMultipleGeomTypeMapper<EquilGridView>;
974 EquilElementMapper equilElemMapper(equilGridView, Dune::mcmgElementLayout());
975
976 // Scatter the global index to local index for lookup during restart
977 if constexpr (isSameGrid) {
978 ElementIndexScatterHandle<EquilElementMapper,ElementMapper> handle(equilElemMapper, elemMapper, localIdxToGlobalIdx_);
979 grid.scatterData(handle);
980 }
981
982 // loop over all elements (global grid) and store Cartesian index
983 for (const auto& elem : elements(equilGrid->leafGridView())) {
984 int elemIdx = equilElemMapper.index(elem);
985 int cartElemIdx = equilCartMapper->cartesianIndex(elemIdx);
986 globalCartesianIndex_[elemIdx] = cartElemIdx;
987 }
988
989 for (int i = 0; i < comm.size(); ++i) {
990 if (i != ioRank)
991 recv.insert(i);
992 }
993 }
994 else
995 {
996 // all other simply send to the I/O rank
997 send.insert(ioRank);
998
999 // Scatter the global index to local index for lookup during restart
1000 // This is a bit hacky since the type differs from the iorank.
1001 // But should work since we only receive, i.e. use the second parameter.
1002 if constexpr (isSameGrid) {
1003 ElementIndexScatterHandle<ElementMapper, ElementMapper> handle(elemMapper, elemMapper, localIdxToGlobalIdx_);
1004 grid.scatterData(handle);
1005 }
1006 }
1007
1008 // Sync the global element indices
1009 if constexpr (isSameGrid) {
1010 ElementIndexHandle<ElementMapper> handle(elemMapper, localIdxToGlobalIdx_);
1011 grid.communicate(handle, Dune::InteriorBorder_All_Interface,
1012 Dune::ForwardCommunication);
1013 }
1014
1015 localIndexMap_.clear();
1016 const std::size_t gridSize = grid.size(0);
1017 localIndexMap_.reserve(gridSize);
1018
1019 // store the local Cartesian index
1020 IndexMapType distributedCartesianIndex;
1021 distributedCartesianIndex.resize(gridSize, -1);
1022
1023 // A mapping for the whole grid (including the ghosts) is needed for restarts
1024 for (const auto& elem : elements(localGridView, Dune::Partitions::interior)) {
1025 int elemIdx = elemMapper.index(elem);
1026 distributedCartesianIndex[elemIdx] = cartMapper.cartesianIndex(elemIdx);
1027
1028 // only store interior element for collection
1029 assert(elem.partitionType() == Dune::InteriorEntity);
1030
1031 localIndexMap_.push_back(elemIdx);
1032 }
1033
1034 // insert send and recv linkage to communicator
1035 toIORankComm_.insertRequest(send, recv);
1036
1037 // need an index map for each rank
1038 indexMaps_.clear();
1039 indexMaps_.resize(comm.size());
1040
1041 // distribute global id's to io rank for later association of dof's
1042 DistributeIndexMapping distIndexMapping(globalCartesianIndex_,
1043 distributedCartesianIndex,
1044 localIndexMap_,
1045 indexMaps_,
1046 globalRanks_,
1047 recv,
1048 isIORank());
1049 toIORankComm_.exchange(distIndexMapping);
1050 }
1051}
1052
1053template <class Grid, class EquilGrid, class GridView>
1055collect(const data::Solution& localCellData,
1056 const std::map<std::pair<std::string, int>, double>& localBlockData,
1057 std::map<std::pair<std::string, int>, double>& extraBlockData,
1058 const data::Wells& localWellData,
1059 const data::WellBlockAveragePressures& localWBPData,
1060 const data::GroupAndNetworkValues& localGroupAndNetworkData,
1061 const data::Aquifers& localAquiferData,
1062 const WellTestState& localWellTestState,
1063 const InterRegFlowMap& localInterRegFlows,
1064 const std::array<FlowsData<double>, 3>& localFlowsn,
1065 const std::array<FlowsData<double>, 3>& localFloresn,
1066 const std::map<std::tuple<std::string, int, int>, double>& localLgrBlockData)
1067{
1068 globalCellData_ = {};
1069 globalBlockData_.clear();
1070 globalLgrBlockData_.clear();
1071 std::map<std::pair<std::string,int>,double> globalExtraBlockData;
1072 globalWellData_.clear();
1073 globalWBPData_.values.clear();
1074 globalGroupAndNetworkData_.clear();
1075 globalAquiferData_.clear();
1076 globalWellTestState_.clear();
1077 this->globalInterRegFlows_.clear();
1078 globalFlowsn_ = {};
1079 globalFloresn_ = {};
1080
1081 // index maps only have to be build when reordering is needed
1082 if(!needsReordering && !isParallel())
1083 return;
1084
1085 // this also linearises the local buffers on ioRank
1086 PackUnPackCellData packUnpackCellData {
1087 localCellData,
1088 this->globalCellData_,
1089 this->localIndexMap_,
1090 this->indexMaps_,
1091 this->numCells(),
1092 this->isIORank()
1093 };
1094
1095 if (! isParallel()) {
1096 // no need to collect anything.
1097 return;
1098 }
1099
1100 // Set the right sizes for Flowsn and Floresn
1101 for (int i = 0; i < 3; ++i) {
1102 const std::size_t sizeFlr = localFloresn[i].indices.size();
1103 globalFloresn_[i].resize(sizeFlr);
1104 const std::size_t sizeFlo = localFlowsn[i].indices.size();
1105 globalFlowsn_[i].resize(sizeFlo);
1106 }
1107
1108 PackUnPackWellData packUnpackWellData {
1109 localWellData,
1110 this->globalWellData_,
1111 this->isIORank()
1112 };
1113
1114 PackUnPackGroupAndNetworkValues packUnpackGroupAndNetworkData {
1115 localGroupAndNetworkData,
1116 this->globalGroupAndNetworkData_,
1117 this->isIORank()
1118 };
1119
1120 PackUnPackBlockData packUnpackBlockData {
1121 localBlockData,
1122 this->globalBlockData_,
1123 this->isIORank()
1124 };
1125
1126 PackUnPackBlockData packUnpackExtraBlockData {
1127 extraBlockData,
1128 globalExtraBlockData,
1129 this->isIORank()
1130 };
1131
1132 PackUnPackLgrBlockData packUnpackLgrBlockData {
1133 localLgrBlockData,
1134 this->globalLgrBlockData_,
1135 this->isIORank()
1136 };
1137
1138 PackUnPackWBPData packUnpackWBPData {
1139 localWBPData,
1140 this->globalWBPData_,
1141 this->isIORank()
1142 };
1143
1144 PackUnPackAquiferData packUnpackAquiferData {
1145 localAquiferData,
1146 this->globalAquiferData_,
1147 this->isIORank()
1148 };
1149
1150 PackUnPackWellTestState packUnpackWellTestState {
1151 localWellTestState,
1152 this->globalWellTestState_,
1153 this->isIORank()
1154 };
1155
1156 PackUnpackInterRegFlows packUnpackInterRegFlows {
1157 localInterRegFlows,
1158 this->globalInterRegFlows_,
1159 this->isIORank()
1160 };
1161
1162 PackUnpackFlows packUnpackFlowsn {
1163 localFlowsn,
1164 this->globalFlowsn_,
1165 this->isIORank()
1166 };
1167
1168 PackUnpackFlows packUnpackFloresn {
1169 localFloresn,
1170 this->globalFloresn_,
1171 this->isIORank()
1172 };
1173
1174 toIORankComm_.exchange(packUnpackCellData);
1175 toIORankComm_.exchange(packUnpackWellData);
1176 toIORankComm_.exchange(packUnpackGroupAndNetworkData);
1177 toIORankComm_.exchange(packUnpackBlockData);
1178 toIORankComm_.exchange(packUnpackExtraBlockData);
1179 toIORankComm_.exchange(packUnpackLgrBlockData);
1180 toIORankComm_.exchange(packUnpackWBPData);
1181 toIORankComm_.exchange(packUnpackAquiferData);
1182 toIORankComm_.exchange(packUnpackWellTestState);
1183 toIORankComm_.exchange(packUnpackInterRegFlows);
1184 toIORankComm_.exchange(packUnpackFlowsn);
1185 toIORankComm_.exchange(packUnpackFloresn);
1186
1187#ifndef NDEBUG
1188 // make sure every process is on the same page
1189 toIORankComm_.barrier();
1190#endif
1191
1192 extraBlockData = globalExtraBlockData;
1193}
1194
1195template <class Grid, class EquilGrid, class GridView>
1197localIdxToGlobalIdx(unsigned localIdx) const
1198{
1199 if (!isParallel()) {
1200 return localIdx;
1201 }
1202
1203 if (this->localIdxToGlobalIdx_.empty()) {
1204 throw std::logic_error("index map is not created on this rank");
1205 }
1206
1207 if (localIdx >= this->localIdxToGlobalIdx_.size()) {
1208 throw std::logic_error("local index is outside map range");
1209 }
1210
1211 return this->localIdxToGlobalIdx_[localIdx];
1212}
1213
1214template <class Grid, class EquilGrid, class GridView>
1216isCartIdxOnThisRank(int cartIdx) const
1217{
1218 if (! this->isParallel()) {
1219 return true;
1220 }
1221
1222 assert (! needsReordering);
1223
1224 auto candidate = std::lower_bound(this->sortedCartesianIdx_.begin(),
1225 this->sortedCartesianIdx_.end(),
1226 cartIdx);
1227
1228 return (candidate != sortedCartesianIdx_.end())
1229 && (*candidate == cartIdx);
1230}
1231
1232} // end namespace Opm
1233
1234#endif // OPM_COLLECT_DATA_ON_IO_RANK_IMPL_HPP
Definition: CollectDataOnIORank.hpp:50
int localIdxToGlobalIdx(unsigned localIdx) const
Definition: CollectDataOnIORank_impl.hpp:1197
bool isCartIdxOnThisRank(int cartIdx) const
Definition: CollectDataOnIORank_impl.hpp:1216
CollectDataOnIORank(const Grid &grid, const EquilGrid *equilGrid, const GridView &gridView, const Dune::CartesianIndexMapper< Grid > &cartMapper, const Dune::CartesianIndexMapper< EquilGrid > *equilCartMapper, const std::set< std::string > &fipRegionsInterregFlow={})
Definition: CollectDataOnIORank_impl.hpp:929
void collect(const data::Solution &localCellData, const std::map< std::pair< std::string, int >, double > &localBlockData, std::map< std::pair< std::string, int >, double > &localExtraBlockData, const data::Wells &localWellData, const data::WellBlockAveragePressures &localWBPData, const data::GroupAndNetworkValues &localGroupAndNetworkData, const data::Aquifers &localAquiferData, const WellTestState &localWellTestState, const InterRegFlowMap &interRegFlows, const std::array< FlowsData< double >, 3 > &localFlowsn, const std::array< FlowsData< double >, 3 > &localFloresn, const std::map< std::tuple< std::string, int, int >, double > &localLgrBlockData)
Definition: CollectDataOnIORank_impl.hpp:1055
Definition: CollectDataOnIORank_impl.hpp:84
void pack(int link, MessageBufferType &buffer)
Definition: CollectDataOnIORank_impl.hpp:163
std::map< int, int > globalPosition_
Definition: CollectDataOnIORank_impl.hpp:89
std::vector< int > & ranks_
Definition: CollectDataOnIORank_impl.hpp:91
IndexMapStorageType & indexMaps_
Definition: CollectDataOnIORank_impl.hpp:88
DistributeIndexMapping(const std::vector< int > &globalIndex, const std::vector< int > &distributedGlobalIndex, IndexMapType &localIndexMap, IndexMapStorageType &indexMaps, std::vector< int > &ranks, std::set< int > &recv, bool isIORank)
Definition: CollectDataOnIORank_impl.hpp:94
IndexMapType & localIndexMap_
Definition: CollectDataOnIORank_impl.hpp:87
const std::vector< int > & distributedGlobalIndex_
Definition: CollectDataOnIORank_impl.hpp:86
void unpack(int link, MessageBufferType &buffer)
Definition: CollectDataOnIORank_impl.hpp:179
~DistributeIndexMapping()
Definition: CollectDataOnIORank_impl.hpp:130
std::set< int > & recv_
Definition: CollectDataOnIORank_impl.hpp:90
Communication handle to scatter the global index.
Definition: CollectDataOnIORank_impl.hpp:239
std::size_t size(const T &)
Definition: CollectDataOnIORank_impl.hpp:251
bool fixedSize(int, int)
Definition: CollectDataOnIORank_impl.hpp:245
void scatter(B &buffer, const T &t, std::size_t)
Definition: CollectDataOnIORank_impl.hpp:261
void gather(B &buffer, const T &t)
Definition: CollectDataOnIORank_impl.hpp:256
int DataType
Definition: CollectDataOnIORank_impl.hpp:244
bool contains(int dim, int codim)
Definition: CollectDataOnIORank_impl.hpp:266
ElementIndexHandle(const Mapper &mapper, std::vector< int > &elementIndices)
Definition: CollectDataOnIORank_impl.hpp:241
Communication handle to scatter the global index.
Definition: CollectDataOnIORank_impl.hpp:199
std::size_t size(const T &)
Definition: CollectDataOnIORank_impl.hpp:211
bool contains(int dim, int codim)
Definition: CollectDataOnIORank_impl.hpp:226
void gather(B &buffer, const T &t)
Definition: CollectDataOnIORank_impl.hpp:216
ElementIndexScatterHandle(const EquilMapper &sendMapper, const Mapper &recvMapper, std::vector< int > &elementIndices)
Definition: CollectDataOnIORank_impl.hpp:201
void scatter(B &buffer, const T &t, std::size_t)
Definition: CollectDataOnIORank_impl.hpp:221
bool fixedSize(int, int)
Definition: CollectDataOnIORank_impl.hpp:205
int DataType
Definition: CollectDataOnIORank_impl.hpp:204
Definition: CollectDataOnIORank_impl.hpp:52
int localIndex() const
Definition: CollectDataOnIORank_impl.hpp:71
void setIndex(int localIndex)
Definition: CollectDataOnIORank_impl.hpp:68
int id() const
Definition: CollectDataOnIORank_impl.hpp:73
GlobalCellIndex()
Definition: CollectDataOnIORank_impl.hpp:58
void setGhost()
Definition: CollectDataOnIORank_impl.hpp:63
bool isInterior() const
Definition: CollectDataOnIORank_impl.hpp:75
void setId(int globalId)
Definition: CollectDataOnIORank_impl.hpp:66
Inter-region flow accumulation maps for all region definition arrays.
Definition: InterRegFlows.hpp:179
void read(MessageBufferType &buffer)
Definition: InterRegFlows.hpp:323
void write(MessageBufferType &buffer) const
Definition: InterRegFlows.hpp:296
Definition: CollectDataOnIORank_impl.hpp:691
void unpack(int, MessageBufferType &buffer)
Definition: CollectDataOnIORank_impl.hpp:728
void pack(int link, MessageBufferType &buffer)
Definition: CollectDataOnIORank_impl.hpp:713
PackUnPackAquiferData(const data::Aquifers &localAquiferData, data::Aquifers &globalAquiferData, bool isIORank)
Definition: CollectDataOnIORank_impl.hpp:696
Definition: CollectDataOnIORank_impl.hpp:531
void pack(int link, MessageBufferType &buffer)
Definition: CollectDataOnIORank_impl.hpp:553
PackUnPackBlockData(const std::map< std::pair< std::string, int >, double > &localBlockData, std::map< std::pair< std::string, int >, double > &globalBlockValues, bool isIORank)
Definition: CollectDataOnIORank_impl.hpp:536
void unpack(int, MessageBufferType &buffer)
Definition: CollectDataOnIORank_impl.hpp:563
Definition: CollectDataOnIORank_impl.hpp:276
void unpack(int link, MessageBufferType &buffer)
Definition: CollectDataOnIORank_impl.hpp:344
PackUnPackCellData(const data::Solution &localCellData, data::Solution &globalCellData, const IndexMapType &localIndexMap, const IndexMapStorageType &indexMaps, std::size_t globalSize, bool isIORank)
Definition: CollectDataOnIORank_impl.hpp:284
void pack(int link, MessageBufferType &buffer)
Definition: CollectDataOnIORank_impl.hpp:315
void read(MessageBufferType &buffer, const IndexMapType &indexMap, Vector &vector, unsigned int offset=0, unsigned int stride=1) const
Definition: CollectDataOnIORank_impl.hpp:367
void write(MessageBufferType &buffer, const IndexMapType &localIndexMap, const Vector &vector, unsigned int offset=0, unsigned int stride=1) const
Definition: CollectDataOnIORank_impl.hpp:349
void doUnpack(const IndexMapType &indexMap, MessageBufferType &buffer)
Definition: CollectDataOnIORank_impl.hpp:330
Definition: CollectDataOnIORank_impl.hpp:423
void unpack(int, MessageBufferType &buffer)
Definition: CollectDataOnIORank_impl.hpp:459
PackUnPackGroupAndNetworkValues(const data::GroupAndNetworkValues &localGroupAndNetworkData, data::GroupAndNetworkValues &globalGroupAndNetworkData, const bool isIORank)
Definition: CollectDataOnIORank_impl.hpp:428
void pack(int link, MessageBufferType &buffer)
Definition: CollectDataOnIORank_impl.hpp:445
Definition: CollectDataOnIORank_impl.hpp:570
void unpack(int, MessageBufferType &buffer)
Definition: CollectDataOnIORank_impl.hpp:603
void pack(int link, MessageBufferType &buffer)
Definition: CollectDataOnIORank_impl.hpp:592
PackUnPackLgrBlockData(const std::map< std::tuple< std::string, int, int >, double > &localLgrBlockData, std::map< std::tuple< std::string, int, int >, double > &globalLgrBlockValues, bool isIORank)
Definition: CollectDataOnIORank_impl.hpp:575
Definition: CollectDataOnIORank_impl.hpp:610
void pack(int link, MessageBufferType &buffer)
Definition: CollectDataOnIORank_impl.hpp:634
PackUnPackWBPData(const data::WellBlockAveragePressures &localWBPData, data::WellBlockAveragePressures &globalWBPValues, const bool isIORank)
Definition: CollectDataOnIORank_impl.hpp:615
void unpack(const int link, MessageBufferType &buffer)
Definition: CollectDataOnIORank_impl.hpp:649
Definition: CollectDataOnIORank_impl.hpp:385
PackUnPackWellData(const data::Wells &localWellData, data::Wells &globalWellData, bool isIORank)
Definition: CollectDataOnIORank_impl.hpp:390
void pack(int link, MessageBufferType &buffer)
Definition: CollectDataOnIORank_impl.hpp:407
void unpack(int, MessageBufferType &buffer)
Definition: CollectDataOnIORank_impl.hpp:417
Definition: CollectDataOnIORank_impl.hpp:657
void pack(int link, MessageBufferType &buffer)
Definition: CollectDataOnIORank_impl.hpp:675
PackUnPackWellTestState(const WellTestState &localWTestState, WellTestState &globalWTestState, bool isIORank)
Definition: CollectDataOnIORank_impl.hpp:659
void unpack(int, MessageBufferType &buffer)
Definition: CollectDataOnIORank_impl.hpp:681
Definition: CollectDataOnIORank_impl.hpp:866
void pack(int link, MessageBufferType &buffer)
Definition: CollectDataOnIORank_impl.hpp:887
void unpack(int, MessageBufferType &buffer)
Definition: CollectDataOnIORank_impl.hpp:905
PackUnpackFlows(const std::array< FlowsData< double >, 3 > &localFlows, std::array< FlowsData< double >, 3 > &globalFlows, const bool isIORank)
Definition: CollectDataOnIORank_impl.hpp:871
Definition: CollectDataOnIORank_impl.hpp:825
void pack(int link, MessageBufferType &buffer)
Definition: CollectDataOnIORank_impl.hpp:847
void unpack(int, MessageBufferType &buffer)
Definition: CollectDataOnIORank_impl.hpp:861
PackUnpackInterRegFlows(const InterRegFlowMap &localInterRegFlows, InterRegFlowMap &globalInterRegFlows, const bool isIORank)
Definition: CollectDataOnIORank_impl.hpp:830
Definition: CollectDataOnIORank_impl.hpp:472
static constexpr int dim
Definition: structuredgridvanguard.hh:68
Definition: blackoilbioeffectsmodules.hh:45
std::vector< int > IndexMapType
Definition: CollectDataOnIORank_impl.hpp:79
void packKeyedBlockMap(const KeyedMap &localData, MessageBufferType &buffer)
Definition: CollectDataOnIORank_impl.hpp:494
std::remove_const_t< typename std::ranges::range_value_t< C >::first_type > KeyTypeOf
Definition: CollectDataOnIORank_impl.hpp:488
typename std::ranges::range_value_t< C >::second_type MappedTypeOf
Definition: CollectDataOnIORank_impl.hpp:491
Dune::Point2PointCommunicator< Dune::SimpleMessageBuffer > P2PCommunicatorType
Definition: CollectDataOnIORank_impl.hpp:81
std::vector< IndexMapType > IndexMapStorageType
Definition: CollectDataOnIORank_impl.hpp:80
std::string to_string(const ConvergenceReport::ReservoirFailure::Type t)
typename P2PCommunicatorType::MessageBufferType MessageBufferType
Definition: CollectDataOnIORank_impl.hpp:82
void unpackKeyedBlockMap(KeyedMap &globalData, MessageBufferType &buffer)
Definition: CollectDataOnIORank_impl.hpp:505