26 #ifndef OOMPH_XDA_TET_MESH_TEMPLATE_CC
27 #define OOMPH_XDA_TET_MESH_TEMPLATE_CC
30 #include "../generic/Telements.h"
45 template<
class ELEMENT>
50 MeshChecker::assert_geometric_element<TElementGeometricBase, ELEMENT>(3);
53 std::ifstream infile(xda_file_name.c_str(), std::ios_base::in);
56 unsigned n_bound_face;
58 if (!infile.is_open())
60 std::ostringstream error_stream;
61 error_stream <<
"Failed to open " << xda_file_name <<
"\n";
63 error_stream.str(), OOMPH_CURRENT_FUNCTION, OOMPH_EXCEPTION_LOCATION);
70 infile.getline(dummy, 100);
76 infile.getline(dummy, 100);
82 infile.getline(dummy, 100);
85 infile.getline(dummy, 100);
89 infile >> n_bound_face;
92 while (dummy[0] !=
'T')
94 infile.getline(dummy, 100);
98 Node_pt.resize(n_node);
99 Element_pt.resize(n_element);
103 std::getline(infile, line);
104 std::istringstream ostr(line);
105 std::istream_iterator<std::string> it(ostr);
106 std::istream_iterator<std::string> end;
107 unsigned nnod_el = 0;
111 first_node.push_back(atoi((*it).c_str()));
119 std::ostringstream error_stream;
121 <<
"XdaTetMesh can currently only be built with quadratic tets "
122 <<
"with 10 nodes. The specified mesh file has " << nnod_el
123 <<
"nodes per element.\n";
125 error_stream.str(), OOMPH_CURRENT_FUNCTION, OOMPH_EXCEPTION_LOCATION);
135 for (
unsigned j = 0; j < nnod_el; j++)
137 global_node[k] = first_node[k];
142 for (
unsigned i = 1;
i < n_element;
i++)
144 for (
unsigned j = 0; j < nnod_el; j++)
146 infile >> global_node[k];
149 infile.getline(dummy, 100);
159 for (
unsigned i = 0;
i < n_node;
i++)
168 unsigned element_nmbr;
171 unsigned max_bound = 0;
174 Boundary_id.resize(n_bound_face + 1);
179 for (
unsigned i = 0;
i < n_bound_face;
i++)
182 infile >> element_nmbr;
191 unsigned oomph_lib_bound_id = bound_id - 1;
192 oomph_lib_bound_id = count;
193 Boundary_id[bound_id].push_back(count);
199 if (oomph_lib_bound_id > max_bound) max_bound = oomph_lib_bound_id;
210 side_node[0] = global_node[nnod_el * element_nmbr + 1];
211 side_node[1] = global_node[nnod_el * element_nmbr];
212 side_node[2] = global_node[nnod_el * element_nmbr + 2];
213 side_node[3] = global_node[nnod_el * element_nmbr + 4];
214 side_node[4] = global_node[nnod_el * element_nmbr + 6];
215 side_node[5] = global_node[nnod_el * element_nmbr + 5];
219 side_node[0] = global_node[nnod_el * element_nmbr];
220 side_node[1] = global_node[nnod_el * element_nmbr + 1];
221 side_node[2] = global_node[nnod_el * element_nmbr + 3];
222 side_node[3] = global_node[nnod_el * element_nmbr + 4];
223 side_node[4] = global_node[nnod_el * element_nmbr + 8];
224 side_node[5] = global_node[nnod_el * element_nmbr + 7];
228 side_node[0] = global_node[nnod_el * element_nmbr + 1];
229 side_node[1] = global_node[nnod_el * element_nmbr + 2];
230 side_node[2] = global_node[nnod_el * element_nmbr + 3];
231 side_node[3] = global_node[nnod_el * element_nmbr + 5];
232 side_node[4] = global_node[nnod_el * element_nmbr + 9];
233 side_node[5] = global_node[nnod_el * element_nmbr + 8];
237 side_node[0] = global_node[nnod_el * element_nmbr + 2];
238 side_node[1] = global_node[nnod_el * element_nmbr];
239 side_node[2] = global_node[nnod_el * element_nmbr + 3];
240 side_node[3] = global_node[nnod_el * element_nmbr + 6];
241 side_node[4] = global_node[nnod_el * element_nmbr + 7];
242 side_node[5] = global_node[nnod_el * element_nmbr + 9];
247 "Unexcpected side number in your '.xda' input file\n",
248 OOMPH_CURRENT_FUNCTION,
249 OOMPH_EXCEPTION_LOCATION);
253 for (
unsigned j = 0; j < 6; j++)
255 boundary_id[side_node[j]].insert(oomph_lib_bound_id);
260 set_nboundary(max_bound + 1);
263 std::vector<bool> done(n_node,
false);
278 unsigned node_count = 0;
279 for (
unsigned e = 0;
e < n_element;
e++)
281 Element_pt[
e] =
new ELEMENT;
284 for (
unsigned j = 0; j < nnod_el; j++)
286 unsigned j_global = global_node[node_count];
287 if (done[j_global] ==
false)
289 if (boundary_id[j_global].size() == 0)
291 Node_pt[j_global] = finite_element_pt(
e)->construct_node(
292 translate[j], time_stepper_pt);
296 Node_pt[j_global] = finite_element_pt(
e)->construct_boundary_node(
297 translate[j], time_stepper_pt);
298 for (std::set<unsigned>::iterator it =
299 boundary_id[j_global].begin();
300 it != boundary_id[j_global].end();
303 add_boundary_node(*it, Node_pt[j_global]);
306 done[j_global] =
true;
307 Node_pt[j_global]->x(0) = x_node[j_global];
308 Node_pt[j_global]->x(1) = y_node[j_global];
309 Node_pt[j_global]->x(2) = z_node[j_global];
313 finite_element_pt(
e)->node_pt(translate[j]) = Node_pt[j_global];
320 setup_boundary_element_info();
324 unsigned nb = nboundary();
325 for (
unsigned b = 0; b < nb; b++)
327 bool switch_normal =
false;
328 setup_boundary_coordinates(b, switch_normal);
344 template<
class ELEMENT>
346 const unsigned& b,
const bool& switch_normal, std::ofstream& outfile)
352 std::map<Node*, Vector<double>> backup_position;
355 unsigned nel = this->nboundary_element(b);
359 for (
unsigned e = 0;
e < nel;
e++)
365 int face_index = this->face_index_at_boundary(b,
e);
370 face_el_pt.push_back(el_pt);
374 for (
unsigned j = 3; j < 6; j++)
376 if (backup_position[el_pt->
node_pt(j)].size() == 0)
379 backup_position[el_pt->
node_pt(j)] = pos;
384 for (
unsigned i = 0;
i < 3;
i++)
401 if (outfile.is_open())
403 face_el_pt[face_el_pt.size() - 1]->output(outfile);
409 Node* lower_left_node_pt = this->boundary_node_pt(b, 0);
410 Node* upper_right_node_pt = this->boundary_node_pt(b, 0);
413 unsigned nnod = this->nboundary_node(b);
414 for (
unsigned j = 0; j < nnod; j++)
417 Node* nod_pt = this->boundary_node_pt(b, j);
420 if (nod_pt->
x(2) < lower_left_node_pt->
x(2))
422 lower_left_node_pt = nod_pt;
425 else if (nod_pt->
x(2) == lower_left_node_pt->
x(2))
428 if (nod_pt->
x(1) < lower_left_node_pt->
x(1))
430 lower_left_node_pt = nod_pt;
433 else if (nod_pt->
x(1) == lower_left_node_pt->
x(1))
436 if (nod_pt->
x(0) < lower_left_node_pt->
x(0))
438 lower_left_node_pt = nod_pt;
445 if (nod_pt->
x(2) > upper_right_node_pt->
x(2))
447 upper_right_node_pt = nod_pt;
450 else if (nod_pt->
x(2) == upper_right_node_pt->
x(2))
453 if (nod_pt->
x(1) > upper_right_node_pt->
x(1))
455 upper_right_node_pt = nod_pt;
458 else if (nod_pt->
x(1) == upper_right_node_pt->
x(1))
461 if (nod_pt->
x(0) > upper_right_node_pt->
x(0))
463 upper_right_node_pt = nod_pt;
474 b0[0] = upper_right_node_pt->
x(0) - lower_left_node_pt->
x(0);
475 b0[1] = upper_right_node_pt->
x(1) - lower_left_node_pt->
x(1);
476 b0[2] = upper_right_node_pt->
x(2) - lower_left_node_pt->
x(2);
480 1.0 / sqrt(b0[0] * b0[0] + b0[1] * b0[1] + b0[2] * b0[2]);
489 ->outer_unit_normal(
s, normal);
493 normal[0] = -normal[0];
494 normal[1] = -normal[1];
495 normal[2] = -normal[2];
501 for (
unsigned e = 0;
e < nel;
e++)
506 ->outer_unit_normal(
s, my_normal);
509 double error = normal[0] * my_normal[0] + normal[1] * my_normal[1] +
510 normal[2] * my_normal[2];
513 if (switch_normal) error += 1.0;
515 if (error > Tolerance_for_boundary_finding)
517 std::ostringstream error_message;
519 <<
"Error in alingment of normals (dot product-1) " << error
520 <<
" for element " <<
e << std::endl
521 <<
"exceeds tolerance specified by the static member data\n"
522 <<
"TetMeshBase::Tolerance_for_boundary_finding = "
523 << Tolerance_for_boundary_finding << std::endl
524 <<
"This usually means that the boundary is not planar.\n\n"
525 <<
"You can suppress this error message by recompiling \n"
526 <<
"recompiling without PARANOID or by changing the tolerance.\n";
528 OOMPH_CURRENT_FUNCTION,
529 OOMPH_EXCEPTION_LOCATION);
536 b1[0] = b0[1] * normal[2] - b0[2] * normal[1];
537 b1[1] = b0[2] * normal[0] - b0[0] * normal[2];
538 b1[2] = b0[0] * normal[1] - b0[1] * normal[0];
541 for (
unsigned j = 0; j < nnod; j++)
544 Node* nod_pt = this->boundary_node_pt(b, j);
548 delta[0] = nod_pt->
x(0) - lower_left_node_pt->
x(0);
549 delta[1] = nod_pt->
x(1) - lower_left_node_pt->
x(1);
550 delta[2] = nod_pt->
x(2) - lower_left_node_pt->
x(2);
553 zeta[0] = delta[0] * b0[0] + delta[1] * b0[1] + delta[2] * b0[2];
554 zeta[1] = delta[0] * b1[0] + delta[1] * b1[1] + delta[2] * b1[2];
559 double error = pow(lower_left_node_pt->
x(0) + zeta[0] * b0[0] +
560 zeta[1] * b1[0] - nod_pt->
x(0),
562 pow(lower_left_node_pt->
x(1) + zeta[0] * b0[1] +
563 zeta[1] * b1[1] - nod_pt->
x(1),
565 pow(lower_left_node_pt->
x(2) + zeta[0] * b0[2] +
566 zeta[1] * b1[2] - nod_pt->
x(2),
569 if (sqrt(error) > Tolerance_for_boundary_finding)
571 std::ostringstream error_message;
573 <<
"Error in setup of boundary coordinate " << sqrt(error)
575 <<
"exceeds tolerance specified by the static member data\n"
576 <<
"TetMeshBase::Tolerance_for_boundary_finding = "
577 << Tolerance_for_boundary_finding << std::endl
578 <<
"This usually means that the boundary is not planar.\n\n"
579 <<
"You can suppress this error message by recompiling \n"
580 <<
"recompiling without PARANOID or by changing the tolerance.\n";
582 OOMPH_CURRENT_FUNCTION,
583 OOMPH_EXCEPTION_LOCATION);
593 Boundary_coordinate_exists[b] =
true;
596 unsigned n = face_el_pt.size();
597 for (
unsigned e = 0;
e < n;
e++)
599 delete face_el_pt[
e];
605 it != backup_position.end();
608 Node* nod_pt = (*it).first;
610 for (
unsigned i = 0;
i < 3;
i++)
612 nod_pt->
x(
i) = pos[
i];
//////////////////////////////////////////////////////////////////// ////////////////////////////////...
A general Finite Element class.
Node *& node_pt(const unsigned &n)
Return a pointer to the local node n.
Nodes are derived from Data, but, in addition, have a definite (Eulerian) position in a space of a gi...
double & x(const unsigned &i)
Return the i-th nodal coordinate.
void position(Vector< double > &pos) const
Compute Vector of nodal positions either directly or via hanging node representation.
virtual void set_coordinates_on_boundary(const unsigned &b, const unsigned &k, const Vector< double > &boundary_zeta)
Set the vector of the k-th generalised boundary coordinates on mesh boundary b. Broken virtual interf...
An OomphLibError object which should be thrown when an run-time error is encountered....
////////////////////////////////////////////////////////////////////// //////////////////////////////...
void setup_boundary_coordinates(const unsigned &b, const bool &switch_normal)
Setup boundary coordinate on boundary b while is temporarily flattened to simplex faces....
XdaTetMesh(const std::string xda_file_name, TimeStepper *time_stepper_pt=&Mesh::Default_TimeStepper)
Constructor: Pass name of xda file. Note that all boundary elements get their own ID – this is requir...
std::string string(const unsigned &i)
Return the i-th string or "" if the relevant string hasn't been defined.
//////////////////////////////////////////////////////////////////// ////////////////////////////////...