OGS
transformData.cpp
Go to the documentation of this file.
1
10#include "transformData.h"
11
12#include <algorithm>
13#include <array>
14#include <optional>
15#include <range/v3/action/push_back.hpp>
16#include <range/v3/view/transform.hpp>
17#include <string>
18
19#include "BaseLib/cpp23.h"
20#include "InfoLib/GitInfo.h"
22#include "MeshLib/Mesh.h"
23#include "MeshLib/MeshEnums.h"
24#include "MeshLib/Node.h"
26#include "partition.h"
27
28using namespace BaseLib;
29namespace MeshLib::IO
30{
32{
33 // https://xdmf.org/index.php/XDMF_Model_and_Format#Topology, Section
34 // Arbitrary
36 unsigned int number_of_nodes;
37};
38
39static constexpr auto elemOGSTypeToXDMFType()
40{
42 elem_type{};
70 ParentDataType::WEDGE, 6}; // parallel triangle wedge
79 return elem_type;
80}
81
83
84constexpr auto cellTypeOGS2XDMF(MeshLib::CellType const& cell_type)
85{
86 return elem_type_ogs2xdmf[to_underlying(cell_type)];
87}
88
89std::optional<XdmfHdfData> transformAttribute(
90 std::pair<std::string, PropertyVectorBase*> const& property_pair,
91 unsigned int const n_files, unsigned int const chunk_size_bytes)
92{
93 // 3 data that will be captured and written by lambda f below
95 std::size_t num_of_tuples = 0;
96 void const* data_ptr = 0;
97
98 // lambda f : Collects properties from the PropertyVectorBase. It captures
99 // (and overwrites) data that can only be collected via the typed property.
100 // It has boolean return type to allow kind of pipe using || operator.
101 auto f = [&data_type, &num_of_tuples, &data_ptr,
102 &property_pair](auto basic_type) -> bool
103 {
104 auto const property_base = property_pair.second;
105 auto const typed_property =
106 dynamic_cast<PropertyVector<decltype(basic_type)> const*>(
107 property_base);
108 if (typed_property == nullptr)
109 {
110 return false;
111 }
112 // overwrite captured data
113 num_of_tuples = typed_property->getNumberOfTuples();
114 data_ptr = typed_property->data();
115
116 if constexpr (std::is_same_v<double, decltype(basic_type)>)
117 {
118 // The standard 64-bit IEEE 754 floating-point type
119 // (double-precision) has a 53 bit fractional part (52 bits written,
120 // one implied)
121 static_assert((std::numeric_limits<double>::digits == 53),
122 "Double has 52 bits fractional part");
124 }
125 else if constexpr (std::is_same_v<float, decltype(basic_type)>)
126 {
127 // The standard 32-bit IEEE 754 floating-point type
128 // (single-precision) has a 24 bit fractional part (23 bits written,
129 // one implied)
130 static_assert((std::numeric_limits<float>::digits == 24),
131 "Float has 23 bits fractional part");
133 }
134 else if constexpr (std::is_same_v<int32_t, decltype(basic_type)>)
135 {
136 data_type = MeshPropertyDataType::int32;
137 }
138 else if constexpr (std::is_same_v<uint32_t, decltype(basic_type)>)
139 {
141 }
142 else if constexpr (std::is_same_v<int64_t, decltype(basic_type)>)
143 {
144 data_type = MeshPropertyDataType::int64;
145 }
146 else if constexpr (std::is_same_v<uint64_t, decltype(basic_type)>)
147 {
149 }
150 else if constexpr (std::is_same_v<int8_t, decltype(basic_type)>)
151 {
152 data_type = MeshPropertyDataType::int8;
153 }
154 else if constexpr (std::is_same_v<uint8_t, decltype(basic_type)>)
155 {
156 data_type = MeshPropertyDataType::uint8;
157 }
158 else if constexpr (std::is_same_v<char, decltype(basic_type)>)
159 {
161 }
162 else if constexpr (std::is_same_v<unsigned char, decltype(basic_type)>)
163 {
164 static_assert((std::numeric_limits<unsigned char>::digits == 8),
165 "Unsigned char has 8 bits");
166 data_type = MeshPropertyDataType::uchar;
167 }
168 else if constexpr (std::is_same_v<unsigned long, decltype(basic_type)>)
169 {
170 if (sizeof(unsigned long) == 8 &&
171 std::numeric_limits<unsigned long>::digits == 64)
172 {
174 }
175 else if (sizeof(unsigned long) == 4 &&
176 std::numeric_limits<unsigned long>::digits == 32)
177 {
179 }
180 else
181 {
182 return false;
183 }
184 }
185 else if constexpr (std::is_same_v<std::size_t, decltype(basic_type)>)
186 {
187 if (sizeof(std::size_t) == 8 &&
188 std::numeric_limits<std::size_t>::digits == 64)
189 {
191 }
192 else if (sizeof(std::size_t) == 4 &&
193 std::numeric_limits<std::size_t>::digits == 32)
194 {
196 }
197 else
198 {
199 return false;
200 }
201 }
202 else
203 {
204 return false;
205 }
206 return true;
207 };
208
209 f(double{}) || f(float{}) || f(int{}) || f(long{}) || f(unsigned{}) ||
210 f(long{}) || f(static_cast<unsigned long>(0)) || f(std::size_t{}) ||
211 f(char{}) || f(static_cast<unsigned char>(0));
212
213 if (data_type == MeshPropertyDataType::unknown)
214 {
215 return std::nullopt;
216 }
217
218 auto const& property_base = property_pair.second;
219 auto const& global_components =
220 property_base->getNumberOfGlobalComponents();
221 // TODO (tm) property_pair vector::getNumberOfGlobalComponents should return
222 // unsigned value. Then explicit cast from signed to unsigned int and
223 // assert can be removed here. Implicit cast to long long is fine and
224 // can be kept
225 assert(global_components >= 0);
226 auto const ui_global_components =
227 static_cast<unsigned int>(global_components);
228
229 MeshLib::MeshItemType const mesh_item_type =
230 property_base->getMeshItemType();
231
232 std::string const& name = property_base->getPropertyName();
233
234 HdfData hdf = {data_ptr, num_of_tuples, ui_global_components, name,
235 data_type, n_files, chunk_size_bytes};
236
237 XdmfData xdmf{num_of_tuples, ui_global_components, data_type,
238 name, mesh_item_type, 0,
239 n_files, std::nullopt};
240
241 return XdmfHdfData{std::move(hdf), std::move(xdmf)};
242}
243
244std::vector<XdmfHdfData> transformAttributes(
245 MeshLib::Mesh const& mesh, unsigned int const n_files,
246 unsigned int const chunk_size_bytes)
247{
248 MeshLib::Properties const& properties = mesh.getProperties();
249
250 // \TODO (tm) use c++20 ranges
251 // a = p | filter (first!=OGS_VERSION) | filter null_opt | transformAttr |
252 std::vector<XdmfHdfData> attributes;
253 for (auto const& [name, property_base] : properties)
254 {
256 {
257 continue;
258 }
259
260 if (!property_base->is_for_output)
261 {
262 continue;
263 }
264
265 if (auto const attribute = transformAttribute(
266
267 std::pair(std::string(name), property_base), n_files,
268 chunk_size_bytes))
269
270 {
271 attributes.push_back(attribute.value());
272 }
273 else
274 {
275 WARN("Could not create attribute meta of {:s}.", name);
276 }
277 }
278 return attributes;
279}
280
281std::vector<double> transformToXDMFGeometry(MeshLib::Mesh const& mesh)
282{
283 std::vector<MeshLib::Node*> const& nodes = mesh.getNodes();
284
285 int const point_size = 3;
286 std::vector<double> values;
287 values.reserve(nodes.size() * point_size);
288 for (auto const& n : nodes)
289 {
290 const double* x = n->data();
291 values.insert(values.cend(), x, x + point_size);
292 }
293
294 return values;
295}
296
297XdmfHdfData transformGeometry(MeshLib::Mesh const& mesh, double const* data_ptr,
298 unsigned int const n_files,
299 unsigned int const chunk_size_bytes)
300{
301 std::string const name = "geometry";
302 std::vector<MeshLib::Node*> const& nodes = mesh.getNodes();
303
304 int const point_size = 3;
305 auto const& partition_dim = nodes.size();
306
307 HdfData const hdf = {data_ptr,
308 partition_dim,
309 point_size,
310 name,
312 n_files,
313 chunk_size_bytes};
314 XdmfData const xdmf = {
315 partition_dim, point_size, MeshPropertyDataType::float64,
316 name, std::nullopt, 2,
317 n_files, std::nullopt};
318
319 return XdmfHdfData{std::move(hdf), std::move(xdmf)};
320}
321
323{
324 auto const& elements = mesh.getElements();
325
326 if (elements.empty())
327 {
329 }
330 auto const ogs_cell_type = elements[0]->getCellType();
331
332 if (std::any_of(elements.begin(), elements.end(),
333 [&](auto const& cell)
334 { return cell->getCellType() != ogs_cell_type; }))
335 {
337 }
338
339 return cellTypeOGS2XDMF(ogs_cell_type).id;
340}
341
342std::pair<std::vector<std::size_t>, ParentDataType> transformToXDMFTopology(
343 MeshLib::Mesh const& mesh, std::size_t const offset)
344{
345 std::vector<MeshLib::Element*> const& elements = mesh.getElements();
346 std::vector<std::size_t> values;
347
348 auto const push_cellnode_ids_to_vector =
349 [&values, &offset](auto const& cell)
350 {
351 values |= ranges::actions::push_back(
352 cell->nodes() | MeshLib::views::ids |
353 ranges::views::transform([&offset](auto const node_id)
354 { return node_id + offset; }));
355 };
356
357 auto const topology_type = getTopologyType(mesh);
358 if (topology_type == ParentDataType::MIXED)
359 {
360 values.reserve(elements.size() * 2); // each cell has at least two
361 // numbers
362 for (auto const& cell : elements)
363 {
364 auto const ogs_cell_type = cell->getCellType();
365 auto const xdmf_cell_id = cellTypeOGS2XDMF(ogs_cell_type).id;
366 values.push_back(to_underlying(xdmf_cell_id));
367 push_cellnode_ids_to_vector(cell);
368 }
369 }
370 else if (topology_type == ParentDataType::POLYLINE)
371 {
372 // '+ 1' for number of nodes of the cell
373 values.reserve(elements.size() * elements[0]->getNumberOfNodes());
374 for (auto const& cell : elements)
375 {
376 push_cellnode_ids_to_vector(cell);
377 }
378 }
379 else
380 {
381 values.reserve(elements.size() * elements[0]->getNumberOfNodes());
382 for (auto const& cell : elements)
383 {
384 push_cellnode_ids_to_vector(cell);
385 }
386 }
387
388 return {values, topology_type};
389}
390
391XdmfHdfData transformTopology(std::vector<std::size_t> const& values,
392 ParentDataType const parent_data_type,
393 unsigned int const n_files,
394 unsigned int const chunk_size_bytes)
395{
396 std::string const name = "topology";
397 auto const tuple_size = ParentDataType2String(parent_data_type).second;
398 HdfData const hdf = {values.data(),
399 values.size() / tuple_size,
400 tuple_size,
401 name,
403 n_files,
404 chunk_size_bytes};
405 XdmfData const xdmf{values.size() / tuple_size,
406 tuple_size,
408 name,
409 std::nullopt,
410 3,
411 n_files,
412 parent_data_type};
413
414 return XdmfHdfData{std::move(hdf), std::move(xdmf)};
415}
416} // namespace MeshLib::IO
Definition of the Element class.
Git information.
void WARN(fmt::format_string< Args... > fmt, Args &&... args)
Definition Logging.h:40
Definition of mesh-related Enumerations.
std::pair< std::string, std::size_t > ParentDataType2String(ParentDataType p)
Enum for all propertyVector data types and XDMF ParentDataTypes.
MeshPropertyDataType
Definition of the Mesh class.
Definition of the Node class.
std::vector< Node * > const & getNodes() const
Get the nodes-vector for the mesh.
Definition Mesh.h:106
std::vector< Element * > const & getElements() const
Get the element-vector for the mesh.
Definition Mesh.h:109
Properties & getProperties()
Definition Mesh.h:134
Property manager on mesh items. Class Properties manages scalar, vector or matrix properties....
Definition Properties.h:36
std::size_t getNumberOfTuples() const
constexpr auto to_underlying(E e) noexcept
Converts an enumeration to its underlying type.
Definition cpp23.h:29
const std::string OGS_VERSION
Definition GitInfo.cpp:20
constexpr auto cellTypeOGS2XDMF(MeshLib::CellType const &cell_type)
ParentDataType getTopologyType(MeshLib::Mesh const &mesh)
std::optional< XdmfHdfData > transformAttribute(std::pair< std::string, PropertyVectorBase * > const &property_pair, unsigned int const n_files, unsigned int const chunk_size_bytes)
std::pair< std::vector< std::size_t >, ParentDataType > transformToXDMFTopology(MeshLib::Mesh const &mesh, std::size_t const offset)
Copies all cells into a new vector. Contiguous data used for writing. The topology is specific to xdm...
std::vector< double > transformToXDMFGeometry(MeshLib::Mesh const &mesh)
Copies all node points into a new vector. Contiguous data used for writing. Conform with XDMF standar...
XdmfHdfData transformGeometry(MeshLib::Mesh const &mesh, double const *data_ptr, unsigned int const n_files, unsigned int const chunk_size_bytes)
Create meta data for geometry used for hdf5 and xdmf.
static constexpr auto elemOGSTypeToXDMFType()
std::vector< XdmfHdfData > transformAttributes(MeshLib::Mesh const &mesh, unsigned int const n_files, unsigned int const chunk_size_bytes)
Create meta data for attributes used for hdf5 and xdmf.
XdmfHdfData transformTopology(std::vector< std::size_t > const &values, ParentDataType const parent_data_type, unsigned int const n_files, unsigned int const chunk_size_bytes)
Create meta data for topology used for HDF5 and XDMF.
constexpr auto elem_type_ogs2xdmf
constexpr ranges::views::view_closure ids
For an element of a range view return its id.
Definition Mesh.h:225
CellType
Types of mesh elements supported by OpenGeoSys.
Definition MeshEnums.h:43
MeshItemType
Definition Location.h:21
Dispatches functions specific to execution platform (w/o MPI)
Transforms OGS Mesh into vectorized data.