cylinder.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// Version 1.0; svn revision $LastChangedRevision$
7 //LIC//
8 //LIC// $LastChangedDate$
9 //LIC//
10 //LIC// Copyright (C) 2006-2016 Matthias Heil and Andrew Hazel
11 //LIC//
12 //LIC// This library is free software; you can redistribute it and/or
13 //LIC// modify it under the terms of the GNU Lesser General Public
14 //LIC// License as published by the Free Software Foundation; either
15 //LIC// version 2.1 of the License, or (at your option) any later version.
16 //LIC//
17 //LIC// This library is distributed in the hope that it will be useful,
18 //LIC// but WITHOUT ANY WARRANTY; without even the implied warranty of
19 //LIC// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
20 //LIC// Lesser General Public License for more details.
21 //LIC//
22 //LIC// You should have received a copy of the GNU Lesser General Public
23 //LIC// License along with this library; if not, write to the Free Software
24 //LIC// Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA
25 //LIC// 02110-1301 USA.
26 //LIC//
27 //LIC// The authors may be contacted at oomph-lib@maths.man.ac.uk.
28 //LIC//
29 //LIC//====================================================================
30 // Driver
31 
32 // The oomphlib headers
33 #include "generic.h"
34 #include "time_harmonic_fourier_decomposed_linear_elasticity.h"
35 
36 // The mesh
37 #include "meshes/rectangular_quadmesh.h"
38 
39 using namespace std;
40 
41 using namespace oomph;
42 
43 //===start_of_namespace=================================================
44 /// Namespace for global parameters
45 //======================================================================
47 {
48  /// Define Poisson's ratio Nu
49  std::complex<double> Nu(0.3,0.05);
50 
51  /// Define the non-dimensional Young's modulus
52  std::complex<double> E(1.0,0.01);
53 
54  // Lame parameters
55  std::complex<double> lambda = E*Nu/(1.0+Nu)/(1.0-2.0*Nu);
56  std::complex<double> mu = E/2.0/(1.0+Nu);
57 
58  /// Define Fourier wavenumber
60 
61  /// \short Define the non-dimensional square angular frequency of
62  /// time-harmonic motion
63  std::complex<double> Omega_sq (10.0,5.0);
64 
65  /// Length of domain in r direction
66  double Lr = 1.0;
67 
68  /// Length of domain in z-direction
69  double Lz = 2.0;
70 
71  // Set up min & max (r,z) coordinates
72  double rmin = 0.1;
73  double zmin = 0.3;
74  double rmax = rmin+Lr;
75  double zmax = zmin+Lz;
76 
77  /// Define the imaginary unit
78  const std::complex<double> I(0.0,1.0);
79 
80  /// The traction function at r=rmin: (t_r, t_z, t_theta)
81  void boundary_traction(const Vector<double> &x,
82  const Vector<double> &n,
83  Vector<std::complex<double> > &result)
84  {
85  result[0] = -6.0*pow(x[0],2)*mu*cos(x[1])-
86  lambda*(I*double(Fourier_wavenumber)*pow(x[0],2)*pow(x[1],3)+
87  (4.0*pow(x[0],2)+pow(x[0],3))*cos(x[1]));
88  result[1] = -mu*(3.0*pow(x[0],2)-pow(x[0],3))*sin(x[1]);
89  result[2] = -mu*pow(x[0],2)*(2*pow(x[1],3)+I*double(Fourier_wavenumber)*
90  cos(x[1]));
91  }
92 
93 
94  /// \short The body force function; returns vector of complex doubles
95  /// in the order (b_r, b_z, b_theta)
96  void body_force(const Vector<double> &x,
97  Vector<std::complex<double> > &result)
98  {
99  result[0] =
100  x[0]*(-2.0*I*lambda*double(Fourier_wavenumber)*pow(x[1],3)-cos(x[1])*
101  (lambda*(8.0+3.0*x[0])-
102  mu*(pow(double(Fourier_wavenumber),2)
103  -16.0+x[0]*(x[0]-3.0))+pow(x[0],2)*Omega_sq));
104  result[1] =
105  x[0]*sin(x[1])*(mu*(pow(double(Fourier_wavenumber),2)-9.0)+
106  4.0*x[0]*(lambda+mu)+pow(x[0],2)*
107  (lambda+2.0*mu-Omega_sq))-
108  3.0*I*double(Fourier_wavenumber)*pow(x[0],2)*pow(x[1],2)*(lambda+mu);
109  result[2] =
110  -x[0]*(8.0*mu*pow(x[1],3)-pow(double(Fourier_wavenumber),2)*pow(x[1],3)*
111  (lambda+2.0*mu)+pow(x[0],2)*(pow(x[1],3)*Omega_sq+6.0*mu*x[1])+
112  I*cos(x[1])*double(Fourier_wavenumber)*
113  (lambda*(4.0+x[0])+mu*(6.0+x[0])));
114  }
115 
116  /// The exact solution in a flat-packed vector:
117  // 0: u_r[real], 1: u_z[real],..., 5: u_theta[imag]
118  void exact_solution(const Vector<double> &x,
119  Vector<double> &u)
120  {
121  u[0] = pow(x[0],3)*cos(x[1]);
122  u[1] = pow(x[0],3)*sin(x[1]);
123  u[2] = pow(x[0],3)*pow(x[1],3);
124  u[3] = 0.0;
125  u[4] = 0.0;
126  u[5] = 0.0;
127  }
128 
129 } // end_of_namespace
130 
131 
132 //===start_of_problem_class=============================================
133 /// Class to validate time harmonic linear elasticity (Fourier
134 /// decomposed)
135 //======================================================================
136 template<class ELEMENT>
138 {
139 public:
140 
141  /// \short Constructor: Pass number of elements in r and z directions
142  /// and boundary locations
144  const unsigned &nr, const unsigned &nz,
145  const double &rmin, const double& rmax,
146  const double &zmin, const double& zmax);
147 
148 
149  /// Update before solve is empty
151 
152  /// Update after solve is empty
154 
155  /// Doc the solution
156  void doc_solution(DocInfo& doc_info);
157 
158 private:
159 
160  /// Allocate traction elements on the bottom surface
161  void assign_traction_elements();
162 
163  /// Pointer to the bulk mesh
165 
166  /// Pointer to the mesh of traction elements
168 }; // end_of_problem_class
169 
170 
171 //===start_of_constructor=============================================
172 /// Problem constructor: Pass number of elements in coordinate
173 /// directions and size of domain.
174 //====================================================================
175 template<class ELEMENT>
178 (const unsigned &nr, const unsigned &nz,
179  const double &rmin, const double& rmax,
180  const double &zmin, const double& zmax)
181 {
182  //Now create the mesh
183  Bulk_mesh_pt = new RectangularQuadMesh<ELEMENT>(nr,nz,rmin,rmax,zmin,zmax);
184 
185  //Create the surface mesh of traction elements
186  Surface_mesh_pt=new Mesh;
187  assign_traction_elements();
188 
189  // Set the boundary conditions for this problem: All nodes are
190  // free by default -- just pin & set the ones that have Dirichlet
191  // conditions here
192 
193  // storage for nodal position
194  Vector<double> x(2);
195 
196  // Storage for prescribed displacements
197  Vector<double> u(6);
198 
199  // Now set displacements on boundaries 0 (z=zmin),
200  //------------------------------------------------
201  // 1 (r=rmax) and 2 (z=zmax)
202  //--------------------------
203  for (unsigned ibound=0;ibound<=2;ibound++)
204  {
205  unsigned num_nod=Bulk_mesh_pt->nboundary_node(ibound);
206  for (unsigned inod=0;inod<num_nod;inod++)
207  {
208  // Get pointer to node
209  Node* nod_pt=Bulk_mesh_pt->boundary_node_pt(ibound,inod);
210 
211  // get r and z coordinates
212  x[0]=nod_pt->x(0);
213  x[1]=nod_pt->x(1);
214 
215  // Pinned in r, z and theta
216  nod_pt->pin(0);nod_pt->pin(1);nod_pt->pin(2);
217  nod_pt->pin(3);nod_pt->pin(4);nod_pt->pin(5);
218 
219  // Compute the value of the exact solution at the nodal point
220  Vector<double> u(6);
222 
223  // Set the displacements
224  nod_pt->set_value(0,u[0]);
225  nod_pt->set_value(1,u[1]);
226  nod_pt->set_value(2,u[2]);
227  nod_pt->set_value(3,u[3]);
228  nod_pt->set_value(4,u[4]);
229  nod_pt->set_value(5,u[5]);
230  }
231  } // end_of_loop_over_boundary_nodes
232 
233 
234  // Complete the problem setup to make the elements fully functional
235 
236  // Loop over the elements
237  unsigned n_el = Bulk_mesh_pt->nelement();
238  for(unsigned e=0;e<n_el;e++)
239  {
240  // Cast to a bulk element
241  ELEMENT *el_pt = dynamic_cast<ELEMENT*>(Bulk_mesh_pt->element_pt(e));
242 
243  // Set the body force
244  el_pt->body_force_fct_pt() = &Global_Parameters::body_force;
245 
246  // Set the pointer to Poisson's ratio
247  el_pt->nu_pt() = &Global_Parameters::Nu;
248 
249  // Set the pointer to Fourier wavenumber
250  el_pt->fourier_wavenumber_pt() = &Global_Parameters::Fourier_wavenumber;
251 
252  // Set the pointer to non-dim Young's modulus
253  el_pt->youngs_modulus_pt() = &Global_Parameters::E;
254 
255  // Set the pointer to square of the angular frequency
256  el_pt->omega_sq_pt() = &Global_Parameters::Omega_sq;
257 
258  }// end loop over elements
259 
260  // Loop over the traction elements
261  unsigned n_traction = Surface_mesh_pt->nelement();
262  for(unsigned e=0;e<n_traction;e++)
263  {
264  // Cast to a surface element
265  TimeHarmonicFourierDecomposedLinearElasticityTractionElement<ELEMENT>*
266  el_pt =
267  dynamic_cast<TimeHarmonicFourierDecomposedLinearElasticityTractionElement
268  <ELEMENT>* >(Surface_mesh_pt->element_pt(e));
269 
270  // Set the applied traction
271  el_pt->traction_fct_pt() = &Global_Parameters::boundary_traction;
272 
273  }// end loop over traction elements
274 
275  // Add the submeshes to the problem
276  add_sub_mesh(Bulk_mesh_pt);
277  add_sub_mesh(Surface_mesh_pt);
278 
279  // Now build the global mesh
280  build_global_mesh();
281 
282  // Assign equation numbers
283  cout << assign_eqn_numbers() << " equations assigned" << std::endl;
284 
285 } // end of constructor
286 
287 
288 //===start_of_traction===============================================
289 /// Make traction elements along the boundary r=rmin
290 //===================================================================
291 template<class ELEMENT>
294 {
295  unsigned bound, n_neigh;
296 
297  // How many bulk elements are next to boundary 3
298  bound=3;
299  n_neigh = Bulk_mesh_pt->nboundary_element(bound);
300 
301  // Now loop over bulk elements and create the face elements
302  for(unsigned n=0;n<n_neigh;n++)
303  {
304  // Create the face element
305  FiniteElement *traction_element_pt
306  = new TimeHarmonicFourierDecomposedLinearElasticityTractionElement<ELEMENT>
307  (Bulk_mesh_pt->boundary_element_pt(bound,n),
308  Bulk_mesh_pt->face_index_at_boundary(bound,n));
309 
310  // Add to mesh
311  Surface_mesh_pt->add_element_pt(traction_element_pt);
312  }
313 
314 } // end of assign_traction_elements
315 
316 
317 //==start_of_doc_solution=================================================
318 /// Doc the solution
319 //========================================================================
320 template<class ELEMENT>
322 doc_solution(DocInfo& doc_info)
323 {
324  ofstream some_file;
325  char filename[100];
326 
327  // Number of plot points
328  unsigned npts=5;
329 
330  // Output solution
331  sprintf(filename,"%s/soln.dat",doc_info.directory().c_str());
332  some_file.open(filename);
333  Bulk_mesh_pt->output(some_file,npts);
334  some_file.close();
335 
336  // Output exact solution
337  sprintf(filename,"%s/exact_soln.dat",doc_info.directory().c_str());
338  some_file.open(filename);
339  Bulk_mesh_pt->output_fct(some_file,npts,
341  some_file.close();
342 
343  // Doc error
344  double error=0.0;
345  double norm=0.0;
346  sprintf(filename,"%s/error.dat",doc_info.directory().c_str());
347  some_file.open(filename);
348  Bulk_mesh_pt->compute_error(some_file,
350  error,norm);
351  some_file.close();
352 
353  // Doc error norm:
354  cout << "\nNorm of error: " << sqrt(error) << std::endl;
355  cout << "Norm of solution: " << sqrt(norm) << std::endl << std::endl;
356  cout << std::endl;
357 
358 } // end_of_doc_solution
359 
360 
361 //===start_of_main======================================================
362 /// Driver code
363 //======================================================================
364 int main(int argc, char* argv[])
365 {
366  // Number of elements in r-direction
367  unsigned nr=5;
368 
369  // Number of elements in z-direction (for (approximately) square elements)
370  unsigned nz=unsigned(double(nr)*Global_Parameters::Lz/Global_Parameters::Lr);
371 
372  // Set up doc info
373  DocInfo doc_info;
374 
375  // Set output directory
376  doc_info.set_directory("RESLT");
377 
378  // Set up problem
380  <QTimeHarmonicFourierDecomposedLinearElasticityElement<3> >
383 
384  // Solve
385  problem.newton_solve();
386 
387  // Output the solution
388  problem.doc_solution(doc_info);
389 
390 } // end_of_main
const std::complex< double > I(0.0, 1.0)
Define the imaginary unit.
Mesh * Bulk_mesh_pt
Pointer to the bulk mesh.
Definition: cylinder.cc:164
void boundary_traction(const Vector< double > &x, const Vector< double > &n, Vector< std::complex< double > > &result)
The traction function at r=rmin: (t_r, t_z, t_theta)
Definition: cylinder.cc:81
std::complex< double > lambda
Definition: cylinder.cc:55
std::complex< double > Nu(0.3, 0.05)
Define Poisson&#39;s ratio Nu.
int Fourier_wavenumber
Define Fourier wavenumber.
Definition: cylinder.cc:59
void doc_solution(DocInfo &doc_info)
Doc the solution.
Definition: cylinder.cc:322
FourierDecomposedTimeHarmonicLinearElasticityProblem(const unsigned &nr, const unsigned &nz, const double &rmin, const double &rmax, const double &zmin, const double &zmax)
Constructor: Pass number of elements in r and z directions and boundary locations.
Definition: cylinder.cc:178
void body_force(const Vector< double > &x, Vector< std::complex< double > > &result)
The body force function; returns vector of complex doubles in the order (b_r, b_z, b_theta)
Definition: cylinder.cc:96
void actions_before_newton_solve()
Update before solve is empty.
Definition: cylinder.cc:150
Namespace for global parameters.
Definition: cylinder.cc:46
std::complex< double > E(1.0, 0.01)
Define the non-dimensional Young&#39;s modulus.
double Lr
Length of domain in r direction.
Definition: cylinder.cc:66
double Lz
Length of domain in z-direction.
Definition: cylinder.cc:69
void exact_solution(const Vector< double > &x, Vector< double > &u)
The exact solution in a flat-packed vector:
Definition: cylinder.cc:118
std::complex< double > mu
Definition: cylinder.cc:56
void actions_after_newton_solve()
Update after solve is empty.
Definition: cylinder.cc:153
void assign_traction_elements()
Allocate traction elements on the bottom surface.
Definition: cylinder.cc:293
std::complex< double > Omega_sq(10.0, 5.0)
Define the non-dimensional square angular frequency of time-harmonic motion.
int main(int argc, char *argv[])
Driver code.
Definition: cylinder.cc:364
Mesh * Surface_mesh_pt
Pointer to the mesh of traction elements.
Definition: cylinder.cc:167