single_layer_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_SPINE_MESH_TEMPLATE_HEADER
27#define OOMPH_SINGLE_LAYER_SPINE_MESH_TEMPLATE_HEADER
28
29#ifndef OOMPH_SINGLE_LAYER_SPINE_MESH_HEADER
30#error __FILE__ should only be included from single_layer_spine_mesh.h.
31#endif // OOMPH_SINGLE_LAYER_SPINE_MESH_HEADER
32
34
35namespace oomph
36{
37 //===========================================================================
38 /// Constructor for spine 2D mesh: Pass number of elements in x-direction,
39 /// number of elements in y-direction, axial length and height of layer,
40 /// and pointer to timestepper (defaults to Static timestepper).
41 ///
42 /// The mesh must be called with spinified elements and it
43 /// constructs the spines and contains the information on how to update
44 /// the nodal positions within the mesh as a function of the spine lengths.
45 /// Equations that determine the spine heights (even if they are pinned)
46 /// must be specified externally or else there will be problems.
47
48 //===========================================================================
49 template<class ELEMENT>
51 const unsigned& nx,
52 const unsigned& ny,
53 const double& lx,
54 const double& h,
55 TimeStepper* time_stepper_pt)
56 : RectangularQuadMesh<ELEMENT>(
57 nx, ny, 0.0, lx, 0.0, h, false, false, time_stepper_pt)
58 {
59 // Mesh can only be built with 2D Qelements.
60 MeshChecker::assert_geometric_element<QElementGeometricBase, ELEMENT>(2);
61
62 // Mesh can only be built with spine elements
63 MeshChecker::assert_geometric_element<SpineFiniteElement, ELEMENT>(2);
64
65 // We've called the "generic" constructor for the RectangularQuadMesh
66 // which doesn't do much...
67
68 // Now build the mesh:
69 build_single_layer_mesh(time_stepper_pt);
70 }
71
72 //===========================================================================
73 /// Constuctor for spine 2D mesh: Pass number of elements in x-direction,
74 /// number of elements in y-direction, axial length and height of layer,
75 /// a boolean flag to make the mesh periodic in the x-direction,
76 /// and pointer to timestepper (defaults to Static timestepper).
77 ///
78 /// The mesh must be called with spinified elements and it
79 /// constructs the spines and contains the information on how to update
80 /// the nodal positions within the mesh as a function of the spine lengths.
81 /// Equations that determine the spine heights (even if they are pinned)
82 /// must be specified externally or else there will be problems.
83 //===========================================================================
84 template<class ELEMENT>
86 const unsigned& nx,
87 const unsigned& ny,
88 const double& lx,
89 const double& h,
90 const bool& periodic_in_x,
91 TimeStepper* time_stepper_pt)
92 : RectangularQuadMesh<ELEMENT>(
93 nx, ny, 0.0, lx, 0.0, h, periodic_in_x, false, time_stepper_pt)
94 {
95 // Mesh can only be built with 2D Qelements.
96 MeshChecker::assert_geometric_element<QElementGeometricBase, ELEMENT>(2);
97
98 // Mesh can only be built with spine elements
99 MeshChecker::assert_geometric_element<SpineFiniteElement, ELEMENT>(2);
100
101 // We've called the "generic" constructor for the RectangularQuadMesh
102 // which doesn't do much...
103
104 // Now build the mesh:
105 build_single_layer_mesh(time_stepper_pt);
106 }
107
108 //===========================================================================
109 /// Helper function that actually builds the single-layer spine mesh
110 /// based on the parameters set in the various constructors
111 //===========================================================================
112 template<class ELEMENT>
114 TimeStepper* time_stepper_pt)
115 {
116 // Mesh can only be built with 2D Qelements.
117 MeshChecker::assert_geometric_element<QElementGeometricBase, ELEMENT>(2);
118
119 // Build the underlying quad mesh:
121
122 // Read out the number of elements in the x-direction
123 unsigned n_x = this->Nx;
124 unsigned n_y = this->Ny;
125
126 // Allocate memory for the spines and fractions along spines
127 //---------------------------------------------------------
128
129 // Read out number of linear points in the element
130 unsigned n_p = dynamic_cast<ELEMENT*>(finite_element_pt(0))->nnode_1d();
131
132 // Allocate store for the spines:
133 if (this->Xperiodic)
134 {
135 Spine_pt.reserve((n_p - 1) * n_x);
136 }
137 else
138 {
139 Spine_pt.reserve((n_p - 1) * n_x + 1);
140 }
141
142 // FIRST SPINE
143 //-----------
144
145 // Element 0
146 // Node 0
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(0, 0);
153 // Set the pointer to the spine
154 nod_pt->spine_pt() = new_spine_pt;
155 // Set the fraction
156 nod_pt->fraction() = 0.0;
157 // Pointer to the mesh that implements the update fct
158 nod_pt->spine_mesh_pt() = this;
159
160 // Loop vertically along the spine
161 // Loop over the elements
162 for (unsigned long i = 0; i < n_y; i++)
163 {
164 // Loop over the vertical nodes, apart from the first
165 for (unsigned l1 = 1; l1 < n_p; l1++)
166 {
167 // Get pointer to node
168 SpineNode* nod_pt = element_node_pt(i * n_x, l1 * n_p);
169 // Set the pointer to the spine
170 nod_pt->spine_pt() = new_spine_pt;
171 // Set the fraction
172 nod_pt->fraction() =
173 (double(i) + double(l1) / double(n_p - 1)) / double(n_y);
174 // Pointer to the mesh that implements the update fct
175 nod_pt->spine_mesh_pt() = this;
176 }
177 }
178
179 // LOOP OVER OTHER SPINES
180 //----------------------
181
182 // Now loop over the elements horizontally
183 for (unsigned long j = 0; j < n_x; j++)
184 {
185 // Loop over the nodes in the elements horizontally, ignoring
186 // the first column
187
188 // Last spine needs special treatment in x-periodic meshes:
189 unsigned n_pmax = n_p;
190 if ((this->Xperiodic) && (j == n_x - 1)) n_pmax = n_p - 1;
191
192 for (unsigned l2 = 1; l2 < n_pmax; l2++)
193 {
194 // Assign the new spine with unit height
195 new_spine_pt = new Spine(1.0);
196 Spine_pt.push_back(new_spine_pt);
197
198 // Get the node
199 SpineNode* nod_pt = element_node_pt(j, l2);
200 // Set the pointer to spine
201 nod_pt->spine_pt() = new_spine_pt;
202 // Set the fraction
203 nod_pt->fraction() = 0.0;
204 // Pointer to the mesh that implements the update fct
205 nod_pt->spine_mesh_pt() = this;
206
207 // Loop vertically along the spine
208 // Loop over the elements
209 for (unsigned long i = 0; i < n_y; i++)
210 {
211 // Loop over the vertical nodes, apart from the first
212 for (unsigned l1 = 1; l1 < n_p; l1++)
213 {
214 // Get the node
215 SpineNode* nod_pt = element_node_pt(i * n_x + j, l1 * n_p + l2);
216 // Set the pointer to the spine
217 nod_pt->spine_pt() = new_spine_pt;
218 // Set the fraction
219 nod_pt->fraction() =
220 (double(i) + double(l1) / double(n_p - 1)) / double(n_y);
221 // Pointer to the mesh that implements the update fct
222 nod_pt->spine_mesh_pt() = this;
223 }
224 }
225 }
226 }
227
228 // Last spine needs special treatment for periodic meshes
229 // because it's the same as the first one...
230 if (this->Xperiodic)
231 {
232 // Last spine is the same as first one...
233 Spine* final_spine_pt = Spine_pt[0];
234
235 // Get the node
236 SpineNode* nod_pt = element_node_pt((n_x - 1), (n_p - 1));
237
238 // Set the pointer for the first node
239 nod_pt->spine_pt() = final_spine_pt;
240 // Set the fraction to be the same as for the nodes on the first row
241 nod_pt->fraction() = element_node_pt(0, 0)->fraction();
242 // Pointer to the mesh that implements the update fct
243 nod_pt->spine_mesh_pt() = element_node_pt(0, 0)->spine_mesh_pt();
244
245 // Now loop vertically along the spine
246 for (unsigned i = 0; i < n_y; i++)
247 {
248 // Loop over the vertical nodes, apart from the first
249 for (unsigned l1 = 1; l1 < n_p; l1++)
250 {
251 // Get the node
253 element_node_pt(i * n_x + (n_x - 1), l1 * n_p + (n_p - 1));
254
255 // Set the pointer to the spine
256 nod_pt->spine_pt() = final_spine_pt;
257 // Set the fraction to be the same as in first row
258 nod_pt->fraction() = element_node_pt(i * n_x, l1 * n_p)->fraction();
259 // Pointer to the mesh that implements the update fct
260 nod_pt->spine_mesh_pt() =
261 element_node_pt(i * n_x, l1 * n_p)->spine_mesh_pt();
262 }
263 }
264 }
265 }
266
267} // namespace oomph
268#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
TimeStepper *& time_stepper_pt()
Access function for pointer to time stepper: Null if object is not time-dependent.
RectangularQuadMesh is a two-dimensional mesh of Quad elements with Nx elements in the "x" (horizonal...
void build_mesh(TimeStepper *time_stepper_pt=&Mesh::Default_TimeStepper)
Generic mesh construction function: contains all the hard work.
SingleLayerSpineMesh(const unsigned &nx, const unsigned &ny, const double &lx, const double &h, TimeStepper *time_stepper_pt=&Mesh::Default_TimeStepper)
Constructor: Pass number of elements in x-direction, number of elements in y-direction,...
virtual void build_single_layer_mesh(TimeStepper *time_stepper_pt)
Helper function to actually build the single-layer spine mesh (called from various constructors)
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).