Toggle navigation
Documentation
Big picture
The finite element method
The data structure
Not-so-quick guide
Optimisation
Order of action functions
Example codes and tutorials
List of example codes and tutorials
Meshing
Solvers
MPI parallel processing
Post-processing/visualisation
Other
Change log
Creating documentation
Coding conventions
Index
FAQ
About
People
Contact/Get involved
Publications
Acknowledgements
Copyright
Picture show
Go
src
meshes
circular_shell_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_CIRCULAR_SHELL_MESH_TEMPLATE_HEADER
27
#define OOMPH_CIRCULAR_SHELL_MESH_TEMPLATE_HEADER
28
29
#ifndef OOMPH_CIRCULAR_SHELL_MESH_HEADER
30
#error __FILE__ should only be included from circular_shell_mesh.h.
31
#endif
// OOMPH_CIRCULAR_SHELL_MESH_HEADER
32
33
#include <float.h>
34
35
#include "
rectangular_quadmesh.h
"
36
37
namespace
oomph
38
{
39
//=======================================================================
40
/// Mesh build fct
41
//=======================================================================
42
template
<
class
ELEMENT>
43
void
CircularCylindricalShellMesh<ELEMENT>::build_mesh
(
const
unsigned
& nx,
44
const
unsigned
& ny,
45
const
double
&
lx
,
46
const
double
&
ly
)
47
{
48
// Mesh can only be built with 2D Qelements.
49
MeshChecker::assert_geometric_element<QElementGeometricBase, ELEMENT>(2);
50
51
// Find out how many nodes there are
52
unsigned
n_node
=
nnode
();
53
54
// Now in this case it is the Lagrangian coordinates that we want to set,
55
// so we have to loop over all nodes and set them to the Eulerian
56
// coordinates that are set by the generic mesh generator
57
for
(
unsigned
i
= 0;
i
<
n_node
;
i
++)
58
{
59
node_pt
(
i
)->xi(0) = scaled_x(
node_pt
(
i
)->x(0));
60
node_pt
(
i
)->xi(1) =
node_pt
(
i
)->x(1);
61
}
62
63
// Loop over elements and nodes to find out min axial spacing
64
// for all nodes
65
66
// Initialise map
67
std::map<Node*, double>
min_dx
;
68
unsigned
nnod
=
nnode
();
69
for
(
unsigned
j
= 0;
j
<
nnod
;
j
++)
min_dx
[
node_pt
(
j
)] =
DBL_MAX
;
70
71
// Loop over elements
72
unsigned
nelem
=
nelement
();
73
for
(
unsigned
e
= 0;
e
<
nelem
;
e
++)
74
{
75
ELEMENT
*
el_pt
=
dynamic_cast<
ELEMENT
*
>
(
element_pt
(
e
));
76
unsigned
n_node
=
el_pt
->nnode();
77
for
(
unsigned
j
= 0;
j
<
n_node
;
j
++)
78
{
79
SolidNode
*
nod_pt
=
dynamic_cast<
SolidNode
*
>
(
el_pt
->node_pt(
j
));
80
double
x =
nod_pt
->xi(0);
81
for
(
unsigned
k
= 0;
k
<
n_node
;
k
++)
82
{
83
double
dx
=
84
fabs
(x -
dynamic_cast<
SolidNode
*
>
(
el_pt
->node_pt(
k
))->xi(0));
85
if
(
dx
<
min_dx
[
nod_pt
])
86
{
87
if
(
dx
!= 0.0)
min_dx
[
nod_pt
] =
dx
;
88
}
89
}
90
}
91
}
92
93
// Assign gradients, etc for the Lagrangian coordinates of
94
// Hermite-type elements
95
96
// Read out number of position dofs
97
unsigned
n_position_type
=
finite_element_pt
(0)->nnodal_position_type();
98
99
// Assign generalised Lagrangian positions (min slope, c.f. M. Heil's PhD
100
// thesis
101
if
(
n_position_type
> 1)
102
{
103
// Default spacing
104
double
xstep
= (this->Xmax - this->Xmin) / ((this->Np - 1) * this->Nx);
105
double
ystep
= (this->Ymax - this->Ymin) / ((this->Np - 1) * this->Ny);
106
107
// Adjust for non-uniform spacing
108
for
(
unsigned
j
= 0;
j
<
n_node
;
j
++)
109
{
110
SolidNode
*
nod_pt
=
node_pt
(
j
);
111
112
// Get min. spacing for non-uniform axial spacing
113
xstep
=
min_dx
[
nod_pt
];
114
115
// The factor 0.5 is because our reference element has length 2.0
116
nod_pt
->xi_gen(1, 0) = 0.5 *
xstep
;
117
nod_pt
->xi_gen(2, 1) = 0.5 *
ystep
;
118
}
119
}
120
}
121
122
//=======================================================================
123
/// Set the undeformed coordinates of the nodes
124
//=======================================================================
125
template
<
class
ELEMENT>
126
void
CircularCylindricalShellMesh<ELEMENT>::assign_undeformed_positions
(
127
GeomObject
*
const
&
undeformed_midplane_pt
)
128
{
129
// Loop over nodes in elements
130
unsigned
nelem
=
nelement
();
131
for
(
unsigned
e
= 0;
e
<
nelem
;
e
++)
132
{
133
ELEMENT
*
el_pt
=
dynamic_cast<
ELEMENT
*
>
(
element_pt
(
e
));
134
unsigned
n_node
=
el_pt
->nnode();
135
for
(
unsigned
n
= 0;
n
<
n_node
;
n
++)
136
{
137
// Get the Lagrangian coordinates
138
Vector<double>
xi
(2);
139
xi
[0] =
dynamic_cast<
SolidNode
*
>
(
el_pt
->node_pt(
n
))->
xi
(0);
140
xi
[1] =
dynamic_cast<
SolidNode
*
>
(
el_pt
->node_pt(
n
))->
xi
(1);
141
142
// Assign memory for values of derivatives, etc
143
Vector<double>
R
(3);
144
DenseMatrix<double>
a
(2, 3);
145
RankThreeTensor<double>
dadxi
(2, 2, 3);
146
147
// Get the geometrical information from the geometric object
148
undeformed_midplane_pt
->d2position(
xi
,
R
,
a
,
dadxi
);
149
150
// Get derivatives of Lagr coordinates w.r.t. local coords
151
DenseMatrix<double>
dxids
(2, 2);
152
Vector<double>
s
(2);
153
el_pt
->local_coordinate_of_node(
n
,
s
);
154
el_pt
->interpolated_dxids(
s
,
dxids
);
155
double
dxds
=
dxids
(0, 0);
156
157
// Loop over coordinate directions
158
for
(
unsigned
i
= 0;
i
< 3;
i
++)
159
{
160
// Set the position
161
el_pt
->node_pt(
n
)->x_gen(0,
i
) =
R
[
i
];
162
163
// Set generalised positions
164
el_pt
->node_pt(
n
)->x_gen(1,
i
) =
a
(0,
i
) *
dxds
;
165
el_pt
->node_pt(
n
)->x_gen(2,
i
) =
166
0.5 *
a
(1,
i
) * ((this->Ymax - this->Ymin) / this->Ny);
167
168
// Set the mixed derivative
169
el_pt
->node_pt(
n
)->x_gen(3,
i
) = 0.0;
170
171
// Check for warping
172
if
(
dadxi
(0, 1,
i
) != 0.0)
173
{
174
std::ostringstream
error_stream
;
175
error_stream
176
<<
"Undef. GeomObject for this shell mesh should not be warped!\n"
177
<<
"It may be possible to generalise the mesh generator to \n"
178
<<
"deal with this case -- feel free to have a go...\n"
;
179
throw
OomphLibError
(
error_stream
.str(),
180
OOMPH_CURRENT_FUNCTION
,
181
OOMPH_EXCEPTION_LOCATION
);
182
}
183
}
184
}
185
}
186
}
187
188
}
// namespace oomph
189
190
// namespace oomph
191
// {
192
193
// //=======================================================================
194
// /// Mesh constructor
195
// /// Argument list:
196
// /// nx : number of elements in the axial direction
197
// /// ny : number of elements in the azimuthal direction
198
// /// lx : length in the axial direction
199
// /// ly : length in theta direction
200
// //=======================================================================
201
// template <class ELEMENT>
202
// CircularCylindricalShellMesh<ELEMENT>::CircularCylindricalShellMesh(
203
// const unsigned &nx,
204
// const unsigned &ny,
205
// const double &lx,
206
// const double &ly,
207
// TimeStepper* time_stepper_pt) :
208
// RectangularQuadMesh<ELEMENT>(nx,ny,lx,ly,time_stepper_pt)
209
// {
210
// //Find out how many nodes there are
211
// unsigned n_node = nnode();
212
213
// //Now in this case it is the Lagrangian coordinates that we want to set,
214
// //so we have to loop over all nodes and set them to the Eulerian
215
// //coordinates that are set by the generic mesh generator
216
// for(unsigned i=0;i<n_node;i++)
217
// {
218
// node_pt(i)->xi(0) = node_pt(i)->x(0);
219
// node_pt(i)->xi(1) = node_pt(i)->x(1);
220
// }
221
222
// //Assign gradients, etc for the Lagrangian coordinates of
223
// //Hermite-type elements
224
225
// //Read out number of position dofs
226
// unsigned n_position_type = finite_element_pt(0)->nnodal_position_type();
227
228
// //If this is greater than 1 set the slopes, which are the distances between
229
// //nodes. If the spacing were non-uniform, this part would be more difficult
230
// if(n_position_type > 1)
231
// {
232
// double xstep = (this->Xmax - this->Xmin)/((this->Np-1)*this->Nx);
233
// double ystep = (this->Ymax - this->Ymin)/((this->Np-1)*this->Ny);
234
// for(unsigned n=0;n<n_node;n++)
235
// {
236
// //The factor 0.5 is because our reference element has length 2.0
237
// node_pt(n)->xi_gen(1,0) = 0.5*xstep;
238
// node_pt(n)->xi_gen(2,1) = 0.5*ystep;
239
// }
240
// }
241
// }
242
243
// //=======================================================================
244
// /// Set the undeformed coordinates of the nodes
245
// //=======================================================================
246
// template <class ELEMENT>
247
// void CircularCylindricalShellMesh<ELEMENT>::assign_undeformed_positions(
248
// GeomObject* const &undeformed_midplane_pt)
249
// {
250
// //Find out how many nodes there are
251
// unsigned n_node = nnode();
252
253
// //Loop over all the nodes
254
// for(unsigned n=0;n<n_node;n++)
255
// {
256
// //Get the Lagrangian coordinates
257
// Vector<double> xi(2);
258
// xi[0] = node_pt(n)->xi(0);
259
// xi[1] = node_pt(n)->xi(1);
260
261
// //Assign memory for values of derivatives, etc
262
// Vector<double> R(3);
263
// DenseMatrix<double> a(2,3);
264
// RankThreeTensor<double> dadxi(2,2,3);
265
266
// //Get the geometrical information from the geometric object
267
// undeformed_midplane_pt->d2position(xi,R,a,dadxi);
268
269
// //Loop over coordinate directions
270
// for(unsigned i=0;i<3;i++)
271
// {
272
// //Set the position
273
// node_pt(n)->x_gen(0,i) = R[i];
274
275
// //Set the derivative wrt Lagrangian coordinates
276
// //Note that we need to scale by the length of each element here!!
277
// node_pt(n)->x_gen(1,i) = 0.5*a(0,i)*((this->Xmax -
278
// this->Xmin)/this->Nx); node_pt(n)->x_gen(2,i) = 0.5*a(1,i)*((this->Ymax
279
// - this->Ymin)/this->Ny);
280
281
// //Set the mixed derivative
282
// //(symmetric so doesn't matter which one we use)
283
// node_pt(n)->x_gen(3,i) = 0.25*dadxi(0,1,i);
284
// }
285
// }
286
// }
287
288
// }
289
#endif
oomph::CircularCylindricalShellMesh::build_mesh
void build_mesh(const unsigned &nx, const unsigned &ny, const double &lx, const double &ly)
Mesh build helper fct.
Definition
circular_shell_mesh.template.cc:43
oomph::CircularCylindricalShellMesh::assign_undeformed_positions
void assign_undeformed_positions(GeomObject *const &undeformed_midplane_pt)
In all elastic problems, the nodes must be assigned an undeformed, or reference, position,...
Definition
circular_shell_mesh.template.cc:126
oomph::RefineableTriangleMesh
Unstructured refineable Triangle Mesh.
Definition
triangle_mesh.h:2225
oomph
Definition
annular_domain.h:35
rectangular_quadmesh.h