canyon_spine_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 MY_CANYON_SPINE_MESH_HEADER
27 #define MY_CANYON_SPINE_MESH_HEADER
28 
29 // oomph-lib includes
30 #include "generic/spines.h"
31 // This has been changed to make reference to my cubic mesh
32 //#include "meshes/simple_cubic_mesh.h"
33 
34 
35 using namespace oomph;
36 //======================================================================
44 //======================================================================
45 template <class ELEMENT, class INTERFACE_ELEMENT>
46 class MyCanyonMesh : public SimpleCubicMesh<ELEMENT >,
47  public SpineMesh
48 {
49 
50 public:
51 
59  MyCanyonMesh(const unsigned &nx,
60  const unsigned &ny,
61  const unsigned &nz,
62  const double &x_min,
63  const double &x_max,
64  const double &y_min,
65  const double &y_max,
66  const double &z_min,
67  const double &z_max,
68  const double &R,
69  const unsigned &rotation_flag,
70  TimeStepper* time_stepper_pt=
72 
73 
75  FiniteElement* &interface_element_pt(const unsigned long &i)
76  {return Interface_element_pt[i];}
77 
79  unsigned long ninterface_element() const
80  {return Interface_element_pt.size();}
81 
83  FiniteElement* &bulk_element_pt(const unsigned long &i)
84  {return Bulk_element_pt[i];}
85 
87  unsigned long nbulk() const {return Bulk_element_pt.size();}
88 
89 // Reurn radius of the canyon
90  double radius() {return Radius;}
91 
92 // Change radius
93  void change_radius(double R)
94  {
95  double scaled_R = R/(this->Zmax - this->Zmin);
96  if ( (scaled_R<0.95) && (scaled_R>0.05) )
97  Radius = R;
98  else
99  {
100  std::ostringstream error_stream;
101  error_stream
102  <<
103  "We can not constract so small elements so close to the origin\n"
104  << "Choose a different radius (actual scaled radius = "<<scaled_R<<
105  std::endl;
106  throw OomphLibError(error_stream.str(),
109  }
110  }
111 
112 
116  virtual void spine_node_update(SpineNode* spine_node_pt)
117  {
118 
119  //Get fraction along the spine
120  double W = spine_node_pt->fraction();
121  //Get spine height
122  double H = spine_node_pt->h();
123 
124  //Get the position of the node at the origin
125  //The geometric data is is the x,y,z position of the wall
126  //to which the spine is affixed
127  Vector<double> origin_pt(3);
128  origin_pt[0] = spine_node_pt->spine_pt()->geom_parameter(0);
129  origin_pt[2] = spine_node_pt->spine_pt()->geom_parameter(2);
130 
131  //set scale norm vector
132  double norm =
133  sqrt( (Xsim - origin_pt[0] ) * (Xsim - origin_pt[0] )+
134  (Zsim - origin_pt[2] ) * (Zsim - origin_pt[2]) );
135 
136  //Set th x coordinate
137  spine_node_pt->x(0) = origin_pt[0] + H*W* (Xsim - origin_pt[0] )/norm;
138 
139  //Set the value of z
140  spine_node_pt->x(2) = origin_pt[2] + H*W* (Zsim - origin_pt[2] )/norm;
141 
142  }
143 
144 
145 //This function wull be called only at the begining for setting the initial spine appropiated for makeing the canyon shape
146 //We will send the node wich is in the inmovile face (origin of the spines)
147  double init_spine_height(SpineNode* spine_node_pt)
148  {
149 
150  //set distance to the axis
151  double daxis = sqrt( (this->Xsim - spine_node_pt->x(0) ) *(this->Xsim - spine_node_pt->x(0) )+(this->Zsim - spine_node_pt->x(2) ) * (this->Zsim - spine_node_pt->x(2)));
152  double init_h = ( daxis - radius() ) ;
153  return init_h;
154 
155  }
156 
157  //========================================================
168  //========================================================
169 
170 
172  {
173  //Clear vectors of pointers to the nodes and elements
174  Node_pt.clear();
175  Bulk_element_pt.clear();
176  Interface_element_pt.clear();
177  Element_pt.clear();
178  Spine_pt.clear();
179  }
180 
181 
182 
183 
184 protected:
185 
188 
191 
193  double Radius;
194 
197  virtual void build_single_layer_mesh(TimeStepper* time_stepper_pt);
198 
199 
200 //Axis of the cilinder
201  double Xsim;
202 
203  double Zsim;
204 
205 // Rotation flag
206 
207  unsigned Rotation_flag;
208 
209 };
210 
211 
212 
213 //#endif
214 
215 
216 //===========================================================================
224 
229 //===========================================================================
230 template<class ELEMENT, class INTERFACE_ELEMENT>
232  const unsigned &nx, const unsigned &ny, const unsigned &nz,
233  const double &x_min, const double &x_max, const double &y_min,
234  const double &y_max, const double &z_min, const double &z_max,
235  const double &R, const unsigned &rotation_flag, TimeStepper* time_stepper_pt) :
236  SimpleCubicMesh<ELEMENT >(nx,ny,nz,x_min,x_max,y_min,y_max,z_min,z_max,
237  time_stepper_pt)
238 {
239  // We've called the "generic" constructor for the RectangularQuadMesh
240  // which doesn't do much...
241  // Now set up the parameters that characterise the mesh geometry
242  // then call the constructor
243 
244 // Axis of the cilinder
245  this->Xsim = 0.0;
246 
247  this->Zsim = 1.0;
248 
249  //Set rotation
250  this->Rotation_flag = rotation_flag;
251 
252  change_radius(R);
253 
254  build_single_layer_mesh(time_stepper_pt);
255 }
256 
257 //===========================================================================
260 //===========================================================================
261 template<class ELEMENT, class INTERFACE_ELEMENT>
263  TimeStepper* time_stepper_pt)
264 {
265 
266 // Set rotation
267  if(Rotation_flag == 1) //rotation around y--axis
268  for(unsigned i = 0;i< this->nnode();i++)
269  {
270  double x_node = this->node_pt(i)->x(0);
271  double z_node = this->node_pt(i)->x(2);
272  this->node_pt(i)->x(0) = -z_node +1.0;
273  this->node_pt(i)->x(2) = x_node;
274  }
275 
276 
277 
278  //Read out the number of elements in the x-direction
279  unsigned n_x = this->Nx;
280  unsigned n_y = this->Ny;
281  unsigned n_z = this->Nz;
282 
283 
284 
285  //Set up the pointers to elements in the bulk
286  unsigned nbulk=nelement();
287  Bulk_element_pt.reserve(nbulk);
288  for(unsigned e=0;e<nbulk;e++)
289  {
290 // Bulk_element_pt.push_back(this->finite_element_pt(e));
291  Bulk_element_pt.push_back(dynamic_cast<ELEMENT*>(this->finite_element_pt(e)));
292  }
293 
294  //Allocate memory for the spines and fractions along spines
295  //---------------------------------------------------------
296 
297  //Read out number of linear points in the element
298  unsigned n_p = dynamic_cast<ELEMENT*>(finite_element_pt(0))->nnode_1d();
299 
300  //Allocate store for the spines: (different in the case of periodic meshes !!)
301  Spine_pt.reserve(((n_p-1)*n_x+1)*((n_p-1)*n_y+1));
302 
303 
304 // NOW WE GO THROUH ALL THE ELEMENTS OF THE LOWER LAYERS AND ATTACHING THE SPINES
305 
306 // FIRST ELEMENT: Element 0
307 
308 
309 
310 for(unsigned l1=0;l1<n_p;l1++) //y loop over the nodes
311 {
312  for(unsigned l2=0;l2<n_p;l2++) //x loop over the nodes
313  {
314 
315  //Node j + i*np
316 // Vector to the origin node, it will be passed as argument for the a later update of the spine
317  Vector<double> origin_node(3);
318  origin_node[0] = element_node_pt(0,l2+l1*n_p)->x(0);
319  origin_node[1] = element_node_pt(0,l2+l1*n_p)->x(1);
320  origin_node[2] = element_node_pt(0,l2+l1*n_p)->x(2);
321 
322  double hinit = init_spine_height( element_node_pt(0,l2+l1*n_p) );
323  //Assign the new spine within the cilinder
324  Spine* new_spine_pt=new Spine( hinit);
325  new_spine_pt->set_geom_parameter(origin_node);
326  Spine_pt.push_back(new_spine_pt);
327 
328  // Get pointer to node
329  SpineNode* nod_pt=element_node_pt(0,l2+l1*n_p); // Element 0; node j + i*n_p
330  //Set the pointer to the spine
331  nod_pt->spine_pt() = new_spine_pt;
332  //Set the fraction
333  nod_pt->fraction() = 0.0;
334  // Pointer to the mesh that implements the update fct
335  nod_pt->spine_mesh_pt() = this;
336 
337  //Loop vertically along the spine
338  //Loop over the elements
339  for(unsigned long k=0;k<n_z;k++)
340  {
341  //Loop over the vertical nodes, apart from the first
342  for(unsigned l3=1;l3<n_p;l3++)
343  {
344  // Get pointer to node
345  SpineNode* nod_pt=element_node_pt(k*n_x*n_y,l3*n_p*n_p+l2+l1*n_p);
346  //Set the pointer to the spine
347  nod_pt->spine_pt() = new_spine_pt;
348  //Set the fraction
349  nod_pt->fraction()=(double(k)+double(l3)/double(n_p-1))/double(n_z);
350  // Pointer to the mesh that implements the update fct
351  nod_pt->spine_mesh_pt() = this;
352  }
353  }
354  }
355 }
356 
357 
358 
359  //LOOP OVER OTHER ELEMENTS IN THE FIRST ROW
360  //-----------------------------------------
361 
362 // The procedure is the same but we have to identify the before defined spines for not defining them two times
363 
364 for(unsigned j=1;j<n_x;j++) //loop over the elements in the first row
365 {
366 
367  for(unsigned l1=0;l1<n_p;l1++) //y loop over the nodes
368  {
369 
370  for(unsigned l2=1;l2<n_p;l2++) //x loop over the nodes
371  {
372 
373  //Node j + i*np
374  Vector<double> origin_node(3);
375  origin_node[0] = element_node_pt(j,l2+l1*n_p)->x(0);
376  origin_node[1] = element_node_pt(j,l2+l1*n_p)->x(1);
377  origin_node[2] = element_node_pt(j,l2+l1*n_p)->x(2);
378  double hinit = init_spine_height( element_node_pt(j,l2+l1*n_p) );
379  //Assign the new spine
380  Spine* new_spine_pt=new Spine( hinit);
381  new_spine_pt->set_geom_parameter(origin_node);
382 
383  Spine_pt.push_back(new_spine_pt);
384 
385 
386  // Get pointer to node
387  SpineNode* nod_pt=element_node_pt(j,l2+l1*n_p); // Element j; node l2 + l1*n_p
388  //Set the pointer to the spine
389  nod_pt->spine_pt() = new_spine_pt;
390  //Set the fraction
391  nod_pt->fraction() = 0.0;
392  // Pointer to the mesh that implements the update fct
393  nod_pt->spine_mesh_pt() = this;
394 
395  //Loop vertically along the spine
396  //Loop over the elements
397  for(unsigned long k=0;k<n_z;k++)
398  {
399  //Loop over the vertical nodes, apart from the first
400  for(unsigned l3=1;l3<n_p;l3++)
401  {
402  // Get pointer to node
403  SpineNode* nod_pt=element_node_pt(j+k*n_x*n_y,l3*n_p*n_p+l2+l1*n_p);
404  //Set the pointer to the spine
405  nod_pt->spine_pt() = new_spine_pt;
406  //Set the fraction
407  nod_pt->fraction()=(double(k)+double(l3)/double(n_p-1))/double(n_z);
408  // Pointer to the mesh that implements the update fct
409  nod_pt->spine_mesh_pt() = this;
410  }
411  }
412 
413 
414  }
415  }
416 }
417 
418 //REST OF THE ELEMENTS
419 // Now we loop over the rest of the elements. We will separe the first of each row being al the rest equal
420 
421 
422 
423 for(unsigned long i=1;i<n_y;i++)
424 {
425 //FIRST ELEMENT OF THE ROW
426 
427  //First line of nodes is copied from the element of the bottom
428 
429  for(unsigned l1=1;l1<n_p;l1++) //y loop over the nodes
430  {
431 
432  for(unsigned l2=0;l2<n_p;l2++) //x loop over the nodes
433  {
434 
435  //Node j + i*np
436  Vector<double> origin_node(3);
437  origin_node[0] = element_node_pt(i*n_x,l2+l1*n_p)->x(0);
438  origin_node[1] = element_node_pt(i*n_x,l2+l1*n_p)->x(1);
439  origin_node[2] = element_node_pt(i*n_x,l2+l1*n_p)->x(2);
440  double hinit = init_spine_height( element_node_pt(i*n_x,l2+l1*n_p) );
441  //Assign the new spine
442  Spine* new_spine_pt= new Spine( hinit);
443  new_spine_pt->set_geom_parameter(origin_node);
444 
445  Spine_pt.push_back(new_spine_pt);
446 
447 
448  // Get pointer to node
449  SpineNode* nod_pt=element_node_pt(i*n_x,l2+l1*n_p); // Element i*n_x; node l2 + l1*n_p
450  //Set the pointer to the spine
451  nod_pt->spine_pt() = new_spine_pt;
452  //Set the fraction
453  nod_pt->fraction() = 0.0;
454  // Pointer to the mesh that implements the update fct
455  nod_pt->spine_mesh_pt() = this;
456 
457  //Loop vertically along the spine
458  //Loop over the elements
459  for(unsigned long k=0;k<n_z;k++)
460  {
461  //Loop over the vertical nodes, apart from the first
462  for(unsigned l3=1;l3<n_p;l3++)
463  {
464  // Get pointer to node
465  SpineNode* nod_pt=element_node_pt(i*n_x+k*n_x*n_y,l3*n_p*n_p+l2+l1*n_p);
466  //Set the pointer to the spine
467  nod_pt->spine_pt() = new_spine_pt;
468  //Set the fraction
469  nod_pt->fraction()=(double(k)+double(l3)/double(n_p-1))/double(n_z);
470  // Pointer to the mesh that implements the update fct
471  nod_pt->spine_mesh_pt() = this;
472  }
473  }
474 
475 
476  }
477  }
478 
479 
480 
481 
482 
483  // REST OF THE ELEMENTS OF THE ROW
484  for(unsigned j=1;j<n_x;j++)
485  {
486 
487 
488 //First line of nodes is copied from the element of the bottom
489 
490  for(unsigned l1=1;l1<n_p;l1++) //y loop over the nodes
491  {
492 
493  for(unsigned l2=1;l2<n_p;l2++) //x loop over the nodes
494  {
495 
496  //Node j + i*np
497  Vector<double> origin_node(3);
498  origin_node[0] = element_node_pt(j+i*n_x,l2+l1*n_p)->x(0);
499  origin_node[1] = element_node_pt(j+i*n_x,l2+l1*n_p)->x(1);
500  origin_node[2] = element_node_pt(j+i*n_x,l2+l1*n_p)->x(2);
501  double hinit = init_spine_height( element_node_pt(j+i*n_x,l2+l1*n_p) );
502  //Assign the new spine with radius as unit length
503  Spine* new_spine_pt=new Spine( hinit);
504  new_spine_pt->set_geom_parameter(origin_node);
505 
506 
507  Spine_pt.push_back(new_spine_pt);
508 
509 
510  // Get pointer to node
511  SpineNode* nod_pt=element_node_pt(j+i*n_x,l2+l1*n_p); // Element j + i*n_x; node l2 + l1*n_p
512  //Set the pointer to the spine
513  nod_pt->spine_pt() = new_spine_pt;
514  //Set the fraction
515  nod_pt->fraction() = 0.0;
516  // Pointer to the mesh that implements the update fct
517  nod_pt->spine_mesh_pt() = this;
518 
519  //Loop vertically along the spine
520  //Loop over the elements
521  for(unsigned long k=0;k<n_z;k++)
522  {
523  //Loop over the vertical nodes, apart from the first
524  for(unsigned l3=1;l3<n_p;l3++)
525  {
526  // Get pointer to node
527  SpineNode* nod_pt=element_node_pt(j+i*n_x+k*n_x*n_y,l3*n_p*n_p+l2+l1*n_p);
528  //Set the pointer to the spine
529  nod_pt->spine_pt() = new_spine_pt;
530  //Set the fraction
531  nod_pt->fraction()=(double(k)+double(l3)/double(n_p-1))/double(n_z);
532  // Pointer to the mesh that implements the update fct
533  nod_pt->spine_mesh_pt() = this;
534  }
535  }
536 
537 
538  }
539  }
540 
541  }
542 
543 
544 }
545 
546 
547 
548 
549 
550 
551  //Assign the 2D Line elements
552  //---------------------------
553 
554  //Get the present number of elements
555  unsigned long element_count = Element_pt.size();
556 
557  //Loop over the elements on the plane
558  for(unsigned l1=0;l1<n_y;l1++)
559  for(unsigned l2=0;l2<n_x;l2++)
560  {
561  {
562  //Construct a new 2D surface element on the face on which the local
563  //coordinate 2 is fixed at its max. value (1)
564  FiniteElement *interface_element_element_pt =
565  new INTERFACE_ELEMENT(finite_element_pt(n_x*n_y*(n_z-1)+l2+l1*n_x),3);
566 
567 
568  //Push it back onto the stack
569  Element_pt.push_back(interface_element_element_pt);
570 
571  //Push it back onto the stack of interface elements
572  Interface_element_pt.push_back(interface_element_element_pt);
573 
574  element_count++;
575  }
576  }
577 
578 
579 //Update the node positions in the mesh
580  this->node_update();
581 
582 }
583 
584 
585 
586 #endif
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
@ R
Definition: StatisticsVector.h:21
Definition: canyon_spine_mesh.h:48
MyCanyonMesh(const unsigned &nx, const unsigned &ny, const unsigned &nz, const double &x_min, const double &x_max, const double &y_min, const double &y_max, const double &z_min, const double &z_max, const double &R, const unsigned &rotation_flag, TimeStepper *time_stepper_pt=&Mesh::Default_TimeStepper)
Definition: canyon_spine_mesh.h:231
double init_spine_height(SpineNode *spine_node_pt)
Definition: canyon_spine_mesh.h:147
double Zsim
Definition: canyon_spine_mesh.h:203
void change_radius(double R)
Definition: canyon_spine_mesh.h:93
Vector< FiniteElement * > Interface_element_pt
Vector of pointers to interface elements.
Definition: canyon_spine_mesh.h:190
double Xsim
Definition: canyon_spine_mesh.h:201
unsigned Rotation_flag
Definition: canyon_spine_mesh.h:207
virtual void spine_node_update(SpineNode *spine_node_pt)
Definition: canyon_spine_mesh.h:116
double Radius
Sacled radius of the canyon (must be between 0 and one.
Definition: canyon_spine_mesh.h:193
virtual void build_single_layer_mesh(TimeStepper *time_stepper_pt)
Definition: canyon_spine_mesh.h:262
FiniteElement *& interface_element_pt(const unsigned long &i)
Access functions for pointers to interface elements.
Definition: canyon_spine_mesh.h:75
void flush_spine_element_and_node_storage()
Definition: canyon_spine_mesh.h:171
unsigned long ninterface_element() const
Number of elements on interface.
Definition: canyon_spine_mesh.h:79
Vector< FiniteElement * > Bulk_element_pt
Vector of pointers to element in the fluid layer.
Definition: canyon_spine_mesh.h:187
FiniteElement *& bulk_element_pt(const unsigned long &i)
Access functions for pointers to elements in bulk.
Definition: canyon_spine_mesh.h:83
unsigned long nbulk() const
Number of elements in bulk.
Definition: canyon_spine_mesh.h:87
double radius()
Definition: canyon_spine_mesh.h:90
Definition: elements.h:1313
static Steady< 0 > Default_TimeStepper
The Steady Timestepper.
Definition: mesh.h:75
double & x(const unsigned &i)
Return the i-th nodal coordinate.
Definition: nodes.h:1060
Definition: oomph_definitions.h:222
Simple cubic 3D Brick mesh class.
Definition: simple_cubic_mesh.template.h:47
Definition: spines.h:613
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
double & fraction()
Set reference to fraction along spine.
Definition: spines.h:378
Definition: spines.h:64
void set_geom_parameter(const Vector< double > &geom_parameter)
Definition: spines.h:273
double & geom_parameter(const unsigned &i)
Definition: spines.h:287
Definition: timesteppers.h:231
char char char int int * k
Definition: level2_impl.h:374
unsigned Nx
Number of elements in each direction (used by SimpleCubicMesh)
Definition: structured_cubic_point_source.cc:114
unsigned Ny
Definition: structured_cubic_point_source.cc:115
double Zmin
Set up min z coordinate.
Definition: axisym_linear_elasticity/cylinder/cylinder.cc:74
unsigned Nz
Number of elements in z-direction.
Definition: axisym_linear_elasticity/cylinder/cylinder.cc:62
double Zmax
Set up max z coordinate.
Definition: axisym_linear_elasticity/cylinder/cylinder.cc:80
double Radius
Radius of the pipe.
Definition: pipe.cc:55
const unsigned nz
Definition: ConstraintElementsUnitTest.cpp:32
const unsigned nx
Definition: ConstraintElementsUnitTest.cpp:30
const unsigned ny
Definition: ConstraintElementsUnitTest.cpp:31
radius
Definition: UniformPSDSelfTest.py:15
@ W
Definition: quadtree.h:63
DRAIG: Change all instances of (SPATIAL_DIM) to (DIM-1).
Definition: AnisotropicHookean.h:10
#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