PropsDataHandle.hpp
Go to the documentation of this file.
1/*
2 Copyright 2020, 2023 Equinor AS.
3 Copyright 2026 SINTEF Digital
4
5 This file is part of the Open Porous Media project (OPM).
6
7 OPM is free software: you can redistribute it and/or modify
8 it under the terms of the GNU General Public License as published by
9 the Free Software Foundation, either version 3 of the License, or
10 (at your option) any later version.
11
12 OPM is distributed in the hope that it will be useful,
13 but WITHOUT ANY WARRANTY; without even the implied warranty of
14 MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
15 GNU General Public License for more details.
16
17 You should have received a copy of the GNU General Public License
18 along with OPM. If not, see <http://www.gnu.org/licenses/>.
19*/
27#ifndef PROPS_DATAHANDLE_HPP
28#define PROPS_DATAHANDLE_HPP
29
30#if HAVE_MPI
31
32#include <opm/input/eclipse/EclipseState/Grid/FieldData.hpp>
33
37#include <dune/grid/common/datahandleif.hh>
38#include <dune/grid/common/mcmgmapper.hh>
39#include <dune/grid/common/partitionset.hh>
40#include <dune/common/parallel/mpihelper.hh>
41#include <algorithm>
42#include <numeric>
43#include <stdexcept>
44#include <unordered_map>
45#include <iostream>
46
47namespace Opm
48{
49
55template<class Grid>
57 : public Dune::CommDataHandleIF< PropsDataHandle<Grid>, double>
58{
59public:
61 using DataType = std::pair<double, unsigned char>;
62
67 PropsDataHandle(const Grid& grid, ParallelEclipseState& eclState)
68 : m_grid(grid),
69 m_distributed_fieldProps(eclState.m_fieldProps)
70 {
71 // Scatter the keys
72 const Parallel::Communication comm = m_grid.comm();
73 if (comm.rank() == 0)
74 {
75 const FieldPropsManager& globalProps = eclState.globalFieldProps();
76 m_intKeys = globalProps.keys<int>();
77 m_doubleKeys = globalProps.keys<double>();
78 m_distributed_fieldProps.copyTran(globalProps);
79
80 // Multi-valued fields such as ZMF use component-major storage:
81 // the cell index varies fastest.
82 m_doubleMult.reserve(m_doubleKeys.size());
83 for (const auto& doubleKey : m_doubleKeys)
84 {
85 const auto& fieldData = globalProps.get_double_field_data(doubleKey,
86 /* allow_unsupported = */ true);
87 m_doubleMult.push_back(fieldData.numValuePerCell());
88 }
89 }
90
92 ser.broadcast(Parallel::RootRank{0}, *this);
93
94 int hasMultiValuedIntField = 0;
95 if (comm.rank() == 0) {
96 const auto& globalProps = eclState.globalFieldProps();
97 hasMultiValuedIntField = std::any_of(
98 m_intKeys.begin(), m_intKeys.end(),
99 [&globalProps](const std::string& key) {
100 return globalProps.get_int_field_data(key).numValuePerCell() > 1;
101 });
102 }
103 comm.broadcast(&hasMultiValuedIntField, 1, 0);
104 if (hasMultiValuedIntField) {
105 throw std::runtime_error {
106 "Distributing multi-valued integer field properties is not supported"
107 };
108 }
109
110 int hasLgr = (comm.rank() == 0) && (eclState.getLgrs().size() > 0);
111 comm.broadcast(&hasLgr, 1, 0);
112 const bool hasMultiValuedField =
113 std::any_of(m_doubleMult.begin(), m_doubleMult.end(),
114 [](const std::size_t multiplicity) { return multiplicity > 1; });
115 if (hasLgr && hasMultiValuedField) {
116 throw std::runtime_error {
117 "Distributing multi-valued field properties with LGRs is not supported"
118 };
119 }
120
121 m_no_data = m_intKeys.size() +
122 std::accumulate(m_doubleMult.begin(), m_doubleMult.end(), std::size_t{0});
123
124 if (comm.rank() == 0) {
125 const FieldPropsManager& globalProps = eclState.globalFieldProps();
126 const auto& idSet = m_grid.localIdSet();
127 const auto& gridView = m_grid.levelGridView(0);
128 using ElementMapper =
129 Dune::MultipleCodimMultipleGeomTypeMapper<typename Grid::LevelGridView>;
130 ElementMapper elemMapper(gridView, Dune::mcmgElementLayout());
131 const std::size_t numCells = gridView.size(0);
132
133 for (const auto &element : elements(gridView, Dune::Partitions::interiorBorder))
134 {
135 const auto& id = idSet.id(element);
136 auto index = elemMapper.index(element);
137 auto& data = elementData_[id];
138 data.reserve(m_no_data);
139
140 for (const auto& intKey : m_intKeys)
141 {
142 const auto& fieldData = globalProps.get_int_field_data(intKey);
143 data.emplace_back(fieldData.data[index],
144 static_cast<unsigned char>(fieldData.value_status[index]));
145 }
146
147 for (std::size_t keyIdx = 0; keyIdx < m_doubleKeys.size(); ++keyIdx)
148 {
149 // We need to allow unsupported keywords to get the data
150 // for TranCalculator, too.
151 const auto& fieldData = globalProps.get_double_field_data(m_doubleKeys[keyIdx],
152 /* allow_unsupported = */ true);
153 for (std::size_t comp = 0; comp < m_doubleMult[keyIdx]; ++comp)
154 {
155 const auto dataIdx = comp * numCells + index;
156 data.emplace_back(fieldData.data[dataIdx],
157 static_cast<unsigned char>(fieldData.value_status[dataIdx]));
158 }
159 }
160 }
161 }
162 }
163
165 {
166 // distributed grid is now correctly set up.
167 const auto& gridView = m_grid.levelGridView(0);
168 const std::size_t numCells = gridView.size(0);
169 for (const auto& intKey : m_intKeys)
170 {
171 m_distributed_fieldProps.m_intProps[intKey].data.resize(numCells);
172 m_distributed_fieldProps.m_intProps[intKey].value_status.resize(numCells);
173 }
174
175 for (std::size_t keyIdx = 0; keyIdx < m_doubleKeys.size(); ++keyIdx)
176 {
177 auto& props = m_distributed_fieldProps.m_doubleProps[m_doubleKeys[keyIdx]];
178 props.data.resize(m_doubleMult[keyIdx] * numCells);
179 props.value_status.resize(m_doubleMult[keyIdx] * numCells);
180 // Preserve the number of values per cell for numCells() and compress().
181 props.kw_info.num_value_per_cell(m_doubleMult[keyIdx]);
182 }
183
184 // copy data for the persistent mao to the field properties
185 const auto& idSet = m_grid.localIdSet();
186 using ElementMapper =
187 Dune::MultipleCodimMultipleGeomTypeMapper<typename Grid::LevelGridView>;
188 ElementMapper elemMapper(gridView, Dune::mcmgElementLayout());
189
190 for (const auto &element : elements( gridView, Dune::Partitions::all))
191 {
192 std::size_t counter{};
193 const auto& id = idSet.id(element);
194 auto index = elemMapper.index(element);
195 auto data = elementData_.find(id);
196 assert(data != elementData_.end());
197
198 for (const auto& intKey : m_intKeys)
199 {
200 const auto& pair = data->second[counter++];
201 m_distributed_fieldProps.m_intProps[intKey].data[index] = static_cast<int>(pair.first);
202 m_distributed_fieldProps.m_intProps[intKey].value_status[index] = static_cast<value::status>(pair.second);
203 }
204
205 for (std::size_t keyIdx = 0; keyIdx < m_doubleKeys.size(); ++keyIdx)
206 {
207 auto& props = m_distributed_fieldProps.m_doubleProps[m_doubleKeys[keyIdx]];
208 for (std::size_t comp = 0; comp < m_doubleMult[keyIdx]; ++comp)
209 {
210 const auto& pair = data->second[counter++];
211 props.data[comp * numCells + index] = pair.first;
212 props.value_status[comp * numCells + index] = static_cast<value::status>(pair.second);
213 }
214 }
215 }
216 }
217
218 bool contains(int /* dim */, int codim)
219 {
220 return codim == 0;
221 }
222
223 bool fixedsize(int /* dim */, int /* codim */)
224 {
225 return true;
226 }
227 bool fixedSize(int /* dim */, int /* codim */)
228 {
229 return true;
230 }
231
232 template<class EntityType>
233 std::size_t size(const EntityType /* entity */)
234 {
235 return m_no_data;
236 }
237
238 template<class BufferType, class EntityType>
239 void gather(BufferType& buffer, const EntityType& e) const
240 {
241 auto iter = elementData_.find(m_grid.localIdSet().id(e));
242 assert(iter != elementData_.end());
243 for (const auto& data : iter->second)
244 {
245 buffer.write(data);
246 }
247 }
248
249 template<class BufferType, class EntityType>
250 void scatter(BufferType& buffer, const EntityType& e, std::size_t n)
251 {
252 assert(n == m_no_data);
253 auto& array = elementData_[m_grid.localIdSet().id(e)];
254 array.resize(n);
255 for (auto& data : array)
256 {
257 buffer.read(data);
258 }
259 }
260
261 template<class Serializer>
262 void serializeOp(Serializer& serializer)
263 {
264 serializer(m_intKeys);
265 serializer(m_doubleKeys);
266 serializer(m_doubleMult);
267 m_distributed_fieldProps.serializeOp(serializer);
268 }
269
270private:
271 using LocalIdSet = typename Grid::LocalIdSet;
272 const Grid& m_grid;
274 ParallelFieldPropsManager& m_distributed_fieldProps;
276 std::vector<std::string> m_intKeys;
278 std::vector<std::string> m_doubleKeys;
280 std::vector<std::size_t> m_doubleMult;
284 std::unordered_map<typename LocalIdSet::IdType, std::vector<std::pair<double,unsigned char> > > elementData_;
286 std::size_t m_no_data;
287};
288
289} // end namespace Opm
290
291#endif // HAVE_MPI
292#endif // PROPS_DATAHANDLE_HPP
Class for serializing and broadcasting data using MPI.
Definition: MPISerializer.hpp:38
void broadcast(RootRank rootrank, Args &&... args)
Definition: MPISerializer.hpp:47
Parallel frontend to the EclipseState.
Definition: ParallelEclipseState.hpp:153
const FieldPropsManager & globalFieldProps() const override
Returns a const ref to global field properties.
Parallel frontend to the field properties.
Definition: ParallelEclipseState.hpp:42
std::map< std::string, Fieldprops::FieldData< int > > m_intProps
Map of integer properties in process-local compressed indices.
Definition: ParallelEclipseState.hpp:132
void serializeOp(Serializer &serializer)
Definition: ParallelEclipseState.hpp:126
void copyTran(const FieldPropsManager &from)
Definition: ParallelEclipseState.hpp:120
std::map< std::string, Fieldprops::FieldData< double > > m_doubleProps
Map of double properties in process-local compressed indices.
Definition: ParallelEclipseState.hpp:133
A Data handle to communicate the field properties during load balance.
Definition: PropsDataHandle.hpp:58
PropsDataHandle(const Grid &grid, ParallelEclipseState &eclState)
Constructor.
Definition: PropsDataHandle.hpp:67
std::size_t size(const EntityType)
Definition: PropsDataHandle.hpp:233
std::pair< double, unsigned char > DataType
the data type we send (ints are converted to double)
Definition: PropsDataHandle.hpp:61
void serializeOp(Serializer &serializer)
Definition: PropsDataHandle.hpp:262
bool fixedSize(int, int)
Definition: PropsDataHandle.hpp:227
bool fixedsize(int, int)
Definition: PropsDataHandle.hpp:223
bool contains(int, int codim)
Definition: PropsDataHandle.hpp:218
~PropsDataHandle()
Definition: PropsDataHandle.hpp:164
void gather(BufferType &buffer, const EntityType &e) const
Definition: PropsDataHandle.hpp:239
void scatter(BufferType &buffer, const EntityType &e, std::size_t n)
Definition: PropsDataHandle.hpp:250
Dune::Communication< MPIComm > Communication
Definition: ParallelCommunication.hpp:30
Definition: blackoilbioeffectsmodules.hh:45
Avoid mistakes in calls to broadcast() by wrapping the root argument in an explicit type.
Definition: MPISerializer.hpp:33