tetgen_mesh.template.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 #ifndef OOMPH_TETGEN_MESH_TEMPLATE_CC
31 #define OOMPH_TETGEN_MESH_TEMPLATE_CC
32 
33 
34 #include<algorithm>
35 
36 #include "tetgen_mesh.template.h"
37 #include "../generic/Telements.h"
38 #include "../generic/map_matrix.h"
39 
40 
41 
42 namespace oomph
43 {
44 
45 
46 
47 ///////////////////////////////////////////////////////////////////////
48 ///////////////////////////////////////////////////////////////////////
49 ///////////////////////////////////////////////////////////////////////
50 
51 
52 
53 //========================================================================
54 /// Build unstructured tet mesh based on output from scaffold
55 //========================================================================
56 template <class ELEMENT>
58  const bool &use_attributes)
59 {
60  // Mesh can only be built with 3D Telements.
61  MeshChecker::assert_geometric_element<TElementGeometricBase,ELEMENT>(3);
62 
63  // Create space for elements
64  unsigned nelem=Tmp_mesh_pt->nelement();
65  Element_pt.resize(nelem);
66 
67  // Create space for nodes
68  unsigned nnode_scaffold=Tmp_mesh_pt->nnode();
69  Node_pt.resize(nnode_scaffold);
70 
71  // Set number of boundaries
72  unsigned nbound=Tmp_mesh_pt->nboundary();
73  set_nboundary(nbound);
74  Boundary_element_pt.resize(nbound);
75  Face_index_at_boundary.resize(nbound);
76 
77  //If we have different regions, then resize the region
78  //information
79  if(use_attributes)
80  {
81  Boundary_region_element_pt.resize(nbound);
82  Face_index_region_at_boundary.resize(nbound);
83  }
84 
85  // Build elements
86  for (unsigned e=0;e<nelem;e++)
87  {
88  Element_pt[e]=new ELEMENT;
89  }
90 
91  // Number of nodes per element
92  unsigned nnod_el=Tmp_mesh_pt->finite_element_pt(0)->nnode();
93 
94  // Setup map to check the (pseudo-)global node number
95  // Nodes whose number is zero haven't been copied across
96  // into the mesh yet.
97  std::map<Node*,unsigned> global_number;
98  unsigned global_count=0;
99 
100  // Map of element attribute pairs
101  std::map<double,Vector<FiniteElement*> > element_attribute_map;
102 
103  // Loop over elements in scaffold mesh, visit their nodes
104  for (unsigned e=0;e<nelem;e++)
105  {
106  // Loop over all nodes in element
107  for (unsigned j=0;j<nnod_el;j++)
108  {
109 
110  // Pointer to node in the scaffold mesh
111  Node* scaffold_node_pt=Tmp_mesh_pt->finite_element_pt(e)->node_pt(j);
112 
113  // Get the (pseudo-)global node number in scaffold mesh
114  // (It's zero [=default] if not visited this one yet)
115  unsigned j_global=global_number[scaffold_node_pt];
116 
117  // Haven't done this one yet
118  if (j_global==0)
119  {
120  // Get pointer to set of mesh boundaries that this
121  // scaffold node occupies; NULL if the node is not on any boundary
122  std::set<unsigned>* boundaries_pt;
123  scaffold_node_pt->get_boundaries_pt(boundaries_pt);
124 
125  // Is it on boundaries?
126  if (boundaries_pt!=0)
127  {
128  // Create new boundary node
129  Node* new_node_pt=finite_element_pt(e)->
130  construct_boundary_node(j,time_stepper_pt);
131 
132  // Give it a number (not necessarily the global node
133  // number in the scaffold mesh -- we just need something
134  // to keep track...)
135  global_count++;
136  global_number[scaffold_node_pt]=global_count;
137 
138  // Add to boundaries
139  for(std::set<unsigned>::iterator it=boundaries_pt->begin();
140  it!=boundaries_pt->end();++it)
141  {
142  add_boundary_node(*it,new_node_pt);
143  }
144  }
145  // Build normal node
146  else
147  {
148  // Create new normal node
149  finite_element_pt(e)->construct_node(j,time_stepper_pt);
150 
151  // Give it a number (not necessarily the global node
152  // number in the scaffold mesh -- we just need something
153  // to keep track...)
154  global_count++;
155  global_number[scaffold_node_pt]=global_count;
156  }
157 
158  // Copy new node, created using the NEW element's construct_node
159  // function into global storage, using the same global
160  // node number that we've just associated with the
161  // corresponding node in the scaffold mesh
162  Node_pt[global_count-1]=finite_element_pt(e)->node_pt(j);
163 
164  // Assign coordinates
165  Node_pt[global_count-1]->x(0)=scaffold_node_pt->x(0);
166  Node_pt[global_count-1]->x(1)=scaffold_node_pt->x(1);
167  Node_pt[global_count-1]->x(2)=scaffold_node_pt->x(2);
168 
169  }
170  // This one has already been done: Copy across
171  else
172  {
173  finite_element_pt(e)->node_pt(j)=Node_pt[j_global-1];
174  }
175  }
176 
177  //Store the attributes in the map
178  if(use_attributes)
179  {
180  element_attribute_map[Tmp_mesh_pt->element_attribute(e)].push_back(
181  finite_element_pt(e));
182  }
183  }
184 
185  //Now let's construct lists
186  //Find the number of attributes
187  if(use_attributes)
188  {
189  unsigned n_attribute = element_attribute_map.size();
190  //There are n_attribute different regions
191  Region_element_pt.resize(n_attribute);
192  Region_attribute.resize(n_attribute);
193  //Copy the vectors in the map over to our internal storage
194  unsigned count = 0;
195  for(std::map<double,Vector<FiniteElement*> >::iterator it =
196  element_attribute_map.begin(); it != element_attribute_map.end();++it)
197  {
198  Region_attribute[count] = it->first;
199  Region_element_pt[count] = it->second;
200  ++count;
201  }
202  }
203 
204  // At this point we've created all the elements and
205  // created their vertex nodes. Now we need to create
206  // the additional (midside and internal) nodes!
207  unsigned boundary_id;
208 
209  // Get number of nodes along element edge and dimension of element (3)
210  // from first element
211  unsigned n_node_1d=finite_element_pt(0)->nnode_1d();
212 
213  // At the moment we're only able to deal with nnode_1d=2 or 3.
214  if ((n_node_1d!=2)&&(n_node_1d!=3))
215  {
216  std::ostringstream error_message;
217  error_message << "Mesh generation from tetgen currently only works\n";
218  error_message << "for nnode_1d = 2 or 3. You're trying to use it\n";
219  error_message << "for nnode_1d=" << n_node_1d << std::endl;
220 
221  throw OomphLibError(error_message.str(),
222  OOMPH_CURRENT_FUNCTION,
223  OOMPH_EXCEPTION_LOCATION);
224  }
225 
226  // Spatial dimension of element = number of local coordinates
227  unsigned dim=finite_element_pt(0)->dim();
228 
229  // Storage for the local coordinate of the new node
230  Vector<double> s(dim);
231 
232  // Get number of nodes in the element from first element
233  unsigned n_node=finite_element_pt(0)->nnode();
234 
235  // Storage for each global edge of the mesh
236  unsigned n_global_edge = Tmp_mesh_pt->nglobal_edge();
237  Vector<Vector<Node*> > nodes_on_global_edge(n_global_edge);
238 
239  //Storage for each global face of the mesh
240  unsigned n_global_face = Tmp_mesh_pt->nglobal_face();
241  Vector<Vector<Node*> > nodes_on_global_face(n_global_face);
242 
243  // Map storing the mid-side of an edge; edge identified by
244  // pointers to vertex nodes in scaffold mesh
245  //MapMatrix<Node*,Node*> central_edge_node_pt;
246  //Node* edge_node1_pt=0;
247  //Node* edge_node2_pt=0;
248 
249  // Map storing the mid point of a face; face identified by
250  // set of pointers to vertex nodes in scaffold mesh
251  //std::map<std::set<Node*>,Node*> central_face_node_pt;
252  //std::set<Node*> face_nodes_pt;
253 
254  //Mapping of Tetgen faces to face nodes in the enriched element
255  unsigned face_map[4] = {1,0,2,3};
256 
257  //Storage for the faces shared by the edges
258  const unsigned faces_on_edge[6][2]={
259  {0,1},{0,2},{1,2},{0,3},{2,3},{1,3}};
260 
261  // Loop over all elements
262  for(unsigned e=0;e<nelem;e++)
263  {
264  //Cache pointers to the elements
265  FiniteElement* const elem_pt = this->finite_element_pt(e);
266  FiniteElement* const tmp_elem_pt = Tmp_mesh_pt->finite_element_pt(e);
267 
268  // The number of edge nodes is 4 + 6*(n_node1d-2)
269  unsigned n_edge_node = 4 + 6*(n_node_1d-2);
270 
271  //Now loop over the edge nodes
272  //assuming that the numbering scheme is the same as the triangles
273  //which puts edge nodes in ascending order.
274  //We don't have any higher than quadratic at the moment, so it's
275  //a bit academic really.
276 
277  //Only bother if we actually have some edge nodes
278  if(n_edge_node > 4)
279  {
280  //Start from node number 4
281  unsigned n=4;
282 
283  //Loop over the edges
284  for(unsigned j=0;j<6;++j)
285  {
286  //Find the global edge index
287  unsigned edge_index = Tmp_mesh_pt->edge_index(e,j);
288 
289  //Use the intersection of the appropriate faces to determine
290  //whether the boundaries on which an edge lies
291  std::set<unsigned> edge_boundaries;
292  for(unsigned i=0;i<2;++i)
293  {
294  unsigned face_boundary_id =
295  Tmp_mesh_pt->face_boundary(e,faces_on_edge[j][i]);
296  if(face_boundary_id > 0)
297  {
298  edge_boundaries.insert(face_boundary_id);
299  }
300  }
301 
302  //If the nodes on the edge have not been allocated, construct them
303  if(nodes_on_global_edge[edge_index].size()==0)
304  {
305  //Now loop over the nodes on the edge
306  for(unsigned j2=0;j2<n_node_1d-2;++j2)
307  {
308  //Storage for the new node
309  Node* new_node_pt = 0;
310 
311  //If the edge is on a boundary, determined from the
312  //scaffold mesh, construct a boundary node
313  //The use of the scaffold mesh's edge_boundary data structure
314  //ensures that a boundary node is created, even if the faces of
315  //the current element do not lie on boundaries
316  if(Tmp_mesh_pt->edge_boundary(edge_index) == true)
317  {
318  new_node_pt =
319  elem_pt->construct_boundary_node(n,time_stepper_pt);
320  //Add it to the boundaries in the set,
321  //remembering to subtract one to get to the oomph-lib numbering
322  //scheme
323  for(std::set<unsigned>::iterator it = edge_boundaries.begin();
324  it!=edge_boundaries.end();++it)
325  {
326  this->add_boundary_node((*it)-1,new_node_pt);
327  }
328  }
329  //Otherwise construct a normal node
330  else
331  {
332  new_node_pt =
333  elem_pt->construct_node(n,time_stepper_pt);
334  }
335 
336  //Find the local coordinates of the node
337  elem_pt->local_coordinate_of_node(n,s);
338 
339  //Find the coordinates of the new node from the exiting and
340  //fully-functional element in the scaffold mesh
341  for(unsigned i=0;i<dim;++i)
342  {
343  new_node_pt->x(i) = tmp_elem_pt->interpolated_x(s,i);
344  }
345 
346  //Add the newly created node to the global node list
347  Node_pt.push_back(new_node_pt);
348  //Add to the edge index
349  nodes_on_global_edge[edge_index].push_back(new_node_pt);
350  //Increment the local node number
351  ++n;
352  } //end of loop over edge nodes
353  }
354  //Otherwise just set the pointers (orientation assumed the same)
355  else
356  {
357  for(unsigned j2=0;j2<n_node_1d-2;++j2)
358  {
359  elem_pt->node_pt(n) =
360  nodes_on_global_edge[edge_index][j2];
361  //It is possible that the edge may be on additional boundaries
362  //through another element
363  //So add again (note that this function will not add to
364  //boundaries twice)
365  for(std::set<unsigned>::iterator it = edge_boundaries.begin();
366  it!=edge_boundaries.end();++it)
367  {
368  this->add_boundary_node((*it)-1,elem_pt->node_pt(n));
369  }
370  ++n;
371  }
372  }
373  } //End of loop over edges
374 
375  //Deal with enriched elements
376  if(n_node == 15)
377  {
378  //Now loop over the faces
379  for(unsigned j=0;j<4;++j)
380  {
381  //Find the boundary id of the face (need to map between node numbers
382  //and the face)
383  boundary_id = Tmp_mesh_pt->face_boundary(e,face_map[j]);
384 
385  //Find the global face index (need to map between node numbers and
386  //the face)
387  unsigned face_index = Tmp_mesh_pt->face_index(e,face_map[j]);
388 
389  //If the nodes on the face have not been allocated
390  if(nodes_on_global_face[face_index].size()==0)
391  {
392  //Storage for the new node
393  Node* new_node_pt=0;
394 
395  //If the face is on a boundary, construct a boundary node
396  if(boundary_id > 0)
397  {
398  new_node_pt =
399  elem_pt->construct_boundary_node(n,time_stepper_pt);
400  //Add it to the boundary
401  this->add_boundary_node(boundary_id-1,new_node_pt);
402  }
403  //Otherwise construct a normal node
404  else
405  {
406  new_node_pt =
407  elem_pt->construct_node(n,time_stepper_pt);
408  }
409 
410  //Find the local coordinates of the node
411  elem_pt->local_coordinate_of_node(n,s);
412 
413  //Find the coordinates of the new node from the exiting and
414  //fully-functional element in the scaffold mesh
415  for(unsigned i=0;i<dim;++i)
416  {
417  new_node_pt->x(i) = tmp_elem_pt->interpolated_x(s,i);
418  }
419 
420  //Add the newly created node to the global node list
421  Node_pt.push_back(new_node_pt);
422  //Add to the face index
423  nodes_on_global_face[face_index].push_back(new_node_pt);
424  //Increment the local node number
425  ++n;
426  }
427  //Otherwise just set the single node from the face element
428  else
429  {
430  elem_pt->node_pt(n) = nodes_on_global_face[face_index][0];
431  ++n;
432  }
433  } //end of loop over faces
434 
435  //Construct the element's central node, which is not on a boundary
436  {
437  Node* new_node_pt=
438  finite_element_pt(e)->construct_node(n,time_stepper_pt);
439  Node_pt.push_back(new_node_pt);
440 
441  // Find the local coordinates of the node
442  elem_pt->local_coordinate_of_node(n,s);
443 
444  // Find the coordinates of the new node from the existing
445  // and fully-functional element in the scaffold mesh
446  for(unsigned i=0;i<dim;i++)
447  {
448  new_node_pt->x(i)=tmp_elem_pt->interpolated_x(s,i);
449  }
450  }
451  } //End of enriched case
452 
453  } //End of case for edge nodes
454 
455 
456  //Now loop over the faces to setup the information about elements
457  //adjacent to the boundary
458  for(unsigned j=0;j<4;++j)
459  {
460  //Find the boundary id of the face
461  boundary_id = Tmp_mesh_pt->face_boundary(e,j);
462 
463  if(boundary_id > 0)
464  {
465  Boundary_element_pt[boundary_id-1].push_back(elem_pt);
466  //Need to put a shift in here because of an inconsistent naming
467  //convention between tetgen and our faces
468  //Tetgen Face 0 is our Face 3
469  //Tetgen Face 1 is our Face 2
470  //Tetgen Face 2 is our Face 1
471  //Tetgen Face 3 is our Face 0
472  Face_index_at_boundary[boundary_id-1].push_back(3-j);
473 
474  //If using regions set up the boundary information
475  if(use_attributes)
476  {
477  //Element adjacent to boundary
478  Boundary_region_element_pt[boundary_id-1]
479  [static_cast<unsigned>(Tmp_mesh_pt->element_attribute(e))].
480  push_back(elem_pt);
481  //Need to put a shift in here because of an inconsistent naming
482  //convention between triangle and face elements
483  Face_index_region_at_boundary[boundary_id-1]
484  [static_cast<unsigned>(Tmp_mesh_pt->element_attribute(e))].
485  push_back(3-j);
486  }
487  }
488  } //End of loop over faces
489 
490 
491  //Lookup scheme has now been setup
492  Lookup_for_elements_next_boundary_is_setup=true;
493 
494 
495  // /*
496 
497  // //For standard quadratic elements all nodes are edge nodes
498  // unsigned n_vertex_and_edge_node = n_node;
499  // //If we have enriched elements, there are only 10 vertex and edge nodes
500  // if(n_node==15)
501  // {
502  // //There are only 10 vertex and edge nodes
503  // n_vertex_and_edge_node = 10;
504  // }
505 
506  // // Loop over the new (edge) nodes in the element and create them.
507  // for(unsigned j=4;j<n_vertex_and_edge_node;j++)
508  // {
509 
510  // // Figure out edge nodes
511  // switch(j)
512  // {
513 
514  // // Node 4 is between nodes 0 and 1
515  // case 4:
516 
517  // edge_node1_pt=Tmp_mesh_pt->finite_element_pt(e)->node_pt(0);
518  // edge_node2_pt=Tmp_mesh_pt->finite_element_pt(e)->node_pt(1);
519  // break;
520 
521 
522  // // Node 5 is between nodes 0 and 2
523  // case 5:
524 
525  // edge_node1_pt=Tmp_mesh_pt->finite_element_pt(e)->node_pt(0);
526  // edge_node2_pt=Tmp_mesh_pt->finite_element_pt(e)->node_pt(2);
527  // break;
528 
529  // // Node 6 is between nodes 0 and 3
530  // case 6:
531 
532  // edge_node1_pt=Tmp_mesh_pt->finite_element_pt(e)->node_pt(0);
533  // edge_node2_pt=Tmp_mesh_pt->finite_element_pt(e)->node_pt(3);
534  // break;
535 
536  // // Node 7 is between nodes 1 and 2
537  // case 7:
538 
539  // edge_node1_pt=Tmp_mesh_pt->finite_element_pt(e)->node_pt(1);
540  // edge_node2_pt=Tmp_mesh_pt->finite_element_pt(e)->node_pt(2);
541  // break;
542 
543  // // Node 8 is between nodes 2 and 3
544  // case 8:
545 
546  // edge_node1_pt=Tmp_mesh_pt->finite_element_pt(e)->node_pt(2);
547  // edge_node2_pt=Tmp_mesh_pt->finite_element_pt(e)->node_pt(3);
548  // break;
549 
550  // // Node 9 is between nodes 1 and 3
551  // case 9:
552 
553  // edge_node1_pt=Tmp_mesh_pt->finite_element_pt(e)->node_pt(1);
554  // edge_node2_pt=Tmp_mesh_pt->finite_element_pt(e)->node_pt(3);
555  // break;
556 
557  // break;
558 
559  // //Error
560  // default:
561 
562  // throw OomphLibError("More than ten edge nodes in Tet Element",
563  // OOMPH_CURRENT_FUNCTION,
564  // OOMPH_EXCEPTION_LOCATION);
565  // }
566 
567 
568 
569 
570  // // Do we need a boundary node?
571  // bool need_boundary_node=false;
572 
573  // // hierher At some point fine tune via intersection of boundary sets
574  // if (edge_node1_pt->is_on_boundary()&&edge_node2_pt->is_on_boundary())
575  // {
576  // need_boundary_node=true;
577  // }
578 
579  // // Do we need a new node?
580  // if (central_edge_node_pt(edge_node1_pt,edge_node2_pt)==0)
581  // {
582  // Node* new_node_pt=0;
583 
584  // // Create new boundary node
585  // if (need_boundary_node)
586  // {
587  // new_node_pt=finite_element_pt(e)->
588  // construct_boundary_node(j,time_stepper_pt);
589  // }
590  // // Create new normal node
591  // else
592  // {
593  // new_node_pt=finite_element_pt(e)->
594  // construct_node(j,time_stepper_pt);
595  // }
596  // Node_pt.push_back(new_node_pt);
597 
598  // // Now indicate existence of newly created mideside node in map
599  // central_edge_node_pt(edge_node1_pt,edge_node2_pt)=new_node_pt;
600  // central_edge_node_pt(edge_node2_pt,edge_node1_pt)=new_node_pt;
601 
602  // // What are the node's local coordinates?
603  // finite_element_pt(e)->local_coordinate_of_node(j,s);
604 
605  // // Find the coordinates of the new node from the existing
606  // // and fully-functional element in the scaffold mesh
607  // for(unsigned i=0;i<dim;i++)
608  // {
609  // new_node_pt->x(i)=
610  // Tmp_mesh_pt->finite_element_pt(e)->interpolated_x(s,i);
611  // }
612  // }
613  // else
614  // {
615  // // Set pointer to the existing node
616  // finite_element_pt(e)->node_pt(j)=
617  // central_edge_node_pt(edge_node1_pt,edge_node2_pt);
618  // }
619 
620  // } // end of loop over new nodes
621 
622  // //Need to sort out the face nodes
623  // if(n_node==15)
624  // {
625  // // Loop over the new (face) nodes in the element and create them.
626  // for(unsigned j=10;j<14;j++)
627  // {
628  // //Empty the set of face nodes
629  // face_nodes_pt.clear();
630  // // Figure out face nodes
631  // switch(j)
632  // {
633 
634  // // Node 10 is between nodes 0 and 1 and 3
635  // case 10:
636 
637  // face_nodes_pt.insert(Tmp_mesh_pt->finite_element_pt(e)->node_pt(0));
638  // face_nodes_pt.insert(Tmp_mesh_pt->finite_element_pt(e)->node_pt(1));
639  // face_nodes_pt.insert(Tmp_mesh_pt->finite_element_pt(e)->node_pt(3));
640  // break;
641 
642  // // Node 11 is between nodes 0 and 1 and 2
643  // case 11:
644 
645  // face_nodes_pt.insert(Tmp_mesh_pt->finite_element_pt(e)->node_pt(0));
646  // face_nodes_pt.insert(Tmp_mesh_pt->finite_element_pt(e)->node_pt(1));
647  // face_nodes_pt.insert(Tmp_mesh_pt->finite_element_pt(e)->node_pt(2));
648  // break;
649 
650  // // Node 12 is between nodes 0 and 2 and 3
651  // case 12:
652 
653  // face_nodes_pt.insert(Tmp_mesh_pt->finite_element_pt(e)->node_pt(0));
654  // face_nodes_pt.insert(Tmp_mesh_pt->finite_element_pt(e)->node_pt(2));
655  // face_nodes_pt.insert(Tmp_mesh_pt->finite_element_pt(e)->node_pt(3));
656  // break;
657 
658  // // Node 13 is between nodes 1 and 2 and 3
659  // case 13:
660 
661  // face_nodes_pt.insert(Tmp_mesh_pt->finite_element_pt(e)->node_pt(1));
662  // face_nodes_pt.insert(Tmp_mesh_pt->finite_element_pt(e)->node_pt(2));
663  // face_nodes_pt.insert(Tmp_mesh_pt->finite_element_pt(e)->node_pt(3));
664  // break;
665 
666 
667  // //Error
668  // default:
669 
670  // throw OomphLibError("More than four face nodes in Tet Element",
671  // OOMPH_CURRENT_FUNCTION,
672  // OOMPH_EXCEPTION_LOCATION);
673  // }
674 
675  // // Do we need a boundary node?
676  // bool need_boundary_node=false;
677 
678  // //Work it out from the face boundary
679  // boundary_id = Tmp_mesh_pt->face_boundary(e,face_map[j-10]);
680  // //If it's non-zero then we do need to create a boundary node
681  // if(boundary_id!=0) {need_boundary_node=true;}
682 
683  // // Do we need a new node?
684  // if (central_face_node_pt[face_nodes_pt]==0)
685  // {
686  // Node* new_node_pt=0;
687 
688  // // Create a new boundary node
689  // if (need_boundary_node)
690  // {
691  // new_node_pt=finite_element_pt(e)->
692  // construct_boundary_node(j,time_stepper_pt);
693  // //Add it to the boundary
694  // add_boundary_node(boundary_id-1,new_node_pt);
695  // }
696  // // Create new normal node
697  // else
698  // {
699  // new_node_pt=finite_element_pt(e)->
700  // construct_node(j,time_stepper_pt);
701  // }
702  // Node_pt.push_back(new_node_pt);
703 
704  // // Now indicate existence of newly created mideside node in map
705  // central_face_node_pt[face_nodes_pt]=new_node_pt;
706 
707  // // What are the node's local coordinates?
708  // finite_element_pt(e)->local_coordinate_of_node(j,s);
709 
710  // // Find the coordinates of the new node from the existing
711  // // and fully-functional element in the scaffold mesh
712  // for(unsigned i=0;i<dim;i++)
713  // {
714  // new_node_pt->x(i)=
715  // Tmp_mesh_pt->finite_element_pt(e)->interpolated_x(s,i);
716  // }
717  // }
718  // else
719  // {
720  // // Set pointer to the existing node
721  // finite_element_pt(e)->node_pt(j)=
722  // central_face_node_pt[face_nodes_pt];
723  // }
724  // } //End of loop over face nodes
725 
726  // //Construct the element's central node, which is not on a boundary
727  // {
728  // Node* new_node_pt=
729  // finite_element_pt(e)->construct_node(14,time_stepper_pt);
730  // Node_pt.push_back(new_node_pt);
731 
732  // // What are the node's local coordinates?
733  // finite_element_pt(e)->local_coordinate_of_node(14,s);
734  // // Find the coordinates of the new node from the existing
735  // // and fully-functional element in the scaffold mesh
736  // for(unsigned i=0;i<dim;i++)
737  // {
738  // new_node_pt->x(i)=
739  // Tmp_mesh_pt->finite_element_pt(e)->interpolated_x(s,i);
740  // }
741  // }
742  // } //End of enriched case
743 
744  // } //end of loop over elements
745 
746 
747  // //Boundary conditions
748 
749  // // Matrix map to check if a node has already been added to
750  // // the boundary number b
751  // MapMatrixMixed<Node*,unsigned,bool> bound_node_done;
752 
753  // // Loop over elements
754  // for (unsigned e=0;e<nelem;e++)
755  // {
756  // // Loop over new local nodes
757  // for(unsigned j=4;j<n_node;j++)
758  // {
759  // // Pointer to the element's local node
760  // Node* loc_node_pt=finite_element_pt(e)->node_pt(j);
761 
762  // // This will have to be changed for higher-order elements
763  // //=======================================================
764 
765  // // These are the face nodes on the element's face 0:
766  // if ( (j==4) || (j==5) || (j==7) )
767  // {
768  // boundary_id=Tmp_mesh_pt->face_boundary(e,0);
769  // if (boundary_id!=0)
770  // {
771  // if (!bound_node_done(loc_node_pt,boundary_id-1))
772  // {
773  // add_boundary_node(boundary_id-1,loc_node_pt);
774  // bound_node_done(loc_node_pt,boundary_id-1)=true;
775  // }
776  // }
777  // }
778 
779 
780  // // These are the face nodes on the element's face 1:
781  // if ( (j==4) || (j==6) || (j==9) )
782  // {
783  // boundary_id=Tmp_mesh_pt->face_boundary(e,1);
784  // if (boundary_id!=0)
785  // {
786  // if (!bound_node_done(loc_node_pt,boundary_id-1))
787  // {
788  // add_boundary_node(boundary_id-1,loc_node_pt);
789  // bound_node_done(loc_node_pt,boundary_id-1)=true;
790  // }
791  // }
792  // }
793 
794  // // These are the face nodes on the element's face 2:
795  // if ( (j==5) || (j==6) || (j==8) )
796  // {
797  // boundary_id=Tmp_mesh_pt->face_boundary(e,2);
798  // if (boundary_id!=0)
799  // {
800  // if (!bound_node_done(loc_node_pt,boundary_id-1))
801  // {
802  // add_boundary_node(boundary_id-1,loc_node_pt);
803  // bound_node_done(loc_node_pt,boundary_id-1)=true;
804  // }
805  // }
806  // }
807 
808 
809  // // These are the face nodes on the element's face 3:
810  // if ( (j==7) || (j==8) || (j==9) )
811  // {
812  // boundary_id=Tmp_mesh_pt->face_boundary(e,3);
813  // if (boundary_id!=0)
814  // {
815  // if (!bound_node_done(loc_node_pt,boundary_id-1))
816  // {
817  // add_boundary_node(boundary_id-1,loc_node_pt);
818  // bound_node_done(loc_node_pt,boundary_id-1)=true;
819  // }
820  // }
821  // }
822 
823  // } //end for j
824 
825  // */
826 
827  } //end for e
828 
829 
830 } // end function
831 
832 
833 
834 
835 ///////////////////////////////////////////////////////////////////////
836 ///////////////////////////////////////////////////////////////////////
837 ///////////////////////////////////////////////////////////////////////
838 
839 
840 //=========================================================================
841 /// Transfer tetgenio data from the input to the output
842 /// The output is assumed to have been constructed and "empty"
843 //=========================================================================
844  template<class ELEMENT>
845  void TetgenMesh<ELEMENT>::deep_copy_of_tetgenio(tetgenio* const &input_pt,
846  tetgenio* &output_pt)
847  {
848  //Copy data values
849  output_pt->firstnumber = input_pt->firstnumber;
850  output_pt->mesh_dim = input_pt->mesh_dim;
851  output_pt->useindex = input_pt->useindex;
852 
853  //Copy the number of points
854  output_pt->numberofpoints = input_pt->numberofpoints;
855  output_pt->numberofpointattributes = input_pt->numberofpointattributes;
856  output_pt->numberofpointmtrs = input_pt->numberofpointmtrs;
857 
858  const int n_point = output_pt->numberofpoints;
859  if(n_point > 0)
860  {
861  output_pt->pointlist = new double[n_point * 3];
862  //Copy the values
863  for(int n=0;n<(n_point * 3);++n)
864  {
865  output_pt->pointlist[n] = input_pt->pointlist[n];
866  }
867 
868  //If there are point markers copy as well
869  if(input_pt->pointmarkerlist != (int*) NULL)
870  {
871  output_pt->pointmarkerlist = new int[n_point];
872  for(int n=0;n<n_point;++n)
873  {
874  output_pt->pointmarkerlist[n] = input_pt->pointmarkerlist[n];
875  }
876  }
877 
878  const int n_attr = output_pt->numberofpointattributes;
879  if(n_attr > 0)
880  {
881  output_pt->pointattributelist = new double[n_point * n_attr];
882  for(int n=0;n<(n_point * n_attr);++n)
883  {
884  output_pt->pointattributelist[n] =
885  input_pt->pointattributelist[n];
886  }
887  }
888  } //End of point case
889 
890  //Now add in metric tensors (if there are any)
891  const int n_point_mtr = output_pt->numberofpointmtrs;
892  if(n_point_mtr > 0)
893  {
894  output_pt->pointmtrlist = new double[n_point * n_point_mtr];
895  for(int n=0;n<(n_point * n_point_mtr);++n)
896  {
897  output_pt->pointmtrlist[n] = input_pt->pointmtrlist[n];
898  }
899  }
900 
901  //Next tetrahedrons
902  output_pt->numberoftetrahedra = input_pt->numberoftetrahedra;
903  output_pt->numberofcorners = input_pt->numberofcorners;
904  output_pt->numberoftetrahedronattributes =
905  input_pt->numberoftetrahedronattributes;
906 
907  const int n_tetra = output_pt->numberoftetrahedra;
908  const int n_corner = output_pt->numberofcorners;
909  if(n_tetra > 0)
910  {
911  output_pt->tetrahedronlist = new int[n_tetra * n_corner];
912  for(int n=0;n<(n_tetra * n_corner);++n)
913  {
914  output_pt->tetrahedronlist[n] = input_pt->tetrahedronlist[n];
915  }
916 
917  //Add in the volume constriants
918  if(input_pt->tetrahedronvolumelist != (double*) NULL)
919  {
920  output_pt->tetrahedronvolumelist = new double[n_tetra];
921  for(int n=0;n<n_tetra;++n)
922  {
923  output_pt->tetrahedronvolumelist[n] =
924  input_pt->tetrahedronvolumelist[n];
925  }
926  }
927 
928  //Add in the attributes
929  const int n_tetra_attr = output_pt->numberoftetrahedronattributes;
930  if(n_tetra_attr > 0)
931  {
932  output_pt->tetrahedronattributelist = new double[n_tetra * n_tetra_attr];
933  for(int n=0;n<(n_tetra * n_tetra_attr);++n)
934  {
935  output_pt->tetrahedronattributelist[n] =
936  input_pt->tetrahedronattributelist[n];
937  }
938  }
939 
940  //Add in the neighbour list
941  if(input_pt->neighborlist != (int*) NULL)
942  {
943  output_pt->neighborlist = new int[n_tetra * 4];
944  for(int n=0;n<(n_tetra * 4);++n)
945  {
946  output_pt->neighborlist = input_pt->neighborlist;
947  }
948  }
949  } //End of tetrahedron section
950 
951  //Now arrange the facet list
952  output_pt->numberoffacets = input_pt->numberoffacets;
953  const int n_facet = output_pt->numberoffacets;
954  if(n_facet > 0)
955  {
956  output_pt->facetlist = new tetgenio::facet[n_facet];
957  for(int n=0;n<n_facet;++n)
958  {
959  tetgenio::facet *input_f_pt = &input_pt->facetlist[n];
960  tetgenio::facet *output_f_pt = &output_pt->facetlist[n];
961 
962  //Copy polygons and holes from the facets
963  output_f_pt->numberofpolygons = input_f_pt->numberofpolygons;
964 
965  //Loop over polygons
966  const int n_poly = output_f_pt->numberofpolygons;
967  if(n_poly > 0)
968  {
969  output_f_pt->polygonlist = new tetgenio::polygon[n_poly];
970  for(int p=0;p<n_poly;++p)
971  {
972  tetgenio::polygon *output_p_pt = &output_f_pt->polygonlist[p];
973  tetgenio::polygon *input_p_pt = &input_f_pt->polygonlist[p];
974  //Find out how many vertices each polygon has
975  output_p_pt->numberofvertices = input_p_pt->numberofvertices;
976  //Now copy of the vertices
977  const int n_vertex = output_p_pt->numberofvertices;
978  if(n_vertex > 0)
979  {
980  output_p_pt->vertexlist = new int[n_vertex];
981  for(int v=0;v<n_vertex;++v)
982  {
983  output_p_pt->vertexlist[v] = input_p_pt->vertexlist[v];
984  }
985  }
986  }
987  }
988 
989  //Hole information
990  output_f_pt->numberofholes = input_f_pt->numberofholes;
991  const int n_hole = output_f_pt->numberofholes;
992  if(n_hole > 0)
993  {
994  throw OomphLibError("Don't know how to handle holes yet\n",
995  OOMPH_CURRENT_FUNCTION,
996  OOMPH_EXCEPTION_LOCATION);
997  }
998  } //end of loop over facets
999 
1000  //Add the facetmarkers if there are any
1001  if(input_pt->facetmarkerlist != (int*) NULL)
1002  {
1003  output_pt->facetmarkerlist = new int[n_facet];
1004  for(int n=0;n<n_facet;++n)
1005  {
1006  output_pt->facetmarkerlist[n] = input_pt->facetmarkerlist[n];
1007  }
1008  }
1009  }
1010 
1011  //Now the holes
1012  output_pt->numberofholes = input_pt->numberofholes;
1013  const int n_hole = output_pt->numberofholes;
1014  if(n_hole > 0)
1015  {
1016  output_pt->holelist = new double[n_hole * 3];
1017  for(int n=0;n<(n_hole * 3);++n)
1018  {
1019  output_pt->holelist[n] = input_pt->holelist[n];
1020  }
1021  }
1022 
1023  //Now the regions
1024  output_pt->numberofregions = input_pt->numberofregions;
1025  const int n_region = output_pt->numberofregions;
1026  if(n_region > 0)
1027  {
1028  output_pt->regionlist = new double[n_region * 5];
1029  for(int n=0;n<(n_region * 5);++n)
1030  {
1031  output_pt->regionlist[n] = input_pt->regionlist[n];
1032  }
1033  }
1034 
1035  //Now the facet constraints
1036  output_pt->numberoffacetconstraints = input_pt->numberoffacetconstraints;
1037  const int n_facet_const = output_pt->numberoffacetconstraints;
1038  if(n_facet_const > 0)
1039  {
1040  output_pt->facetconstraintlist = new double[n_facet_const * 2];
1041  for(int n=0;n<(n_facet_const * 2);++n)
1042  {
1043  output_pt->facetconstraintlist[n] = input_pt->facetconstraintlist[n];
1044  }
1045  }
1046 
1047  //Now the segment constraints
1048  output_pt->numberofsegmentconstraints = input_pt->numberofsegmentconstraints;
1049  const int n_seg_const = output_pt->numberofsegmentconstraints;
1050  if(n_seg_const > 0)
1051  {
1052  output_pt->segmentconstraintlist = new double[n_seg_const * 2];
1053  for(int n=0;n<(n_seg_const * 2);++n)
1054  {
1055  output_pt->segmentconstraintlist[n] = input_pt->segmentconstraintlist[n];
1056  }
1057  }
1058 
1059  //Now the face list
1060  output_pt->numberoftrifaces = input_pt->numberoftrifaces;
1061  const int n_tri_face = output_pt->numberoftrifaces;
1062  if(n_tri_face > 0)
1063  {
1064  output_pt->trifacelist = new int[n_tri_face * 3];
1065  for(int n=0;n<(n_tri_face * 3);++n)
1066  {
1067  output_pt->trifacelist[n] = input_pt->trifacelist[n];
1068  }
1069 
1070  output_pt->trifacemarkerlist = new int[n_tri_face];
1071  for(int n=0;n<n_tri_face;++n)
1072  {
1073  output_pt->trifacemarkerlist[n] = input_pt->trifacemarkerlist[n];
1074  }
1075  }
1076 
1077  //Now the edge list
1078  output_pt->numberofedges = input_pt->numberofedges;
1079  const int n_edge = output_pt->numberofedges;
1080  if(n_edge > 0)
1081  {
1082  output_pt->edgelist = new int[n_edge * 2];
1083  for(int n=0;n<(n_edge * 2);++n)
1084  {
1085  output_pt->edgelist[n] = input_pt->edgelist[n];
1086  }
1087 
1088  output_pt->edgemarkerlist = new int[n_edge];
1089  for(int n=0;n<n_edge;++n)
1090  {
1091  output_pt->edgemarkerlist[n] = input_pt->edgemarkerlist[n];
1092  }
1093  }
1094  }
1095 
1096 
1097 }
1098 #endif
virtual void local_coordinate_of_node(const unsigned &j, Vector< double > &s) const
Get local coordinates of node j in the element; vector sets its own size (broken virtual) ...
Definition: elements.h:1803
void build_from_scaffold(TimeStepper *time_stepper_pt, const bool &use_attributes)
Build mesh from scaffold.
cstr elem_len * i
Definition: cfortran.h:607
A general Finite Element class.
Definition: elements.h:1274
virtual Node * construct_boundary_node(const unsigned &n)
Construct the local node n as a boundary node; that is a node that MAY be placed on a mesh boundary a...
Definition: elements.h:2420
Nodes are derived from Data, but, in addition, have a definite (Eulerian) position in a space of a gi...
Definition: nodes.h:852
e
Definition: cfortran.h:575
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
double & x(const unsigned &i)
Return the i-th nodal coordinate.
Definition: nodes.h:995
virtual double interpolated_x(const Vector< double > &s, const unsigned &i) const
Return FE interpolated coordinate x[i] at local coordinate s.
Definition: elements.cc:3881
virtual Node * construct_node(const unsigned &n)
Construct the local node n and return a pointer to the newly created node object. ...
Definition: elements.h:2392
static char t char * s
Definition: cfortran.h:572
void deep_copy_of_tetgenio(tetgenio *const &input_pt, tetgenio *&output_pt)
Node *& node_pt(const unsigned &n)
Return a pointer to the local node n.
Definition: elements.h:2109
Base class for time-stepping schemes. Timestepper provides an approximation of the temporal derivativ...
Definition: timesteppers.h:219