47 unsigned n_vertex = vertex_node_pt.size();
49 for (
unsigned v = 0; v < n_vertex; ++v)
55 unsigned n_facet = facet_connectivity.size();
57 for (
unsigned f = 0; f < n_facet; ++f)
59 unsigned n_vertex_on_facet = facet_connectivity[f].size();
61 for (
unsigned i = 0;
i < n_vertex_on_facet; ++
i)
66 Facet_pt[f]->set_one_based_boundary_id(facet_boundary_id[f]);
76 unsigned n_facet = this->
nfacet();
77 for (
unsigned f = 0; f < n_facet; f++)
81 unsigned n_vertex = this->
nvertex();
82 for (
unsigned v = 0; v < n_vertex; v++)
105 if (outfile)
doc =
true;
120 vector_of_boundary_element_pt.resize(nbound);
134 for (
unsigned e = 0;
e < nel;
e++)
139 if (
doc) outfile <<
"Element: " <<
e <<
" " << fe_pt << std::endl;
142 if (fe_pt->
dim() == 3)
148 for (
unsigned i = 0;
i < 4;
i++)
159 if (boundaries_pt[0] && boundaries_pt[1] && boundaries_pt[2])
161 std::set<unsigned> aux;
163 std::set_intersection(
164 boundaries_pt[0]->begin(),
165 boundaries_pt[0]->end(),
166 boundaries_pt[1]->begin(),
167 boundaries_pt[1]->end(),
168 std::insert_iterator<std::set<unsigned>>(aux, aux.begin()));
170 std::set_intersection(
173 boundaries_pt[2]->begin(),
174 boundaries_pt[2]->end(),
175 std::insert_iterator<std::set<unsigned>>(face[3], face[3].begin()));
179 if (boundaries_pt[0] && boundaries_pt[1] && boundaries_pt[3])
181 std::set<unsigned> aux;
183 std::set_intersection(
184 boundaries_pt[0]->begin(),
185 boundaries_pt[0]->end(),
186 boundaries_pt[1]->begin(),
187 boundaries_pt[1]->end(),
188 std::insert_iterator<std::set<unsigned>>(aux, aux.begin()));
190 std::set_intersection(
193 boundaries_pt[3]->begin(),
194 boundaries_pt[3]->end(),
195 std::insert_iterator<std::set<unsigned>>(face[2], face[2].begin()));
199 if (boundaries_pt[0] && boundaries_pt[2] && boundaries_pt[3])
201 std::set<unsigned> aux;
203 std::set_intersection(
204 boundaries_pt[0]->begin(),
205 boundaries_pt[0]->end(),
206 boundaries_pt[2]->begin(),
207 boundaries_pt[2]->end(),
208 std::insert_iterator<std::set<unsigned>>(aux, aux.begin()));
210 std::set_intersection(
213 boundaries_pt[3]->begin(),
214 boundaries_pt[3]->end(),
215 std::insert_iterator<std::set<unsigned>>(face[1], face[1].begin()));
219 if (boundaries_pt[1] && boundaries_pt[2] && boundaries_pt[3])
221 std::set<unsigned> aux;
223 std::set_intersection(
224 boundaries_pt[1]->begin(),
225 boundaries_pt[1]->end(),
226 boundaries_pt[2]->begin(),
227 boundaries_pt[2]->end(),
228 std::insert_iterator<std::set<unsigned>>(aux, aux.begin()));
230 std::set_intersection(
233 boundaries_pt[3]->begin(),
234 boundaries_pt[3]->end(),
235 std::insert_iterator<std::set<unsigned>>(face[0], face[0].begin()));
240 for (
unsigned i = 0;
i < 4;
i++)
250 for (std::set<unsigned>::iterator it = face[
i].begin();
261 std::ostringstream error_stream;
262 fe_pt->
output(error_stream);
263 error_stream <<
"Face " <<
i <<
" is on " << count
265 error_stream <<
"This is rather strange.\n";
266 error_stream <<
"Your mesh may be too coarse or your tet mesh\n";
267 error_stream <<
"may be screwed up. I'm skipping the automated\n";
268 error_stream <<
"setup of the elements next to the boundaries\n";
269 error_stream <<
"lookup schemes.\n";
271 OOMPH_CURRENT_FUNCTION,
272 OOMPH_EXCEPTION_LOCATION);
280 vector_of_boundary_element_pt[
static_cast<unsigned>(boundary)]
282 vector_of_boundary_element_pt[
static_cast<unsigned>(boundary)]
288 vector_of_boundary_element_pt[
static_cast<unsigned>(boundary)]
291 vector_of_boundary_element_pt[
static_cast<unsigned>(boundary)]
296 face_identifier(
static_cast<unsigned>(boundary), fe_pt) =
i;
301 for (
unsigned i = 0;
i < 4;
i++)
303 boundaries_pt[
i] = 0;
313 for (
unsigned i = 0;
i < nbound;
i++)
316 unsigned nel = vector_of_boundary_element_pt[
i].size();
321 unsigned e_count = 0;
323 for (IT it = vector_of_boundary_element_pt[
i].begin();
324 it != vector_of_boundary_element_pt[
i].end();
346 for (
unsigned i = 0;
i < nbound;
i++)
349 outfile <<
"Boundary: " <<
i <<
" is adjacent to " << nel <<
" elements"
353 for (
unsigned e = 0;
e < nel;
e++)
356 outfile <<
"Boundary element:" << fe_pt
357 <<
" Face index of boundary is "
376 for (
unsigned e = 0;
e < 6;
e++)
381 for (
unsigned e = 0;
e < nel;
e++)
384 for (
unsigned i = 0;
i < 3;
i++)
394 double max_length = 0.0;
395 for (
unsigned j = 0; j < 6; j++)
398 for (
unsigned i = 0;
i < 3;
i++)
400 length += edge[j][
i] * edge[j][
i];
402 length = sqrt(length);
403 if (length > max_length) max_length = length;
407 double min_height = DBL_MAX;
408 for (
unsigned j = 0; j < 4; j++)
446 normal[0] = edge[e0][1] * edge[e1][2] - edge[e0][2] * edge[e1][1];
447 normal[1] = edge[e0][2] * edge[e1][0] - edge[e0][0] * edge[e1][2];
448 normal[2] = edge[e0][0] * edge[e1][1] - edge[e0][1] * edge[e1][0];
450 normal[0] * normal[0] + normal[1] * normal[1] + normal[2] * normal[2];
451 double inv_norm = 1.0 / sqrt(norm);
452 normal[0] *= inv_norm;
453 normal[1] *= inv_norm;
454 normal[2] *= inv_norm;
456 double height = fabs(edge[e2][0] * normal[0] + edge[e2][1] * normal[1] +
457 edge[e2][2] * normal[2]);
459 if (height < min_height) min_height = height;
462 double aspect_ratio = max_length / min_height;
464 some_file <<
"ZONE N=4, E=1, F=FEPOINT, ET=TETRAHEDRON\n";
465 for (
unsigned j = 0; j < 4; j++)
467 for (
unsigned i = 0;
i < 3;
i++)
469 some_file << fe_pt->
node_pt(j)->
x(
i) <<
" ";
471 some_file << aspect_ratio << std::endl;
473 some_file <<
"1 2 3 4" << std::endl;
486 std::map<Node*, Vector<double>> old_nodal_posn;
487 std::map<Node*, Vector<double>> new_nodal_posn;
488 unsigned nnod =
nnode();
489 for (
unsigned j = 0; j < nnod; j++)
494 old_nodal_posn[nod_pt] = x;
499 for (
unsigned b = 0; b < n_bound; b++)
504 std::stringstream reason;
505 reason <<
"Can't snap nodes on boundary " << b
506 <<
" onto geom object because: \n";
509 std::map<unsigned, TetMeshFacetedSurface*>::iterator it =
513 faceted_surface_pt = (*it).second;
517 if (faceted_surface_pt == 0)
519 reason <<
"-- no facets asssociated with boundary\n";
528 if (geom_obj_pt == 0)
530 reason <<
"-- no geom object associated with boundary\n";
538 reason <<
"-- facet has to be triangular and vertex coordinates have\n"
539 <<
" to have been set up\n";
546 reason <<
"-- no boundary coordinates were set up\n";
552 unsigned facet_id_of_boundary = 0;
556 unsigned nf = faceted_surface_pt->
nfacet();
557 for (
unsigned f = 0; f < nf; f++)
561 facet_id_of_boundary = f;
565 f_pt = faceted_surface_pt->
facet_pt(facet_id_of_boundary);
572 reason <<
"-- number of facet vertices is " << nv
573 <<
" rather than 3\n";
582 reason <<
"-- no boundary coordinates were set up\n";
591 const bool tell_us_why =
false;
609 double detT = (y2 - y3) * (x1 - x3) + (x3 - x2) * (y1 - y3);
617 for (
unsigned n = 0; n < n_boundary_node; ++n)
629 ((y2 - y3) * (zeta[0] - x3) + (x3 - x2) * (zeta[1] - y3)) / detT;
631 ((y3 - y1) * (zeta[0] - x3) + (x1 - x3) * (zeta[1] - y3)) / detT;
632 double s2 = 1.0 - s0 - s1;
652 double tol = 1.0e-12;
655 for (
unsigned v = 0; v < 3; v++)
658 for (
unsigned alt = 0; alt < 2; alt++)
667 facet_id_of_boundary, 0.0, zeta_from_boundary);
672 facet_id_of_boundary, 1.0, zeta_from_boundary);
681 facet_id_of_boundary, 1.0, zeta_from_boundary);
686 facet_id_of_boundary, 0.0, zeta_from_boundary);
695 facet_id_of_boundary, 1.0, zeta_from_boundary);
700 facet_id_of_boundary, 0.0, zeta_from_boundary);
706 sqrt(pow((zeta_vertex[0] - zeta_from_boundary[0]), 2) +
707 pow((zeta_vertex[1] - zeta_from_boundary[1]), 2));
710 std::ostringstream error_message;
712 <<
"Error in parametrisation of boundary coordinates \n"
713 <<
"for vertex " << v <<
" [alt=" << alt <<
"] in facet "
714 << facet_id_of_boundary <<
" : \n"
715 <<
"zeta_vertex = [ " << zeta_vertex[0] <<
" "
716 << zeta_vertex[1] <<
" ] \n"
717 <<
"zeta_from_boundary = [ " << zeta_from_boundary[0]
718 <<
" " << zeta_from_boundary[1] <<
" ] \n"
721 OOMPH_CURRENT_FUNCTION,
722 OOMPH_EXCEPTION_LOCATION);
738 facet_id_of_boundary, 1.0 - s0, zeta_d);
742 facet_id_of_boundary, 1.0 - s1, zeta_f);
745 facet_id_of_boundary, 1.0 - s2, zeta_b);
749 zeta_in_geom_obj[0] = s0 * (zeta_a[0] + zeta_b[0] - zeta_0[0]) +
750 s1 * (zeta_c[0] + zeta_d[0] - zeta_1[0]) +
751 s2 * (zeta_e[0] + zeta_f[0] - zeta_2[0]);
752 zeta_in_geom_obj[1] = s0 * (zeta_a[1] + zeta_b[1] - zeta_0[1]) +
753 s1 * (zeta_c[1] + zeta_d[1] - zeta_1[1]) +
754 s2 * (zeta_e[1] + zeta_f[1] - zeta_2[1]);
758 for (
unsigned t = 0;
t < n_tvalues; ++
t)
761 geom_obj_pt->
position(
t, zeta_in_geom_obj, position_from_geom_obj);
764 for (
unsigned i = 0;
i < 3;
i++)
766 nod_pt->
x(
t,
i) = position_from_geom_obj[
i];
774 bool some_element_is_inverted =
false;
777 for (
unsigned e = 0;
e < nel;
e++)
784 some_element_is_inverted =
true;
786 std::ofstream some_file;
787 sprintf(filename,
"overly_distorted_element%i.dat", count);
788 some_file.open(filename);
789 unsigned nnod_1d = el_pt->
nnode_1d();
790 el_pt->
output(some_file, nnod_1d);
794 unsigned nnod = el_pt->
nnode();
795 for (
unsigned j = 0; j < nnod; j++)
800 new_nodal_posn[nod_pt] = x_current;
802 for (
unsigned i = 0;
i < 3;
i++)
804 nod_pt->
x(
i) = old_x[
i];
809 sprintf(filename,
"orig_overly_distorted_element%i.dat", count);
810 some_file.open(filename);
811 el_pt->
output(some_file, nnod_1d);
815 for (
unsigned j = 0; j < nnod; j++)
818 for (
unsigned i = 0;
i < 3;
i++)
820 nod_pt->
x(
i) = new_nodal_posn[nod_pt][
i];
828 if (some_element_is_inverted)
830 std::ostringstream error_message;
832 <<
"A number of elements, namely: " << count
833 <<
" are inverted after snapping. Their shapes are in "
834 <<
" overly_distorted_element*.dat and "
835 "orig_overly_distorted_element*.dat"
836 <<
"Next person to get this error: Please implement a straightforward\n"
837 <<
"variant of one of the functors in src/mesh_smoothing to switch\n"
838 <<
"to harmonic mapping\n"
841 error_message.str(), OOMPH_CURRENT_FUNCTION, OOMPH_EXCEPTION_LOCATION);
845 oomph_info <<
"No elements are inverted after snapping. Yay!"
A general Finite Element class.
Node *& node_pt(const unsigned &n)
Return a pointer to the local node n.
virtual void output(std::ostream &outfile)
Output the element data — typically the values at the nodes in a format suitable for post-processing.
unsigned dim() const
Return the spatial dimension of the element, i.e. the number of local coordinates required to paramet...
unsigned nnode() const
Return the number of nodes.
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...
virtual unsigned nnode_1d() const
Return the number of nodes along one edge of the element Default is to return zero — must be overload...
/////////////////////////////////////////////////////////////////////
virtual void position(const Vector< double > &zeta, Vector< double > &r) const =0
Parametrised position on object at current time: r(zeta).
MapMatrixMixed is a generalised, STL-map-based, sparse(ish) matrix class with mixed indices.
unsigned long nboundary_node(const unsigned &ibound) const
Return number of nodes on a particular boundary.
Vector< Vector< FiniteElement * > > Boundary_element_pt
Vector of Vector of pointers to elements on the boundaries: Boundary_element_pt(b,...
bool Lookup_for_elements_next_boundary_is_setup
Flag to indicate that the lookup schemes for elements that are adjacent to the boundaries has been se...
std::vector< bool > Boundary_coordinate_exists
Vector of boolean data that indicates whether the boundary coordinates have been set for the boundary...
FiniteElement * finite_element_pt(const unsigned &e) const
Upcast (downcast?) to FiniteElement (needed to access FiniteElement member functions).
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.
unsigned long nnode() const
Return number of nodes in the mesh.
Node *& node_pt(const unsigned long &n)
Return pointer to global node n.
Node *& boundary_node_pt(const unsigned &b, const unsigned &n)
Return pointer to node n on boundary b.
unsigned long nelement() const
Return number of elements in the mesh.
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.
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 position(Vector< double > &pos) const
Compute Vector of nodal positions either directly or via hanging node representation.
TimeStepper *& position_time_stepper_pt()
Return a pointer to the position timestepper.
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....
An OomphLibError object which should be thrown when an run-time error is encountered....
An OomphLibWarning object which should be created as a temporary object to issue a warning....
void snap_nodes_onto_geometric_objects()
Move the nodes on boundaries with associated GeomObjects so that they exactly coincide with the geome...
std::map< unsigned, TetMeshFacetedSurface * > Tet_mesh_faceted_surface_pt
Reverse lookup scheme: Pointer to faceted surface (if any!) associated with boundary b.
static double Tolerance_for_boundary_finding
Global static data that specifies the permitted error in the setup of the boundary coordinates.
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.
void setup_boundary_element_info()
Setup lookup schemes which establish which elements are located next to mesh's boundaries (wrapper to...
std::map< unsigned, Vector< Vector< double > > > Triangular_facet_vertex_boundary_coordinate
Boundary coordinates of vertices in triangular facets associated with given boundary....
///////////////////////////////////////////////////////////////////// ///////////////////////////////...
TetMeshVertex * vertex_pt(const unsigned &j) const
Pointer to j-th vertex (const)
unsigned nvertex() const
Number of vertices.
virtual ~TetMeshFacetedClosedSurfaceForRemesh()
Destructor. Delete allocated memory.
TetMeshFacetedClosedSurfaceForRemesh(Vector< Node * > const &vertex_node_pt, Vector< Vector< unsigned >> const &facet_connectivity, Vector< unsigned > const &facet_boundary_id)
Constructor for a FacetedSurface created from a list of nodes and connectivity information....
///////////////////////////////////////////////////////////////////// ///////////////////////////////...
///////////////////////////////////////////////////////////////////// ///////////////////////////////...
virtual void boundary_zeta01(const unsigned &facet_id, const double &zeta_boundary, Vector< double > &zeta)
Virtual function that specifies the variation of the zeta coordinates in the GeomObject along the bou...
Vector< TetMeshVertex * > Vertex_pt
Vector pointers to vertices.
unsigned nfacet() const
Number of facets.
virtual void boundary_zeta12(const unsigned &facet_id, const double &zeta_boundary, Vector< double > &zeta)
Virtual function that specifies the variation of the zeta coordinates in the GeomObject along the bou...
Vector< TetMeshFacet * > Facet_pt
Vector of pointers to facets.
unsigned one_based_facet_boundary_id(const unsigned &j) const
One-based boundary id of j-th facet.
TetMeshFacet * facet_pt(const unsigned &j) const
Pointer to j-th facet.
virtual void boundary_zeta20(const unsigned &facet_id, const double &zeta_boundary, Vector< double > &zeta)
Virtual function that specifies the variation of the zeta coordinates in the GeomObject along the bou...
unsigned nvertex() const
Number of vertices.
DiskLikeGeomObjectWithBoundaries * geom_object_with_boundaries_pt()
Access to GeomObject with boundaries associated with this surface (Null if there isn't one!...
Vertex for Tet mesh generation. Can lie on multiple boundaries (identified via one-based enumeration!...
Vector< double > zeta_in_geom_object() const
Get intrinisic coordinates in GeomObject (returns zero sized vector if no such coordinates have been ...
virtual unsigned nprev_values() const =0
Number of previous values available: 0 for static, 1 for BDF<1>,...
A slight extension to the standard template vector class so that we can include "graceful" array rang...
//////////////////////////////////////////////////////////////////// ////////////////////////////////...
OomphInfo oomph_info
Single (global) instantiation of the OomphInfo object – this is used throughout the library as a "rep...