single_layer_cubic_spine_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-2025 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_SINGLE_LAYER_CUBIC_SPINE_MESH_TEMPLATE_HEADER
27#define OOMPH_SINGLE_LAYER_CUBIC_SPINE_MESH_TEMPLATE_HEADER
28
29#ifndef OOMPH_SINGLE_LAYER_CUBIC_SPINE_MESH_HEADER
30#error __FILE__ should only be included from single_layer_cubic_spine_mesh.h.
31#endif // OOMPH_SINGLE_LAYER_CUBIC_SPINE_MESH_HEADER
32
33#include "simple_cubic_mesh.h"
34
35namespace oomph
36{
37 //===========================================================================
38 /// Constructor for spine 3D mesh: Pass number of elements in x-direction,
39 /// number of elements in y-direction, number elements in z-direction,
40 /// length, width and height of layer,
41 /// and pointer to timestepper (defaults to Static timestepper).
42 //===========================================================================
43 template<class ELEMENT>
45 const unsigned& nx,
46 const unsigned& ny,
47 const unsigned& nz,
48 const double& lx,
49 const double& ly,
50 const double& h,
51 TimeStepper* time_stepper_pt)
52 : SimpleCubicMesh<ELEMENT>(nx, ny, nz, lx, ly, h, time_stepper_pt)
53 {
54 // Mesh can only be built with 3D Qelements.
55 MeshChecker::assert_geometric_element<QElementGeometricBase, ELEMENT>(3);
56
57 // Mesh can only be built with spine elements
58 MeshChecker::assert_geometric_element<SpineFiniteElement, ELEMENT>(3);
59
60 // Now build the single layer mesh on top of the existing mesh
61 build_single_layer_mesh(time_stepper_pt);
62 }
63
64 //===========================================================================
65 /// Helper function that actually builds the single-layer spine mesh
66 /// based on the parameters set in the various constructors
67 //===========================================================================
68 template<class ELEMENT>
70 TimeStepper* time_stepper_pt)
71 {
72 // Read out the number of elements in the x-direction
73 unsigned n_x = this->Nx;
74 // Read out the number of elements in the y-direction
75 unsigned n_y = this->Ny;
76 // Read out the number of elements in the z-direction
77 unsigned n_z = this->Nz;
78
79 // Allocate memory for the spines and fractions along spines
80
81 // Read out number of linear points in the element
82 unsigned n_p = dynamic_cast<ELEMENT*>(finite_element_pt(0))->nnode_1d();
83
84 // Allocate store for the spines: (different in the case of periodic meshes
85 // !!)
86 Spine_pt.reserve(((n_p - 1) * n_x + 1) * ((n_p - 1) * n_y + 1));
87
88 // Now we loop over all the elements and attach the spines
89
90 // FIRST ELEMENT: Element 0
91 // Loop over the nodes on the base of the element
92 for (unsigned l1 = 0; l1 < n_p; l1++) // y loop over the nodes
93 {
94 for (unsigned l2 = 0; l2 < n_p; l2++) // x loop over the nodes
95 {
96 // Assign the new spine with length h
97 Spine* new_spine_pt = new Spine(1.0);
98 Spine_pt.push_back(new_spine_pt);
99
100 // Get pointer to node
101 SpineNode* nod_pt = element_node_pt(0, l2 + l1 * n_p);
102 // Set the pointer to the spine
103 nod_pt->spine_pt() = new_spine_pt;
104 // Set the fraction
105 nod_pt->fraction() = 0.0;
106 // Pointer to the mesh that implements the update fct
107 nod_pt->spine_mesh_pt() = this;
108
109 // Loop vertically along the spine
110 // Loop over the elements
111 for (unsigned long k = 0; k < n_z; k++)
112 {
113 // Loop over the vertical nodes, apart from the first
114 for (unsigned l3 = 1; l3 < n_p; l3++)
115 {
116 // Get pointer to node
118 element_node_pt(k * n_x * n_y, l3 * n_p * n_p + l2 + l1 * n_p);
119 // Set the pointer to the spine
120 nod_pt->spine_pt() = new_spine_pt;
121 // Set the fraction
122 nod_pt->fraction() =
123 (double(k) + double(l3) / double(n_p - 1)) / double(n_z);
124 // Pointer to the mesh that implements the update fct
125 nod_pt->spine_mesh_pt() = this;
126 }
127 }
128 }
129 }
130
131 // LOOP OVER OTHER ELEMENTS IN THE FIRST ROW
132 //-----------------------------------------
133
134 // The procedure is the same but we have to identify the
135 // before defined spines for not defining them two times
136
137 for (unsigned j = 1; j < n_x; j++) // loop over the elements in the first
138 // row
139 {
140 for (unsigned l1 = 0; l1 < n_p; l1++) // y loop over the nodes
141 {
142 // First we copy the last row of nodes into the
143 // first row of the new element (and extend to the third dimension)
144 for (unsigned l2 = 1; l2 < n_p; l2++) // x loop over the nodes
145 {
146 // Node j + i*np
147 // Assign the new spine with unit length
148 Spine* new_spine_pt = new Spine(1.0);
149 Spine_pt.push_back(new_spine_pt);
150
151 // Get pointer to node
152 SpineNode* nod_pt = element_node_pt(j, l2 + l1 * n_p);
153
154 // Set the pointer to the spine
155 nod_pt->spine_pt() = new_spine_pt;
156 // Set the fraction
157 nod_pt->fraction() = 0.0;
158 // Pointer to the mesh that implements the update fct
159 nod_pt->spine_mesh_pt() = this;
160
161 // Loop vertically along the spine
162 // Loop over the elements
163 for (unsigned long k = 0; k < n_z; k++)
164 {
165 // Loop over the vertical nodes, apart from the first
166 for (unsigned l3 = 1; l3 < n_p; l3++)
167 {
168 // Get pointer to node
169 SpineNode* nod_pt = element_node_pt(
170 j + k * n_x * n_y, l3 * n_p * n_p + l2 + l1 * n_p);
171 // Set the pointer to the spine
172 nod_pt->spine_pt() = new_spine_pt;
173 // Set the fraction
174 nod_pt->fraction() =
175 (double(k) + double(l3) / double(n_p - 1)) / double(n_z);
176 // Pointer to the mesh that implements the update fct
177 nod_pt->spine_mesh_pt() = this;
178 }
179 }
180 }
181 }
182 }
183
184 // REST OF THE ELEMENTS
185 // Now we loop over the rest of the elements.
186 // We will separate the first of each row being al the rest equal
187 for (unsigned long i = 1; i < n_y; i++)
188 {
189 // FIRST ELEMENT OF THE ROW
190
191 // First line of nodes is copied from the element of the bottom
192 for (unsigned l1 = 1; l1 < n_p; l1++) // y loop over the nodes
193 {
194 for (unsigned l2 = 0; l2 < n_p; l2++) // x loop over the nodes
195 {
196 // Node j + i*np
197 // Assign the new spine with unit length
198 Spine* new_spine_pt = new Spine(1.0);
199 Spine_pt.push_back(new_spine_pt);
200
201 // Get pointer to node
202 // Element i*n_x; node l2 + l1*n_p
203 SpineNode* nod_pt = element_node_pt(i * n_x, l2 + l1 * n_p);
204 // Set the pointer to the spine
205 nod_pt->spine_pt() = new_spine_pt;
206 // Set the fraction
207 nod_pt->fraction() = 0.0;
208 // Pointer to the mesh that implements the update fct
209 nod_pt->spine_mesh_pt() = this;
210
211 // Loop vertically along the spine
212 // Loop over the elements
213 for (unsigned long k = 0; k < n_z; k++)
214 {
215 // Loop over the vertical nodes, apart from the first
216 for (unsigned l3 = 1; l3 < n_p; l3++)
217 {
218 // Get pointer to node
219 SpineNode* nod_pt = element_node_pt(
220 i * n_x + k * n_x * n_y, l3 * n_p * n_p + l2 + l1 * n_p);
221 // Set the pointer to the spine
222 nod_pt->spine_pt() = new_spine_pt;
223 // Set the fraction
224 nod_pt->fraction() =
225 (double(k) + double(l3) / double(n_p - 1)) / double(n_z);
226 // Pointer to the mesh that implements the update fct
227 nod_pt->spine_mesh_pt() = this;
228 }
229 }
230 }
231 }
232
233 // REST OF THE ELEMENTS OF THE ROW
234 for (unsigned j = 1; j < n_x; j++)
235 {
236 // First line of nodes is copied from the element of the bottom
237 for (unsigned l1 = 1; l1 < n_p; l1++) // y loop over the nodes
238 {
239 for (unsigned l2 = 1; l2 < n_p; l2++) // x loop over the nodes
240 {
241 // Node j + i*np
242 // Assign the new spine with unit length
243 Spine* new_spine_pt = new Spine(1.0);
244 Spine_pt.push_back(new_spine_pt);
245
246 // Get pointer to node
247 // Element j + i*n_x; node l2 + l1*n_p
248 SpineNode* nod_pt = element_node_pt(j + i * n_x, l2 + l1 * n_p);
249 // Set the pointer to the spine
250 nod_pt->spine_pt() = new_spine_pt;
251 // Set the fraction
252 nod_pt->fraction() = 0.0;
253 // Pointer to the mesh that implements the update fct
254 nod_pt->spine_mesh_pt() = this;
255
256 // Loop vertically along the spine
257 // Loop over the elements
258 for (unsigned long k = 0; k < n_z; k++)
259 {
260 // Loop over the vertical nodes, apart from the first
261 for (unsigned l3 = 1; l3 < n_p; l3++)
262 {
263 // Get pointer to node
264 SpineNode* nod_pt = element_node_pt(
265 j + i * n_x + k * n_x * n_y, l3 * n_p * n_p + l2 + l1 * n_p);
266 // Set the pointer to the spine
267 nod_pt->spine_pt() = new_spine_pt;
268 // Set the fraction
269 nod_pt->fraction() =
270 (double(k) + double(l3) / double(n_p - 1)) / double(n_z);
271 // Pointer to the mesh that implements the update fct
272 nod_pt->spine_mesh_pt() = this;
273 }
274 }
275 }
276 }
277 }
278 }
279 }
280
281} // namespace oomph
282#endif
cstr elem_len * i
Definition cfortran.h:603
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:2222
Simple cubic 3D Brick mesh class.
virtual void build_single_layer_mesh(TimeStepper *time_stepper_pt)
Helper function to actually build the single-layer spine mesh (called from various constructors)
SingleLayerCubicSpineMesh(const unsigned &nx, const unsigned &ny, const unsigned &nz, const double &lx, const double &ly, const double &h, TimeStepper *time_stepper_pt=&Mesh::Default_TimeStepper)
Constructor: Pass number of elements in x-direction, number of elements in y-direction,...
Class for nodes that live on spines. The assumption is that each Node lies at a fixed fraction on a s...
Definition spines.h:328
Spines are used for algebraic node update operations in free-surface fluid problems: They form the ba...
Definition spines.h:64
TAdvectionDiffusionReactionElement<NREAGENT,DIM,NNODE_1D> elements are isoparametric triangular DIM-d...
TAdvectionDiffusionReactionElement()
Constructor: Call constructors for TElement and AdvectionDiffusionReaction equations.
Base class for time-stepping schemes. Timestepper provides an approximation of the temporal derivativ...
DRAIG: Change all instances of (SPATIAL_DIM) to (DIM-1).