18 "Insert constraint prisms between paired master/slave triangle meshsets.\n"
20 "Pairs are detected by meshset names:\n"
21 " TIE_MASTER_<suffix>\n"
22 " TIE_SLAVE_<suffix>\n"
24 "Prisms are always created from the SLAVE surface.\n"
26 "If the MASTER surface has more triangles than the SLAVE surface, the tool\n"
27 "only warns and suggests renaming the TIE blocks so the finer surface is\n"
30 "Virtual refinement:\n"
31 " - -tie_ref_level N recursively refines each effective slave triangle N times\n"
32 " in-memory using 1-to-4 midpoint subdivision before ray casting\n"
33 " - -ray_length value overrides the automatic ray length\n"
35 "Current limitations:\n"
36 " - only tet meshes are supported\n"
37 " - only triangle surface meshsets are supported\n\n";
45struct SurfaceMeshsetData {
51constexpr std::array<std::array<int, 3>, 3> TRI_PERMUTATIONS = {{
58 moab::Interface &moab,
const SurfaceMeshsetData &
surface,
59 const Range &desired_tris) {
64 "Can not update triangles for null meshset pointer");
67 const auto meshset =
surface.meshsetPtr->meshset;
74 CHKERR moab.get_entities_by_dimension(meshset, 3, vols,
true);
76 CHKERR moab.remove_entities(meshset, vols);
79 CHKERR moab.get_entities_by_dimension(meshset, 2, faces,
true);
80 Range current_tris = faces.subset_by_type(MBTRI);
81 Range other_faces = subtract(faces, current_tris);
82 if (!other_faces.empty())
83 CHKERR moab.remove_entities(meshset, other_faces);
85 Range tris_to_remove = subtract(current_tris, desired_tris);
86 if (!tris_to_remove.empty())
87 CHKERR moab.remove_entities(meshset, tris_to_remove);
89 Range tris_to_add = subtract(desired_tris, current_tris);
90 if (!tris_to_add.empty())
91 CHKERR moab.add_entities(meshset, tris_to_add);
101 CHKERR moab.get_connectivity(ents, verts,
true);
104 "Can not calculate bounding box for empty vertex range");
106 std::vector<double> coords(3 * verts.size());
107 CHKERR moab.get_coords(verts, coords.data());
109 double min_c[
SPACE_DIM] = {std::numeric_limits<double>::max(),
110 std::numeric_limits<double>::max(),
111 std::numeric_limits<double>::max()};
112 double max_c[
SPACE_DIM] = {-std::numeric_limits<double>::max(),
113 -std::numeric_limits<double>::max(),
114 -std::numeric_limits<double>::max()};
116 for (
size_t vv = 0; vv != verts.size(); ++vv) {
117 for (
int dd = 0; dd != 3; ++dd) {
118 min_c[dd] = std::min(min_c[dd], coords[3 * vv + dd]);
119 max_c[dd] = std::max(max_c[dd], coords[3 * vv + dd]);
124 auto t_max_c = getFTensor1FromPtr<SPACE_DIM>(max_c);
125 auto t_min_c = getFTensor1FromPtr<SPACE_DIM>(min_c);
126 t_diag(
i) = t_max_c(
i) - t_min_c(
i);
133 const Range &tet_skin,
134 SurfaceMeshsetData &surface_data) {
137 surface_data.meshsetPtr = &meshset_data;
138 surface_data.name = meshset_data.
getName();
141 CHKERR moab.get_entities_by_dimension(meshset_data.
meshset, 3, vols,
true);
144 "Meshset %s contains 3D entities. Only surface meshsets are "
146 surface_data.name.c_str());
150 CHKERR moab.get_entities_by_dimension(meshset_data.
meshset, 2, faces,
true);
153 "Meshset %s does not contain surface entities",
154 surface_data.name.c_str());
157 surface_data.tris = faces.subset_by_type(MBTRI);
158 const Range other_faces = subtract(faces, surface_data.tris);
159 if (!other_faces.empty()) {
161 "Meshset %s contains non-triangle surface entities. Only "
162 "triangles are supported",
163 surface_data.name.c_str());
166 const Range skin_tris = intersect(surface_data.tris, tet_skin);
167 if (skin_tris.size() != surface_data.tris.size()) {
169 "Meshset %s contains triangles that are not on the tet skin",
170 surface_data.name.c_str());
176MoFEMErrorCode get_coords_centroid(
const double *coords,
const int num_nodes,
177 std::array<double, 3> ¢roid) {
179 centroid = {0., 0., 0.};
180 for (
int nn = 0; nn != num_nodes; ++nn)
182 centroid[dd] += coords[
SPACE_DIM * nn + dd] / num_nodes;
187 const EntityHandle tri,
188 std::array<EntityHandle, 3> *tri_nodes,
189 std::array<double, SPACE_DIM> &outward_normal) {
192 const EntityHandle *conn =
nullptr;
194 CHKERR moab.get_connectivity(tri, conn, num_nodes,
true);
197 "Only 3-node triangles are supported");
200 for (
int ii = 0; ii != 3; ++ii)
201 (*tri_nodes)[ii] = conn[ii];
204 double tri_coords[9];
205 CHKERR moab.get_coords(conn, 3, tri_coords);
207 std::array<double, SPACE_DIM> centroid;
208 CHKERR get_coords_centroid(tri_coords, 3, centroid);
209 auto t_centroid = getFTensor1FromPtr<SPACE_DIM>(centroid.data());
211 auto t_outward_normal = getFTensor1FromPtr<SPACE_DIM>(outward_normal.data());
213 const double tri_norm = t_outward_normal.l2();
214 if (tri_norm <= std::numeric_limits<double>::epsilon()) {
216 "Triangle %lu has zero normal", tri);
218 t_outward_normal(
i) /= tri_norm;
221 CHKERR moab.get_adjacencies(&tri, 1, 3,
false, adj_tets);
222 adj_tets = adj_tets.subset_by_type(MBTET);
223 if (adj_tets.size() != 1) {
225 "Triangle %lu is expected to have exactly one adjacent tet", tri);
228 const EntityHandle tet = adj_tets[0];
229 const EntityHandle *tet_conn =
nullptr;
230 int tet_num_nodes = 0;
231 CHKERR moab.get_connectivity(tet, tet_conn, tet_num_nodes,
true);
232 if (tet_num_nodes != 4)
234 "Only 4-node tets are supported");
236 double tet_coords[12];
237 CHKERR moab.get_coords(tet_conn, 4, tet_coords);
238 std::array<double, SPACE_DIM> tet_centroid;
239 CHKERR get_coords_centroid(tet_coords, 4, tet_centroid);
240 auto t_tet_centroid = getFTensor1FromPtr<SPACE_DIM>(tet_centroid.data());
243 t_delta(
i) = t_tet_centroid(
i) - t_centroid(
i);
245 if (t_outward_normal(
i) * t_delta(
i) > 0)
246 t_outward_normal(
i) *= -1.;
251MoFEMErrorCode get_triangle_coords(moab::Interface &moab,
const EntityHandle tri,
252 std::array<double, 9> &coords) {
254 const EntityHandle *conn =
nullptr;
256 CHKERR moab.get_connectivity(tri, conn, num_nodes,
true);
257 if (num_nodes != 3) {
259 "Only 3-node triangles are supported");
261 CHKERR moab.get_coords(conn, 3, coords.data());
266 const int ref_level,
MatrixDouble &reference_child_centroids) {
270 double base_coords[] = {0, 0, 0, 1, 0, 0, 0, 1, 0};
271 EntityHandle nodes[3];
272 for (
int nn = 0; nn != 3; ++nn)
273 CHKERR moab_ref.create_vertex(&base_coords[3 * nn], nodes[nn]);
275 CHKERR moab_ref.create_element(MBTRI, nodes, 3, tri);
283 Range tris(tri, tri);
285 CHKERR m_field_ref.
get_moab().get_adjacencies(tris, 1,
true, edges,
286 moab::Interface::UNION);
291 const bool debug =
true;
293 const bool debug =
false;
296 for (
int ll = 0; ll != ref_level; ++ll) {
298 CHKERR bit_ref_manager->getEntitiesByTypeAndRefLevel(
302 CHKERR moab_ref.get_adjacencies(current_tris, 1,
true, edges,
303 moab::Interface::UNION);
304 CHKERR m_ref->addVerticesInTheMiddleOfEdges(edges,
bit);
309 CHKERR bit_ref_manager->getEntitiesByTypeAndRefLevel(
311 reference_child_centroids.resize(refined_tris.size(),
SPACE_DIM,
false);
313 for (
auto child_tri : refined_tris) {
314 std::array<double, 9> child_coords;
315 std::array<double, 3> child_centroid;
316 CHKERR get_triangle_coords(moab_ref, child_tri, child_coords);
317 CHKERR get_coords_centroid(child_coords.data(), 3, child_centroid);
319 reference_child_centroids(rr, dd) = child_centroid[dd];
328 const std::array<double, 9> &tri_coords,
MatrixDouble &child_centroids) {
331 child_centroids.resize(reference_child_centroids.size1(),
SPACE_DIM,
false);
332 std::array<double, 9> mutable_coords = tri_coords;
333 auto t_p0 = getFTensor1FromPtr<SPACE_DIM>(&mutable_coords[0]);
334 auto t_p1 = getFTensor1FromPtr<SPACE_DIM>(&mutable_coords[3]);
335 auto t_p2 = getFTensor1FromPtr<SPACE_DIM>(&mutable_coords[6]);
337 for (
size_t rr = 0; rr != reference_child_centroids.size1(); ++rr) {
338 const double n1 = reference_child_centroids(rr, 0);
339 const double n2 = reference_child_centroids(rr, 1);
340 const double n0 = 1. - n1 - n2;
341 std::array<double, 3> child_centroid = {0., 0., 0.};
342 auto t_child_centroid =
343 getFTensor1FromPtr<SPACE_DIM>(child_centroid.data());
344 t_child_centroid(
i) = n0 * t_p0(
i) + n1 * t_p1(
i) + n2 * t_p2(
i);
346 child_centroids(rr, dd) = child_centroid[dd];
353 OrientedBoxTreeTool &tree,
const EntityHandle root_set,
354 const std::array<double, 3> &source_centroid,
355 const std::array<double, 3> &source_normal,
const double ray_length,
356 const double ray_tol,
357 std::set<EntityHandle> &target_tris) {
360 auto collect_closest_hit = [&](
const double ray_sign, EntityHandle &closest_tri,
361 double &closest_dist) {
364 std::vector<double> distances;
365 std::vector<EntityHandle> facets;
366 double ray_point[
SPACE_DIM] = {source_centroid[0], source_centroid[1],
368 double ray_dir[
SPACE_DIM] = {ray_sign * source_normal[0],
369 ray_sign * source_normal[1],
370 ray_sign * source_normal[2]};
371 double max_ray_length = ray_length;
373 CHKERR tree.ray_intersect_triangles(distances, facets, root_set, ray_tol,
374 ray_point, ray_dir, &max_ray_length);
377 closest_dist = std::numeric_limits<double>::max();
378 for (
size_t ii = 0; ii != facets.size(); ++ii) {
379 const double dist = distances[ii];
382 if (dist < closest_dist) {
384 closest_tri = facets[ii];
391 EntityHandle forward_tri = 0;
392 EntityHandle reverse_tri = 0;
393 double forward_dist = std::numeric_limits<double>::max();
394 double reverse_dist = std::numeric_limits<double>::max();
395 CHKERR collect_closest_hit(1., forward_tri, forward_dist);
396 CHKERR collect_closest_hit(-1., reverse_tri, reverse_dist);
398 if (forward_dist <= reverse_dist) {
400 target_tris.insert(forward_tri);
401 }
else if (reverse_tri) {
402 target_tris.insert(reverse_tri);
409 const std::array<EntityHandle, 3> &master_nodes,
410 const std::array<EntityHandle, 3> &slave_nodes,
411 std::array<int, 3> &perm) {
414 double master_coords[9];
415 double slave_coords[9];
416 CHKERR moab.get_coords(master_nodes.data(), 3, master_coords);
417 CHKERR moab.get_coords(slave_nodes.data(), 3, slave_coords);
419 double best_score = std::numeric_limits<double>::max();
422 for (
const auto &candidate_perm : TRI_PERMUTATIONS) {
425 for (
int ii = 0; ii != 3; ++ii) {
426 auto t_master_c = getFTensor1FromPtr<3>(&master_coords[3 * ii]);
428 getFTensor1FromPtr<3>(&slave_coords[3 * candidate_perm[ii]]);
430 t_delta(
j) = t_master_c(
j) - t_slave_c(
j);
431 score += t_delta(
j) * t_delta(
j);
434 if (score < best_score) {
436 perm = candidate_perm;
443 "Could not find a vertex mapping between paired master and slave "
452 const EntityHandle target_tri, EntityHandle &prism) {
457 std::array<EntityHandle, 3> source_nodes;
458 std::array<double, SPACE_DIM> source_normal;
459 CHKERR get_skin_triangle_data(moab, source_tri, &source_nodes, source_normal);
460 auto t_source_normal = getFTensor1FromPtr<SPACE_DIM>(source_normal.data());
462 const EntityHandle *target_conn =
nullptr;
463 int target_num_nodes = 0;
464 CHKERR moab.get_connectivity(target_tri, target_conn, target_num_nodes,
true);
465 if (target_num_nodes != 3)
467 "Only 3-node target triangles are supported");
469 const EntityHandle *source_conn =
nullptr;
470 int source_num_nodes = 0;
471 CHKERR moab.get_connectivity(source_tri, source_conn, source_num_nodes,
true);
472 if (source_num_nodes != 3)
474 "Only 3-node source triangles are supported");
476 double source_coords[9];
477 CHKERR moab.get_coords(source_conn, 3, source_coords);
478 std::array<double, SPACE_DIM> raw_source_normal;
479 auto t_raw_source_normal =
480 getFTensor1FromPtr<SPACE_DIM>(raw_source_normal.data());
483 std::array<EntityHandle, 3> prism_source_nodes = source_nodes;
484 if (t_raw_source_normal(
i) * t_source_normal(
i) < 0)
485 std::swap(prism_source_nodes[1], prism_source_nodes[2]);
487 std::array<EntityHandle, 3> target_nodes = {target_conn[0], target_conn[1],
489 std::array<int, 3> target_perm = {0, 1, 2};
490 CHKERR match_triangle_vertices(moab, prism_source_nodes, target_nodes,
493 std::array<EntityHandle, 3> prism_target_nodes = {
494 target_nodes[target_perm[0]], target_nodes[target_perm[1]],
495 target_nodes[target_perm[2]]};
498 prism_source_nodes.data(), prism_target_nodes.data(),
501 int side_number = -1;
505 CHKERR moab.side_number(prism, source_tri, side_number, sense, offset);
506 if (side_number != 3) {
508 "Created prism %lu does not use source triangle %lu as side 3",
512 CHKERR moab.side_number(prism, target_tri, side_number, sense, offset);
513 if (side_number != 4) {
515 "Created prism %lu does not use target triangle %lu as side 4",
524int main(
int argc,
char *argv[]) {
530 char mesh_file_name[255] =
"mesh.h5m";
531 char mesh_out_file[255] =
"out.h5m";
532 char master_prefix[255] =
"TIE_MASTER_";
533 char slave_prefix[255] =
"TIE_SLAVE_";
534 PetscBool flg_my_file = PETSC_FALSE;
535 PetscBool flg_ray_length = PETSC_FALSE;
536 PetscInt ref_level = 1;
537 PetscReal ray_length_option = 0;
539 PetscOptionsBegin(PETSC_COMM_WORLD,
"",
"Insert constraint prisms",
"none");
540 CHKERR PetscOptionsString(
"-my_file",
"mesh file name",
"",
"mesh.h5m",
541 mesh_file_name, 255, &flg_my_file);
542 if (flg_my_file != PETSC_TRUE)
543 CHKERR PetscOptionsString(
"-file_name",
"mesh file name",
"",
"mesh.h5m",
544 mesh_file_name, 255, &flg_my_file);
545 CHKERR PetscOptionsString(
"-output_file",
"output mesh file name",
"",
546 "out.h5m", mesh_out_file, 255, PETSC_NULLPTR);
547 CHKERR PetscOptionsString(
"-master_prefix",
"master meshset name prefix",
548 "",
"TIE_MASTER_", master_prefix, 255,
550 CHKERR PetscOptionsString(
"-slave_prefix",
"slave meshset name prefix",
"",
551 "TIE_SLAVE_", slave_prefix, 255, PETSC_NULLPTR);
552 CHKERR PetscOptionsInt(
"-tie_ref_level",
553 "virtual recursive refinement level on slave "
555 "", ref_level, &ref_level, PETSC_NULLPTR);
556 CHKERR PetscOptionsReal(
"-ray_length",
"absolute ray length",
"",
557 ray_length_option, &ray_length_option,
561 if (flg_my_file != PETSC_TRUE) {
563 "error -my_file (-file_name) (mesh file needed)");
567 "-tie_ref_level must be greater than or equal to 1");
569 if (flg_ray_length == PETSC_TRUE && ray_length_option <= 0) {
571 "-ray_length must be greater than 0");
574 moab::Core mb_instance;
575 moab::Interface &moab = mb_instance;
576 ParallelComm *pcomm = ParallelComm::get_pcomm(&moab,
MYPCOMM_INDEX);
578 pcomm =
new ParallelComm(&moab, PETSC_COMM_WORLD);
580 CHKERR moab.load_file(mesh_file_name);
586 CHKERR moab.get_entities_by_type(0, MBTET, tets,
false);
589 "No tetrahedra found. Only tet meshes are currently supported");
593 CHKERR moab.get_entities_by_dimension(0, 3, other_vols,
false);
594 other_vols = subtract(other_vols, tets);
595 if (!other_vols.empty()) {
597 "Only tetrahedral volume meshes are currently supported");
602 Skinner skinner(&moab);
603 CHKERR skinner.find_skin(0, tets,
false, tet_skin);
604 tet_skin = tet_skin.subset_by_type(MBTRI);
607 const std::string master_prefix_str(master_prefix);
608 const std::string slave_prefix_str(slave_prefix);
610 std::map<std::string, const CubitMeshSets *> master_sets;
611 std::map<std::string, const CubitMeshSets *> slave_sets;
614 const std::string name = it->getName();
616 if (name.compare(0, master_prefix_str.size(), master_prefix_str) == 0) {
617 const auto suffix = name.substr(master_prefix_str.size());
618 if (!master_sets.emplace(suffix, &*it).second) {
620 "More than one master meshset uses suffix %s", suffix.c_str());
624 if (name.compare(0, slave_prefix_str.size(), slave_prefix_str) == 0) {
625 const auto suffix = name.substr(slave_prefix_str.size());
626 if (!slave_sets.emplace(suffix, &*it).second) {
628 "More than one slave meshset uses suffix %s", suffix.c_str());
633 if (master_sets.empty()) {
635 "No master meshsets found with prefix %s",
636 master_prefix_str.c_str());
639 for (
const auto &slave_pair : slave_sets) {
640 const auto &suffix = slave_pair.first;
641 if (master_sets.find(suffix) == master_sets.end()) {
643 "Found slave meshset with suffix %s but no matching master "
653 CHKERR collect_virtual_refined_triangle_centroids(ref_level,
654 reference_child_centroids);
658 for (
const auto &[suffix, master_ptr] : master_sets) {
659 auto slave_it = slave_sets.find(suffix);
660 if (slave_it == slave_sets.end()) {
662 "Found master meshset with suffix %s but no matching slave "
667 const auto *slave_ptr = slave_it->second;
669 if (master_ptr->getBcType() != slave_ptr->getBcType()) {
671 "Master/slave meshset types differ for suffix %s",
675 SurfaceMeshsetData master_surface;
676 CHKERR validate_surface_meshset(moab, *master_ptr, tet_skin,
679 SurfaceMeshsetData slave_surface;
680 CHKERR validate_surface_meshset(moab, *slave_ptr, tet_skin, slave_surface);
682 const auto master_tri_count = master_surface.tris.size();
683 const auto slave_tri_count = slave_surface.tris.size();
684 double bbox_diag = 0;
685 CHKERR get_range_bbox_diag(moab,
686 unite(master_surface.tris, slave_surface.tris),
689 const double geom_eps =
690 std::max(1e-12 * std::max(1., bbox_diag), 10. *
691 std::numeric_limits<double>::epsilon());
692 const double ray_tol = geom_eps;
693 const double ray_length =
694 (flg_ray_length == PETSC_TRUE) ? ray_length_option
695 : std::max(10. * bbox_diag, 1.);
697 OrientedBoxTreeTool master_tree(&moab,
"ROOTSET_CONSTRAINT_PRISMS",
true);
698 EntityHandle master_root = 0;
699 CHKERR master_tree.build(master_surface.tris, master_root);
702 size_t unmatched_slave_tris = 0;
704 for (
auto slave_tri : slave_surface.tris) {
705 std::array<double, SPACE_DIM> slave_normal;
706 CHKERR get_skin_triangle_data(moab, slave_tri,
nullptr, slave_normal);
708 std::array<double, 9> slave_coords;
709 CHKERR get_triangle_coords(moab, slave_tri, slave_coords);
711 CHKERR map_reference_centroids_to_triangle(reference_child_centroids,
715 std::set<EntityHandle> hit_master_tris;
716 for (
size_t rr = 0; rr != child_centroids.size1(); ++rr) {
717 std::array<double, 3> child_centroid = {
718 child_centroids(rr, 0), child_centroids(rr, 1),
719 child_centroids(rr, 2)};
720 CHKERR collect_target_triangles(master_tree, master_root,
721 child_centroid, slave_normal,
726 if (hit_master_tris.empty()) {
727 ++unmatched_slave_tris;
731 for (
auto master_tri : hit_master_tris) {
732 EntityHandle prism = 0;
733 CHKERR create_prism_from_triangle_pair(*prisms_from_surface, slave_tri,
735 pair_prisms.insert(prism);
742 CHKERR set_surface_meshset_triangles(moab, master_surface,
743 master_surface.tris);
744 CHKERR set_surface_meshset_triangles(moab, slave_surface,
747 all_prisms.merge(pair_prisms);
750 <<
"Inserted " << pair_prisms.size()
751 <<
" prisms for master/slave suffix " << suffix;
752 if (master_tri_count > slave_tri_count) {
754 <<
"Master surface has more triangles than slave surface for "
756 << suffix <<
" (" << master_tri_count <<
" > "
758 <<
"); consider renaming the TIE blocks so the finer surface is "
763 <<
"Skipped " << unmatched_slave_tris
764 <<
" slave triangles without master hits for suffix "
769 <<
"Inserted total " << all_prisms.size() <<
" constraint prisms";
771 CHKERR moab.write_file(mesh_out_file);
#define FTENSOR_INDEX(DIM, I)
#define CATCH_ERRORS
Catch errors.
#define MoFEMFunctionReturnHot(a)
Last executable line of each PETSc function used for error handling. Replaces return()
#define MYPCOMM_INDEX
default communicator number PCOMM
#define MoFEMFunctionBegin
First executable line of each MoFEM function, used for error handling. Final line of MoFEM functions ...
@ MOFEM_DATA_INCONSISTENCY
#define MoFEMFunctionReturn(a)
Last executable line of each PETSc function used for error handling. Replaces return()
#define CHKERR
Inline error check.
#define MoFEMFunctionBeginHot
First executable line of each MoFEM function, used for error handling. Final line of MoFEM functions ...
#define MOFEM_LOG(channel, severity)
Log.
#define _IT_CUBITMESHSETS_FOR_LOOP_(MESHSET_MANAGER, IT)
Iterator that loops over all the Cubit MeshSets in a moFEM field.
FTensor::Index< 'i', SPACE_DIM > i
FTensor::Index< 'j', 3 > j
PetscErrorCode MoFEMErrorCode
MoFEM/PETSc error code.
std::bitset< BITREFLEVEL_SIZE > BitRefLevel
Bit structure attached to each entity identifying to what mesh entity is attached.
implementation of Data Operators for Forces and Sources
virtual moab::Interface & get_moab()=0
static MoFEMErrorCode Initialize(int *argc, char ***args, const char file[], const char help[])
Initializes the MoFEM database PETSc, MOAB and MPI.
static MoFEMErrorCode Finalize()
Checks for options to be called at the conclusion of the program.
this struct keeps basic methods for moab meshset about material and boundary conditions
std::string getName() const
get name of block, sideset etc. (this is set in Cubit block properties)
Deprecated interface functions.
Mesh refinement interface.
merge node from two bit levels
MoFEMErrorCode createPrism(const EntityHandle tri3_nodes[3], const EntityHandle tri4_nodes[3], const SwapType swap_type, EntityHandle &prism)
Create a prism from two triangle node triplets.
MoFEMErrorCode updateMeshestByEdgeBlock(const Range &prisms)
Add quads to bockset.
MoFEMErrorCode updateMeshestByTriBlock(const Range &prisms)
Add prism to bockset.
MoFEMErrorCode getInterface(IFACE *&iface) const
Get interface reference to pointer of interface.