30 #ifndef OOMPH_XDA_TET_MESH_TEMPLATE_CC 31 #define OOMPH_XDA_TET_MESH_TEMPLATE_CC 34 #include "../generic/Telements.h" 51 template <
class ELEMENT>
56 MeshChecker::assert_geometric_element<TElementGeometricBase,ELEMENT>(3);
59 std::ifstream infile(xda_file_name.c_str(),std::ios_base::in);
62 unsigned n_bound_face;
64 if (!infile.is_open())
66 std::ostringstream error_stream;
68 <<
"Failed to open " << xda_file_name
71 OOMPH_CURRENT_FUNCTION,
72 OOMPH_EXCEPTION_LOCATION);
79 infile.getline(dummy, 100);
85 infile.getline(dummy, 100);
91 infile.getline(dummy, 100);
94 infile.getline(dummy, 100);
101 while (dummy[0]!=
'T') {infile.getline(dummy, 100);}
104 Node_pt.resize(n_node);
105 Element_pt.resize(n_element);
109 std::getline(infile,line);
110 std::istringstream ostr(line);
111 std::istream_iterator<std::string> it(ostr);
112 std::istream_iterator<std::string> end;
113 unsigned nnod_el = 0;
117 first_node.push_back(atoi((*it).c_str()));
125 std::ostringstream error_stream;
127 <<
"XdaTetMesh can currently only be built with quadratic tets " 128 <<
"with 10 nodes. The specified mesh file has " << nnod_el
129 <<
"nodes per element.\n";
131 OOMPH_CURRENT_FUNCTION,
132 OOMPH_EXCEPTION_LOCATION);
142 for(
unsigned j=0;j<nnod_el;j++)
144 global_node[k]=first_node[k];
149 for(
unsigned i=1;
i<n_element;
i++)
151 for(
unsigned j=0;j<nnod_el;j++)
153 infile >> global_node[k];
156 infile.getline(dummy, 100);
166 for(
unsigned i=0;
i<n_node;
i++)
175 unsigned element_nmbr;
178 unsigned max_bound=0;
181 Boundary_id.resize(n_bound_face+1);
186 for(
unsigned i=0;
i<n_bound_face;
i++)
189 infile>> element_nmbr ;
198 unsigned oomph_lib_bound_id=bound_id-1;
199 oomph_lib_bound_id=count;
200 Boundary_id[bound_id].push_back(count);
206 if (oomph_lib_bound_id>max_bound) max_bound=oomph_lib_bound_id;
217 side_node[0]=global_node[nnod_el*element_nmbr+1];
218 side_node[1]=global_node[nnod_el*element_nmbr];
219 side_node[2]=global_node[nnod_el*element_nmbr+2];
220 side_node[3]=global_node[nnod_el*element_nmbr+4];
221 side_node[4]=global_node[nnod_el*element_nmbr+6];
222 side_node[5]=global_node[nnod_el*element_nmbr+5];
226 side_node[0]=global_node[nnod_el*element_nmbr];
227 side_node[1]=global_node[nnod_el*element_nmbr+1];
228 side_node[2]=global_node[nnod_el*element_nmbr+3];
229 side_node[3]=global_node[nnod_el*element_nmbr+4];
230 side_node[4]=global_node[nnod_el*element_nmbr+8];
231 side_node[5]=global_node[nnod_el*element_nmbr+7];
235 side_node[0]=global_node[nnod_el*element_nmbr+1];
236 side_node[1]=global_node[nnod_el*element_nmbr+2];
237 side_node[2]=global_node[nnod_el*element_nmbr+3];
238 side_node[3]=global_node[nnod_el*element_nmbr+5];
239 side_node[4]=global_node[nnod_el*element_nmbr+9];
240 side_node[5]=global_node[nnod_el*element_nmbr+8];
244 side_node[0]=global_node[nnod_el*element_nmbr+2];
245 side_node[1]=global_node[nnod_el*element_nmbr];
246 side_node[2]=global_node[nnod_el*element_nmbr+3];
247 side_node[3]=global_node[nnod_el*element_nmbr+6];
248 side_node[4]=global_node[nnod_el*element_nmbr+7];
249 side_node[5]=global_node[nnod_el*element_nmbr+9];
254 "Unexcpected side number in your '.xda' input file\n",
255 OOMPH_CURRENT_FUNCTION,
256 OOMPH_EXCEPTION_LOCATION);
260 for (
unsigned j=0;j<6;j++)
262 boundary_id[side_node[j]].insert(oomph_lib_bound_id);
267 set_nboundary(max_bound+1);
270 std::vector<bool> done(n_node,
false);
285 unsigned node_count=0;
286 for(
unsigned e=0;
e<n_element;
e++)
288 Element_pt[
e]=
new ELEMENT;
291 for(
unsigned j=0;j<nnod_el;j++)
293 unsigned j_global=global_node[node_count];
294 if(done[j_global]==
false)
296 if (boundary_id[j_global].size()==0)
299 finite_element_pt(
e)->construct_node(translate[j],time_stepper_pt);
304 finite_element_pt(
e)->construct_boundary_node(translate[j],
306 for (std::set<unsigned>::iterator it=boundary_id[j_global].begin();
307 it!=boundary_id[j_global].end();it++)
309 add_boundary_node(*it,Node_pt[j_global]);
313 Node_pt[j_global]->x(0)=x_node[j_global];
314 Node_pt[j_global]->x(1)=y_node[j_global];
315 Node_pt[j_global]->x(2)=z_node[j_global];
319 finite_element_pt(
e)->node_pt(translate[j]) = Node_pt[j_global];
326 setup_boundary_element_info();
330 unsigned nb=nboundary();
331 for (
unsigned b=0;b<nb;b++)
333 bool switch_normal=
false;
334 setup_boundary_coordinates(b,switch_normal);
351 template <
class ELEMENT>
353 const bool& switch_normal,
354 std::ofstream& outfile)
361 std::map<Node*,Vector<double> > backup_position;
364 unsigned nel=this->nboundary_element(b);
368 for(
unsigned e=0;
e<nel;
e++)
374 int face_index = this->face_index_at_boundary(b,
e);
379 face_el_pt.push_back(el_pt);
383 for (
unsigned j=3;j<6;j++)
385 if (backup_position[el_pt->
node_pt(j)].size()==0)
388 backup_position[el_pt->
node_pt(j)]=pos;
393 for (
unsigned i=0;
i<3;
i++)
410 if (outfile.is_open())
412 face_el_pt[face_el_pt.size()-1]->output(outfile);
418 Node* lower_left_node_pt=this->boundary_node_pt(b,0);
419 Node* upper_right_node_pt=this->boundary_node_pt(b,0);
422 unsigned nnod=this->nboundary_node(b);
423 for (
unsigned j=0;j<nnod;j++)
427 Node* nod_pt=this->boundary_node_pt(b,j);
430 if (nod_pt->
x(2)<lower_left_node_pt->
x(2))
432 lower_left_node_pt=nod_pt;
435 else if (nod_pt->
x(2)==lower_left_node_pt->
x(2))
438 if (nod_pt->
x(1)<lower_left_node_pt->
x(1))
440 lower_left_node_pt=nod_pt;
443 else if (nod_pt->
x(1)==lower_left_node_pt->
x(1))
447 if (nod_pt->
x(0)<lower_left_node_pt->
x(0))
449 lower_left_node_pt=nod_pt;
456 if (nod_pt->
x(2)>upper_right_node_pt->
x(2))
458 upper_right_node_pt=nod_pt;
461 else if (nod_pt->
x(2)==upper_right_node_pt->
x(2))
464 if (nod_pt->
x(1)>upper_right_node_pt->
x(1))
466 upper_right_node_pt=nod_pt;
469 else if (nod_pt->
x(1)==upper_right_node_pt->
x(1))
473 if (nod_pt->
x(0)>upper_right_node_pt->
x(0))
475 upper_right_node_pt=nod_pt;
486 b0[0]=upper_right_node_pt->
x(0)-lower_left_node_pt->
x(0);
487 b0[1]=upper_right_node_pt->
x(1)-lower_left_node_pt->
x(1);
488 b0[2]=upper_right_node_pt->
x(2)-lower_left_node_pt->
x(2);
491 double inv_length=1.0/sqrt(b0[0]*b0[0]+b0[1]*b0[1]+b0[2]*b0[2]);
500 outer_unit_normal(s,normal);
504 normal[0]=-normal[0];
505 normal[1]=-normal[1];
506 normal[2]=-normal[2];
512 for(
unsigned e=0;
e<nel;
e++)
517 outer_unit_normal(s,my_normal);
521 normal[0]*my_normal[0]+
522 normal[1]*my_normal[1]+
523 normal[2]*my_normal[2];
526 if (switch_normal) error+=1.0;
528 if (error>Tolerance_for_boundary_finding)
530 std::ostringstream error_message;
532 <<
"Error in alingment of normals (dot product-1) " 533 << error <<
" for element " <<
e << std::endl
534 <<
"exceeds tolerance specified by the static member data\n" 535 <<
"TetMeshBase::Tolerance_for_boundary_finding = " 536 << Tolerance_for_boundary_finding << std::endl
537 <<
"This usually means that the boundary is not planar.\n\n" 538 <<
"You can suppress this error message by recompiling \n" 539 <<
"recompiling without PARANOID or by changing the tolerance.\n";
541 OOMPH_CURRENT_FUNCTION,
542 OOMPH_EXCEPTION_LOCATION);
549 b1[0]=b0[1]*normal[2]-b0[2]*normal[1];
550 b1[1]=b0[2]*normal[0]-b0[0]*normal[2];
551 b1[2]=b0[0]*normal[1]-b0[1]*normal[0];
554 for (
unsigned j=0;j<nnod;j++)
557 Node* nod_pt=this->boundary_node_pt(b,j);
561 delta[0]=nod_pt->
x(0)-lower_left_node_pt->
x(0);
562 delta[1]=nod_pt->
x(1)-lower_left_node_pt->
x(1);
563 delta[2]=nod_pt->
x(2)-lower_left_node_pt->
x(2);
566 zeta[0]=delta[0]*b0[0]+delta[1]*b0[1]+delta[2]*b0[2];
567 zeta[1]=delta[0]*b1[0]+delta[1]*b1[1]+delta[2]*b1[2];
573 pow(lower_left_node_pt->
x(0)+zeta[0]*b0[0]+zeta[1]*b1[0]-
575 pow(lower_left_node_pt->
x(1)+zeta[0]*b0[1]+zeta[1]*b1[1]-
577 pow(lower_left_node_pt->
x(2)+zeta[0]*b0[2]+zeta[1]*b1[2]-
580 if (sqrt(error)>Tolerance_for_boundary_finding)
582 std::ostringstream error_message;
584 <<
"Error in setup of boundary coordinate " 585 << sqrt(error) << std::endl
586 <<
"exceeds tolerance specified by the static member data\n" 587 <<
"TetMeshBase::Tolerance_for_boundary_finding = " 588 << Tolerance_for_boundary_finding << std::endl
589 <<
"This usually means that the boundary is not planar.\n\n" 590 <<
"You can suppress this error message by recompiling \n" 591 <<
"recompiling without PARANOID or by changing the tolerance.\n";
593 OOMPH_CURRENT_FUNCTION,
594 OOMPH_EXCEPTION_LOCATION);
605 Boundary_coordinate_exists[b]=
true;
608 unsigned n=face_el_pt.size();
609 for (
unsigned e=0;
e<n;
e++)
611 delete face_el_pt[
e];
617 it!=backup_position.end();it++)
619 Node* nod_pt=(*it).first;
621 for (
unsigned i=0;
i<3;
i++)
void setup_boundary_coordinates(const unsigned &b, const bool &switch_normal)
Setup boundary coordinate on boundary b while is temporarily flattened to simplex faces...
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...
A general Finite Element class.
Nodes are derived from Data, but, in addition, have a definite (Eulerian) position in a space of a gi...
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 requi...
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.
Node *& node_pt(const unsigned &n)
Return a pointer to the local node n.
std::string string(const unsigned &i)
Return the i-th string or "" if the relevant string hasn't been defined.
Base class for time-stepping schemes. Timestepper provides an approximation of the temporal derivativ...