v0.16.3
Loading...
Searching...
No Matches
Functions | Variables
mesh_data_transfer.cpp File Reference

Transfer data from source mesh to target mesh. More...

#include <MoFEM.hpp>
#include <mbcoupler/Coupler.hpp>

Go to the source code of this file.

Functions

int main (int argc, char *argv[])
 

Variables

static char help [] = "...\n\n"
 

Detailed Description

Transfer data from source mesh to target mesh.

The data is transferred from element or nodal tags on the source mesh to element or nodal tags on the target mesh. This code uses MBCoupler functionality of MOAB and is based on mbcoupler_test.cpp from MOAB.

For this tool to work, source and target files should be partitioned using mbpart tool from MOAB, e.g. mbpart -z PHG -t 4 sslv116_hex.cub sslv116_hex_4mp.h5m

Definition in file mesh_data_transfer.cpp.

Function Documentation

◆ main()

int main ( int  argc,
char *  argv[] 
)

Definition at line 21 of file mesh_data_transfer.cpp.

21 {
22 MoFEM::Core::Initialize(&argc, &argv, (char *)0, help);
23
24 try {
25
26 moab::Core mb_instance;
27 moab::Interface &moab = mb_instance;
28
29 // Create MoFEM database
30 MoFEM::Core core(moab);
31 MoFEM::Interface &m_field = core;
32
33 char mesh_source_file[255] = "source.h5m";
34 char mesh_target_file[255] = "target.h5m";
35 char mesh_out_file[255] = "out.h5m";
36 char iterp_tag_name[255] = "INTERNAL_STRESS";
37 char output_tag_name[255] = "";
38
39 int interp_order = 1;
40 PetscBool hybrid_interp = PETSC_TRUE;
41 PetscBool src_tag_nodes_to_elem_avg = PETSC_FALSE;
42 PetscBool src_tag_nodes_to_elem_set = PETSC_FALSE;
43 int atom_test = 0;
44
45 double toler = 5.e-10;
46
47 PetscOptionsBegin(m_field.get_comm(), "", "mesh data transfer tool",
48 "none");
49 CHKERR PetscOptionsString("-source_file", "source mesh file name", "",
50 "source.h5m", mesh_source_file, 255,
51 PETSC_NULLPTR);
52 CHKERR PetscOptionsString("-target_file", "target mesh file name", "",
53 "target.h5m", mesh_target_file, 255,
54 PETSC_NULLPTR);
55 CHKERR PetscOptionsString("-output_file", "output mesh file name", "",
56 "out.h5m", mesh_out_file, 255, PETSC_NULLPTR);
57 CHKERR PetscOptionsString("-interp_tag", "interpolation tag name", "",
58 "INTERNAL_STRESS", iterp_tag_name, 255,
59 PETSC_NULLPTR);
60 CHKERR PetscOptionsString("-output_tag", "output tag name",
61 "", "", output_tag_name, 255, PETSC_NULLPTR);
62 CHKERR PetscOptionsInt("-interp_order", "interpolation order", "", 0,
63 &interp_order, PETSC_NULLPTR);
64 CHKERR PetscOptionsBool("-hybrid_interp", "use hybrid interpolation", "",
65 hybrid_interp, &hybrid_interp, PETSC_NULLPTR);
66 CHKERR PetscOptionsBool(
67 "-src_nodes_to_elem", "0: use source nodes directly; 1: average nodes to elements; omitted: use source elements",
68 "", src_tag_nodes_to_elem_avg, &src_tag_nodes_to_elem_avg,
69 &src_tag_nodes_to_elem_set);
70 CHKERR PetscOptionsInt("-atom_test", "atom test number", "", 0, &atom_test,
71 PETSC_NULLPTR);
72
73 PetscOptionsEnd();
74
75 MOFEM_LOG_CHANNEL("WORLD");
76 MOFEM_LOG_TAG("WORLD", "mesh_data_transfer");
77
78 Coupler::Method method;
79 switch (interp_order) {
80 case 0:
81 method = Coupler::CONSTANT;
82 break;
83 case 1:
84 method = Coupler::LINEAR_FE;
85 break;
86 default:
87 SETERRQ(PETSC_COMM_WORLD, MOFEM_NOT_IMPLEMENTED,
88 "Unsupported interpolation order");
89 }
90
91 const bool src_tag_nodes =
92 src_tag_nodes_to_elem_set && !src_tag_nodes_to_elem_avg;
93 if (src_tag_nodes && interp_order != 1) {
94 SETERRQ(PETSC_COMM_WORLD, MOFEM_DATA_INCONSISTENCY,
95 "-src_nodes_to_elem 0 requires -interp_order 1; use "
96 "-src_nodes_to_elem 1 to average nodal data for elemental output");
97 }
98
99 std::vector<std::string> mesh_files(2);
100 mesh_files[0] = string(mesh_source_file);
101 mesh_files[1] = string(mesh_target_file);
102
103 int nprocs, rank;
104 ierr = MPI_Comm_size(MPI_COMM_WORLD, &nprocs);
105 CHKERRQ(ierr);
106 ierr = MPI_Comm_rank(MPI_COMM_WORLD, &rank);
107 CHKERRQ(ierr);
108
109 std::string read_opts, write_opts;
110 read_opts = "PARALLEL=READ_PART;PARTITION=PARALLEL_PARTITION;PARTITION_"
111 "DISTRIBUTE;PARALLEL_RESOLVE_SHARED_ENTS";
112 if (nprocs > 1)
113 read_opts += ";PARALLEL_GHOSTS=3.0.1";
114 write_opts = (nprocs > 1) ? "PARALLEL=WRITE_PART" : "";
115
116 std::vector<boost::shared_ptr<ParallelComm>> pcs(mesh_files.size());
117 std::vector<EntityHandle> roots(mesh_files.size());
118
119 for (unsigned int i = 0; i < mesh_files.size(); i++) {
120 pcs[i] = boost::make_shared<ParallelComm>(&moab, MPI_COMM_WORLD);
121 int index = pcs[i]->get_id();
122 std::string newread_opts;
123 std::ostringstream extra_opt;
124 extra_opt << ";PARALLEL_COMM=" << index;
125 newread_opts = read_opts + extra_opt.str();
126
127 CHKERR moab.create_meshset(MESHSET_SET, roots[i]);
128
129 CHKERR moab.load_file(mesh_files[i].c_str(), &roots[i],
130 newread_opts.c_str());
131 }
132
133 Range src_elems, targ_elems, targ_verts;
134 CHKERR pcs[0]->get_part_entities(src_elems, 3);
135
136 Tag interp_tag;
137 CHKERR moab.tag_get_handle(iterp_tag_name, interp_tag);
138
139 int interp_tag_len;
140 CHKERR moab.tag_get_length(interp_tag, interp_tag_len);
141
142 if (interp_tag_len != 1 && interp_tag_len != 3 && interp_tag_len != 9) {
143 SETERRQ(PETSC_COMM_WORLD, MOFEM_NOT_IMPLEMENTED,
144 "Unsupported interpolation tag length: %d", interp_tag_len);
145 }
146
147 Tag output_tag = interp_tag;
148 if (output_tag_name[0]) {
149 std::vector<double> def_val(interp_tag_len, 0.0);
150 auto rval = moab.tag_get_handle(output_tag_name, interp_tag_len,
151 MB_TYPE_DOUBLE, output_tag,
152 MB_TAG_CREAT | MB_TAG_DENSE,
153 def_val.data());
154 if (rval == MB_ALREADY_ALLOCATED) {
155 SETERRQ(PETSC_COMM_WORLD, MOFEM_DATA_INCONSISTENCY,
156 "Output tag '%s' has a conflicting default; use another name",
157 output_tag_name);
158 }
159 CHKERR rval;
160 }
161
162 if (src_tag_nodes_to_elem_avg) {
163 for (auto &elem : src_elems) {
164 Range adj_verts;
165 CHKERR moab.get_connectivity(&elem, 1, adj_verts, true);
166
167 std::vector<double> adj_vert_data(adj_verts.size() * interp_tag_len, 0.0);
168 std::vector<double> elem_data(interp_tag_len, 0.0);
169 CHKERR moab.tag_get_data(interp_tag, adj_verts, adj_vert_data.data());
170
171 // Average vertex tag values and store the result on the source element.
172 for (int itag = 0; itag < interp_tag_len; ++itag) {
173 for (size_t ivert = 0; ivert != adj_verts.size(); ++ivert)
174 elem_data[itag] += adj_vert_data[ivert * interp_tag_len + itag];
175 elem_data[itag] /= adj_verts.size();
176 }
177 CHKERR moab.tag_set_data(interp_tag, &elem, 1, elem_data.data());
178 }
179 }
180
181 Coupler mbc(&moab, pcs[0].get(), src_elems, 0, true);
182
183 std::vector<double> vpos; // the positions we are interested in
184 int num_pts = 0;
185
186 Range tmp_verts;
187
188 // First get all vertices adj to partition entities in target mesh
189 CHKERR pcs[1]->get_part_entities(targ_elems, 3);
190 if (interp_order == 0) {
191 targ_verts = targ_elems;
192 } else {
193 CHKERR moab.get_adjacencies(targ_elems, 0, false, targ_verts,
194 moab::Interface::UNION);
195 }
196
197 // Then get non-owned verts and subtract
198 CHKERR pcs[1]->get_pstatus_entities(0, PSTATUS_NOT_OWNED, tmp_verts);
199 targ_verts = subtract(targ_verts, tmp_verts);
200
201 // get position of these entities; these are the target points
202 num_pts = (int)targ_verts.size();
203 vpos.resize(3 * targ_verts.size());
204 CHKERR moab.get_coords(targ_verts, &vpos[0]);
205
206 // Locate those points in the source mesh
207 boost::shared_ptr<TupleList> tl_ptr;
208 tl_ptr = boost::make_shared<TupleList>();
209 CHKERR mbc.locate_points(&vpos[0], num_pts, 0, toler, tl_ptr.get(), false);
210
211 // If some points were not located, we need to process them
212 auto find_missing_points = [&](Range &targ_verts, int &num_pts,
213 std::vector<double> &vpos,
214 Range &missing_verts) {
216 int missing_pts_num = 0;
217 int i = 0;
218 auto vit = targ_verts.begin();
219 for (; vit != targ_verts.end(); i++) {
220 if (tl_ptr->vi_rd[3 * i + 1] == -1) {
221 missing_verts.insert(*vit);
222 vit = targ_verts.erase(vit);
223 missing_pts_num++;
224 } else {
225 vit++;
226 }
227 }
228
229 int missing_pts_num_global = 0;
230 MPI_Allreduce(&missing_pts_num, &missing_pts_num_global, 1, MPI_INT,
231 MPI_SUM, m_field.get_comm());
232 if (missing_pts_num_global) {
233 MOFEM_LOG("WORLD", Sev::warning)
234 << missing_pts_num_global
235 << " points in target mesh were not located in source mesh. ";
236 }
237
238 if (missing_pts_num) {
239 num_pts = (int)targ_verts.size();
240 vpos.resize(3 * targ_verts.size());
241 CHKERR moab.get_coords(targ_verts, &vpos[0]);
242 tl_ptr->reset();
243 CHKERR mbc.locate_points(&vpos[0], num_pts, 0, toler, tl_ptr.get(),
244 false);
245 }
247 };
248
249 Range missing_verts;
250 CHKERR find_missing_points(targ_verts, num_pts, vpos, missing_verts);
251
252 Range src_entities;
253 if (src_tag_nodes) {
254 CHKERR moab.get_connectivity(src_elems, src_entities, true);
255 } else {
256 src_entities = src_elems;
257 }
258 std::vector<double> source_data(interp_tag_len * src_entities.size(), 0.0);
259 std::vector<double> target_data(interp_tag_len * num_pts, 0.0);
260
261 CHKERR moab.tag_get_data(interp_tag, src_entities, source_data.data());
262
263 Tag scalar_tag, adj_count_tag;
264 double def_scl = 0;
265 string scalar_tag_name = string(iterp_tag_name) + "_COMP";
266 CHKERR moab.tag_get_handle(scalar_tag_name.c_str(), 1, MB_TYPE_DOUBLE,
267 scalar_tag, MB_TAG_CREAT | MB_TAG_DENSE,
268 &def_scl);
269
270 string adj_count_tag_name = "ADJ_COUNT";
271 double def_adj = 0;
272 CHKERR moab.tag_get_handle(adj_count_tag_name.c_str(), 1, MB_TYPE_DOUBLE,
273 adj_count_tag, MB_TAG_CREAT | MB_TAG_DENSE,
274 &def_adj);
275
276 // MBCoupler functionality supports only scalar tags. For the case of
277 // vector or tensor tags we need to save each component as a scalar tag
278 auto create_scalar_tags = [&](const Range &src_elems,
279 const std::vector<double> &source_data,
280 int itag) {
282
283 std::vector<double> source_data_scalar(src_entities.size());
284 for (size_t i = 0; i != src_entities.size(); ++i)
285 source_data_scalar[i] = source_data[i * interp_tag_len + itag];
286
287 CHKERR moab.tag_set_data(scalar_tag, src_entities,
288 source_data_scalar.data());
289
290 if (!src_tag_nodes && interp_order == 1) {
291 // Linear interpolation: compute average value of data on vertices
292 Range src_verts;
293 CHKERR moab.get_connectivity(src_elems, src_verts, true);
294
295 CHKERR moab.tag_clear_data(scalar_tag, src_verts, &def_scl);
296 CHKERR moab.tag_clear_data(adj_count_tag, src_verts, &def_adj);
297
298 for (auto &tet : src_elems) {
299 double tet_data = 0;
300 CHKERR moab.tag_get_data(scalar_tag, &tet, 1, &tet_data);
301
302 Range adj_verts;
303 CHKERR moab.get_connectivity(&tet, 1, adj_verts, true);
304
305 std::vector<double> adj_vert_data(adj_verts.size(), 0.0);
306 std::vector<double> adj_vert_count(adj_verts.size(), 0.0);
307
308 CHKERR moab.tag_get_data(scalar_tag, adj_verts, &adj_vert_data[0]);
309 CHKERR moab.tag_get_data(adj_count_tag, adj_verts,
310 &adj_vert_count[0]);
311
312 for (int ivert = 0; ivert < adj_verts.size(); ivert++) {
313 adj_vert_data[ivert] += tet_data;
314 adj_vert_count[ivert] += 1;
315 }
316
317 CHKERR moab.tag_set_data(scalar_tag, adj_verts, &adj_vert_data[0]);
318 CHKERR moab.tag_set_data(adj_count_tag, adj_verts,
319 &adj_vert_count[0]);
320 }
321
322 // Reduce tags for the parallel case
323 std::vector<Tag> tags = {scalar_tag, adj_count_tag};
324 pcs[0]->reduce_tags(tags, tags, MPI_SUM, src_verts);
325
326 std::vector<double> src_vert_data(src_verts.size(), 0.0);
327 std::vector<double> src_vert_adj_count(src_verts.size(), 0.0);
328
329 CHKERR moab.tag_get_data(scalar_tag, src_verts, &src_vert_data[0]);
330 CHKERR moab.tag_get_data(adj_count_tag, src_verts,
331 &src_vert_adj_count[0]);
332
333 for (int ivert = 0; ivert < src_verts.size(); ivert++) {
334 src_vert_data[ivert] /= src_vert_adj_count[ivert];
335 }
336 CHKERR moab.tag_set_data(scalar_tag, src_verts, &src_vert_data[0]);
337 }
339 };
340
341 for (int itag = 0; itag < interp_tag_len; itag++) {
342
343 CHKERR create_scalar_tags(src_elems, source_data, itag);
344
345 std::vector<double> target_data_scalar(num_pts, 0.0);
346 CHKERR mbc.interpolate(method, scalar_tag_name, &target_data_scalar[0],
347 tl_ptr.get());
348
349 for (int ielem = 0; ielem < num_pts; ielem++) {
350 target_data[itag + ielem * interp_tag_len] = target_data_scalar[ielem];
351 }
352 }
353
354 // Store the interpolated values on the target tag
355 CHKERR moab.tag_set_data(output_tag, targ_verts, &target_data[0]);
356
357 if (missing_verts.size() && (interp_order == 1) && hybrid_interp) {
358 MOFEM_LOG("WORLD", Sev::warning) << "Using hybrid interpolation for "
359 "missing points in the target mesh.";
360 Range missing_adj_elems;
361 CHKERR moab.get_adjacencies(missing_verts, 3, false, missing_adj_elems,
362 moab::Interface::UNION);
363
364 int num_adj_elems = (int)missing_adj_elems.size();
365 std::vector<double> vpos_adj_elems;
366
367 vpos_adj_elems.resize(3 * missing_adj_elems.size());
368 CHKERR moab.get_coords(missing_adj_elems, &vpos_adj_elems[0]);
369
370 // Locate those points in the source mesh
371 tl_ptr->reset();
372 CHKERR mbc.locate_points(&vpos_adj_elems[0], num_adj_elems, 0, toler,
373 tl_ptr.get(), false);
374
375 Range missing_tets;
376 CHKERR find_missing_points(missing_adj_elems, num_adj_elems,
377 vpos_adj_elems, missing_tets);
378 if (missing_tets.size()) {
379 MOFEM_LOG("WORLD", Sev::warning)
380 << missing_tets.size()
381 << "points in target mesh were not located in source mesh. ";
382 }
383
384 std::vector<double> target_data_adj_elems(interp_tag_len * num_adj_elems,
385 0.0);
386
387 for (int itag = 0; itag < interp_tag_len; itag++) {
388 CHKERR create_scalar_tags(src_elems, source_data, itag);
389
390 std::vector<double> target_data_adj_elems_scalar(num_adj_elems, 0.0);
391 CHKERR mbc.interpolate(method, scalar_tag_name,
392 &target_data_adj_elems_scalar[0], tl_ptr.get());
393
394 for (int ielem = 0; ielem < num_adj_elems; ielem++) {
395 target_data_adj_elems[itag + ielem * interp_tag_len] =
396 target_data_adj_elems_scalar[ielem];
397 }
398 }
399
400 CHKERR moab.tag_set_data(output_tag, missing_adj_elems,
401 &target_data_adj_elems[0]);
402
403 // FIXME: add implementation for parallel case
404 for (auto &vert : missing_verts) {
405 Range adj_elems;
406 CHKERR moab.get_adjacencies(&vert, 1, 3, false, adj_elems,
407 moab::Interface::UNION);
408
409 std::vector<double> adj_elems_data(adj_elems.size() * interp_tag_len,
410 0.0);
411 CHKERR moab.tag_get_data(output_tag, adj_elems, &adj_elems_data[0]);
412
413 std::vector<double> vert_data(interp_tag_len, 0.0);
414 for (int itag = 0; itag < interp_tag_len; itag++) {
415 for (int i = 0; i < adj_elems.size(); i++) {
416 vert_data[itag] += adj_elems_data[i * interp_tag_len + itag];
417 }
418 vert_data[itag] /= adj_elems.size();
419 }
420 CHKERR moab.tag_set_data(output_tag, &vert, 1, &vert_data[0]);
421 }
422 }
423
424 CHKERR moab.tag_delete(scalar_tag);
425 CHKERR moab.tag_delete(adj_count_tag);
426
427 if (atom_test == 1 || atom_test == 2) {
428 // Check the integrated stress for the SSLV116 test
429
430 if (interp_order == 1) {
431 // If the data was interpolated to target mesh vertices, we need to
432 // average the vertex values for each 3D element and save on its tag
433
434 // We need to reduce tags for the parallel case
435 std::vector<Tag> tags;
436 tags.push_back(output_tag);
437 pcs[1]->reduce_tags(tags, tags, MPI_SUM, targ_verts);
438
439 for (auto &tet : targ_elems) {
440 Range adj_verts;
441 CHKERR moab.get_connectivity(&tet, 1, adj_verts, true);
442
443 std::vector<double> adj_vert_data(adj_verts.size() * interp_tag_len,
444 0.0);
445 CHKERR moab.tag_get_data(output_tag, adj_verts, &adj_vert_data[0]);
446
447 std::vector<double> tet_data(interp_tag_len, 0.0);
448 for (int itag = 0; itag < interp_tag_len; itag++) {
449 for (int i = 0; i < adj_verts.size(); i++) {
450 tet_data[itag] += adj_vert_data[i * interp_tag_len + itag];
451 }
452 tet_data[itag] /= adj_verts.size();
453 }
454 CHKERR moab.tag_set_data(output_tag, &tet, 1, &tet_data[0]);
455 }
456 }
457
458 std::vector<double> data_integ(interp_tag_len, 0.0);
459 for (auto &tet : targ_elems) {
460
461 std::vector<double> tet_data(interp_tag_len, 0.0);
462 CHKERR moab.tag_get_data(output_tag, &tet, 1, &tet_data[0]);
463
464 const EntityHandle *vert_conn;
465 int vert_num;
466 CHKERR moab.get_connectivity(tet, vert_conn, vert_num, true);
467 std::vector<double> vpos(3 * vert_num);
468 CHKERR moab.get_coords(vert_conn, vert_num, &vpos[0]);
469 double vol = Tools::tetVolume(vpos.data());
470
471 for (int itag = 0; itag < interp_tag_len; itag++) {
472 data_integ[itag] += tet_data[itag] * vol;
473 }
474 }
475
476 std::vector<double> global_data_integ(interp_tag_len, 0.0);
477 MPI_Allreduce(&data_integ[0], &global_data_integ[0], interp_tag_len,
478 MPI_DOUBLE, MPI_SUM, m_field.get_comm());
479
480 std::string temp = "Integrated stress for sslv116 test: ";
481 for (int i = 0; i < 9; ++i) {
482 std::stringstream ss;
483 ss << std::scientific << std::setprecision(3) << global_data_integ[i];
484 temp += ss.str() + " ";
485 }
486 MOFEM_LOG("WORLD", Sev::inform) << temp;
487
488 double non_zero_val = 1.655e12;
489 double non_zero_tol = 5.1e-2;
490 if (interp_order == 1) {
491 non_zero_tol = 1e-3;
492 }
493 std::vector<int> non_zero_inds(3);
494 std::vector<int> zero_inds(6);
495 if (atom_test == 1) {
496 non_zero_inds = {0, 4, 8};
497 zero_inds = {1, 2, 3, 5, 6, 7};
498 } else {
499 non_zero_inds = {0, 1, 2};
500 zero_inds = {3, 4, 5, 6, 7, 8};
501 }
502 bool non_zero_check =
503 all_of(begin(non_zero_inds), end(non_zero_inds), [&](int i) {
504 return abs(global_data_integ[i] - non_zero_val) / non_zero_val <
505 non_zero_tol;
506 });
507 bool zero_check = all_of(begin(zero_inds), end(zero_inds), [&](int i) {
508 return abs(global_data_integ[i]) < 1e-12;
509 });
510 if (!non_zero_check || !zero_check) {
511 SETERRQ(PETSC_COMM_WORLD, MOFEM_ATOM_TEST_INVALID,
512 "Wrong value of the integrated stress");
513 }
514 } else if (atom_test) {
515 SETERRQ(PETSC_COMM_WORLD, MOFEM_NOT_IMPLEMENTED,
516 "Unknown test number: %d", atom_test);
517 }
518
519 Range part_sets;
520 // Only save the target mesh
521 part_sets.insert(roots[1]);
522 std::string new_write_opts;
523 std::ostringstream extra_opt;
524 if (nprocs > 1) {
525 int index = pcs[1]->get_id();
526 extra_opt << ";PARALLEL_COMM=" << index;
527 }
528 new_write_opts = write_opts + extra_opt.str();
529 CHKERR moab.write_file(mesh_out_file, NULL, new_write_opts.c_str(),
530 part_sets);
531 if (0 == rank) {
532 MOFEM_LOG("WORLD", Sev::inform) << "Wrote file " << mesh_out_file;
533 }
534 }
536
538
539 return 0;
540}
#define CATCH_ERRORS
Catch errors.
#define MoFEMFunctionBegin
First executable line of each MoFEM function, used for error handling. Final line of MoFEM functions ...
@ MOFEM_ATOM_TEST_INVALID
Definition definitions.h:40
@ MOFEM_DATA_INCONSISTENCY
Definition definitions.h:31
@ MOFEM_NOT_IMPLEMENTED
Definition definitions.h:32
#define MoFEMFunctionReturn(a)
Last executable line of each PETSc function used for error handling. Replaces return()
#define CHKERR
Inline error check.
#define MOFEM_LOG(channel, severity)
Log.
#define MOFEM_LOG_TAG(channel, tag)
Tag channel.
#define MOFEM_LOG_CHANNEL(channel)
Set and reset channel.
FTensor::Index< 'i', SPACE_DIM > i
static char help[]
static MoFEMErrorCodeGeneric< PetscErrorCode > ierr
static MoFEMErrorCodeGeneric< moab::ErrorCode > rval
void temp(int x, int y=10)
Definition simple.cpp:4
virtual MPI_Comm & get_comm() const =0
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
Deprecated interface functions.
static double tetVolume(const double *coords)
Calculate volume of tetrahedron.
Definition Tools.cpp:30
int atom_test
Atom test.
Definition plastic.cpp:121

Variable Documentation

◆ help

char help[] = "...\n\n"
static

Definition at line 19 of file mesh_data_transfer.cpp.