tet_mesh.cc
Go to the documentation of this file.
1 //LIC// ====================================================================
2 //LIC// This file forms part of oomph-lib, the object-oriented,
3 //LIC// multi-physics finite-element library, available
4 //LIC// at http://www.oomph-lib.org.
5 //LIC//
6 //LIC// Version 1.0; svn revision $LastChangedRevision$
7 //LIC//
8 //LIC// $LastChangedDate$
9 //LIC//
10 //LIC// Copyright (C) 2006-2016 Matthias Heil and Andrew Hazel
11 //LIC//
12 //LIC// This library is free software; you can redistribute it and/or
13 //LIC// modify it under the terms of the GNU Lesser General Public
14 //LIC// License as published by the Free Software Foundation; either
15 //LIC// version 2.1 of the License, or (at your option) any later version.
16 //LIC//
17 //LIC// This library is distributed in the hope that it will be useful,
18 //LIC// but WITHOUT ANY WARRANTY; without even the implied warranty of
19 //LIC// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
20 //LIC// Lesser General Public License for more details.
21 //LIC//
22 //LIC// You should have received a copy of the GNU Lesser General Public
23 //LIC// License along with this library; if not, write to the Free Software
24 //LIC// Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA
25 //LIC// 02110-1301 USA.
26 //LIC//
27 //LIC// The authors may be contacted at oomph-lib@maths.man.ac.uk.
28 //LIC//
29 //LIC//====================================================================
30 
31 #include <algorithm>
32 
33 #include "map_matrix.h"
34 #include "tet_mesh.h"
35 #include "Telements.h"
36 
37 
38 namespace oomph
39 {
40 
41 
42 //================================================================
43 /// Global static data that specifies the permitted
44 /// error in the setup of the boundary coordinates
45 //================================================================
47 
48 
49 //================================================================
50 /// Setup lookup schemes which establish which elements are located
51 /// next to which boundaries (Doc to outfile if it's open).
52 //================================================================
53 void TetMeshBase::setup_boundary_element_info(std::ostream &outfile)
54 {
55 
56  //Should we document the output here
57  bool doc = false;
58 
59  if (outfile) doc = true;
60 
61  // Number of boundaries
62  unsigned nbound=nboundary();
63 
64  // Wipe/allocate storage for arrays
65  Boundary_element_pt.clear();
66  Face_index_at_boundary.clear();
67  Boundary_element_pt.resize(nbound);
68  Face_index_at_boundary.resize(nbound);
70 
71  // Temporary vector of vectors of pointers to elements on the boundaries:
72  // This is a vector to ensure UNIQUE ordering in all processors
73  Vector<Vector<FiniteElement*> > vector_of_boundary_element_pt;
74  vector_of_boundary_element_pt.resize(nbound);
75 
76  // Matrix map for working out the fixed face for elements on boundary
78  face_identifier;
79 
80  // Loop over elements
81  //-------------------
82  unsigned nel=nelement();
83 
84 
85  // Get pointer to vector of boundaries that the
86  // node lives on
87  Vector<std::set<unsigned>*> boundaries_pt(4,0);
88 
89  for (unsigned e=0;e<nel;e++)
90  {
91  // Get pointer to element
93 
94  if (doc) outfile << "Element: " << e << " " << fe_pt << std::endl;
95 
96  // Only include 3D elements! Some meshes contain interface elements too.
97  if (fe_pt->dim()==3)
98  {
99  // Loop over the element's nodes and find out which boundaries they're on
100  // ----------------------------------------------------------------------
101  //We need only loop over the corner nodes
102  for(unsigned i=0;i<4;i++)
103  {
104  fe_pt->node_pt(i)->get_boundaries_pt(boundaries_pt[i]);
105  }
106 
107  //Find the common boundaries of each face
108  Vector<std::set<unsigned> > face(4);
109 
110  // NOTE: Face indices defined in Telements.h
111 
112  //Face 3 connnects points 0, 1 and 2
113  if(boundaries_pt[0] && boundaries_pt[1] && boundaries_pt[2])
114  {
115  std::set<unsigned> aux;
116 
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> >(
120  aux,aux.begin()));
121 
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()));
126  }
127 
128  //Face 2 connects points 0, 1 and 3
129  if(boundaries_pt[0] && boundaries_pt[1] && boundaries_pt[3])
130  {
131  std::set<unsigned> aux;
132 
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> >(
136  aux,aux.begin()));
137 
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()));
142  }
143 
144  //Face 1 connects points 0, 2 and 3
145  if(boundaries_pt[0] && boundaries_pt[2] && boundaries_pt[3])
146  {
147  std::set<unsigned> aux;
148 
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> >(
152  aux,aux.begin()));
153 
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()));
158  }
159 
160  //Face 0 connects points 1, 2 and 3
161  if(boundaries_pt[1] && boundaries_pt[2] && boundaries_pt[3])
162  {
163  std::set<unsigned> aux;
164 
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> >(
168  aux,aux.begin()));
169 
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()));
174  }
175 
176 
177 
178  //We now know whether any faces lay on the boundaries
179  for(unsigned i=0;i<4;i++)
180  {
181  //How many boundaries are there
182  unsigned count = 0;
183 
184  //The number of the boundary
185  int boundary=-1;
186 
187  //Loop over all the members of the set and add to the count
188  //and set the boundary
189  for(std::set<unsigned>::iterator it=face[i].begin();
190  it!=face[i].end();++it)
191  {
192  ++count;
193  boundary = *it;
194  }
195 
196  //If we're on more than one boundary, this is weird, so die
197  if(count > 1)
198  {
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";
209  error_stream.str(),
210  OOMPH_CURRENT_FUNCTION,
211  OOMPH_EXCEPTION_LOCATION);
212  }
213 
214  //If we have a boundary then add this to the appropriate set
215  if(boundary >= 0)
216  {
217 
218  // Does the pointer already exits in the vector
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(),
224  fe_pt);
225 
226  //Only insert if we have not found it (i.e. got to the end)
227  if(b_el_it == vector_of_boundary_element_pt[
228  static_cast<unsigned>(boundary)].end())
229  {
230  vector_of_boundary_element_pt[static_cast<unsigned>(boundary)].
231  push_back(fe_pt);
232  }
233 
234  //Also set the fixed face
235  face_identifier(static_cast<unsigned>(boundary),fe_pt) = i;
236  }
237  }
238 
239  //Now we set the pointers to the boundary sets to zero
240  for(unsigned i=0;i<4;i++) {boundaries_pt[i] = 0;}
241 
242  }
243  }
244 
245  // Now copy everything across into permanent arrays
246  //-------------------------------------------------
247 
248  // Loop over boundaries
249  //---------------------
250  for (unsigned i=0;i<nbound;i++)
251  {
252  // Number of elements on this boundary (currently stored in a set)
253  unsigned nel=vector_of_boundary_element_pt[i].size();
254 
255  // Allocate storage for the coordinate identifiers
256  Face_index_at_boundary[i].resize(nel);
257 
258  unsigned e_count=0;
260  for (IT it=vector_of_boundary_element_pt[i].begin();
261  it!=vector_of_boundary_element_pt[i].end();
262  it++)
263  {
264  // Recover pointer to element
265  FiniteElement* fe_pt=*it;
266 
267  // Add to permanent storage
268  Boundary_element_pt[i].push_back(fe_pt);
269 
270  Face_index_at_boundary[i][e_count] = face_identifier(i,fe_pt);
271 
272  // Increment counter
273  e_count++;
274  }
275  }
276 
277 
278 
279  // Doc?
280  //-----
281  if (doc)
282  {
283  // Loop over boundaries
284  for (unsigned i=0;i<nbound;i++)
285  {
286  unsigned nel=Boundary_element_pt[i].size();
287  outfile << "Boundary: " << i
288  << " is adjacent to " << nel
289  << " elements" << std::endl;
290 
291  // Loop over elements on given boundary
292  for (unsigned e=0;e<nel;e++)
293  {
295  outfile << "Boundary element:" << fe_pt
296  << " Face index of boundary is "
297  << Face_index_at_boundary[i][e] << std::endl;
298  }
299  }
300  }
301 
302 
303  // Lookup scheme has now been setup yet
305 
306 }
307 
308 
309 
310 
311 
312 //======================================================================
313 /// Assess mesh quality: Ratio of max. edge length to min. height,
314 /// so if it's very large it's BAAAAAD.
315 //======================================================================
316 void TetMeshBase::assess_mesh_quality(std::ofstream& some_file)
317 {
318  Vector<Vector<double> > edge(6);
319  for (unsigned e=0;e<6;e++)
320  {
321  edge[e].resize(3);
322  }
323  unsigned nel=this->nelement();
324  for (unsigned e=0;e<nel;e++)
325  {
326  FiniteElement* fe_pt=this->finite_element_pt(e);
327  for (unsigned i=0;i<3;i++)
328  {
329  edge[0][i]=fe_pt->node_pt(2)->x(i)-fe_pt->node_pt(1)->x(i);
330  edge[1][i]=fe_pt->node_pt(0)->x(i)-fe_pt->node_pt(2)->x(i);
331  edge[2][i]=fe_pt->node_pt(1)->x(i)-fe_pt->node_pt(0)->x(i);
332  edge[3][i]=fe_pt->node_pt(3)->x(i)-fe_pt->node_pt(0)->x(i);
333  edge[4][i]=fe_pt->node_pt(3)->x(i)-fe_pt->node_pt(1)->x(i);
334  edge[5][i]=fe_pt->node_pt(3)->x(i)-fe_pt->node_pt(2)->x(i);
335  }
336 
337  double max_length=0.0;
338  for (unsigned j=0;j<6;j++)
339  {
340  double length=0.0;
341  for (unsigned i=0;i<3;i++)
342  {
343  length+=edge[j][i]*edge[j][i];
344  }
345  length=sqrt(length);
346  if (length>max_length) max_length=length;
347  }
348 
349 
350  double min_height=DBL_MAX;
351  for (unsigned j=0;j<4;j++)
352  {
353  Vector<double> normal(3);
354  unsigned e0=0;
355  unsigned e1=0;
356  unsigned e2=0;
357  switch(j)
358  {
359  case 0:
360  e0=4;
361  e1=5;
362  e2=1;
363  break;
364 
365  case 1:
366  e0=1;
367  e1=3;
368  e2=2;
369  break;
370 
371  case 2:
372  e0=3;
373  e1=4;
374  e2=1;
375  break;
376 
377  case 3:
378  e0=1;
379  e1=2;
380  e2=3;
381  break;
382 
383  default:
384 
385  oomph_info << "never get here\n";
386  abort();
387  }
388 
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];
392  double norm=
393  normal[0]*normal[0]+
394  normal[1]*normal[1]+
395  normal[2]*normal[2];
396  double inv_norm=1.0/sqrt(norm);
397  normal[0]*=inv_norm;
398  normal[1]*=inv_norm;
399  normal[2]*=inv_norm;
400 
401  double height=fabs(
402  edge[e2][0]*normal[0]+
403  edge[e2][1]*normal[1]+
404  edge[e2][2]*normal[2]);
405 
406  if (height<min_height) min_height=height;
407  }
408 
409  double aspect_ratio=max_length/min_height;
410 
411  some_file << "ZONE N=4, E=1, F=FEPOINT, ET=TETRAHEDRON\n";
412  for (unsigned j=0;j<4;j++)
413  {
414  for (unsigned i=0;i<3;i++)
415  {
416  some_file << fe_pt->node_pt(j)->x(i) << " ";
417  }
418  some_file << aspect_ratio << std::endl;
419  }
420  some_file << "1 2 3 4" << std::endl;
421  }
422 }
423 
424 
425 
426  //======================================================================
427  /// Move the nodes on boundaries with associated Geometric Objects (if any)
428  /// so that they exactly coincide with the geometric object. This requires
429  /// that the boundary coordinates are set up consistently
430  //======================================================================
432  {
433 
434  // Backup in case elements get inverted
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++)
439  {
440  Node* nod_pt=node_pt(j);
441  Vector<double> x(3);
442  nod_pt->position(x);
443  old_nodal_posn[nod_pt]=x;
444  }
445 
446  // Loop over all boundaries
447  unsigned n_bound = this->nboundary();
448  for (unsigned b = 0; b < n_bound; b++)
449  {
450  bool do_it=true;
451 
452  // Accumulate reason for not snapping
453  std::stringstream reason;
454  reason << "Can't snap nodes on boundary " << b
455  << " onto geom object because: \n";
456 
457  TetMeshFacetedSurface* faceted_surface_pt=0;
458  std::map<unsigned,TetMeshFacetedSurface*>::iterator it=
460  if (it!=Tet_mesh_faceted_surface_pt.end())
461  {
462  faceted_surface_pt=(*it).second;
463  }
464 
465  // Facet associated with this boundary?
466  if (faceted_surface_pt==0)
467  {
468  reason << "-- no facets asssociated with boundary\n";
469  do_it=false;
470  }
471 
472  // Get geom object associated with facet
473  GeomObject* geom_obj_pt=0;
474  if (do_it)
475  {
476  geom_obj_pt=
477  faceted_surface_pt->geom_object_with_boundaries_pt();
478  if (geom_obj_pt==0)
479  {
480  reason << "-- no geom object associated with boundary\n";
481  do_it=false;
482  }
483  }
484 
485  // Triangular facet?
487  {
488  reason << "-- facet has to be triangular and vertex coordinates have\n"
489  << " to have been set up\n";
490  do_it=false;
491  }
492 
493  // We need boundary coordinates!
495  {
496  reason << "-- no boundary coordinates were set up\n";
497  do_it=false;
498  }
499 
500 
501 
502  // Which facet is associated with this boundary?
503  unsigned facet_id_of_boundary=0;
504  TetMeshFacet* f_pt=0;
505  if (do_it)
506  {
507  unsigned nf=faceted_surface_pt->nfacet();
508  for (unsigned f=0;f<nf;f++)
509  {
510  if ((faceted_surface_pt->
511  one_based_facet_boundary_id(f)-1)==b)
512  {
513  facet_id_of_boundary=f;
514  break;
515  }
516  }
517  f_pt=faceted_surface_pt->
518  facet_pt(facet_id_of_boundary);
519 
520 
521  // Three vertices?
522  unsigned nv=f_pt->nvertex();
523  if (nv!=3)
524  {
525  reason << "-- number of facet vertices is " << nv << " rather than 3\n";
526  do_it=false;
527  }
528 
529  // Have we set up zeta coordinates in geometric object?
530  if ((f_pt->vertex_pt(0)->zeta_in_geom_object().size()!=2)||
531  (f_pt->vertex_pt(1)->zeta_in_geom_object().size()!=2)||
532  (f_pt->vertex_pt(2)->zeta_in_geom_object().size()!=2))
533  {
534  reason << "-- no boundary coordinates were set up\n";
535  do_it=false;
536  }
537  }
538 
539 
540  // Are we ready to go?
541  if (!do_it)
542  {
543  const bool tell_us_why=false;
544  if (tell_us_why)
545  {
546  oomph_info << reason.str() << std::endl;
547  }
548  }
549  else
550  {
551 
552  // Setup area coordinantes in triangular facet
555 
558 
561 
562  double detT=(y2-y3)*(x1-x3)+(x3-x2)*(y1-y3);
563 
564 
565  // Boundary coordinate (cartesian coordinates inside facet)
566  Vector<double> zeta(2);
567 
568  // Loop over all nodes on that boundary
569  const unsigned n_boundary_node = this->nboundary_node(b);
570  for (unsigned n = 0; n < n_boundary_node; ++n)
571  {
572  // Get the boundary node and coordinates
573  Node* const nod_pt = this->boundary_node_pt(b,n);
574  nod_pt->get_coordinates_on_boundary(b,zeta);
575 
576  // Now we have zeta, the cartesian boundary coordinates
577  // in the (assumed to be triangular) boundary facet; let's
578  // work out the area coordinates
579  // Notation as in
580  // https://en.wikipedia.org/wiki/Barycentric_coordinate_system
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;
583  double s2=1.0-s0-s1;
584 
585  Vector<double> zeta_in_geom_obj(2,0.0);
586  Vector<double> position_from_geom_obj(3,0.0);
587 
588  // Vertex zeta coordinates
589  Vector<double> zeta_0(2);
590  zeta_0=f_pt->vertex_pt(0)->zeta_in_geom_object();
591 
592  Vector<double> zeta_1(2);
593  zeta_1=f_pt->vertex_pt(1)->zeta_in_geom_object();
594 
595  Vector<double> zeta_2(2);
596  zeta_2=f_pt->vertex_pt(2)->zeta_in_geom_object();
597 
598 
599 #ifdef PARANOID
600 
601  // Compute zeta values of the vertices from parametrisation of
602  // boundaries
603  double tol=1.0e-12;
604  Vector<double> zeta_from_boundary(2);
605  Vector<double> zeta_vertex(2);
606  for (unsigned v=0;v<3;v++)
607  {
608  zeta_vertex=f_pt->vertex_pt(v)->zeta_in_geom_object();
609  for (unsigned alt=0;alt<2;alt++)
610  {
611  switch (v)
612  {
613 
614  case 0:
615 
616  if (alt==0)
617  {
618  faceted_surface_pt->
619  boundary_zeta01(facet_id_of_boundary,0.0,zeta_from_boundary);
620  }
621  else
622  {
623  faceted_surface_pt->
624  boundary_zeta20(facet_id_of_boundary,1.0,zeta_from_boundary);
625  }
626  break;
627 
628  case 1:
629 
630  if (alt==0)
631  {
632  faceted_surface_pt->
633  boundary_zeta01(facet_id_of_boundary,1.0,zeta_from_boundary);
634  }
635  else
636  {
637  faceted_surface_pt->
638  boundary_zeta12(facet_id_of_boundary,0.0,zeta_from_boundary);
639  }
640  break;
641 
642  case 2:
643 
644  if (alt==0)
645  {
646  faceted_surface_pt->
647  boundary_zeta12(facet_id_of_boundary,1.0,zeta_from_boundary);
648  }
649  else
650  {
651  faceted_surface_pt->
652  boundary_zeta20(facet_id_of_boundary,0.0,zeta_from_boundary);
653  }
654  break;
655  }
656 
657  double error=sqrt(pow((zeta_vertex[0]-zeta_from_boundary[0]),2)+
658  pow((zeta_vertex[1]-zeta_from_boundary[1]),2));
659  if (error>tol)
660  {
661  std::ostringstream error_message;
662  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"
672  << std::endl;
673  throw OomphLibError(error_message.str(),
674  OOMPH_CURRENT_FUNCTION,
675  OOMPH_EXCEPTION_LOCATION);
676  }
677  }
678  }
679 
680 #endif
681 
682  // Compute zeta values of the interpolation parameters
683  Vector<double> zeta_a(3,0.0);
684  Vector<double> zeta_b(3,0.0);
685  Vector<double> zeta_c(3,0.0);
686  Vector<double> zeta_d(3,0.0);
687  Vector<double> zeta_e(3,0.0);
688  Vector<double> zeta_f(3,0.0);
689  faceted_surface_pt->
690  boundary_zeta01(facet_id_of_boundary, s1,zeta_a);
691  faceted_surface_pt->
692  boundary_zeta01(facet_id_of_boundary,1.0-s0,zeta_d);
693 
694  faceted_surface_pt->
695  boundary_zeta12(facet_id_of_boundary, s2,zeta_c);
696  faceted_surface_pt->
697  boundary_zeta12(facet_id_of_boundary,1.0-s1,zeta_f);
698 
699  faceted_surface_pt->
700  boundary_zeta20(facet_id_of_boundary,1.0-s2,zeta_b);
701  faceted_surface_pt->
702  boundary_zeta20(facet_id_of_boundary, s0,zeta_e);
703 
704  // Transfinite mapping
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]);
713 
714  unsigned n_tvalues=1+nod_pt->position_time_stepper_pt()->nprev_values();
715  for (unsigned t = 0; t < n_tvalues; ++t)
716  {
717  // Get the position according to the underlying geometric object
718  geom_obj_pt->position(t,zeta_in_geom_obj,position_from_geom_obj);
719 
720  // Move the node
721  for (unsigned i=0;i<3;i++)
722  {
723  nod_pt->x(t,i)=position_from_geom_obj[i];
724  }
725  }
726  }
727  }
728  }
729 
730  // Check if any element is inverted
731  bool some_element_is_inverted=false;
732  unsigned count=0;
733  unsigned nel=nelement();
734  for (unsigned e=0;e<nel;e++)
735  {
737  bool passed=true;
738  el_pt->check_J_eulerian_at_knots(passed);
739  if (!passed)
740  {
741  some_element_is_inverted=true;
742  char filename[100];
743  std::ofstream some_file;
744  sprintf(filename,"overly_distorted_element%i.dat",count);
745  some_file.open(filename);
746  unsigned nnod_1d=el_pt->nnode_1d();
747  el_pt->output(some_file,nnod_1d);
748  some_file.close();
749 
750  // Reset to old nodal position
751  unsigned nnod=el_pt->nnode();
752  for (unsigned j=0;j<nnod;j++)
753  {
754  Node* nod_pt=el_pt->node_pt(j);
755  Vector<double> x_current(3);
756  nod_pt->position(x_current);
757  new_nodal_posn[nod_pt]=x_current;
758  Vector<double> old_x(old_nodal_posn[nod_pt]);
759  for (unsigned i=0;i<3;i++)
760  {
761  nod_pt->x(i)=old_x[i];
762  }
763  }
764 
765  // Plot
766  sprintf(filename,"orig_overly_distorted_element%i.dat",count);
767  some_file.open(filename);
768  el_pt->output(some_file,nnod_1d);
769  some_file.close();
770 
771  // Reset
772  for (unsigned j=0;j<nnod;j++)
773  {
774  Node* nod_pt=el_pt->node_pt(j);
775  for (unsigned i=0;i<3;i++)
776  {
777  nod_pt->x(i)=new_nodal_posn[nod_pt][i];
778  }
779  }
780 
781  // Bump
782  count++;
783  }
784  }
785  if (some_element_is_inverted)
786  {
787  std::ostringstream error_message;
788  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"
795  << std::endl;
796  throw OomphLibError(error_message.str(),
797  OOMPH_CURRENT_FUNCTION,
798  OOMPH_EXCEPTION_LOCATION);
799  }
800  else
801  {
802 
803  oomph_info << "No elements are inverted after snapping. Yay!"
804  << std::endl;
805  }
806 
807  }
808 
809 
810 
811 
812 
813 /////////////////////////////////////////////////////////////////////
814 /////////////////////////////////////////////////////////////////////
815 /////////////////////////////////////////////////////////////////////
816 
817 
818 
819 
820 
821 
822 }
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...
Definition: elements.cc:4155
static double Tolerance_for_boundary_finding
Global static data that specifies the permitted error in the setup of the boundary coordinates...
Definition: tet_mesh.h:670
Node *& boundary_node_pt(const unsigned &b, const unsigned &n)
Return pointer to node n on boundary b.
Definition: mesh.h:497
virtual void output(std::ostream &outfile)
Output the element data — typically the values at the nodes in a format suitable for post-processing...
Definition: elements.h:2884
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!
Definition: tet_mesh.h:1052
std::vector< bool > Boundary_coordinate_exists
Vector of boolean data that indicates whether the boundary coordinates have been set for the boundary...
Definition: mesh.h:201
unsigned nvertex() const
Number of vertices.
Definition: tet_mesh.h:171
cstr elem_len * i
Definition: cfortran.h:607
void assess_mesh_quality(std::ofstream &some_file)
Assess mesh quality: Ratio of max. edge length to min. height, so if it&#39;s very large it&#39;s BAAAAAD...
Definition: tet_mesh.cc:316
A general Finite Element class.
Definition: elements.h:1274
char t
Definition: cfortran.h:572
TimeStepper *& position_time_stepper_pt()
Return a pointer to the position timestepper.
Definition: nodes.h:969
Nodes are derived from Data, but, in addition, have a definite (Eulerian) position in a space of a gi...
Definition: nodes.h:852
unsigned long nboundary_node(const unsigned &ibound) const
Return number of nodes on a particular boundary.
Definition: mesh.h:809
virtual void position(const Vector< double > &zeta, Vector< double > &r) const =0
Parametrised position on object at current time: r(zeta).
OomphInfo oomph_info
e
Definition: cfortran.h:575
bool Lookup_for_elements_next_boundary_is_setup
Definition: mesh.h:98
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.
Definition: nodes.cc:2301
unsigned long nelement() const
Return number of elements in the mesh.
Definition: mesh.h:587
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...
Definition: nodes.h:1284
void snap_nodes_onto_geometric_objects()
Move the nodes on boundaries with associated GeomObjects so that they exactly coincide with the geome...
Definition: tet_mesh.cc:431
double & x(const unsigned &i)
Return the i-th nodal coordinate.
Definition: nodes.h:995
void setup_boundary_element_info()
Definition: tet_mesh.h:1004
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...
Definition: mesh.h:106
unsigned nboundary() const
Return number of boundaries.
Definition: mesh.h:806
std::map< unsigned, TetMeshFacetedSurface * > Tet_mesh_faceted_surface_pt
Reverse lookup scheme: Pointer to faceted surface (if any!) associated with boundary b...
Definition: tet_mesh.h:1043
void position(Vector< double > &pos) const
Compute Vector of nodal positions either directly or via hanging node representation.
Definition: nodes.cc:2413
DiskLikeGeomObjectWithBoundaries * geom_object_with_boundaries_pt()
Access to GeomObject with boundaries associated with this surface (Null if there isn&#39;t one!) ...
Definition: tet_mesh.h:382
Node *& node_pt(const unsigned &n)
Return a pointer to the local node n.
Definition: elements.h:2109
unsigned nfacet() const
Number of facets.
Definition: tet_mesh.h:321
Node *& node_pt(const unsigned long &n)
Return pointer to global node n.
Definition: mesh.h:456
Vector< Vector< FiniteElement * > > Boundary_element_pt
Vector of Vector of pointers to elements on the boundaries: Boundary_element_pt(b,e)
Definition: mesh.h:102
unsigned long nnode() const
Return number of nodes in the mesh.
Definition: mesh.h:590
FiniteElement * finite_element_pt(const unsigned &e) const
Upcast (downcast?) to FiniteElement (needed to access FiniteElement member functions).
Definition: mesh.h:477
unsigned dim() const
Return the spatial dimension of the element, i.e. the number of local coordinates required to paramet...
Definition: elements.h:2482
virtual unsigned nnode_1d() const
Return the number of nodes along one edge of the element Default is to return zero — must be overloa...
Definition: elements.h:2151
TetMeshVertex * vertex_pt(const unsigned &j) const
Pointer to j-th vertex (const)
Definition: tet_mesh.h:177
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.
Definition: elements.h:2146
Vector< double > zeta_in_geom_object() const
Get intrinisic coordinates in GeomObject (returns zero sized vector if no such coordinates have been ...
Definition: tet_mesh.h:105