v0.16.0
Loading...
Searching...
No Matches
Functions | Variables
insert_constraint_prisms.cpp File Reference

Insert prism elements between paired master/slave surface meshsets. More...

#include <MoFEM.hpp>

Go to the source code of this file.

Functions

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

Variables

static char help []
 

Detailed Description

Insert prism elements between paired master/slave surface meshsets.

Meshsets are paired by name, using prefixes: TIE_MASTER_<suffix> TIE_SLAVE_<suffix>

Current limitations:

Definition in file insert_constraint_prisms.cpp.

Function Documentation

◆ main()

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

Definition at line 524 of file insert_constraint_prisms.cpp.

524 {
525
526 MoFEM::Core::Initialize(&argc, &argv, (char *)0, help);
527
528 try {
529
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;
538
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,
549 PETSC_NULLPTR);
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 "
554 "triangles",
555 "", ref_level, &ref_level, PETSC_NULLPTR);
556 CHKERR PetscOptionsReal("-ray_length", "absolute ray length", "",
557 ray_length_option, &ray_length_option,
558 &flg_ray_length);
559 PetscOptionsEnd();
560
561 if (flg_my_file != PETSC_TRUE) {
562 SETERRQ(PETSC_COMM_SELF, MOFEM_INVALID_DATA,
563 "error -my_file (-file_name) (mesh file needed)");
564 }
565 if (ref_level < 1) {
566 SETERRQ(PETSC_COMM_SELF, MOFEM_INVALID_DATA,
567 "-tie_ref_level must be greater than or equal to 1");
568 }
569 if (flg_ray_length == PETSC_TRUE && ray_length_option <= 0) {
570 SETERRQ(PETSC_COMM_SELF, MOFEM_INVALID_DATA,
571 "-ray_length must be greater than 0");
572 }
573
574 moab::Core mb_instance;
575 moab::Interface &moab = mb_instance;
576 ParallelComm *pcomm = ParallelComm::get_pcomm(&moab, MYPCOMM_INDEX);
577 if (pcomm == NULL)
578 pcomm = new ParallelComm(&moab, PETSC_COMM_WORLD);
579
580 CHKERR moab.load_file(mesh_file_name);
581
582 MoFEM::Core core(moab);
583 MoFEM::Interface &m_field = core;
584
585 Range tets;
586 CHKERR moab.get_entities_by_type(0, MBTET, tets, false);
587 if (tets.empty()) {
588 SETERRQ(PETSC_COMM_SELF, MOFEM_NOT_IMPLEMENTED,
589 "No tetrahedra found. Only tet meshes are currently supported");
590 }
591
592 Range other_vols;
593 CHKERR moab.get_entities_by_dimension(0, 3, other_vols, false);
594 other_vols = subtract(other_vols, tets);
595 if (!other_vols.empty()) {
596 SETERRQ(PETSC_COMM_SELF, MOFEM_NOT_IMPLEMENTED,
597 "Only tetrahedral volume meshes are currently supported");
598 }
599
600 Range tet_skin;
601 {
602 Skinner skinner(&moab);
603 CHKERR skinner.find_skin(0, tets, false, tet_skin);
604 tet_skin = tet_skin.subset_by_type(MBTRI);
605 }
606
607 const std::string master_prefix_str(master_prefix);
608 const std::string slave_prefix_str(slave_prefix);
609
610 std::map<std::string, const CubitMeshSets *> master_sets;
611 std::map<std::string, const CubitMeshSets *> slave_sets;
612
613 for (_IT_CUBITMESHSETS_FOR_LOOP_(m_field, it)) {
614 const std::string name = it->getName();
615
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) {
619 SETERRQ(PETSC_COMM_SELF, MOFEM_DATA_INCONSISTENCY,
620 "More than one master meshset uses suffix %s", suffix.c_str());
621 }
622 }
623
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) {
627 SETERRQ(PETSC_COMM_SELF, MOFEM_DATA_INCONSISTENCY,
628 "More than one slave meshset uses suffix %s", suffix.c_str());
629 }
630 }
631 }
632
633 if (master_sets.empty()) {
634 SETERRQ(PETSC_COMM_SELF, MOFEM_NOT_FOUND,
635 "No master meshsets found with prefix %s",
636 master_prefix_str.c_str());
637 }
638
639 for (const auto &slave_pair : slave_sets) {
640 const auto &suffix = slave_pair.first;
641 if (master_sets.find(suffix) == master_sets.end()) {
642 SETERRQ(PETSC_COMM_SELF, MOFEM_DATA_INCONSISTENCY,
643 "Found slave meshset with suffix %s but no matching master "
644 "meshset",
645 suffix.c_str());
646 }
647 }
648
649 PrismsFromSurfaceInterface *prisms_from_surface = nullptr;
650 CHKERR m_field.getInterface(prisms_from_surface);
651
652 MatrixDouble reference_child_centroids;
653 CHKERR collect_virtual_refined_triangle_centroids(ref_level,
654 reference_child_centroids);
655
656 Range all_prisms;
657
658 for (const auto &[suffix, master_ptr] : master_sets) {
659 auto slave_it = slave_sets.find(suffix);
660 if (slave_it == slave_sets.end()) {
661 SETERRQ(PETSC_COMM_SELF, MOFEM_DATA_INCONSISTENCY,
662 "Found master meshset with suffix %s but no matching slave "
663 "meshset",
664 suffix.c_str());
665 }
666
667 const auto *slave_ptr = slave_it->second;
668
669 if (master_ptr->getBcType() != slave_ptr->getBcType()) {
670 SETERRQ(PETSC_COMM_SELF, MOFEM_DATA_INCONSISTENCY,
671 "Master/slave meshset types differ for suffix %s",
672 suffix.c_str());
673 }
674
675 SurfaceMeshsetData master_surface;
676 CHKERR validate_surface_meshset(moab, *master_ptr, tet_skin,
677 master_surface);
678
679 SurfaceMeshsetData slave_surface;
680 CHKERR validate_surface_meshset(moab, *slave_ptr, tet_skin, slave_surface);
681
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),
687 bbox_diag);
688
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.);
696
697 OrientedBoxTreeTool master_tree(&moab, "ROOTSET_CONSTRAINT_PRISMS", true);
698 EntityHandle master_root = 0;
699 CHKERR master_tree.build(master_surface.tris, master_root);
700
701 Range pair_prisms;
702 size_t unmatched_slave_tris = 0;
703
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);
707
708 std::array<double, 9> slave_coords;
709 CHKERR get_triangle_coords(moab, slave_tri, slave_coords);
710 MatrixDouble child_centroids;
711 CHKERR map_reference_centroids_to_triangle(reference_child_centroids,
712 slave_coords,
713 child_centroids);
714
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,
722 ray_length, ray_tol,
723 hit_master_tris);
724 }
725
726 if (hit_master_tris.empty()) {
727 ++unmatched_slave_tris;
728 continue;
729 }
730
731 for (auto master_tri : hit_master_tris) {
732 EntityHandle prism = 0;
733 CHKERR create_prism_from_triangle_pair(*prisms_from_surface, slave_tri,
734 master_tri, prism);
735 pair_prisms.insert(prism);
736 }
737 }
738
739 CHKERR prisms_from_surface->updateMeshestByEdgeBlock(pair_prisms);
740 CHKERR prisms_from_surface->updateMeshestByTriBlock(pair_prisms);
741
742 CHKERR set_surface_meshset_triangles(moab, master_surface,
743 master_surface.tris);
744 CHKERR set_surface_meshset_triangles(moab, slave_surface,
745 slave_surface.tris);
746
747 all_prisms.merge(pair_prisms);
748
749 MOFEM_LOG("WORLD", Sev::inform)
750 << "Inserted " << pair_prisms.size()
751 << " prisms for master/slave suffix " << suffix;
752 if (master_tri_count > slave_tri_count) {
753 MOFEM_LOG("WORLD", Sev::warning)
754 << "Master surface has more triangles than slave surface for "
755 "suffix "
756 << suffix << " (" << master_tri_count << " > "
757 << slave_tri_count
758 << "); consider renaming the TIE blocks so the finer surface is "
759 "named TIE_SLAVE_"
760 << suffix;
761 }
762 MOFEM_LOG("WORLD", Sev::warning)
763 << "Skipped " << unmatched_slave_tris
764 << " slave triangles without master hits for suffix "
765 << suffix;
766 }
767
768 MOFEM_LOG("WORLD", Sev::inform)
769 << "Inserted total " << all_prisms.size() << " constraint prisms";
770
771 CHKERR moab.write_file(mesh_out_file);
772 }
774
776
777 return 0;
778}
#define CATCH_ERRORS
Catch errors.
#define MYPCOMM_INDEX
default communicator number PCOMM
@ MOFEM_NOT_FOUND
Definition definitions.h:33
@ MOFEM_DATA_INCONSISTENCY
Definition definitions.h:31
@ MOFEM_INVALID_DATA
Definition definitions.h:36
@ MOFEM_NOT_IMPLEMENTED
Definition definitions.h:32
#define CHKERR
Inline error check.
#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.
static char help[]
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.
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.

Variable Documentation

◆ help

char help[]
static
Initial value:
=
"Insert constraint prisms between paired master/slave triangle meshsets.\n"
"\n"
"Pairs are detected by meshset names:\n"
" TIE_MASTER_<suffix>\n"
" TIE_SLAVE_<suffix>\n"
"\n"
"Prisms are always created from the SLAVE surface.\n"
"\n"
"If the MASTER surface has more triangles than the SLAVE surface, the tool\n"
"only warns and suggests renaming the TIE blocks so the finer surface is\n"
"named SLAVE.\n"
"\n"
"Virtual refinement:\n"
" - -tie_ref_level N recursively refines each effective slave triangle N times\n"
" in-memory using 1-to-4 midpoint subdivision before ray casting\n"
" - -ray_length value overrides the automatic ray length\n"
"\n"
"Current limitations:\n"
" - only tet meshes are supported\n"
" - only triangle surface meshsets are supported\n\n"

Definition at line 17 of file insert_constraint_prisms.cpp.