45 std::ifstream element_file(element_file_name.c_str(), std::ios_base::in);
49 if (!element_file.is_open())
51 std::string error_msg(
"Failed to open element file: ");
52 error_msg +=
"\"" + element_file_name +
"\".";
54 error_msg, OOMPH_CURRENT_FUNCTION, OOMPH_EXCEPTION_LOCATION);
61 element_file >> n_element;
64 unsigned n_local_node;
65 element_file >> n_local_node;
68 if (n_local_node != 4)
70 std::ostringstream error_stream;
72 <<
"Tetgen should only be used to generate 4-noded tetrahedra!\n"
73 <<
"Your tetgen input file, contains data for " << n_local_node
74 <<
"-noded tetrahedra" << std::endl;
77 error_stream.str(), OOMPH_CURRENT_FUNCTION, OOMPH_EXCEPTION_LOCATION);
81 unsigned dummy_attribute;
88 unsigned dummy_element_number;
96 unsigned attribute_flag;
97 element_file >> attribute_flag;
100 if (attribute_flag == 0)
103 for (
unsigned i = 0;
i < n_element;
i++)
105 element_file >> dummy_element_number;
106 for (
unsigned j = 0; j < n_local_node; j++)
116 for (
unsigned i = 0;
i < n_element;
i++)
118 element_file >> dummy_element_number;
119 for (
unsigned j = 0; j < n_local_node; j++)
127 element_file.close();
134 std::ifstream node_file(node_file_name.c_str(), std::ios_base::in);
138 if (!node_file.is_open())
140 std::string error_msg(
"Failed to open node file: ");
141 error_msg +=
"\"" + node_file_name +
"\".";
143 error_msg, OOMPH_CURRENT_FUNCTION, OOMPH_EXCEPTION_LOCATION);
153 std::vector<bool> done(n_node,
false);
160 node_file >> dimension;
166 OOMPH_CURRENT_FUNCTION,
167 OOMPH_EXCEPTION_LOCATION);
172 node_file >> attribute_flag;
175 unsigned boundary_markers_flag;
176 node_file >> boundary_markers_flag;
179 unsigned dummy_node_number;
189 if (attribute_flag == 0)
192 if (boundary_markers_flag == 1)
194 for (
unsigned i = 0;
i < n_node;
i++)
196 node_file >> dummy_node_number;
197 node_file >> x_node[
i];
198 node_file >> y_node[
i];
199 node_file >> z_node[
i];
200 node_file >> bound[
i];
207 for (
unsigned i = 0;
i < n_node;
i++)
209 node_file >> dummy_node_number;
210 node_file >> x_node[
i];
211 node_file >> y_node[
i];
212 node_file >> z_node[
i];
221 if (boundary_markers_flag == 1)
223 for (
unsigned i = 0;
i < n_node;
i++)
225 node_file >> dummy_node_number;
226 node_file >> x_node[
i];
227 node_file >> y_node[
i];
228 node_file >> z_node[
i];
229 node_file >> dummy_attribute;
230 node_file >> bound[
i];
236 for (
unsigned i = 0;
i < n_node;
i++)
238 node_file >> dummy_node_number;
239 node_file >> x_node[
i];
240 node_file >> y_node[
i];
241 node_file >> z_node[
i];
242 node_file >> dummy_attribute;
251 unsigned n_bound = 0;
252 if (boundary_markers_flag == 1)
255 for (
unsigned i = 1;
i < n_node;
i++)
257 if (bound[
i] > n_bound)
268 std::ifstream face_file(face_file_name.c_str(), std::ios_base::in);
272 if (!face_file.is_open())
274 std::string error_msg(
"Failed to open face file: ");
275 error_msg +=
"\"" + face_file_name +
"\".";
277 error_msg, OOMPH_CURRENT_FUNCTION, OOMPH_EXCEPTION_LOCATION);
286 face_file >> boundary_markers_flag;
299 unsigned dummy_face_number;
307 for (
unsigned i = 0;
i < n_face;
i++)
309 face_file >> dummy_face_number;
310 face_file >> first_node[
i];
311 face_file >> second_node[
i];
312 face_file >> third_node[
i];
319 node_on_faces[first_node[
i]].insert(
i);
320 node_on_faces[second_node[
i]].insert(
i);
321 node_on_faces[third_node[
i]].insert(
i);
332 unsigned counter = 0;
333 for (
unsigned e = 0;
e < n_element;
e++)
371 for (
unsigned j = 0; j < (n_local_node - 1); j++)
378 if ((boundary_markers_flag == 1) &&
437 const unsigned first_local_edge_node[6] = {0, 0, 0, 1, 2, 1};
438 const unsigned second_local_edge_node[6] = {1, 2, 3, 2, 3, 3};
441 for (
unsigned e = 0;
e < n_element;
e++)
447 for (
unsigned i = 0;
i < 4;
i++)
457 const unsigned element_offset =
e * n_local_node;
458 unsigned glob_num[4] = {0, 0, 0, 0};
459 for (
unsigned i = 0;
i < 4; ++
i)
473 for (
unsigned i = 0;
i < 4; ++
i)
477 const unsigned omitted_node = 3 -
i;
481 std::set<unsigned> input = node_on_faces[glob_num[
i]];
485 if (input.size() > 0)
488 unsigned local_node =
i;
489 for (
unsigned i2 = 0; i2 < 3; ++i2)
492 local_node = (local_node + 1) % 4;
495 if (local_node != omitted_node)
498 std::set<unsigned> intersection_result;
501 std::set_intersection(
504 node_on_faces[glob_num[local_node]].begin(),
505 node_on_faces[glob_num[local_node]].end(),
506 std::insert_iterator<std::set<unsigned>>(
507 intersection_result, intersection_result.begin()));
509 input = intersection_result;
516 if (input.size() > 1)
519 "Nodes in scaffold mesh share more than one global face",
520 OOMPH_CURRENT_FUNCTION,
521 OOMPH_EXCEPTION_LOCATION);
526 if (input.size() == 0)
531 for (
unsigned i2 = 0; i2 < 4; ++i2)
534 if (i2 != omitted_node)
543 else if (input.size() == 1)
545 const unsigned global_face_index = *input.begin();
549 if (global_face_index < n_face)
554 for (
unsigned i2 = 0; i2 < 4; ++i2)
557 if (i2 != omitted_node)
569 for (
unsigned i = 0;
i < 6; ++
i)
572 std::vector<unsigned> local_edge_index;
574 const unsigned first_global_num = glob_num[first_local_edge_node[
i]];
575 const unsigned second_global_num = glob_num[second_local_edge_node[
i]];
579 std::set_intersection(node_on_edges[first_global_num].begin(),
580 node_on_edges[first_global_num].end(),
581 node_on_edges[second_global_num].begin(),
582 node_on_edges[second_global_num].end(),
583 std::insert_iterator<std::vector<unsigned>>(
584 local_edge_index, local_edge_index.begin()));
588 if (local_edge_index.size() > 1)
591 "Nodes in scaffold mesh share more than one global edge",
592 OOMPH_CURRENT_FUNCTION,
593 OOMPH_EXCEPTION_LOCATION);
598 if (local_edge_index.size() == 0)
609 else if (local_edge_index.size() == 1)
627 for (
unsigned i = 0;
i < n_face; ++
i)
631 std::vector<unsigned> local_edge_index;
634 std::set_intersection(node_on_edges[first_node[
i]].begin(),
635 node_on_edges[first_node[
i]].end(),
636 node_on_edges[second_node[
i]].begin(),
637 node_on_edges[second_node[
i]].end(),
638 std::insert_iterator<std::vector<unsigned>>(
639 local_edge_index, local_edge_index.begin()));
643 if (local_edge_index.size() != 1)
646 "Nodes in scaffold mesh face do not share exactly one global edge",
647 OOMPH_CURRENT_FUNCTION,
648 OOMPH_EXCEPTION_LOCATION);
658 std::vector<unsigned> local_edge_index;
661 std::set_intersection(node_on_edges[second_node[
i]].begin(),
662 node_on_edges[second_node[
i]].end(),
663 node_on_edges[third_node[
i]].begin(),
664 node_on_edges[third_node[
i]].end(),
665 std::insert_iterator<std::vector<unsigned>>(
666 local_edge_index, local_edge_index.begin()));
670 if (local_edge_index.size() != 1)
673 "Nodes in scaffold mesh face do not share exactly one global edge",
674 OOMPH_CURRENT_FUNCTION,
675 OOMPH_EXCEPTION_LOCATION);
685 std::vector<unsigned> local_edge_index;
688 std::set_intersection(node_on_edges[first_node[
i]].begin(),
689 node_on_edges[first_node[
i]].end(),
690 node_on_edges[third_node[
i]].begin(),
691 node_on_edges[third_node[
i]].end(),
692 std::insert_iterator<std::vector<unsigned>>(
693 local_edge_index, local_edge_index.begin()));
697 if (local_edge_index.size() != 1)
700 "Nodes in scaffold mesh face do not share exactly one global edge",
701 OOMPH_CURRENT_FUNCTION,
702 OOMPH_EXCEPTION_LOCATION);
726 unsigned n_element =
static_cast<unsigned>(tetgen_data.numberoftetrahedra);
729 unsigned n_local_node =
static_cast<unsigned>(tetgen_data.numberofcorners);
732 if (n_local_node != 4)
734 std::ostringstream error_stream;
736 <<
"Tetgen should only be used to generate 4-noded tetrahedra!\n"
737 <<
"Your tetgen input data, contains data for " << n_local_node
738 <<
"-noded tetrahedra" << std::endl;
741 error_stream.str(), OOMPH_CURRENT_FUNCTION, OOMPH_EXCEPTION_LOCATION);
754 unsigned attribute_flag =
755 static_cast<unsigned>(tetgen_data.numberoftetrahedronattributes);
758 if (attribute_flag == 0)
760 for (
unsigned i = 0;
i < n_element;
i++)
762 for (
unsigned j = 0; j < n_local_node; j++)
765 static_cast<unsigned>(tetgen_data.tetrahedronlist[k]);
773 for (
unsigned i = 0;
i < n_element;
i++)
775 for (
unsigned j = 0; j < n_local_node; j++)
778 static_cast<unsigned>(tetgen_data.tetrahedronlist[k]);
789 unsigned n_node = tetgen_data.numberofpoints;
792 std::vector<bool> done(n_node,
false);
798 unsigned boundary_markers_flag = 0;
799 if (tetgen_data.pointmarkerlist != 0)
801 boundary_markers_flag = 1;
811 if (boundary_markers_flag == 1)
813 for (
unsigned i = 0;
i < n_node;
i++)
815 x_node[
i] = tetgen_data.pointlist[3 *
i];
816 y_node[
i] = tetgen_data.pointlist[3 *
i + 1];
817 z_node[
i] = tetgen_data.pointlist[3 *
i + 2];
818 bound[
i] =
static_cast<unsigned>(tetgen_data.pointmarkerlist[
i]);
824 for (
unsigned i = 0;
i < n_node;
i++)
826 x_node[
i] = tetgen_data.pointlist[3 *
i];
827 y_node[
i] = tetgen_data.pointlist[3 *
i + 1];
828 z_node[
i] = tetgen_data.pointlist[3 *
i + 2];
836 unsigned n_bound = 0;
837 if (boundary_markers_flag == 1)
840 for (
unsigned i = 1;
i < n_node;
i++)
842 if (bound[
i] > n_bound)
853 unsigned n_face = tetgen_data.numberoftrifaces;
871 for (
unsigned i = 0;
i < n_face;
i++)
873 first_node[
i] =
static_cast<unsigned>(tetgen_data.trifacelist[3 *
i]);
875 static_cast<unsigned>(tetgen_data.trifacelist[3 *
i + 1]);
876 third_node[
i] =
static_cast<unsigned>(tetgen_data.trifacelist[3 *
i + 2]);
878 static_cast<unsigned>(tetgen_data.trifacemarkerlist[
i]);
884 node_on_faces[first_node[
i]].insert(
i);
885 node_on_faces[second_node[
i]].insert(
i);
886 node_on_faces[third_node[
i]].insert(
i);
925 unsigned counter = 0;
926 for (
unsigned e = 0;
e < n_element;
e++)
964 for (
unsigned j = 0; j < (n_local_node - 1); j++)
971 if ((boundary_markers_flag == 1) &&
1030 const unsigned first_local_edge_node[6] = {0, 0, 0, 1, 2, 1};
1031 const unsigned second_local_edge_node[6] = {1, 2, 3, 2, 3, 3};
1034 for (
unsigned e = 0;
e < n_element;
e++)
1040 for (
unsigned i = 0;
i < 4;
i++)
1050 const unsigned element_offset =
e * n_local_node;
1051 unsigned glob_num[4] = {0, 0, 0, 0};
1052 for (
unsigned i = 0;
i < 4; ++
i)
1066 for (
unsigned i = 0;
i < 4; ++
i)
1070 const unsigned omitted_node = 3 -
i;
1074 std::set<unsigned> input = node_on_faces[glob_num[
i]];
1078 if (input.size() > 0)
1081 unsigned local_node =
i;
1082 for (
unsigned i2 = 0; i2 < 3; ++i2)
1085 local_node = (local_node + 1) % 4;
1088 if (local_node != omitted_node)
1091 std::set<unsigned> intersection_result;
1094 std::set_intersection(
1097 node_on_faces[glob_num[local_node]].begin(),
1098 node_on_faces[glob_num[local_node]].end(),
1099 std::insert_iterator<std::set<unsigned>>(
1100 intersection_result, intersection_result.begin()));
1102 input = intersection_result;
1109 if (input.size() > 1)
1112 "Nodes in scaffold mesh share more than one global face",
1113 OOMPH_CURRENT_FUNCTION,
1114 OOMPH_EXCEPTION_LOCATION);
1119 if (input.size() == 0)
1124 for (
unsigned i2 = 0; i2 < 4; ++i2)
1127 if (i2 != omitted_node)
1136 else if (input.size() == 1)
1138 const unsigned global_face_index = *input.begin();
1142 if (global_face_index < n_face)
1147 for (
unsigned i2 = 0; i2 < 4; ++i2)
1150 if (i2 != omitted_node)
1162 for (
unsigned i = 0;
i < 6; ++
i)
1165 std::vector<unsigned> local_edge_index;
1167 const unsigned first_global_num = glob_num[first_local_edge_node[
i]];
1168 const unsigned second_global_num = glob_num[second_local_edge_node[
i]];
1172 std::set_intersection(node_on_edges[first_global_num].begin(),
1173 node_on_edges[first_global_num].end(),
1174 node_on_edges[second_global_num].begin(),
1175 node_on_edges[second_global_num].end(),
1176 std::insert_iterator<std::vector<unsigned>>(
1177 local_edge_index, local_edge_index.begin()));
1181 if (local_edge_index.size() > 1)
1184 "Nodes in scaffold mesh share more than one global edge",
1185 OOMPH_CURRENT_FUNCTION,
1186 OOMPH_EXCEPTION_LOCATION);
1191 if (local_edge_index.size() == 0)
1202 else if (local_edge_index.size() == 1)
1220 for (
unsigned i = 0;
i < n_face; ++
i)
1224 std::vector<unsigned> local_edge_index;
1227 std::set_intersection(node_on_edges[first_node[
i]].begin(),
1228 node_on_edges[first_node[
i]].end(),
1229 node_on_edges[second_node[
i]].begin(),
1230 node_on_edges[second_node[
i]].end(),
1231 std::insert_iterator<std::vector<unsigned>>(
1232 local_edge_index, local_edge_index.begin()));
1236 if (local_edge_index.size() != 1)
1239 "Nodes in scaffold mesh face do not share exactly one global edge",
1240 OOMPH_CURRENT_FUNCTION,
1241 OOMPH_EXCEPTION_LOCATION);
1251 std::vector<unsigned> local_edge_index;
1254 std::set_intersection(node_on_edges[second_node[
i]].begin(),
1255 node_on_edges[second_node[
i]].end(),
1256 node_on_edges[third_node[
i]].begin(),
1257 node_on_edges[third_node[
i]].end(),
1258 std::insert_iterator<std::vector<unsigned>>(
1259 local_edge_index, local_edge_index.begin()));
1263 if (local_edge_index.size() != 1)
1266 "Nodes in scaffold mesh face do not share exactly one global edge",
1267 OOMPH_CURRENT_FUNCTION,
1268 OOMPH_EXCEPTION_LOCATION);
1278 std::vector<unsigned> local_edge_index;
1281 std::set_intersection(node_on_edges[first_node[
i]].begin(),
1282 node_on_edges[first_node[
i]].end(),
1283 node_on_edges[third_node[
i]].begin(),
1284 node_on_edges[third_node[
i]].end(),
1285 std::insert_iterator<std::vector<unsigned>>(
1286 local_edge_index, local_edge_index.begin()));
1290 if (local_edge_index.size() != 1)
1293 "Nodes in scaffold mesh face do not share exactly one global edge",
1294 OOMPH_CURRENT_FUNCTION,
1295 OOMPH_EXCEPTION_LOCATION);
virtual Node * construct_node(const unsigned &n)
Construct the local node n and return a pointer to the newly created node object.
Node *& node_pt(const unsigned &n)
Return a pointer to the local node n.
virtual Node * construct_boundary_node(const unsigned &n)
Construct the local node n as a boundary node; that is a node that MAY be placed on a mesh boundary a...
void add_boundary_node(const unsigned &b, Node *const &node_pt)
Add a (pointer to) a node to the b-th boundary.
Vector< Node * > Node_pt
Vector of pointers to nodes.
FiniteElement * finite_element_pt(const unsigned &e) const
Upcast (downcast?) to FiniteElement (needed to access FiniteElement member functions).
void set_nboundary(const unsigned &nbound)
Set the number of boundaries in the mesh.
Vector< GeneralisedElement * > Element_pt
Vector of pointers to generalised elements.
An OomphLibError object which should be thrown when an run-time error is encountered....
std::vector< bool > Edge_boundary
Vector of booleans to indicate whether a global edge lies on a boundary.
unsigned Nglobal_face
Storage for the number of global faces.
TetgenScaffoldMesh()
Empty constructor.
unsigned face_boundary(const unsigned &e, const unsigned &i) const
Return the boundary id of the i-th face in the e-th element: This is zero-based as in tetgen....
Vector< double > Element_attribute
Vector of double attributes for each element. NOTE: This stores doubles because tetgen forces us to!...
Vector< Vector< unsigned > > Face_index
Vector of vectors containing the global edge index of.
unsigned global_node_number(const unsigned &i)
Return the global node of each local node listed element-by-element e*n_local_node + n_local Note tha...
unsigned Nglobal_edge
Storage for the number of global edges.
Vector< Vector< unsigned > > Edge_index
Vector of vectors containing the global edge index of.
Vector< unsigned > Global_node
Storage for global node numbers listed element-by-element.
Vector< Vector< unsigned > > Face_boundary
Vector of vectors containing the boundary ids of the elements' faces.
std::string string(const unsigned &i)
Return the i-th string or "" if the relevant string hasn't been defined.
//////////////////////////////////////////////////////////////////// ////////////////////////////////...