poisson_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 Poisson elements
31 #ifndef OOMPH_POISSON_ELEMENTS_HEADER
32 #define OOMPH_POISSON_ELEMENTS_HEADER
33 
34 
35 // Config header generated by autoconfig
36 #ifdef HAVE_CONFIG_H
37  #include <oomph-lib-config.h>
38 #endif
39 
40 #include<sstream>
41 
42 //OOMPH-LIB headers
43 #include "../generic/projection.h"
44 #include "../generic/nodes.h"
45 #include "../generic/Qelements.h"
46 #include "../generic/oomph_utilities.h"
47 
48 
49 
50 namespace oomph
51 {
52 
53 //=============================================================
54 /// A class for all isoparametric elements that solve the
55 /// Poisson equations.
56 /// \f[
57 /// \frac{\partial^2 u}{\partial x_i^2} = f(x_j)
58 /// \f]
59 /// This contains the generic maths. Shape functions, geometric
60 /// mapping etc. must get implemented in derived class.
61 //=============================================================
62 template <unsigned DIM>
63 class PoissonEquations : public virtual FiniteElement
64 {
65 
66 public:
67 
68  /// \short Function pointer to source function fct(x,f(x)) --
69  /// x is a Vector!
70  typedef void (*PoissonSourceFctPt)(const Vector<double>& x, double& f);
71 
72 
73  /// \short Function pointer to gradient of source function fct(x,g(x)) --
74  /// x is a Vector!
75  typedef void (*PoissonSourceFctGradientPt)(const Vector<double>& x,
76  Vector<double>& gradient);
77 
78 
79  /// Constructor (must initialise the Source_fct_pt to null)
81  {}
82 
83  /// Broken copy constructor
85  {
86  BrokenCopy::broken_copy("PoissonEquations");
87  }
88 
89  /// Broken assignment operator
91  {
92  BrokenCopy::broken_assign("PoissonEquations");
93  }
94 
95  /// \short Return the index at which the unknown value
96  /// is stored. The default value, 0, is appropriate for single-physics
97  /// problems, when there is only one variable, the value that satisfies
98  /// the poisson equation.
99  /// In derived multi-physics elements, this function should be overloaded
100  /// to reflect the chosen storage scheme. Note that these equations require
101  /// that the unknown is always stored at the same index at each node.
102  virtual inline unsigned u_index_poisson() const {return 0;}
103 
104 
105  /// \short Output solution in data vector at local cordinates s:
106  /// x,y [,z], u
108  {
109  // Dimension
110  unsigned dim=s.size();
111 
112  // Resize data for values
113  data.resize(dim+1);
114 
115  // Write values in the vector
116  for (unsigned i=0; i<dim; i++)
117  {
118  data[i]=interpolated_x(s,i);
119  }
120  data[dim]=this->interpolated_u_poisson(s);
121  }
122 
123 
124  /// \short Number of scalars/fields output by this element. Reimplements
125  /// broken virtual function in base class.
126  unsigned nscalar_paraview() const
127  {
128  return 1;
129  }
130 
131  /// \short Write values of the i-th scalar field at the plot points. Needs
132  /// to be implemented for each new specific element type.
133  void scalar_value_paraview(std::ofstream& file_out,
134  const unsigned& i,
135  const unsigned& nplot) const
136  {
137 #ifdef PARANOID
138  if (i!=0)
139  {
140  std::stringstream error_stream;
141  error_stream
142  << "Poisson elements only store a single field so i must be 0 rather"
143  << " than " << i << std::endl;
144  throw OomphLibError(
145  error_stream.str(),
146  OOMPH_CURRENT_FUNCTION,
147  OOMPH_EXCEPTION_LOCATION);
148  }
149 #endif
150 
151  unsigned local_loop=this->nplot_points_paraview(nplot);
152  for(unsigned j=0;j<local_loop;j++)
153  {
154  // Get the local coordinate of the required plot point
155  Vector<double> s(DIM);
156  this->get_s_plot(j,nplot,s);
157 
158  file_out << this->interpolated_u_poisson(s)
159  << std::endl;
160  }
161  }
162 
163  /// \short Name of the i-th scalar field. Default implementation
164  /// returns V1 for the first one, V2 for the second etc. Can (should!) be
165  /// overloaded with more meaningful names in specific elements.
166  std::string scalar_name_paraview(const unsigned& i) const
167  {
168 
169 #ifdef PARANOID
170  if (i!=0)
171  {
172  std::stringstream error_stream;
173  error_stream
174  << "Poisson elements only store a single field so i must be 0 rather"
175  << " than " << i << std::endl;
176  throw OomphLibError(
177  error_stream.str(),
178  OOMPH_CURRENT_FUNCTION,
179  OOMPH_EXCEPTION_LOCATION);
180  }
181 #endif
182 
183  return "Poisson solution";
184  }
185 
186 
187  /// \short Write values of the i-th scalar field at the plot points. Needs
188  /// to be implemented for each new specific element type.
189  void scalar_value_fct_paraview(std::ofstream& file_out,
190  const unsigned& i,
191  const unsigned& nplot,
193  exact_soln_pt) const
194  {
195 
196 #ifdef PARANOID
197  if (i!=0)
198  {
199  std::stringstream error_stream;
200  error_stream
201  << "Poisson equation has only one field. Can't call "
202  << "this function for value " << i << std::endl;
203  throw OomphLibError(
204  error_stream.str(),
205  OOMPH_CURRENT_FUNCTION,
206  OOMPH_EXCEPTION_LOCATION);
207  }
208 #endif
209 
210  //Vector of local coordinates
211  Vector<double> s(DIM);
212 
213  // Vector for coordinates
214  Vector<double> x(DIM);
215 
216  // Exact solution Vector
217  Vector<double> exact_soln(1);
218 
219  // Loop over plot points
220  unsigned num_plot_points=nplot_points_paraview(nplot);
221  for (unsigned iplot=0;iplot<num_plot_points;iplot++)
222  {
223  // Get local coordinates of plot point
224  get_s_plot(iplot,nplot,s);
225 
226  // Get x position as Vector
227  interpolated_x(s,x);
228 
229  // Get exact solution at this point
230  (*exact_soln_pt)(x,exact_soln);
231 
232  // Write it
233  file_out << exact_soln[0] << std::endl;
234 
235  }
236  }
237 
238  /// Output with default number of plot points
239  void output(std::ostream &outfile)
240  {
241  const unsigned n_plot=5;
242  output(outfile,n_plot);
243  }
244 
245  /// \short Output FE representation of soln: x,y,u or x,y,z,u at
246  /// n_plot^DIM plot points
247  void output(std::ostream &outfile, const unsigned &n_plot);
248 
249  /// C_style output with default number of plot points
250  void output(FILE* file_pt)
251  {
252  const unsigned n_plot=5;
253  output(file_pt,n_plot);
254  }
255 
256  /// \short C-style output FE representation of soln: x,y,u or x,y,z,u at
257  /// n_plot^DIM plot points
258  void output(FILE* file_pt, const unsigned &n_plot);
259 
260  /// Output exact soln: x,y,u_exact or x,y,z,u_exact at n_plot^DIM plot points
261  void output_fct(std::ostream &outfile, const unsigned &n_plot,
263 
264  /// \short Output exact soln: x,y,u_exact or x,y,z,u_exact at
265  /// n_plot^DIM plot points (dummy time-dependent version to
266  /// keep intel compiler happy)
267  virtual void output_fct(std::ostream &outfile, const unsigned &n_plot,
268  const double& time,
270  exact_soln_pt)
271  {
272  throw OomphLibError(
273  "There is no time-dependent output_fct() for Poisson elements ",
274  OOMPH_CURRENT_FUNCTION,
275  OOMPH_EXCEPTION_LOCATION);
276  }
277 
278 
279  /// \short Compute norm of solution: square of the L2 norm
280  void compute_norm(double& norm);
281 
282  /// Get error against and norm of exact solution
283  void compute_error(std::ostream &outfile,
285  double& error, double& norm);
286 
287 
288  /// Dummy, time dependent error checker
289  void compute_error(std::ostream &outfile,
291  const double& time, double& error, double& norm)
292  {
293  throw OomphLibError(
294  "There is no time-dependent compute_error() for Poisson elements",
295  OOMPH_CURRENT_FUNCTION,
296  OOMPH_EXCEPTION_LOCATION);
297  }
298 
299  /// Access function: Pointer to source function
301 
302  /// Access function: Pointer to source function. Const version
304 
305  /// Access function: Pointer to gradient of source function
307  {return Source_fct_gradient_pt;}
308 
309  /// Access function: Pointer to gradient source function. Const version
311  {return Source_fct_gradient_pt;}
312 
313 
314  /// Get source term at (Eulerian) position x. This function is
315  /// virtual to allow overloading in multi-physics problems where
316  /// the strength of the source function might be determined by
317  /// another system of equations.
318  inline virtual void get_source_poisson(const unsigned& ipt,
319  const Vector<double>& x,
320  double& source) const
321  {
322  //If no source function has been set, return zero
323  if(Source_fct_pt==0) {source = 0.0;}
324  else
325  {
326  // Get source strength
327  (*Source_fct_pt)(x,source);
328  }
329  }
330 
331 
332  /// Get gradient of source term at (Eulerian) position x. This function is
333  /// virtual to allow overloading in multi-physics problems where
334  /// the strength of the source function might be determined by
335  /// another system of equations. Computed via function pointer
336  /// (if set) or by finite differencing (default)
337  inline virtual void get_source_gradient_poisson(
338  const unsigned& ipt,
339  const Vector<double>& x,
340  Vector<double>& gradient) const
341  {
342  //If no gradient function has been set, FD it
344  {
345  // Reference value
346  double source=0.0;
347  get_source_poisson(ipt,x,source);
348 
349  // FD it
351  double source_pls=0.0;
352  Vector<double> x_pls(x);
353  for (unsigned i=0;i<DIM;i++)
354  {
355  x_pls[i]+=eps_fd;
356  get_source_poisson(ipt,x_pls,source_pls);
357  gradient[i]=(source_pls-source)/eps_fd;
358  x_pls[i]=x[i];
359  }
360  }
361  else
362  {
363  // Get gradient
364  (*Source_fct_gradient_pt)(x,gradient);
365  }
366  }
367 
368 
369 
370 
371  /// Get flux: flux[i] = du/dx_i
372  void get_flux(const Vector<double>& s, Vector<double>& flux) const
373  {
374  //Find out how many nodes there are in the element
375  const unsigned n_node = nnode();
376 
377  //Get the index at which the unknown is stored
378  const unsigned u_nodal_index = u_index_poisson();
379 
380  //Set up memory for the shape and test functions
381  Shape psi(n_node);
382  DShape dpsidx(n_node,DIM);
383 
384  //Call the derivatives of the shape and test functions
385  dshape_eulerian(s,psi,dpsidx);
386 
387  //Initialise to zero
388  for(unsigned j=0;j<DIM;j++)
389  {
390  flux[j] = 0.0;
391  }
392 
393  // Loop over nodes
394  for(unsigned l=0;l<n_node;l++)
395  {
396  //Loop over derivative directions
397  for(unsigned j=0;j<DIM;j++)
398  {
399  flux[j] += this->nodal_value(l,u_nodal_index)*dpsidx(l,j);
400  }
401  }
402  }
403 
404 
405  /// Get derivative of flux w.r.t. to nodal values:
406  /// dflux_dnodal_u[i][j] = d ( du/dx_i ) / dU_j
408  Vector<Vector<double> >& dflux_dnodal_u) const
409  {
410  //Find out how many nodes there are in the element
411  const unsigned n_node = nnode();
412 
413  //Set up memory for the shape and test functions
414  Shape psi(n_node);
415  DShape dpsidx(n_node,DIM);
416 
417  //Call the derivatives of the shape and test functions
418  dshape_eulerian(s,psi,dpsidx);
419 
420  // And here it is...
421  for(unsigned i=0;i<DIM;i++)
422  {
423  for(unsigned j=0;j<n_node;j++)
424  {
425  dflux_dnodal_u[i][j] = dpsidx(j,i);
426  }
427  }
428  }
429 
430 
431  /// Add the element's contribution to its residual vector (wrapper)
433  {
434  //Call the generic residuals function with flag set to 0
435  //using a dummy matrix argument
438  }
439 
440 
441  /// Add the element's contribution to its residual vector and
442  /// element Jacobian matrix (wrapper)
444  DenseMatrix<double> &jacobian)
445  {
446  //Call the generic routine with the flag set to 1
447  fill_in_generic_residual_contribution_poisson(residuals,jacobian,1);
448  }
449 
450 
451 
452  /// \short Return FE representation of function value u_poisson(s)
453  /// at local coordinate s
454  virtual inline double interpolated_u_poisson(const Vector<double> &s) const
455  {
456  //Find number of nodes
457  const unsigned n_node = nnode();
458 
459  //Get the index at which the poisson unknown is stored
460  const unsigned u_nodal_index = u_index_poisson();
461 
462  //Local shape function
463  Shape psi(n_node);
464 
465  //Find values of shape function
466  shape(s,psi);
467 
468  //Initialise value of u
469  double interpolated_u = 0.0;
470 
471  //Loop over the local nodes and sum
472  for(unsigned l=0;l<n_node;l++)
473  {
474  interpolated_u += this->nodal_value(l,u_nodal_index)*psi[l];
475  }
476 
477  return(interpolated_u);
478  }
479 
480 
481  /// \short Compute derivatives of elemental residual vector with respect
482  /// to nodal coordinates. Overwrites default implementation in
483  /// FiniteElement base class.
484  /// dresidual_dnodal_coordinates(l,i,j) = d res(l) / dX_{ij}
486  dresidual_dnodal_coordinates);
487 
488  /// \short Self-test: Return 0 for OK
489  unsigned self_test();
490 
491 
492 protected:
493 
494  /// \short Shape/test functions and derivs w.r.t. to global coords at
495  /// local coord. s; return Jacobian of mapping
496  virtual double dshape_and_dtest_eulerian_poisson(const Vector<double> &s,
497  Shape &psi,
498  DShape &dpsidx, Shape &test,
499  DShape &dtestdx) const=0;
500 
501 
502  /// \short Shape/test functions and derivs w.r.t. to global coords at
503  /// integration point ipt; return Jacobian of mapping
504  virtual double dshape_and_dtest_eulerian_at_knot_poisson(const unsigned &ipt,
505  Shape &psi,
506  DShape &dpsidx,
507  Shape &test,
508  DShape &dtestdx)
509  const=0;
510 
511  /// \short Shape/test functions and derivs w.r.t. to global coords at
512  /// integration point ipt; return Jacobian of mapping (J). Also compute
513  /// derivatives of dpsidx, dtestdx and J w.r.t. nodal coordinates.
515  const unsigned &ipt,
516  Shape &psi,
517  DShape &dpsidx,
518  RankFourTensor<double> &d_dpsidx_dX,
519  Shape &test,
520  DShape &dtestdx,
521  RankFourTensor<double> &d_dtestdx_dX,
522  DenseMatrix<double> &djacobian_dX) const=0;
523 
524  /// \short Compute element residual Vector only (if flag=and/or element
525  /// Jacobian matrix
527  Vector<double> &residuals, DenseMatrix<double> &jacobian,
528  const unsigned& flag);
529 
530  /// Pointer to source function:
532 
533  /// Pointer to gradient of source function
535 
536 };
537 
538 
539 
540 
541 
542 
543 ///////////////////////////////////////////////////////////////////////////
544 ///////////////////////////////////////////////////////////////////////////
545 ///////////////////////////////////////////////////////////////////////////
546 
547 
548 
549 //======================================================================
550 /// QPoissonElement elements are linear/quadrilateral/brick-shaped
551 /// Poisson elements with isoparametric interpolation for the function.
552 //======================================================================
553 template <unsigned DIM, unsigned NNODE_1D>
554  class QPoissonElement : public virtual QElement<DIM,NNODE_1D>,
555  public virtual PoissonEquations<DIM>
556 {
557 
558 private:
559 
560  /// \short Static int that holds the number of variables at
561  /// nodes: always the same
562  static const unsigned Initial_Nvalue;
563 
564  public:
565 
566 
567  ///\short Constructor: Call constructors for QElement and
568  /// Poisson equations
569  QPoissonElement() : QElement<DIM,NNODE_1D>(), PoissonEquations<DIM>()
570  {}
571 
572  /// Broken copy constructor
574  {
575  BrokenCopy::broken_copy("QPoissonElement");
576  }
577 
578  /// Broken assignment operator
580  {
581  BrokenCopy::broken_assign("QPoissonElement");
582  }
583 
584  /// \short Required # of `values' (pinned or dofs)
585  /// at node n
586  inline unsigned required_nvalue(const unsigned &n) const
587  {return Initial_Nvalue;}
588 
589  /// \short Output function:
590  /// x,y,u or x,y,z,u
591  void output(std::ostream &outfile)
593 
594 
595  /// \short Output function:
596  /// x,y,u or x,y,z,u at n_plot^DIM plot points
597  void output(std::ostream &outfile, const unsigned &n_plot)
598  {PoissonEquations<DIM>::output(outfile,n_plot);}
599 
600 
601  /// \short C-style output function:
602  /// x,y,u or x,y,z,u
603  void output(FILE* file_pt)
605 
606 
607  /// \short C-style output function:
608  /// x,y,u or x,y,z,u at n_plot^DIM plot points
609  void output(FILE* file_pt, const unsigned &n_plot)
610  {PoissonEquations<DIM>::output(file_pt,n_plot);}
611 
612 
613  /// \short Output function for an exact solution:
614  /// x,y,u_exact or x,y,z,u_exact at n_plot^DIM plot points
615  void output_fct(std::ostream &outfile, const unsigned &n_plot,
617  {PoissonEquations<DIM>::output_fct(outfile,n_plot,exact_soln_pt);}
618 
619 
620 
621  /// \short Output function for a time-dependent exact solution.
622  /// x,y,u_exact or x,y,z,u_exact at n_plot^DIM plot points
623  /// (Calls the steady version)
624  void output_fct(std::ostream &outfile, const unsigned &n_plot,
625  const double& time,
627  {PoissonEquations<DIM>::output_fct(outfile,n_plot,time,exact_soln_pt);}
628 
629 
630 protected:
631 
632 /// Shape, test functions & derivs. w.r.t. to global coords. Return Jacobian.
633  inline double dshape_and_dtest_eulerian_poisson(
634  const Vector<double> &s, Shape &psi, DShape &dpsidx,
635  Shape &test, DShape &dtestdx) const;
636 
637 
638  /// \short Shape, test functions & derivs. w.r.t. to global coords. at
639  /// integration point ipt. Return Jacobian.
640  inline double dshape_and_dtest_eulerian_at_knot_poisson(const unsigned& ipt,
641  Shape &psi,
642  DShape &dpsidx,
643  Shape &test,
644  DShape &dtestdx)
645  const;
646 
647  /// \short Shape/test functions and derivs w.r.t. to global coords at
648  /// integration point ipt; return Jacobian of mapping (J). Also compute
649  /// derivatives of dpsidx, dtestdx and J w.r.t. nodal coordinates.
651  const unsigned &ipt,
652  Shape &psi,
653  DShape &dpsidx,
654  RankFourTensor<double> &d_dpsidx_dX,
655  Shape &test,
656  DShape &dtestdx,
657  RankFourTensor<double> &d_dtestdx_dX,
658  DenseMatrix<double> &djacobian_dX) const;
659 
660 };
661 
662 
663 
664 
665 //Inline functions:
666 
667 
668 //======================================================================
669 /// Define the shape functions and test functions and derivatives
670 /// w.r.t. global coordinates and return Jacobian of mapping.
671 ///
672 /// Galerkin: Test functions = shape functions
673 //======================================================================
674 template<unsigned DIM, unsigned NNODE_1D>
676  const Vector<double> &s,
677  Shape &psi,
678  DShape &dpsidx,
679  Shape &test,
680  DShape &dtestdx) const
681 {
682  //Call the geometrical shape functions and derivatives
683  const double J = this->dshape_eulerian(s,psi,dpsidx);
684 
685  //Set the test functions equal to the shape functions
686  test = psi;
687  dtestdx= dpsidx;
688 
689  //Return the jacobian
690  return J;
691 }
692 
693 
694 
695 
696 //======================================================================
697 /// Define the shape functions and test functions and derivatives
698 /// w.r.t. global coordinates and return Jacobian of mapping.
699 ///
700 /// Galerkin: Test functions = shape functions
701 //======================================================================
702 template<unsigned DIM, unsigned NNODE_1D>
705  const unsigned &ipt,
706  Shape &psi,
707  DShape &dpsidx,
708  Shape &test,
709  DShape &dtestdx) const
710 {
711  //Call the geometrical shape functions and derivatives
712  const double J = this->dshape_eulerian_at_knot(ipt,psi,dpsidx);
713 
714  //Set the pointers of the test functions
715  test = psi;
716  dtestdx = dpsidx;
717 
718  //Return the jacobian
719  return J;
720 }
721 
722 
723 
724 //======================================================================
725 /// Define the shape functions (psi) and test functions (test) and
726 /// their derivatives w.r.t. global coordinates (dpsidx and dtestdx)
727 /// and return Jacobian of mapping (J). Additionally compute the
728 /// derivatives of dpsidx, dtestdx and J w.r.t. nodal coordinates.
729 ///
730 /// Galerkin: Test functions = shape functions
731 //======================================================================
732 template<unsigned DIM, unsigned NNODE_1D>
735  const unsigned &ipt,
736  Shape &psi,
737  DShape &dpsidx,
738  RankFourTensor<double> &d_dpsidx_dX,
739  Shape &test,
740  DShape &dtestdx,
741  RankFourTensor<double> &d_dtestdx_dX,
742  DenseMatrix<double> &djacobian_dX) const
743  {
744  // Call the geometrical shape functions and derivatives
745  const double J = this->dshape_eulerian_at_knot(ipt,psi,dpsidx,
746  djacobian_dX,d_dpsidx_dX);
747 
748  // Set the pointers of the test functions
749  test = psi;
750  dtestdx = dpsidx;
751  d_dtestdx_dX = d_dpsidx_dX;
752 
753  //Return the jacobian
754  return J;
755 }
756 
757 
758 
759 ////////////////////////////////////////////////////////////////////////
760 ////////////////////////////////////////////////////////////////////////
761 ////////////////////////////////////////////////////////////////////////
762 
763 
764 
765 //=======================================================================
766 /// Face geometry for the QPoissonElement elements: The spatial
767 /// dimension of the face elements is one lower than that of the
768 /// bulk element but they have the same number of points
769 /// along their 1D edges.
770 //=======================================================================
771 template<unsigned DIM, unsigned NNODE_1D>
772 class FaceGeometry<QPoissonElement<DIM,NNODE_1D> >:
773  public virtual QElement<DIM-1,NNODE_1D>
774 {
775 
776  public:
777 
778  /// \short Constructor: Call the constructor for the
779  /// appropriate lower-dimensional QElement
780  FaceGeometry() : QElement<DIM-1,NNODE_1D>() {}
781 
782 };
783 
784 ////////////////////////////////////////////////////////////////////////
785 ////////////////////////////////////////////////////////////////////////
786 ////////////////////////////////////////////////////////////////////////
787 
788 
789 //=======================================================================
790 /// Face geometry for the 1D QPoissonElement elements: Point elements
791 //=======================================================================
792 template<unsigned NNODE_1D>
793 class FaceGeometry<QPoissonElement<1,NNODE_1D> >:
794  public virtual PointElement
795 {
796 
797  public:
798 
799  /// \short Constructor: Call the constructor for the
800  /// appropriate lower-dimensional QElement
802 
803 };
804 
805 
806 
807 ////////////////////////////////////////////////////////////////////////
808 ////////////////////////////////////////////////////////////////////////
809 ////////////////////////////////////////////////////////////////////////
810 
811 
812 //==========================================================
813 /// Poisson upgraded to become projectable
814 //==========================================================
815  template<class POISSON_ELEMENT>
817  public virtual ProjectableElement<POISSON_ELEMENT>
818  {
819 
820  public:
821 
822  /// \short Specify the values associated with field fld.
823  /// The information is returned in a vector of pairs which comprise
824  /// the Data object and the value within it, that correspond to field fld.
826  {
827 
828 #ifdef PARANOID
829  if (fld!=0)
830  {
831  std::stringstream error_stream;
832  error_stream
833  << "Poisson elements only store a single field so fld must be 0 rather"
834  << " than " << fld << std::endl;
835  throw OomphLibError(
836  error_stream.str(),
837  OOMPH_CURRENT_FUNCTION,
838  OOMPH_EXCEPTION_LOCATION);
839  }
840 #endif
841 
842  // Create the vector
843  unsigned nnod=this->nnode();
844  Vector<std::pair<Data*,unsigned> > data_values(nnod);
845 
846  // Loop over all nodes
847  for (unsigned j=0;j<nnod;j++)
848  {
849  // Add the data value associated field: The node itself
850  data_values[j]=std::make_pair(this->node_pt(j),fld);
851  }
852 
853  // Return the vector
854  return data_values;
855  }
856 
857  /// \short Number of fields to be projected: Just one
859  {
860  return 1;
861  }
862 
863  /// \short Number of history values to be stored for fld-th field
864  /// (includes current value!)
865  unsigned nhistory_values_for_projection(const unsigned &fld)
866  {
867 #ifdef PARANOID
868  if (fld!=0)
869  {
870  std::stringstream error_stream;
871  error_stream
872  << "Poisson elements only store a single field so fld must be 0 rather"
873  << " than " << fld << std::endl;
874  throw OomphLibError(
875  error_stream.str(),
876  OOMPH_CURRENT_FUNCTION,
877  OOMPH_EXCEPTION_LOCATION);
878  }
879 #endif
880  return this->node_pt(0)->ntstorage();
881  }
882 
883  ///\short Number of positional history values
884  /// (Note: count includes current value!)
886  {
887  return this->node_pt(0)->position_time_stepper_pt()->ntstorage();
888  }
889 
890  /// \short Return Jacobian of mapping and shape functions of field fld
891  /// at local coordinate s
892  double jacobian_and_shape_of_field(const unsigned &fld,
893  const Vector<double> &s,
894  Shape &psi)
895  {
896 #ifdef PARANOID
897  if (fld!=0)
898  {
899  std::stringstream error_stream;
900  error_stream
901  << "Poisson elements only store a single field so fld must be 0 rather"
902  << " than " << fld << std::endl;
903  throw OomphLibError(
904  error_stream.str(),
905  OOMPH_CURRENT_FUNCTION,
906  OOMPH_EXCEPTION_LOCATION);
907  }
908 #endif
909  unsigned n_dim=this->dim();
910  unsigned n_node=this->nnode();
911  Shape test(n_node);
912  DShape dpsidx(n_node,n_dim), dtestdx(n_node,n_dim);
913  double J=this->dshape_and_dtest_eulerian_poisson(s,psi,dpsidx,
914  test,dtestdx);
915  return J;
916  }
917 
918 
919 
920  /// \short Return interpolated field fld at local coordinate s, at time level
921  /// t (t=0: present; t>0: history values)
922  double get_field(const unsigned &t,
923  const unsigned &fld,
924  const Vector<double>& s)
925  {
926 #ifdef PARANOID
927  if (fld!=0)
928  {
929  std::stringstream error_stream;
930  error_stream
931  << "Poisson elements only store a single field so fld must be 0 rather"
932  << " than " << fld << std::endl;
933  throw OomphLibError(
934  error_stream.str(),
935  OOMPH_CURRENT_FUNCTION,
936  OOMPH_EXCEPTION_LOCATION);
937  }
938 #endif
939  //Find the index at which the variable is stored
940  unsigned u_nodal_index = this->u_index_poisson();
941 
942  //Local shape function
943  unsigned n_node=this->nnode();
944  Shape psi(n_node);
945 
946  //Find values of shape function
947  this->shape(s,psi);
948 
949  //Initialise value of u
950  double interpolated_u = 0.0;
951 
952  //Sum over the local nodes
953  for(unsigned l=0;l<n_node;l++)
954  {
955  interpolated_u += this->nodal_value(l,u_nodal_index)*psi[l];
956  }
957  return interpolated_u;
958  }
959 
960 
961 
962 
963  ///Return number of values in field fld: One per node
964  unsigned nvalue_of_field(const unsigned &fld)
965  {
966 #ifdef PARANOID
967  if (fld!=0)
968  {
969  std::stringstream error_stream;
970  error_stream
971  << "Poisson elements only store a single field so fld must be 0 rather"
972  << " than " << fld << std::endl;
973  throw OomphLibError(
974  error_stream.str(),
975  OOMPH_CURRENT_FUNCTION,
976  OOMPH_EXCEPTION_LOCATION);
977  }
978 #endif
979  return this->nnode();
980  }
981 
982 
983  ///Return local equation number of value j in field fld.
984  int local_equation(const unsigned &fld,
985  const unsigned &j)
986  {
987 #ifdef PARANOID
988  if (fld!=0)
989  {
990  std::stringstream error_stream;
991  error_stream
992  << "Poisson elements only store a single field so fld must be 0 rather"
993  << " than " << fld << std::endl;
994  throw OomphLibError(
995  error_stream.str(),
996  OOMPH_CURRENT_FUNCTION,
997  OOMPH_EXCEPTION_LOCATION);
998  }
999 #endif
1000  const unsigned u_nodal_index = this->u_index_poisson();
1001  return this->nodal_local_eqn(j,u_nodal_index);
1002  }
1003 
1004  };
1005 
1006 
1007 //=======================================================================
1008 /// Face geometry for element is the same as that for the underlying
1009 /// wrapped element
1010 //=======================================================================
1011  template<class ELEMENT>
1013  : public virtual FaceGeometry<ELEMENT>
1014  {
1015  public:
1016  FaceGeometry() : FaceGeometry<ELEMENT>() {}
1017  };
1018 
1019 
1020 //=======================================================================
1021 /// Face geometry of the Face Geometry for element is the same as
1022 /// that for the underlying wrapped element
1023 //=======================================================================
1024  template<class ELEMENT>
1026  : public virtual FaceGeometry<FaceGeometry<ELEMENT> >
1027  {
1028  public:
1030  };
1031 
1032 
1033 
1034 
1035 }
1036 
1037 #endif
unsigned nvalue_of_field(const unsigned &fld)
Return number of values in field fld: One per node.
PoissonEquations()
Constructor (must initialise the Source_fct_pt to null)
void broken_copy(const std::string &class_name)
Issue error message and terminate execution.
void fill_in_contribution_to_residuals(Vector< double > &residuals)
Add the element&#39;s contribution to its residual vector (wrapper)
void fill_in_contribution_to_jacobian(Vector< double > &residuals, DenseMatrix< double > &jacobian)
virtual void get_s_plot(const unsigned &i, const unsigned &nplot, Vector< double > &s, const bool &shifted_to_interior=false) const
Get cector of local coordinates of plot point i (when plotting nplot points in each "coordinate direc...
Definition: elements.h:2978
virtual double dshape_eulerian_at_knot(const unsigned &ipt, Shape &psi, DShape &dpsidx) const
Return the geometric shape functions and also first derivatives w.r.t. global coordinates at the ipt-...
Definition: elements.cc:3254
static const unsigned Initial_Nvalue
Static int that holds the number of variables at nodes: always the same.
void scalar_value_paraview(std::ofstream &file_out, const unsigned &i, const unsigned &nplot) const
Write values of the i-th scalar field at the plot points. Needs to be implemented for each new specif...
void output_fct(std::ostream &outfile, const unsigned &n_plot, const double &time, FiniteElement::UnsteadyExactSolutionFctPt exact_soln_pt)
Output function for a time-dependent exact solution. x,y,u_exact or x,y,z,u_exact at n_plot^DIM plot ...
virtual void get_source_poisson(const unsigned &ipt, const Vector< double > &x, double &source) const
void output(std::ostream &outfile)
Output function: x,y,u or x,y,z,u.
virtual unsigned nplot_points_paraview(const unsigned &nplot) const
Return the number of actual plot points for paraview plot with parameter nplot. Broken virtual; can b...
Definition: elements.h:2712
void get_dflux_dnodal_u(const Vector< double > &s, Vector< Vector< double > > &dflux_dnodal_u) const
cstr elem_len * i
Definition: cfortran.h:607
unsigned required_nvalue(const unsigned &n) const
Required # of `values&#39; (pinned or dofs) at node n.
PoissonSourceFctGradientPt & source_fct_gradient_pt()
Access function: Pointer to gradient of source function.
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 fill_in_generic_residual_contribution_poisson(Vector< double > &residuals, DenseMatrix< double > &jacobian, const unsigned &flag)
Compute element residual Vector only (if flag=and/or element Jacobian matrix.
QPoissonElement()
Constructor: Call constructors for QElement and Poisson equations.
unsigned nhistory_values_for_coordinate_projection()
Number of positional history values (Note: count includes current value!)
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.
A Rank 4 Tensor class.
Definition: matrices.h:1625
double dshape_and_dtest_eulerian_at_knot_poisson(const unsigned &ipt, Shape &psi, DShape &dpsidx, Shape &test, DShape &dtestdx) const
Shape, test functions & derivs. w.r.t. to global coords. at integration point ipt. Return Jacobian.
void operator=(const PoissonEquations &)
Broken assignment operator.
QPoissonElement(const QPoissonElement< DIM, NNODE_1D > &dummy)
Broken copy constructor.
void output(std::ostream &outfile)
Output with default number of plot points.
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
virtual unsigned u_index_poisson() const
Return the index at which the unknown value is stored. The default value, 0, is appropriate for singl...
A Rank 3 Tensor class.
Definition: matrices.h:1337
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
unsigned nhistory_values_for_projection(const unsigned &fld)
Number of history values to be stored for fld-th field (includes current value!)
PoissonEquations(const PoissonEquations &dummy)
Broken copy constructor.
virtual void get_source_gradient_poisson(const unsigned &ipt, const Vector< double > &x, Vector< double > &gradient) const
static char t char * s
Definition: cfortran.h:572
void output_fct(std::ostream &outfile, const unsigned &n_plot, FiniteElement::SteadyExactSolutionFctPt exact_soln_pt)
Output function for an exact solution: x,y,u_exact or x,y,z,u_exact at n_plot^DIM plot points...
virtual void get_dresidual_dnodal_coordinates(RankThreeTensor< double > &dresidual_dnodal_coordinates)
Compute derivatives of elemental residual vector with respect to nodal coordinates. Overwrites default implementation in FiniteElement base class. dresidual_dnodal_coordinates(l,i,j) = d res(l) / dX_{ij}.
void point_output_data(const Vector< double > &s, Vector< double > &data)
Output solution in data vector at local cordinates s: x,y [,z], u.
void operator=(const QPoissonElement< DIM, NNODE_1D > &)
Broken assignment operator.
PoissonSourceFctGradientPt Source_fct_gradient_pt
Pointer to gradient of source function.
void(* PoissonSourceFctPt)(const Vector< double > &x, double &f)
Function pointer to source function fct(x,f(x)) – x is a Vector!
double dshape_and_dtest_eulerian_poisson(const Vector< double > &s, Shape &psi, DShape &dpsidx, Shape &test, DShape &dtestdx) const
Shape, test functions & derivs. w.r.t. to global coords. Return Jacobian.
void compute_error(std::ostream &outfile, FiniteElement::SteadyExactSolutionFctPt exact_soln_pt, double &error, double &norm)
Get error against and norm of exact solution.
int local_equation(const unsigned &fld, const unsigned &j)
Return local equation number of value j in field fld.
Node *& node_pt(const unsigned &n)
Return a pointer to the local node n.
Definition: elements.h:2109
void scalar_value_fct_paraview(std::ofstream &file_out, const unsigned &i, const unsigned &nplot, FiniteElement::SteadyExactSolutionFctPt exact_soln_pt) const
Write values of the i-th scalar field at the plot points. Needs to be implemented for each new specif...
std::string scalar_name_paraview(const unsigned &i) const
Name of the i-th scalar field. Default implementation returns V1 for the first one, V2 for the second etc. Can (should!) be overloaded with more meaningful names in specific elements.
virtual void output_fct(std::ostream &outfile, const unsigned &n_plot, const double &time, FiniteElement::UnsteadyExactSolutionFctPt exact_soln_pt)
Output exact soln: x,y,u_exact or x,y,z,u_exact at n_plot^DIM plot points (dummy time-dependent versi...
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
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
void get_flux(const Vector< double > &s, Vector< double > &flux) const
Get flux: flux[i] = du/dx_i.
unsigned dim() const
Return the spatial dimension of the element, i.e. the number of local coordinates required to paramet...
Definition: elements.h:2482
void broken_assign(const std::string &class_name)
Issue error message and terminate execution.
PoissonSourceFctPt & source_fct_pt()
Access function: Pointer to source function.
virtual double interpolated_u_poisson(const Vector< double > &s) const
Return FE representation of function value u_poisson(s) at local coordinate s.
void compute_error(std::ostream &outfile, FiniteElement::UnsteadyExactSolutionFctPt exact_soln_pt, const double &time, double &error, double &norm)
Dummy, time dependent error checker.
void output(FILE *file_pt)
C-style output function: x,y,u or x,y,z,u.
std::string string(const unsigned &i)
Return the i-th string or "" if the relevant string hasn&#39;t been defined.
PoissonSourceFctGradientPt source_fct_gradient_pt() const
Access function: Pointer to gradient source function. Const version.
FaceGeometry()
Constructor: Call the constructor for the appropriate lower-dimensional QElement. ...
unsigned nfields_for_projection()
Number of fields to be projected: Just one.
FaceGeometry()
Constructor: Call the constructor for the appropriate lower-dimensional QElement. ...
unsigned nscalar_paraview() const
Number of scalars/fields output by this element. Reimplements broken virtual function in base class...
void(* PoissonSourceFctGradientPt)(const Vector< double > &x, Vector< double > &gradient)
Function pointer to gradient of source function fct(x,g(x)) – x is a Vector!
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(FILE *file_pt, const unsigned &n_plot)
C-style output function: x,y,u or x,y,z,u at n_plot^DIM plot points.
PoissonSourceFctPt source_fct_pt() const
Access function: Pointer to source function. Const version.
Poisson upgraded to become projectable.
unsigned nnode() const
Return the number of nodes.
Definition: elements.h:2146
virtual double dshape_and_dtest_eulerian_poisson(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...
virtual double dshape_and_dtest_eulerian_at_knot_poisson(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 ...
void compute_norm(double &norm)
Compute norm of solution: square of the L2 norm.
static double Default_fd_jacobian_step
Double used for the default finite difference step in elemental jacobian calculations.
Definition: elements.h:1164
void output_fct(std::ostream &outfile, const unsigned &n_plot, FiniteElement::SteadyExactSolutionFctPt exact_soln_pt)
Output exact soln: x,y,u_exact or x,y,z,u_exact at n_plot^DIM plot points.
void output(std::ostream &outfile, const unsigned &n_plot)
Output function: x,y,u or x,y,z,u at n_plot^DIM plot points.
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...
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...
PoissonSourceFctPt Source_fct_pt
Pointer to source function:
static DenseMatrix< double > Dummy_matrix
Empty dense matrix used as a dummy argument to combined residual and jacobian functions in the case w...
Definition: elements.h:228
unsigned self_test()
Self-test: Return 0 for OK.
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