OGS
transformData.cpp
Go to the documentation of this file.
1
10// \TODO (tm) Extend xdmf lib with 64bit data types
11
12#include "transformData.h"
13
14#include <algorithm>
15#include <array>
16#include <optional>
17#include <range/v3/action/push_back.hpp>
18#include <range/v3/view/transform.hpp>
19#include <string>
20
21#include "BaseLib/cpp23.h"
22#include "InfoLib/GitInfo.h"
24#include "MeshLib/Mesh.h"
25#include "MeshLib/MeshEnums.h"
26#include "MeshLib/Node.h"
28#include "partition.h"
29
30using namespace BaseLib;
31namespace MeshLib::IO
32{
34{
35 // https://xdmf.org/index.php/XDMF_Model_and_Format#Topology, Section
36 // Arbitrary
38 unsigned int number_of_nodes;
39};
40
41static constexpr auto elemOGSTypeToXDMFType()
42{
44 elem_type{};
72 ParentDataType::WEDGE, 6}; // parallel triangle wedge
81 return elem_type;
82}
83
85
86constexpr auto cellTypeOGS2XDMF(MeshLib::CellType const& cell_type)
87{
88 return elem_type_ogs2xdmf[to_underlying(cell_type)];
89}
90
91std::optional<XdmfHdfData> transformAttribute(
92 std::pair<std::string, PropertyVectorBase*> const& property_pair,
93 unsigned int const n_files, unsigned int const chunk_size_bytes)
94{
95 // 3 data that will be captured and written by lambda f below
97 std::size_t num_of_tuples = 0;
98 void const* data_ptr = 0;
99
100 // lambda f : Collects properties from the propertyVectorBase. It captures
101 // (and overwrites) data that can only be collected via the typed property.
102 // It has boolean return type to allow kind of pipe using || operator.
103 auto f = [&data_type, &num_of_tuples, &data_ptr,
104 &property_pair](auto basic_type) -> bool
105 {
106 auto const property_base = property_pair.second;
107 auto const typed_property =
108 dynamic_cast<PropertyVector<decltype(basic_type)> const*>(
109 property_base);
110 if (typed_property == nullptr)
111 {
112 return false;
113 }
114 // overwrite captured data
115 num_of_tuples = typed_property->getNumberOfTuples();
116 data_ptr = typed_property->data();
117
118 if constexpr (std::is_same_v<double, decltype(basic_type)>)
119 {
120 // The standard 64-bit IEEE 754 floating-point type
121 // (double-precision) has a 53 bit fractional part (52 bits written,
122 // one implied)
123 static_assert((std::numeric_limits<double>::digits == 53),
124 "Double has 52 bits fractional part");
126 }
127 else if constexpr (std::is_same_v<float, decltype(basic_type)>)
128 {
129 // The standard 32-bit IEEE 754 floating-point type
130 // (single-precision) has a 24 bit fractional part (23 bits written,
131 // one implied)
132 static_assert((std::numeric_limits<float>::digits == 24),
133 "Float has 23 bits fractional part");
135 }
136 else if constexpr (std::is_same_v<int, decltype(basic_type)>)
137 {
138 static_assert((std::numeric_limits<int>::digits == 31),
139 "Signed int has 32-1 bits");
140 data_type = MeshPropertyDataType::int32;
141 }
142 // ToDo (tm) These tests are platform specific and currently fail on
143 // Windows else if constexpr (std::is_same_v<long,
144 // decltype(basic_type)>)
145 //{
146 // static_assert((std::numeric_limits<long>::digits == 63),
147 // "Signed int has 64-1 bits");
148 // data_type = MeshPropertyDataType::int64;
149 //}
150 // else if constexpr (std::is_same_v<unsigned long,
151 // decltype(basic_type)>)
152 //{
153 // static_assert((std::numeric_limits<unsigned long>::digits == 64),
154 // "Unsigned long has 64 bits");
155 // data_type = MeshPropertyDataType::uint64;
156 //}
157 else if constexpr (std::is_same_v<unsigned int, decltype(basic_type)>)
158 {
159 static_assert((std::numeric_limits<unsigned int>::digits == 32),
160 "Unsigned int has 32 bits");
162 }
163 else if constexpr (std::is_same_v<std::size_t, decltype(basic_type)>)
164 {
165 static_assert((std::numeric_limits<std::size_t>::digits == 64),
166 "size_t has 64 bits");
168 }
169 else if constexpr (std::is_same_v<char, decltype(basic_type)>)
170 {
172 }
173 else if constexpr (std::is_same_v<unsigned char, decltype(basic_type)>)
174 {
175 static_assert((std::numeric_limits<unsigned char>::digits == 8),
176 "Unsigned char has 8 bits");
177 data_type = MeshPropertyDataType::uchar;
178 }
179 else
180 {
181 return false;
182 }
183 return true;
184 };
185
186 f(double{}) || f(float{}) || f(int{}) || f(long{}) || f(unsigned{}) ||
187 f(long{}) || f(static_cast<unsigned long>(0)) || f(std::size_t{}) ||
188 f(char{}) || f(static_cast<unsigned char>(0));
189
190 if (data_type == MeshPropertyDataType::unknown)
191 {
192 return std::nullopt;
193 }
194
195 auto const& property_base = property_pair.second;
196 auto const& global_components =
197 property_base->getNumberOfGlobalComponents();
198 // TODO (tm) property_pair vector::getNumberOfGlobalComponents should return
199 // unsigned value. Then explicit cast from signed to unsigned int and
200 // assert can be removed here. Implicit cast to long long is fine and
201 // can be kept
202 assert(global_components >= 0);
203 auto const ui_global_components =
204 static_cast<unsigned int>(global_components);
205
206 MeshLib::MeshItemType const mesh_item_type =
207 property_base->getMeshItemType();
208
209 std::string const& name = property_base->getPropertyName();
210
211 HdfData hdf = {data_ptr, num_of_tuples, ui_global_components, name,
212 data_type, n_files, chunk_size_bytes};
213
214 XdmfData xdmf{num_of_tuples, ui_global_components, data_type,
215 name, mesh_item_type, 0,
216 n_files, std::nullopt};
217
218 return XdmfHdfData{std::move(hdf), std::move(xdmf)};
219}
220
221std::vector<XdmfHdfData> transformAttributes(
222 MeshLib::Mesh const& mesh, unsigned int const n_files,
223 unsigned int const chunk_size_bytes)
224{
225 MeshLib::Properties const& properties = mesh.getProperties();
226
227 // \TODO (tm) use c++20 ranges
228 // a = p | filter (first!=OGS_VERSION) | filter null_opt | transformAttr |
229 std::vector<XdmfHdfData> attributes;
230 for (auto const& [name, property_base] : properties)
231 {
233 {
234 continue;
235 }
236
237 if (!property_base->is_for_output)
238 {
239 continue;
240 }
241
242 if (auto const attribute = transformAttribute(
243
244 std::pair(std::string(name), property_base), n_files,
245 chunk_size_bytes))
246
247 {
248 attributes.push_back(attribute.value());
249 }
250 else
251 {
252 WARN("Could not create attribute meta of {:s}.", name);
253 }
254 }
255 return attributes;
256}
257
258std::vector<double> transformToXDMFGeometry(MeshLib::Mesh const& mesh)
259{
260 std::vector<MeshLib::Node*> const& nodes = mesh.getNodes();
261
262 int const point_size = 3;
263 std::vector<double> values;
264 values.reserve(nodes.size() * point_size);
265 for (auto const& n : nodes)
266 {
267 const double* x = n->data();
268 values.insert(values.cend(), x, x + point_size);
269 }
270
271 return values;
272}
273
274XdmfHdfData transformGeometry(MeshLib::Mesh const& mesh, double const* data_ptr,
275 unsigned int const n_files,
276 unsigned int const chunk_size_bytes)
277{
278 std::string const name = "geometry";
279 std::vector<MeshLib::Node*> const& nodes = mesh.getNodes();
280
281 int const point_size = 3;
282 auto const& partition_dim = nodes.size();
283
284 HdfData const hdf = {data_ptr,
285 partition_dim,
286 point_size,
287 name,
289 n_files,
290 chunk_size_bytes};
291 XdmfData const xdmf = {
292 partition_dim, point_size, MeshPropertyDataType::float64,
293 name, std::nullopt, 2,
294 n_files, std::nullopt};
295
296 return XdmfHdfData{std::move(hdf), std::move(xdmf)};
297}
298
300{
301 auto const& elements = mesh.getElements();
302
303 if (elements.empty())
304 {
306 }
307 auto const ogs_cell_type = elements[0]->getCellType();
308
309 if (std::any_of(elements.begin(), elements.end(),
310 [&](auto const& cell)
311 { return cell->getCellType() != ogs_cell_type; }))
312 {
314 }
315
316 return cellTypeOGS2XDMF(ogs_cell_type).id;
317}
318
319std::pair<std::vector<int>, ParentDataType> transformToXDMFTopology(
320 MeshLib::Mesh const& mesh, std::size_t const offset)
321{
322 std::vector<MeshLib::Element*> const& elements = mesh.getElements();
323 std::vector<int> values;
324
325 auto const push_cellnode_ids_to_vector =
326 [&values, &offset](auto const& cell)
327 {
328 values |= ranges::actions::push_back(
329 cell->nodes() | MeshLib::views::ids |
330 ranges::views::transform([&offset](auto const node_id) -> int
331 { return node_id + offset; }));
332 };
333
334 auto const topology_type = getTopologyType(mesh);
335 if (topology_type == ParentDataType::MIXED)
336 {
337 values.reserve(elements.size() * 2); // each cell has at least two
338 // numbers
339 for (auto const& cell : elements)
340 {
341 auto const ogs_cell_type = cell->getCellType();
342 auto const xdmf_cell_id = cellTypeOGS2XDMF(ogs_cell_type).id;
343 values.push_back(to_underlying(xdmf_cell_id));
344 push_cellnode_ids_to_vector(cell);
345 }
346 }
347 else if (topology_type == ParentDataType::POLYVERTEX ||
348 topology_type == ParentDataType::POLYLINE)
349 {
350 // '+ 1' for number of nodes of the cell
351 values.reserve(elements.size() * (elements[0]->getNumberOfNodes() + 1));
352 for (auto const& cell : elements)
353 {
354 values.push_back(cell->getNumberOfNodes());
355 push_cellnode_ids_to_vector(cell);
356 }
357 }
358 else
359 {
360 values.reserve(elements.size() * elements[0]->getNumberOfNodes());
361 for (auto const& cell : elements)
362 {
363 push_cellnode_ids_to_vector(cell);
364 }
365 }
366
367 return {values, topology_type};
368}
369
370XdmfHdfData transformTopology(std::vector<int> const& values,
371 ParentDataType const parent_data_type,
372 unsigned int const n_files,
373 unsigned int const chunk_size_bytes)
374{
375 std::string const name = "topology";
376 HdfData const hdf = {
377 values.data(), values.size(), 1, name, MeshPropertyDataType::int32,
378 n_files, chunk_size_bytes};
379 XdmfData const xdmf{values.size(),
380 1,
382 name,
383 std::nullopt,
384 3,
385 n_files,
386 parent_data_type};
387
388 return XdmfHdfData{std::move(hdf), std::move(xdmf)};
389}
390} // 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.
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
XdmfHdfData transformTopology(std::vector< int > 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.
std::pair< std::vector< int >, 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...
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::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.
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.