DataExport
Last update: 10.07.2023Examples creating entites and importing or exporting from or to specific formats.
//
// COPYRIGHT ANSYS. ALL RIGHTS RESERVED.
//
#include "dpf_api.h"
#include "helpers/dpf_result.h"
#include "helpers/dpf_model.h"
#include <limits>
#ifdef EXAMPLE
#include "Example.h"
#else
#include <gtest/gtest.h>
#endif
// TemporaryDirectory
#include <boost/filesystem.hpp>
#include <boost/dll.hpp>
#include <thread>
#include <sstream>
struct DataExportTempDir
{
private:
boost::filesystem::path _result_path;
public:
DataExportTempDir()
{
std::ostringstream ss;
ss << std::this_thread::get_id();
boost::filesystem::path program_loc = boost::dll::program_location().parent_path();
program_loc /= ("DpfData" + ss.str());
if (!boost::filesystem::exists(program_loc))
boost::filesystem::create_directories(program_loc);
_result_path = program_loc;
}
~DataExportTempDir()
{
clear();
}
void clear()
{
if (boost::filesystem::exists(_result_path))
boost::filesystem::remove_all(_result_path);
}
std::string getTempFile(std::string const& name) const
{
return (_result_path / name).string();
}
};
TEST(CreateAndExport, CreateEntitesAndHdf5Export)
{
/*
You can create your field, fields container, or meshed region, to use in DPF operators, with your own data.
These entities can then be exported into HDF5 format, that can be re-opened in another process.
*/
ansys::dpf::LabelSpace label_space_2 = { { ansys::dpf::labels::time, 2 } };
ansys::dpf::LabelSpace label_space_3 = { { ansys::dpf::labels::time, 3 } };
int numNodes = 9;
int numElements = 3;
ansys::dpf::MeshedRegion mesh;
ansys::dpf::FieldsContainer fc_disp;
ansys::dpf::FieldsContainer fc_stress;
ansys::dpf::MeshesContainer meshes;
ansys::dpf::DataSources hdf5_ds;
// set the result folder path to the right path
DataExportTempDir temp_dir;
// 1. Create a new mesh with 1 quad, 1 point element and 1 tetra
// -------------------------------------------------------------
{
//quad element with 4 nodes
mesh.addNode(1, { 0.0, 0.0, 0.0 });
mesh.addNode(2, { 1.0, 0.0, 0.0 });
mesh.addNode(3, { 1.0, 1.0, 0.0 });
mesh.addNode(4, { 0.0, 1.0, 0.0 });
mesh.addElement(ansys::dpf::elements::quadShell4, 1, { 0, 1, 2, 3 }); // connectivity is by node indexes
//point element
mesh.addNode(5, { 0.0, 0.0, 0.0 });
//tetra element with 4 nodes
mesh.addNode(6, { 0.0, 0.0, 0.0 });
mesh.addNode(7, { 1.0, 0.0, 0.0 });
mesh.addNode(8, { 1.0, 1.0, 0.0 });
mesh.addNode(9, { 0.0, 1.0, 1.0 });
// Access the mesh information
//return:
//11
//return:
//4
}
// 2. Create nodal displacement FieldContainer for 3 time steps
// ------------------------------------------------------------
/*
Create displacement fields over time with three time sets. For the first time set, the displacement
on each node is the value of its x, y, and z coordinates. For the second time set, the displacement
on each node is two times the value of its x, y, and z coordinates. For the third time set, the
displacement on each node is three times the value of its x, y, and z coordinates.
*/
{
add.connect(0, coordinates_field);
add.connect(1, coordinates_field);
ansys::dpf::Field coordinates_x_2 = add.getOutputField(0);
add.connect(1, coordinates_x_2);
ansys::dpf::Field coordinates_x_3 = add.getOutputField(0);
// fill whole data in once
time_1_disp_data.setData(data_1, coordinates_field.dataSize());
ansys::dpf::Field time_2_disp_data(numNodes, { 1 }, ansys::dpf::locations::nodal);
double* data_2 = coordinates_x_2.data().data();
time_2_disp_data.setData(data_2, coordinates_x_2.dataSize());
ansys::dpf::Field time_3_disp_data(numNodes, { 1 }, ansys::dpf::locations::nodal);
double* data_3 = coordinates_x_3.data().data();
time_3_disp_data.setData(data_3, coordinates_x_3.dataSize());
ansys::dpf::FieldDefinition field_def_1 = time_1_disp_data.fieldDefinition();
field_def_1.setUnit(mesh.lengthUnit());
time_1_disp_data.setFieldDefinition(field_def_1);
ansys::dpf::FieldDefinition field_def_2 = time_2_disp_data.fieldDefinition();
field_def_2.setUnit(mesh.lengthUnit());
time_2_disp_data.setFieldDefinition(field_def_2);
ansys::dpf::FieldDefinition field_def_3 = time_3_disp_data.fieldDefinition();
field_def_3.setUnit(mesh.lengthUnit());
time_3_disp_data.setFieldDefinition(field_def_3);
time_1_disp_data.setScoping(coordinates_field.scoping());
time_2_disp_data.setScoping(coordinates_field.scoping());
time_3_disp_data.setScoping(coordinates_field.scoping());
fc_disp.add(label_space_1, time_1_disp_data);
fc_disp.add(label_space_2, time_2_disp_data);
fc_disp.add(label_space_3, time_3_disp_data);
}
// 3. Create elemental stress FieldContainer for 3 time steps
// ----------------------------------------------------------
{
int num_entities = 3;
ansys::dpf::Field field_stress_1(num_entities, { 3, 3 }, ansys::dpf::locations::elemental); //elemental sym matrix
ansys::dpf::Field field_stress_2(num_entities, { 3, 3 }, ansys::dpf::locations::elemental); //elemental sym matrix
ansys::dpf::Field field_stress_3(num_entities, { 3, 3 }, ansys::dpf::locations::elemental); //elemental sym matrix
ansys::dpf::FieldDefinition field_def_1 = field_stress_1.fieldDefinition();
field_stress_1.setFieldDefinition(field_def_1);
ansys::dpf::FieldDefinition field_def_2 = field_stress_2.fieldDefinition();
field_stress_2.setFieldDefinition(field_def_2);
ansys::dpf::FieldDefinition field_def_3 = field_stress_3.fieldDefinition();
field_stress_3.setFieldDefinition(field_def_3);
// fill by entity
std::vector<double> elem_data_1 = { 1.0, 1.0, 1.0, 0.0, 0.0, 0.0, 1.0, 1.0, 1.0, 0.0, 0.0, 0.0, 1.0, 1.0, 1.0, 0.0, 0.0, 0.0, 1.0, 1.0, 1.0, 0.0, 0.0, 0.0, };
std::vector<double> elem_data_2 = { 4.0, 4.0, 4.0, 0.0, 0.0, 0.0 };
std::vector<double> elem_data_3 = { 2.3, 1.0, 1.0, 0.0, 0.0, 1.0, 2.3, 1.0, 1.0, 0.0, 0.0, 1.0, 2.3, 1.0, 1.0, 0.0, 0.0, 1.0, 2.3, 1.0, 1.0, 0.0, 0.0, 1.0 };
field_stress_1.push_back(1, elem_data_1);
field_stress_1.push_back(2, elem_data_2);
field_stress_1.push_back(4, elem_data_3);
field_stress_2.push_back(1, elem_data_1);
field_stress_2.push_back(2, elem_data_2);
field_stress_2.push_back(4, elem_data_3);
field_stress_3.push_back(1, elem_data_1);
field_stress_3.push_back(2, elem_data_2);
field_stress_3.push_back(4, elem_data_3);
fc_stress.addLabel(ansys::dpf::labels::time);
fc_stress.add(label_space_1, field_stress_1);
fc_stress.add(label_space_2, field_stress_2);
fc_stress.add(label_space_3, field_stress_3);
}
// 4. Get deformed meshed in a MeshesContainer
// -------------------------------------------
{
ansys::dpf::Field node_coords = mesh.nodesCoordinates();
ansys::dpf::Operator add_coords("add");
add_coords.connect(0, node_coords);
add_coords.connect(1, disp_field_1);
ansys::dpf::Field deformed_coords_1 = add_coords.getOutputField(0);
ansys::dpf::Field disp_field_2 = fc_disp.getField(label_space_2);
add_coords.connect(1, disp_field_2);
ansys::dpf::Field deformed_coords_2 = add_coords.getOutputField(0);
ansys::dpf::Field disp_field_3 = fc_disp.getField(label_space_3);
add_coords.connect(1, disp_field_3);
ansys::dpf::Field deformed_coords_3 = add_coords.getOutputField(0);
mesh_1.setNodesCoordinates(deformed_coords_1);
ansys::dpf::MeshedRegion mesh_2 = mesh.deep_copy();
mesh_2.setNodesCoordinates(deformed_coords_2);
ansys::dpf::MeshedRegion mesh_3 = mesh.deep_copy();
mesh_3.setNodesCoordinates(deformed_coords_3);
meshes.add(label_space_1, mesh_1);
meshes.add(label_space_2, mesh_2);
meshes.add(label_space_3, mesh_3);
}
// 5. Serialize into hdf5 file
// ---------------------------
{
ansys::dpf::Operator op_hdf5("hdf5::h5dpf::make_result_file");
op_hdf5.connect(0, temp_dir.getTempFile("export_hdf5.h5"));
op_hdf5.connect(1, mesh);
op_hdf5.connect(4, std::string("stress_result"));
op_hdf5.connect(5, fc_stress);
op_hdf5.connect(6, std::string("disp_result"));
op_hdf5.connect(7, fc_disp);
hdf5_ds = op_hdf5.getOutputDataSources(0);
}
// 6. Deserialize the H5 file and check the result
// -----------------------------------------------
ansys::dpf::MeshedRegion mesh_deser = ansys::dpf::MeshedRegion::emptyMeshedRegion();
{
ansys::dpf::Operator stream("stream_provider");
stream.connect(ansys::dpf::eDataSourcesPin, hdf5_ds);
ansys::dpf::Operator h5_read_op("hdf5::h5dpf::custom");
h5_read_op.connect(ansys::dpf::eStreamPin, stream, 0);
h5_read_op.connect(60, std::string("stress_result"));
stress_deser = h5_read_op.getOutputFieldsContainer(0);
h5_read_op.connect(60, std::string("disp_result"));
disp_deser = h5_read_op.getOutputFieldsContainer(0);
ansys::dpf::Operator mesh_prov_op("MeshProvider");
mesh_prov_op.connect(ansys::dpf::eStreamPin, stream, 0);
mesh_deser = mesh_prov_op.getOutputMeshedRegion(0);
}
// 7. Ensure serialized and deserialized values are identical
// ----------------------------------------------------------
EXPECT_TRUE(disp_deser[0].dataSize() == fc_disp[0].dataSize());
EXPECT_TRUE(stress_deser[1].dataSize() == stress_deser[1].dataSize());
}
Definition: dpf_api.h:1954
Definition: dpf_api.h:532
void setUnit(ansys::dpf::Unit const &rhs)
dp_double *const data(int &size) const
FieldDefinition fieldDefinition() const
dp_int dataSize() const
Scoping scoping() const
void add(LabelSpace const &lab_space, Field const &f)
dp_int size() const
void addLabel(std::string const &label)
Field getField(LabelSpace const &lab_space) const
static FieldsContainer emptyFieldsContainer()
Definition: dpf_api.h:630
Holds the mesh for a given region (body, faces, skin, ...)
Definition: dpf_api.h:3596
void addElement(ElementDescriptor const &descriptor, dp_id elem_id, std::vector< dp_index > const &node_indices)
void addNode(dp_id node_id, std::array< dp_double, 3 > const &data)
Scoping elementScoping() const
Field nodesCoordinates() const
void setLengthUnit(Unit const &unit)
void prepareConstruction(dp_int n_nodes, dp_int n_elements)
dp_int numberOfElements() const
MeshedRegion deep_copy(ansys::dpf::Client const *const client) const
Scoping nodeScoping() const
void setNodesCoordinates(Field coordinates)
Unit lengthUnit() const
dp_int numberOfNodes() const
Definition: dpf_api.h:1841
void addLabel(std::string const &label)
void add(LabelSpace const &labels, MeshedRegion const &f)
dp_int size() const
Definition: dpf_api.h:226
static const ElementDescriptor quadShell4
Definition: dpf_api_base.h:660