68 "Use BIH for finding initial candidates, then continue by prolongation.")
70 "Use BIH for finding all candidates.")
72 "Use bounding boxes for finding initial candidates, then continue by prolongation.")
77 return IT::Record(
"Mesh",
"Record with mesh related data." )
80 "Input file with mesh description.")
82 "List of additional region and region set definitions not contained in the mesh. " 83 "There are three region sets implicitly defined:\n\n" 84 "- ALL (all regions of the mesh)\n" 85 "- .BOUNDARY (all boundary regions)\n" 86 "- BULK (all bulk regions)")
90 IT::Default(
"\"BIHsearch\""),
"Search algorithm for element intersections.")
92 "Maximal snapping distance from Mesh in various search operations. In particular is used " 93 "in ObservePoint to find closest mesh element and in FieldFormula to find closest surface " 94 "element in plan view (Z projection).")
96 "Output file with neighboring data from mesh.")
123 istringstream is(
"{mesh_file=\"\"}");
137 MessageOut() <<
"Opening raw ngh output: " << raw_output_file_path <<
"\n";
178 for(
int i=0; i < 3; i++) {
180 for(
int j=0; j < i+2; j++)
184 for (
unsigned int sid=0; sid<RefElement<1>::n_sides; sid++)
185 for (
unsigned int nid=0; nid<RefElement<1>::n_nodes_per_side; nid++)
188 for (
unsigned int sid=0; sid<RefElement<2>::n_sides; sid++)
189 for (
unsigned int nid=0; nid<RefElement<2>::n_nodes_per_side; nid++)
192 for (
unsigned int sid=0; sid<RefElement<3>::n_sides; sid++)
193 for (
unsigned int nid=0; nid<RefElement<3>::n_nodes_per_side; nid++)
200 if (edg.side_)
delete[] edg.side_;
202 for (
unsigned int idx=0; idx <
bulk_size_; idx++) {
208 for(
unsigned int idx=bulk_size_; idx <
element_vec_.size(); idx++) {
236 unsigned int li, count = 0;
238 for (li=0; li<ele->n_nodes(); li++) {
260 switch (elm->dim()) {
276 for (
auto elem_to_region : map) {
292 if (ele.quality_measure_smooth(ele.side(0)) < 0.001)
WarningOut().fmt(
"Bad quality (<0.001) of the element {}.\n", ele.idx());
307 id_4_old[i++] = ele.idx();
336 for (
unsigned int n=0; n<ele->n_nodes(); n++)
340 stable_sort(n->begin(), n->end());
350 if (nodes_list.size() == 0) {
351 intersection_element_list.clear();
352 }
else if (nodes_list.size() == 1) {
359 it1=set_intersection(
362 intersection_element_list.begin());
363 intersection_element_list.resize(it1-intersection_element_list.begin());
365 for(;it2<nodes_list.end();++it2) {
366 it1=set_intersection(
367 intersection_element_list.begin(), intersection_element_list.end(),
369 intersection_element_list.begin());
370 intersection_element_list.resize(it1-intersection_element_list.begin());
377 bool is_neighbour =
false;
385 if (is_neighbour)
xprintf(
UsrErr,
"Too matching elements id: %d and id: %d in the same mesh.\n",
392 element_list.resize( e_dest - element_list.begin());
400 && find(side_nodes.begin(), side_nodes.end(), si->
node(ni).idx() ) != side_nodes.end() ) ni++;
401 return ( ni == si->
n_nodes() );
416 .error(
"Temporary structure of boundary element data is not empty. Did you call create_boundary_elements?");
420 unsigned int ngh_element_idx, last_edge_idx;
422 neighbour.
mesh_ =
this;
436 side_nodes.resize(bc_ele->
n_nodes());
437 for (
unsigned n=0; n<bc_ele->
n_nodes(); n++) side_nodes[n] = bc_ele->
node_idx(n);
441 xprintf(
UsrErr,
"Boundary element (id: %d) match a regular element (id: %d) of lower dimension.\n",
444 if (intersection_list.size() == 0) {
446 WarningOut().fmt(
"Lonely boundary element, id: {}, region: {}, dimension {}.\n",
450 last_edge_idx=
edges.size();
451 edges.resize(last_edge_idx+1);
452 edg = &(
edges.back() );
454 edg->
side_ =
new struct SideIter[ intersection_list.size() ];
468 for (
unsigned int ecs=0; ecs<elem->
n_sides(); ecs++) {
474 int new_bc_ele_idx=i;
475 THROW( ExcDuplicateBoundary()
476 << EI_ElemLast(this->
elem_index(last_bc_ele_idx))
478 << EI_ElemNew(this->
elem_index(new_bc_ele_idx))
501 for (
unsigned int s=0; s<e->n_sides(); s++)
508 side_nodes.resize(e.side(s)->n_nodes());
509 for (
unsigned n=0; n<e.side(s)->n_nodes(); n++) side_nodes[n] = e.side(s)->node(n).idx();
518 last_edge_idx=
edges.size();
519 edges.resize(last_edge_idx+1);
520 edg = &(
edges.back() );
522 edg->
side_ =
new struct SideIter[ intersection_list.size() ];
526 if (intersection_list.size() == 1) {
529 edg->
side_[0] = e.side(s);
532 if (e->boundary_idx_ == NULL) {
547 for(
unsigned int ni = 0; ni< side_nodes.size(); ni++) bc_ele->
nodes_[ni] = side_nodes[ni];
561 for (
unsigned int ecs=0; ecs<elem->
n_sides(); ecs++) {
567 last_edge_idx=
edges.size();
568 edges.resize(last_edge_idx+1);
569 edg = &(
edges.back() );
587 OLD_ASSERT( is_neighbour || ( (
unsigned int) edg->
n_sides ) == intersection_list.size(),
"Some connected sides were not found.\n");
601 edg->side(0)->element()->permutation_idx_[edg->side(0)->side_idx()] = 0;
603 if (edg->n_sides > 1)
606 unsigned int permutation[edg->side(0)->n_nodes()];
608 for (
unsigned int i=0; i<edg->side(0)->n_nodes(); i++)
609 node_numbers[edg->side(0)->node(i).idx()] = i;
612 for (
int sid=1; sid<edg->n_sides; sid++)
614 for (
unsigned int i=0; i<edg->side(0)->n_nodes(); i++)
615 permutation[node_numbers[edg->side(sid)->node(i).idx()]] = i;
618 switch (edg->side(0)->dim())
637 unsigned int permutation[nb->element()->n_nodes()];
641 for (
unsigned int i=0; i<nb->element()->n_nodes(); i++)
642 node_numbers[nb->element().node(i)] = i;
644 for (
unsigned int i=0; i<nb->side()->n_nodes(); i++)
645 permutation[node_numbers[nb->side()->node(i).node()]] = i;
647 switch (nb->side()->dim())
675 ele->n_neighs_vb_ =0;
678 for (
auto & ngh : this->
vb_neighbours_) ngh.element()->n_neighs_vb_++;
682 if( ele->n_neighs_vb() > 0 ) {
683 ele->neigh_vb =
new struct Neighbour* [ele->n_neighs_vb()];
689 for (
auto & ngh : this->vb_neighbours_) {
711 intersections = std::make_shared<MixedMeshIntersections>(
this);
733 if (bulk_elements_id.size() ==0) {
738 map_it = bulk_elements_id.begin();
740 for(
unsigned int idx=0; idx <
n_elements(); idx++, ++map_it) {
742 if (last_id >=
id)
xprintf(
UsrErr,
"Element IDs in non-increasing order, ID: %d\n",
id);
743 last_id=*map_it = id;
746 boundary_elements_id.resize(
n_elements(
true));
747 map_it = boundary_elements_id.begin();
754 if (
id < 0) last_id=*map_it=-1;
756 if (last_id >=
id)
xprintf(
UsrErr,
"Element IDs in non-increasing order, ID: %d\n",
id);
757 last_id=*map_it = id;
765 static const double point_tolerance = 1E-10;
766 return fabs(p1[0]-p2[0]) < point_tolerance
767 && fabs(p1[1]-p2[1]) < point_tolerance
768 && fabs(p1[2]-p2[2]) < point_tolerance;
785 unsigned int i_node, i_elm_node;
789 node_ids.resize( this->
n_nodes() );
793 int found_i_node = -1;
794 bih_tree.
find_point(point, searched_elements);
798 for (i_node=0; i_node<ele->
n_nodes(); i_node++)
802 if (found_i_node == -1) found_i_node = i_elm_node;
803 else if (found_i_node != i_elm_node) {
811 if (found_i_node == -1) {
816 node_ids[i] = (
unsigned int)found_i_node;
817 searched_elements.clear();
826 bulk_elements_id.clear();
832 for (
unsigned int j=0; j<elm->n_nodes(); j++) {
833 node_list.push_back( node_ids[ elm->node_idx(j) ] );
836 for (
auto i_elm : candidate_list) {
837 if ( mesh.
element_accessor(i_elm)->
dim() == elm.dim() ) result_list.push_back( elm.index() );
839 if (result_list.size() != 1) {
844 bulk_elements_id[i] = (
LongIdx)result_list[0];
856 boundary_elements_id.clear();
857 boundary_elements_id.resize(bc_mesh->n_elements());
861 for (
auto elm : bc_mesh->elements_range()) {
862 for (
unsigned int j=0; j<elm->n_nodes(); j++) {
863 node_list.push_back( node_ids[ elm->node_idx(j) ] );
866 for (
auto i_elm : candidate_list) {
869 if (result_list.size() != 1) {
874 boundary_elements_id[i] = (
LongIdx)result_list[0];
887 it != region_list.
end();
945 node.
point() = coords;
950 void Mesh::add_element(
unsigned int elm_id,
unsigned int dim,
unsigned int region_id,
unsigned int partition_id,
962 WarningOut().fmt(
"Bulk elements of zero size(dim=0) are not supported. Element ID: {}.\n", elm_id);
966 this->
init_element(ele, elm_id, dim, region_idx, partition_id, node_ids);
974 ele->
init(dim, region_idx);
975 ele->
pid_ = partition_id;
977 for (
unsigned int ni=0; ni<ele->
n_nodes(); ni++) {
986 WarningOut().fmt(
"Tetrahedron element with id {} has wrong numbering or is degenerated (Jacobian = {}).",elm_id,jac);
1020 ASSERT_DBG(
id<0)(id).error(
"Add boundary element from mesh file trough temporary structure!");
1056 raw_ngh_output_file <<
"// fields:\n//ele_id n_sides ns_side_neighbors[n] neighbors[n*ns] n_vb_neighbors vb_neighbors[n_vb]\n";
1062 unsigned int undefined_ele_id = -1;
1065 if(ele->n_neighs_vb() > 0){
1066 for (
unsigned int i = 0; i < ele->n_neighs_vb(); i++){
1069 auto search = neigh_vb_map.find(higher_ele.
idx());
1070 if(search != neigh_vb_map.end()){
1072 search->second[ele->neigh_vb[i]->side()->side_idx()] = ele.idx();
1077 higher_ele_side_ngh[ele->neigh_vb[i]->side()->side_idx()] = ele.idx();
1078 neigh_vb_map[higher_ele.
idx()] = higher_ele_side_ngh;
1088 auto search_neigh = neigh_vb_map.end();
1089 for (
unsigned int i = 0; i < ele->n_sides(); i++) {
1090 unsigned int n_side_neighs = ele.side(i)->edge()->n_sides-1;
1092 if(n_side_neighs == 0){
1094 if(search_neigh == neigh_vb_map.end())
1095 search_neigh = neigh_vb_map.find(ele.idx());
1097 if(search_neigh != neigh_vb_map.end())
1098 if(search_neigh->second[i] != undefined_ele_id)
1104 for (
unsigned int i = 0; i < ele->n_sides(); i++) {
1106 if(ele.side(i)->edge()->n_sides > 1){
1107 for (
int j = 0; j < edge->
n_sides; j++) {
1108 if(edge->
side(j) != ele.side(i))
1113 else if(search_neigh != neigh_vb_map.end()
1114 && search_neigh->second[i] != undefined_ele_id){
1121 for (
unsigned int i = 0; i < ele->n_neighs_vb(); i++)
1132 unsigned int i, pos;
1153 std::array<unsigned int, 4> tmp_nodes;
1157 for(
unsigned int i=0; i<elem.
n_nodes(); i++)
1159 tmp_nodes[i] = elem.
nodes_[permutation_vec[i]];
1170 std::array<unsigned int, 4> tmp_nodes;
1174 for(
unsigned int i=0; i<elem.
n_nodes(); i++)
1176 tmp_nodes[i] = elem.
nodes_[permutation_vec[i]];
Distribution * el_ds
Parallel distribution of elements.
int LongIdx
Define type that represents indices of large arrays (elements, nodes, dofs etc.)
const Edge * edge() const
Class for the mesh partitioning. This should provide:
void output_internal_ngh_data()
Output of neighboring data into raw output.
const Element * element() const
unsigned int n_nodes() const
std::array< unsigned int, 4 > nodes_
indices to element's nodes
vector< Element > element_vec_
BidirectionalMap< int > node_ids_
Maps node ids to indexes into vector node_vec_.
vector< vector< unsigned int > > const & node_elements()
#define ASSERT_EQ_DBG(a, b)
Definition of comparative assert macro (EQual) only for debug mode.
unsigned int * boundary_idx_
void permute_tetrahedron(unsigned int elm_idx, std::vector< unsigned int > permutation_vec)
Permute nodes of 3D elements of given elm_idx.
bool is_boundary() const
Returns true if it is a Boundary region and false if it is a Bulk region.
NodeAccessor< 3 > node_accessor(unsigned int ni) const
BCMesh * bc_mesh_
Boundary mesh, object is created only if it's necessary.
unsigned int side_idx() const
MapElementIDToRegionID el_to_reg_map_
void init_element_vector(unsigned int size)
Initialize element_vec_, set size and reset counters of boundary and bulk elements.
virtual const LongIdx * get_local_part()
MixedMeshIntersections & mixed_intersections()
BidirectionalMap< int > element_ids_
Maps element ids to indexes into vector element_vec_.
void add_node(unsigned int node_id, arma::vec3 coords)
Add new node of given id and coordinates to mesh.
#define MessageOut()
Macro defining 'message' record of log.
unsigned int elem_idx_
Index of element in Mesh::element_vec_.
static const Input::Type::Record & get_input_type()
ElementAccessor< 3 > element_accessor(unsigned int idx) const override
Overwrite Mesh::element_accessor()
static const unsigned int undef_idx
std::vector< BoundingBox > get_element_boxes()
Compute bounding boxes of elements contained in mesh.
ofstream raw_ngh_output_file
std::string format(CStringRef format_str, ArgList args)
NodeAccessor< 3 > node_accessor(unsigned int idx) const
Create and return NodeAccessor to node of given idx.
void create_node_element_lists()
static unsigned int permutation_index(unsigned int p[n_nodes_per_side])
BCMesh * get_bc_mesh()
Create boundary mesh if doesn't exist and return it.
static const Input::Type::Record & get_input_type()
int elem_index(int elem_id) const
For element of given elem_id returns index in element_vec_ or (-1) if element doesn't exist...
std::shared_ptr< MixedMeshIntersections > intersections
double global_snap_radius() const
Maximal distance of observe point from Mesh relative to its size.
unsigned int max_edge_sides_[3]
Maximal number of sides per one edge in the actual mesh (set in make_neighbours_and_edges()).
std::string create_label_from_id(unsigned int id) const
vector< vector< vector< unsigned int > > > side_nodes
SideIter side(const unsigned int loc_index)
#define ASSERT(expr)
Allow use shorter versions of macro names if these names is not used with external library...
virtual unsigned int n_nodes() const
void add_physical_name(unsigned int dim, unsigned int id, std::string name)
Add new node of given id and coordinates to mesh.
vector< Boundary > boundary_
int node_index(int node_id) const
For node of given node_id returns index in element_vec_ or (-1) if node doesn't exist.
ElementAccessor< 3 > element() const
virtual Partitioning * get_part()
virtual ElementAccessor< 3 > element_accessor(unsigned int idx) const
Create and return ElementAccessor to element of given idx.
void init(unsigned int dim, RegionIdx reg)
Region get_region(unsigned int id, unsigned int dim)
unsigned int n_vb_neighbours() const
ElementAccessor< 3 > element()
void open_stream(Stream &stream) const
virtual bool check_compatible_mesh(Mesh &mesh, vector< LongIdx > &bulk_elements_id, vector< LongIdx > &boundary_elements_id)
unsigned int edge_idx_
Index of Edge in Mesh.
void read_regions_from_input(Input::Array region_list)
unsigned int boundary_loaded_size_
Count of boundary elements loaded from mesh file.
bool same_sides(const SideIter &si, vector< unsigned int > &side_nodes)
int find_elem_id(unsigned int pos) const
Return element id (in GMSH file) of element of given position in element vector.
unsigned int add_item(T val)
Add new item at the end position of map.
unsigned int node_idx(unsigned int ni) const
Return index (in Mesh::node_vec) of ni-th node.
void check_element_size(unsigned int elem_idx) const
Check if given index is in element_vec_.
IntersectionSearch get_intersection_search()
Getter for input type selection for intersection search algorithm.
LongIdx * el_4_loc
Index set assigning to local element index its global index.
unsigned int edge_idx(unsigned int edg_idx) const
Return edge_idx of given index.
friend class RegionSetBase
static const Input::Type::Selection & get_input_intersection_variant()
The definition of input record for selection of variant of file format.
unsigned int n_sides() const
#define START_TIMER(tag)
Starts a timer with specified tag.
Class for O(log N) lookup for intersections with a set of bounding boxes.
void set_item(T val, unsigned int pos)
LongIdx * row_4_el
Index set assigning to global element index the local index used in parallel vectors.
BoundingBox bounding_box() const
Region implicit_boundary_region()
virtual Range< ElementAccessor< 3 > > elements_range() const
Returns range of bulk elements.
unsigned int n_sides() const
std::shared_ptr< BIHTree > bih_tree_
Element * add_element_to_vector(int id, bool boundary=false)
Adds element to mesh data structures (element_vec_, element_ids_), returns pointer to this element...
vector< vector< unsigned int > > node_elements_
For each node the vector contains a list of elements that use this node.
void reinit(unsigned int init_size=0)
Reset data of map, allow reserve size.
NodeAccessor< 3 > node(unsigned int i) const
void elements_id_maps(vector< LongIdx > &bulk_elements_id, vector< LongIdx > &boundary_elements_id) const
void count_element_types()
bool compare_points(const arma::vec3 &p1, const arma::vec3 &p2)
const BIHTree & get_bih_tree()
Getter for BIH. Creates and compute BIH at first call.
void create_boundary_elements()
Create boundary elements from data of temporary structure, this method MUST be call after read mesh f...
Dedicated class for storing path to input and output files.
void mark_used_region(unsigned int idx)
Support classes for parallel programing.
Region add_region(unsigned int id, const std::string &label, unsigned int dim, const std::string &address="implicit")
vector< Neighbour > vb_neighbours_
virtual unsigned int n_elements(bool boundary=false) const
Returns count of boundary or bulk elements.
void find_point(const Space< 3 >::Point &point, std::vector< unsigned int > &result_list, bool full_list=false) const
Class represents boundary part of mesh.
std::vector< Edge > edges
Vector of MH edges, this should not be part of the geometrical mesh.
bool find_lower_dim_element(vector< unsigned int > &element_list, unsigned int dim, unsigned int &element_idx)
int pid_
Id # of mesh partition.
void print_region_table(std::ostream &stream) const
void intersect_element_lists(vector< unsigned int > const &nodes_list, vector< unsigned int > &intersection_element_list)
void modify_element_ids(const RegionDB::MapElementIDToRegionID &map)
#define WarningOut()
Macro defining 'warning' record of log.
void make_edge_permutations()
double tetrahedron_jacobian() const
Class RefElement defines numbering of vertices, sides, calculation of normal vectors etc...
static Input::Type::Abstract & get_input_type()
Range< NodeAccessor< 3 > > node_range() const
Returns range of nodes.
const LongIdx * get_loc_part() const
void add_element(unsigned int elm_id, unsigned int dim, unsigned int region_id, unsigned int partition_id, std::vector< unsigned int > node_ids)
Add new element of given id to mesh.
bool is_valid() const
Returns false if the region has undefined/invalid value.
IntersectionSearch
Types of search algorithm for finding intersection candidates.
void element_to_neigh_vb()
void init_element(Element *ele, unsigned int elm_id, unsigned int dim, RegionIdx region_idx, unsigned int partition_id, std::vector< unsigned int > node_ids)
Initialize element.
unsigned int n_neighs_vb_
of neighbours, V-B type (comp.)
void reinit(Input::Record in_record)
void permute_triangle(unsigned int elm_idx, std::vector< unsigned int > permutation_vec)
Permute nodes of 2D elements of given elm_idx.
unsigned int idx() const
Return local idx of element in boundary / bulk part of element vector.
#define THROW(whole_exception_expr)
Wrapper for throw. Saves the throwing point.
SideIter side(const unsigned int i) const
Implementation of range helper class.
unsigned int bulk_size_
Count of bulk elements.
std::shared_ptr< Partitioning > part_
void make_neighbours_and_edges()
vector< ElementTmpData > bc_element_tmp_
Hold data of boundary elements during reading mesh (allow to preserve correct order during reading of...
Mesh * mesh_
Pointer to Mesh to which belonged.
void init_node_vector(unsigned int size)
Initialize node_vec_, set size.
unsigned int id() const
Returns id of the region (using RegionDB)
Main class for computation of intersection of meshes of combined dimensions.
unsigned int n_nodes() const
virtual ~Mesh()
Destructor.
unsigned int idx() const
Returns a global index of the region.
#define ASSERT_LT_DBG(a, b)
Definition of comparative assert macro (Less Than) only for debug mode.
const Node * node(unsigned int ni) const