eighth_sphere_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// Copyright (C) 2006-2023 Matthias Heil and Andrew Hazel
7 // LIC//
8 // LIC// This library is free software; you can redistribute it and/or
9 // LIC// modify it under the terms of the GNU Lesser General Public
10 // LIC// License as published by the Free Software Foundation; either
11 // LIC// version 2.1 of the License, or (at your option) any later version.
12 // LIC//
13 // LIC// This library is distributed in the hope that it will be useful,
14 // LIC// but WITHOUT ANY WARRANTY; without even the implied warranty of
15 // LIC// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
16 // LIC// Lesser General Public License for more details.
17 // LIC//
18 // LIC// You should have received a copy of the GNU Lesser General Public
19 // LIC// License along with this library; if not, write to the Free Software
20 // LIC// Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA
21 // LIC// 02110-1301 USA.
22 // LIC//
23 // LIC// The authors may be contacted at oomph-lib@maths.man.ac.uk.
24 // LIC//
25 // LIC//====================================================================
26 #ifndef OOMPH_EIGHTH_SPHERE_MESH_TEMPLATE_CC
27 #define OOMPH_EIGHTH_SPHERE_MESH_TEMPLATE_CC
28 
30 
31 
32 namespace oomph
33 {
34  //======================================================================
35  /// Constructor for the eighth of a sphere mesh: Pass timestepper;
36  /// defaults to static default timestepper.
37  //======================================================================
38  template<class ELEMENT>
40  TimeStepper* time_stepper_pt)
41  : Radius(radius)
42  {
43  // Mesh can only be built with 3D Qelements.
44  MeshChecker::assert_geometric_element<QElementGeometricBase, ELEMENT>(3);
45 
46  // Set the number of boundaries
47  this->set_nboundary(4);
48 
49  // Provide storage for the four elements
50  this->Element_pt.resize(4);
51 
52  // Set the domain pointer: Pass the radius of the sphere
54 
55 
56  Vector<double> s(3), s_fraction(3);
57  Vector<double> r(3);
58 
59  // Create first element
60  //--------------------
61  this->Element_pt[0] = new ELEMENT;
62 
63  // Give it nodes
64 
65  // How many 1D nodes are there?
66  unsigned nnode1d = this->finite_element_pt(0)->nnode_1d();
67 
68  // Loop over nodes
69  for (unsigned i = 0; i < nnode1d; i++)
70  {
71  for (unsigned j = 0; j < nnode1d; j++)
72  {
73  for (unsigned k = 0; k < nnode1d; k++)
74  {
75  unsigned jnod = k * nnode1d * nnode1d + j * nnode1d + i;
76 
77  // If we're on a boundary, make a boundary node
78  if ((i == 0) || (j == 0) || (k == 0))
79  {
80  // Allocate the node according to the element's wishes
81  this->Node_pt.push_back(
82  this->finite_element_pt(0)->construct_boundary_node(
83  jnod, time_stepper_pt));
84  }
85  // Otherwise it's a normal node
86  else
87  {
88  // Allocate the node according to the element's wishes
89  this->Node_pt.push_back(this->finite_element_pt(0)->construct_node(
90  jnod, time_stepper_pt));
91  }
92 
93  // Work out the node's coordinates in the finite element's local
94  // coordinate system
95  this->finite_element_pt(0)->local_fraction_of_node(jnod, s_fraction);
96 
97 
98  // Get the position of the node from macro element mapping
99  s[0] = -1.0 + 2.0 * s_fraction[0];
100  s[1] = -1.0 + 2.0 * s_fraction[1];
101  s[2] = -1.0 + 2.0 * s_fraction[2];
103 
104  // Assign coordinates
105  this->finite_element_pt(0)->node_pt(jnod)->x(0) = r[0];
106  this->finite_element_pt(0)->node_pt(jnod)->x(1) = r[1];
107  this->finite_element_pt(0)->node_pt(jnod)->x(2) = r[2];
108 
109  // Add the node to the appropriate boundary
110  if (i == 0)
111  add_boundary_node(0, this->finite_element_pt(0)->node_pt(jnod));
112  if (j == 0)
113  add_boundary_node(1, this->finite_element_pt(0)->node_pt(jnod));
114  if (k == 0)
115  add_boundary_node(2, this->finite_element_pt(0)->node_pt(jnod));
116  }
117  }
118  }
119 
120 
121  // Create a second element
122  //------------------------
123  this->Element_pt[1] = new ELEMENT;
124  ;
125 
126  // Give it nodes
127 
128  // Loop over nodes
129  for (unsigned i = 0; i < nnode1d; i++)
130  {
131  for (unsigned j = 0; j < nnode1d; j++)
132  {
133  for (unsigned k = 0; k < nnode1d; k++)
134  {
135  unsigned jnod = k * nnode1d * nnode1d + j * nnode1d + i;
136 
137  // If node has not been yet created, create it
138  if (i > 0)
139  {
140  // If the node is on a boundary, make a boundary node
141  if ((i == nnode1d - 1) || (j == 0) || (k == 0))
142  {
143  this->Node_pt.push_back(
144  this->finite_element_pt(1)->construct_boundary_node(
145  jnod, time_stepper_pt));
146  }
147  // Otherwise make a normal node
148  else
149  {
150  this->Node_pt.push_back(
151  this->finite_element_pt(1)->construct_node(jnod,
152  time_stepper_pt));
153  }
154 
155  // Work out the node's coordinates in the finite element's local
156  // coordinate system
158  s_fraction);
159 
160  // Get the position of the node from macro element mapping
161  s[0] = -1.0 + 2.0 * s_fraction[0];
162  s[1] = -1.0 + 2.0 * s_fraction[1];
163  s[2] = -1.0 + 2.0 * s_fraction[2];
165 
166  // Assign coordinate
167  this->finite_element_pt(1)->node_pt(jnod)->x(0) = r[0];
168  this->finite_element_pt(1)->node_pt(jnod)->x(1) = r[1];
169  this->finite_element_pt(1)->node_pt(jnod)->x(2) = r[2];
170 
171  // Add the node to the approriate boundary
172  if (j == 0)
173  add_boundary_node(1, this->finite_element_pt(1)->node_pt(jnod));
174  if (k == 0)
175  add_boundary_node(2, this->finite_element_pt(1)->node_pt(jnod));
176  if (i == nnode1d - 1)
177  add_boundary_node(3, this->finite_element_pt(1)->node_pt(jnod));
178  }
179 
180  // ...else use the node already created
181  else
182  {
183  this->finite_element_pt(1)->node_pt(jnod) =
184  this->finite_element_pt(0)->node_pt(jnod + nnode1d - 1);
185  }
186  }
187  }
188  }
189 
190 
191  // Create a third element
192  //------------------------
193  this->Element_pt[2] = new ELEMENT;
194 
195  // Give it nodes
196 
197  // Loop over nodes
198  for (unsigned i = 0; i < nnode1d; i++)
199  {
200  for (unsigned j = 0; j < nnode1d; j++)
201  {
202  for (unsigned k = 0; k < nnode1d; k++)
203  {
204  unsigned jnod = k * nnode1d * nnode1d + j * nnode1d + i;
205 
206  // If the node has not been yet created, create it
207  if ((i < nnode1d - 1) && (j > 0))
208  {
209  // If it's on a boundary, make a boundary node
210  if ((i == 0) || (j == nnode1d - 1) || (k == 0))
211  {
212  // Allocate the node according to the element's wishes
213  this->Node_pt.push_back(
214  this->finite_element_pt(2)->construct_boundary_node(
215  jnod, time_stepper_pt));
216  }
217  // Otherwise allocate a normal node
218  else
219  {
220  // Allocate the node according to the element's wishes
221  this->Node_pt.push_back(
222  this->finite_element_pt(2)->construct_node(jnod,
223  time_stepper_pt));
224  }
225 
226  // Work out the node's coordinates in the finite element's local
227  // coordinate system
229  s_fraction);
230 
231  // Get the position of the node from macro element mapping
232  s[0] = -1.0 + 2.0 * s_fraction[0];
233  s[1] = -1.0 + 2.0 * s_fraction[1];
234  s[2] = -1.0 + 2.0 * s_fraction[2];
236 
237  // Assign coordinates
238  this->finite_element_pt(2)->node_pt(jnod)->x(0) = r[0];
239  this->finite_element_pt(2)->node_pt(jnod)->x(1) = r[1];
240  this->finite_element_pt(2)->node_pt(jnod)->x(2) = r[2];
241 
242  // Add the node to the appropriate boundary
243  if (i == 0)
244  add_boundary_node(0, this->finite_element_pt(2)->node_pt(jnod));
245  if (k == 0)
246  add_boundary_node(2, this->finite_element_pt(2)->node_pt(jnod));
247  if (j == nnode1d - 1)
248  add_boundary_node(3, this->finite_element_pt(2)->node_pt(jnod));
249  }
250 
251  // ...else use the nodes already created
252  else
253  {
254  // If the node belongs to the element 0
255  if (j == 0)
256  this->finite_element_pt(2)->node_pt(jnod) =
257  this->finite_element_pt(0)->node_pt(jnod +
258  nnode1d * (nnode1d - 1));
259 
260  // ...else it belongs to the element 1
261  else if (i == nnode1d - 1)
262  this->finite_element_pt(2)->node_pt(jnod) =
263  this->finite_element_pt(1)->node_pt(nnode1d * nnode1d * k + j +
264  i * nnode1d);
265  }
266  }
267  }
268  }
269 
270 
271  // Create the fourth element
272  //-------------------------
273  this->Element_pt[3] = new ELEMENT;
274 
275  // Give it nodes
276 
277  // Loop over nodes
278  for (unsigned i = 0; i < nnode1d; i++)
279  {
280  for (unsigned j = 0; j < nnode1d; j++)
281  {
282  for (unsigned k = 0; k < nnode1d; k++)
283  {
284  unsigned jnod = k * nnode1d * nnode1d + j * nnode1d + i;
285 
286  // If the node has not been yet created, create it
287  if ((k > 0) && (i < nnode1d - 1) && (j < nnode1d - 1))
288  {
289  // If it's on a boundary, allocate a boundary node
290  if ((i == 0) || (j == 0) || (k == nnode1d - 1))
291  {
292  // Allocate the node according to the element's wishes
293  this->Node_pt.push_back(
294  this->finite_element_pt(3)->construct_boundary_node(
295  jnod, time_stepper_pt));
296  }
297  // Otherwise allocate a normal node
298  else
299  {
300  // Allocate the node according to the element's wishes
301  this->Node_pt.push_back(
302  this->finite_element_pt(3)->construct_node(jnod,
303  time_stepper_pt));
304  }
305 
306  // Work out the node's coordinates in the finite element's local
307  // coordinate system
309  s_fraction);
310 
311  // Get the position of the node from macro element mapping
312  s[0] = -1.0 + 2.0 * s_fraction[0];
313  s[1] = -1.0 + 2.0 * s_fraction[1];
314  s[2] = -1.0 + 2.0 * s_fraction[2];
316 
317  // Assign coordinates
318  this->finite_element_pt(3)->node_pt(jnod)->x(0) = r[0];
319  this->finite_element_pt(3)->node_pt(jnod)->x(1) = r[1];
320  this->finite_element_pt(3)->node_pt(jnod)->x(2) = r[2];
321 
322  // Add the node to the appropriate boundary
323  if (i == 0)
324  add_boundary_node(0, this->finite_element_pt(3)->node_pt(jnod));
325  if (j == 0)
326  add_boundary_node(1, this->finite_element_pt(3)->node_pt(jnod));
327  if (k == nnode1d - 1)
328  add_boundary_node(3, this->finite_element_pt(3)->node_pt(jnod));
329  }
330 
331  // ...otherwise the node was already created: use it.
332  else
333  {
334  // if k=0 then the node belongs to element 0
335  if (k == 0)
336  {
337  this->finite_element_pt(3)->node_pt(jnod) =
338  this->finite_element_pt(0)->node_pt(jnod + nnode1d * nnode1d *
339  (nnode1d - 1));
340  }
341  else
342  {
343  // else if i==nnode1d-1 the node already exists in element 1
344  if (i == nnode1d - 1)
345  {
346  this->finite_element_pt(3)->node_pt(jnod) =
347  this->finite_element_pt(1)->node_pt(
348  k + i * nnode1d * nnode1d + j * nnode1d);
349  }
350  else
351  // else, the node exists in element 2
352  {
353  this->finite_element_pt(3)->node_pt(jnod) =
354  this->finite_element_pt(2)->node_pt(i + k * nnode1d +
355  j * nnode1d * nnode1d);
356  }
357  }
358  }
359  }
360  }
361  }
362 
363  // Setup boundary element lookup schemes
365  }
366 
367 } // namespace oomph
368 #endif
static char t char * s
Definition: cfortran.h:568
cstr elem_len * i
Definition: cfortran.h:603
void setup_boundary_element_info()
Setup lookup schemes which establish whic elements are located next to mesh's boundaries (wrapper to ...
Definition: brick_mesh.h:195
MacroElement * macro_element_pt(const unsigned &i)
Access to i-th macro element.
Definition: domain.h:116
Eighth sphere as domain. Domain is parametrised by four macro elements.
EighthSphereMesh(const double &radius, TimeStepper *time_stepper_pt=&Mesh::Default_TimeStepper)
Constructor: Pass radius and timestepper; defaults to static default timestepper.
Domain * Domain_pt
Pointer to the domain.
double Radius
Radius of the sphere.
Node *& node_pt(const unsigned &n)
Return a pointer to the local node n.
Definition: elements.h:2175
virtual void local_fraction_of_node(const unsigned &j, Vector< double > &s_fraction)
Get the local fraction of the node j in the element A dumb, but correct default implementation is pro...
Definition: elements.cc:3191
virtual unsigned nnode_1d() const
Return the number of nodes along one edge of the element Default is to return zero — must be overload...
Definition: elements.h:2218
void macro_map(const Vector< double > &s, Vector< double > &r)
The mapping from local to global coordinates at the current time : r(s)
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
Vector< Node * > Node_pt
Vector of pointers to nodes.
Definition: mesh.h:183
FiniteElement * finite_element_pt(const unsigned &e) const
Upcast (downcast?) to FiniteElement (needed to access FiniteElement member functions).
Definition: mesh.h:473
void set_nboundary(const unsigned &nbound)
Set the number of boundaries in the mesh.
Definition: mesh.h:505
Node *& node_pt(const unsigned long &n)
Return pointer to global node n.
Definition: mesh.h:436
Vector< GeneralisedElement * > Element_pt
Vector of pointers to generalised elements.
Definition: mesh.h:186
double & x(const unsigned &i)
Return the i-th nodal coordinate.
Definition: nodes.h:1060
////////////////////////////////////////////////////////////////////// //////////////////////////////...
Definition: timesteppers.h:231
//////////////////////////////////////////////////////////////////// ////////////////////////////////...