Commit 7f5ddad5 authored by Tobias Meisel's avatar Tobias Meisel
Browse files

[MeL/IO] Transforming MeshData to flattened vector and creating meta information

parent 1a1b92a8
......@@ -7,34 +7,25 @@
* http://www.opengeosys.org/project/license
*/
// \TODO (tm) Extend xdmf lib with 64bit datatypes
#if !_MSC_VER
#pragma GCC diagnostic ignored "-Wnarrowing"
#endif
// \TODO (tm) Extend xdmf lib with 64bit data types
#include "transformData.h"
#include <XdmfArrayType.hpp>
#include <XdmfAttributeCenter.hpp>
#include <XdmfTopologyType.hpp>
#include <optional>
#include <variant>
#include <string>
#include "InfoLib/GitInfo.h"
#include "MeshLib/Elements/Element.h"
#include "MeshLib/Mesh.h"
#include "MeshLib/MeshEnums.h"
#include "MeshLib/Node.h"
namespace
{
using XdmfDimType = unsigned int;
using Hdf5DimType = unsigned long long;
} // namespace
#include "MeshPropertyDataType.h"
#include "partition.h"
namespace MeshLib::IO
{
// \TODO (tm) constexpr by other funtion signature can not be transformed to
// \TODO (tm) constexpr by other function signature can not be transformed to
// constexpr shared_ptr is not literal type / has non trivial destructor
boost::shared_ptr<const XdmfTopologyType> cellTypeOGS2XDMF(
MeshLib::CellType const cell_type)
......@@ -65,94 +56,54 @@ boost::shared_ptr<const XdmfTopologyType> cellTypeOGS2XDMF(
return elem_type_ogs2xdmf.at(cell_type);
}
boost::shared_ptr<const XdmfAttributeCenter> elemTypeOGS2XDMF(
MeshLib::MeshItemType const elem_type)
{
std::map<MeshLib::MeshItemType,
boost::shared_ptr<const XdmfAttributeCenter>>
mesh_item_type_ogs2xdmf = {
{MeshLib::MeshItemType::Cell, XdmfAttributeCenter::Cell()},
{MeshLib::MeshItemType::Edge, XdmfAttributeCenter::Edge()},
{MeshLib::MeshItemType::Face, XdmfAttributeCenter::Face()},
{MeshLib::MeshItemType::Node, XdmfAttributeCenter::Node()},
{MeshLib::MeshItemType::IntegrationPoint,
XdmfAttributeCenter::Other()}};
return mesh_item_type_ogs2xdmf.at(elem_type);
}
std::optional<AttributeMeta> transformAttribute(
std::pair<std::string, PropertyVectorBase*> const& property)
std::pair<std::string, PropertyVectorBase*> const& property_pair)
{
// lambda f : Transforms property to AttributeMeta, first parameter is
// output parameter because the boolean return type is used to allow kind of
// pipe using || operator
auto f = [&](std::optional<AttributeMeta>& attribute_meta,
auto basic_type,
auto property_pair) -> bool {
// 3 data that will be captured and written by lambda f below
MeshPropertyDataType data_type = MeshPropertyDataType::unknown;
std::size_t num_of_tuples = 0;
void const* data_ptr = 0;
// lambda f : Collects properties from the propertyVectorBase. It captures
// (and overwrites) data that can only be collected via the typed property.
// It has boolean return type to allow kind of pipe using || operator.
auto f = [&data_type, &num_of_tuples, &data_ptr,
&property_pair](auto basic_type) -> bool {
auto const property_base = property_pair.second;
auto const name = property_pair.first;
auto const typed_property =
dynamic_cast<PropertyVector<decltype(basic_type)> const*>(
property_base);
if (typed_property == nullptr)
{
attribute_meta = std::nullopt;
return false;
}
auto const mesh_item_type =
elemTypeOGS2XDMF(property_base->getMeshItemType());
auto const global_components =
property_base->getNumberOfGlobalComponents();
auto const size = typed_property->getNumberOfTuples();
auto const vdims = [](XdmfDimType num_components,
XdmfDimType size) -> std::vector<XdmfDimType> {
if (num_components > 1)
{
return {size, num_components};
}
return {size};
}(global_components, size);
// \TODO (tm) Remove code duplicationby eliminating the need for a
// second vldim at all by modification of XdmfHdf5Controller
// taking unsigned long long
auto const vldims = [](XdmfDimType num_components,
XdmfDimType size) -> std::vector<Hdf5DimType> {
if (num_components > 1)
{
return std::vector<Hdf5DimType>{size, num_components};
}
else
{
return std::vector<Hdf5DimType>{size};
}
}(global_components, size);
auto data_type = XdmfArrayType::Float64();
// overwrite captured data
num_of_tuples = typed_property->getNumberOfTuples();
data_ptr = typed_property->data();
if constexpr (std::is_same_v<double, decltype(basic_type)>)
{
// The standard 64-bit IEEE 754 floating-point type (double-precision)
// has a 53 bit fractional part (52 bits written, one implied)
// The standard 64-bit IEEE 754 floating-point type
// (double-precision) has a 53 bit fractional part (52 bits written,
// one implied)
static_assert((std::numeric_limits<double>::digits == 53),
"Double has 52 bits fractional part");
data_type = XdmfArrayType::Float64();
data_type = MeshPropertyDataType::float64;
}
else if constexpr (std::is_same_v<float, decltype(basic_type)>)
{
// The standard 32-bit IEEE 754 floating-point type (single-precision)
// has a 24 bit fractional part (23 bits written, one implied)
// The standard 32-bit IEEE 754 floating-point type
// (single-precision) has a 24 bit fractional part (23 bits written,
// one implied)
static_assert((std::numeric_limits<float>::digits == 24),
"Float has 23 bits fractional part");
data_type = XdmfArrayType::Float32();
data_type = MeshPropertyDataType::float32;
}
else if constexpr (std::is_same_v<int, decltype(basic_type)>)
{
static_assert((std::numeric_limits<int>::digits == 31),
"Signed int has 32-1 bits");
data_type = XdmfArrayType::Int32();
data_type = MeshPropertyDataType::int32;
}
// \TODO (tm) Reimplement size checks
// else if constexpr (std::is_same_v<long, decltype(basic_type)>)
......@@ -165,71 +116,74 @@ std::optional<AttributeMeta> transformAttribute(
{
static_assert((std::numeric_limits<unsigned int>::digits == 32),
"Unsigned int has 32 bits");
data_type = XdmfArrayType::UInt32();
data_type = MeshPropertyDataType::uint32;
}
// else if constexpr (std::is_same_v<unsigned long, decltype(basic_type)>)
// else if constexpr (std::is_same_v<unsigned long,
// decltype(basic_type)>)
// {
// static_assert((std::numeric_limits<unsigned long>::digits == 64),
// "Unsigned long has 64 bits");
// // \TODO (tm) Extend XdmfLibrary with 64bit datatypes
// // \TODO (tm) Extend XdmfLibrary with 64bit data types
// data_type = XdmfArrayType::UInt32();
// }
else if constexpr (std::is_same_v<std::size_t, decltype(basic_type)>)
{
static_assert((std::numeric_limits<std::size_t>::digits == 64),
"size_t has 64 bits");
// \TODO (tm) Extend XdmfLibrary with 64bit datatypes
data_type = XdmfArrayType::UInt32();
// \TODO (tm) Extend XdmfLibrary with 64bit data types
data_type = MeshPropertyDataType::uint32;
}
else if constexpr (std::is_same_v<char, decltype(basic_type)>)
{
static_assert((std::numeric_limits<char>::digits == 7),
"char has 8-1 bits");
data_type = XdmfArrayType::Int8();
"Signed char has 8-1 bits");
data_type = MeshPropertyDataType::int8;
}
else if constexpr (std::is_same_v<unsigned char, decltype(basic_type)>)
{
static_assert((std::numeric_limits<unsigned char>::digits == 8),
"Unsigned char has 8 bits");
data_type = XdmfArrayType::UInt8();
data_type = MeshPropertyDataType::uint8;
}
else
{
return false;
}
std::vector<XdmfDimType> const starts = {0, 0, 0};
std::vector<XdmfDimType> const strides = {1, 1, 1};
attribute_meta = {typed_property->data(),
name,
mesh_item_type,
data_type,
starts,
strides,
vdims,
vldims};
return true;
};
std::optional<AttributeMeta> attribute;
f(attribute, double{}, property) || f(attribute, float{}, property) ||
f(attribute, int{}, property) || f(attribute, long{}, property) ||
f(attribute, unsigned{}, property) || f(attribute, long{}, property) ||
f(attribute, static_cast<unsigned long>(0), property) ||
f(attribute, std::size_t{}, property) ||
f(attribute, char{}, property) ||
f(attribute, static_cast<unsigned char>(0), property);
f(double{}) || f(float{}) || f(int{}) || f(long{}) || f(unsigned{}) ||
f(long{}) || f(static_cast<unsigned long>(0)) || f(std::size_t{}) ||
f(char{}) || f(static_cast<unsigned char>(0));
if (!attribute)
if (data_type == MeshPropertyDataType::unknown)
{
OGS_FATAL("Could not apply function to PropertyVector '{:s}'.",
property.second->getPropertyName());
return std::nullopt;
}
return attribute;
auto const& property_base = property_pair.second;
auto const& global_components =
property_base->getNumberOfGlobalComponents();
// TODO (tm) property_pair vector::getNumberOfGlobalComponents should return
// unsigned value. Then explicit cast from signed to unsigned int and
// assert can be removed here. Implicit cast to long long is fine and
// can be kept
assert(global_components >= 0);
auto const ui_global_components =
static_cast<unsigned int>(global_components);
MeshLib::MeshItemType const mesh_item_type =
property_base->getMeshItemType();
std::string const& name = property_base->getPropertyName();
HdfData hdf =
HdfData(data_ptr, num_of_tuples, ui_global_components, name, data_type);
XdmfData xdmf = XdmfData(num_of_tuples, ui_global_components, data_type,
name, mesh_item_type);
return AttributeMeta{std::move(hdf), std::move(xdmf)};
}
std::vector<AttributeMeta> transformAttributes(MeshLib::Mesh const& mesh)
......@@ -258,52 +212,64 @@ std::vector<AttributeMeta> transformAttributes(MeshLib::Mesh const& mesh)
Geometry transformGeometry(MeshLib::Mesh const& mesh)
{
std::string const name = "geometry";
std::vector<MeshLib::Node*> const& nodes = mesh.getNodes();
int const point_size = 3;
std::vector<double> values;
values.reserve(nodes.size() * 3);
for (auto n : nodes)
values.reserve(nodes.size() * point_size);
for (auto const& n : nodes)
{
const double* x = n->getCoords();
values.insert(values.cend(), x, x + 3);
values.insert(values.cend(), x, x + point_size);
}
std::vector<XdmfDimType> const vdims = {static_cast<XdmfDimType>(nodes.size()), 3};
std::vector<Hdf5DimType> const vldims = {nodes.size(), 3};
std::vector<XdmfDimType> const starts = {0, 0, 0};
std::vector<XdmfDimType> const strides = {1, 1, 1};
return Geometry{std::move(values), starts, strides, vdims, vldims};
auto const& partition_dim = nodes.size();
HdfData hdf = HdfData(values.data(),
partition_dim,
point_size,
name,
MeshPropertyDataType::float64);
XdmfData xdmf = XdmfData(partition_dim,
point_size,
MeshPropertyDataType::float64,
name,
std::nullopt);
return Geometry{std::move(values), std::move(hdf), std::move(xdmf)};
}
Topology transformTopology(MeshLib::Mesh const& mesh)
Topology transformTopology(MeshLib::Mesh const& mesh, std::size_t const offset)
{
std::vector<MeshLib::Element*> elements = mesh.getElements();
std::string const name = "topology";
std::vector<MeshLib::Element*> const& elements = mesh.getElements();
// \TODO (tm) Precalculate exact size
std::vector<int> values;
values.reserve(elements.size());
for (auto const& cell : elements)
{
auto const celltype = cellTypeOGS2XDMF(cell->getCellType());
auto const celltype_id = celltype->getID();
values.push_back(celltype_id);
if (celltype_id == 2 || celltype_id == 3)
auto const cell_type = cellTypeOGS2XDMF(cell->getCellType());
auto const cell_type_id = cell_type->getID();
values.push_back(cell_type_id);
if (cell_type_id == 2 || cell_type_id == 3)
{
values.push_back(celltype->getNodesPerElement());
values.push_back(cell_type->getNodesPerElement());
}
for (std::size_t i = 0; i < cell->getNumberOfNodes(); ++i)
{
MeshLib::Node const* node = cell->getNode(i);
values.push_back(node->getID());
values.push_back(node->getID() + offset);
}
}
std::vector<XdmfDimType> const starts = {0};
std::vector<XdmfDimType> const strides = {1};
std::vector<XdmfDimType> const vdims = {static_cast<XdmfDimType>(values.size())};
std::vector<Hdf5DimType> const vldims = {values.size()};
HdfData hdf = HdfData(values.data(), values.size(), 1, name,
MeshPropertyDataType::int32);
XdmfData xdmf = XdmfData(values.size(), 1, MeshPropertyDataType::int32,
name, std::nullopt);
return Topology{std::move(values), starts, strides, vdims, vldims};
return Topology{std::move(values), std::move(hdf), std::move(xdmf)};
}
} // namespace MeshLib::IO
......@@ -2,17 +2,16 @@
* \file
* \author Tobias Meisel
* \date 2020-11-13
* \brief Transforms OGS Mesh into vectorized data
* \brief Transforms OGS Mesh into vectorized data.
* \copyright
* Copyright (c) 2012-2021, OpenGeoSys Community (http://www.opengeosys.org)
* Distributed under a Modified BSD License.
* See accompanying file LICENSE.txt or
* http://www.opengeosys.org/project/license
*/
#pragma once
#include <vector>
#include "XdmfData.h"
#include "XdmfHdfData.h"
namespace MeshLib
{
......@@ -21,7 +20,25 @@ class Mesh;
namespace MeshLib::IO
{
/**
* \brief Create meta data for attributes used for hdf5 and xdmf
* @param mesh OGS mesh can be mesh or partitionedMesh
* @return vector of meta data
*/
std::vector<AttributeMeta> transformAttributes(MeshLib::Mesh const& mesh);
/**
* \brief Copies all node points into a new vector. Contiguous data used for
* writing.
* @param mesh OGS mesh can be mesh or partitionedMesh
* @return Geometry containing a copy of the data and the geometry meta data
*/
Geometry transformGeometry(MeshLib::Mesh const& mesh);
Topology transformTopology(MeshLib::Mesh const& mesh);
/**
* \brief Copies all cells into a new vector. Contiguous data used for writing.
* The topology is specific to xdmf because it contains the xdmf cell types!!
* See section topology in https://www.xdmf.org/index.php/XDMF_Model_and_Format
* @param mesh OGS mesh can be mesh or partitionedMesh
* @return Topology containing a copy of the data and the topology meta data
*/
Topology transformTopology(MeshLib::Mesh const& mesh, std::size_t offset);
} // namespace MeshLib::IO
\ No newline at end of file
Supports Markdown
0% or .
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment