st_mesh.h
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-2022 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 #ifndef ST_MESH_HEADER
27 #define ST_MESH_HEADER
28 
29 // oomph-lib includes
30 #include "generic/spines.h"
31 
32 // Include the Meshes which form the Saffman-Taylor mesh
34 #include "comb_can_spine_mesh.h"
35 #include "comb_tip_spine_mesh.h"
36 
37 
38 using namespace oomph;
39 
40 
41 
42 
43 //======================================================================
49 //======================================================================
50 
51 
52 template <class ELEMENT, class INTERFACE_ELEMENT>
53 class STSpineMesh : public SpineMesh
54 {
55 
56 public:
57 
60 // to the elements in each direction of each cubic mesh
61 
62 
63  STSpineMesh(const unsigned int &nel_can, const unsigned int &nel, const unsigned int &nel_liq ,const double &alpha,
64  const double &length_can, const double &length_tip,const double &length_liq,const double &height, const double &radius,
65  TimeStepper* time_stepper_pt = &Mesh::Default_TimeStepper );
66 
67 
69  FiniteElement* &interface_element_pt(const unsigned long &i)
70  {return Interface_element_pt[i];}
71 
73  unsigned long ninterface_element() const {return Interface_element_pt.size();}
74 
76  FiniteElement* &interface_line_element_pt(const unsigned long &i)
77  {return Interface_line_element_pt[i];}
78 
79 
81  unsigned long ninterfaceline() const {return Interface_line_element_pt.size();}
82 
84  FiniteElement* &bulk_element_pt(const unsigned long &i)
85  {return Bulk_element_pt[i];}
86 
88  unsigned long nbulk() const {return Bulk_element_pt.size();}
89 
90 // /Access functions for pointers to elements in the outlet (here identified as boundary 3)
91  FiniteElement* &bulk_outlet_element_pt(const unsigned long &i)
92  {return Bulk_outlet_element_pt[i];}
93 
94 //Number of outlet elements
95  unsigned long nbulkoutlet() const {return Bulk_outlet_element_pt.size();}
96 
97 
98 
99 // /Access functions for pointers to elements in the inlet (here identified as boundary 1)
100  FiniteElement* &bulk_inlet_element_pt(const unsigned long &i)
101  {return Bulk_inlet_element_pt[i];}
102 
103 //Number of intlet elements
104  unsigned long nbulkinlet() const {return Bulk_inlet_element_pt.size();}
105 
106 
107 //Acces functions for the fixed coordinates of the bulk outlet and inlet elements
108 
109  //Face index for the outlet elements
110  int face_index_outlet() {return Face_index_outlet;}
111 
112  //Face index for the inlet elements
113  int face_index_inlet() {return Face_index_inlet;}
114 
118 
119 /* virtual void spine_node_update(SpineNode* spine_node_pt)
120  {
121  //Get fraction along the spine
122  double W = spine_node_pt->fraction();
123  //Get spine height
124  double H = spine_node_pt->h();
125 
126  //Set the value of z
127  spine_node_pt->x(2) = 0.0 + W*H;
128  }*/
129 
130 
131 void full_output(std::ostream &outfile, const unsigned &n_plot)
132  {
133  //Loop over the elements and call their output functions
134  //Assign Element_pt_range
135  unsigned long Element_pt_range = Bulk_element_pt.size();
136  for(unsigned long e=0;e<Element_pt_range;e++)
137  {
138  // Try to cast to Navier Stokes Element
139  NavierStokesEquations<3>* el_pt=dynamic_cast<NavierStokesEquations<3>* >(Bulk_element_pt[e]);
140  if (el_pt==0)
141  {
142  oomph_info << "Can't execute output(...) for non Navier Stokes Elements"
143  << std::endl;
144  }
145  else
146  {
147  el_pt->full_output(outfile,n_plot);
148  }
149  }
150  }
151 
152 
153 void surface_output(std::ostream &outfile, const unsigned &n_plot)
154  {
155  //Loop over the elements and call their output functions
156  //Assign Element_pt_range
157  unsigned long Element_pt_range = Interface_element_pt.size();
158  for(unsigned long e=0;e<Element_pt_range;e++)
159  {
160  // Try to cast to Navier Stokes Element
161  FiniteElement* el_pt=dynamic_cast<FiniteElement* >(Interface_element_pt[e]);
162  if (el_pt==0)
163  {
164  oomph_info << "Can't execute surface output(...) for non Finite Element elements"
165  << std::endl;
166  }
167  else
168  {
169  el_pt->output(outfile,n_plot);
170  }
171  }
172  }
173 
174 
175 
176  virtual void spine_node_update(SpineNode* spine_node_pt)
177  {
178 
179  //Get de flag
180  unsigned flag = spine_node_pt->node_update_fct_id();
181 
182 // Lets first chech whether it is a real SpinNode (not in the liquid mesh)
183  if(flag != 2)
184  {
185  //Get fraction along the spine
186  double W = spine_node_pt->fraction();
187  //Get spine height
188  double H = spine_node_pt->h();
189  //Get the position of the node at the origin
190  Vector<double> origin_pt(3);
191  origin_pt[0] = spine_node_pt->spine_pt()->geom_parameter(0);
192  origin_pt[1] = spine_node_pt->spine_pt()->geom_parameter(1);
193  origin_pt[2] = spine_node_pt->spine_pt()->geom_parameter(2);
194 
195 
196 
197  if(flag ==0) // Canyon mesh
198  {
199  //set scale norm vector
200  double norm = sqrt( (Xsim - origin_pt[0] ) * (Xsim - origin_pt[0] )+(Zsim - origin_pt[2] ) * (Zsim - origin_pt[2]) );
201 
202  //Set th x coordinate
203  spine_node_pt->x(0) = origin_pt[0] + H*W* (Xsim - origin_pt[0] )/norm;
204 
205  //Set the value of z
206  spine_node_pt->x(2) = origin_pt[2] + H*W* (Zsim - origin_pt[2] )/norm;
207 
208 
209  }
210 
211  if(flag ==1) //Tip mesh
212  {
213 
214  //set scale norm vector
215  double norm = sqrt( (Xsim - origin_pt[0] ) * (Xsim - origin_pt[0] )+ (Ysim - origin_pt[1] ) * (Ysim - origin_pt[1] ) +
216  (Zsim- origin_pt[2] ) * (Zsim - origin_pt[2]) );
217 
218  //Set the x coordinate
219  spine_node_pt->x(0) = origin_pt[0] + H*W* (Xsim - origin_pt[0] )/norm;
220 
221  //Set the y coordinate
222  spine_node_pt->x(1) = origin_pt[1] + H*W* (Ysim - origin_pt[1] )/norm;
223 
224  //Set the value of z
225  spine_node_pt->x(2) = origin_pt[2] + H*W* (Zsim - origin_pt[2] )/norm;
226  }
227  }
228  }
229 
230 protected:
231 
232 
233 //Number of elements
234  unsigned int Nel_can;
235  unsigned int Nel;
236  unsigned int Nel_liq;
237 
239  double Alpha;
240  double Length_can;
241  double Length_tip;
242  double Length_liq;
243  double Height;
244  double Radius;
245 
246 // Axis of simmetry of the canyon mesh
247  double Xsim;
248  double Zsim;
249 
250 //Point of simety of the tip mesh (in the axis of canyon mesh)
251  double Ysim;
252 
253 
254  //Face index for the outlet elements
256 
257  //Face index for the inlet elements
259 
260 
261 
264 
267 
270 
273 
274 // Vector of pointers to the surface elements which will generate the LinContElement
276 
279  virtual void build_single_layer_mesh(TimeStepper* time_stepper_pt);
280 
281 // add side_mesh to the problem mesh
282  void add_side_spinemesh(unsigned int bound1, CombTipSpineMesh<ELEMENT,INTERFACE_ELEMENT > *addmesh_pt,int *addmesh_map_boundary, int total_boundaries, unsigned flag);
283 
284  void add_mesh(unsigned int bound1, Mesh *addmesh_pt, int *addmesh_map_boundary, int total_boundaries, unsigned spine_flag);
285 
286 };
287 
288 
289 
290 
291 //===========================================================================
296 
297 //===========================================================================
298 template<class ELEMENT, class INTERFACE_ELEMENT>
299 STSpineMesh<ELEMENT, INTERFACE_ELEMENT>::STSpineMesh(const unsigned int &nel_can, const unsigned int &nel, const unsigned int &nel_liq ,
300  const double &alpha, const double &length_can, const double &length_tip,const double &length_liq,
301  const double &height, const double &radius,
302  TimeStepper* time_stepper_pt):
303  Nel_can(nel_can), Nel(nel), Nel_liq(nel_liq), Alpha(alpha), Length_can(length_can), Length_tip(length_tip), Length_liq(length_liq), Height(height), Radius(radius)
304 {
305  // We've called the "generic" constructor for the RectangularQuadMesh
306  // which doesn't do much...
307  // Now set up the parameters that characterise the mesh geometry
308  // then call the constructor
309 
310 
311  // Now build the mesh:
312 
313 
314  build_single_layer_mesh(time_stepper_pt);
315 
316 }
317 
318 
319 
320 //===========================================================================
323 //===========================================================================
324 template<class ELEMENT, class INTERFACE_ELEMENT>
326  TimeStepper* time_stepper_pt)
327 {
328 
329 
330 // Axis pf simmetry
331  Xsim = 0.0;
332  Ysim = 0.0;
333  Zsim = 1.0 * Height/2;
334 
335 
336  // Build first canion mesh with flag 0
338 
339  mesh1_pt->node_update();
340 
341 // We copy this mesh to our problem mesh
342 
343 
344 // add the nodes to the mesh
345 //we reasign the spine_nodes to point to the ptoblem mesh
346  for(unsigned i = 0; i< mesh1_pt->nnode(); i++)
347  {
348  //Set spine update flag equal to 0 for the nodes of this function
349  mesh1_pt->node_pt(i)->node_update_fct_id() = 0;
350  mesh1_pt->node_pt(i)->spine_mesh_pt() = this;
351  this->add_node_pt(mesh1_pt->node_pt(i));
352  }
353 
354  // add the bulk elements to the mesh
355  for(unsigned i = 0; i< mesh1_pt->nbulk(); i++)
356  {
357  Bulk_element_pt.push_back(mesh1_pt->bulk_element_pt(i));
358  }
359 
360  // add the interface elements to the mesh
361 for(unsigned i = 0; i< mesh1_pt->ninterface_element(); i++)
362  {
363  Interface_element_pt.push_back(mesh1_pt->interface_element_pt(i));
364  }
365 
366 // add all the elements to the mesh
367 for(unsigned i = 0; i< mesh1_pt->nelement(); i++)
368  {
369  Element_pt.push_back(mesh1_pt->element_pt(i));
370  }
371 
372 
373  // add the spines to the mesh
374 for(unsigned i = 0; i< mesh1_pt->nspine(); i++)
375  {
376  Spine_pt.push_back(mesh1_pt->spine_pt(i));
377  }
378 
379 //add the boundaries
380  set_nboundary( mesh1_pt->nboundary());
381 
382 for(unsigned b =0; b< mesh1_pt->nboundary(); b++)
383  {
384  for(unsigned i = 0; i<mesh1_pt->nboundary_node(b); i++)
385  {
386  // We remove the node from the old boundary mesh ( This is not necessary and it is mainly wrotten for avoiding the warning message)
387  Node* node_pt = mesh1_pt->boundary_node_pt(b,i );
388  node_pt->remove_from_boundary(b);
389  this->add_boundary_node( b , node_pt);
390  }
391  }
392 
393 // Set the outlet bulk elements
394 
395  for(unsigned long e =0;e< mesh1_pt->nbulkoutlet();e++)
396  Bulk_outlet_element_pt.push_back(mesh1_pt->bulk_outlet_element_pt(e));
397 
398  this->Face_index_outlet = mesh1_pt->face_index_outlet();
399 
400  for(unsigned long e =0;e< mesh1_pt->ninterfaceline();e++)
401  Interface_line_element_pt.push_back(mesh1_pt->interface_line_element_pt(e));
402 
403 
404 
405 //We create the tip mesh with flag 1
407 
408 //Resignation pointer for the boundary conditions of the second mesh
409  int addmesh_map_boundary[7];
410 
411  for(unsigned int i =0;i<7;i++)
412  {
413  addmesh_map_boundary[i] = i;
414  }
415  addmesh_map_boundary[3] = -1;
416 
417 // Add the tip mesh
418  add_side_spinemesh(1, mesh2_pt ,addmesh_map_boundary, 7,1);
419 
420  std::cout<<"Tip mesh added"<<std::endl;
421 
422 //Creating the cubic mesh
423  double lycubicmin = -(Length_tip + Length_liq);
424  double lycubicmax = -Length_tip;
425  unsigned Nzcubic = 2*Nel;
426  double heightcubic = Height;
427  double alphacubic = Alpha/2;
428 
429  SimpleCubicMesh<ELEMENT >* mesh3_pt = new SimpleCubicMesh<ELEMENT >(Nel,Nel_liq,Nzcubic,0,alphacubic,lycubicmin,lycubicmax,0, heightcubic,time_stepper_pt);
430 
431 
432 // Set the inlet elementes
433  // int nxin = mesh3_pt->nx(); //It is not working in this way (ask Andrew)
434  // int nyin = mesh3_pt->ny();
435  // int nzin = mesh3_pt->nz();
436  int nxin = Nel;
437  int nyin = Nel_liq;
438  int nzin = Nzcubic;
439 
440  int jin = 0;
441  for(int k =0; k<nzin;k++)
442  {
443  for(int i =0; i<nxin;i++)
444  {
445  ELEMENT *el_pt = dynamic_cast<ELEMENT*>(mesh3_pt->element_pt(i+jin*nxin+k*nxin*nyin));
446  Bulk_inlet_element_pt.push_back(el_pt);
447  }
448  }
449 
450  // Constant coordinate for the face inlet elementes
451  Face_index_inlet = -2;
452 
453 //Resignation pointer for the boundary conditions of the third mesh
454  for(unsigned int i =0;i<7;i++)
455  {
456  addmesh_map_boundary[i] = i;
457  }
458  addmesh_map_boundary[3] = -1;
459  addmesh_map_boundary[5] = 6;
460 
461 
462 
463 // Add the cubic mesh with flag 2
464  add_mesh(1, mesh3_pt, addmesh_map_boundary,7,2);
465 
466 // cout<<"Cubic mesh added"<<endl;
467 
468  std::cout<<"The complete mesh consists of "<<nbulk()<< " bulk elements and "<<ninterface_element()<<" interface elements"<<std::endl;
469 
470 // At the end we destroy the block meshes in two steps
471 
472 // 1. We disconect the meshesh from the nodes and elements (if not we delete them at the time we delete the meshes)
475  mesh3_pt->flush_element_and_node_storage();
476 
477 //2. Simply delete (this function can give a segmentation fault error when there are spines still attached to the old update functions written in the constructor)
478  delete mesh1_pt;
479  delete mesh2_pt;
480  delete mesh3_pt;
481 
482 
483 
484 }
485 
486 
487 
488 
489 //Agregate a MySpineMesh to the problem mesh mesh_pt
490 //The function neeeds the pointer to the new added mes;, the sahred boundary of the problem mesh;
491 //a pointer which is a map between the boundaries in the addeed mesh and their new values when the mesh
492 //is attached (we will set as convection boundary = -1 for the shared boundary), the new total value of boundaries and a flag
493 // which will be used by the function update_node ( so that all the sub meshes with the same flag will be updated using the same function)
494 
495 //This function can not be extended to adding every spine_mesh because the class SpineMesh lacks the bulk and interface element pointers
496 
497 template<class ELEMENT, class INTERFACE_ELEMENT> void STSpineMesh<ELEMENT, INTERFACE_ELEMENT>::add_side_spinemesh(unsigned int bound1,
498  CombTipSpineMesh<ELEMENT,INTERFACE_ELEMENT > *addmesh_pt, int *addmesh_map_boundary, int total_boundaries, unsigned spine_flag)
499 {
500 
501 
502  //Call the generic function
503  MeshHelper::merge_spine_meshes(this,bound1,addmesh_pt,addmesh_map_boundary,
504  total_boundaries,spine_flag);
505 
506 // add the bulk elements to the mesh
507  for(unsigned i = 0; i< addmesh_pt->nbulk(); i++)
508  {
509  this->Bulk_element_pt.push_back(addmesh_pt->bulk_element_pt(i));
510  }
511 
512  // add the interface elements to the mesh
513 for(unsigned i = 0; i< addmesh_pt->ninterface_element(); i++)
514  {
515  this->Interface_element_pt.push_back(addmesh_pt->interface_element_pt(i));
516  }
517 
518 }
519 
520 
521 
522 
523 
527 
528 
529 // Add a mesh without spines to our mesh
530 
531 template<class ELEMENT, class INTERFACE_ELEMENT> void STSpineMesh<ELEMENT, INTERFACE_ELEMENT>::add_mesh(unsigned int bound1,
532  Mesh *addmesh_pt, int *addmesh_map_boundary, int total_boundaries, unsigned spine_flag)
533 {
534 
535  int bound2 = -1;
536 
537  Mesh *mesh_pt = this;
538 
539 //Map of the commom nodes from the nodes in the added mesh to the old mesh (It is needed for the added elements to point to the old nodes and not duplicate this nodes)
540  std::map<Node*,Node*> map_bound_node;
541 
542 // We have to look for the shared boundary of the second mwsh. We identify it giving a value of -1 in the mappring of the old to the new boundary conditions
543  for(unsigned i = 0; i<addmesh_pt->nboundary(); i++)
544  {
545  if(addmesh_map_boundary[i] == -1)
546  bound2 = i;
547  }
548 
549 //#ifdef PARANOID
550 
551  if(bound2 == -1) {
552  throw OomphLibError("Error setting the shared boundary conditions\n",
555  }
556 
557 
558 // Another control. Test that the two shared boundaries have the same number of nodes
559  if(addmesh_pt->nboundary_node(bound2) != mesh_pt->nboundary_node(bound1) )
560  {
561  std::ostringstream error_stream;
562  error_stream
563  <<"Different number of nodes in the shared boundaries:\n" <<
564  "Boundary "<<bound1<<" in the original mesh has "
565  <<mesh_pt->nboundary_node(bound1)<<" nodes \n"<<
566  "and Boundary "<<bound2<<" in the added mesh has "
567  <<addmesh_pt->nboundary_node(bound2)<<" nodes.\n";
568 
569  throw OomphLibError(error_stream.str(),
572  }
573 
574 //#endif
575 
576 //We create the mappping
577 
578  //square distance between two nodes
579  double d;
580 // Minimun distance between two nodes (only useful in case of error)
581  double dmin;
582  //Dimession of the space
583  unsigned dim = addmesh_pt->node_pt(0)->ndim();
584 
585  unsigned long nodecounter;
586 
587 
588 
589  for( unsigned long i = 0; i< addmesh_pt->nboundary_node(bound2);i++)
590  {
591  nodecounter =0;
592  dmin = 100.0;
593  do
594  {
595  d = 0.0;
596  for(unsigned int k=0;k<dim;k++)
597  {
598  d += (addmesh_pt->boundary_node_pt(bound2,i)->x(k) - mesh_pt->boundary_node_pt(bound1,nodecounter)->x(k) )*
599  (addmesh_pt->boundary_node_pt(bound2,i)->x(k) - mesh_pt->boundary_node_pt(bound1,nodecounter)->x(k) );
600  }
601 
602 
603  nodecounter++;
604  if(dmin>d) dmin = d;
605 
606  }while((nodecounter < mesh_pt->nboundary_node(bound1)) && (d>1E-10));
607 
608  if((nodecounter == mesh_pt->nboundary_node(bound1)) && (d>1E-10))
609  {
610  std::ostringstream error_stream;
611  error_stream
612  <<"Error doing the mapping between shared boundaries:\n" <<
613  "it could not be found minimum distance in node "<<i<<"\n"
614  <<"Minimum found distance = "<<sqrt(dmin)<<"\n"
615  <<"Position in the added mesh = "
616  <<addmesh_pt->boundary_node_pt(bound2,i)->x(0)<<" "
617  <<addmesh_pt->boundary_node_pt(bound2,i)->x(1)<<" "
618  <<addmesh_pt->boundary_node_pt(bound2,i)->x(2)<<"\n";
619 
620  throw OomphLibError(error_stream.str(),
623  }
624  else
625  {
626 
627  // Creating the nodes map
628  map_bound_node[addmesh_pt->boundary_node_pt(bound2,i)] = mesh_pt->boundary_node_pt(bound1,nodecounter-1);
629 
630  }
631 
632 
633  }
634  //Now we loop over the elements of the added mesh on the shared boundary and reasign the node pointers to the ones
635  // of the original mesh.
636 
637 // REMARCK!!!!! the boundary_element scheme was not implemented in the mesh design, so that we have to loop over all the elements
638 
639 
640  for(unsigned int i = 0; i< addmesh_pt->nelement(); i++ )
641  {
642 
643 //Pointer to the element
644  ELEMENT* el_pt = dynamic_cast<ELEMENT*>( addmesh_pt->element_pt(i));
645 
646  // Loop over the nodes in the element
647  for(unsigned j =0;j< el_pt->nnode();j++)
648  {
649  //In case the node is in the boundary (and therefore in the map), we reasign the node
650  if(map_bound_node[ el_pt->node_pt(j) ] != 0)
651  {
652  el_pt->node_pt(j) = map_bound_node[ el_pt->node_pt(j)];
653  }
654  }
655  }
656 
657 
658 //We add the nodes which are not in the shared boundary
659 
660 
661  unsigned long n_nodes_addmesh = addmesh_pt->nnode();
662  unsigned int zaehler = 0;
663  for(unsigned j=0;j<n_nodes_addmesh;j++)
664  {
665  if( map_bound_node[ addmesh_pt->node_pt(j)] == 0)
666  {
667  SpineNode* nod_pt = dynamic_cast<SpineNode*>(addmesh_pt->node_pt(j));
668  nod_pt->spine_mesh_pt() = this;
669  nod_pt->node_update_fct_id() = spine_flag;
670  mesh_pt->add_node_pt( addmesh_pt->node_pt(j) );
671  }
672  else
673  {
674  zaehler++;
675  }
676  }
677 
678 
679 //#ifdef PARANOID
680 
681 // Another control
682  if(zaehler != addmesh_pt->nboundary_node(bound2))
683  {
684  std::ostringstream error_stream;
685  error_stream
686  <<"You have added "
687  <<(zaehler-addmesh_pt->nboundary_node(bound2))
688  <<" nodes too much to the mesh.\n"
689  <<"(This control should be removed in case we do not want to copy all the nodes of the shared boundaries)\n";
690 
691  throw OomphLibError(error_stream.str(),
694  }
695 
696 
697 //#endif
698 
699  //We add the elements to the mesh
700 
701  for(unsigned i = 0; i< addmesh_pt->nelement(); i++)
702  {
703  ELEMENT* el_pt = dynamic_cast<ELEMENT*>( addmesh_pt->element_pt(i));
704  // FiniteElement* el_pt = addmesh_pt->finite_element_pt(i);
705  Element_pt.push_back(el_pt);
706  Bulk_element_pt.push_back(el_pt );
707  }
708 
709 
710  // We reset the number of boundaries
711  mesh_pt->set_nboundary(total_boundaries);
712 
713 
714  //We reset the boundary conditions of the old mesh (the shared boundary is not more in a boundary)
715  mesh_pt->remove_boundary_nodes(bound1);
716 
717 
718 
719  //We reset the boundary conditions of the new nodes
720  for(int i=0;i<(int)(addmesh_pt->nboundary());i++)
721  {
722  //Loop over the boundary nodes
723  for(unsigned long j =0;j<addmesh_pt->nboundary_node(i);j++)
724  {
725 
726  //We do not reset the commom boundary,whose nodes will be deleted at the end
727  if(i!=bound2)
728  {
729  //Create a pointer to the node
730  Node* node_pt = addmesh_pt->boundary_node_pt(i,j);
731 
732  // We remove the old boundaries in case it is not yet included in a new boundary
733  bool alr_included = 0;
734  for(unsigned k =0;k<this->nboundary_node(i);k++)
735  {
736  if(node_pt == this->boundary_node_pt(i,k) )
737  alr_included = 1;
738  }
739  if(!alr_included)
740  node_pt->remove_from_boundary(i);
741 
742  // We test again not to include the nodes which will be deleted
743  if( map_bound_node[node_pt] == 0)
744  {
745  mesh_pt->add_boundary_node( addmesh_map_boundary[i], node_pt );
746  }
747  // if not we have to include to the boundarie (in the case that they were not included before)the maped nodes
748  else
749  {
750  Node* map_node_pt = map_bound_node[node_pt];
751  if(!map_node_pt->is_on_boundary(addmesh_map_boundary[i]) )
752  mesh_pt->add_boundary_node(addmesh_map_boundary[i], map_node_pt );
753  }
754  }
755  }
756  }
757 
758 
759 // At the end we remove the shared nodes of the second mesh for avoiding problems with memory leaking
760 
761  for(unsigned long j =0;j<addmesh_pt->nboundary_node(bound2);j++)
762  delete addmesh_pt->boundary_node_pt(bound2,j);
763 
764  // We reset the number of boundaries
765  mesh_pt->set_nboundary(total_boundaries);
766 
767 // Small control
768 //#ifdef PARANOID
769  for(unsigned i = 0; i<mesh_pt->nboundary(); i ++)
770  {
771  std::cout<<"Boundary "<<i
772  <<" has "<<mesh_pt->nboundary_node(i)<<" nodes."<<std::endl;
773  }
774 //#endif
775 
776  }
777 
778 
779 #endif
780 
781 
785 
786 
AnnoyingScalar sqrt(const AnnoyingScalar &x)
Definition: AnnoyingScalar.h:134
int i
Definition: BiCGSTAB_step_by_step.cpp:9
Array< double, 1, 3 > e(1./3., 0.5, 2.)
MatrixXf H
Definition: HessenbergDecomposition_matrixH.cpp:4
Scalar * b
Definition: benchVecAdd.cpp:17
Definition: comb_can_spine_mesh.h:55
unsigned long nbulk() const
Number of elements in bulk.
Definition: comb_can_spine_mesh.h:89
int face_index_outlet()
Definition: comb_can_spine_mesh.h:86
FiniteElement *& interface_line_element_pt(const unsigned long &i)
Definition: comb_can_spine_mesh.h:80
unsigned long ninterface_element() const
Number of elements on interface.
Definition: comb_can_spine_mesh.h:92
FiniteElement *& bulk_outlet_element_pt(const unsigned long &i)
Definition: comb_can_spine_mesh.h:75
unsigned long nbulkoutlet() const
Definition: comb_can_spine_mesh.h:95
void flush_spine_element_and_node_storage()
Definition: comb_can_spine_mesh.h:100
FiniteElement *& bulk_element_pt(const unsigned long &i)
Access functions for pointers to elements in bulk.
Definition: comb_can_spine_mesh.h:71
unsigned long ninterfaceline() const
Definition: comb_can_spine_mesh.h:98
FiniteElement *& interface_element_pt(const unsigned long &i)
Access functions for pointers to interface elements.
Definition: comb_can_spine_mesh.h:67
Definition: comb_tip_spine_mesh.h:62
unsigned long ninterface_element() const
Number of elements on interface.
Definition: comb_tip_spine_mesh.h:81
FiniteElement *& interface_element_pt(const unsigned long &i)
Access functions for pointers to interface elements.
Definition: comb_tip_spine_mesh.h:76
unsigned long nbulk() const
Number of elements in bulk.
Definition: comb_tip_spine_mesh.h:89
void flush_spine_element_and_node_storage()
Definition: comb_tip_spine_mesh.h:93
FiniteElement *& bulk_element_pt(const unsigned long &i)
Access functions for pointers to elements in bulk.
Definition: comb_tip_spine_mesh.h:84
Definition: st_mesh.h:54
int Face_index_inlet
Definition: st_mesh.h:258
unsigned long nbulkinlet() const
Definition: st_mesh.h:104
unsigned int Nel
Definition: st_mesh.h:235
Vector< FiniteElement * > Bulk_element_pt
Vector of pointers to element in the fluid layer.
Definition: st_mesh.h:263
int Face_index_outlet
Definition: st_mesh.h:255
Vector< FiniteElement * > Interface_line_element_pt
Definition: st_mesh.h:275
unsigned long nbulkoutlet() const
Definition: st_mesh.h:95
unsigned int Nel_liq
Definition: st_mesh.h:236
double Xsim
Definition: st_mesh.h:247
unsigned long ninterface_element() const
Number of elements on interface.
Definition: st_mesh.h:73
FiniteElement *& interface_element_pt(const unsigned long &i)
Access functions for pointers to interface elements.
Definition: st_mesh.h:69
FiniteElement *& bulk_inlet_element_pt(const unsigned long &i)
Definition: st_mesh.h:100
Vector< FiniteElement * > Interface_element_pt
Vector of pointers to interface elements.
Definition: st_mesh.h:266
double Length_liq
Definition: st_mesh.h:242
double Length_tip
Definition: st_mesh.h:241
double Ysim
Definition: st_mesh.h:251
FiniteElement *& bulk_element_pt(const unsigned long &i)
Access functions for pointers to elements in bulk.
Definition: st_mesh.h:84
virtual void spine_node_update(SpineNode *spine_node_pt)
Definition: st_mesh.h:176
double Height
Definition: st_mesh.h:243
void full_output(std::ostream &outfile, const unsigned &n_plot)
Definition: st_mesh.h:131
virtual void build_single_layer_mesh(TimeStepper *time_stepper_pt)
Definition: st_mesh.h:325
unsigned int Nel_can
Definition: st_mesh.h:234
unsigned long nbulk() const
Number of elements in bulk.
Definition: st_mesh.h:88
Vector< FiniteElement * > Bulk_inlet_element_pt
Vector of pointers to the bulk inlet elements in the fluid layer.
Definition: st_mesh.h:272
void add_mesh(unsigned int bound1, Mesh *addmesh_pt, int *addmesh_map_boundary, int total_boundaries, unsigned spine_flag)
Definition: st_mesh.h:531
int face_index_outlet()
Definition: st_mesh.h:110
FiniteElement *& interface_line_element_pt(const unsigned long &i)
Access functions for pointers to interface line elements.
Definition: st_mesh.h:76
void add_side_spinemesh(unsigned int bound1, CombTipSpineMesh< ELEMENT, INTERFACE_ELEMENT > *addmesh_pt, int *addmesh_map_boundary, int total_boundaries, unsigned flag)
Definition: st_mesh.h:497
double Alpha
Aspect ratio, length, height and radius.
Definition: st_mesh.h:239
int face_index_inlet()
Definition: st_mesh.h:113
Vector< FiniteElement * > Bulk_outlet_element_pt
Vector of pointers to the bulk outlet elements in the fluid layer.
Definition: st_mesh.h:269
void surface_output(std::ostream &outfile, const unsigned &n_plot)
Definition: st_mesh.h:153
FiniteElement *& bulk_outlet_element_pt(const unsigned long &i)
Definition: st_mesh.h:91
unsigned long ninterfaceline() const
Number of elements on the line interface.
Definition: st_mesh.h:81
double Zsim
Definition: st_mesh.h:248
STSpineMesh(const unsigned int &nel_can, const unsigned int &nel, const unsigned int &nel_liq, const double &alpha, const double &length_can, const double &length_tip, const double &length_liq, const double &height, const double &radius, TimeStepper *time_stepper_pt=&Mesh::Default_TimeStepper)
Definition: st_mesh.h:299
double Radius
Definition: st_mesh.h:244
double Length_can
Definition: st_mesh.h:240
Definition: elements.h:1313
virtual void output(std::ostream &outfile)
Definition: elements.h:3050
Definition: mesh.h:67
void add_boundary_node(const unsigned &b, Node *const &node_pt)
Add a (pointer to) a node to the b-th boundary.
Definition: mesh.cc:243
unsigned long nboundary_node(const unsigned &ibound) const
Return number of nodes on a particular boundary.
Definition: mesh.h:833
static Steady< 0 > Default_TimeStepper
The Steady Timestepper.
Definition: mesh.h:75
void flush_element_and_node_storage()
Definition: mesh.h:407
void set_nboundary(const unsigned &nbound)
Set the number of boundaries in the mesh.
Definition: mesh.h:505
unsigned nboundary() const
Return number of boundaries.
Definition: mesh.h:827
GeneralisedElement *& element_pt(const unsigned long &e)
Return pointer to element e.
Definition: mesh.h:448
void remove_boundary_nodes()
Clear all pointers to boundary nodes.
Definition: mesh.cc:204
unsigned long nnode() const
Return number of nodes in the mesh.
Definition: mesh.h:596
Node *& node_pt(const unsigned long &n)
Return pointer to global node n.
Definition: mesh.h:436
void add_node_pt(Node *const &node_pt)
Add a (pointer to a) node to the mesh.
Definition: mesh.h:611
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
Definition: navier_stokes_elements.h:395
void full_output(std::ostream &outfile)
Definition: navier_stokes_elements.h:1180
Definition: nodes.h:906
double & x(const unsigned &i)
Return the i-th nodal coordinate.
Definition: nodes.h:1060
virtual bool is_on_boundary() const
Definition: nodes.h:1373
virtual void remove_from_boundary(const unsigned &b)
Definition: nodes.cc:2350
unsigned ndim() const
Return (Eulerian) spatial dimension of the node.
Definition: nodes.h:1054
Definition: oomph_definitions.h:222
Simple cubic 3D Brick mesh class.
Definition: simple_cubic_mesh.template.h:47
Definition: spines.h:613
SpineNode * node_pt(const unsigned long &n)
Return a pointer to the n-th global SpineNode.
Definition: spines.h:648
unsigned long nspine() const
Return the number of spines in the mesh.
Definition: spines.h:635
Spine *& spine_pt(const unsigned long &i)
Return the i-th spine in the mesh.
Definition: spines.h:623
void node_update(const bool &update_all_solid_nodes=false)
Definition: spines.cc:84
Definition: spines.h:328
double & h()
Access function to spine height.
Definition: spines.h:397
SpineMesh *& spine_mesh_pt()
Definition: spines.h:391
Spine *& spine_pt()
Access function to spine.
Definition: spines.h:372
unsigned & node_update_fct_id()
Access function to ID of node update function (within specific mesh)
Definition: spines.h:384
double & fraction()
Set reference to fraction along spine.
Definition: spines.h:378
double & geom_parameter(const unsigned &i)
Definition: spines.h:287
Definition: timesteppers.h:231
#define dmin(a, b)
Definition: datatypes.h:24
return int(ret)+1
RealScalar alpha
Definition: level1_cplx_impl.h:151
char char char int int * k
Definition: level2_impl.h:374
double Height
Height of domain.
Definition: flow_past_oscillating_cylinder.cc:316
double E
Elastic modulus.
Definition: TwenteMeshGluing.cpp:68
double Radius
Radius of the pipe.
Definition: pipe.cc:55
double Length_liq
Definition: three_d_breth.cc:77
double Length_can
Definition: three_d_breth.cc:79
double height(const double &x)
Height of domain.
Definition: simple_spine_channel.cc:429
double Length_tip
Definition: three_d_breth.cc:75
double Alpha
Parameter for steepness of step.
Definition: two_d_adv_diff_adapt.cc:53
radius
Definition: UniformPSDSelfTest.py:15
void merge_spine_meshes(MESH1 *mesh_pt, unsigned bound1, MESH2 *addmesh_pt, int *addmesh_map_boundary, int total_boundaries, unsigned spine_flag)
Definition: merge_meshes.h:32
@ W
Definition: quadtree.h:63
DRAIG: Change all instances of (SPATIAL_DIM) to (DIM-1).
Definition: AnisotropicHookean.h:10
OomphInfo oomph_info
Definition: oomph_definitions.cc:319
#define OOMPH_EXCEPTION_LOCATION
Definition: oomph_definitions.h:61
#define OOMPH_CURRENT_FUNCTION
Definition: oomph_definitions.h:86
std::ptrdiff_t j
Definition: tut_arithmetic_redux_minmax.cpp:2