annular_mesh.template.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// Version 1.0; svn revision $LastChangedRevision$
7 //LIC//
8 //LIC// $LastChangedDate$
9 //LIC//
10 //LIC// Copyright (C) 2006-2016 Matthias Heil and Andrew Hazel
11 //LIC//
12 //LIC// This library is free software; you can redistribute it and/or
13 //LIC// modify it under the terms of the GNU Lesser General Public
14 //LIC// License as published by the Free Software Foundation; either
15 //LIC// version 2.1 of the License, or (at your option) any later version.
16 //LIC//
17 //LIC// This library is distributed in the hope that it will be useful,
18 //LIC// but WITHOUT ANY WARRANTY; without even the implied warranty of
19 //LIC// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
20 //LIC// Lesser General Public License for more details.
21 //LIC//
22 //LIC// You should have received a copy of the GNU Lesser General Public
23 //LIC// License along with this library; if not, write to the Free Software
24 //LIC// Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA
25 //LIC// 02110-1301 USA.
26 //LIC//
27 //LIC// The authors may be contacted at oomph-lib@maths.man.ac.uk.
28 //LIC//
29 //LIC//====================================================================
30 
31 #ifndef OOMPH_ANNULAR_MESH_HEADER
32 #define OOMPH_ANNULAR_MESH_HEADER
33 
34 // Headers
37 
38 
39 //Include the headers file for domain
40 #include "annular_domain.h"
41 
42 namespace oomph
43 {
44 
45 
46 //===================================================================
47 /// 2D annular mesh with a unit circle in the middle and a layer
48 /// of thickness h surrounding it.
49 //==================================================================
50 template<class ELEMENT>
51 class TwoDAnnularMesh : public virtual RectangularQuadMesh<ELEMENT>
52 {
53 
54 public:
55 
56 
57  ///Constructor
58  TwoDAnnularMesh(const bool& periodic, const double& azimuthal_fraction,
59  const unsigned &ntheta, const unsigned &nr,
60  const double& a, const double &h, TimeStepper* time_stepper_pt
61  = &Mesh::Default_TimeStepper) :
62  RectangularQuadMesh<ELEMENT>(ntheta,nr,1.0,1.0,
63  periodic,time_stepper_pt)
64  {
65  // Mesh can only be built with 2D Qelements.
66  MeshChecker::assert_geometric_element<QElementGeometricBase,ELEMENT>(2);
67 
68  // Wrap mesh into annular shape
69  double phi=0.0;
70  wrap_into_annular_shape(a,h,azimuthal_fraction,phi);
71  }
72 
73  ///Constructor; rotate mesh by angle phi.
74  TwoDAnnularMesh(const bool& periodic, const double& azimuthal_fraction,
75  const unsigned &ntheta, const unsigned &nr,
76  const double& a, const double &h,
77  const double& phi, TimeStepper* time_stepper_pt
78  = &Mesh::Default_TimeStepper) :
79  RectangularQuadMesh<ELEMENT>(ntheta,nr,1.0,1.0,
80  periodic,time_stepper_pt)
81  {
82  // Mesh can only be built with 2D Qelements.
83  MeshChecker::assert_geometric_element<QElementGeometricBase,ELEMENT>(2);
84 
85  // Wrap mesh into annular shape
86  wrap_into_annular_shape(a,h,azimuthal_fraction,phi);
87  }
88 
89 
90  private:
91 
92  /// Wrap mesh into annular shape
93  void wrap_into_annular_shape(const double& a, const double& h,
94  const double& azimuthal_fraction,
95  const double& phi);
96 
97 };
98 
99 
100 //////////////////////////////////////////////////////////////////////
101 //////////////////////////////////////////////////////////////////////
102 //////////////////////////////////////////////////////////////////////
103 
104 
105 //===================================================================
106 /// Refineable 2D annular mesh with a unit circle in the middle and a layer
107 /// of thickness h surrounding it.
108 //==================================================================
109 template<class ELEMENT>
110  class RefineableTwoDAnnularMesh : public virtual TwoDAnnularMesh<ELEMENT>,
111  public virtual RefineableQuadMesh<ELEMENT>
112 {
113 
114 public:
115 
116  ///Constructor
117  RefineableTwoDAnnularMesh(const bool& periodic,
118  const double& azimuthal_fraction,
119  const unsigned &ntheta,
120  const unsigned &nr,
121  const double& a,
122  const double &h,
123  TimeStepper* time_stepper_pt
124  = &Mesh::Default_TimeStepper) :
125  RectangularQuadMesh<ELEMENT>(ntheta,nr,1.0,1.0,
126  periodic,time_stepper_pt),
127  TwoDAnnularMesh<ELEMENT>(periodic,azimuthal_fraction,ntheta,
128  nr,a,h,time_stepper_pt)
129  {
130  // Mesh can only be built with 2D Qelements.
131  MeshChecker::assert_geometric_element<QElementGeometricBase,ELEMENT>(2);
132 
133  // Build macro element-based domain
134  double phi=0.0;
135  Domain_pt = new AnnularDomain(azimuthal_fraction,
136  ntheta,nr,a,h,phi);
137 
138  // Loop over all elements and set macro element pointer
139  unsigned nel=this->nelement();
140  for (unsigned ielem=0;ielem<nel;ielem++)
141  {
142  dynamic_cast<RefineableQElement<2>*>(this->element_pt(ielem))->
143  set_macro_elem_pt(this->Domain_pt->macro_element_pt(ielem));
144  }
145 
146  // Update nodal positions based on macro-element representation
147  this->node_update();
148 
149  // Nodal positions etc. were created in constructor for
150  // RectangularMesh<...>. Only need to setup quadtree forest
151  this->setup_quadtree_forest();
152 
153  //Setup the periodic neighbour information of the TreeRoots
154  //Cast to specific elements
155  if (periodic)
156  {
157  Vector<TreeRoot*> left_root_pt(nr);
158  Vector<TreeRoot*> right_root_pt(nr);
159  for(unsigned i=0;i<nr;i++)
160  {
161  left_root_pt[i] =
162  dynamic_cast<ELEMENT*>(this->element_pt(i*ntheta))->
163  tree_pt()->root_pt();
164 
165  right_root_pt[i] =
166  dynamic_cast<ELEMENT*>(this->element_pt((i+1)*ntheta-1))->
167  tree_pt()->root_pt();
168  }
169 
170  //Set the neighbour and periodicity
171  using namespace QuadTreeNames;
172  for(unsigned i=0;i<nr;i++)
173  {
174  left_root_pt[i]->neighbour_pt(W) = right_root_pt[i];
175  left_root_pt[i]->set_neighbour_periodic(W);
176 
177  right_root_pt[i]->neighbour_pt(E) = left_root_pt[i];
178  right_root_pt[i]->set_neighbour_periodic(E);
179  }
180  }
181  }
182 
183 
184 
185  ///Constructor; rotate mesh by angle phi
186  RefineableTwoDAnnularMesh(const bool& periodic,
187  const double& azimuthal_fraction,
188  const unsigned &ntheta,
189  const unsigned &nr,
190  const double& a,
191  const double &h,
192  const double &phi,
193  TimeStepper* time_stepper_pt
194  = &Mesh::Default_TimeStepper) :
195  RectangularQuadMesh<ELEMENT>(ntheta,nr,1.0,1.0,
196  periodic,time_stepper_pt),
197  TwoDAnnularMesh<ELEMENT>(periodic,azimuthal_fraction,ntheta,
198  nr,a,h,phi,time_stepper_pt)
199  {
200  // Mesh can only be built with 2D Qelements.
201  MeshChecker::assert_geometric_element<QElementGeometricBase,ELEMENT>(2);
202 
203  // Build macro element-based domain
204  Domain_pt = new AnnularDomain(azimuthal_fraction,
205  ntheta,nr,a,h,phi);
206 
207  // Loop over all elements and set macro element pointer
208  unsigned nel=this->nelement();
209  for (unsigned ielem=0;ielem<nel;ielem++)
210  {
211  dynamic_cast<RefineableQElement<2>*>(this->element_pt(ielem))->
212  set_macro_elem_pt(this->Domain_pt->macro_element_pt(ielem));
213  }
214 
215  // Update nodal positions based on macro-element representation
216  this->node_update();
217 
218  // Nodal positions etc. were created in constructor for
219  // RectangularMesh<...>. Only need to setup quadtree forest
220  this->setup_quadtree_forest();
221 
222  //Setup the periodic neighbour information of the TreeRoots
223  //Cast to specific elements
224  if (periodic)
225  {
226  Vector<TreeRoot*> left_root_pt(nr);
227  Vector<TreeRoot*> right_root_pt(nr);
228  for(unsigned i=0;i<nr;i++)
229  {
230  left_root_pt[i] =
231  dynamic_cast<ELEMENT*>(this->element_pt(i*ntheta))->
232  tree_pt()->root_pt();
233 
234  right_root_pt[i] =
235  dynamic_cast<ELEMENT*>(this->element_pt((i+1)*ntheta-1))->
236  tree_pt()->root_pt();
237  }
238 
239  //Set the neighbour and periodicity
240  using namespace QuadTreeNames;
241  for(unsigned i=0;i<nr;i++)
242  {
243  left_root_pt[i]->neighbour_pt(W) = right_root_pt[i];
244  left_root_pt[i]->set_neighbour_periodic(W);
245 
246  right_root_pt[i]->neighbour_pt(E) = left_root_pt[i];
247  right_root_pt[i]->set_neighbour_periodic(E);
248  }
249  }
250  }
251 
252  private:
253 
254 
255  /// Pointer to domain
257 
258 };
259 
260 }
261 
262 #endif
void wrap_into_annular_shape(const double &a, const double &h, const double &azimuthal_fraction, const double &phi)
Wrap mesh into annular shape.
AnnularDomain * Domain_pt
Pointer to domain.
TwoDAnnularMesh(const bool &periodic, const double &azimuthal_fraction, const unsigned &ntheta, const unsigned &nr, const double &a, const double &h, TimeStepper *time_stepper_pt=&Mesh::Default_TimeStepper)
Constructor.
RefineableTwoDAnnularMesh(const bool &periodic, const double &azimuthal_fraction, const unsigned &ntheta, const unsigned &nr, const double &a, const double &h, const double &phi, TimeStepper *time_stepper_pt=&Mesh::Default_TimeStepper)
Constructor; rotate mesh by angle phi.
TwoDAnnularMesh(const bool &periodic, const double &azimuthal_fraction, const unsigned &ntheta, const unsigned &nr, const double &a, const double &h, const double &phi, TimeStepper *time_stepper_pt=&Mesh::Default_TimeStepper)
Constructor; rotate mesh by angle phi.
Annular domain.
RefineableTwoDAnnularMesh(const bool &periodic, const double &azimuthal_fraction, const unsigned &ntheta, const unsigned &nr, const double &a, const double &h, TimeStepper *time_stepper_pt=&Mesh::Default_TimeStepper)
Constructor.