triangle_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// Copyright (C) 2006-2023 Matthias Heil and Andrew Hazel
7 // LIC//
8 // LIC// This library is free software; you can redistribute it and/or
9 // LIC// modify it under the terms of the GNU Lesser General Public
10 // LIC// License as published by the Free Software Foundation; either
11 // LIC// version 2.1 of the License, or (at your option) any later version.
12 // LIC//
13 // LIC// This library is distributed in the hope that it will be useful,
14 // LIC// but WITHOUT ANY WARRANTY; without even the implied warranty of
15 // LIC// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
16 // LIC// Lesser General Public License for more details.
17 // LIC//
18 // LIC// You should have received a copy of the GNU Lesser General Public
19 // LIC// License along with this library; if not, write to the Free Software
20 // LIC// Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA
21 // LIC// 02110-1301 USA.
22 // LIC//
23 // LIC// The authors may be contacted at oomph-lib@maths.man.ac.uk.
24 // LIC//
25 // LIC//====================================================================
26 
27 #include <algorithm>
28 #include "map_matrix.h"
30 #include "triangle_mesh.h"
31 
32 namespace oomph
33 {
34 #ifdef OOMPH_HAS_TRIANGLE_LIB
35 
36  //==============================================================
37  /// Dump the triangulateio structure to a dump file and
38  /// record boundary coordinates of boundary nodes
39  //==============================================================
40  void TriangleMeshBase::dump_triangulateio(std::ostream& dump_file)
41  {
43 
44 #ifdef OOMPH_HAS_MPI
45  // If the mesh is not distributed then process what follows
46  if (!this->is_mesh_distributed())
47  {
48 #endif // #ifdef OOMPH_HAS_MPI
49 
50  // Loop over all boundary nodes and dump out boundary coordinates
51  // if they exist
52  Vector<double> zeta(1);
53  unsigned nb = nboundary();
54  for (unsigned b = 0; b < nb; b++)
55  {
57  {
58  dump_file << "1 # Boundary coordinate for boundary " << b
59  << " does exist\n";
60  unsigned nnod = nboundary_node(b);
61  dump_file << nnod << " # Number of dumped boundary nodes\n";
62  for (unsigned j = 0; j < nnod; j++)
63  {
64  Node* nod_pt = boundary_node_pt(b, j);
65  nod_pt->get_coordinates_on_boundary(b, zeta);
66  dump_file << zeta[0] << std::endl;
67  }
68  dump_file << "-999 # Done boundary coords for boundary " << b << "\n";
69  }
70  else
71  {
72  dump_file << "0 # Boundary coordinate for boundary " << b
73  << " does not exist\n";
74  }
75  }
76 
77 #ifdef OOMPH_HAS_MPI
78  }
79 #endif // #ifdef OOMPH_HAS_MPI
80  }
81 
82 
83  //==============================================================
84  /// Regenerate the mesh from a dumped triangulateio file
85  /// and dumped boundary coordinates of boundary nodes
86  //==============================================================
87  void TriangleMeshBase::remesh_from_triangulateio(std::istream& restart_file)
88  {
89 #ifdef PARANOID
90  // Record number of boundaries
91  unsigned nbound_old = nboundary();
92 #endif
93 
94  // Clear the existing triangulate io
96 
97  // Read the data into the file
99 
100  // Now remesh from the new data structure
102 
103 #ifdef OOMPH_HAS_MPI
104  // If the mesh is not distributed then process what follows
105  if (!this->is_mesh_distributed())
106  {
107 #endif // #ifdef OOMPH_HAS_MPI
108 
109 #ifdef PARANOID
110  // Record number of boundary nodes after remesh
111  unsigned nbound_new = nboundary();
112  if (nbound_new != nbound_old)
113  {
114  std::ostringstream error_stream;
115  error_stream
116  << "Number of boundaries before remesh from triangulateio, "
117  << nbound_new << ",\ndoesn't match number boundaries afterwards, "
118  << nbound_old
119  << ". Have you messed \naround with boundary nodes in the "
120  << "derived mesh constructor (or after calling \nit)? If so,"
121  << " the dump/restart won't work as written at the moment.";
122  throw OomphLibError(
123  error_stream.str(), OOMPH_CURRENT_FUNCTION, OOMPH_EXCEPTION_LOCATION);
124  }
125 #endif
126 
127 
128  // Loop over all boundary nodes and read boundary coordinates
129  // if they exist
130  Vector<double> zeta(1);
131  std::string input_string;
132  unsigned nb = nboundary();
133  for (unsigned b = 0; b < nb; b++)
134  {
135  // Read line up to termination sign
136  getline(restart_file, input_string, '#');
137 
138  // Ignore rest of line
139  restart_file.ignore(80, '\n');
140 
141  // Did boundary coordinate exist?
142  const unsigned bound_coord_exists = atoi(input_string.c_str());
143  if (bound_coord_exists == 1)
144  {
145  // Remember it!
146  Boundary_coordinate_exists[b] = true;
147 
148  // Read line up to termination sign
149  getline(restart_file, input_string, '#');
150 
151  // Ignore rest of line
152  restart_file.ignore(80, '\n');
153 
154  // How many nodes did we dump?
155  const unsigned nnod_dumped = atoi(input_string.c_str());
156 
157  // Does it match?
158  unsigned nnod = nboundary_node(b);
159  if (nnod != nnod_dumped)
160  {
161  std::ostringstream error_stream;
162  error_stream << "Number of dumped boundary nodes " << nnod_dumped
163  << " doesn't match number of nodes on boundary " << b
164  << ": " << nnod << std::endl;
165  throw OomphLibError(error_stream.str(),
166  OOMPH_CURRENT_FUNCTION,
167  OOMPH_EXCEPTION_LOCATION);
168  }
169 
170  // Loop over all nodes
171  for (unsigned j = 0; j < nnod; j++)
172  {
173  // Read line up to termination sign
174  getline(restart_file, input_string);
175 
176  // Boundary coordinate
177  zeta[0] = atof(input_string.c_str());
178 
179  // Set it
180  Node* nod_pt = boundary_node_pt(b, j);
181  nod_pt->set_coordinates_on_boundary(b, zeta);
182  }
183 
184  // Read line up to termination sign
185  getline(restart_file, input_string, '#');
186 
187  // Ignore rest of line
188  restart_file.ignore(80, '\n');
189 
190  // Have we reached the end?
191  const int check = atoi(input_string.c_str());
192  if (check != -999)
193  {
194  std::ostringstream error_stream;
195  error_stream << "Haven't read all nodes on boundary " << b
196  << std::endl;
197  throw OomphLibError(error_stream.str(),
198  OOMPH_CURRENT_FUNCTION,
199  OOMPH_EXCEPTION_LOCATION);
200  }
201  }
202  else
203  {
204  oomph_info << "Restart: Boundary coordinate for boundary " << b
205  << " does not exist.\n";
206  }
207  }
208 #ifdef OOMPH_HAS_MPI
209  } // if (!this->is_mesh_distributed())
210 #endif // #ifdef OOMPH_HAS_MPI
211  }
212 
213 
214  //==============================================================
215  /// Write a Triangulateio_object file of the TriangulateIO object
216  /// String s is add to assign a different value for
217  /// input and/or output structure.
218  /// The function give the same result of the "report" function
219  /// included in the tricall.c, esternal_src.
220  //==============================================================
222  std::string& s)
223  {
224  std::ofstream outfile;
225  char filename[100];
226 
227  sprintf(filename, "Triangulateio_object_%s.dat", s.c_str());
228  outfile.open(filename);
229  outfile << "# Triangulateio object values:\n\n" << std::endl;
230 
231  // Write points coordinates
232  if (triangle.numberofpoints != 0)
233  {
234  outfile << "# Triangulateio number of points is:"
235  << triangle.numberofpoints << std::endl;
236  }
237  if (triangle.pointlist != NULL)
238  {
239  outfile << "# Vertex coordinates are:" << std::endl;
240  for (int k = 0; k < triangle.numberofpoints * 2; k += 2)
241  {
242  outfile << (k * 0.5) + 1 << " " << triangle.pointlist[k] << " "
243  << triangle.pointlist[k + 1] << std::endl;
244  }
245  }
246 
247  // Write points attribute list
248  if (triangle.numberofpointattributes != 0)
249  {
250  outfile << "# Triangulateio number of points attributelist is:"
251  << triangle.numberofpointattributes << std::endl;
252  }
253  if (triangle.pointattributelist != NULL)
254  {
255  outfile << "# Vertex attribute are:" << std::endl;
256  for (int k = 0; k < triangle.numberofpointattributes; k++)
257  {
258  outfile << triangle.pointattributelist[k] << std::endl;
259  }
260  }
261 
262  // Write point markers list
263  if (triangle.pointmarkerlist != NULL)
264  {
265  outfile << "# Vertex Markers are:" << std::endl;
266  for (int k = 0; k < triangle.numberofpoints; k++)
267  {
268  outfile << triangle.pointmarkerlist[k] << std::endl;
269  }
270  }
271 
272  // Write the 1.node file used by the showme function
273  std::ofstream nodefile;
274  char nodename[100];
275 
276  sprintf(nodename, "file_%s.1.node", s.c_str());
277  nodefile.open(nodename);
278  nodefile << triangle.numberofpoints << " 2 "
279  << triangle.numberofpointattributes << " 0" << std::endl;
280  for (int j = 0; j < triangle.numberofpoints * 2; j += 2)
281  {
282  nodefile << (j / 2) + 1 << " " << triangle.pointlist[j] << " "
283  << triangle.pointlist[j + 1] << std::endl;
284  }
285  nodefile.close();
286 
287 
288  // Write segments edge elements
289  if (triangle.numberofsegments != 0)
290  {
291  outfile << "# The number of segments is:" << triangle.numberofsegments
292  << std::endl;
293  }
294  if (triangle.segmentlist != NULL)
295  {
296  outfile << "# Segments are:" << std::endl;
297  for (int k = 0; k < triangle.numberofsegments * 2; k += 2)
298  {
299  outfile << triangle.segmentlist[k] << " "
300  << triangle.segmentlist[k + 1] << std::endl;
301  }
302  }
303 
304  // Write segments markers list
305  if (triangle.segmentmarkerlist != NULL)
306  {
307  outfile << "# Segments Markers are:" << std::endl;
308  for (int k = 0; k < triangle.numberofsegments; k++)
309  {
310  outfile << triangle.segmentmarkerlist[k] << std::endl;
311  }
312  }
313 
314  // Write regions
315  if (triangle.numberofregions != 0)
316  {
317  outfile << "# The number of region is:" << triangle.numberofregions
318  << std::endl;
319  }
320 
321  // Write holes
322  if (triangle.numberofholes != 0)
323  {
324  outfile << "# The number of holes is:" << triangle.numberofholes
325  << std::endl;
326  }
327  if (triangle.holelist != NULL)
328  {
329  outfile << "# Holes are:" << std::endl;
330  for (int k = 0; k < triangle.numberofholes * 2; k += 2)
331  {
332  outfile << triangle.holelist[k] << " " << triangle.holelist[k + 1]
333  << std::endl;
334  }
335  }
336 
337  // Write triangles
338  if (triangle.numberoftriangles != 0)
339  {
340  outfile << "# Triangulateio number of triangles:"
341  << triangle.numberoftriangles << std::endl;
342  }
343  if (triangle.numberofcorners != 0)
344  {
345  outfile << "# Triangulateio number of corners:"
346  << triangle.numberofcorners << std::endl;
347  }
348  if (triangle.numberoftriangleattributes != 0)
349  {
350  outfile << "# Triangulateio number of triangles attributes:"
351  << triangle.numberoftriangleattributes << std::endl;
352  }
353  if (triangle.trianglelist != NULL)
354  {
355  outfile << "# Traingles are:" << std::endl;
356  for (int k = 0; k < triangle.numberoftriangles * 3; k += 3)
357  {
358  outfile << triangle.trianglelist[k] << " "
359  << triangle.trianglelist[k + 1] << " "
360  << triangle.trianglelist[k + 2] << std::endl;
361  }
362  }
363 
364  if (triangle.trianglearealist != NULL)
365  {
366  outfile << "# Triangle's areas are:" << std::endl;
367  for (int k = 0; k < triangle.numberoftriangles; k++)
368  {
369  outfile << triangle.trianglearealist[k] << std::endl;
370  }
371  }
372 
373  if (triangle.trianglelist != NULL)
374  {
375  // Write the 1.ele file used by the showme function
376  std::ofstream elefile;
377  char elename[100];
378 
379  sprintf(elename, "file_%s.1.ele", s.c_str());
380  elefile.open(elename);
381  elefile << triangle.numberoftriangles << " 3 0" << std::endl;
382  for (int j = 0; j < triangle.numberoftriangles * 3; j += 3)
383  {
384  elefile << (j / 3) + 1 << " " << triangle.trianglelist[j] << " "
385  << triangle.trianglelist[j + 1] << " "
386  << triangle.trianglelist[j + 2] << std::endl;
387  }
388  elefile.close();
389  }
390 
391  outfile.close();
392  }
393 
394 #endif
395 
396  //================================================================
397  /// Setup lookup schemes which establish which elements are located
398  /// next to which boundaries (Doc to outfile if it's open).
399  //================================================================
401  {
402  // Should we document the output here
403  bool doc = false;
404 
405  if (outfile) doc = true;
406 
407  // Number of boundaries
408  unsigned nbound = nboundary();
409 
410  // Wipe/allocate storage for arrays
411  Boundary_element_pt.clear();
412  Face_index_at_boundary.clear();
413  Boundary_element_pt.resize(nbound);
414  Face_index_at_boundary.resize(nbound);
415 
416  // Temporary vector of vectors of pointers to elements on the boundaries:
417  // This is a vector to ensure that order is strictly preserved
418  Vector<Vector<FiniteElement*>> vector_of_boundary_element_pt;
419  vector_of_boundary_element_pt.resize(nbound);
420 
421  // Matrix map for working out the fixed face for elements on boundary
423 
424  // Loop over elements
425  //-------------------
426  unsigned nel = nelement();
427 
428  // Get pointer to vector of boundaries that the
429  // node lives on
430  Vector<std::set<unsigned>*> boundaries_pt(3, 0);
431 
432  // Data needed to deal with edges through the
433  // interior of the domain
434  std::map<Edge, unsigned> edge_count;
435  std::map<Edge, TriangleBoundaryHelper::BCInfo> edge_bcinfo;
436  std::map<Edge, TriangleBoundaryHelper::BCInfo> face_info;
438  Vector<unsigned> bonus(nbound);
439 
440  // When using internal boundaries, an edge can be related to more than
441  // one element (because of both sides of the internal boundaries)
442  std::map<Edge, Vector<TriangleBoundaryHelper::BCInfo>> edge_internal_bnd;
443 
444  for (unsigned e = 0; e < nel; e++)
445  {
446  // Get pointer to element
448 
449  if (doc)
450  {
451  outfile << "Element: " << e << " " << fe_pt << std::endl;
452  }
453 
454  // Only include 2D elements! Some meshes contain interface elements too.
455  if (fe_pt->dim() == 2)
456  {
457  // Loop over the element's nodes and find out which boundaries they're
458  // on
459  // ----------------------------------------------------------------------
460 
461  // We need only loop over the corner nodes
462  for (unsigned i = 0; i < 3; i++)
463  {
464  fe_pt->node_pt(i)->get_boundaries_pt(boundaries_pt[i]);
465  }
466 
467  // Find the common boundaries of each edge
468  Vector<std::set<unsigned>> edge_boundary(3);
469 
470  // Edge 0 connects points 1 and 2
471  //-----------------------------
472 
473  if (boundaries_pt[1] && boundaries_pt[2])
474  {
475  // Create the corresponding edge
476  Edge edge0(fe_pt->node_pt(1), fe_pt->node_pt(2));
477 
478  // Update infos about this edge
480  info.Face_id = 0;
481  info.FE_pt = fe_pt;
482 
483  std::set_intersection(boundaries_pt[1]->begin(),
484  boundaries_pt[1]->end(),
485  boundaries_pt[2]->begin(),
486  boundaries_pt[2]->end(),
487  std::insert_iterator<std::set<unsigned>>(
488  edge_boundary[0], edge_boundary[0].begin()));
489  std::set<unsigned>::iterator it0 = edge_boundary[0].begin();
490 
491  // Edge does exist:
492  if (edge_boundary[0].size() > 0)
493  {
494  info.Boundary = *it0;
495 
496  // How many times this edge has been visited
497  edge_count[edge0]++;
498 
499  // Update edge_bcinfo
500  edge_bcinfo.insert(std::make_pair(edge0, info));
501 
502  // ... and also update the info associated with internal bnd
503  edge_internal_bnd[edge0].push_back(info);
504  }
505  }
506 
507  // Edge 1 connects points 0 and 2
508  //-----------------------------
509 
510  if (boundaries_pt[0] && boundaries_pt[2])
511  {
512  std::set_intersection(boundaries_pt[0]->begin(),
513  boundaries_pt[0]->end(),
514  boundaries_pt[2]->begin(),
515  boundaries_pt[2]->end(),
516  std::insert_iterator<std::set<unsigned>>(
517  edge_boundary[1], edge_boundary[1].begin()));
518 
519  // Create the corresponding edge
520  Edge edge1(fe_pt->node_pt(0), fe_pt->node_pt(2));
521 
522  // Update infos about this edge
524  info.Face_id = 1;
525  info.FE_pt = fe_pt;
526  std::set<unsigned>::iterator it1 = edge_boundary[1].begin();
527 
528  // Edge does exist:
529  if (edge_boundary[1].size() > 0)
530  {
531  info.Boundary = *it1;
532 
533  // How many times this edge has been visited
534  edge_count[edge1]++;
535 
536  // Update edge_bcinfo
537  edge_bcinfo.insert(std::make_pair(edge1, info));
538 
539  // ... and also update the info associated with internal bnd
540  edge_internal_bnd[edge1].push_back(info);
541  }
542  }
543 
544  // Edge 2 connects points 0 and 1
545  //-----------------------------
546 
547  if (boundaries_pt[0] && boundaries_pt[1])
548  {
549  std::set_intersection(boundaries_pt[0]->begin(),
550  boundaries_pt[0]->end(),
551  boundaries_pt[1]->begin(),
552  boundaries_pt[1]->end(),
553  std::insert_iterator<std::set<unsigned>>(
554  edge_boundary[2], edge_boundary[2].begin()));
555 
556  // Create the corresponding edge
557  Edge edge2(fe_pt->node_pt(0), fe_pt->node_pt(1));
558 
559  // Update infos about this edge
561  info.Face_id = 2;
562  info.FE_pt = fe_pt;
563  std::set<unsigned>::iterator it2 = edge_boundary[2].begin();
564 
565  // Edge does exist:
566  if (edge_boundary[2].size() > 0)
567  {
568  info.Boundary = *it2;
569 
570  // How many times this edge has been visited
571  edge_count[edge2]++;
572 
573  // Update edge_bcinfo
574  edge_bcinfo.insert(std::make_pair(edge2, info));
575 
576  // ... and also update the info associated with internal bnd
577  edge_internal_bnd[edge2].push_back(info);
578  }
579  }
580 
581 
582 #ifdef PARANOID
583 
584  // Check if edge is associated with multiple boundaries
585 
586  // We now know whether any edges lay on the boundaries
587  for (unsigned i = 0; i < 3; i++)
588  {
589  // How many boundaries are there
590  unsigned count = 0;
591 
592  // Loop over all the members of the set and add to the count
593  // and set the boundary
594  for (std::set<unsigned>::iterator it = edge_boundary[i].begin();
595  it != edge_boundary[i].end();
596  ++it)
597  {
598  ++count;
599  }
600 
601  // If we're on more than one boundary, this is weird, so die
602  if (count > 1)
603  {
604  std::ostringstream error_stream;
605  error_stream << "Edge " << i << " is located on " << count
606  << " boundaries.\n";
607  error_stream << "This is rather strange, so I'm going to die\n";
608  throw OomphLibError(error_stream.str(),
609  OOMPH_CURRENT_FUNCTION,
610  OOMPH_EXCEPTION_LOCATION);
611  }
612  }
613 
614 #endif
615 
616  // Now we set the pointers to the boundary sets to zero
617  for (unsigned i = 0; i < 3; i++)
618  {
619  boundaries_pt[i] = 0;
620  }
621  }
622  } // end of loop over all elements
623 
624  // Loop over all edges that are located on a boundary
625  typedef std::map<Edge, TriangleBoundaryHelper::BCInfo>::iterator ITE;
626  for (ITE it = edge_bcinfo.begin(); it != edge_bcinfo.end(); it++)
627  {
628  Edge current_edge = it->first;
629  unsigned bound = it->second.Boundary;
630 
631  // If the edge has been visited only once
632  if (edge_count[current_edge] == 1)
633  {
634  // Count the edges that are on the same element and on the same boundary
635  face_count(static_cast<unsigned>(bound), it->second.FE_pt) =
636  face_count(static_cast<unsigned>(bound), it->second.FE_pt) + 1;
637 
638  // If such edges exist, let store the corresponding element
639  if (face_count(bound, it->second.FE_pt) > 1)
640  {
641  // Update edge's infos
643  info.Face_id = it->second.Face_id;
644  info.FE_pt = it->second.FE_pt;
645  info.Boundary = it->second.Boundary;
646 
647  // Add it to FIinfo, that stores infos of problematic elements
648  face_info.insert(std::make_pair(current_edge, info));
649 
650  // How many edges on which boundary have to be added
651  bonus[bound]++;
652  }
653  else
654  {
655  // Add element and face to the appropriate vectors
656  // Does the pointer already exits in the vector
657  Vector<FiniteElement*>::iterator b_el_it = std::find(
658  vector_of_boundary_element_pt[static_cast<unsigned>(bound)].begin(),
659  vector_of_boundary_element_pt[static_cast<unsigned>(bound)].end(),
660  it->second.FE_pt);
661 
662  // Only insert if we have not found it (i.e. got to the end)
663  if (b_el_it ==
664  vector_of_boundary_element_pt[static_cast<unsigned>(bound)].end())
665  {
666  vector_of_boundary_element_pt[static_cast<unsigned>(bound)]
667  .push_back(it->second.FE_pt);
668  }
669 
670  // set_of_boundary_element_pt[static_cast<unsigned>(bound)].insert(
671  // it->second.FE_pt);
672  face_identifier(static_cast<unsigned>(bound), it->second.FE_pt) =
673  it->second.Face_id;
674  }
675  }
676 
677  } // End of "adding-boundaries"-loop
678 
679 
680  // Now copy everything across into permanent arrays
681  //-------------------------------------------------
682 
683  // Loop over boundaries
684  for (unsigned i = 0; i < nbound; i++)
685  {
686  // Number of elements on this boundary that have to be added
687  // in addition to other elements
688  unsigned bonus1 = bonus[i];
689 
690  // Number of elements on this boundary
691  unsigned nel = vector_of_boundary_element_pt[i].size() + bonus1;
692 
693  // Allocate storage for the coordinate identifiers
694  Face_index_at_boundary[i].resize(nel);
695 
696  unsigned e_count = 0;
698  for (IT it = vector_of_boundary_element_pt[i].begin();
699  it != vector_of_boundary_element_pt[i].end();
700  it++)
701  {
702  // Recover pointer to element
703  FiniteElement* fe_pt = *it;
704 
705  // Add to permanent storage
706  Boundary_element_pt[i].push_back(fe_pt);
707 
708  Face_index_at_boundary[i][e_count] = face_identifier(i, fe_pt);
709 
710  // Increment counter
711  e_count++;
712  }
713  // We add the elements that have two or more edges on this boundary
714  for (ITE itt = face_info.begin(); itt != face_info.end(); itt++)
715  {
716  if (itt->second.Boundary == i)
717  {
718  // Add to permanent storage
719  Boundary_element_pt[i].push_back(itt->second.FE_pt);
720 
721  Face_index_at_boundary[i][e_count] = itt->second.Face_id;
722 
723  e_count++;
724  }
725  }
726 
727  } // End of loop over boundaries
728 
729  // Doc?
730  //-----
731  if (doc)
732  {
733  // Loop over boundaries
734  for (unsigned i = 0; i < nbound; i++)
735  {
736  unsigned nel = Boundary_element_pt[i].size();
737  outfile << "Boundary: " << i << " is adjacent to " << nel << " elements"
738  << std::endl;
739 
740  // Loop over elements on given boundary
741  for (unsigned e = 0; e < nel; e++)
742  {
744  outfile << "Boundary element:" << fe_pt
745  << " Face index of boundary is "
746  << Face_index_at_boundary[i][e] << std::endl;
747  }
748  }
749  }
750 
751  // Lookup scheme has now been setup yet
753  }
754 } // namespace oomph
e
Definition: cfortran.h:571
static char t char * s
Definition: cfortran.h:568
cstr elem_len * i
Definition: cfortran.h:603
//////////////////////////////////////////////////////////////////////// ////////////////////////////...
Definition: mesh.h:2692
A general Finite Element class.
Definition: elements.h:1313
Node *& node_pt(const unsigned &n)
Return a pointer to the local node n.
Definition: elements.h:2175
unsigned dim() const
Return the spatial dimension of the element, i.e. the number of local coordinates required to paramet...
Definition: elements.h:2611
MapMatrixMixed is a generalised, STL-map-based, sparse(ish) matrix class with mixed indices.
Definition: map_matrix.h:109
unsigned long nboundary_node(const unsigned &ibound) const
Return number of nodes on a particular boundary.
Definition: mesh.h:833
bool is_mesh_distributed() const
Boolean to indicate if Mesh has been distributed.
Definition: mesh.h:1588
Vector< Vector< FiniteElement * > > Boundary_element_pt
Vector of Vector of pointers to elements on the boundaries: Boundary_element_pt(b,...
Definition: mesh.h:91
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...
Definition: mesh.h:87
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:190
FiniteElement * finite_element_pt(const unsigned &e) const
Upcast (downcast?) to FiniteElement (needed to access FiniteElement member functions).
Definition: mesh.h:473
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:95
unsigned nboundary() const
Return number of boundaries.
Definition: mesh.h:827
Node *& boundary_node_pt(const unsigned &b, const unsigned &n)
Return pointer to node n on boundary b.
Definition: mesh.h:493
unsigned long nelement() const
Return number of elements in the mesh.
Definition: mesh.h:590
Nodes are derived from Data, but, in addition, have a definite (Eulerian) position in a space of a gi...
Definition: nodes.h:906
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:1365
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...
Definition: nodes.cc:2394
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....
Definition: nodes.cc:2379
An OomphLibError object which should be thrown when an run-time error is encountered....
virtual void remesh_from_internal_triangulateio()
Virtual function that is used for specific remeshing from the triangulateio.
void dump_triangulateio(std::ostream &dump_file)
Dump the triangulateio structure to a dump file and record boundary coordinates of boundary nodes.
TriangulateIO Triangulateio
TriangulateIO representation of the mesh.
void remesh_from_triangulateio(std::istream &restart_file)
Regenerate the mesh from a dumped triangulateio file and dumped boundary coordinates of boundary node...
void setup_boundary_element_info()
Setup lookup schemes which establish whic elements are located next to mesh's boundaries (wrapper to ...
Definition: triangle_mesh.h:88
void write_triangulateio(TriangulateIO &triangulate_io, std::string &s)
Helper function. Write a TriangulateIO object file with all the triangulateio fields....
std::string string(const unsigned &i)
Return the i-th string or "" if the relevant string hasn't been defined.
void dump_triangulateio(TriangulateIO &triangle_io, std::ostream &dump_file)
Write all the triangulateio data to disk in a dump file that can then be used to restart simulations.
void read_triangulateio(std::istream &restart_file, TriangulateIO &triangle_io)
Read the triangulateio data from a dump file on disk, which can then be used to restart simulations.
void clear_triangulateio(TriangulateIO &triangulate_io, const bool &clear_hole_data)
Clear TriangulateIO structure.
//////////////////////////////////////////////////////////////////// ////////////////////////////////...
OomphInfo oomph_info
Single (global) instantiation of the OomphInfo object – this is used throughout the library as a "rep...
FiniteElement * FE_pt
Pointer to bulk finite element.
The Triangle data structure, modified from the triangle.h header supplied with triangle 1....
double * pointlist
Pointer to list of points x coordinate followed by y coordinate.
int * pointmarkerlist
Pointer to list of point markers.
double * pointattributelist
Pointer to list of point attributes.