59 if (outfile) doc =
true;
74 vector_of_boundary_element_pt.resize(nbound);
89 for (
unsigned e=0;
e<nel;
e++)
94 if (doc) outfile <<
"Element: " <<
e <<
" " << fe_pt << std::endl;
102 for(
unsigned i=0;
i<4;
i++)
113 if(boundaries_pt[0] && boundaries_pt[1] && boundaries_pt[2])
115 std::set<unsigned> aux;
117 std::set_intersection(boundaries_pt[0]->begin(),boundaries_pt[0]->end(),
118 boundaries_pt[1]->begin(),boundaries_pt[1]->end(),
119 std::insert_iterator<std::set<unsigned> >(
122 std::set_intersection(aux.begin(),aux.end(),
123 boundaries_pt[2]->begin(),boundaries_pt[2]->end(),
124 std::insert_iterator<std::set<unsigned> >(
125 face[3],face[3].begin()));
129 if(boundaries_pt[0] && boundaries_pt[1] && boundaries_pt[3])
131 std::set<unsigned> aux;
133 std::set_intersection(boundaries_pt[0]->begin(),boundaries_pt[0]->end(),
134 boundaries_pt[1]->begin(),boundaries_pt[1]->end(),
135 std::insert_iterator<std::set<unsigned> >(
138 std::set_intersection(aux.begin(),aux.end(),
139 boundaries_pt[3]->begin(),boundaries_pt[3]->end(),
140 std::insert_iterator<std::set<unsigned> >(
141 face[2],face[2].begin()));
145 if(boundaries_pt[0] && boundaries_pt[2] && boundaries_pt[3])
147 std::set<unsigned> aux;
149 std::set_intersection(boundaries_pt[0]->begin(),boundaries_pt[0]->end(),
150 boundaries_pt[2]->begin(),boundaries_pt[2]->end(),
151 std::insert_iterator<std::set<unsigned> >(
154 std::set_intersection(aux.begin(),aux.end(),
155 boundaries_pt[3]->begin(),boundaries_pt[3]->end(),
156 std::insert_iterator<std::set<unsigned> >(
157 face[1],face[1].begin()));
161 if(boundaries_pt[1] && boundaries_pt[2] && boundaries_pt[3])
163 std::set<unsigned> aux;
165 std::set_intersection(boundaries_pt[1]->begin(),boundaries_pt[1]->end(),
166 boundaries_pt[2]->begin(),boundaries_pt[2]->end(),
167 std::insert_iterator<std::set<unsigned> >(
170 std::set_intersection(aux.begin(),aux.end(),
171 boundaries_pt[3]->begin(),boundaries_pt[3]->end(),
172 std::insert_iterator<std::set<unsigned> >(
173 face[0],face[0].begin()));
179 for(
unsigned i=0;
i<4;
i++)
189 for(std::set<unsigned>::iterator it=face[
i].begin();
190 it!=face[
i].end();++it)
199 std::ostringstream error_stream;
200 fe_pt->
output(error_stream);
201 error_stream <<
"Face " <<
i <<
" is on " <<
202 count <<
" boundaries.\n";
203 error_stream <<
"This is rather strange.\n";
204 error_stream <<
"Your mesh may be too coarse or your tet mesh\n";
205 error_stream <<
"may be screwed up. I'm skipping the automated\n";
206 error_stream <<
"setup of the elements next to the boundaries\n";
207 error_stream <<
"lookup schemes.\n";
210 OOMPH_CURRENT_FUNCTION,
211 OOMPH_EXCEPTION_LOCATION);
220 std::find(vector_of_boundary_element_pt[
221 static_cast<unsigned>(boundary)].begin(),
222 vector_of_boundary_element_pt[
223 static_cast<unsigned>(boundary)].end(),
227 if(b_el_it == vector_of_boundary_element_pt[
228 static_cast<unsigned>(boundary)].end())
230 vector_of_boundary_element_pt[
static_cast<unsigned>(boundary)].
235 face_identifier(static_cast<unsigned>(boundary),fe_pt) =
i;
240 for(
unsigned i=0;
i<4;
i++) {boundaries_pt[
i] = 0;}
250 for (
unsigned i=0;
i<nbound;
i++)
253 unsigned nel=vector_of_boundary_element_pt[
i].size();
260 for (IT it=vector_of_boundary_element_pt[
i].begin();
261 it!=vector_of_boundary_element_pt[
i].end();
284 for (
unsigned i=0;
i<nbound;
i++)
287 outfile <<
"Boundary: " <<
i 288 <<
" is adjacent to " << nel
289 <<
" elements" << std::endl;
292 for (
unsigned e=0;
e<nel;
e++)
295 outfile <<
"Boundary element:" << fe_pt
296 <<
" Face index of boundary is " 319 for (
unsigned e=0;
e<6;
e++)
324 for (
unsigned e=0;
e<nel;
e++)
327 for (
unsigned i=0;
i<3;
i++)
337 double max_length=0.0;
338 for (
unsigned j=0;j<6;j++)
341 for (
unsigned i=0;
i<3;
i++)
343 length+=edge[j][
i]*edge[j][
i];
346 if (length>max_length) max_length=length;
350 double min_height=DBL_MAX;
351 for (
unsigned j=0;j<4;j++)
389 normal[0]=edge[e0][1]*edge[e1][2]-edge[e0][2]*edge[e1][1];
390 normal[1]=edge[e0][2]*edge[e1][0]-edge[e0][0]*edge[e1][2];
391 normal[2]=edge[e0][0]*edge[e1][1]-edge[e0][1]*edge[e1][0];
396 double inv_norm=1.0/sqrt(norm);
402 edge[e2][0]*normal[0]+
403 edge[e2][1]*normal[1]+
404 edge[e2][2]*normal[2]);
406 if (height<min_height) min_height=height;
409 double aspect_ratio=max_length/min_height;
411 some_file <<
"ZONE N=4, E=1, F=FEPOINT, ET=TETRAHEDRON\n";
412 for (
unsigned j=0;j<4;j++)
414 for (
unsigned i=0;
i<3;
i++)
416 some_file << fe_pt->
node_pt(j)->
x(
i) <<
" ";
418 some_file << aspect_ratio << std::endl;
420 some_file <<
"1 2 3 4" << std::endl;
435 std::map<Node*,Vector<double> > old_nodal_posn;
436 std::map<Node*,Vector<double> > new_nodal_posn;
437 unsigned nnod=
nnode();
438 for (
unsigned j=0;j<nnod;j++)
443 old_nodal_posn[nod_pt]=x;
448 for (
unsigned b = 0; b < n_bound; b++)
453 std::stringstream reason;
454 reason <<
"Can't snap nodes on boundary " << b
455 <<
" onto geom object because: \n";
458 std::map<unsigned,TetMeshFacetedSurface*>::iterator it=
462 faceted_surface_pt=(*it).second;
466 if (faceted_surface_pt==0)
468 reason <<
"-- no facets asssociated with boundary\n";
480 reason <<
"-- no geom object associated with boundary\n";
488 reason <<
"-- facet has to be triangular and vertex coordinates have\n" 489 <<
" to have been set up\n";
496 reason <<
"-- no boundary coordinates were set up\n";
503 unsigned facet_id_of_boundary=0;
507 unsigned nf=faceted_surface_pt->
nfacet();
508 for (
unsigned f=0;f<nf;f++)
510 if ((faceted_surface_pt->
511 one_based_facet_boundary_id(f)-1)==b)
513 facet_id_of_boundary=f;
517 f_pt=faceted_surface_pt->
518 facet_pt(facet_id_of_boundary);
525 reason <<
"-- number of facet vertices is " << nv <<
" rather than 3\n";
534 reason <<
"-- no boundary coordinates were set up\n";
543 const bool tell_us_why=
false;
562 double detT=(y2-y3)*(x1-x3)+(x3-x2)*(y1-y3);
570 for (
unsigned n = 0; n < n_boundary_node; ++n)
581 double s0=((y2-y3)*(zeta[0]-x3)+(x3-x2)*(zeta[1]-y3))/detT;
582 double s1=((y3-y1)*(zeta[0]-x3)+(x1-x3)*(zeta[1]-y3))/detT;
606 for (
unsigned v=0;v<3;v++)
609 for (
unsigned alt=0;alt<2;alt++)
619 boundary_zeta01(facet_id_of_boundary,0.0,zeta_from_boundary);
624 boundary_zeta20(facet_id_of_boundary,1.0,zeta_from_boundary);
633 boundary_zeta01(facet_id_of_boundary,1.0,zeta_from_boundary);
638 boundary_zeta12(facet_id_of_boundary,0.0,zeta_from_boundary);
647 boundary_zeta12(facet_id_of_boundary,1.0,zeta_from_boundary);
652 boundary_zeta20(facet_id_of_boundary,0.0,zeta_from_boundary);
657 double error=sqrt(pow((zeta_vertex[0]-zeta_from_boundary[0]),2)+
658 pow((zeta_vertex[1]-zeta_from_boundary[1]),2));
661 std::ostringstream error_message;
663 <<
"Error in parametrisation of boundary coordinates \n" 664 <<
"for vertex " << v <<
" [alt=" << alt
665 <<
"] in facet " << facet_id_of_boundary <<
" : \n" 666 <<
"zeta_vertex = [ " 667 << zeta_vertex[0] <<
" " 668 << zeta_vertex[1] <<
" ] \n" 669 <<
"zeta_from_boundary = [ " 670 << zeta_from_boundary[0] <<
" " 671 << zeta_from_boundary[1] <<
" ] \n" 674 OOMPH_CURRENT_FUNCTION,
675 OOMPH_EXCEPTION_LOCATION);
690 boundary_zeta01(facet_id_of_boundary, s1,zeta_a);
692 boundary_zeta01(facet_id_of_boundary,1.0-s0,zeta_d);
695 boundary_zeta12(facet_id_of_boundary, s2,zeta_c);
697 boundary_zeta12(facet_id_of_boundary,1.0-s1,zeta_f);
700 boundary_zeta20(facet_id_of_boundary,1.0-s2,zeta_b);
702 boundary_zeta20(facet_id_of_boundary, s0,zeta_e);
705 zeta_in_geom_obj[0] =
706 s0*(zeta_a[0]+zeta_b[0]-zeta_0[0])+
707 s1*(zeta_c[0]+zeta_d[0]-zeta_1[0])
708 +s2*(zeta_e[0]+zeta_f[0]-zeta_2[0]);
709 zeta_in_geom_obj[1] =
710 s0*(zeta_a[1]+zeta_b[1]-zeta_0[1])+
711 s1*(zeta_c[1]+zeta_d[1]-zeta_1[1])
712 +s2*(zeta_e[1]+zeta_f[1]-zeta_2[1]);
715 for (
unsigned t = 0;
t < n_tvalues; ++
t)
718 geom_obj_pt->
position(
t,zeta_in_geom_obj,position_from_geom_obj);
721 for (
unsigned i=0;
i<3;
i++)
723 nod_pt->
x(
t,
i)=position_from_geom_obj[
i];
731 bool some_element_is_inverted=
false;
734 for (
unsigned e=0;
e<nel;
e++)
741 some_element_is_inverted=
true;
743 std::ofstream some_file;
744 sprintf(filename,
"overly_distorted_element%i.dat",count);
745 some_file.open(filename);
747 el_pt->
output(some_file,nnod_1d);
751 unsigned nnod=el_pt->
nnode();
752 for (
unsigned j=0;j<nnod;j++)
757 new_nodal_posn[nod_pt]=x_current;
759 for (
unsigned i=0;
i<3;
i++)
761 nod_pt->x(
i)=old_x[
i];
766 sprintf(filename,
"orig_overly_distorted_element%i.dat",count);
767 some_file.open(filename);
768 el_pt->
output(some_file,nnod_1d);
772 for (
unsigned j=0;j<nnod;j++)
775 for (
unsigned i=0;
i<3;
i++)
777 nod_pt->
x(
i)=new_nodal_posn[nod_pt][
i];
785 if (some_element_is_inverted)
787 std::ostringstream error_message;
789 <<
"A number of elements, namely: " << count
790 <<
" are inverted after snapping. Their shapes are in " 791 <<
" overly_distorted_element*.dat and orig_overly_distorted_element*.dat" 792 <<
"Next person to get this error: Please implement a straightforward\n" 793 <<
"variant of one of the functors in src/mesh_smoothing to switch\n" 794 <<
"to harmonic mapping\n" 797 OOMPH_CURRENT_FUNCTION,
798 OOMPH_EXCEPTION_LOCATION);
803 oomph_info <<
"No elements are inverted after snapping. Yay!" void check_J_eulerian_at_knots(bool &passed) const
Check that Jacobian of mapping between local and Eulerian coordinates at all integration points is po...
static double Tolerance_for_boundary_finding
Global static data that specifies the permitted error in the setup of the boundary coordinates...
Node *& boundary_node_pt(const unsigned &b, const unsigned &n)
Return pointer to node n on boundary b.
virtual void output(std::ostream &outfile)
Output the element data — typically the values at the nodes in a format suitable for post-processing...
std::map< unsigned, Vector< Vector< double > > > Triangular_facet_vertex_boundary_coordinate
Boundary coordinates of vertices in triangular facets associated with given boundary. Is only set up for triangular facets!
std::vector< bool > Boundary_coordinate_exists
Vector of boolean data that indicates whether the boundary coordinates have been set for the boundary...
unsigned nvertex() const
Number of vertices.
void assess_mesh_quality(std::ofstream &some_file)
Assess mesh quality: Ratio of max. edge length to min. height, so if it's very large it's BAAAAAD...
A general Finite Element class.
TimeStepper *& position_time_stepper_pt()
Return a pointer to the position timestepper.
Nodes are derived from Data, but, in addition, have a definite (Eulerian) position in a space of a gi...
unsigned long nboundary_node(const unsigned &ibound) const
Return number of nodes on a particular boundary.
virtual void position(const Vector< double > &zeta, Vector< double > &r) const =0
Parametrised position on object at current time: r(zeta).
bool Lookup_for_elements_next_boundary_is_setup
virtual void get_coordinates_on_boundary(const unsigned &b, const unsigned &k, Vector< double > &boundary_zeta)
Return the vector of the k-th generalised boundary coordinates on mesh boundary b. Broken virtual interface provides run-time error checking.
unsigned long nelement() const
Return number of elements in the mesh.
virtual void get_boundaries_pt(std::set< unsigned > *&boundaries_pt)
Return a pointer to set of mesh boundaries that this node occupies; this will be overloaded by Bounda...
void snap_nodes_onto_geometric_objects()
Move the nodes on boundaries with associated GeomObjects so that they exactly coincide with the geome...
double & x(const unsigned &i)
Return the i-th nodal coordinate.
void setup_boundary_element_info()
Vector< Vector< int > > Face_index_at_boundary
For the e-th finite element on boundary b, this is the index of the face that lies along that boundar...
unsigned nboundary() const
Return number of boundaries.
std::map< unsigned, TetMeshFacetedSurface * > Tet_mesh_faceted_surface_pt
Reverse lookup scheme: Pointer to faceted surface (if any!) associated with boundary b...
void position(Vector< double > &pos) const
Compute Vector of nodal positions either directly or via hanging node representation.
DiskLikeGeomObjectWithBoundaries * geom_object_with_boundaries_pt()
Access to GeomObject with boundaries associated with this surface (Null if there isn't one!) ...
Node *& node_pt(const unsigned &n)
Return a pointer to the local node n.
unsigned nfacet() const
Number of facets.
Node *& node_pt(const unsigned long &n)
Return pointer to global node n.
Vector< Vector< FiniteElement * > > Boundary_element_pt
Vector of Vector of pointers to elements on the boundaries: Boundary_element_pt(b,e)
unsigned long nnode() const
Return number of nodes in the mesh.
FiniteElement * finite_element_pt(const unsigned &e) const
Upcast (downcast?) to FiniteElement (needed to access FiniteElement member functions).
unsigned dim() const
Return the spatial dimension of the element, i.e. the number of local coordinates required to paramet...
virtual unsigned nnode_1d() const
Return the number of nodes along one edge of the element Default is to return zero — must be overloa...
TetMeshVertex * vertex_pt(const unsigned &j) const
Pointer to j-th vertex (const)
virtual unsigned nprev_values() const =0
Number of previous values available: 0 for static, 1 for BDF<1>,...
unsigned nnode() const
Return the number of nodes.
Vector< double > zeta_in_geom_object() const
Get intrinisic coordinates in GeomObject (returns zero sized vector if no such coordinates have been ...