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"
25 #include "MeshPropertyDataType.h"
26 #include "partition.h"
27 
28 using namespace BaseLib;
29 namespace 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 
39 static 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 
67 constexpr auto cellTypeOGS2XDMF(MeshLib::CellType const& cell_type)
68 {
69  return elem_type_ogs2xdmf[to_underlying(cell_type)];
70 }
71 
72 std::optional<XdmfHdfData> transformAttribute(
73  std::pair<std::string, PropertyVectorBase*> const& property_pair,
74  unsigned int const n_files)
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, &property_pair](
85  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");
106  data_type = MeshPropertyDataType::float64;
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");
115  data_type = MeshPropertyDataType::float32;
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");
142  data_type = MeshPropertyDataType::uint32;
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");
148  data_type = MeshPropertyDataType::uint64;
149  }
150  else if constexpr (std::is_same_v<char, decltype(basic_type)>)
151  {
152  static_assert((std::numeric_limits<char>::digits == 7),
153  "Signed char has 8-1 bits");
154  data_type = MeshPropertyDataType::int8;
155  }
156  else if constexpr (std::is_same_v<unsigned char, decltype(basic_type)>)
157  {
158  static_assert((std::numeric_limits<unsigned char>::digits == 8),
159  "Unsigned char has 8 bits");
160  data_type = MeshPropertyDataType::uint8;
161  }
162  else
163  {
164  return false;
165  }
166  return true;
167  };
168 
169  f(double{}) || f(float{}) || f(int{}) || f(long{}) || f(unsigned{}) ||
170  f(long{}) || f(static_cast<unsigned long>(0)) || f(std::size_t{}) ||
171  f(char{}) || f(static_cast<unsigned char>(0));
172 
173  if (data_type == MeshPropertyDataType::unknown)
174  {
175  return std::nullopt;
176  }
177 
178  auto const& property_base = property_pair.second;
179  auto const& global_components =
180  property_base->getNumberOfGlobalComponents();
181  // TODO (tm) property_pair vector::getNumberOfGlobalComponents should return
182  // unsigned value. Then explicit cast from signed to unsigned int and
183  // assert can be removed here. Implicit cast to long long is fine and
184  // can be kept
185  assert(global_components >= 0);
186  auto const ui_global_components =
187  static_cast<unsigned int>(global_components);
188 
189  MeshLib::MeshItemType const mesh_item_type =
190  property_base->getMeshItemType();
191 
192  std::string const& name = property_base->getPropertyName();
193 
194  HdfData hdf = {data_ptr, num_of_tuples, ui_global_components,
195  name, data_type, n_files};
196 
197  XdmfData xdmf = {num_of_tuples, ui_global_components, data_type,
198  name, mesh_item_type, 0,
199  n_files};
200 
201  return XdmfHdfData{std::move(hdf), std::move(xdmf)};
202 }
203 
204 std::vector<XdmfHdfData> transformAttributes(MeshLib::Mesh const& mesh,
205  unsigned int const n_files)
206 {
207  MeshLib::Properties const& properties = mesh.getProperties();
208 
209  // \TODO (tm) use c++20 ranges
210  // a = p | filter (first!=OGS_VERSION) | filter null_opt | transformAttr |
211  std::vector<XdmfHdfData> attributes;
212  for (auto const& [name, property_base] : properties)
213  {
215  {
216  continue;
217  }
218 
219  if (auto const attribute =
220  transformAttribute(std::pair(name, property_base), n_files))
221  {
222  attributes.push_back(attribute.value());
223  }
224  else
225  {
226  WARN("Could not create attribute meta of {:s}.", name);
227  }
228  }
229  return attributes;
230 }
231 
232 std::vector<double> transformToXDMFGeometry(MeshLib::Mesh const& mesh)
233 {
234  std::vector<MeshLib::Node*> const& nodes = mesh.getNodes();
235 
236  int const point_size = 3;
237  std::vector<double> values;
238  values.reserve(nodes.size() * point_size);
239  for (auto const& n : nodes)
240  {
241  const double* x = n->getCoords();
242  values.insert(values.cend(), x, x + point_size);
243  }
244 
245  return values;
246 }
247 
249  double const* data_ptr,
250  unsigned int const n_files)
251 {
252  std::string const name = "geometry";
253  std::vector<MeshLib::Node*> const& nodes = mesh.getNodes();
254 
255  int const point_size = 3;
256  auto const& partition_dim = nodes.size();
257 
258  HdfData const hdf = {data_ptr,
259  partition_dim,
260  point_size,
261  name,
263  n_files};
264  XdmfData const xdmf = {
265  partition_dim, point_size, MeshPropertyDataType::float64,
266  name, std::nullopt, 2,
267  n_files};
268 
269  return XdmfHdfData{std::move(hdf), std::move(xdmf)};
270 }
271 
272 std::vector<int> transformToXDMFTopology(MeshLib::Mesh const& mesh,
273  std::size_t const offset)
274 {
275  std::vector<MeshLib::Element*> const& elements = mesh.getElements();
276  std::vector<int> values;
277  values.reserve(elements.size());
278 
279  for (auto const& cell : elements)
280  {
281  auto const ogs_cell_type = cell->getCellType();
282  auto const xdmf_cell_id = cellTypeOGS2XDMF(ogs_cell_type).id;
283  values.push_back(xdmf_cell_id);
284  if (ogs_cell_type == MeshLib::CellType::LINE2 ||
285  ogs_cell_type == MeshLib::CellType::LINE3)
286  {
287  values.push_back(cellTypeOGS2XDMF(ogs_cell_type).number_of_nodes);
288  }
289 
290  for (std::size_t i = 0; i < cell->getNumberOfNodes(); ++i)
291  {
292  MeshLib::Node const* node = cell->getNode(i);
293  values.push_back(node->getID() + offset);
294  }
295  }
296  return values;
297 }
298 
299 XdmfHdfData transformTopology(std::vector<int> const& values,
300  unsigned int const n_files)
301 {
302  std::string const name = "topology";
303  HdfData const hdf = {
304  values.data(), values.size(), 1, name, MeshPropertyDataType::int32,
305  n_files};
306  XdmfData const xdmf = {
307  values.size(), 1, MeshPropertyDataType::int32, name, std::nullopt, 3,
308  n_files};
309 
310  return XdmfHdfData{std::move(hdf), std::move(xdmf)};
311 }
312 } // namespace MeshLib::IO
Definition of the Element class.
Git information.
void WARN(char const *fmt, Args const &... args)
Definition: Logging.h:37
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
Definition: Point3dWithID.h:62
std::vector< Node * > const & getNodes() const
Get the nodes-vector for the mesh.
Definition: Mesh.h:95
std::vector< Element * > const & getElements() const
Get the element-vector for the mesh.
Definition: Mesh.h:98
Properties & getProperties()
Definition: Mesh.h:123
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:30
const std::string OGS_VERSION
Definition: GitInfo.cpp:20
std::vector< XdmfHdfData > transformAttributes(MeshLib::Mesh const &mesh, unsigned int const n_files)
Create meta data for attributes used for hdf5 and xdmf.
XdmfHdfData transformGeometry(MeshLib::Mesh const &mesh, double const *data_ptr, unsigned int const n_files)
Create meta data for geometry used for hdf5 and xdmf.
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::vector< double > transformToXDMFGeometry(MeshLib::Mesh const &mesh)
Copies all node points into a new vector. Contiguous data used for writing. Conform with XDMF standar...
std::optional< XdmfHdfData > transformAttribute(std::pair< std::string, PropertyVectorBase * > const &property_pair, unsigned int const n_files)
XdmfHdfData transformTopology(std::vector< int > const &values, unsigned int const n_files)
Create meta data for topology used for HDF5 and XDMF.
static constexpr auto elemOGSTypeToXDMFType()
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.