Qspectral_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 functions for classes that define Qelements
31 
32 //Include guards to prevent multiple inclusion of the header
33 #ifndef OOMPH_QSPECTRAL_ELEMENT_HEADER
34 #define OOMPH_QSPECTRAL_ELEMENT_HEADER
35 
36 // Config header generated by autoconfig
37 #ifdef HAVE_CONFIG_H
38  #include <oomph-lib-config.h>
39 #endif
40 
41 //oomph-lib headers
42 #include "Qelements.h"
43 
44 namespace oomph
45 {
46 
47 //=====================================================================
48 /// Class that returns the shape functions associated with legendre
49 //=====================================================================
51 {
52  public:
53  static std::map<unsigned,Vector<double> > z;
54 
55  /// Static function used to populate the stored positions
56  static inline void calculate_nodal_positions(const unsigned &order)
57  {
58  //If we haven't already calculated these
59  if(z.find(order)==z.end())
60  {
61  Orthpoly::gll_nodes(order,z[order]);
62  }
63  }
64 
65  static inline double nodal_position(const unsigned &order, const unsigned &n)
66  {return z[order][n];}
67 
68  /// Constructor
69  OneDLegendreShapeParam(const unsigned &order,const double &s) :
70  Shape(order)
71  {
72  using namespace Orthpoly;
73 
74  unsigned p = order-1;
75  //Now populate the shape function
76  for(unsigned i=0;i<order;i++)
77  {
78  //If we're at one of the nodes, the value must be 1.0
79  if(std::fabs(s-z[order][i]) < Orthpoly::eps)
80  {
81  (*this)[i] = 1.0;
82  }
83  //Otherwise use the lagrangian interpolant
84  else
85  {
86  (*this)[i] = (1.0 - s*s)*dlegendre(p,s)/
87  (p*(p+1)*legendre(p,z[order][i])*(z[order][i] - s));
88  }
89  }
90  }
91 };
92 
93 
95 {
96  public:
97  // Constructor
98  OneDLegendreDShapeParam(const unsigned &order, const double &s) :
99  Shape(order)
100  {
101  unsigned p = order - 1;
103 
104  bool root=false;
105  for(unsigned i=0;i<order;i++)
106  {
107  unsigned rootnum=0;
108  for(unsigned j=0;j<order;j++)
109  { // Loop over roots to check if
110  if(std::fabs(s-z[j])<10.0*Orthpoly::eps)
111  { // s happens to be a root.
112  root=true;
113  break;
114  }
115  rootnum+=1;
116  }
117  if(root==true)
118  {
119  if(i==rootnum && i==0)
120  {
121  (*this)[i]=-(1.0+p)*p/4.0;
122  }
123  else if(i==rootnum && i==p)
124  {
125  (*this)[i]=(1.0+p)*p/4.0;
126  }
127  else if(i==rootnum)
128  {
129  (*this)[i]=0.0;
130  }
131  else
132  {
133  (*this)[i]=Orthpoly::legendre(p,z[rootnum])
134  /Orthpoly::legendre(p,z[i])/(z[rootnum]-z[i]);
135  }
136  }
137  else
138  {
139  (*this)[i]=((1+s*(s-2*z[i]))/(s-z[i])* Orthpoly::dlegendre(p,s)
140  -(1-s*s)* Orthpoly::ddlegendre(p,s))
141  /p/(p+1.0)/Orthpoly::legendre(p,z[i])/(s-z[i]);
142  }
143  root = false;
144  }
145 
146 
147  }
148 
149 };
150 
151 
152 
153 //========================================================================
154 // A Base class for Spectral elements
155 //========================================================================
156 class SpectralElement : public virtual FiniteElement
157 {
158  protected:
159 
160  /// Additional Storage for shared spectral data
162 
163  /// Vector that represents the spectral order in each dimension
165 
166  /// Vector that represents the nodal spectral order
168 
169  /// Local equation numbers for the spectral degrees of freedom
171 
172  public:
173 
174  SpectralElement() : FiniteElement(), Spectral_data_pt(0) {}
175 
177  {
178  if(Spectral_data_pt!=0)
179  {
180  delete Spectral_data_pt;
181  Spectral_data_pt=0;
182  }
183  }
184 
185 
186  ///\short Return the i-th data object associated with the polynomials
187  ///of order p. Note that i <= p.
188  Data* spectral_data_pt(const unsigned &i) const
189  {return (*Spectral_data_pt)[i];}
190 
191  /// \short Function to describe the local dofs of the element. The ostream
192  /// specifies the output stream to which the description
193  /// is written; the string stores the currently
194  /// assembled output that is ultimately written to the
195  /// output stream by Data::describe_dofs(...); it is typically
196  /// built up incrementally as we descend through the
197  /// call hierarchy of this function when called from
198  /// Problem::describe_dofs(...)
199  virtual void describe_local_dofs(std::ostream& out,
200  const std::string& current_string) const
201  {
202  //Do the standard finite element stuff
203  FiniteElement::describe_local_dofs(out,current_string);
204  //Now get the number of spectral data.
205  unsigned n_spectral = nspectral();
206 
207  //Now loop over the nodes again and assign local equation numbers
208  for(unsigned n=0;n<n_spectral;n++)
209  {
210  //Can we upcast to a node
211  Node* cast_node_pt = dynamic_cast<Node*>(spectral_data_pt(n));
212  if(cast_node_pt)
213  {
214  std::stringstream conversion;
215  conversion <<" of Node "<<n<<current_string;
216  std::string in(conversion.str());
217  cast_node_pt->describe_dofs(out,in);
218  }
219  // Otherwise it is data.
220  else
221  {
222  Data* data_pt = spectral_data_pt(n);
223  std::stringstream conversion;
224  conversion <<" of Data "<<n<<current_string;
225  std::string in(conversion.str());
226  data_pt->describe_dofs(out,in);
227  }
228  }
229  }
230 
231  /// \short Assign the local equation numbers. If the boolean argument is
232  /// true then store degrees of freedom at Dof_pt
234  const bool &store_local_dof_pt)
235  {
236  //Do the standard finite element stuff
238 
239  //Now need to loop over the spectral data
240  unsigned n_spectral = nspectral();
241  if(n_spectral > 0)
242  {
243  //Find the number of local equations assigned so far
244  unsigned local_eqn_number = ndof();
245 
246  //Find number of values stored at the first node
247  unsigned max_n_value = spectral_data_pt(0)->nvalue();
248  //Loop over the other nodes and find the maximum number of values stored
249  for(unsigned n=1;n<n_spectral;n++)
250  {
251  unsigned n_value = spectral_data_pt(n)->nvalue();
252  if(n_value > max_n_value) {max_n_value = n_value;}
253  }
254 
255  //Resize the storage for the nodal local equation numbers
256  //initially all local equations are unclassified
257  Spectral_local_eqn.resize(n_spectral,max_n_value,Data::Is_unclassified);
258 
259  //Construct a set of pointers to the nodes
260  std::set<Data*> set_of_node_pt;
261  unsigned n_node = nnode();
262  for(unsigned n=0;n<n_node;n++) {set_of_node_pt.insert(node_pt(n));}
263 
264  //A local queue to store the global equation numbers
265  std::deque<unsigned long> global_eqn_number_queue;
266 
267  //Now loop over the nodes again and assign local equation numbers
268  for(unsigned n=0;n<n_spectral;n++)
269  {
270  //Need to find whether the data is, in fact a node
271  //(and hence already assigned)
272 
273  //Can we upcast to a node
274  Node* cast_node_pt = dynamic_cast<Node*>(spectral_data_pt(n));
275  if((cast_node_pt) &&
276  (set_of_node_pt.find(cast_node_pt)!=set_of_node_pt.end()))
277  {
278  //Find the number of values
279  unsigned n_value = cast_node_pt->nvalue();
280  //Copy them across
281  for(unsigned j=0;j<n_value;j++)
282  {
283  Spectral_local_eqn(n,j) =
284  nodal_local_eqn(get_node_number(cast_node_pt),j);
285  }
286  //Remove from the set
287  set_of_node_pt.erase(cast_node_pt);
288  }
289  //Otherwise it's just data
290  else
291  {
292  Data* const data_pt = spectral_data_pt(n);
293  unsigned n_value = data_pt->nvalue();
294  //Loop over the number of values
295  for(unsigned j=0;j<n_value;j++)
296  {
297  //Get the GLOBAL equation number
298  long eqn_number = data_pt->eqn_number(j);
299  //If the GLOBAL equation number is positive (a free variable)
300  if(eqn_number >= 0)
301  {
302  //Add the GLOBAL equation number to the
303  //local-to-global translation
304  //scheme
305  global_eqn_number_queue.push_back(eqn_number);
306  //Add pointer to the dof to the queue if required
307  if(store_local_dof_pt)
308  {
310  data_pt->value_pt(j));
311  }
312  //Add the local equation number to the local scheme
313  Spectral_local_eqn(n,j) = local_eqn_number;
314  //Increase the local number
315  local_eqn_number++;
316  }
317  else
318  {
319  //Set the local scheme to be pinned
320  Spectral_local_eqn(n,j) = Data::Is_pinned;
321  }
322  }
323  } //End of case when it's not a nodal dof
324  }
325 
326  //Now add our global equations numbers to the internal element storage
327  add_global_eqn_numbers(global_eqn_number_queue,
329  //Clear the memory used in the deque
330  if(store_local_dof_pt)
331  {std::deque<double*>().swap(GeneralisedElement::Dof_pt_deque);}
332 
333  } //End of case when there are spectral degrees of freedom
334  }
335 
336  unsigned nspectral() const
337  {
338  if(Spectral_data_pt==0) {return 0;}
339  else
340  {
341  return Spectral_data_pt->size();
342  }
343  }
344 
345 };
346 
347 
348 
349 //=======================================================================
350 ///General QLegendreElement class
351 ///
352 /// Empty, just establishes the template parameters
353 //=======================================================================
354 template<unsigned DIM, unsigned NNODE_1D>
356 {
357 };
358 
359 
360 //=======================================================================
361 ///General QSpectralElement class specialised to one spatial dimension
362 //=======================================================================
363 template<unsigned NNODE_1D>
364 class QSpectralElement<1,NNODE_1D> : public virtual SpectralElement,
365  public virtual LineElementBase
366 {
367  private:
368 
369  /// \short Default integration rule: Gaussian integration of same 'order'
370  /// as the element
371  //This is sort of optimal, because it means that the integration is exact
372  //for the shape functions. Can overwrite this in specific element defintion.
374 
375 public:
376 
377  /// Constructor
379  {
380  //There are NNODE_1D nodes in this element
381  this->set_n_node(NNODE_1D);
382  Spectral_order.resize(1,NNODE_1D);
383  Nodal_spectral_order.resize(1,NNODE_1D);
384  //Set the elemental and nodal dimensions
385  this->set_dimension(1);
386  //Assign integral point
387  this->set_integration_scheme(&integral);
388  //Calculate the nodal positions for the shape functions
390  //OneDLegendreShapeParam::calculate_nodal_positions(NNODE_1D);
391  }
392 
393  /// Min. value of local coordinate
394  double s_min() const {return -1.0;}
395 
396  /// Max. value of local coordinate
397  double s_max() const {return 1.0;}
398 
399  /// Number of vertex nodes in the element
400  unsigned nvertex_node() const
401  { return 2; }
402 
403  /// Pointer to the j-th vertex node in the element
404  Node* vertex_node_pt(const unsigned &j) const
405  {
406  unsigned n_node_1d = nnode_1d();
407  Node* nod_pt;
408  switch(j)
409  {
410  case 0:
411  nod_pt = this->node_pt(0);
412  break;
413  case 1:
414  nod_pt = this->node_pt(n_node_1d-1);
415  break;
416  default:
417  std::ostringstream error_message;
418  error_message << "Vertex node number is " << j <<
419  " but must be from 0 to 1\n";
420 
421  throw OomphLibError(error_message.str(),
422  OOMPH_CURRENT_FUNCTION,
423  OOMPH_EXCEPTION_LOCATION);
424  }
425  return nod_pt;
426  }
427 
428  /// Get local coordinates of node j in the element; vector sets its own size
429  void local_coordinate_of_node(const unsigned& n, Vector<double>& s) const
430  {
431  s.resize(1);
433  }
434 
435  /// Get the local fractino of node j in the element
436  void local_fraction_of_node(const unsigned &n, Vector<double> &s_fraction)
437  {
438  this->local_coordinate_of_node(n,s_fraction);
439  //Resize
440  s_fraction[0] = 0.5*(s_fraction[0] + 1.0);
441  }
442 
443  /// The local one-d fraction is the same
444  double local_one_d_fraction_of_node(const unsigned &n1d, const unsigned &i)
445  {
446  return
448  }
449 
450  /// Calculate the geometric shape functions at local coordinate s
451  inline void shape(const Vector<double> &s, Shape &psi) const;
452 
453  /// \short Compute the geometric shape functions and
454  /// derivatives w.r.t. local coordinates at local coordinate s
455  inline void dshape_local(const Vector<double> &s, Shape &psi, DShape &dpsids)
456  const;
457 
458  /// \short Compute the geometric shape functions, derivatives and
459  /// second derivatives w.r.t. local coordinates at local coordinate s
460  /// d2psids(i,0) = \f$ d^2 \psi_j / d s^2 \f$
461  inline void d2shape_local(const Vector<double> &s, Shape &psi, DShape &dpsids,
462  DShape &d2psids) const;
463 
464  /// \short Overload the template-free interface for the calculation of
465  /// inverse jacobian matrix. This is a one-dimensional element, so
466  /// use the 1D version.
468  DenseMatrix<double> &inverse_jacobian) const
469  {return FiniteElement::invert_jacobian<1>(jacobian,inverse_jacobian);}
470 
471 
472  /// Number of nodes along each element edge
473  unsigned nnode_1d() const {return NNODE_1D;}
474 
475  /// C-style output
476  void output(FILE* file_pt)
477  {FiniteElement::output(file_pt);}
478 
479  /// C_style output at n_plot points
480  void output(FILE* file_pt, const unsigned &n_plot)
481  {FiniteElement::output(file_pt,n_plot);}
482 
483  /// Output
484  void output(std::ostream &outfile);
485 
486  /// Output at n_plot points
487  void output(std::ostream &outfile, const unsigned &n_plot);
488 
489 /// \short Get cector of local coordinates of plot point i (when plotting
490  /// nplot points in each "coordinate direction).
492  const unsigned& i,
493  const unsigned& nplot,
494  Vector<double>& s,
495  const bool& use_equally_spaced_interior_sample_points=false) const
496  {
497  if (nplot>1)
498  {
499  s[0]=-1.0+2.0*double(i)/double(nplot-1);
500  if (use_equally_spaced_interior_sample_points)
501  {
502  double range=2.0;
503  double dx_new=range/double(nplot);
504  double range_new=double(nplot-1)*dx_new;
505  s[0]=-1.0+0.5*dx_new+range_new*(1.0+s[0])/range;
506  }
507  }
508  else
509  {
510  s[0]=0.0;
511  }
512  }
513 
514  /// \short Return string for tecplot zone header (when plotting
515  /// nplot points in each "coordinate direction)
516  std::string tecplot_zone_string(const unsigned& nplot) const
517  {
518  std::ostringstream header;
519  header << "ZONE I=" << nplot << "\n";
520  return header.str();
521  }
522 
523  /// \short Return total number of plot points (when plotting
524  /// nplot points in each "coordinate direction)
525  unsigned nplot_points(const unsigned& nplot) const
526  {
527  unsigned DIM=1;
528  unsigned np=1;
529  for (unsigned i=0;i<DIM;i++) {np*=nplot;}
530  return np;
531  }
532 
533  /// \short Build the lower-dimensional FaceElement (an element of type
534  /// QSpectralElement<0,NNODE_1D>). The face index takes two values
535  /// corresponding to the two possible faces:
536  /// -1 (Left) s[0] = -1.0
537  /// +1 (Right) s[0] = 1.0
538  void build_face_element(const int &face_index,
539  FaceElement* face_element_pt);
540 
541 };
542 
543 
544 //=======================================================================
545 ///Shape function for specific QSpectralElement<1,..>
546 //=======================================================================
547 template <unsigned NNODE_1D>
549  const
550 {
551  //Call the OneDimensional Shape functions
553  //OneDLegendreShapeParam psi1(NNODE_1D,s[0]);
554 
555  //Now let's loop over the nodal points in the element
556  //and copy the values back in
557  for(unsigned i=0;i<NNODE_1D;i++) {psi(i) = psi1[i];}
558 }
559 
560 //=======================================================================
561 ///Derivatives of shape functions for specific QSpectralElement<1,..>
562 //=======================================================================
563 template <unsigned NNODE_1D>
565  Shape &psi,
566  DShape &dpsids) const
567 {
568  //Call the shape functions and derivatives
571 
572  //OneDLegendreShapeParam psi1(NNODE_1D,s[0]);
573  //OneDLegendreDShapeParam dpsi1ds(NNODE_1D,s[0]);
574 
575  //Loop over shape functions in element and assign to psi
576  for(unsigned l=0;l<NNODE_1D;l++)
577  {
578  psi(l) = psi1[l];
579  dpsids(l,0) = dpsi1ds[l];
580  }
581 }
582 
583 //=======================================================================
584 /// Second derivatives of shape functions for specific QSpectralElement<1,..>
585 /// d2psids(i,0) = \f$ d^2 \psi_j / d s^2 \f$
586 //=======================================================================
587 template <unsigned NNODE_1D>
589  DShape &dpsids, DShape &d2psids) const
590 {
591  std::ostringstream error_message;
592  error_message <<"\nd2shpe_local currently not implemented for this element\n";
593  throw OomphLibError(error_message.str(),
594  OOMPH_CURRENT_FUNCTION,
595  OOMPH_EXCEPTION_LOCATION);
596 
597 /* //Call the shape functions and derivatives */
598 /* OneDimensionalShape<NNODE_1D> psi1(s[0]); */
599 /* OneDimensionalDShape<NNODE_1D> dpsi1ds(s[0]); */
600 /* OneDimensionalD2Shape<NNODE_1D> d2psi1ds(s[0]); */
601 
602 /* //Loop over shape functions in element and assign to psi */
603 /* for(unsigned l=0;l<NNODE_1D;l++) */
604 /* { */
605 /* psi[l] = psi1[l]; */
606 /* dpsids[l][0] = dpsi1ds[l]; */
607 /* d2psids[l][0] = d2psi1ds[l]; */
608 /* } */
609 }
610 
611 
612 //=======================================================================
613 ///General QSpectralElement class specialised to two spatial dimensions
614 //=======================================================================
615 template<unsigned NNODE_1D>
616 class QSpectralElement<2,NNODE_1D> : public virtual SpectralElement,
617  public virtual QuadElementBase
618 {
619  private:
620 
621  /// \short Default integration rule: Gaussian integration of same 'order'
622  /// as the element
623  //This is sort of optimal, because it means that the integration is exact
624  //for the shape functions. Can overwrite this in specific element defintion.
626 
627 public:
628 
629  /// Constructor
631  {
632  //There are NNODE_1D^2 nodes in this element
633  this->set_n_node(NNODE_1D*NNODE_1D);
634  Spectral_order.resize(2,NNODE_1D);
635  Nodal_spectral_order.resize(2,NNODE_1D);
636  //Set the elemental and nodal dimensions
637  this->set_dimension(2);
638  //Assign integral pointer
639  this->set_integration_scheme(&integral);
640  //Calculate the nodal positions for the shape functions
642  //OneDLegendreShapeParam::calculate_nodal_positions(NNODE_1D);
643  }
644 
645  /// Min. value of local coordinate
646  double s_min() const {return -1.0;}
647 
648  /// Max. value of local coordinate
649  double s_max() const {return 1.0;}
650 
651  /// Number of vertex nodes in the element
652  unsigned nvertex_node() const
653  { return 4;}
654 
655  /// Pointer to the j-th vertex node in the element
656  Node* vertex_node_pt(const unsigned &j) const
657  {
658  unsigned n_node_1d = nnode_1d();
659  Node* nod_pt;
660  switch(j)
661  {
662  case 0:
663  nod_pt = this->node_pt(0);
664  break;
665  case 1:
666  nod_pt = this->node_pt(n_node_1d-1);
667  break;
668  case 2:
669  nod_pt = this->node_pt(n_node_1d*(n_node_1d-1));
670  break;
671  case 3:
672  nod_pt = this->node_pt(n_node_1d*n_node_1d-1);
673  break;
674  default:
675  std::ostringstream error_message;
676  error_message << "Vertex node number is " << j <<
677  " but must be from 0 to 3\n";
678 
679  throw OomphLibError(error_message.str(),
680 OOMPH_CURRENT_FUNCTION,
681  OOMPH_EXCEPTION_LOCATION);
682  }
683  return nod_pt;
684  }
685 
686 
687  /// Get local coordinates of node j in the element; vector sets its own size
688  void local_coordinate_of_node(const unsigned& n, Vector<double>& s) const
689  {
690  s.resize(2);
691  unsigned n0 = n%NNODE_1D;
692  unsigned n1 = unsigned(double(n)/double(NNODE_1D));
695  }
696 
697  /// Get the local fractino of node j in the element
698  void local_fraction_of_node(const unsigned &n, Vector<double> &s_fraction)
699  {
700  this->local_coordinate_of_node(n,s_fraction);
701  //Resize
702  s_fraction[0] = 0.5*(s_fraction[0] + 1.0);
703  s_fraction[1] = 0.5*(s_fraction[1] + 1.0);
704  }
705 
706  /// The local one-d fraction is the same
707  double local_one_d_fraction_of_node(const unsigned &n1d, const unsigned &i)
708  {
709  return
711  }
712 
713  /// Calculate the geometric shape functions at local coordinate s
714  inline void shape(const Vector<double> &s, Shape &psi) const;
715 
716  /// \short Compute the geometric shape functions and
717  /// derivatives w.r.t. local coordinates at local coordinate s
718  inline void dshape_local(const Vector<double> &s, Shape &psi, DShape &dpsids)
719  const;
720 
721  /// \short Compute the geometric shape functions, derivatives and
722  /// second derivatives w.r.t. local coordinates at local coordinate s
723  /// d2psids(i,0) = \f$ \partial ^2 \psi_j / \partial s_0^2 \f$
724  /// d2psids(i,1) = \f$ \partial ^2 \psi_j / \partial s_1^2 \f$
725  /// d2psids(i,2) = \f$ \partial ^2 \psi_j / \partial s_0 \partial s_1 \f$
726  inline void d2shape_local(const Vector<double> &s, Shape &psi, DShape &dpsids,
727  DShape &d2psids) const;
728 
729  /// \short Overload the template-free interface for the calculation of
730  /// inverse jacobian matrix. This is a one-dimensional element, so
731  /// use the 1D version.
733  DenseMatrix<double> &inverse_jacobian) const
734  {return FiniteElement::invert_jacobian<2>(jacobian,inverse_jacobian);}
735 
736 
737  /// Number of nodes along each element edge
738  unsigned nnode_1d() const {return NNODE_1D;}
739 
740  /// C-style output
741  void output(FILE* file_pt)
742  {FiniteElement::output(file_pt);}
743 
744  /// C_style output at n_plot points
745  void output(FILE* file_pt, const unsigned &n_plot)
746  {FiniteElement::output(file_pt,n_plot);}
747 
748  /// Output
749  void output(std::ostream &outfile);
750 
751  /// Output at n_plot points
752  void output(std::ostream &outfile, const unsigned &n_plot);
753 
754 /// \short Get cector of local coordinates of plot point i (when plotting
755  /// nplot points in each "coordinate direction).
757  const unsigned& i,
758  const unsigned& nplot,
759  Vector<double>& s,
760  const bool& use_equally_spaced_interior_sample_points=false) const
761  {
762  if (nplot>1)
763  {
764  unsigned i0=i%nplot;
765  unsigned i1=(i-i0)/nplot;
766 
767  s[0]=-1.0+2.0*double(i0)/double(nplot-1);
768  s[1]=-1.0+2.0*double(i1)/double(nplot-1);
769  if (use_equally_spaced_interior_sample_points)
770  {
771  double range=2.0;
772  double dx_new=range/double(nplot);
773  double range_new=double(nplot-1)*dx_new;
774  s[0]=-1.0+0.5*dx_new+range_new*(1.0+s[0])/range;
775  s[1]=-1.0+0.5*dx_new+range_new*(1.0+s[1])/range;
776  }
777  }
778  else
779  {
780  s[0]=0.0;
781  s[1]=0.0;
782  }
783  }
784 
785 
786  /// \short Return string for tecplot zone header (when plotting
787  /// nplot points in each "coordinate direction)
788  std::string tecplot_zone_string(const unsigned& nplot) const
789  {
790  std::ostringstream header;
791  header << "ZONE I=" << nplot << ", J=" << nplot << "\n";
792  return header.str();
793  }
794 
795  /// \short Return total number of plot points (when plotting
796  /// nplot points in each "coordinate direction)
797  unsigned nplot_points(const unsigned& nplot) const
798  {
799  unsigned DIM=2;
800  unsigned np=1;
801  for (unsigned i=0;i<DIM;i++) {np*=nplot;}
802  return np;
803  }
804 
805  /// \short Build the lower-dimensional FaceElement (an element of type
806  /// QSpectralElement<1,NNODE_1D>). The face index takes four values
807  /// corresponding to the four possible faces:
808  /// -1 (West) s[0] = -1.0
809  /// +1 (East) s[0] = 1.0
810  /// -2 (South) s[1] = -1.0
811  /// +2 (North) s[1] = 1.0
812  void build_face_element(const int &face_index,
813  FaceElement* face_element_pt);
814 };
815 
816 
817 //=======================================================================
818 ///Shape function for specific QSpectralElement<2,..>
819 //=======================================================================
820 template <unsigned NNODE_1D>
822  const
823 {
824  //Call the OneDimensional Shape functions
825  OneDimensionalLegendreShape<NNODE_1D> psi1(s[0]), psi2(s[1]);
826  //OneDLegendreShapeParam psi1(NNODE_1D,s[0]), psi2(NNODE_1D,s[1]);
827 
828  //Now let's loop over the nodal points in the element
829  //and copy the values back in
830  for(unsigned i=0;i<NNODE_1D;i++)
831  {
832  for(unsigned j=0;j<NNODE_1D;j++)
833  {
834  psi(NNODE_1D*i + j) = psi2[i]*psi1[j];
835  }
836  }
837 }
838 
839 //=======================================================================
840 ///Derivatives of shape functions for specific QSpectralElement<2,..>
841 //=======================================================================
842 template <unsigned NNODE_1D>
844  Shape &psi,
845  DShape &dpsids) const
846 {
847  //Call the shape functions and derivatives
848  OneDimensionalLegendreShape<NNODE_1D> psi1(s[0]), psi2(s[1]);
849  OneDimensionalLegendreDShape<NNODE_1D> dpsi1ds(s[0]), dpsi2ds(s[1]);
850 
851  //OneDLegendreShapeParam psi1(NNODE_1D,s[0]), psi2(NNODE_1D,s[1]);
852  //OneDLegendreDShapeParam dpsi1ds(NNODE_1D,s[0]), dpsi2ds(NNODE_1D,s[1]);
853 
854  //Index for the shape functions
855  unsigned index=0;
856  //Loop over shape functions in element
857  for(unsigned i=0;i<NNODE_1D;i++)
858  {
859  for(unsigned j=0;j<NNODE_1D;j++)
860  {
861  //Assign the values
862  dpsids(index,0) = psi2[i]*dpsi1ds[j];
863  dpsids(index,1) = dpsi2ds[i]*psi1[j];
864  psi[index] = psi2[i]*psi1[j];
865  //Increment the index
866  ++index;
867  }
868  }
869 }
870 
871 
872 //=======================================================================
873 ///Second derivatives of shape functions for specific QSpectralElement<2,..>
874 /// d2psids(i,0) = \f$ \partial ^2 \psi_j / \partial s_0^2 \f$
875 /// d2psids(i,1) = \f$ \partial ^2 \psi_j / \partial s_1^2 \f$
876 /// d2psids(i,2) = \f$ \partial ^2 \psi_j / \partial s_0 \partial s_1 \f$
877 //=======================================================================
878 template <unsigned NNODE_1D>
880  DShape &dpsids, DShape &d2psids) const
881 {
882  std::ostringstream error_message;
883  error_message <<"\nd2shpe_local currently not implemented for this element\n";
884  throw OomphLibError(error_message.str(),
885  OOMPH_CURRENT_FUNCTION,
886  OOMPH_EXCEPTION_LOCATION);
887 
888 /* //Call the shape functions and derivatives */
889 /* OneDimensionalShape<NNODE_1D> psi1(s[0]); */
890 /* OneDimensionalDShape<NNODE_1D> dpsi1ds(s[0]); */
891 /* OneDimensionalD2Shape<NNODE_1D> d2psi1ds(s[0]); */
892 
893 /* //Loop over shape functions in element and assign to psi */
894 /* for(unsigned l=0;l<NNODE_1D;l++) */
895 /* { */
896 /* psi[l] = psi1[l]; */
897 /* dpsids[l][0] = dpsi1ds[l]; */
898 /* d2psids[l][0] = d2psi1ds[l]; */
899 /* } */
900 }
901 
902 
903 //=======================================================================
904 ///General QSpectralElement class specialised to three spatial dimensions
905 //=======================================================================
906 template<unsigned NNODE_1D>
907 class QSpectralElement<3,NNODE_1D> : public virtual SpectralElement,
908  public virtual BrickElementBase
909 {
910  private:
911 
912  /// \short Default integration rule: Gaussian integration of same 'order'
913  /// as the element
914  //This is sort of optimal, because it means that the integration is exact
915  //for the shape functions. Can overwrite this in specific element defintion.
917 
918 public:
919 
920  /// Constructor
922  {
923  //There are NNODE_1D^3 nodes in this element
924  this->set_n_node(NNODE_1D*NNODE_1D*NNODE_1D);
925  Spectral_order.resize(3,NNODE_1D);
926  Nodal_spectral_order.resize(3,NNODE_1D);
927  //Set the elemental and nodal dimensions
928  this->set_dimension(3);
929  //Assign integral point
930  this->set_integration_scheme(&integral);
931  //Calculate the nodal positions for the shape functions
933  //OneDLegendreShapeParam::calculate_nodal_positions(NNODE_1D);
934  }
935 
936  /// Min. value of local coordinate
937  double s_min() const {return -1.0;}
938 
939  /// Max. value of local coordinate
940  double s_max() const {return 1.0;}
941 
942  /// Number of vertex nodes in the element
943  unsigned nvertex_node() const
944  { return 8;}
945 
946  /// Pointer to the j-th vertex node in the element
947  Node* vertex_node_pt(const unsigned &j) const
948  {
949  unsigned n_node_1d = nnode_1d();
950  Node* nod_pt;
951  switch(j)
952  {
953  case 0:
954  nod_pt = this->node_pt(0);
955  break;
956  case 1:
957  nod_pt=this->node_pt(n_node_1d-1);
958  break;
959  case 2:
960  nod_pt=this->node_pt(n_node_1d*(n_node_1d-1));
961  break;
962  case 3:
963  nod_pt=this->node_pt(n_node_1d*n_node_1d-1);
964  break;
965  case 4:
966  nod_pt=this->node_pt(n_node_1d*n_node_1d*(n_node_1d-1));
967  break;
968  case 5:
969  nod_pt=this->node_pt(n_node_1d*n_node_1d*(n_node_1d-1)+(n_node_1d-1));
970  break;
971  case 6:
972  nod_pt=this->node_pt(n_node_1d*n_node_1d*n_node_1d-n_node_1d);
973  break;
974  case 7:
975  nod_pt=this->node_pt(n_node_1d*n_node_1d*n_node_1d-1);
976  break;
977  default:
978  std::ostringstream error_message;
979  error_message << "Vertex node number is " << j <<
980  " but must be from 0 to 7\n";
981 
982  throw OomphLibError(error_message.str(),
983 OOMPH_CURRENT_FUNCTION,
984  OOMPH_EXCEPTION_LOCATION);
985  }
986  return nod_pt;
987  }
988 
989 
990  /// Get local coordinates of node j in the element; vector sets its own size
991  void local_coordinate_of_node(const unsigned& n, Vector<double>& s) const
992  {
993  s.resize(3);
994  unsigned n0 = n%NNODE_1D;
995  unsigned n1 = unsigned(double(n)/double(NNODE_1D))%NNODE_1D;
996  unsigned n2 = unsigned(double(n)/double(NNODE_1D*NNODE_1D));
1000  }
1001 
1002  /// Get the local fractino of node j in the element
1003  void local_fraction_of_node(const unsigned &n, Vector<double> &s_fraction)
1004  {
1005  this->local_coordinate_of_node(n,s_fraction);
1006  //Resize
1007  s_fraction[0] = 0.5*(s_fraction[0] + 1.0);
1008  s_fraction[1] = 0.5*(s_fraction[1] + 1.0);
1009  s_fraction[2] = 0.5*(s_fraction[2] + 1.0);
1010  }
1011 
1012  /// The local one-d fraction is the same
1013  double local_one_d_fraction_of_node(const unsigned &n1d, const unsigned &i)
1014  {
1015  return
1017  }
1018 
1019  /// Calculate the geometric shape functions at local coordinate s
1020  inline void shape(const Vector<double> &s, Shape &psi) const;
1021 
1022  /// \short Compute the geometric shape functions and
1023  /// derivatives w.r.t. local coordinates at local coordinate s
1024  inline void dshape_local(const Vector<double> &s, Shape &psi, DShape &dpsids)
1025  const;
1026 
1027  /// \short Compute the geometric shape functions, derivatives and
1028  /// second derivatives w.r.t. local coordinates at local coordinate s
1029  /// d2psids(i,0) = \f$ \partial ^2 \psi_j / \partial s_0^2 \f$
1030  /// d2psids(i,1) = \f$ \partial ^2 \psi_j / \partial s_1^2 \f$
1031  /// d2psids(i,2) = \f$ \partial ^2 \psi_j / \partial s_2^2 \f$
1032  /// d2psids(i,3) = \f$ \partial ^2 \psi_j / \partial s_0 \partial s_1 \f$
1033  /// d2psids(i,4) = \f$ \partial ^2 \psi_j / \partial s_0 \partial s_2 \f$
1034  /// d2psids(i,5) = \f$ \partial ^2 \psi_j / \partial s_1 \partial s_2 \f$
1035  inline void d2shape_local(const Vector<double> &s, Shape &psi, DShape &dpsids,
1036  DShape &d2psids) const;
1037 
1038 
1039  /// \short Overload the template-free interface for the calculation of
1040  /// inverse jacobian matrix. This is a one-dimensional element, so
1041  /// use the 3D version.
1043  DenseMatrix<double> &inverse_jacobian) const
1044  {return FiniteElement::invert_jacobian<3>(jacobian,inverse_jacobian);}
1045 
1046  /// Number of nodes along each element edge
1047  unsigned nnode_1d() const {return NNODE_1D;}
1048 
1049  /// C-style output
1050  void output(FILE* file_pt)
1051  {FiniteElement::output(file_pt);}
1052 
1053  /// C_style output at n_plot points
1054  void output(FILE* file_pt, const unsigned &n_plot)
1055  {FiniteElement::output(file_pt,n_plot);}
1056 
1057  /// Output
1058  void output(std::ostream &outfile);
1059 
1060  /// Output at nplot points
1061  void output(std::ostream &outfile, const unsigned& nplot);
1062 
1063 /// \short Get cector of local coordinates of plot point i (when plotting
1064  /// nplot points in each "coordinate direction).
1066  const unsigned& i,
1067  const unsigned& nplot,
1068  Vector<double>& s,
1069  const bool& use_equally_spaced_interior_sample_points=false) const
1070  {
1071  if (nplot>1)
1072  {
1073  unsigned i01=i%(nplot*nplot);
1074  unsigned i0=i01%nplot;
1075  unsigned i1=(i01-i0)/nplot;
1076  unsigned i2=(i-i01)/(nplot*nplot);
1077 
1078  s[0]=-1.0+2.0*double(i0)/double(nplot-1);
1079  s[1]=-1.0+2.0*double(i1)/double(nplot-1);
1080  s[2]=-1.0+2.0*double(i2)/double(nplot-1);
1081  if (use_equally_spaced_interior_sample_points)
1082  {
1083  double range=2.0;
1084  double dx_new=range/double(nplot);
1085  double range_new=double(nplot-1)*dx_new;
1086  s[0]=-1.0+0.5*dx_new+range_new*(1.0+s[0])/range;
1087  s[1]=-1.0+0.5*dx_new+range_new*(1.0+s[1])/range;
1088  s[2]=-1.0+0.5*dx_new+range_new*(1.0+s[2])/range;
1089 
1090  }
1091  }
1092  else
1093  {
1094  s[0]=0.0;
1095  s[1]=0.0;
1096  s[2]=0.0;
1097  }
1098  }
1099 
1100 
1101  /// \short Return string for tecplot zone header (when plotting
1102  /// nplot points in each "coordinate direction)
1103  std::string tecplot_zone_string(const unsigned& nplot) const
1104  {
1105  std::ostringstream header;
1106  header << "ZONE I=" << nplot << ", J=" << nplot << ", K="
1107  << nplot << "\n";
1108  return header.str();
1109  }
1110 
1111  /// \short Return total number of plot points (when plotting
1112  /// nplot points in each "coordinate direction)
1113  unsigned nplot_points(const unsigned& nplot) const
1114  {
1115  unsigned DIM=3;
1116  unsigned np=1;
1117  for (unsigned i=0;i<DIM;i++) {np*=nplot;}
1118  return np;
1119  }
1120 
1121  /// \short Build the lower-dimensional FaceElement (an element of type
1122  /// QSpectralElement<2,NNODE_1D>). The face index takes six values
1123  /// corresponding to the six possible faces:
1124  /// -1 (Left) s[0] = -1.0
1125  /// +1 (Right) s[0] = 1.0
1126  /// -2 (Down) s[1] = -1.0
1127  /// +2 (Up) s[1] = 1.0
1128  /// -3 (Back) s[2] = -1.0
1129  /// +3 (Front) s[2] = 1.0
1130  void build_face_element(const int &face_index,
1131  FaceElement* face_element_pt);
1132 };
1133 
1134 
1135 //=======================================================================
1136 ///Shape function for specific QSpectralElement<3,..>
1137 //=======================================================================
1138 template <unsigned NNODE_1D>
1140  const
1141 {
1142  //Call the OneDimensional Shape functions
1143  OneDimensionalLegendreShape<NNODE_1D> psi1(s[0]), psi2(s[1]), psi3(s[2]);
1144  //OneDLegendreShapeParam psi1(NNODE_1D,s[0]), psi2(NNODE_1D,s[1]),
1145  // psi3(NNODE_1D,s[2]);
1146 
1147  //Now let's loop over the nodal points in the element
1148  //and copy the values back in
1149  for(unsigned i=0;i<NNODE_1D;i++)
1150  {
1151  for(unsigned j=0;j<NNODE_1D;j++)
1152  {
1153  for(unsigned k=0;k<NNODE_1D;k++)
1154  {
1155  psi(NNODE_1D*NNODE_1D*i + NNODE_1D*j + k) = psi3[i]*psi2[j]*psi1[k];
1156  }
1157  }
1158  }
1159 }
1160 
1161 //=======================================================================
1162 ///Derivatives of shape functions for specific QSpectralElement<3,..>
1163 //=======================================================================
1164 template <unsigned NNODE_1D>
1166  Shape &psi,
1167  DShape &dpsids) const
1168 {
1169  //Call the shape functions and derivatives
1170  //OneDLegendreShapeParam psi1(NNODE_1D,s[0]), psi2(NNODE_1D,s[1]),
1171  // psi3(NNODE_1D,s[2]);
1172  //OneDLegendreDShapeParam dpsi1ds(NNODE_1D,s[0]), dpsi2ds(NNODE_1D,s[1]),
1173  // dpsi3ds(NNODE_1D,s[2]);
1174  OneDimensionalLegendreShape<NNODE_1D> psi1(s[0]), psi2(s[1]), psi3(s[2]);
1175  OneDimensionalLegendreDShape<NNODE_1D> dpsi1ds(s[0]), dpsi2ds(s[1]),
1176  dpsi3ds(s[2]);
1177 
1178 
1179  //Index for the shape functions
1180  unsigned index=0;
1181 
1182  //Loop over shape functions in element
1183  for(unsigned i=0;i<NNODE_1D;i++)
1184  {
1185  for(unsigned j=0;j<NNODE_1D;j++)
1186  {
1187  for(unsigned k=0;k<NNODE_1D;k++)
1188  {
1189  //Assign the values
1190  dpsids(index,0) = psi3[i]*psi2[j]*dpsi1ds[k];
1191  dpsids(index,1) = psi3[i]*dpsi2ds[j]*psi1[k];
1192  dpsids(index,2) = dpsi3ds[i]*psi2[j]*psi1[k];
1193  psi[index] = psi3[i]*psi2[j]*psi1[k];
1194  //Increment the index
1195  ++index;
1196  }
1197  }
1198  }
1199 }
1200 
1201 
1202 //=======================================================================
1203 ///Second derivatives of shape functions for specific QSpectralElement<3,..>
1204 /// d2psids(i,0) = \f$ \partial ^2 \psi_j / \partial s_0^2 \f$
1205 /// d2psids(i,1) = \f$ \partial ^2 \psi_j / \partial s_1^2 \f$
1206 /// d2psids(i,2) = \f$ \partial ^2 \psi_j / \partial s_2^2 \f$
1207 /// d2psids(i,3) = \f$ \partial ^2 \psi_j / \partial s_0 \partial s_1 \f$
1208 /// d2psids(i,4) = \f$ \partial ^2 \psi_j / \partial s_0 \partial s_2 \f$
1209 /// d2psids(i,5) = \f$ \partial ^2 \psi_j / \partial s_1 \partial s_2 \f$
1210 //=======================================================================
1211 template <unsigned NNODE_1D>
1213  DShape &dpsids, DShape &d2psids) const
1214 {
1215  std::ostringstream error_message;
1216  error_message <<"\nd2shpe_local currently not implemented for this element\n";
1217  throw OomphLibError(error_message.str(),
1218  OOMPH_CURRENT_FUNCTION,
1219  OOMPH_EXCEPTION_LOCATION);
1220 
1221 /* //Call the shape functions and derivatives */
1222 /* OneDimensionalShape<NNODE_1D> psi1(s[0]); */
1223 /* OneDimensionalDShape<NNODE_1D> dpsi1ds(s[0]); */
1224 /* OneDimensionalD2Shape<NNODE_1D> d2psi1ds(s[0]); */
1225 
1226 /* //Loop over shape functions in element and assign to psi */
1227 /* for(unsigned l=0;l<NNODE_1D;l++) */
1228 /* { */
1229 /* psi[l] = psi1[l]; */
1230 /* dpsids[l][0] = dpsi1ds[l]; */
1231 /* d2psids[l][0] = d2psi1ds[l]; */
1232 /* } */
1233 }
1234 
1235 //==============================================================
1236 /// A class that is used to template the refineable Q spectral elements
1237 /// by dimension. It's really nothing more than a policy class
1238 //=============================================================
1239 template<unsigned DIM>
1241 {
1242  public:
1243 
1244  /// Empty constuctor
1246 };
1247 
1248 }
1249 
1250 #endif
void local_fraction_of_node(const unsigned &n, Vector< double > &s_fraction)
Get the local fractino of node j in the element.
double local_one_d_fraction_of_node(const unsigned &n1d, const unsigned &i)
The local one-d fraction is the same.
static GaussLobattoLegendre< 2, NNODE_1D > integral
Default integration rule: Gaussian integration of same &#39;order&#39; as the element.
void get_s_plot(const unsigned &i, const unsigned &nplot, Vector< double > &s, const bool &use_equally_spaced_interior_sample_points=false) const
Get cector of local coordinates of plot point i (when plotting.
Base class for all line elements.
Definition: Qelements.h:492
unsigned nvertex_node() const
Number of vertex nodes in the element.
virtual void assign_all_generic_local_eqn_numbers(const bool &store_local_dof_pt)
Overloaded version of the calculation of the local equation numbers. If the boolean argument is true ...
Definition: elements.h:2099
double dlegendre(const unsigned &p, const double &x)
Calculates first derivative of Legendre polynomial of degree p at x using three term recursive formul...
Definition: orthpoly.h:118
unsigned nvertex_node() const
Number of vertex nodes in the element.
double invert_jacobian_mapping(const DenseMatrix< double > &jacobian, DenseMatrix< double > &inverse_jacobian) const
Overload the template-free interface for the calculation of inverse jacobian matrix. This is a one-dimensional element, so use the 3D version.
unsigned nplot_points(const unsigned &nplot) const
Return total number of plot points (when plotting nplot points in each "coordinate direction) ...
virtual void output(std::ostream &outfile)
Output the element data — typically the values at the nodes in a format suitable for post-processing...
Definition: elements.h:2884
double invert_jacobian_mapping(const DenseMatrix< double > &jacobian, DenseMatrix< double > &inverse_jacobian) const
Overload the template-free interface for the calculation of inverse jacobian matrix. This is a one-dimensional element, so use the 1D version.
DenseMatrix< int > Spectral_local_eqn
Local equation numbers for the spectral degrees of freedom.
cstr elem_len * i
Definition: cfortran.h:607
double * value_pt(const unsigned &i) const
Return the pointer to the i-the stored value. Typically this is required when direct access to the st...
Definition: nodes.h:322
double s_min() const
Min. value of local coordinate.
unsigned nspectral() const
Base class for all brick elements.
Definition: Qelements.h:1184
virtual void describe_local_dofs(std::ostream &out, const std::string &current_string) const
Function to describe the local dofs of the element[s]. The ostream specifies the output stream to whi...
Definition: elements.cc:1682
static GaussLobattoLegendre< 3, NNODE_1D > integral
Default integration rule: Gaussian integration of same &#39;order&#39; as the element.
double s_max() const
Max. value of local coordinate.
A general Finite Element class.
Definition: elements.h:1274
double s_max() const
Max. value of local coordinate.
unsigned nplot_points(const unsigned &nplot) const
Return total number of plot points (when plotting nplot points in each "coordinate direction) ...
static std::map< unsigned, Vector< double > > z
double legendre(const unsigned &p, const double &x)
Calculates Legendre polynomial of degree p at x using the three term recurrence relation ...
Definition: orthpoly.h:62
double s_max() const
Max. value of local coordinate.
Nodes are derived from Data, but, in addition, have a definite (Eulerian) position in a space of a gi...
Definition: nodes.h:852
double invert_jacobian_mapping(const DenseMatrix< double > &jacobian, DenseMatrix< double > &inverse_jacobian) const
Overload the template-free interface for the calculation of inverse jacobian matrix. This is a one-dimensional element, so use the 1D version.
static double nodal_position(const unsigned &n)
Definition: shape.h:768
long & eqn_number(const unsigned &i)
Return the equation number of the i-th stored variable.
Definition: nodes.h:365
OneDLegendreShapeParam(const unsigned &order, const double &s)
Constructor.
unsigned nvalue() const
Return number of values stored in data object (incl pinned ones).
Definition: nodes.h:448
virtual void describe_dofs(std::ostream &out, const std::string &current_string) const
Function to describe the dofs of the Node. The ostream specifies the output stream to which the descr...
Definition: nodes.cc:905
unsigned nnode_1d() const
Number of nodes along each element edge.
void local_coordinate_of_node(const unsigned &n, Vector< double > &s) const
Get local coordinates of node j in the element; vector sets its own size.
RefineableQSpectralElement()
Empty constuctor.
virtual void assign_all_generic_local_eqn_numbers(const bool &store_local_dof_pt)
Assign the local equation numbers. If the boolean argument is true then store degrees of freedom at D...
Node * vertex_node_pt(const unsigned &j) const
Pointer to the j-th vertex node in the element.
double local_one_d_fraction_of_node(const unsigned &n1d, const unsigned &i)
The local one-d fraction is the same.
void local_fraction_of_node(const unsigned &n, Vector< double > &s_fraction)
Get the local fractino of node j in the element.
Node * vertex_node_pt(const unsigned &j) const
Pointer to the j-th vertex node in the element.
Base class for all quad elements.
Definition: Qelements.h:821
virtual void describe_local_dofs(std::ostream &out, const std::string &current_string) const
Function to describe the local dofs of the element. The ostream specifies the output stream to which ...
void gll_nodes(const unsigned &Nnode, Vector< double > &x)
Calculates the Gauss Lobatto Legendre abscissas for degree p = NNode-1.
Definition: orthpoly.cc:38
void local_coordinate_of_node(const unsigned &n, Vector< double > &s) const
Get local coordinates of node j in the element; vector sets its own size.
Class that returns the shape functions associated with legendre.
double local_one_d_fraction_of_node(const unsigned &n1d, const unsigned &i)
The local one-d fraction is the same.
double ddlegendre(const unsigned &p, const double &x)
Calculates second derivative of Legendre polynomial of degree p at x using three term recursive formu...
Definition: orthpoly.h:137
void output(FILE *file_pt, const unsigned &n_plot)
C_style output at n_plot points.
double s_min() const
Min. value of local coordinate.
static long Is_pinned
Static "Magic number" used in place of the equation number to indicate that the value is pinned...
Definition: nodes.h:192
double s_min() const
Min. value of local coordinate.
unsigned nnode_1d() const
Number of nodes along each element edge.
static char t char * s
Definition: cfortran.h:572
Vector< unsigned > Spectral_order
Vector that represents the spectral order in each dimension.
std::string tecplot_zone_string(const unsigned &nplot) const
Return string for tecplot zone header (when plotting nplot points in each "coordinate direction) ...
Node * vertex_node_pt(const unsigned &j) const
Pointer to the j-th vertex node in the element.
void get_s_plot(const unsigned &i, const unsigned &nplot, Vector< double > &s, const bool &use_equally_spaced_interior_sample_points=false) const
Get cector of local coordinates of plot point i (when plotting.
OneDLegendreDShapeParam(const unsigned &order, const double &s)
A class that represents a collection of data; each Data object may contain many different individual ...
Definition: nodes.h:89
unsigned nplot_points(const unsigned &nplot) const
Return total number of plot points (when plotting nplot points in each "coordinate direction) ...
unsigned nnode_1d() const
Number of nodes along each element edge.
Vector< unsigned > Nodal_spectral_order
Vector that represents the nodal spectral order.
Data * spectral_data_pt(const unsigned &i) const
Return the i-th data object associated with the polynomials of order p. Note that i <= p...
static GaussLobattoLegendre< 1, NNODE_1D > integral
Default integration rule: Gaussian integration of same &#39;order&#39; as the element.
void get_s_plot(const unsigned &i, const unsigned &nplot, Vector< double > &s, const bool &use_equally_spaced_interior_sample_points=false) const
Get cector of local coordinates of plot point i (when plotting.
void local_coordinate_of_node(const unsigned &n, Vector< double > &s) const
Get local coordinates of node j in the element; vector sets its own size.
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.
void output(FILE *file_pt, const unsigned &n_plot)
C_style output at n_plot points.
void output(FILE *file_pt)
C-style output.
void output(FILE *file_pt)
C-style output.
static void calculate_nodal_positions(const unsigned &order)
Static function used to populate the stored positions.
std::string string(const unsigned &i)
Return the i-th string or "" if the relevant string hasn&#39;t been defined.
static long Is_unclassified
Static "Magic number" used in place of the equation number to denote a value that hasn&#39;t been classif...
Definition: nodes.h:201
static void calculate_nodal_positions()
Static function used to populate the stored positions.
Definition: shape.h:759
static std::deque< double * > Dof_pt_deque
Static storage for deque used to add_global_equation_numbers when pointers to the dofs in each elemen...
Definition: elements.h:232
std::string tecplot_zone_string(const unsigned &nplot) const
Return string for tecplot zone header (when plotting nplot points in each "coordinate direction) ...
void local_fraction_of_node(const unsigned &n, Vector< double > &s_fraction)
Get the local fractino of node j in the element.
void output(FILE *file_pt)
C-style output.
void output(FILE *file_pt, const unsigned &n_plot)
C_style output at n_plot points.
Vector< Data * > * Spectral_data_pt
Additional Storage for shared spectral data.
const double eps
Definition: orthpoly.h:57
std::string tecplot_zone_string(const unsigned &nplot) const
Return string for tecplot zone header (when plotting nplot points in each "coordinate direction) ...
unsigned nvertex_node() const
Number of vertex nodes in the element.
Class that returns the shape functions associated with legendre.
Definition: shape.h:751
static double nodal_position(const unsigned &order, const unsigned &n)
void resize(const unsigned long &n)
Definition: matrices.h:511