axisym_displ_based_fvk_elements.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: 1097 $
7 //LIC//
8 //LIC// $LastChangedDate: 2015-12-17 11:53:17 +0000 (Thu, 17 Dec 2015) $
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 //Non-inline functions for axisym FoepplvonKarman elements
31 
33 
34 
35 
36 namespace oomph
37 {
38 
39 //======================================================================
40 /// Set the data for the number of Variables at each node - 3
41 //======================================================================
42  template<unsigned NNODE_1D>
43  const unsigned AxisymFoepplvonKarmanElement<NNODE_1D>::Initial_Nvalue = 3;
44 
45 
46 //======================================================================
47 /// Compute contribution to element residual Vector
48 ///
49 /// Pure version without hanging nodes
50 //======================================================================
53  {
54  //Find out how many nodes there are
55  const unsigned n_node = nnode();
56 
57  //Set up memory for the shape and test functions
58  Shape psi(n_node), test(n_node);
59  DShape dpsidr(n_node,1), dtestdr(n_node,1);
60 
61  //Set the value of n_intpt
62  const unsigned n_intpt = integral_pt()->nweight();
63 
64  //Indices at which the unknowns are stored
65  const unsigned w_nodal_index = nodal_index_fvk(0);
66  const unsigned laplacian_w_nodal_index = nodal_index_fvk(1);
67  const unsigned u_r_nodal_index = nodal_index_fvk(2);
68 
69  // Local copy of parameters
70  const double nu_local=nu();
71  const double eta_local=eta();
72 
73  //Integers to store the local equation numbers
74  int local_eqn=0;
75 
76  //Loop over the integration points
77  for(unsigned ipt=0;ipt<n_intpt;ipt++)
78  {
79  //Get the integral weight
80  double w = integral_pt()->weight(ipt);
81 
82  //Call the derivatives of the shape and test functions
83  double J = dshape_and_dtest_eulerian_at_knot_axisym_fvk(ipt,psi,dpsidr,
84  test,dtestdr);
85 
86  //Allocate and initialise to zero storage for the interpolated values
87  double interpolated_r = 0.0;
88 
89  double interpolated_w = 0.0;
90  double interpolated_laplacian_w = 0.0;
91  double interpolated_u_r = 0.0;
92 
93  double interpolated_dwdr = 0.0;
94  double interpolated_dlaplacian_wdr = 0.0;
95  double interpolated_du_rdr = 0.0;
96 
98 
99  //Calculate function values and derivatives:
100  //-----------------------------------------
101  // Loop over nodes
102  for(unsigned l=0;l<n_node;l++)
103  {
104  //Get the nodal values
105  nodal_value[0] = raw_nodal_value(l,w_nodal_index);
106  nodal_value[1] = raw_nodal_value(l,laplacian_w_nodal_index);
107  nodal_value[2] = raw_nodal_value(l,u_r_nodal_index);
108 
109  //Add contributions from current node/shape function
110  interpolated_w += nodal_value[0]*psi(l);
111  interpolated_laplacian_w += nodal_value[1]*psi(l);
112  interpolated_u_r +=nodal_value[2]*psi(l);
113 
114  interpolated_r += raw_nodal_position(l,0)*psi(l);
115 
116  interpolated_dwdr += nodal_value[0]*dpsidr(l,0);
117  interpolated_dlaplacian_wdr += nodal_value[1]*dpsidr(l,0);
118  interpolated_du_rdr += nodal_value[2]*dpsidr(l,0);
119 
120  }// End of loop over the nodes
121 
122  //Premultiply the weights and the Jacobian
123  double W = w*interpolated_r*J;
124 
125  //Get pressure function
126  //---------------------
127  double pressure=0.0;
128  get_pressure_fvk(ipt,interpolated_r,pressure);
129 
130  // Determine the stresses
131  //-----------------------
132 
133  double sigma_r_r = 0.0;
134  double sigma_phi_phi = 0.0;
135 
137  {
138  sigma_r_r = 1.0/(1.0-nu_local*nu_local)*
139  (interpolated_du_rdr+0.5*interpolated_dwdr*
140  interpolated_dwdr+nu_local*1.0/interpolated_r*interpolated_u_r);
141 
142  sigma_phi_phi = 1.0/(1.0-nu_local*nu_local)
143  *(1.0/interpolated_r*interpolated_u_r+nu_local
144  *(interpolated_du_rdr+0.5*interpolated_dwdr*interpolated_dwdr));
145  }
146  else
147  {
148  sigma_r_r = 1.0/(1.0-nu_local*nu_local)
149  *(interpolated_du_rdr+nu_local*1.0/interpolated_r*interpolated_u_r);
150 
151  sigma_phi_phi = 1.0/(1.0-nu_local*nu_local)
152  *(1.0/interpolated_r*interpolated_u_r+nu_local*interpolated_du_rdr);
153  }
154 
155 
156  // Assemble residuals and Jacobian:
157  //--------------------------------
158  // Loop over the test functions
159  for(unsigned l=0;l<n_node;l++)
160  {
161 
162  // Get the local equation
163  local_eqn = nodal_local_eqn(l,w_nodal_index);
164 
165  // IF it's not a boundary condition
166  if(local_eqn >= 0)
167  {
168  residuals[local_eqn] += (pressure*test(l)
169  +(dtestdr(l,0))
170  *interpolated_dlaplacian_wdr)*W;
172  {
173  residuals[local_eqn] -= eta_local*sigma_r_r
174  *(dtestdr(l,0))
175  *interpolated_dwdr*W;
176  }
177  }
178 
179  // Get the local equation
180  local_eqn = nodal_local_eqn(l,laplacian_w_nodal_index);
181 
182  // IF it's not a boundary condition
183  if(local_eqn >= 0)
184  {
185  residuals[local_eqn] += (test(l)*interpolated_laplacian_w
186  +(dtestdr(l,0))
187  *interpolated_dwdr)*W;
188  }
189 
190  // Get the local equation
191  local_eqn = nodal_local_eqn(l,u_r_nodal_index);
192 
193  // IF it's not a boundary condition
194  if(local_eqn >= 0)
195  {
196  residuals[local_eqn] += (sigma_r_r*dtestdr(l,0)+1.0/interpolated_r
197  *sigma_phi_phi*test(l))*W;
198  }
199 
200  } // End of loop over test functions
201  } // End of loop over integration points
202 
203  }
204 
205 
206 //======================================================================
207 /// Self-test: Return 0 for OK
208 //======================================================================
210  {
211 
212  bool passed=true;
213 
214  // Check lower-level stuff
215  if (FiniteElement::self_test()!=0)
216  {
217  passed=false;
218  }
219 
220  // Return verdict
221  if (passed)
222  {
223  return 0;
224  }
225  else
226  {
227  return 1;
228  }
229 
230  }
231 
232 
233 //======================================================================
234 /// Compute in-plane stresses. Return boolean to indicate success
235 /// (false if attempt to evaluate stresses at zero radius)
236 //======================================================================
238  (const Vector<double> &s, double& sigma_r_r, double& sigma_phi_phi) const
239  {
240 
241  // No in plane stresses if linear bending
242  if(Linear_bending_model)
243  {
244  sigma_r_r=0.0;
245  sigma_phi_phi=0.0;
246 
247  // Success!
248  return true;
249  }
250  else
251  {
252  // Get shape fcts and derivs
253  unsigned n_dim=this->dim();
254  unsigned n_node=this->nnode();
255  Shape psi(n_node);
256  DShape dpsidr(n_node,n_dim);
257 
258  // Check if we're dividing by zero
259  Vector<double> r(1);
260  this->interpolated_x(s,r);
261  if (r[0]==0.0)
262  {
263  sigma_r_r=0.0;
264  sigma_phi_phi=0.0;
265  return false;
266  }
267 
268  // Get shape fcts and derivs
269  dshape_eulerian(s,psi,dpsidr);
270 
271  //Allocate and initialise to zero storage for the interpolated values
272  double interpolated_r = 0.0;
273  double interpolated_u_r = 0.0;
274 
275  double interpolated_dwdr= 0.0;
276  double interpolated_du_rdr = 0.0;
277 
278  double nu_local = nu();
279 
280 
281  // Calculate function values and derivatives:
282  //-----------------------------------------
283  // Loop over nodes
284  for(unsigned l=0;l<n_node;l++)
285  {
286  //Add contributions from current node/shape function
287  interpolated_r += raw_nodal_position(l,0)*psi(l);
288  interpolated_u_r += this->raw_nodal_value(l,nodal_index_fvk(2))*psi(l);
289  interpolated_dwdr += this->raw_nodal_value(l,nodal_index_fvk(0))*
290  dpsidr(l,0);
291  interpolated_du_rdr += this->raw_nodal_value(l,nodal_index_fvk(2))*
292  dpsidr(l,0);
293  } // End of loop over nodes
294 
295  // Compute the stresses:
296  //---------------------
297  sigma_r_r = 1.0/(1.0-nu_local*nu_local)
298  *(interpolated_du_rdr+0.5*interpolated_dwdr
299  *interpolated_dwdr+nu_local*1.0/interpolated_r*interpolated_u_r);
300 
301  sigma_phi_phi = 1.0/(1.0-nu_local*nu_local)
302  *(1.0/interpolated_r*interpolated_u_r+nu_local
303  *(interpolated_du_rdr+0.5*interpolated_dwdr*interpolated_dwdr));
304 
305  // Success!
306  return true;
307 
308  } // End if
309 
310  } // End of interpolated_stress function
311 
312 //======================================================================
313 /// Output function:
314 /// r, w, sigma_r_r, sigma_phi_phi
315 /// nplot points
316 //======================================================================
317  void AxisymFoepplvonKarmanEquations::output(std::ostream &outfile,
318  const unsigned &nplot)
319  {
320 
321  //Vector of local coordinates
322  Vector<double> s(1);
323 
324  // Tecplot header info
325  outfile << "ZONE\n";
326 
327  // Loop over plot points
328  unsigned num_plot_points=nplot_points(nplot);
329  for (unsigned iplot=0;iplot<num_plot_points;iplot++)
330  {
331  // Get local coordinates of plot point
332  get_s_plot(iplot,nplot,s);
333 
334  // Get stress
335  double sigma_r_r=0.0;
336  double sigma_phi_phi=0.0;
337  bool success=interpolated_stress(s,sigma_r_r,sigma_phi_phi);
338  if (success)
339  {
340  outfile << interpolated_x(s,0) << " "
341  << interpolated_w_fvk(s) << " "
342  << interpolated_u_fvk(s) << " "
343  << sigma_r_r << " "
344  << sigma_phi_phi << std::endl;
345  }
346  }
347 
348  }
349 
350 //======================================================================
351 /// C-style output function:
352 /// r,w
353 /// nplot points
354 //======================================================================
356  const unsigned &nplot)
357  {
358  //Vector of local coordinates
359  Vector<double> s(1);
360 
361  // Tecplot header info
362  fprintf(file_pt,"%s",tecplot_zone_string(nplot).c_str());
363 
364  // Loop over plot points
365  unsigned num_plot_points=nplot_points(nplot);
366  for (unsigned iplot=0;iplot<num_plot_points;iplot++)
367  {
368  // Get local coordinates of plot point
369  get_s_plot(iplot,nplot,s);
370 
371  fprintf(file_pt,"%g ",interpolated_x(s,0));
372  fprintf(file_pt,"%g \n",interpolated_w_fvk(s));
373  fprintf(file_pt,"%g \n",interpolated_u_fvk(s));
374  }
375 
376  // Write tecplot footer (e.g. FE connectivity lists)
377  write_tecplot_zone_footer(file_pt,nplot);
378  }
379 
380 
381 //======================================================================
382  /// Output exact solution
383  ///
384  /// Solution is provided via function pointer.
385  /// Plot at a given number of plot points.
386  ///
387  /// r,w_exact
388 //======================================================================
390  (std::ostream &outfile,
391  const unsigned &nplot,
393  {
394  //Vector of local coordinates
395  Vector<double> s(1);
396 
397  // Vector for coordinates
398  Vector<double> r(1);
399 
400  // Tecplot header info
401  outfile << tecplot_zone_string(nplot);
402 
403  // Exact solution Vector (here a scalar)
404  //Vector<double> exact_soln(1);
405  Vector<double> exact_soln(1);
406 
407  // Loop over plot points
408  unsigned num_plot_points=nplot_points(nplot);
409  for (unsigned iplot=0;iplot<num_plot_points;iplot++)
410  {
411  // Get local coordinates of plot point
412  get_s_plot(iplot,nplot,s);
413 
414  // Get r position as Vector
415  interpolated_x(s,r);
416 
417  // Get exact solution at this point
418  (*exact_soln_pt)(r,exact_soln);
419 
420  //Output r,w_exact
421  outfile << r[0] << " ";
422  outfile << exact_soln[0] << std::endl;
423  }
424 
425  // Write tecplot footer (e.g. FE connectivity lists)
426  write_tecplot_zone_footer(outfile,nplot);
427  }
428 
429 
430 //======================================================================
431  /// Validate against exact solution
432  ///
433  /// Solution is provided via function pointer.
434  /// Plot error at a given number of plot points.
435  ///
436 //======================================================================
438  (std::ostream &outfile,
440  double& error, double& norm)
441  {
442  // Initialise
443  error=0.0;
444  norm=0.0;
445 
446  //Vector of local coordinates
447  Vector<double> s(1);
448 
449  // Vector for coordintes
450  Vector<double> r(1);
451 
452  //Find out how many nodes there are in the element
453  unsigned n_node = nnode();
454 
455  Shape psi(n_node);
456 
457  //Set the value of n_intpt
458  unsigned n_intpt = integral_pt()->nweight();
459 
460  // Tecplot
461  outfile << "ZONE" << std::endl;
462 
463  // Exact solution Vector (here a scalar)
464  //Vector<double> exact_soln(1);
465  Vector<double> exact_soln(1);
466 
467  //Loop over the integration points
468  for(unsigned ipt=0;ipt<n_intpt;ipt++)
469  {
470  //Assign values of s
471  s[0] = integral_pt()->knot(ipt,0);
472 
473  //Get the integral weight
474  double w = integral_pt()->weight(ipt);
475 
476  // Get jacobian of mapping
477  double J=J_eulerian(s);
478 
479  //Premultiply the weights and the Jacobian
480  double W = w*J;
481 
482  // Get r position as Vector
483  interpolated_x(s,r);
484 
485  // Get FE function value
486  double w_fe=interpolated_w_fvk(s);
487 
488  // Get exact solution at this point
489  (*exact_soln_pt)(r,exact_soln);
490 
491  //Output r,error
492  outfile << r[0] << " ";
493  outfile << exact_soln[0] << " " << exact_soln[0]-w_fe << std::endl;
494 
495  // Add to error and norm
496  norm+=exact_soln[0]*exact_soln[0]*W;
497  error+=(exact_soln[0]-w_fe)*(exact_soln[0]-w_fe)*W;
498  }
499 
500  {
501  // Initialise
502  error=0.0;
503  norm=0.0;
504 
505  //Vector of local coordinates
506  Vector<double> s(1);
507 
508  // Vector for coordintes
509  Vector<double> r(1);
510 
511  //Find out how many nodes there are in the element
512  unsigned n_node = nnode();
513 
514  Shape psi(n_node);
515 
516  //Set the value of n_intpt
517  unsigned n_intpt = integral_pt()->nweight();
518 
519  // Tecplot
520  outfile << "ZONE" << std::endl;
521 
522  // Exact solution Vector (here a scalar)
523  //Vector<double> exact_soln(1);
524  Vector<double> exact_soln(1);
525 
526  //Loop over the integration points
527  for(unsigned ipt=0;ipt<n_intpt;ipt++)
528  {
529  //Assign values of s
530  s[0] = integral_pt()->knot(ipt,0);
531 
532  //Get the integral weight
533  double w = integral_pt()->weight(ipt);
534 
535  // Get jacobian of mapping
536  double J=J_eulerian(s);
537 
538  //Premultiply the weights and the Jacobian
539  double W = w*J;
540 
541  // Get r position as Vector
542  interpolated_x(s,r);
543 
544  // Get FE function value
545  double w_fe=interpolated_w_fvk(s);
546 
547  // Get exact solution at this point
548  (*exact_soln_pt)(r,exact_soln);
549 
550  //Output r error
551  outfile << r[0] << " ";
552  outfile << exact_soln[0] << " " << exact_soln[0]-w_fe << std::endl;
553 
554  // Add to error and norm
555  norm+=exact_soln[0]*exact_soln[0]*W;
556  error+=(exact_soln[0]-w_fe)*(exact_soln[0]-w_fe)*W;
557  }
558  }
559  }
560 
561 
562 //====================================================================
563 // Force build of templates
564 //====================================================================
565  template class AxisymFoepplvonKarmanElement<2>;
566  template class AxisymFoepplvonKarmanElement<3>;
567  template class AxisymFoepplvonKarmanElement<4>;
568 
569 }
virtual void get_s_plot(const unsigned &i, const unsigned &nplot, Vector< double > &s) const
Get cector of local coordinates of plot point i (when plotting nplot points in each "coordinate direc...
Definition: elements.h:2938
virtual void write_tecplot_zone_footer(std::ostream &outfile, const unsigned &nplot) const
Add tecplot zone "footer" to output stream (when plotting nplot points in each "coordinate direction"...
Definition: elements.h:2962
virtual unsigned nplot_points(const unsigned &nplot) const
Return total number of plot points (when plotting nplot points in each "coordinate direction") ...
Definition: elements.h:2976
virtual unsigned self_test()
Self-test: Check inversion of element & do self-test for GeneralisedElement. Return 0 if OK...
Definition: elements.cc:4247
double nodal_value(const unsigned &n, const unsigned &i) const
Return the i-th value stored at local node n. Produces suitably interpolated values for hanging nodes...
Definition: elements.h:2458
const double & eta() const
FvK parameter.
double raw_nodal_position(const unsigned &n, const unsigned &i) const
Return the i-th coordinate at local node n. Do not use the hanging node representation. NOTE: Moved to cc file because of a possible compiler bug in gcc (yes, really!). The move to the cc file avoids inlining which appears to cause problems (only) when compiled with gcc and -O3; offensive "illegal read" is in optimised-out section of code and data that is allegedly illegal is readily readable (by other means) just before this function is called so I can't really see how we could possibly be responsible for this...
Definition: elements.cc:1657
virtual double weight(const unsigned &i) const =0
Return weight of i-th integration point.
const double & nu() const
Poisson's ratio.
void output(std::ostream &outfile)
Output with default number of plot points.
unsigned self_test()
Self-test: Return 0 for OK.
virtual double interpolated_x(const Vector< double > &s, const unsigned &i) const
Return FE interpolated coordinate x[i] at local coordinate s.
Definition: elements.cc:3841
static char t char * s
Definition: cfortran.h:572
Integral *const & integral_pt() const
Return the pointer to the integration scheme (const version)
Definition: elements.h:1900
void(* SteadyExactSolutionFctPt)(const Vector< double > &, Vector< double > &)
Function pointer for function that computes vector-valued steady "exact solution" as ...
Definition: elements.h:1720
virtual unsigned nodal_index_fvk(const unsigned &i=0) const
Return the index at which the i-th unknown value is stored. The default value, i, is appropriate for ...
double interpolated_u_fvk(const Vector< double > &s) const
Return FE representation of radial displacement.
virtual double dshape_and_dtest_eulerian_at_knot_axisym_fvk(const unsigned &ipt, Shape &psi, DShape &dpsidr, Shape &test, DShape &dtestdr) const =0
Shape/test functions and derivs w.r.t. to global coords at integration point ipt; return Jacobian of ...
int nodal_local_eqn(const unsigned &n, const unsigned &i) const
Return the local equation number corresponding to the i-th value at the n-th local node...
Definition: elements.h:1383
virtual void get_pressure_fvk(const unsigned &ipt, const double &r, double &pressure) const
Get pressure term at (Eulerian) position r. This function is virtual to allow overloading in multi-ph...
double raw_nodal_value(const unsigned &n, const unsigned &i) const
Return the i-th value stored at local node n but do NOT take hanging nodes into account.
Definition: elements.h:2446
virtual unsigned nweight() const =0
Return the number of integration points of the scheme.
unsigned nnode() const
Return the number of nodes.
Definition: elements.h:2134
void compute_error(std::ostream &outfile, FiniteElement::SteadyExactSolutionFctPt exact_soln_pt, double &error, double &norm)
Get error against and norm of exact solution.
virtual std::string tecplot_zone_string(const unsigned &nplot) const
Return string for tecplot zone header (when plotting nplot points in each "coordinate direction") ...
Definition: elements.h:2949
bool Linear_bending_model
Flag which stores whether we are using a linear, pure bending model instead of the full non-linear Fo...
double interpolated_w_fvk(const Vector< double > &s) const
Return FE representation of transverse displacement.
bool interpolated_stress(const Vector< double > &s, double &sigma_r_r, double &sigma_phi_phi) const
Compute in-plane stresses. Return boolean to indicate success (false if attempt to evaluate stresses ...
void output_fct(std::ostream &outfile, const unsigned &n_plot, FiniteElement::SteadyExactSolutionFctPt exact_soln_pt)
Output exact soln: r,w_exact at n_plot plot points.
void fill_in_contribution_to_residuals(Vector< double > &residuals)
Fill in the residuals with this element's contribution.