displacement_based_foeppl_von_karman_elements.h
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 //Header file for FoepplvonKarman elements
31 #ifndef OOMPH_FOEPPLVONKARMAN_DISPLACEMENT_ELEMENTS_HEADER
32 #define OOMPH_FOEPPLVONKARMAN_DISPLACEMENT_ELEMENTS_HEADER
33 
34 // Config header generated by autoconfig
35 #ifdef HAVE_CONFIG_H
36  #include <oomph-lib-config.h>
37 #endif
38 
39 #include<sstream>
40 
41 //OOMPH-LIB headers
42 #include "../generic/projection.h"
43 #include "../generic/nodes.h"
44 #include "../generic/oomph_utilities.h"
45 
46 
47 
48 namespace oomph
49 {
50 
51 //=============================================================
52 /// A class for all isoparametric elements that solve the
53 /// Foeppl von Karman equations.
54 /// \f[
55 /// \nabla^4 w - \eta \frac{\partial}{\partial x_{\beta}}
56 /// \left( \sigma^{\alpha \beta}
57 /// \frac{\partial w}{\partial x_{\alpha}}
58 /// \right) = p(x,y)
59 /// \f]
60 /// and
61 /// \f[
62 /// \frac{\sigma^{\alpha \beta}}{\partial x_{\beta}} = \tau_\alpha
63 /// \f]
64 /// This contains the generic maths. Shape functions, geometric
65 /// mapping etc. must get implemented in derived class.
66 //=============================================================
68 {
69 
70 public:
71 
72  /// \short Function pointer to pressure function fct(x,f(x)) --
73  /// x is a Vector!
75  const Vector<double>& x, double& f);
76 
77  /// \short Function pointer to traction function fct(x,f(x)) --
78  /// x is a Vector!
79  typedef void (*FoepplvonKarmanTractionFctPt)(const Vector<double>& x,
80  Vector<double>& f);
81 
82  /// \short Constructor (must initialise the Pressure_fct_pt and the
83  /// Traction_fct_pt. Also set physical parameters to their default
84  /// values.
87  {
88  //Set default
90 
91  // Set all the physical constants to the default value (zero)
93 
94  // Linear bending model?
95  Linear_bending_model = false;
96  }
97 
98  /// Broken copy constructor
100  {
101  BrokenCopy::broken_copy("DisplacementBasedFoepplvonKarmanEquations");
102  }
103 
104  /// Broken assignment operator
106  {
107  BrokenCopy::broken_assign("DisplacementBasedFoepplvonKarmanEquations");
108  }
109 
110  /// Poisson's ratio
111  const double &nu() const {return *Nu_pt;}
112 
113  /// Pointer to Poisson's ratio
114  double* &nu_pt() {return Nu_pt;}
115 
116  /// Eta
117  const double &eta() const {return *Eta_pt;}
118 
119  /// Pointer to eta
120  double* &eta_pt() {return Eta_pt;}
121 
122  /// \short Return the index at which the i-th unknown value
123  /// is stored. The default value, i, is appropriate for single-physics
124  /// problems. By default, these are:
125  /// 0: w
126  /// 1: laplacian w
127  /// 2: u_x
128  /// 3: u_y
129  /// In derived multi-physics elements, this function should be overloaded
130  /// to reflect the chosen storage scheme. Note that these equations require
131  /// that the unknown is always stored at the same index at each node.
132  virtual inline unsigned nodal_index_fvk(const unsigned& i=0) const {return i;}
133 
134  /// Output with default number of plot points
135  void output(std::ostream &outfile)
136  {
137  const unsigned n_plot=5;
138  output(outfile,n_plot);
139  }
140 
141  /// \short Output FE representation of soln: x,y,w at
142  /// n_plot^DIM plot points
143  void output(std::ostream &outfile, const unsigned &n_plot);
144 
145  /// C_style output with default number of plot points
146  void output(FILE* file_pt)
147  {
148  const unsigned n_plot=5;
149  output(file_pt,n_plot);
150  }
151 
152  /// \short C-style output FE representation of soln: x,y,w at
153  /// n_plot^DIM plot points
154  void output(FILE* file_pt, const unsigned &n_plot);
155 
156  /// Output exact soln: x,y,w_exact at n_plot^DIM plot points
157  void output_fct(std::ostream &outfile, const unsigned &n_plot,
159 
160  /// \short Output exact soln: x,y,w_exact at
161  /// n_plot^DIM plot points (dummy time-dependent version to
162  /// keep intel compiler happy)
163  virtual void output_fct(std::ostream &outfile, const unsigned &n_plot,
164  const double& time,
166  exact_soln_pt)
167  {
168  throw OomphLibError(
169  "There is no time-dependent output_fct() for Foeppl von Karman"
170  "elements ",
171  OOMPH_CURRENT_FUNCTION,
172  OOMPH_EXCEPTION_LOCATION);
173  }
174 
175 
176  /// Get error against and norm of exact solution
177  void compute_error(std::ostream &outfile,
179  double& error, double& norm);
180 
181 
182  /// Dummy, time dependent error checker
183  void compute_error(std::ostream &outfile,
185  const double& time, double& error, double& norm)
186  {
187  throw OomphLibError(
188  "There is no time-dependent compute_error() for Foeppl von Karman"
189  "elements",
190  OOMPH_CURRENT_FUNCTION,
191  OOMPH_EXCEPTION_LOCATION);
192  }
193 
194  /// Access function: Pointer to pressure function
196 
197  /// Access function: Pointer to pressure function. Const version
199  {return Pressure_fct_pt;}
200 
201  /// Access function: Pointer to in-plane traction function
203 
204  /// Access function: Pointer to in-plane traction function. Const version
206  {return Traction_fct_pt;}
207 
208  /// \short Get pressure term at (Eulerian) position x. This function
209  /// is virtual to allow overloading in multi-physics problems where
210  /// the strength of the pressure function might be determined by
211  /// another system of equations.
212  inline virtual void get_pressure_fvk(const unsigned& ipt,
213  const Vector<double>& x,
214  double& pressure) const
215  {
216  //If no pressure function has been set, return zero
217  if(Pressure_fct_pt==0) {pressure = 0.0;}
218  else
219  {
220  // Get pressure strength
221  (*Pressure_fct_pt)(x,pressure);
222  }
223  }
224 
225  /// \short Get in-plane traction term at (Eulerian) position x.
226  inline virtual void get_traction_fvk(Vector<double>& x,
227  Vector<double>& traction) const
228  {
229  //If no pressure function has been set, return zero
230  if(Traction_fct_pt==0)
231  {
232  traction[0] = 0.0;
233  traction[1] = 0.0;
234  }
235  else
236  {
237  // Get traction
238  (*Traction_fct_pt)(x,traction);
239  }
240  }
241 
242  /// Get gradient of deflection: gradient[i] = dw/dx_i
244  Vector<double>& gradient) const
245  {
246  //Find out how many nodes there are in the element
247  const unsigned n_node = nnode();
248 
249  //Get the index at which the unknown is stored
250  // Indexes for unknows are
251  // 0: W (vertical displacement)
252  // 1: L (laplacian of W)
253  // 2: Ux (In plane displacement x)
254  // 3: Uy (In plane displacement y)
255  unsigned w_nodal_index = nodal_index_fvk(0);
256 
257  //Set up memory for the shape and test functions
258  Shape psi(n_node);
259  DShape dpsidx(n_node,2);
260 
261  //Call the derivatives of the shape and test functions
262  dshape_eulerian(s,psi,dpsidx);
263 
264  //Initialise to zero
265  for(unsigned j=0;j<2;j++)
266  {
267  gradient[j] = 0.0;
268  }
269 
270  // Loop over nodes
271  for(unsigned l=0;l<n_node;l++)
272  {
273  //Loop over derivative directions
274  for(unsigned j=0;j<2;j++)
275  {
276  gradient[j] += this->nodal_value(l,w_nodal_index)*dpsidx(l,j);
277  }
278  }
279  }
280 
281  /// Get gradient of field: gradient[i] = d[.]/dx_i,
282  // Indices for fields are
283  // 0: W (vertical displacement)
284  // 1: L (laplacian of W)
285  // 2: Ux (In plane displacement x)
286  // 3: Uy (In plane displacement y)
288  Vector<double>& gradient,
289  const unsigned &index) const
290  {
291  //Find out how many nodes there are in the element
292  const unsigned n_node = nnode();
293 
294  //Get the index at which the unknown is stored
295  // Indexes for unknows are
296  // 0: W (vertical displacement)
297  // 1: L (laplacian of W)
298  // 2: Ux (In plane displacement x)
299  // 3: Uy (In plane displacement y)
300  const unsigned w_nodal_index = nodal_index_fvk(index);
301 
302  //Set up memory for the shape and test functions
303  Shape psi(n_node);
304  DShape dpsidx(n_node,2);
305 
306  //Call the derivatives of the shape and test functions
307  dshape_eulerian(s,psi,dpsidx);
308 
309  //Initialise to zero
310  for(unsigned j=0;j<2;j++)
311  {
312  gradient[j] = 0.0;
313  }
314 
315  // Loop over nodes
316  for(unsigned l=0;l<n_node;l++)
317  {
318  //Loop over derivative directions
319  for(unsigned j=0;j<2;j++)
320  {
321  gradient[j] += this->nodal_value(l,w_nodal_index)*dpsidx(l,j);
322  }
323  }
324  }
325 
326  /// Get the in-plane stress (sigma) as a fct of the pre=computed
327  /// displcement derivatives
329  const Vector<double> &interpolated_dwdx,
330  const Vector<double> &interpolated_duxdx,
331  const Vector<double> &interpolated_duydx)
332  {
333  // The strain tensor values
334  double e_xx = interpolated_duxdx[0];
335  double e_yy = interpolated_duydx[1];
336  double e_xy = 0.5 * (interpolated_duxdx[1] + interpolated_duydx[0]);
337  e_xx+= 0.5 * interpolated_dwdx[0] * interpolated_dwdx[0];
338  e_yy+= 0.5 * interpolated_dwdx[1] * interpolated_dwdx[1];
339  e_xy+= 0.5 * interpolated_dwdx[0] * interpolated_dwdx[1];
340 
341  // Get Poisson's ratio
342  const double _nu = nu();
343 
344  double inv_denom=1.0/(1.0-_nu*_nu);
345 
346  // The stress tensor values
347  // sigma_xx
348  sigma(0,0) = (e_xx + _nu*e_yy)*inv_denom;
349 
350  // sigma_yy
351  sigma(1,1) = (e_yy + _nu*e_xx)*inv_denom;
352 
353  // sigma_xy = sigma_yx
354  sigma(0,1) = sigma(1,0) = e_xy/(1.0+_nu);
355 
356  }
357 
358  // Get the stress for output
360  DenseMatrix<double> &sigma,
361  DenseMatrix<double> &strain)
362  {
363  //Find out how many nodes there are
364  const unsigned n_node = nnode();
365 
366  //Set up memory for the shape and test functions
367  Shape psi(n_node);
368  DShape dpsidx(n_node,2);
369 
370  //Local shape function
371  dshape_eulerian(s,psi,dpsidx);
372 
373  // Get the derivatives of the shape and test functions
374  //double J = dshape_and_dtest_eulerian_fvk(s, psi, dpsidx, test, dtestdx);
375 
376  //Indices at which the unknowns are stored
377  const unsigned w_nodal_index = nodal_index_fvk(0);
378  const unsigned u_x_nodal_index = nodal_index_fvk(2);
379  const unsigned u_y_nodal_index = nodal_index_fvk(3);
380 
381  //Allocate and initialise to zero storage for the interpolated values
382 
383  // The variables
384  Vector<double> interpolated_dwdx(2,0.0);
385  Vector<double> interpolated_duxdx(2,0.0);
386  Vector<double> interpolated_duydx(2,0.0);
387 
388  //--------------------------------------------
389  //Calculate function values and derivatives:
390  //--------------------------------------------
392  // Loop over nodes
393  for(unsigned l=0;l<n_node;l++)
394  {
395  //Get the nodal values
396  nodal_value[0] = this->nodal_value(l,w_nodal_index);
397  nodal_value[2] = this->nodal_value(l,u_x_nodal_index);
398  nodal_value[3] = this->nodal_value(l,u_y_nodal_index);
399 
400  //Add contributions from current node/shape function
401 
402  // Loop over directions
403  for(unsigned j=0;j<2;j++)
404  {
405  interpolated_dwdx[j] += nodal_value[0]*dpsidx(l,j);
406  interpolated_duxdx[j] += nodal_value[2]*dpsidx(l,j);
407  interpolated_duydx[j] += nodal_value[3]*dpsidx(l,j);
408 
409  } // Loop over directions for (j<2)
410 
411  } // Loop over nodes for (l<n_node)
412 
413 
414  // Get in-plane stress
415  get_sigma(sigma, interpolated_dwdx,
416  interpolated_duxdx, interpolated_duydx);
417 
418 
419  // The strain tensor values
420  // E_xx
421  strain(0,0) = interpolated_duxdx[0];
422  strain(0,0)+= 0.5 * interpolated_dwdx[0] * interpolated_dwdx[0];
423 
424  // E_yy
425  strain(1,1) = interpolated_duydx[1];
426  strain(1,1)+= 0.5 * interpolated_dwdx[1] * interpolated_dwdx[1];
427 
428  // E_xy
429  strain(0,1) = 0.5 * (interpolated_duxdx[1] + interpolated_duydx[0]);
430  strain(0,1)+= 0.5 * interpolated_dwdx[0] * interpolated_dwdx[1];
431 
432  // E_yx
433  strain(1,0)=strain(0,1);
434 
435  }
436 
437 
438  /// hierher dummy
440  Vector<double> &residuals, DenseMatrix<double> &jacobian,
441  DenseMatrix<double> &mass_matrix)
442  {
443 
444  // Get Jacobian from base class (FD-ed)
446  jacobian);
447 
448  // Dummy diagonal (won't result in global unit matrix but
449  // doesn't matter for zero eigenvalue/eigenvector
450  unsigned ndof=mass_matrix.nrow();
451  for (unsigned i=0;i<ndof;i++)
452  {
453  mass_matrix(i,i)+=1.0;
454  }
455 
456  }
457 
458 
459 
460 
461  /// Fill in the residuals with this element's contribution
463  {
464  //Find out how many nodes there are
465  const unsigned n_node = nnode();
466 
467  //Set up memory for the shape and test functions
468  Shape psi(n_node), test(n_node);
469  DShape dpsidx(n_node,2), dtestdx(n_node,2);
470 
471  //Indices at which the unknowns are stored
472  const unsigned w_nodal_index = nodal_index_fvk(0);
473  const unsigned laplacian_w_nodal_index = nodal_index_fvk(1);
474  const unsigned u_x_nodal_index = nodal_index_fvk(2);
475  const unsigned u_y_nodal_index = nodal_index_fvk(3);
476 
477  //Set the value of n_intpt
478  const unsigned n_intpt = integral_pt()->nweight();
479 
480  //Integers to store the local equation numbers
481  int local_eqn=0;
482 
483  //Loop over the integration points
484  for(unsigned ipt=0;ipt<n_intpt;ipt++)
485  {
486  //Get the integral weight
487  double w = integral_pt()->weight(ipt);
488 
489  //Call the derivatives of the shape and test functions
490  double J = dshape_and_dtest_eulerian_at_knot_fvk(ipt,psi,dpsidx,
491  test,dtestdx);
492 
493  //Premultiply the weights and the Jacobian
494  double W = w*J;
495 
496  //Allocate and initialise to zero storage for the interpolated values
498 
499  // The variables
500  double interpolated_laplacian_w = 0;
501  Vector<double> interpolated_dwdx(2,0.0);
502  Vector<double> interpolated_dlaplacian_wdx(2,0.0);
503  Vector<double> interpolated_duxdx(2,0.0);
504  Vector<double> interpolated_duydx(2,0.0);
505 
506  //--------------------------------------------
507  //Calculate function values and derivatives:
508  //--------------------------------------------
510  // Loop over nodes
511  for(unsigned l=0;l<n_node;l++)
512  {
513  //Get the nodal values
514  nodal_value[0] = this->nodal_value(l,w_nodal_index);
515  nodal_value[1] = this->nodal_value(l,laplacian_w_nodal_index);
516  nodal_value[2] = this->nodal_value(l,u_x_nodal_index);
517  nodal_value[3] = this->nodal_value(l,u_y_nodal_index);
518 
519  //Add contributions from current node/shape function
520  interpolated_laplacian_w += nodal_value[1]*psi(l);
521 
522  // Loop over directions
523  for(unsigned j=0;j<2;j++)
524  {
525  interpolated_x[j] += nodal_position(l,j)*psi(l);
526  interpolated_dwdx[j] += nodal_value[0]*dpsidx(l,j);
527  interpolated_dlaplacian_wdx[j] += nodal_value[1]*dpsidx(l,j);
528  interpolated_duxdx[j] += nodal_value[2]*dpsidx(l,j);
529  interpolated_duydx[j] += nodal_value[3]*dpsidx(l,j);
530 
531  } // Loop over directions for (j<2)
532 
533  } // Loop over nodes for (l<n_node)
534 
535  // Get in-plane stress
536  DenseMatrix<double> sigma(2,2,0.0);
537 
538  // Stress not used if we have the linear bending model
540  {
541  // Get the value of in plane stress at the integration
542  // point
543  get_sigma(sigma, interpolated_dwdx,
544  interpolated_duxdx, interpolated_duydx);
545  }
546 
547  //Get pressure function
548  //-------------------
549  double pressure = 0.0;
550  get_pressure_fvk(ipt,interpolated_x,pressure);
551 
552  // Assemble residuals and Jacobian
553  //--------------------------------
554 
555  // Loop over the test functions
556  for(unsigned l=0;l<n_node;l++)
557  {
558  //Get the local equation (First equation)
559  local_eqn = nodal_local_eqn(l,w_nodal_index);
560 
561  // IF it's not a boundary condition
562  if(local_eqn >= 0)
563  {
564  residuals[local_eqn] += pressure*test(l)*W;
565 
566  // Reduced order biharmonic operator
567  for(unsigned k=0;k<2;k++)
568  {
569  residuals[local_eqn] +=
570  interpolated_dlaplacian_wdx[k]*dtestdx(l,k)*W;
571  }
572 
573  // Sigma_alpha_beta part
575  {
576  // Alpha loop
577  for (unsigned alpha=0;alpha<2;alpha++)
578  {
579  // Beta loop
580  for(unsigned beta=0;beta<2;beta++)
581  {
582  residuals[local_eqn]-=
583  eta()*sigma(alpha,beta)*
584  interpolated_dwdx[alpha]*dtestdx(l,beta)*W;
585  }
586  }
587  } // if(!Linear_bending_model)
588  }
589 
590  //Get the local equation (Second equation)
591  local_eqn = nodal_local_eqn(l,laplacian_w_nodal_index);
592 
593  // IF it's not a boundary condition
594  if(local_eqn >= 0)
595  {
596  // The coupled Poisson equations for the biharmonic operator
597  residuals[local_eqn] += interpolated_laplacian_w*test(l)*W;
598 
599  for(unsigned k=0;k<2;k++)
600  {
601  residuals[local_eqn] += interpolated_dwdx[k]*dtestdx(l,k)*W;
602  }
603  }
604 
605  // Get in plane traction
606  Vector<double> traction(2, 0.0);
607  get_traction_fvk(interpolated_x,traction);
608 
609  //Get the local equation (Third equation)
610  local_eqn = nodal_local_eqn(l,u_x_nodal_index);
611 
612  // IF it's not a boundary condition
613  if(local_eqn >= 0)
614  {
615  // tau_x
616  residuals[local_eqn] += traction[0]*test(l)*W;
617 
618  // r_{\alpha = x}
619  for(unsigned beta=0;beta<2;beta++)
620  {
621  residuals[local_eqn] += sigma(0,beta)*dtestdx(l,beta)*W;
622  }
623 
624  }
625 
626  //Get the local equation (Fourth equation)
627  local_eqn = nodal_local_eqn(l,u_y_nodal_index);
628 
629  // IF it's not a boundary condition
630  if(local_eqn >= 0)
631  {
632  // tau_y
633  residuals[local_eqn] += traction[1]*test(l)*W;
634 
635  // r_{\alpha = y}
636  for(unsigned beta=0;beta<2;beta++)
637  {
638  residuals[local_eqn] += sigma(1,beta)*dtestdx(l,beta)*W;
639  }
640 
641  }
642 
643  } // End loop over nodes or test functions (l<n_node)
644 
645  } // End of loop over integration points
646 
647  }
648 
649 
650 
651  /// \short Return FE representation of function value w_fvk(s)
652  /// at local coordinate s (by default - if index > 0, returns
653  /// FE representation of valued stored at index^th nodal index
654  inline double interpolated_w_fvk(const Vector<double> &s,
655  unsigned index=0) const
656  {
657  //Find number of nodes
658  const unsigned n_node = nnode();
659 
660  //Get the index at which the poisson unknown is stored
661  const unsigned w_nodal_index = nodal_index_fvk(index);
662 
663  //Local shape function
664  Shape psi(n_node);
665 
666  //Find values of shape function
667  shape(s,psi);
668 
669  //Initialise value of u
670  double interpolated_w = 0.0;
671 
672  //Loop over the local nodes and sum
673  for(unsigned l=0;l<n_node;l++)
674  {
675  interpolated_w += this->nodal_value(l,w_nodal_index)*psi[l];
676  }
677 
678  return(interpolated_w);
679  }
680 
681  /// \short Self-test: Return 0 for OK
682  unsigned self_test();
683 
684  /// \short Sets a flag to signify that we are solving the linear, pure bending
685  /// equations, and pin all the nodal values that will not be used in this case
687  {
688  // Set the boolean flag
689  Linear_bending_model = true;
690 
691  // Get the index of the first FvK nodal value
692  unsigned first_fvk_nodal_index = nodal_index_fvk();
693 
694  // Get the total number of FvK nodal values (assuming they are stored
695  // contiguously) at node 0 (it's the same at all nodes anyway)
696  unsigned total_fvk_nodal_indices = 4;
697 
698  // Get the number of nodes in this element
699  unsigned n_node = nnode();
700 
701  // Loop over the appropriate nodal indices
702  for(unsigned index=first_fvk_nodal_index+2; // because [2] is u_x
703  // and [3] is u_y
704  index<first_fvk_nodal_index+total_fvk_nodal_indices;
705  index++)
706  {
707  // Loop over the nodes in the element
708  for(unsigned inod=0;inod<n_node;inod++)
709  {
710  // Pin the nodal value at the current index
711  node_pt(inod)->pin(index);
712  }
713  }
714  }
715 
716 
717 protected:
718 
719  /// \short Shape/test functions and derivs w.r.t. to global coords at
720  /// local coord. s; return Jacobian of mapping
721  virtual double dshape_and_dtest_eulerian_fvk(const Vector<double> &s,
722  Shape &psi,
723  DShape &dpsidx, Shape &test,
724  DShape &dtestdx) const=0;
725 
726 
727  /// \short Shape/test functions and derivs w.r.t. to global coords at
728  /// integration point ipt; return Jacobian of mapping
729  virtual double dshape_and_dtest_eulerian_at_knot_fvk(const unsigned &ipt,
730  Shape &psi,
731  DShape &dpsidx,
732  Shape &test,
733  DShape &dtestdx)
734  const=0;
735 
736 
737  /// Pointer to global Poisson's ratio
738  double *Nu_pt;
739 
740  /// Pointer to global eta
741  double *Eta_pt;
742 
743  /// Pointer to pressure function:
745 
746  /// Pointer to traction function:
748 
749 private:
750 
751  /// Default value for Poisson's ratio
752  static double Default_Nu_Value;
753 
754  /// Default value for physical constants
756 
757  /// \short Flag which stores whether we are using a linear, pure
758  /// bending model instead of the full non-linear Foeppl-von Karman
760 
761 };
762 
763 
764 //==========================================================
765 /// Foeppl von Karman upgraded to become projectable
766 //==========================================================
767  template<class FVK_ELEMENT>
769  public virtual ProjectableElement<FVK_ELEMENT>
770  {
771 
772  public:
773 
774  /// \short Specify the values associated with field fld. The
775  /// information is returned in a vector of pairs which comprise the
776  /// Data object and the value within it, that correspond to field
777  /// fld.
779  {
780 
781 #ifdef PARANOID
782  if (fld > 3)
783  {
784  std::stringstream error_stream;
785  error_stream
786  << "Foeppl von Karman elements only store four fields so fld must be"
787  << "0 to 3 rather than " << fld << std::endl;
788  throw OomphLibError(
789  error_stream.str(),
790  OOMPH_CURRENT_FUNCTION,
791  OOMPH_EXCEPTION_LOCATION);
792  }
793 #endif
794 
795  // Create the vector
796  unsigned nnod=this->nnode();
797  Vector<std::pair<Data*,unsigned> > data_values(nnod);
798 
799  // Loop over all nodes
800  for (unsigned j=0;j<nnod;j++)
801  {
802  // Add the data value associated field: The node itself
803  data_values[j]=std::make_pair(this->node_pt(j),fld);
804  }
805 
806  // Return the vector
807  return data_values;
808  }
809 
810  /// \short Number of fields to be projected: Just two
812  {
813  return 4;
814  }
815 
816  /// \short Number of history values to be stored for fld-th field.
817  /// (Note: count includes current value!)
818  unsigned nhistory_values_for_projection(const unsigned &fld)
819  {
820 #ifdef PARANOID
821  if (fld > 3)
822  {
823  std::stringstream error_stream;
824  error_stream
825  << "Foeppl von Karman elements only store four fields so fld must be"
826  << "0 to 3 rather than " << fld << std::endl;
827  throw OomphLibError(
828  error_stream.str(),
829  OOMPH_CURRENT_FUNCTION,
830  OOMPH_EXCEPTION_LOCATION);
831  }
832 #endif
833  return this->node_pt(0)->ntstorage();
834  }
835 
836 
837  ///\short Number of positional history values
838  /// (Note: count includes current value!)
840  {
841  return this->node_pt(0)->position_time_stepper_pt()->ntstorage();
842  }
843 
844  /// \short Return Jacobian of mapping and shape functions of field fld
845  /// at local coordinate s
846  double jacobian_and_shape_of_field(const unsigned &fld,
847  const Vector<double> &s,
848  Shape &psi)
849  {
850 #ifdef PARANOID
851  if (fld > 3)
852  {
853  std::stringstream error_stream;
854  error_stream
855  << "Foeppl von Karman elements only store four fields so fld must be"
856  << "0 to 3 rather than " << fld << std::endl;
857  throw OomphLibError(
858  error_stream.str(),
859  OOMPH_CURRENT_FUNCTION,
860  OOMPH_EXCEPTION_LOCATION);
861  }
862 #endif
863  unsigned n_dim=this->dim();
864  unsigned n_node=this->nnode();
865  Shape test(n_node);
866  DShape dpsidx(n_node,n_dim), dtestdx(n_node,n_dim);
867  double J=this->dshape_and_dtest_eulerian_fvk(s,psi,dpsidx,
868  test,dtestdx);
869  return J;
870  }
871 
872 
873 
874  /// \short Return interpolated field fld at local coordinate s, at
875  /// time level t (t=0: present; t>0: history values)
876  double get_field(const unsigned &t,
877  const unsigned &fld,
878  const Vector<double>& s)
879  {
880 
881 #ifdef PARANOID
882  if (fld > 3)
883  {
884  std::stringstream error_stream;
885  error_stream
886  << "Foeppl von Karman elements only store four fields so fld must be"
887  << "0 to 3 rather than " << fld << std::endl;
888  throw OomphLibError(
889  error_stream.str(),
890  OOMPH_CURRENT_FUNCTION,
891  OOMPH_EXCEPTION_LOCATION);
892  }
893 #endif
894  //Find the index at which the variable is stored
895  unsigned w_nodal_index = this->nodal_index_fvk(fld);
896 
897  //Local shape function
898  unsigned n_node=this->nnode();
899  Shape psi(n_node);
900 
901  //Find values of shape function
902  this->shape(s,psi);
903 
904  //Initialise value of u
905  double interpolated_w = 0.0;
906 
907  //Sum over the local nodes
908  for(unsigned l=0;l<n_node;l++)
909  {
910  interpolated_w += this->nodal_value(t,l,w_nodal_index)*psi[l];
911  }
912  return interpolated_w;
913  }
914 
915 
916 
917 
918  ///Return number of values in field fld: One per node
919  unsigned nvalue_of_field(const unsigned &fld)
920  {
921 #ifdef PARANOID
922  if (fld > 3)
923  {
924  std::stringstream error_stream;
925  error_stream
926  << "Foeppl von Karman elements only store four fields so fld must be"
927  << "0 to 3 rather than " << fld << std::endl;
928  throw OomphLibError(
929  error_stream.str(),
930  OOMPH_CURRENT_FUNCTION,
931  OOMPH_EXCEPTION_LOCATION);
932  }
933 #endif
934  return this->nnode();
935  }
936 
937 
938  ///Return local equation number of field fld of node j.
939  int local_equation(const unsigned &fld,
940  const unsigned &j)
941  {
942 #ifdef PARANOID
943  if (fld > 3)
944  {
945  std::stringstream error_stream;
946  error_stream
947  << "Foeppl von Karman elements only store four fields so fld must be"
948  << "0 to 3 rather than " << fld << std::endl;
949  throw OomphLibError(
950  error_stream.str(),
951  OOMPH_CURRENT_FUNCTION,
952  OOMPH_EXCEPTION_LOCATION);
953  }
954 #endif
955  const unsigned w_nodal_index = this->nodal_index_fvk(fld);
956  return this->nodal_local_eqn(j,w_nodal_index);
957  }
958 
959  };
960 
961 //=======================================================================
962 /// Face geometry for element is the same as that for the underlying
963 /// wrapped element
964 //=======================================================================
965  template<class ELEMENT>
967  : public virtual FaceGeometry<ELEMENT>
968  {
969  public:
970  FaceGeometry() : FaceGeometry<ELEMENT>() {}
971  };
972 
973 
974 //=======================================================================
975 /// Face geometry of the Face Geometry for element is the same as
976 /// that for the underlying wrapped element
977 //=======================================================================
978  template<class ELEMENT>
980  : public virtual FaceGeometry<FaceGeometry<ELEMENT> >
981  {
982  public:
984  };
985 
986 }
987 
988 #endif
unsigned nvalue_of_field(const unsigned &fld)
Return number of values in field fld: One per node.
unsigned nhistory_values_for_projection(const unsigned &fld)
Number of history values to be stored for fld-th field. (Note: count includes current value!) ...
void(* FoepplvonKarmanPressureFctPt)(const Vector< double > &x, double &f)
Function pointer to pressure function fct(x,f(x)) – x is a Vector!
void broken_copy(const std::string &class_name)
Issue error message and terminate execution.
FoepplvonKarmanTractionFctPt & traction_fct_pt()
Access function: Pointer to in-plane traction function.
void output(std::ostream &outfile)
Output with default number of plot points.
unsigned long nrow() const
Return the number of rows of the matrix.
Definition: matrices.h:504
static double Default_Nu_Value
Default value for Poisson&#39;s ratio.
double get_field(const unsigned &t, const unsigned &fld, const Vector< double > &s)
Return interpolated field fld at local coordinate s, at time level t (t=0: present; t>0: history valu...
virtual void get_traction_fvk(Vector< double > &x, Vector< double > &traction) const
Get in-plane traction term at (Eulerian) position x.
DisplacementBasedFoepplvonKarmanEquations()
Constructor (must initialise the Pressure_fct_pt and the Traction_fct_pt. Also set physical parameter...
double nodal_position(const unsigned &n, const unsigned &i) const
Return the i-th coordinate at local node n. If the node is hanging, the appropriate interpolation is ...
Definition: elements.h:2227
virtual double dshape_and_dtest_eulerian_at_knot_fvk(const unsigned &ipt, Shape &psi, DShape &dpsidx, Shape &test, DShape &dtestdx) const =0
Shape/test functions and derivs w.r.t. to global coords at integration point ipt; return Jacobian of ...
cstr elem_len * i
Definition: cfortran.h:607
void get_gradient_of_deflection(const Vector< double > &s, Vector< double > &gradient) const
Get gradient of deflection: gradient[i] = dw/dx_i.
unsigned nfields_for_projection()
Number of fields to be projected: Just two.
void output(FILE *file_pt)
C_style output with default number of plot points.
A general Finite Element class.
Definition: elements.h:1274
void(* UnsteadyExactSolutionFctPt)(const double &, const Vector< double > &, Vector< double > &)
Function pointer for function that computes Vector-valued time-dependent function as ...
Definition: elements.h:1729
char t
Definition: cfortran.h:572
TimeStepper *& position_time_stepper_pt()
Return a pointer to the position timestepper.
Definition: nodes.h:969
virtual void output_fct(std::ostream &outfile, const unsigned &n_plot, const double &time, FiniteElement::UnsteadyExactSolutionFctPt exact_soln_pt)
Output exact soln: x,y,w_exact at n_plot^DIM plot points (dummy time-dependent version to keep intel ...
FoepplvonKarmanTractionFctPt Traction_fct_pt
Pointer to traction function:
virtual double weight(const unsigned &i) const =0
Return weight of i-th integration point.
void pin(const unsigned &i)
Pin the i-th stored variable.
Definition: nodes.h:383
void(* FoepplvonKarmanTractionFctPt)(const Vector< double > &x, Vector< double > &f)
Function pointer to traction function fct(x,f(x)) – x is a Vector!
unsigned nhistory_values_for_coordinate_projection()
Number of positional history values (Note: count includes current value!)
unsigned ndof() const
Return the number of equations/dofs in the element.
Definition: elements.h:834
void use_linear_bending_model()
Sets a flag to signify that we are solving the linear, pure bending equations, and pin all the nodal ...
void(* SteadyExactSolutionFctPt)(const Vector< double > &, Vector< double > &)
Function pointer for function that computes vector-valued steady "exact solution" as ...
Definition: elements.h:1723
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:3881
static double Default_Physical_Constant_Value
Default value for physical constants.
double dshape_eulerian(const Vector< double > &s, Shape &psi, DShape &dpsidx) const
Compute the geometric shape functions and also first derivatives w.r.t. global coordinates at local c...
Definition: elements.cc:3227
Integral *const & integral_pt() const
Return the pointer to the integration scheme (const version)
Definition: elements.h:1908
static char t char * s
Definition: cfortran.h:572
void get_sigma(DenseMatrix< double > &sigma, const Vector< double > &interpolated_dwdx, const Vector< double > &interpolated_duxdx, const Vector< double > &interpolated_duydx)
FoepplvonKarmanTractionFctPt traction_fct_pt() const
Access function: Pointer to in-plane traction function. Const version.
Node *& node_pt(const unsigned &n)
Return a pointer to the local node n.
Definition: elements.h:2109
double interpolated_w_fvk(const Vector< double > &s, unsigned index=0) const
Return FE representation of function value w_fvk(s) at local coordinate s (by default - if index > 0...
Vector< std::pair< Data *, unsigned > > data_values_of_field(const unsigned &fld)
Specify the values associated with field fld. The information is returned in a vector of pairs which ...
void output_fct(std::ostream &outfile, const unsigned &n_plot, FiniteElement::SteadyExactSolutionFctPt exact_soln_pt)
Output exact soln: x,y,w_exact at n_plot^DIM plot points.
FoepplvonKarmanPressureFctPt & pressure_fct_pt()
Access function: Pointer to pressure function.
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:2470
unsigned ntstorage() const
Return the number of doubles required to represent history (one for steady)
Definition: timesteppers.h:562
void fill_in_contribution_to_jacobian_and_mass_matrix(Vector< double > &residuals, DenseMatrix< double > &jacobian, DenseMatrix< double > &mass_matrix)
hierher dummy
unsigned ntstorage() const
Return total number of doubles stored per value to record time history of each value (one for steady ...
Definition: nodes.cc:847
int local_equation(const unsigned &fld, const unsigned &j)
Return local equation number of field fld of node j.
FoepplvonKarmanPressureFctPt pressure_fct_pt() const
Access function: Pointer to pressure function. Const version.
unsigned dim() const
Return the spatial dimension of the element, i.e. the number of local coordinates required to paramet...
Definition: elements.h:2482
DisplacementBasedFoepplvonKarmanEquations(const DisplacementBasedFoepplvonKarmanEquations &dummy)
Broken copy constructor.
bool Linear_bending_model
Flag which stores whether we are using a linear, pure bending model instead of the full non-linear Fo...
void broken_assign(const std::string &class_name)
Issue error message and terminate execution.
FoepplvonKarmanPressureFctPt Pressure_fct_pt
Pointer to pressure function:
virtual unsigned nweight() const =0
Return the number of integration points of the scheme.
virtual void get_pressure_fvk(const unsigned &ipt, const Vector< double > &x, double &pressure) const
Get pressure term at (Eulerian) position x. This function is virtual to allow overloading in multi-ph...
void get_gradient_of_field(const Vector< double > &s, Vector< double > &gradient, const unsigned &index) const
Get gradient of field: gradient[i] = d[.]/dx_i,.
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 jacobian_and_shape_of_field(const unsigned &fld, const Vector< double > &s, Shape &psi)
Return Jacobian of mapping and shape functions of field fld at local coordinate s.
unsigned nnode() const
Return the number of nodes.
Definition: elements.h:2146
void get_stress_and_strain_for_output(const Vector< double > &s, DenseMatrix< double > &sigma, DenseMatrix< double > &strain)
virtual double dshape_and_dtest_eulerian_fvk(const Vector< double > &s, Shape &psi, DShape &dpsidx, Shape &test, DShape &dtestdx) const =0
Shape/test functions and derivs w.r.t. to global coords at local coord. s; return Jacobian of mapping...
void fill_in_contribution_to_jacobian(Vector< double > &residuals, DenseMatrix< double > &jacobian)
Add the elemental contribution to the jacobian matrix. and the residuals vector. Note that this funct...
Definition: elements.h:1697
virtual void shape(const Vector< double > &s, Shape &psi) const =0
Calculate the geometric shape functions at local coordinate s. This function must be overloaded for e...
void operator=(const DisplacementBasedFoepplvonKarmanEquations &)
Broken assignment operator.
void compute_error(std::ostream &outfile, FiniteElement::UnsteadyExactSolutionFctPt exact_soln_pt, const double &time, double &error, double &norm)
Dummy, time dependent error checker.
void compute_error(std::ostream &outfile, FiniteElement::SteadyExactSolutionFctPt exact_soln_pt, double &error, double &norm)
Get error against and norm of exact solution.
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:1386
void fill_in_contribution_to_residuals(Vector< double > &residuals)
Fill in the residuals with this element&#39;s contribution.