v0.16.0
Loading...
Searching...
No Matches
mesh_tag_transfer.cpp
Go to the documentation of this file.
1/** \file mesh_tag_transfer.cpp
2
3 \brief extract mesh tag
4 tool to extract a mesh tag and write to new mesh file.
5 Can be used to extract a component of an existing vector tag.
6
7 NOTE: Only supports extracting one component from tags defined on tetrahedral entities
8 and creates new tag on same entities. Can be extended to support other entity types as needed.
9*/
10
11#include <MoFEM.hpp>
12using namespace MoFEM;
13
14static char help[] = "...\n\n";
15
16int main(int argc, char *argv[]) {
17 MoFEM::Core::Initialize(&argc, &argv, (char *)0, help);
18
19 try {
20
21 moab::Core mb_instance;
22 moab::Interface &moab = mb_instance;
23
24 char mesh_file_name[255] = "mesh.h5m";
25 char mesh_out_file[255] = "out.h5m";
26 char tag_name[255] = "new_tag";
27 char extract_tag_name[255] = "old_tag_name";
28 int extract_component = 0;
29
30 PetscBool flg_extract_tag_name = PETSC_FALSE;
31 int atom_test = 0;
32
33 PetscBool flg_file = PETSC_FALSE;
34 PetscBool flg_analytical = PETSC_FALSE;
35
36 PetscOptionsBegin(PETSC_COMM_WORLD, "", "none", "none");
37 CHKERR PetscOptionsString("-file_name", "mesh file name", "", "mesh.h5m",
38 mesh_file_name, 255, &flg_file);
39 CHKERR PetscOptionsString("-create_tag_name", "name of tag to create", "",
40 "", tag_name, 255, PETSC_NULLPTR);
41 CHKERR PetscOptionsString("-extract_tag_name",
42 "name of tag to extract from", "", "",
43 extract_tag_name, 255, &flg_extract_tag_name);
44 CHKERR PetscOptionsInt("-component_to_extract",
45 "component of vector tag to extract (0-based index)",
46 "", extract_component, &extract_component,
47 PETSC_NULLPTR);
48 CHKERR PetscOptionsString("-output_file", "output mesh file name", "",
49 "out.h5m", mesh_out_file, 255, PETSC_NULLPTR);
50 CHKERR PetscOptionsInt("-atom_test", "flag to create tag for test", "",
51 atom_test, &atom_test, PETSC_NULLPTR);
52 CHKERR PetscOptionsBool("-use_analytical_tag",
53 "bool to use coded analytical function", "",
54 flg_analytical, &flg_analytical, PETSC_NULLPTR);
55 PetscOptionsEnd();
56
57 const char *option;
58 option = "";
59 CHKERR moab.load_file(mesh_file_name, 0, option);
60
61 ParallelComm *pcomm = ParallelComm::get_pcomm(&moab, MYPCOMM_INDEX);
62 if (pcomm == NULL)
63 pcomm = new ParallelComm(&moab, PETSC_COMM_WORLD);
64
65 // Create MoFEM database
66 MoFEM::Core core(moab);
67
68 Range ents;
69 std::vector<double> new_tag_values;
70 // default entity type is tets, can be updated as needed
71 EntityType entity_type = MBTET;
72
73 if (atom_test || flg_analytical)
74 entity_type = MBVERTEX;
75
76 if (flg_extract_tag_name) {
77 // Tag extraction only supported on tets for now, can be extended to other entity types as needed
78 CHKERR moab.get_entities_by_type(0, entity_type, ents);
79 // find existing tag to extract value from
80 Tag extract_tag;
81 auto rval = moab.tag_get_handle(extract_tag_name, extract_tag);
82 if (rval != MB_SUCCESS) {
83 SETERRQ(PETSC_COMM_SELF, MOFEM_DATA_INCONSISTENCY,
84 "Failed to get handle for tag '%s'", extract_tag_name);
85 }
86
87 int extract_tag_len;
88 CHKERR moab.tag_get_length(extract_tag, extract_tag_len);
89 MOFEM_LOG("WORLD", Sev::inform)
90 << "Extracting component " << extract_component << " from tag '"
91 << extract_tag_name << "' with length " << extract_tag_len;
92
93 std::vector<double> extract_values(extract_tag_len * ents.size(), 0.0);
94 CHKERR moab.tag_get_data(extract_tag, ents, &extract_values[0]);
95
96 MOFEM_LOG("WORLD", Sev::inform)
97 << "Extracted " << extract_values.size() << " values from tag '"
98 << extract_tag_name << "'";
99
100 // extract specified component into new tag values
101 for (size_t i = 0; i < ents.size(); ++i) {
102 int idx = extract_component; // Assuming 1 component
103 if (idx < extract_tag_len) {
104 new_tag_values.push_back(extract_values[i * extract_tag_len + idx]);
105 } else {
106 SETERRQ(
107 PETSC_COMM_SELF, MOFEM_DATA_INCONSISTENCY,
108 "Component index to extract is out of bounds for the tag length");
109 }
110 }
111 MOFEM_LOG("WORLD", Sev::inform) << "Extracted component values for "
112 << new_tag_values.size() << " entities";
113 } else {
114 MOFEM_LOG("WORLD", Sev::warning) << "No tag specified for extraction.";
115 std::vector<double> test_data;
116 if (atom_test) {
117 // Atom test assigns values based on vector index
118 CHKERR moab.get_entities_by_type(0, entity_type, ents);
119
120 std::vector<double> test_data;
121 if (atom_test == 1) {
122 for (size_t i = 0; i < ents.size(); ++i) {
123 // assign index 0-5 for each
124 for (int idx = 0; idx < 5; ++idx) {
125 test_data.push_back(idx);
126 }
127 }
128 } else {
129 SETERRQ(PETSC_COMM_WORLD, MOFEM_DATA_INCONSISTENCY,
130 "atom test '%i' does not exist for setting a tag", atom_test);
131 }
132
133 for (const auto &val : test_data) {
134 new_tag_values.push_back(val);
135 }
136 } else if (flg_analytical) {
137 // create new tag for youngs modulus and set value based on analytical function
138 auto analytical_elastic = [](double, double,
139 const std::vector<double> &x,
140 const std::vector<double> &y,
141 const std::vector<double> &z, int) {
142 std::vector<double> youngs_modulus;
143 youngs_modulus.reserve(x.size());
144
145 for (double xi : x) {
146 double E0 = 1000.0;
147 double local = E0 * std::exp(xi);
148 youngs_modulus.push_back(local);
149 }
150
151 return youngs_modulus;
152 };
153
154 std::vector<double> coords(3 * ents.size(), 0.0);
155 CHKERR moab.get_coords(ents, &coords[0]);
156
157 for (size_t i = 0; i < ents.size(); ++i) {
158 double x = coords[3 * i + 0];
159 double y = coords[3 * i + 1];
160 double z = coords[3 * i + 2];
161
162 double val = analytical_elastic(0.0, 0.0, {x}, {y}, {z}, 0)[0];
163 test_data.push_back(val);
164 }
165
166 for (const auto &val : test_data) {
167 new_tag_values.push_back(val);
168 }
169 } else {
170 MOFEM_LOG("WORLD", Sev::warning) << "No tag has been created.";
171 }
172 }
173
174 // print the range of new tag values for verification
175 auto minmax =
176 std::minmax_element(new_tag_values.begin(), new_tag_values.end());
177 MOFEM_LOG("WORLD", Sev::inform)
178 << "New tag '" << tag_name << "' value range: [" << *minmax.first
179 << ", " << *minmax.second << "]";
180
181 // Create new tag and set value
182 std::vector<double> def_val;
183
184 if (atom_test == 1) {
185 def_val = {0.0, 0.0, 0.0, 0.0, 0.0};
186 } else {
187 def_val = {0.0};
188 }
189
190 Tag new_tag;
191 CHKERR moab.tag_get_handle(tag_name, def_val.size(), MB_TYPE_DOUBLE, new_tag,
192 MB_TAG_CREAT | MB_TAG_DENSE, &def_val);
193
194 CHKERR moab.tag_set_data(new_tag, ents, &new_tag_values[0]);
195
196 // write output mesh with new tag
197 CHKERR moab.write_file(mesh_out_file, "MOAB", "PARALLEL=WRITE_PART");
198 CHKERR moab.write_file("out.vtk", "vtk");
199
200 // check results
201 if (atom_test == 1) {
202 std::vector<double> check_values(new_tag_values.size(), 0.0);
203 CHKERR moab.tag_get_data(new_tag, ents, &check_values[0]);
204 MOFEM_LOG("WORLD", Sev::inform)
205 << "check_values size: " << check_values.size()
206 << ", new_tag_values size: " << new_tag_values.size();
207
208 for (size_t i = 0; i < new_tag_values.size(); ++i) {
209 if (std::abs(check_values[i] - new_tag_values[i]) > 1e-6) {
210 SETERRQ(PETSC_COMM_WORLD, MOFEM_DATA_INCONSISTENCY,
211 "Atom test failed: Value mismatch at index %zu: expected %f, "
212 "got %f",
213 i, new_tag_values[i], check_values[i]);
214 }
215 }
216 } else if (atom_test == 2) {
217 // For index test, check that extracted values match the expected component index
218 // instead of new_tag_values use expected values based on component index
219 std::vector<double> expected_values(new_tag_values.size(), 0.0);
220 CHKERR moab.tag_get_data(new_tag, ents, &expected_values[0]);
221 MOFEM_LOG("WORLD", Sev::inform)
222 << "check_values size: " << expected_values.size()
223 << ", new_tag_values size: " << new_tag_values.size();
224
225 for (size_t i = 0; i < expected_values.size(); ++i) {
226 if (std::abs(expected_values[i] - extract_component) > 1e-6) {
227 SETERRQ(PETSC_COMM_WORLD, MOFEM_DATA_INCONSISTENCY,
228 "Tag extraction test failed: Value mismatch at index %zu: "
229 "expected %i, got %f",
230 i, extract_component, expected_values[i]);
231 }
232 }
233 } else if (atom_test > 0) {
234 SETERRQ(PETSC_COMM_WORLD, MOFEM_DATA_INCONSISTENCY,
235 "atom test %i does not exist", atom_test);
236 }
237 }
239
241
242 return 0;
243}
int main()
#define CATCH_ERRORS
Catch errors.
#define MYPCOMM_INDEX
default communicator number PCOMM
@ MOFEM_DATA_INCONSISTENCY
Definition definitions.h:31
#define CHKERR
Inline error check.
#define MOFEM_LOG(channel, severity)
Log.
FTensor::Index< 'i', SPACE_DIM > i
static char help[]
static MoFEMErrorCodeGeneric< moab::ErrorCode > rval
implementation of Data Operators for Forces and Sources
Definition Common.hpp:10
Core (interface) class.
Definition Core.hpp:83
static MoFEMErrorCode Initialize(int *argc, char ***args, const char file[], const char help[])
Initializes the MoFEM database PETSc, MOAB and MPI.
Definition Core.cpp:68
static MoFEMErrorCode Finalize()
Checks for options to be called at the conclusion of the program.
Definition Core.cpp:123
int atom_test
Atom test.
Definition plastic.cpp:122