version 3.11-dev
All Classes Namespaces Files Functions Variables Typedefs Enumerations Enumerator Friends Macros Modules Pages Concepts
vtkgriddatahandle.hh
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// SPDX-FileCopyrightText: Copyright © DuMux Project contributors, see AUTHORS.md in root folder
5// SPDX-License-Identifier: GPL-3.0-or-later
6//
12#ifndef DUMUX_VTK_GRID_DATA_HANDLE_HH
13#define DUMUX_VTK_GRID_DATA_HANDLE_HH
14
15#include <memory>
16#include <algorithm>
17#include <map>
18#include <numeric>
19
20#include <dune/common/parallel/communication.hh>
21#include <dune/geometry/dimension.hh>
22#include <dune/grid/common/partitionset.hh>
23#include <dune/grid/common/datahandleif.hh>
24
26
27namespace Dumux {
28
33template<class Grid, class GridFactory, class Data>
35: public Dune::CommDataHandleIF<VtkGridDataHandle<Grid, GridFactory, Data>, typename Data::value_type>
36{
37 using GridView = typename Grid::LevelGridView;
38
39 VtkGridDataHandle(const Grid& grid, const GridFactory& gridFactory, VTKReader::Data& cellData, VTKReader::Data& pointData)
40 : gridView_(grid.levelGridView(0))
41 , idSet_(grid.localIdSet())
42 , userCellData_(cellData)
43 , userPointData_(pointData)
44 {
45 // For the following to work we assume a sorted map of keys to values in the user data.
46 // This is not guaranteed by the VTKReader, so we need to sort the data first.
47 for (const auto& [key, data] : userCellData_)
48 cellData_[key] = std::move(userCellData_[key]);
49 for (const auto& [key, data] : userPointData_)
50 pointData_[key] = std::move(userPointData_[key]);
51
52 // assume all data is on rank 0 (see grid manager)
53 // First broadcast how many keys we have
54 std::array<std::size_t, 2> numKeys{{ cellData_.size(), pointData_.size() }};
55 Dune::MPIHelper::getCommunication().broadcast(numKeys.data(), 2, 0);
56
57 // then broadcast the length of the individual key strings
58 // and the number of component associated with each key (e.g. vector/tensor fields)
59 std::vector<std::size_t> keyLengthAndComponents(2*(numKeys[0] + numKeys[1]), 0);
60 {
61 int n = 0;
62
63 // key length
64 for (const auto& [key, data] : cellData_)
65 keyLengthAndComponents[n++] = key.size();
66 for (const auto& [key, data] : pointData_)
67 keyLengthAndComponents[n++] = key.size();
68
69 // number of components
70 for (const auto& [key, data] : cellData_)
71 keyLengthAndComponents[n++] = gridView_.size(0) > 0 ? data.size()/gridView_.size(0) : 0;
72 for (const auto& [key, data] : pointData_)
73 keyLengthAndComponents[n++] = gridView_.size(Grid::dimension) > 0 ? data.size()/gridView_.size(Grid::dimension) : 0;
74
75 // entries only exist on rank 0 and the data containers are empty on other ranks
76 assert((Dune::MPIHelper::instance().rank() == 0) == (n == keyLengthAndComponents.size()));
77
78 Dune::MPIHelper::getCommunication().broadcast(keyLengthAndComponents.data(), keyLengthAndComponents.size(), 0);
79 }
80
81 // save the number of components for each cell and point data array
82 const auto begin = keyLengthAndComponents.begin() + numKeys[0] + numKeys[1];
83 cellDataComponents_.assign(begin, begin + numKeys[0]);
84 pointDataComponents_.assign(begin + numKeys[0], keyLengthAndComponents.end());
85 numCellDataPerElement_ = std::accumulate(cellDataComponents_.begin(), cellDataComponents_.end(), 0UL);
86 numPointDataPerVertex_ = std::accumulate(pointDataComponents_.begin(), pointDataComponents_.end(), 0UL);
87
88 // then broadcast the actual keys
89 std::string keys; keys.resize(std::accumulate(keyLengthAndComponents.begin(), begin, 0UL));
90 {
91 int n = 0;
92 for (const auto& [key, data] : cellData_)
93 for (const auto& c : key)
94 keys[n++] = c;
95 for (const auto& [key, data] : pointData_)
96 for (const auto& c : key)
97 keys[n++] = c;
98
99 // entries only exist on rank 0 and the data containers are empty on other ranks
100 assert((Dune::MPIHelper::instance().rank() == 0) == (n == keys.size()));
101
102 Dune::MPIHelper::getCommunication().broadcast(keys.data(), keys.size(), 0);
103 }
104
105 // create the entries in the cellData and pointData maps on all processes
106 std::size_t offset = 0;
107 for (int keyIdx = 0; keyIdx < numKeys[0]; ++keyIdx)
108 {
109 if (std::string key{ keys, offset, keyLengthAndComponents[keyIdx] }; cellData_.count(key) == 0)
110 cellData_[key] = Data{};
111
112 offset += keyLengthAndComponents[keyIdx];
113 }
114 for (int keyIdx = numKeys[0]; keyIdx < numKeys[0] + numKeys[1]; ++keyIdx)
115 {
116 if (std::string key{ keys, offset, keyLengthAndComponents[keyIdx] }; pointData_.count(key) == 0)
117 pointData_[key] = Data{};
118
119 offset += keyLengthAndComponents[keyIdx];
120 }
121
122 // write data into an id map
123 for (const auto& element : elements(gridView_, Dune::Partitions::interior))
124 {
125 data_[idSet_.id(element)].resize(numCellDataPerElement_);
126
127 int n = 0, l = 0;
128 for (const auto& [key, data] : cellData_)
129 {
130 const auto nComp = cellDataComponents_[l++];
131 for (int k = 0; k < nComp; ++k)
132 std::swap(cellData_[key][k + nComp*gridFactory.insertionIndex(element)], data_[idSet_.id(element)][n++]);
133 }
134
135 assert(n == numCellDataPerElement_);
136 }
137
138 for (const auto& vertex : vertices(gridView_))
139 {
140 data_[idSet_.id(vertex)].resize(numPointDataPerVertex_);
141
142 int n = 0, l = 0;
143 for (const auto& [key, data] : pointData_)
144 {
145 const auto nComp = pointDataComponents_[l++];
146 for (int k = 0; k < nComp; ++k)
147 std::swap(pointData_[key][k + nComp*gridFactory.insertionIndex(vertex)], data_[idSet_.id(vertex)][n++]);
148 }
149
150 assert(n == numPointDataPerVertex_);
151 }
152 }
153
155 {
156 // resize arrays and unpack communicated data
157 const auto& indexSet = gridView_.indexSet();
158
159 {
160 int n = 0;
161 for (const auto& [key, data] : cellData_)
162 cellData_[key].resize(indexSet.size(0)*cellDataComponents_[n++]);
163 }
164 {
165 int n = 0;
166 for (const auto& [key, data] : pointData_)
167 pointData_[key].resize(indexSet.size(GridView::dimension)*pointDataComponents_[n++]);
168 }
169
170 for (const auto& element : elements(gridView_))
171 {
172 int n = 0, l = 0;
173 for (const auto& [key, data] : cellData_)
174 {
175 const auto nComp = cellDataComponents_[l++];
176 for (int k = 0; k < nComp; ++k)
177 std::swap(cellData_[key][k + nComp*indexSet.index(element)], data_[idSet_.id(element)][n++]);
178 }
179 }
180
181 for (const auto& vertex : vertices(gridView_))
182 {
183 int n = 0, l = 0;
184 for (const auto& [key, data] : pointData_)
185 {
186 const auto nComp = pointDataComponents_[l++];
187 for (int k = 0; k < nComp; ++k)
188 std::swap(pointData_[key][k + nComp*indexSet.index(vertex)], data_[idSet_.id(vertex)][n++]);
189 }
190 }
191
192 // move data back from sorted internal storage to user data
193 for (const auto& [key, data] : cellData_)
194 userCellData_[key] = std::move(cellData_[key]);
195 for (const auto& [key, data] : pointData_)
196 userPointData_[key] = std::move(pointData_[key]);
197 }
198
199 Dune::CommDataHandleIF<VtkGridDataHandle<Grid, GridFactory, Data>, typename Data::value_type>& interface()
200 { return *this; }
201
202 bool contains (int dim, int codim) const
203 { return codim == 0 || codim == dim; }
204
206 bool fixedSize(int dim, int codim) const
207 { return true; }
208
209 template<class Entity>
210 std::size_t size (const Entity&) const
211 {
212 if constexpr (Entity::codimension == 0)
213 return numCellDataPerElement_;
214 else if constexpr (Entity::codimension == GridView::dimension)
215 return numPointDataPerVertex_;
216 else
217 return 0;
218 }
219
220 template<class MessageBufferImp, class Entity>
221 void gather (MessageBufferImp& buff, const Entity& e) const
222 {
223 if constexpr (Entity::codimension == 0)
224 {
225 const auto& data = data_[idSet_.id(e)];
226 for (int n = 0; n < numCellDataPerElement_; ++n)
227 buff.write(data[n]);
228 }
229
230 if constexpr (Entity::codimension == GridView::dimension)
231 {
232 const auto& data = data_[idSet_.id(e)];
233 for (int n = 0; n < numPointDataPerVertex_; ++n)
234 buff.write(data[n]);
235 }
236 }
237
238 template<class MessageBufferImp, class Entity>
239 void scatter (MessageBufferImp& buff, const Entity& e, std::size_t n)
240 {
241 auto& data = data_[idSet_.id(e)];
242 data.resize(n);
243
244 if constexpr (Entity::codimension == 0)
245 for (int k = 0; k < numCellDataPerElement_; ++k)
246 buff.read(data[k]);
247
248 if constexpr (Entity::codimension == GridView::dimension)
249 for (int k = 0; k < numPointDataPerVertex_; ++k)
250 buff.read(data[k]);
251 }
252
253private:
254 using IdSet = typename Grid::LocalIdSet;
255
256 const GridView gridView_;
257 const IdSet &idSet_;
258
259 VTKReader::Data& userCellData_;
260 VTKReader::Data& userPointData_;
261
262 std::map<std::string, VTKReader::Data::mapped_type> cellData_;
263 std::map<std::string, VTKReader::Data::mapped_type> pointData_;
264
265 std::vector<std::size_t> cellDataComponents_;
266 std::vector<std::size_t> pointDataComponents_;
267
268 std::size_t numCellDataPerElement_;
269 std::size_t numPointDataPerVertex_;
270
271 mutable std::map< typename IdSet::IdType, std::vector<typename Data::value_type> > data_;
272};
273
274} // namespace Dumux
275
276#endif
std::unordered_map< std::string, std::vector< double > > Data
the cell / point data type for point data read from a grid file
Definition: vtkreader.hh:277
Definition: adapt.hh:17
A data handle for communicating grid data for VTK grids.
Definition: vtkgriddatahandle.hh:36
void scatter(MessageBufferImp &buff, const Entity &e, std::size_t n)
Definition: vtkgriddatahandle.hh:239
void gather(MessageBufferImp &buff, const Entity &e) const
Definition: vtkgriddatahandle.hh:221
bool contains(int dim, int codim) const
Definition: vtkgriddatahandle.hh:202
bool fixedSize(int dim, int codim) const
returns true if size per entity of given dim and codim is a constant
Definition: vtkgriddatahandle.hh:206
~VtkGridDataHandle()
Definition: vtkgriddatahandle.hh:154
Dune::CommDataHandleIF< VtkGridDataHandle< Grid, GridFactory, Data >, typename Data::value_type > & interface()
Definition: vtkgriddatahandle.hh:199
std::size_t size(const Entity &) const
Definition: vtkgriddatahandle.hh:210
VtkGridDataHandle(const Grid &grid, const GridFactory &gridFactory, VTKReader::Data &cellData, VTKReader::Data &pointData)
Definition: vtkgriddatahandle.hh:39
typename Grid::LevelGridView GridView
Definition: vtkgriddatahandle.hh:37
A vtk file reader using tinyxml2 as xml backend.