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-2024 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_CC
27#define OOMPH_CIRCULAR_SHELL_MESH_TEMPLATE_CC
28
29#include <float.h>
30
33
34
35namespace oomph
36{
37 //=======================================================================
38 /// Mesh build fct
39 //=======================================================================
40 template<class ELEMENT>
42 const unsigned& ny,
43 const double& lx,
44 const double& ly)
45 {
46 // Mesh can only be built with 2D Qelements.
47 MeshChecker::assert_geometric_element<QElementGeometricBase, ELEMENT>(2);
48
49 // Find out how many nodes there are
50 unsigned n_node = nnode();
51
52 // Now in this case it is the Lagrangian coordinates that we want to set,
53 // so we have to loop over all nodes and set them to the Eulerian
54 // coordinates that are set by the generic mesh generator
55 for (unsigned i = 0; i < n_node; i++)
56 {
57 node_pt(i)->xi(0) = scaled_x(node_pt(i)->x(0));
58 node_pt(i)->xi(1) = node_pt(i)->x(1);
59 }
60
61
62 // Loop over elements and nodes to find out min axial spacing
63 // for all nodes
64
65 // Initialise map
66 std::map<Node*, double> min_dx;
67 unsigned nnod = nnode();
68 for (unsigned j = 0; j < nnod; j++) min_dx[node_pt(j)] = DBL_MAX;
69
70 // Loop over elements
71 unsigned nelem = nelement();
72 for (unsigned e = 0; e < nelem; e++)
73 {
74 ELEMENT* el_pt = dynamic_cast<ELEMENT*>(element_pt(e));
75 unsigned n_node = el_pt->nnode();
76 for (unsigned j = 0; j < n_node; j++)
77 {
78 SolidNode* nod_pt = dynamic_cast<SolidNode*>(el_pt->node_pt(j));
79 double x = nod_pt->xi(0);
80 for (unsigned k = 0; k < n_node; k++)
81 {
82 double dx =
83 fabs(x - dynamic_cast<SolidNode*>(el_pt->node_pt(k))->xi(0));
84 if (dx < min_dx[nod_pt])
85 {
86 if (dx != 0.0) min_dx[nod_pt] = dx;
87 }
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 {
111
112 // Get min. spacing for non-uniform axial spacing
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 //=======================================================================
124 /// Set the undeformed coordinates of the nodes
125 //=======================================================================
126 template<class ELEMENT>
129 {
130 // Loop over nodes in elements
131 unsigned nelem = nelement();
132 for (unsigned e = 0; e < nelem; e++)
133 {
134 ELEMENT* el_pt = dynamic_cast<ELEMENT*>(element_pt(e));
135 unsigned n_node = el_pt->nnode();
136 for (unsigned n = 0; n < n_node; n++)
137 {
138 // Get the Lagrangian coordinates
140 xi[0] = dynamic_cast<SolidNode*>(el_pt->node_pt(n))->xi(0);
141 xi[1] = dynamic_cast<SolidNode*>(el_pt->node_pt(n))->xi(1);
142
143 // Assign memory for values of derivatives, etc
144 Vector<double> R(3);
147
148 // Get the geometrical information from the geometric object
149 undeformed_midplane_pt->d2position(xi, R, a, dadxi);
150
151
152 // Get derivatives of Lagr coordinates w.r.t. local coords
154 Vector<double> s(2);
155 el_pt->local_coordinate_of_node(n, s);
156 el_pt->interpolated_dxids(s, dxids);
157 double dxds = dxids(0, 0);
158
159 // Loop over coordinate directions
160 for (unsigned i = 0; i < 3; i++)
161 {
162 // Set the position
163 el_pt->node_pt(n)->x_gen(0, i) = R[i];
164
165 // Set generalised positions
166 el_pt->node_pt(n)->x_gen(1, i) = a(0, i) * dxds;
167 el_pt->node_pt(n)->x_gen(2, i) =
168 0.5 * a(1, i) * ((this->Ymax - this->Ymin) / this->Ny);
169
170 // Set the mixed derivative
171 el_pt->node_pt(n)->x_gen(3, i) = 0.0;
172
173 // Check for warping
174 if (dadxi(0, 1, i) != 0.0)
175 {
176 std::ostringstream error_stream;
178 << "Undef. GeomObject for this shell mesh should not be warped!\n"
179 << "It may be possible to generalise the mesh generator to \n"
180 << "deal with this case -- feel free to have a go...\n";
181 throw OomphLibError(error_stream.str(),
184 }
185 }
186 }
187 }
188 }
189
190
191} // namespace oomph
192
193
194// namespace oomph
195// {
196
197
198// //=======================================================================
199// /// Mesh constructor
200// /// Argument list:
201// /// nx : number of elements in the axial direction
202// /// ny : number of elements in the azimuthal direction
203// /// lx : length in the axial direction
204// /// ly : length in theta direction
205// //=======================================================================
206// template <class ELEMENT>
207// CircularCylindricalShellMesh<ELEMENT>::CircularCylindricalShellMesh(
208// const unsigned &nx,
209// const unsigned &ny,
210// const double &lx,
211// const double &ly,
212// TimeStepper* time_stepper_pt) :
213// RectangularQuadMesh<ELEMENT>(nx,ny,lx,ly,time_stepper_pt)
214// {
215// //Find out how many nodes there are
216// unsigned n_node = nnode();
217
218// //Now in this case it is the Lagrangian coordinates that we want to set,
219// //so we have to loop over all nodes and set them to the Eulerian
220// //coordinates that are set by the generic mesh generator
221// for(unsigned i=0;i<n_node;i++)
222// {
223// node_pt(i)->xi(0) = node_pt(i)->x(0);
224// node_pt(i)->xi(1) = node_pt(i)->x(1);
225// }
226
227
228// //Assign gradients, etc for the Lagrangian coordinates of
229// //Hermite-type elements
230
231// //Read out number of position dofs
232// unsigned n_position_type = finite_element_pt(0)->nnodal_position_type();
233
234// //If this is greater than 1 set the slopes, which are the distances between
235// //nodes. If the spacing were non-uniform, this part would be more difficult
236// if(n_position_type > 1)
237// {
238// double xstep = (this->Xmax - this->Xmin)/((this->Np-1)*this->Nx);
239// double ystep = (this->Ymax - this->Ymin)/((this->Np-1)*this->Ny);
240// for(unsigned n=0;n<n_node;n++)
241// {
242// //The factor 0.5 is because our reference element has length 2.0
243// node_pt(n)->xi_gen(1,0) = 0.5*xstep;
244// node_pt(n)->xi_gen(2,1) = 0.5*ystep;
245// }
246// }
247// }
248
249
250// //=======================================================================
251// /// Set the undeformed coordinates of the nodes
252// //=======================================================================
253// template <class ELEMENT>
254// void CircularCylindricalShellMesh<ELEMENT>::assign_undeformed_positions(
255// GeomObject* const &undeformed_midplane_pt)
256// {
257// //Find out how many nodes there are
258// unsigned n_node = nnode();
259
260// //Loop over all the nodes
261// for(unsigned n=0;n<n_node;n++)
262// {
263// //Get the Lagrangian coordinates
264// Vector<double> xi(2);
265// xi[0] = node_pt(n)->xi(0);
266// xi[1] = node_pt(n)->xi(1);
267
268// //Assign memory for values of derivatives, etc
269// Vector<double> R(3);
270// DenseMatrix<double> a(2,3);
271// RankThreeTensor<double> dadxi(2,2,3);
272
273// //Get the geometrical information from the geometric object
274// undeformed_midplane_pt->d2position(xi,R,a,dadxi);
275
276// //Loop over coordinate directions
277// for(unsigned i=0;i<3;i++)
278// {
279// //Set the position
280// node_pt(n)->x_gen(0,i) = R[i];
281
282// //Set the derivative wrt Lagrangian coordinates
283// //Note that we need to scale by the length of each element here!!
284// node_pt(n)->x_gen(1,i) = 0.5*a(0,i)*((this->Xmax -
285// this->Xmin)/this->Nx); node_pt(n)->x_gen(2,i) = 0.5*a(1,i)*((this->Ymax
286// - this->Ymin)/this->Ny);
287
288// //Set the mixed derivative
289// //(symmetric so doesn't matter which one we use)
290// node_pt(n)->x_gen(3,i) = 0.25*dadxi(0,1,i);
291// }
292// }
293// }
294
295
296// }
297#endif
void build_mesh(const unsigned &nx, const unsigned &ny, const double &lx, const double &ly)
Mesh build helper fct.
void assign_undeformed_positions(GeomObject *const &undeformed_midplane_pt)
In all elastic problems, the nodes must be assigned an undeformed, or reference, position,...
Simple rectangular 2D Quad mesh class. Nx : number of elements in the x direction.
////////////////////////////////////////////////////////////////////// //////////////////////////////...