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
36
37namespace oomph
38{
39 //=======================================================================
40 /// Mesh build fct
41 //=======================================================================
42 template<class ELEMENT>
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 {
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 /// Set the undeformed coordinates of the nodes
124 //=======================================================================
125 template<class ELEMENT>
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);
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
152 Vector<double> s(2);
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;
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(),
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
e
Definition cfortran.h:571
static char t char * s
Definition cfortran.h:568
cstr elem_len * i
Definition cfortran.h:603
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,...
virtual void local_coordinate_of_node(const unsigned &j, Vector< double > &s) const
Get local coordinates of node j in the element; vector sets its own size (broken virtual)
Definition elements.h:1846
unsigned nnodal_position_type() const
Return the number of coordinate types that the element requires to interpolate the geometry between t...
Definition elements.h:2467
unsigned nnode() const
Return the number of nodes.
Definition elements.h:2214
Node *& node_pt(const unsigned &n)
Return a pointer to the local node n.
Definition elements.h:2179
A geometric object is an object that provides a parametrised description of its shape via the functio...
virtual void d2position(const Vector< double > &zeta, RankThreeTensor< double > &ddrdzeta) const
2nd derivative of position Vector w.r.t. to coordinates: = ddrdzeta(alpha,beta,i)....
double & x(const unsigned &i)
Return the i-th nodal coordinate.
Definition nodes.h:1060
double & x_gen(const unsigned &k, const unsigned &i)
Reference to the generalised position x(k,i). ‘Type’: k; Coordinate direction: i.
Definition nodes.h:1126
An OomphLibError object which should be thrown when an run-time error is encountered....
A Class for nodes that deform elastically (i.e. position is an unknown in the problem)....
Definition nodes.h:1686
double & xi(const unsigned &i)
Reference to i-th Lagrangian position.
Definition nodes.h:1883
TAdvectionDiffusionReactionElement<NREAGENT,DIM,NNODE_1D> elements are isoparametric triangular DIM-d...
TAdvectionDiffusionReactionElement()
Constructor: Call constructors for TElement and AdvectionDiffusionReaction equations.
DRAIG: Change all instances of (SPATIAL_DIM) to (DIM-1).