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 <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
35 unsigned int id;
36 unsigned int number_of_nodes;
37};
38
39static constexpr auto elemOGSTypeToXDMFType()
40{
42 elem_type{};
43 elem_type[to_underlying(MeshLib::CellType::POINT1)] = {0x1, 1};
44 elem_type[to_underlying(MeshLib::CellType::LINE2)] = {0x2, 2};
45 elem_type[to_underlying(MeshLib::CellType::LINE3)] = {0x2, 3};
46 elem_type[to_underlying(MeshLib::CellType::TRI3)] = {0x4, 3};
47 elem_type[to_underlying(MeshLib::CellType::TRI6)] = {0x24, 6};
48 elem_type[to_underlying(MeshLib::CellType::QUAD4)] = {0x5, 4};
49 elem_type[to_underlying(MeshLib::CellType::QUAD8)] = {0x25, 8};
50 elem_type[to_underlying(MeshLib::CellType::QUAD9)] = {0x23, 9};
51 elem_type[to_underlying(MeshLib::CellType::TET4)] = {0x6, 4};
52 elem_type[to_underlying(MeshLib::CellType::TET10)] = {0x26, 10};
53 elem_type[to_underlying(MeshLib::CellType::HEX8)] = {0x9, 8};
54 elem_type[to_underlying(MeshLib::CellType::HEX20)] = {0x30, 20};
55 elem_type[to_underlying(MeshLib::CellType::HEX27)] = {0x32, 27};
57 0x8, 6}; // parallel triangle wedge
58 elem_type[to_underlying(MeshLib::CellType::PRISM15)] = {0x28, 15};
59 elem_type[to_underlying(MeshLib::CellType::PRISM18)] = {0x29, 18};
60 elem_type[to_underlying(MeshLib::CellType::PYRAMID5)] = {0x7, 5};
61 elem_type[to_underlying(MeshLib::CellType::PYRAMID13)] = {0x27, 13};
62 return elem_type;
63}
64
66
67constexpr auto cellTypeOGS2XDMF(MeshLib::CellType const& cell_type)
68{
69 return elem_type_ogs2xdmf[to_underlying(cell_type)];
70}
71
72std::optional<XdmfHdfData> transformAttribute(
73 std::pair<std::string, PropertyVectorBase*> const& property_pair,
74 unsigned int const n_files, unsigned int const chunk_size_bytes)
75{
76 // 3 data that will be captured and written by lambda f below
78 std::size_t num_of_tuples = 0;
79 void const* data_ptr = 0;
80
81 // lambda f : Collects properties from the propertyVectorBase. It captures
82 // (and overwrites) data that can only be collected via the typed property.
83 // It has boolean return type to allow kind of pipe using || operator.
84 auto f = [&data_type, &num_of_tuples, &data_ptr,
85 &property_pair](auto basic_type) -> bool
86 {
87 auto const property_base = property_pair.second;
88 auto const typed_property =
89 dynamic_cast<PropertyVector<decltype(basic_type)> const*>(
90 property_base);
91 if (typed_property == nullptr)
92 {
93 return false;
94 }
95 // overwrite captured data
96 num_of_tuples = typed_property->getNumberOfTuples();
97 data_ptr = typed_property->data();
98
99 if constexpr (std::is_same_v<double, decltype(basic_type)>)
100 {
101 // The standard 64-bit IEEE 754 floating-point type
102 // (double-precision) has a 53 bit fractional part (52 bits written,
103 // one implied)
104 static_assert((std::numeric_limits<double>::digits == 53),
105 "Double has 52 bits fractional part");
107 }
108 else if constexpr (std::is_same_v<float, decltype(basic_type)>)
109 {
110 // The standard 32-bit IEEE 754 floating-point type
111 // (single-precision) has a 24 bit fractional part (23 bits written,
112 // one implied)
113 static_assert((std::numeric_limits<float>::digits == 24),
114 "Float has 23 bits fractional part");
116 }
117 else if constexpr (std::is_same_v<int, decltype(basic_type)>)
118 {
119 static_assert((std::numeric_limits<int>::digits == 31),
120 "Signed int has 32-1 bits");
121 data_type = MeshPropertyDataType::int32;
122 }
123 // ToDo (tm) These tests are platform specific and currently fail on
124 // Windows else if constexpr (std::is_same_v<long,
125 // decltype(basic_type)>)
126 //{
127 // static_assert((std::numeric_limits<long>::digits == 63),
128 // "Signed int has 64-1 bits");
129 // data_type = MeshPropertyDataType::int64;
130 //}
131 // else if constexpr (std::is_same_v<unsigned long,
132 // decltype(basic_type)>)
133 //{
134 // static_assert((std::numeric_limits<unsigned long>::digits == 64),
135 // "Unsigned long has 64 bits");
136 // data_type = MeshPropertyDataType::uint64;
137 //}
138 else if constexpr (std::is_same_v<unsigned int, decltype(basic_type)>)
139 {
140 static_assert((std::numeric_limits<unsigned int>::digits == 32),
141 "Unsigned int has 32 bits");
143 }
144 else if constexpr (std::is_same_v<std::size_t, decltype(basic_type)>)
145 {
146 static_assert((std::numeric_limits<std::size_t>::digits == 64),
147 "size_t has 64 bits");
149 }
150 else if constexpr (std::is_same_v<char, decltype(basic_type)>)
151 {
153 }
154 else if constexpr (std::is_same_v<unsigned char, decltype(basic_type)>)
155 {
156 static_assert((std::numeric_limits<unsigned char>::digits == 8),
157 "Unsigned char has 8 bits");
158 data_type = MeshPropertyDataType::uchar;
159 }
160 else
161 {
162 return false;
163 }
164 return true;
165 };
166
167 f(double{}) || f(float{}) || f(int{}) || f(long{}) || f(unsigned{}) ||
168 f(long{}) || f(static_cast<unsigned long>(0)) || f(std::size_t{}) ||
169 f(char{}) || f(static_cast<unsigned char>(0));
170
171 if (data_type == MeshPropertyDataType::unknown)
172 {
173 return std::nullopt;
174 }
175
176 auto const& property_base = property_pair.second;
177 auto const& global_components =
178 property_base->getNumberOfGlobalComponents();
179 // TODO (tm) property_pair vector::getNumberOfGlobalComponents should return
180 // unsigned value. Then explicit cast from signed to unsigned int and
181 // assert can be removed here. Implicit cast to long long is fine and
182 // can be kept
183 assert(global_components >= 0);
184 auto const ui_global_components =
185 static_cast<unsigned int>(global_components);
186
187 MeshLib::MeshItemType const mesh_item_type =
188 property_base->getMeshItemType();
189
190 std::string const& name = property_base->getPropertyName();
191
192 HdfData hdf = {data_ptr, num_of_tuples, ui_global_components, name,
193 data_type, n_files, chunk_size_bytes};
194
195 XdmfData xdmf = {num_of_tuples, ui_global_components, data_type,
196 name, mesh_item_type, 0,
197 n_files};
198
199 return XdmfHdfData{std::move(hdf), std::move(xdmf)};
200}
201
202std::vector<XdmfHdfData> transformAttributes(
203 MeshLib::Mesh const& mesh, unsigned int const n_files,
204 unsigned int const chunk_size_bytes)
205{
206 MeshLib::Properties const& properties = mesh.getProperties();
207
208 // \TODO (tm) use c++20 ranges
209 // a = p | filter (first!=OGS_VERSION) | filter null_opt | transformAttr |
210 std::vector<XdmfHdfData> attributes;
211 for (auto const& [name, property_base] : properties)
212 {
214 {
215 continue;
216 }
217
218 if (!property_base->is_for_output)
219 {
220 continue;
221 }
222
223 if (auto const attribute = transformAttribute(
224
225 std::pair(std::string(name), property_base), n_files,
226 chunk_size_bytes))
227
228 {
229 attributes.push_back(attribute.value());
230 }
231 else
232 {
233 WARN("Could not create attribute meta of {:s}.", name);
234 }
235 }
236 return attributes;
237}
238
239std::vector<double> transformToXDMFGeometry(MeshLib::Mesh const& mesh)
240{
241 std::vector<MeshLib::Node*> const& nodes = mesh.getNodes();
242
243 int const point_size = 3;
244 std::vector<double> values;
245 values.reserve(nodes.size() * point_size);
246 for (auto const& n : nodes)
247 {
248 const double* x = n->data();
249 values.insert(values.cend(), x, x + point_size);
250 }
251
252 return values;
253}
254
255XdmfHdfData transformGeometry(MeshLib::Mesh const& mesh, double const* data_ptr,
256 unsigned int const n_files,
257 unsigned int const chunk_size_bytes)
258{
259 std::string const name = "geometry";
260 std::vector<MeshLib::Node*> const& nodes = mesh.getNodes();
261
262 int const point_size = 3;
263 auto const& partition_dim = nodes.size();
264
265 HdfData const hdf = {data_ptr,
266 partition_dim,
267 point_size,
268 name,
270 n_files,
271 chunk_size_bytes};
272 XdmfData const xdmf = {
273 partition_dim, point_size, MeshPropertyDataType::float64,
274 name, std::nullopt, 2,
275 n_files};
276
277 return XdmfHdfData{std::move(hdf), std::move(xdmf)};
278}
279
280std::vector<int> transformToXDMFTopology(MeshLib::Mesh const& mesh,
281 std::size_t const offset)
282{
283 std::vector<MeshLib::Element*> const& elements = mesh.getElements();
284 std::vector<int> values;
285 values.reserve(elements.size());
286
287 for (auto const& cell : elements)
288 {
289 auto const ogs_cell_type = cell->getCellType();
290 auto const xdmf_cell_id = cellTypeOGS2XDMF(ogs_cell_type).id;
291 values.push_back(xdmf_cell_id);
292 if (ogs_cell_type == MeshLib::CellType::LINE2 ||
293 ogs_cell_type == MeshLib::CellType::LINE3)
294 {
295 values.push_back(cellTypeOGS2XDMF(ogs_cell_type).number_of_nodes);
296 }
297
298 for (std::size_t i = 0; i < cell->getNumberOfNodes(); ++i)
299 {
300 MeshLib::Node const* node = cell->getNode(i);
301 values.push_back(node->getID() + offset);
302 }
303 }
304 return values;
305}
306
307XdmfHdfData transformTopology(std::vector<int> const& values,
308 unsigned int const n_files,
309 unsigned int const chunk_size_bytes)
310{
311 std::string const name = "topology";
312 HdfData const hdf = {
313 values.data(), values.size(), 1, name, MeshPropertyDataType::int32,
314 n_files, chunk_size_bytes};
315 XdmfData const xdmf = {
316 values.size(), 1, MeshPropertyDataType::int32, name, std::nullopt, 3,
317 n_files};
318
319 return XdmfHdfData{std::move(hdf), std::move(xdmf)};
320}
321} // 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.
MeshPropertyDataType
Definition of the Mesh class.
Definition of the Node class.
std::size_t getID() const
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
std::vector< int > 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)
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.
XdmfHdfData transformTopology(std::vector< int > const &values, 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
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.