fourier_decomposed_helmholtz_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 Fourier-decomposed Helmholtz elements
31 #ifndef OOMPH_FOURIER_DECOMPOSED_HELMHOLTZ_ELEMENTS_HEADER
32 #define OOMPH_FOURIER_DECOMPOSED_HELMHOLTZ_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 "math.h"
41 #include <complex>
42 
43 
44 //OOMPH-LIB headers
45 #include "../generic/projection.h"
46 #include "../generic/nodes.h"
47 #include "../generic/Qelements.h"
48 #include "../generic/oomph_utilities.h"
49 
50 namespace oomph
51 {
52 
53 //========================================================================
54 /// Helper namespace for functions required for Helmholtz computations
55 //========================================================================
56  namespace Legendre_functions_helper
57  {
58 
59  /// Factorial
60  extern double factorial(const unsigned& l);
61 
62  /// Legendre polynomials depending on one parameter
63  extern double plgndr1(const unsigned& n, const double& x);
64 
65  /// Legendre polynomials depending on two parameters
66  extern double plgndr2(const unsigned& l, const unsigned& m, const double& x);
67 
68  } // end namespace
69 
70 
71 ///////////////////////////////////////////////////////////////////////
72 ///////////////////////////////////////////////////////////////////////
73 ///////////////////////////////////////////////////////////////////////
74 
75 
76 //=============================================================
77 /// A class for all isoparametric elements that solve the
78 /// Helmholtz equations.
79 /// \f[
80 /// \nabla^2 U + k^2 U = f
81 /// \f]
82 /// in Fourier decomposed form (cylindrical polars):
83 /// \f[
84 /// U(r,\varphi,z) = \Re( u^{(n)}(r,z) \exp(-i n \varphi))
85 /// \f]
86 /// We are solving for \f$ u^{(n)}(r,z)\f$ for given parameters
87 /// \f$ k^2 \f$ and \f$ n \f$ .
88 /// This contains the generic maths. Shape functions, geometric
89 /// mapping etc. must get implemented in derived class.
90 //=============================================================
92  {
93 
94  public:
95 
96  /// \short Function pointer to source function fct(x,f(x)) --
97  /// x is a Vector!
98  typedef void (*FourierDecomposedHelmholtzSourceFctPt)(
99  const Vector<double>& x,
100  std::complex<double>& f);
101 
102 
103  /// Constructor
105  K_squared_pt(0), N_fourier_pt(0)
106  {}
107 
108  /// Broken copy constructor
111  {
112  BrokenCopy::broken_copy("FourierDecomposedHelmholtzEquations");
113  }
114 
115  /// Broken assignment operator
116 //Commented out broken assignment operator because this can lead to a conflict warning
117 //when used in the virtual inheritence hierarchy. Essentially the compiler doesn't
118 //realise that two separate implementations of the broken function are the same and so,
119 //quite rightly, it shouts.
120  /*void operator=(const FourierDecomposedHelmholtzEquations&)
121  {
122  BrokenCopy::broken_assign("FourierDecomposedHelmholtzEquations");
123  }*/
124 
125 
126  /// \short Return the index at which the unknown value
127  /// is stored: Real/imag part of index contains (real) index of
128  /// real/imag part.
129  virtual inline std::complex<unsigned> u_index_fourier_decomposed_helmholtz()
130  const
131  {return std::complex<unsigned>(0,1);}
132 
133 
134  /// Get pointer to square of wavenumber
135  double*& k_squared_pt()
136  {
137  return K_squared_pt;
138  }
139 
140  /// Get the square of wavenumber
141  double k_squared()
142  {
143  if (K_squared_pt==0)
144  {
145  return 0.0;
146  }
147  else
148  {
149  return *K_squared_pt;
150  }
151  }
152 
153  /// Get pointer to Fourier wavenumber
155  {
156  return N_fourier_pt;
157  }
158 
159  /// Get the Fourier wavenumber
161  {
162  if (N_fourier_pt==0)
163  {
164  return 0;
165  }
166  else
167  {
168  return *N_fourier_pt;
169  }
170  }
171 
172  /// Output with default number of plot points
173  void output(std::ostream &outfile)
174  {
175  const unsigned n_plot=5;
176  output(outfile,n_plot);
177  }
178 
179  /// \short Output FE representation of soln: x,y,u_re,u_im or
180  /// x,y,z,u_re,u_im at n_plot^2 plot points
181  void output(std::ostream &outfile, const unsigned &n_plot);
182 
183  /// \short Output function for real part of full time-dependent solution
184  /// u = Re( (u_r +i u_i) exp(-i omega t)
185  /// at phase angle omega t = phi.
186  /// r,z,u at n_plot plot points in each coordinate
187  /// direction
188  void output_real(std::ostream &outfile, const double& phi,
189  const unsigned &n_plot);
190 
191  /// C_style output with default number of plot points
192  void output(FILE* file_pt)
193  {
194  const unsigned n_plot=5;
195  output(file_pt,n_plot);
196  }
197 
198  /// \short C-style output FE representation of soln: r,z,u_re,u_im or
199  /// at n_plot^2 plot points
200  void output(FILE* file_pt, const unsigned &n_plot);
201 
202  /// Output exact soln: r,z,u_re_exact,u_im_exact
203  /// at n_plot^2 plot points
204  void output_fct(std::ostream &outfile, const unsigned &n_plot,
206 
207  /// \short Output exact soln: (dummy time-dependent version to
208  /// keep intel compiler happy)
209  virtual void output_fct(std::ostream &outfile, const unsigned &n_plot,
210  const double& time,
212  exact_soln_pt)
213  {
214  throw OomphLibError(
215  "There is no time-dependent output_fct() for FourierDecomposedHelmholtz elements ",
216  OOMPH_CURRENT_FUNCTION,
217  OOMPH_EXCEPTION_LOCATION);
218  }
219 
220 
221  /// \short Output function for real part of full time-dependent fct
222  /// u = Re( (u_r +i u_i) exp(-i omega t)
223  /// at phase angle omega t = phi.
224  /// r,z,u at n_plot plot points in each coordinate
225  /// direction
226  void output_real_fct(std::ostream &outfile,
227  const double& phi,
228  const unsigned &n_plot,
230 
231 
232  /// Get error against and norm of exact solution
233  void compute_error(std::ostream &outfile,
235  double& error, double& norm);
236 
237 
238  /// Dummy, time dependent error checker
239  void compute_error(std::ostream &outfile,
241  const double& time, double& error, double& norm)
242  {
243  throw OomphLibError(
244  "There is no time-dependent compute_error() for FourierDecomposedHelmholtz elements",
245  OOMPH_CURRENT_FUNCTION,
246  OOMPH_EXCEPTION_LOCATION);
247  }
248 
249  /// Compute norm of fe solution
250  void compute_norm(double& norm);
251 
252  /// Access function: Pointer to source function
253  FourierDecomposedHelmholtzSourceFctPt& source_fct_pt() {return Source_fct_pt;}
254 
255  /// Access function: Pointer to source function. Const version
256  FourierDecomposedHelmholtzSourceFctPt source_fct_pt() const
257  {return Source_fct_pt;}
258 
259  /// Get source term at (Eulerian) position x. This function is
260  /// virtual to allow overloading in multi-physics problems where
261  /// the strength of the source function might be determined by
262  /// another system of equations.
264  const unsigned& ipt,
265  const Vector<double>& x,
266  std::complex<double>& source) const
267  {
268  //If no source function has been set, return zero
269  if(Source_fct_pt==0)
270  {
271  source = std::complex<double>(0.0,0.0);
272  }
273  else
274  {
275  // Get source strength
276  (*Source_fct_pt)(x,source);
277  }
278  }
279 
280 
281  /// Get flux: flux[i] = du/dx_i for real and imag part
282  void get_flux(const Vector<double>& s,
283  Vector<std::complex <double> >& flux) const
284  {
285  //Find out how many nodes there are in the element
286  const unsigned n_node = nnode();
287 
288  //Set up memory for the shape and test functions
289  Shape psi(n_node);
290  DShape dpsidx(n_node,2);
291 
292  //Call the derivatives of the shape and test functions
293  dshape_eulerian(s,psi,dpsidx);
294 
295  //Initialise to zero
296  const std::complex<double> zero(0.0,0.0);
297  for(unsigned j=0;j<2;j++)
298  {
299  flux[j] = zero;
300  }
301 
302  // Loop over nodes
303  for(unsigned l=0;l<n_node;l++)
304  {
305  //Cache the complex value of the unknown
306  const std::complex<double> u_value(
307  this->nodal_value(l,u_index_fourier_decomposed_helmholtz().real()),
308  this->nodal_value(l,u_index_fourier_decomposed_helmholtz().imag()));
309 
310  //Loop over derivative directions
311  for(unsigned j=0;j<2;j++)
312  {
313  flux[j] += u_value*dpsidx(l,j);
314  }
315  }
316  }
317 
318 
319  /// Add the element's contribution to its residual vector (wrapper)
321  {
322  //Call the generic residuals function with flag set to 0
323  //using a dummy matrix argument
324  fill_in_generic_residual_contribution_fourier_decomposed_helmholtz(
326  }
327 
328 
329 
330  /// \short Add the element's contribution to its residual vector and
331  /// element Jacobian matrix (wrapper)
333  DenseMatrix<double> &jacobian)
334  {
335  //Call the generic routine with the flag set to 1
336  fill_in_generic_residual_contribution_fourier_decomposed_helmholtz(
337  residuals,jacobian,1);
338  }
339 
340 
341 
342  /// \short Return FE representation of function value u(s)
343  /// at local coordinate s
344  inline std::complex<double> interpolated_u_fourier_decomposed_helmholtz(
345  const Vector<double> &s)
346  const
347  {
348  //Find number of nodes
349  const unsigned n_node = nnode();
350 
351  //Local shape function
352  Shape psi(n_node);
353 
354  //Find values of shape function
355  shape(s,psi);
356 
357  //Initialise value of u
358  std::complex<double> interpolated_u(0.0,0.0);
359 
360  //Get the index at which the helmholtz unknown is stored
361  const unsigned u_nodal_index_real =
362  u_index_fourier_decomposed_helmholtz().real();
363  const unsigned u_nodal_index_imag =
364  u_index_fourier_decomposed_helmholtz().imag();
365 
366  //Loop over the local nodes and sum
367  for(unsigned l=0;l<n_node;l++)
368  {
369  //Make a temporary complex number from the stored data
370  const std::complex<double> u_value(
371  this->nodal_value(l,u_nodal_index_real),
372  this->nodal_value(l,u_nodal_index_imag));
373  //Add to the interpolated value
374  interpolated_u += u_value*psi[l];
375  }
376  return interpolated_u;
377  }
378 
379 
380  /// \short Self-test: Return 0 for OK
381  unsigned self_test();
382 
383 
384  protected:
385 
386  /// \short Shape/test functions and derivs w.r.t. to global coords at
387  /// local coord. s; return Jacobian of mapping
388  virtual double dshape_and_dtest_eulerian_fourier_decomposed_helmholtz(
389  const Vector<double> &s,
390  Shape &psi,
391  DShape &dpsidx, Shape &test,
392  DShape &dtestdx) const=0;
393 
394 
395  /// \short Shape/test functions and derivs w.r.t. to global coords at
396  /// integration point ipt; return Jacobian of mapping
397  virtual double dshape_and_dtest_eulerian_at_knot_fourier_decomposed_helmholtz(
398  const unsigned &ipt,
399  Shape &psi,
400  DShape &dpsidx,
401  Shape &test,
402  DShape &dtestdx) const=0;
403 
404  /// \short Compute element residual Vector only (if flag=and/or element
405  /// Jacobian matrix
406  virtual void
407  fill_in_generic_residual_contribution_fourier_decomposed_helmholtz(
408  Vector<double> &residuals, DenseMatrix<double> &jacobian,
409  const unsigned& flag);
410 
411  /// Pointer to source function:
412  FourierDecomposedHelmholtzSourceFctPt Source_fct_pt;
413 
414  /// Pointer to square of wavenumber
415  double* K_squared_pt;
416 
417  /// Pointer to Fourier wave number
419 
420  };
421 
422 
423 
424 
425 ///////////////////////////////////////////////////////////////////////////
426 ///////////////////////////////////////////////////////////////////////////
427 ///////////////////////////////////////////////////////////////////////////
428 
429 
430 
431 //======================================================================
432 /// QFourierDecomposedHelmholtzElement elements are
433 /// linear/quadrilateral/brick-shaped FourierDecomposedHelmholtz
434 /// elements with isoparametric interpolation for the function.
435 //======================================================================
436  template <unsigned NNODE_1D>
438  public virtual QElement<2,NNODE_1D>,
440  {
441 
442  private:
443 
444  /// \short Static int that holds the number of variables at
445  /// nodes: always the same
446  static const unsigned Initial_Nvalue;
447 
448  public:
449 
450 
451  ///\short Constructor: Call constructors for QElement and
452  /// FourierDecomposedHelmholtz equations
455  {}
456 
457  /// Broken copy constructor
460  {
461  BrokenCopy::broken_copy("QFourierDecomposedHelmholtzElement");
462  }
463 
464  /// Broken assignment operator
465  /*void operator=(const QFourierDecomposedHelmholtzElement<NNODE_1D>&)
466  {
467  BrokenCopy::broken_assign("QFourierDecomposedHelmholtzElement");
468  }*/
469 
470 
471  /// \short Required # of `values' (pinned or dofs)
472  /// at node n
473  inline unsigned required_nvalue(const unsigned &n) const
474  {return Initial_Nvalue;}
475 
476  /// \short Output function: r,z,u
477  void output(std::ostream &outfile)
479 
480  /// \short Output function:
481  /// r,z,u at n_plot^2 plot points
482  void output(std::ostream &outfile, const unsigned &n_plot)
484 
485  /// \short Output function for real part of full time-dependent solution
486  /// u = Re( (u_r +i u_i) exp(-i omega t)
487  /// at phase angle omega t = phi.
488  /// r,z,u at n_plot plot points in each coordinate
489  /// direction
490  void output_real(std::ostream &outfile, const double& phi,
491  const unsigned &n_plot)
493 
494  /// \short C-style output function: r,z,u
495  void output(FILE* file_pt)
497 
498  /// \short C-style output function:
499  /// r,z,u at n_plot^2 plot points
500  void output(FILE* file_pt, const unsigned &n_plot)
502 
503  /// \short Output function for an exact solution:
504  /// r,z,u_exact at n_plot^2 plot points
505  void output_fct(std::ostream &outfile, const unsigned &n_plot,
507  {
509  exact_soln_pt);
510  }
511 
512  /// \short Output function for real part of full time-dependent fct
513  /// u = Re( (u_r +i u_i) exp(-i omega t)
514  /// at phase angle omega t = phi.
515  /// r,z,u at n_plot plot points in each coordinate
516  /// direction
517  void output_real_fct(std::ostream &outfile,
518  const double& phi,
519  const unsigned &n_plot,
521  {
523  n_plot,exact_soln_pt);
524  }
525 
526 
527  /// \short Output function for a time-dependent exact solution.
528  /// r,z,u_exact at n_plot^2 plot points
529  /// (Calls the steady version)
530  void output_fct(std::ostream &outfile, const unsigned &n_plot,
531  const double& time,
533  {
535  time,exact_soln_pt);
536  }
537 
538  protected:
539 
540  /// Shape, test functions & derivs. w.r.t. to global coords.
541  /// Return Jacobian.
542  inline double dshape_and_dtest_eulerian_fourier_decomposed_helmholtz(
543  const Vector<double> &s, Shape &psi, DShape &dpsidx,
544  Shape &test, DShape &dtestdx) const;
545 
546 
547  /// \short Shape, test functions & derivs. w.r.t. to global coords. at
548  /// integration point ipt. Return Jacobian.
549  inline double
550  dshape_and_dtest_eulerian_at_knot_fourier_decomposed_helmholtz(
551  const unsigned& ipt,
552  Shape &psi,
553  DShape &dpsidx,
554  Shape &test,
555  DShape &dtestdx) const;
556 
557  };
558 
559 
560 
561 
562 //Inline functions:
563 
564 
565 //======================================================================
566 /// Define the shape functions and test functions and derivatives
567 /// w.r.t. global coordinates and return Jacobian of mapping.
568 ///
569 /// Galerkin: Test functions = shape functions
570 //======================================================================
571  template<unsigned NNODE_1D>
574  const Vector<double> &s,
575  Shape &psi,
576  DShape &dpsidx,
577  Shape &test,
578  DShape &dtestdx) const
579  {
580  //Call the geometrical shape functions and derivatives
581  const double J = this->dshape_eulerian(s,psi,dpsidx);
582 
583  //Set the test functions equal to the shape functions
584  test = psi;
585  dtestdx= dpsidx;
586 
587  //Return the jacobian
588  return J;
589  }
590 
591 
592 
593 
594 //======================================================================
595 /// Define the shape functions and test functions and derivatives
596 /// w.r.t. global coordinates and return Jacobian of mapping.
597 ///
598 /// Galerkin: Test functions = shape functions
599 //======================================================================
600  template<unsigned NNODE_1D>
603  const unsigned &ipt,
604  Shape &psi,
605  DShape &dpsidx,
606  Shape &test,
607  DShape &dtestdx) const
608  {
609  //Call the geometrical shape functions and derivatives
610  const double J = this->dshape_eulerian_at_knot(ipt,psi,dpsidx);
611 
612  //Set the pointers of the test functions
613  test = psi;
614  dtestdx = dpsidx;
615 
616  //Return the jacobian
617  return J;
618  }
619 
620 ////////////////////////////////////////////////////////////////////////
621 ////////////////////////////////////////////////////////////////////////
622 ////////////////////////////////////////////////////////////////////////
623 
624 
625 
626 //=======================================================================
627 /// Face geometry for the QFourierDecomposedHelmholtzElement elements:
628 /// The spatial dimension of the face elements is one lower than that of the
629 /// bulk element but they have the same number of points
630 /// along their 1D edges.
631 //=======================================================================
632  template<unsigned NNODE_1D>
634  public virtual QElement<1,NNODE_1D>
635  {
636 
637  public:
638 
639  /// \short Constructor: Call the constructor for the
640  /// appropriate lower-dimensional QElement
641  FaceGeometry() : QElement<1,NNODE_1D>() {}
642  };
643 
644 
645 ////////////////////////////////////////////////////////////////////////
646 ////////////////////////////////////////////////////////////////////////
647 ////////////////////////////////////////////////////////////////////////
648 
649 
650 
651 //==========================================================
652 /// Fourier decomposed Helmholtz upgraded to become projectable
653 //==========================================================
654  template<class FOURIER_DECOMPOSED_HELMHOLTZ_ELEMENT>
656  public virtual ProjectableElement<FOURIER_DECOMPOSED_HELMHOLTZ_ELEMENT>
657  {
658 
659  public:
660 
661 
662  /// \short Constructor [this was only required explicitly
663  /// from gcc 4.5.2 onwards...]
665 
666  /// \short Specify the values associated with field fld.
667  /// The information is returned in a vector of pairs which comprise
668  /// the Data object and the value within it, that correspond to field fld.
670  {
671 
672 #ifdef PARANOID
673  if (fld>1)
674  {
675  std::stringstream error_stream;
676  error_stream
677  << "Fourier decomposed Helmholtz elements only store 2 fields so fld = "
678  << fld << " is illegal \n";
679  throw OomphLibError(
680  error_stream.str(),
681  OOMPH_CURRENT_FUNCTION,
682  OOMPH_EXCEPTION_LOCATION);
683  }
684 #endif
685 
686  // Create the vector
687  unsigned nnod=this->nnode();
688  Vector<std::pair<Data*,unsigned> > data_values(nnod);
689 
690  // Loop over all nodes
691  for (unsigned j=0;j<nnod;j++)
692  {
693  // Add the data value associated field: The node itself
694  data_values[j]=std::make_pair(this->node_pt(j),fld);
695  }
696 
697  // Return the vector
698  return data_values;
699  }
700 
701  /// \short Number of fields to be projected: 2 (real and imag part)
703  {
704  return 2;
705  }
706 
707  /// \short Number of history values to be stored for fld-th field.
708  /// (Note: count includes current value!)
709  unsigned nhistory_values_for_projection(const unsigned &fld)
710  {
711 #ifdef PARANOID
712  if (fld>1)
713  {
714  std::stringstream error_stream;
715  error_stream
716  << "Helmholtz elements only store two fields so fld = "
717  << fld << " is illegal\n";
718  throw OomphLibError(
719  error_stream.str(),
720  OOMPH_CURRENT_FUNCTION,
721  OOMPH_EXCEPTION_LOCATION);
722  }
723 #endif
724  return this->node_pt(0)->ntstorage();
725  }
726 
727  ///\short Number of positional history values
728  /// (Note: count includes current value!)
730  {
731  return this->node_pt(0)->position_time_stepper_pt()->ntstorage();
732  }
733 
734  /// \short Return Jacobian of mapping and shape functions of field fld
735  /// at local coordinate s
736  double jacobian_and_shape_of_field(const unsigned &fld,
737  const Vector<double> &s,
738  Shape &psi)
739  {
740 #ifdef PARANOID
741  if (fld>1)
742  {
743  std::stringstream error_stream;
744  error_stream
745  << "Helmholtz elements only store two fields so fld = "
746  << fld << " is illegal.\n";
747  throw OomphLibError(
748  error_stream.str(),
749  OOMPH_CURRENT_FUNCTION,
750  OOMPH_EXCEPTION_LOCATION);
751  }
752 #endif
753  unsigned n_dim=this->dim();
754  unsigned n_node=this->nnode();
755  Shape test(n_node);
756  DShape dpsidx(n_node,n_dim), dtestdx(n_node,n_dim);
757  double J=this->dshape_and_dtest_eulerian_fourier_decomposed_helmholtz(
758  s,psi,dpsidx,
759  test,dtestdx);
760  return J;
761  }
762 
763 
764 
765  /// \short Return interpolated field fld at local coordinate s, at time level
766  /// t (t=0: present; t>0: history values)
767  double get_field(const unsigned &t,
768  const unsigned &fld,
769  const Vector<double>& s)
770  {
771 #ifdef PARANOID
772  if (fld>1)
773  {
774  std::stringstream error_stream;
775  error_stream
776  << "Helmholtz elements only store two fields so fld = "
777  << fld << " is illegal\n";
778  throw OomphLibError(
779  error_stream.str(),
780  OOMPH_CURRENT_FUNCTION,
781  OOMPH_EXCEPTION_LOCATION);
782  }
783 #endif
784  //Find the index at which the variable is stored
785  std::complex<unsigned> complex_u_nodal_index =
786  this->u_index_fourier_decomposed_helmholtz();
787  unsigned u_nodal_index = 0;
788  if (fld==0)
789  {
790  u_nodal_index = complex_u_nodal_index.real();
791  }
792  else
793  {
794  u_nodal_index = complex_u_nodal_index.imag();
795  }
796 
797 
798  //Local shape function
799  unsigned n_node=this->nnode();
800  Shape psi(n_node);
801 
802  //Find values of shape function
803  this->shape(s,psi);
804 
805  //Initialise value of u
806  double interpolated_u = 0.0;
807 
808  //Sum over the local nodes
809  for(unsigned l=0;l<n_node;l++)
810  {
811  interpolated_u += this->nodal_value(t,l,u_nodal_index)*psi[l];
812  }
813  return interpolated_u;
814  }
815 
816 
817 
818 
819  ///Return number of values in field fld: One per node
820  unsigned nvalue_of_field(const unsigned &fld)
821  {
822 #ifdef PARANOID
823  if (fld>1)
824  {
825  std::stringstream error_stream;
826  error_stream
827  << "Helmholtz elements only store two fields so fld = "
828  << fld << " is illegal\n";
829  throw OomphLibError(
830  error_stream.str(),
831  OOMPH_CURRENT_FUNCTION,
832  OOMPH_EXCEPTION_LOCATION);
833  }
834 #endif
835  return this->nnode();
836  }
837 
838 
839  ///Return local equation number of value j in field fld.
840  int local_equation(const unsigned &fld,
841  const unsigned &j)
842  {
843 #ifdef PARANOID
844  if (fld>1)
845  {
846  std::stringstream error_stream;
847  error_stream
848  << "Helmholtz elements only store two fields so fld = "
849  << fld << " is illegal\n";
850  throw OomphLibError(
851  error_stream.str(),
852  OOMPH_CURRENT_FUNCTION,
853  OOMPH_EXCEPTION_LOCATION);
854  }
855 #endif
856  std::complex<unsigned> complex_u_nodal_index =
857  this->u_index_fourier_decomposed_helmholtz();
858  unsigned u_nodal_index = 0;
859  if (fld==0)
860  {
861  u_nodal_index = complex_u_nodal_index.real();
862  }
863  else
864  {
865  u_nodal_index = complex_u_nodal_index.imag();
866  }
867  return this->nodal_local_eqn(j,u_nodal_index);
868  }
869 
870 
871 
872 
873  /// \short Output FE representation of soln: x,y,u or x,y,z,u at
874  /// n_plot^DIM plot points
875  void output(std::ostream &outfile, const unsigned &nplot)
876  {
878  }
879 
880 
881  };
882 
883 
884 //=======================================================================
885 /// Face geometry for element is the same as that for the underlying
886 /// wrapped element
887 //=======================================================================
888  template<class ELEMENT>
890  : public virtual FaceGeometry<ELEMENT>
891  {
892  public:
893  FaceGeometry() : FaceGeometry<ELEMENT>() {}
894  };
895 
896 
897 //=======================================================================
898 /// Face geometry of the Face Geometry for element is the same as
899 /// that for the underlying wrapped element
900 //=======================================================================
901  template<class ELEMENT>
903  : public virtual FaceGeometry<FaceGeometry<ELEMENT> >
904  {
905  public:
907  };
908 
909 
910 
911 
912 }
913 
914 #endif
void output_real(std::ostream &outfile, const double &phi, const unsigned &n_plot)
Output function for real part of full time-dependent solution u = Re( (u_r +i u_i) exp(-i omega t) at...
void broken_copy(const std::string &class_name)
Issue error message and terminate execution.
double factorial(const unsigned &l)
Factorial.
GeneralisedAxisymAdvectionDiffusionSourceFctPt Source_fct_pt
Pointer to source function:
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. r,z,u_exact at n_plot^2 plot points (Calls the s...
Fourier decomposed Helmholtz upgraded to become projectable.
int *& fourier_wavenumber_pt()
Get pointer to Fourier wavenumber.
void output(std::ostream &outfile)
Output function: r,z,u.
double * K_squared_pt
Pointer to square of wavenumber.
QFourierDecomposedHelmholtzElement(const QFourierDecomposedHelmholtzElement< NNODE_1D > &dummy)
Broken copy constructor.
void output_fct(std::ostream &outfile, const unsigned &n_plot, FiniteElement::SteadyExactSolutionFctPt exact_soln_pt)
void output(std::ostream &outfile)
Output with default number of plot points.
void output_fct(std::ostream &outfile, const unsigned &nplot, FiniteElement::SteadyExactSolutionFctPt exact_soln_pt)
Output exact soln: r,z,u_exact at nplot^2 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
unsigned nvalue_of_field(const unsigned &fld)
Return number of values in field fld: One per node.
virtual void output_fct(std::ostream &outfile, const unsigned &n_plot, const double &time, FiniteElement::UnsteadyExactSolutionFctPt exact_soln_pt)
Output exact soln: (dummy time-dependent version to keep intel compiler happy)
unsigned required_nvalue(const unsigned &n) const
Broken assignment operator.
unsigned nhistory_values_for_coordinate_projection()
Number of positional history values (Note: count includes current value!)
void output(std::ostream &outfile, const unsigned &n_plot)
Output function: r,z,u at n_plot^2 plot points.
double plgndr1(const unsigned &n, const double &x)
Legendre polynomials depending on one parameter.
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)
C-style output function: r,z,u.
void get_flux(const Vector< double > &s, Vector< std::complex< double > > &flux) const
Get flux: flux[i] = du/dx_i for real and imag part.
FourierDecomposedHelmholtzEquations(const FourierDecomposedHelmholtzEquations &dummy)
Broken copy constructor.
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(* SteadyExactSolutionFctPt)(const Vector< double > &, Vector< double > &)
Function pointer for function that computes vector-valued steady "exact solution" as ...
Definition: elements.h:1723
ProjectableFourierDecomposedHelmholtzElement()
Constructor [this was only required explicitly from gcc 4.5.2 onwards...].
void fill_in_contribution_to_jacobian(Vector< double > &residuals, DenseMatrix< double > &jacobian)
Add the element&#39;s contribution to its residual vector and element Jacobian matrix (wrapper) ...
QFourierDecomposedHelmholtzElement()
Constructor: Call constructors for QElement and FourierDecomposedHelmholtz equations.
unsigned self_test()
Self-test: Return 0 for OK.
virtual void get_source_fourier_decomposed_helmholtz(const unsigned &ipt, const Vector< double > &x, std::complex< double > &source) const
static char t char * s
Definition: cfortran.h:572
void fill_in_contribution_to_residuals(Vector< double > &residuals)
Add the element&#39;s contribution to its residual vector (wrapper)
FourierDecomposedHelmholtzSourceFctPt Source_fct_pt
Pointer to source function:
double *& k_squared_pt()
Get pointer to square of wavenumber.
void shape(const double &s, double *Psi)
Definition for 1D Lagrange shape functions. The value of all the shape functions at the local coordin...
Definition: shape.h:549
void output(std::ostream &outfile)
Output with default number of plot points.
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...
FourierDecomposedHelmholtzSourceFctPt & source_fct_pt()
Access function: Pointer to source function.
void output(FILE *file_pt, const unsigned &n_plot)
C-style output function: r,z,u at n_plot^2 plot points.
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.
int local_equation(const unsigned &fld, const unsigned &j)
Return local equation number of value j in field fld.
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.
FaceGeometry()
Constructor: Call the constructor for the appropriate lower-dimensional QElement. ...
void output(std::ostream &outfile, const unsigned &nplot)
Output FE representation of soln: x,y,u or x,y,z,u at n_plot^DIM plot points.
static const unsigned Initial_Nvalue
Static int that holds the number of variables at nodes: always the same.
void output_real(std::ostream &outfile, const double &phi, const unsigned &n_plot)
Output function for real part of full time-dependent solution u = Re( (u_r +i u_i) exp(-i omega t) at...
unsigned nfields_for_projection()
Number of fields to be projected: 2 (real and imag part)
FourierDecomposedHelmholtzSourceFctPt source_fct_pt() const
Access function: Pointer to source function. Const version.
void output_fct(std::ostream &outfile, const unsigned &n_plot, FiniteElement::SteadyExactSolutionFctPt exact_soln_pt)
Output function for an exact solution: r,z,u_exact at n_plot^2 plot points.
virtual std::complex< unsigned > u_index_fourier_decomposed_helmholtz() const
Broken assignment operator.
void output_real_fct(std::ostream &outfile, const double &phi, const unsigned &n_plot, FiniteElement::SteadyExactSolutionFctPt exact_soln_pt)
Output function for real part of full time-dependent fct u = Re( (u_r +i u_i) exp(-i omega t) at phas...
void output_real_fct(std::ostream &outfile, const double &phi, const unsigned &n_plot, FiniteElement::SteadyExactSolutionFctPt exact_soln_pt)
Output function for real part of full time-dependent fct u = Re( (u_r +i u_i) exp(-i omega t) at phas...
std::complex< double > interpolated_u_fourier_decomposed_helmholtz(const Vector< double > &s) const
Return FE representation of function value u(s) at local coordinate s.
double dshape_and_dtest_eulerian_at_knot_fourier_decomposed_helmholtz(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.
double dshape_and_dtest_eulerian_fourier_decomposed_helmholtz(const Vector< double > &s, Shape &psi, DShape &dpsidx, Shape &test, DShape &dtestdx) const
void output(FILE *file_pt)
C_style output with default number of plot points.
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
double plgndr2(const unsigned &l, const unsigned &m, const double &x)
Legendre polynomials depending on two parameters.