refineable_spherical_navier_stokes_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: 1097 $
7 //LIC//
8 //LIC// $LastChangedDate: 2015-12-17 11:53:17 +0000 (Thu, 17 Dec 2015) $
9 //LIC//
10 //LIC// Copyright (C) 2006-2016 Matthias Heil and Andrew Hazel
11 //LIC//
12 //LIC// This library is free software; you can redistribute it and/or
13 //LIC// modify it under the terms of the GNU Lesser General Public
14 //LIC// License as published by the Free Software Foundation; either
15 //LIC// version 2.1 of the License, or (at your option) any later version.
16 //LIC//
17 //LIC// This library is distributed in the hope that it will be useful,
18 //LIC// but WITHOUT ANY WARRANTY; without even the implied warranty of
19 //LIC// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
20 //LIC// Lesser General Public License for more details.
21 //LIC//
22 //LIC// You should have received a copy of the GNU Lesser General Public
23 //LIC// License along with this library; if not, write to the Free Software
24 //LIC// Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA
25 //LIC// 02110-1301 USA.
26 //LIC//
27 //LIC// The authors may be contacted at oomph-lib@maths.man.ac.uk.
28 //LIC//
29 //LIC//====================================================================
30 //Header file for refineable axisymmetric quad Navier Stokes elements
31 #ifndef OOMPH_REFINEABLE_SPHERICAL_NAVIER_STOKES_ELEMENTS_HEADER
32 #define OOMPH_REFINEABLE_SPHERICAL_NAVIER_STOKES_ELEMENTS_HEADER
33 
34 // Config header generated by autoconfig
35 #ifdef HAVE_CONFIG_H
36 #include <oomph-lib-config.h>
37 #endif
38 
39 //Oomph lib includes
40 #include "../generic/refineable_quad_element.h"
41 #include "../generic/error_estimator.h"
43 
44 namespace oomph
45 {
46 
47 
48 //======================================================================
49 ///Refineable version of the Spherical Navier--Stokes equations
50 //======================================================================
52 public virtual SphericalNavierStokesEquations,
53 public virtual RefineableElement,
54 public virtual ElementWithZ2ErrorEstimator
55 {
56  protected:
57 
58  /// \short Pointer to n_p-th pressure node (Default: NULL,
59  /// indicating that pressure is not based on nodal interpolation).
60  virtual Node* pressure_node_pt(const unsigned& n_p) {return NULL;}
61 
62  /// \short Unpin all pressure dofs in the element
63  virtual void unpin_elemental_pressure_dofs()=0;
64 
65 /// \short Pin unused nodal pressure dofs (empty by default, because
66  /// by default pressure dofs are not associated with nodes)
68 
69  public:
70 
71  /// \short Empty Constructor
76 
77  /// Number of 'flux' terms for Z2 error estimation
78  unsigned num_Z2_flux_terms()
79  {
80  // 3 diagonal strain rates, 3 off diagonal
81  return 6;
82  }
83 
84  /// \short Get 'flux' for Z2 error recovery: Upper triangular entries
85  /// in strain rate tensor.
87  {
88  //Specify the number of velocity dimensions
89  unsigned DIM=3;
90 #ifdef PARANOID
91  unsigned num_entries=DIM+((DIM*DIM)-DIM)/2;
92  if (flux.size() < num_entries)
93  {
94  std::ostringstream error_message;
95  error_message << "The flux vector is too small, size "
96  << flux.size() << ", whereas it should be "
97  << num_entries << std::endl;
98  throw OomphLibError(
99  error_message.str(),
100  OOMPH_CURRENT_FUNCTION,
101  OOMPH_EXCEPTION_LOCATION);
102  }
103 #endif
104  // Get strain rate matrix
105  DenseMatrix<double> strainrate(DIM);
106  this->strain_rate(s,strainrate);
107 
108  // Pack into flux Vector
109  unsigned icount=0;
110 
111  // Start with diagonal terms
112  for(unsigned i=0;i<DIM;i++)
113  {
114  flux[icount]=strainrate(i,i);
115  icount++;
116  }
117 
118  //Off diagonals row by row
119  for(unsigned i=0;i<DIM;i++)
120  {
121  for(unsigned j=i+1;j<DIM;j++)
122  {
123  flux[icount]=strainrate(i,j);
124  icount++;
125  }
126  }
127  }
128 
129  /// Fill in the geometric Jacobian, which in this case is r*r*sin(theta)
131  {return x[0]*x[0]*sin(x[1]);}
132 
133 
134  /// Further build: pass the pointers down to the sons
136  {
137  //Find the father element
138  RefineableSphericalNavierStokesEquations* cast_father_element_pt
140  (this->father_element_pt());
141 
142  //Set the viscosity ratio pointer
143  this->Viscosity_Ratio_pt = cast_father_element_pt->viscosity_ratio_pt();
144  //Set the density ratio pointer
145  this->Density_Ratio_pt = cast_father_element_pt->density_ratio_pt();
146  //Set pointer to global Reynolds number
147  this->Re_pt = cast_father_element_pt->re_pt();
148  //Set pointer to global Reynolds number x Strouhal number (=Womersley)
149  this->ReSt_pt = cast_father_element_pt->re_st_pt();
150  //Set pointer to the global Reynolds number x inverse Rossby number
151  this->ReInvRo_pt = cast_father_element_pt->re_invro_pt();
152  //Set pointer to global Reynolds number x inverse Froude number
153  this->ReInvFr_pt = cast_father_element_pt->re_invfr_pt();
154  //Set pointer to global gravity Vector
155  this->G_pt = cast_father_element_pt->g_pt();
156 
157  //Set pointer to body force function
158  this->Body_force_fct_pt = cast_father_element_pt->body_force_fct_pt();
159 
160  //Set pointer to volumetric source function
161  this->Source_fct_pt = cast_father_element_pt->source_fct_pt();
162 
163  //Set the ALE flag
164  this->ALE_is_disabled = cast_father_element_pt->ALE_is_disabled;
165  }
166 
167  /// \short Loop over all elements in Vector (which typically contains
168  /// all the elements in a fluid mesh) and pin the nodal pressure degrees
169  /// of freedom that are not being used. Function uses
170  /// the member function
171  /// - \c RefineableSphericalNavierStokesEquations::
172  /// pin_all_nodal_pressure_dofs()
173  /// .
174  /// which is empty by default and should be implemented for
175  /// elements with nodal pressure degrees of freedom
176  /// (e.g. for refineable Taylor-Hood.)
178  element_pt)
179  {
180  // Loop over all elements to brutally pin all nodal pressure degrees of
181  // freedom
182  unsigned n_element=element_pt.size();
183  for(unsigned e=0;e<n_element;e++)
184  {
187  }
188  }
189 
190  /// \short Unpin all pressure dofs in elements listed in vector.
192  element_pt)
193  {
194  // Loop over all elements to brutally unpin all nodal pressure degrees of
195  // freedom and internal pressure degrees of freedom
196  unsigned n_element = element_pt.size();
197  for(unsigned e=0;e<n_element;e++)
198  {
200  (element_pt[e])->unpin_elemental_pressure_dofs();
201  }
202  }
203 
204 
205  private:
206 
207  /// \short Add element's contribution to the elemental residual vector
208  /// and/or Jacobian matrix
209  /// flag=1: compute both
210  /// flag=0: compute only residual vector
212  Vector<double> &residuals,
213  DenseMatrix<double> &jacobian,
214  DenseMatrix<double> &mass_matrix,
215  unsigned flag);
216 
217 };
218 
219 //======================================================================
220 /// Refineable version of Spherical Quad Taylor Hood elements.
221 /// (note that unlike the cartesian version this is not scale-able
222 /// to higher dimensions!)
223 //======================================================================
227 public virtual RefineableQElement<2>
228 {
229  private:
230 
231  /// \short Pointer to n_p-th pressure node
232  Node* pressure_node_pt(const unsigned &n_p)
233  {return this->node_pt(this->Pconv[n_p]);}
234 
235  /// Unpin all pressure dofs
237  {
238  unsigned n_node = this->nnode();
239  int p_index = this->p_nodal_index_spherical_nst();
240  // loop over nodes
241  for(unsigned n=0;n<n_node;n++) {this->node_pt(n)->unpin(p_index);}
242  }
243 
244  /// Unpin the proper nodal pressure dofs
246  {
247  //Loop over all nodes
248  unsigned n_node = this->nnode();
249  int p_index = this->p_nodal_index_spherical_nst();
250  // loop over all nodes and pin all the nodal pressures
251  for(unsigned n=0;n<n_node;n++) {this->node_pt(n)->pin(p_index);}
252 
253  // Loop over all actual pressure nodes and unpin if they're not hanging
254  unsigned n_pres = this->npres_spherical_nst();
255  for(unsigned l=0;l<n_pres;l++)
256  {
257  Node* nod_pt = this->node_pt(this->Pconv[l]);
258  if (!nod_pt->is_hanging(p_index)) {nod_pt->unpin(p_index);}
259  }
260  }
261 
262  public:
263 
264  /// \short Constructor:
268  RefineableQElement<2>(),
270 
271  /// Number of values (pinned or dofs) required at node n.
272  // Bumped up to 4 so we don't have to worry if a hanging mid-side node
273  // gets shared by a corner node (which has extra degrees of freedom)
274  unsigned required_nvalue(const unsigned &n) const {return 4;}
275 
276  /// Number of continuously interpolated values: 4 (3 velocities + 1 pressure)
277  unsigned ncont_interpolated_values() const {return 4;}
278 
279  /// Rebuild from sons: empty
280  void rebuild_from_sons(Mesh* &mesh_pt) {}
281 
282  /// \short Order of recovery shape functions for Z2 error estimation:
283  /// Same order as shape functions.
284  unsigned nrecovery_order() {return 2;}
285 
286  /// \short Number of vertex nodes in the element
287  unsigned nvertex_node() const
289 
290  /// \short Pointer to the j-th vertex node in the element
291  Node* vertex_node_pt(const unsigned& j) const
292  {
294  }
295 
296 /// \short Get the function value u in Vector.
297 /// Note: Given the generality of the interface (this function
298 /// is usually called from black-box documentation or interpolation routines),
299 /// the values Vector sets its own size in here.
301  {
302  // Set size of values Vector: u,w,v,p and initialise to zero
303  values.resize(4,0.0);
304 
305  //Calculate three velocities: values[0],...
306  for(unsigned i=0;i<3;i++) {values[i] = interpolated_u_spherical_nst(s,i);}
307 
308  //Calculate pressure: values[3]
309  values[3] = interpolated_p_spherical_nst(s);
310  }
311 
312 /// \short Get the function value u in Vector.
313 /// Note: Given the generality of the interface (this function
314 /// is usually called from black-box documentation or interpolation routines),
315 /// the values Vector sets its own size in here.
316  void get_interpolated_values(const unsigned& t, const Vector<double>&s,
317  Vector<double>& values)
318  {
319  // Set size of Vector: u,w,v,p
320  values.resize(4);
321 
322  // Initialise
323  for(unsigned i=0;i<4;i++) {values[i]=0.0;}
324 
325  //Find out how many nodes there are
326  unsigned n_node = nnode();
327 
328  // Shape functions
329  Shape psif(n_node);
330  shape(s,psif);
331 
332  //Calculate velocities: values[0],...
333  for(unsigned i=0;i<3;i++)
334  {
335  //Get the nodal coordinate of the velocity
336  const unsigned u_nodal_index = u_index_spherical_nst(i);
337  for(unsigned l=0;l<n_node;l++)
338  {
339  values[i] += nodal_value(t,l,u_nodal_index)*psif[l];
340  }
341  }
342 
343  //Calculate pressure: values[3]
344  //(no history is carried in the pressure)
345  values[3] = interpolated_p_spherical_nst(s);
346  }
347 
348  /// \short Perform additional hanging node procedures for variables
349  /// that are not interpolated by all nodes. The pressures are stored
350  /// at the 3rd location in each node
352  {
353  this->setup_hang_for_value(3);
354  }
355 
356  /// \short The velocities are isoparametric and so the "nodes" interpolating
357  /// the velocities are the geometric nodes. The pressure "nodes" are a
358  /// subset of the nodes, so when n_value==3, the n-th pressure
359  /// node is returned.
360  Node* interpolating_node_pt(const unsigned &n,
361  const int &n_value)
362 
363  {
364  //The only different nodes are the pressure nodes
365  if(n_value==3) {return this->node_pt(this->Pconv[n]);}
366  //The other variables are interpolated via the usual nodes
367  else {return this->node_pt(n);}
368  }
369 
370  /// \short The pressure nodes are the corner nodes, so when n_value==DIM,
371  /// the fraction is the same as the 1d node number, 0 or 1.
372  double local_one_d_fraction_of_interpolating_node(const unsigned &n1d,
373  const unsigned &i,
374  const int &n_value)
375  {
376  if(n_value==3)
377  {
378  //The pressure nodes are just located on the boundaries at 0 or 1
379  return double(n1d);
380  }
381  //Otherwise the velocity nodes are the same as the geometric ones
382  else
383  {
384  return this->local_one_d_fraction_of_node(n1d,i);
385  }
386  }
387 
388  /// \short The velocity nodes are the same as the geometric nodes. The
389  /// pressure nodes must be calculated by using the same methods as
390  /// the geometric nodes, but by recalling that there are only two pressure
391  /// nodes per edge.
393  const int &n_value)
394  {
395  //If we are calculating pressure nodes
396  if(n_value==3)
397  {
398  //Storage for the index of the pressure node
399  unsigned total_index=0;
400  //The number of nodes along each 1d edge is 2.
401  unsigned NNODE_1D = 2;
402  //Storage for the index along each boundary
403  //Note that it's only a 2D spatial element
404  Vector<int> index(2);
405  //Loop over the coordinates
406  for(unsigned i=0;i<2;i++)
407  {
408  //If we are at the lower limit, the index is zero
409  if(s[i]==-1.0)
410  {
411  index[i] = 0;
412  }
413  //If we are at the upper limit, the index is the number of nodes minus 1
414  else if(s[i] == 1.0)
415  {
416  index[i] = NNODE_1D-1;
417  }
418  //Otherwise, we have to calculate the index in general
419  else
420  {
421  //For uniformly spaced nodes the 0th node number would be
422  double float_index = 0.5*(1.0 + s[i])*(NNODE_1D-1);
423  index[i] = int(float_index);
424  //What is the excess. This should be safe because the
425  //taking the integer part rounds down
426  double excess = float_index - index[i];
427  //If the excess is bigger than our tolerance there is no node,
428  //return null
429  if((excess > FiniteElement::Node_location_tolerance) && (
430  (1.0 - excess) > FiniteElement::Node_location_tolerance))
431  {
432  return 0;
433  }
434  }
435  ///Construct the general pressure index from the components.
436  total_index += index[i]*
437  static_cast<unsigned>(pow(static_cast<float>(NNODE_1D),
438  static_cast<int>(i)));
439  }
440  //If we've got here we have a node, so let's return a pointer to it
441  return this->node_pt(this->Pconv[total_index]);
442  }
443  //Otherwise velocity nodes are the same as pressure nodes
444  else
445  {
446  return this->get_node_at_local_coordinate(s);
447  }
448  }
449 
450 
451  /// \short The number of 1d pressure nodes is 2, the number of 1d velocity
452  /// nodes is the same as the number of 1d geometric nodes.
453  unsigned ninterpolating_node_1d(const int &n_value)
454  {
455  if(n_value==3) {return 2;}
456  else {return this->nnode_1d();}
457  }
458 
459  /// \short The number of pressure nodes is 4. The number of
460  /// velocity nodes is the same as the number of geometric nodes.
461  unsigned ninterpolating_node(const int &n_value)
462  {
463  if(n_value==3) {return 4;}
464  else {return this->nnode();}
465  }
466 
467  /// \short The basis interpolating the pressure is given by pshape().
468  //// The basis interpolating the velocity is shape().
470  Shape &psi,
471  const int &n_value) const
472  {
473  if(n_value==3) {return this->pshape_spherical_nst(s,psi);}
474  else {return this->shape(s,psi);}
475  }
476 
477 };
478 
479 
480 ///////////////////////////////////////////////////////////////////////////
481 ///////////////////////////////////////////////////////////////////////////
482 ///////////////////////////////////////////////////////////////////////////
483 
484 //=======================================================================
485 /// Face geometry of the RefineableQuadQTaylorHoodElements
486 //=======================================================================
487 template<>
489 public virtual FaceGeometry<QSphericalTaylorHoodElement>
490 {
491  public:
493 };
494 
495 
496 //=======================================================================
497 /// Face geometry of the RefineableQuadQTaylorHoodElements
498 //=======================================================================
499 template<>
501 public virtual FaceGeometry<FaceGeometry<QSphericalTaylorHoodElement> >
502 {
503  public:
506 };
507 
508 
509 //======================================================================
510 /// Refineable version of Spherical Quad Crouzeix Raviart elements
511 /// (note that unlike the cartesian version this is not scale-able
512 /// to higher dimensions!)
513 //======================================================================
517 public virtual RefineableQElement<2>
518 {
519  private:
520 
521  ///Unpin all the internal pressure freedoms
523  {
524  unsigned n_pres = this->npres_spherical_nst();
525  // loop over pressure dofs and unpin
526  for(unsigned l=0;l<n_pres;l++)
528  }
529 
530  public:
531 
532 /// \short Constructor:
536  RefineableQElement<2>(),
538 
539  /// Number of continuously interpolated values: 3 (velocities)
540  unsigned ncont_interpolated_values() const {return 3;}
541 
542  /// Rebuild from sons: Reconstruct pressure from the (merged) sons
543  void rebuild_from_sons(Mesh* &mesh_pt)
544  {
545  using namespace QuadTreeNames;
546 
547  //Central pressure value:
548  //-----------------------
549 
550  // Use average of the sons central pressure values
551  // Other options: Take average of the four (discontinuous)
552  // pressure values at the father's midpoint]
553 
554  double av_press=0.0;
555 
556  // Loop over the sons
557  for (unsigned ison=0;ison<4;ison++)
558  {
559  // Add the sons midnode pressure
560  av_press += quadtree_pt()->son_pt(ison)->object_pt()->
562  }
563 
564  // Use the average
566 
567 
568  //Slope in s_0 direction
569  //----------------------
570 
571  // Use average of the 2 FD approximations based on the
572  // elements central pressure values
573  // [Other options: Take average of the four
574  // pressure derivatives]
575 
576  double slope1= quadtree_pt()->son_pt(SE)->object_pt()->
578  quadtree_pt()->son_pt(SW)->object_pt()->
580 
581  double slope2 = quadtree_pt()->son_pt(NE)->object_pt()->
583  quadtree_pt()->son_pt(NW)->object_pt()->
585 
586 
587  // Use the average
589  set_value(1,0.5*(slope1+slope2));
590 
591 
592  //Slope in s_1 direction
593  //----------------------
594 
595  // Use average of the 2 FD approximations based on the
596  // elements central pressure values
597  // [Other options: Take average of the four
598  // pressure derivatives]
599 
600  slope1 = quadtree_pt()->son_pt(NE)->object_pt()->
602  quadtree_pt()->son_pt(SE)->object_pt()->
604 
605  slope2 = quadtree_pt()->son_pt(NW)->object_pt()->
607  quadtree_pt()->son_pt(SW)->object_pt()->
609 
610 
611  // Use the average
613  set_value(2,0.5*(slope1+slope2));
614 
615 
616  }
617 
618 /// \short Order of recovery shape functions for Z2 error estimation:
619 /// Same order as shape functions.
620  unsigned nrecovery_order()
621  {
622  return 2;
623  }
624 
625  /// \short Number of vertex nodes in the element
626  unsigned nvertex_node() const
628 
629  /// \short Pointer to the j-th vertex node in the element
630  Node* vertex_node_pt(const unsigned& j) const
632 
633 /// \short Get the function value u in Vector.
634 /// Note: Given the generality of the interface (this function
635 /// is usually called from black-box documentation or interpolation routines),
636 /// the values Vector sets its own size in here.
638  {
639  // Set size of Vector: u,w,v and initialise to zero
640  values.resize(3,0.0);
641 
642  //Calculate velocities: values[0],...
643  for(unsigned i=0;i<3;i++) {values[i] = interpolated_u_spherical_nst(s,i);}
644  }
645 
646  /// \short Get all function values [u,v..,p] at previous timestep t
647  /// (t=0: present; t>0: previous timestep).
648  /// \n
649  /// Note: Given the generality of the interface (this function is
650  /// usually called from black-box documentation or interpolation routines),
651  /// the values Vector sets its own size in here.
652  /// \n
653  /// Note: No pressure history is kept, so pressure is always
654  /// the current value.
655  void get_interpolated_values(const unsigned& t, const Vector<double>&s,
656  Vector<double>& values)
657  {
658  // Set size of Vector: u,w,v
659  values.resize(3);
660 
661  // Initialise
662  for(unsigned i=0;i<3;i++) {values[i]=0.0;}
663 
664  //Find out how many nodes there are
665  unsigned n_node = nnode();
666 
667  // Shape functions
668  Shape psif(n_node);
669  shape(s,psif);
670 
671  //Calculate velocities: values[0],...
672  for(unsigned i=0;i<3;i++)
673  {
674  //Get the local index at which the i-th velocity is stored
675  unsigned u_local_index = u_index_spherical_nst(i);
676  for(unsigned l=0;l<n_node;l++)
677  {
678  values[i] += nodal_value(t,l,u_local_index)*psif[l];
679  }
680  }
681  }
682 
683  /// \short Perform additional hanging node procedures for variables
684  /// that are not interpolated by all nodes. Empty
686 
687  /// Further build for Crouzeix_Raviart interpolates the internal
688  /// pressure dofs from father element: Make sure pressure values and
689  /// dp/ds agree between fathers and sons at the midpoints of the son
690  /// elements.
692  {
693  //Call the generic further build
695 
696  using namespace QuadTreeNames;
697 
698  // What type of son am I? Ask my quadtree representation...
699  int son_type=quadtree_pt()->son_type();
700 
701  // Pointer to my father (in element impersonation)
702  RefineableElement* father_el_pt=
704 
705  Vector<double> s_father(2);
706 
707  // Son midpoint is located at the following coordinates in father element:
708 
709  // South west son
710  if (son_type==SW)
711  {
712  s_father[0]=-0.5;
713  s_father[1]=-0.5;
714  }
715  // South east son
716  else if (son_type==SE)
717  {
718  s_father[0]= 0.5;
719  s_father[1]=-0.5;
720  }
721  // North east son
722  else if (son_type==NE)
723  {
724  s_father[0]=0.5;
725  s_father[1]=0.5;
726  }
727 
728  // North west son
729  else if (son_type==NW)
730  {
731  s_father[0]=-0.5;
732  s_father[1]= 0.5;
733  }
734 
735  // Pressure value in father element
737  dynamic_cast<RefineableQSphericalCrouzeixRaviartElement*>(father_el_pt);
738  double press=cast_father_el_pt->interpolated_p_spherical_nst(s_father);
739 
740  // Pressure value gets copied straight into internal dof:
742 
743 
744  // The slopes get copied from father
746  set_value(1,0.5*cast_father_el_pt
748  ->value(1));
749 
751  set_value(2,0.5*cast_father_el_pt
753  ->value(2));
754 }
755 
756 };
757 
758 
759 
760 //=======================================================================
761 /// Face geometry of the RefineableQuadQCrouzeixRaviartElements
762 //=======================================================================
763 template<>
765 public virtual FaceGeometry<QSphericalCrouzeixRaviartElement>
766 {
767  public:
769 };
770 
771 
772 //=======================================================================
773 /// Face geometry of the RefineableQuadQCrouzeixRaviartElements
774 //=======================================================================
775 template<>
778 public virtual FaceGeometry<FaceGeometry<QSphericalCrouzeixRaviartElement> >
779 {
780  public:
783 };
784 
785 
786 }
787 
788 #endif
void unpin(const unsigned &i)
Unpin the i-th stored variable.
Definition: nodes.h:386
SphericalNavierStokesBodyForceFctPt Body_force_fct_pt
Pointer to body force function.
double *& re_invfr_pt()
Pointer to global inverse Froude number.
Base class for finite elements that can compute the quantities that are required for the Z2 error est...
virtual Node * pressure_node_pt(const unsigned &n_p)
Pointer to n_p-th pressure node (Default: NULL, indicating that pressure is not based on nodal interp...
void fill_in_generic_residual_contribution_spherical_nst(Vector< double > &residuals, DenseMatrix< double > &jacobian, DenseMatrix< double > &mass_matrix, unsigned flag)
Add element's contribution to the elemental residual vector and/or Jacobian matrix flag=1: compute bo...
Node * interpolating_node_pt(const unsigned &n, const int &n_value)
The velocities are isoparametric and so the "nodes" interpolating the velocities are the geometric no...
unsigned ninterpolating_node_1d(const int &n_value)
The number of 1d pressure nodes is 2, the number of 1d velocity nodes is the same as the number of 1d...
static const unsigned Pconv[]
Static array of ints to hold conversion from pressure node numbers to actual node numbers...
RefineableElement * object_pt() const
Return the pointer to the object (RefineableElement) represented by the tree.
Definition: tree.h:102
void get_interpolated_values(const unsigned &t, const Vector< double > &s, Vector< double > &values)
Get all function values [u,v..,p] at previous timestep t (t=0: present; t>0: previous timestep)...
SphericalNavierStokesSourceFctPt & source_fct_pt()
Access function for the source-function pointer.
cstr elem_len * i
Definition: cfortran.h:607
unsigned nvertex_node() const
Number of vertex nodes in the element.
Refineable version of the Spherical Navier–Stokes equations.
double geometric_jacobian(const Vector< double > &x)
Fill in the geometric Jacobian, which in this case is r*r*sin(theta)
double * ReSt_pt
Pointer to global Reynolds number x Strouhal number (=Womersley)
double nodal_value(const unsigned &n, const unsigned &i) const
Return the i-th value stored at local node n. Produces suitably interpolated values for hanging nodes...
Definition: elements.h:2458
unsigned num_Z2_flux_terms()
Number of 'flux' terms for Z2 error estimation.
unsigned nvertex_node() const
Number of vertex nodes in the element.
char t
Definition: cfortran.h:572
void setup_hang_for_value(const int &value_id)
Internal helper function that is used to construct the hanging node schemes for the value_id-th inter...
virtual void pin_elemental_redundant_nodal_pressure_dofs()
Pin unused nodal pressure dofs (empty by default, because.
Nodes are derived from Data, but, in addition, have a definite (Eulerian) position in a space of a gi...
Definition: nodes.h:852
unsigned npres_spherical_nst() const
Return number of pressure values.
e
Definition: cfortran.h:575
void further_build()
Further build: pass the pointers down to the sons.
unsigned npres_spherical_nst() const
Return number of pressure values.
virtual unsigned nnode_1d() const
Return the number of nodes along one edge of the element Default is to return zero — must be overload...
Definition: elements.h:2139
void pin(const unsigned &i)
Pin the i-th stored variable.
Definition: nodes.h:383
Node * vertex_node_pt(const unsigned &j) const
Pointer to the j-th vertex node in the element.
bool ALE_is_disabled
Boolean flag to indicate if ALE formulation is disabled when time-derivatives are computed...
double *& density_ratio_pt()
Pointer to Density ratio.
unsigned nrecovery_order()
Order of recovery shape functions for Z2 error estimation: Same order as shape functions.
QuadTree * quadtree_pt()
Pointer to quadtree representation of this element.
bool is_hanging() const
Test whether the node is geometrically hanging.
Definition: nodes.h:1207
void further_setup_hanging_nodes()
Perform additional hanging node procedures for variables that are not interpolated by all nodes...
static void pin_redundant_nodal_pressures(const Vector< GeneralisedElement * > &element_pt)
Loop over all elements in Vector (which typically contains all the elements in a fluid mesh) and pin ...
Vector< double > * G_pt
Pointer to global gravity Vector.
unsigned ncont_interpolated_values() const
Number of continuously interpolated values: 3 (velocities)
unsigned required_nvalue(const unsigned &n) const
Number of values (pinned or dofs) required at node n.
static char t char * s
Definition: cfortran.h:572
void rebuild_from_sons(Mesh *&mesh_pt)
Rebuild from sons: empty.
Vector< double > *& g_pt()
Pointer to Vector of gravitational components.
void set_value(const unsigned &i, const double &value_)
Set the i-th stored data value to specified value. The only reason that we require an explicit set fu...
Definition: nodes.h:267
Data *& internal_data_pt(const unsigned &i)
Return a pointer to i-th internal data object.
Definition: elements.h:623
double * ReInvRo_pt
Pointer to global Reynolds number x inverse Rossby number (used when in a rotating frame) ...
virtual Node * get_node_at_local_coordinate(const Vector< double > &s) const
If there is a node at this local coordinate, return the pointer to the node.
Definition: elements.cc:3804
SphericalNavierStokesSourceFctPt Source_fct_pt
Pointer to volumetric source function.
unsigned ncont_interpolated_values() const
Number of continuously interpolated values: 4 (3 velocities + 1 pressure)
void further_setup_hanging_nodes()
Perform additional hanging node procedures for variables that are not interpolated by all nodes...
void get_interpolated_values(const unsigned &t, const Vector< double > &s, Vector< double > &values)
Get the function value u in Vector. Note: Given the generality of the interface (this function is usu...
void interpolating_basis(const Vector< double > &s, Shape &psi, const int &n_value) const
The basis interpolating the pressure is given by pshape(). / The basis interpolating the velocity is ...
Node *& node_pt(const unsigned &n)
Return a pointer to the local node n.
Definition: elements.h:2097
double *& re_invro_pt()
Pointer to global inverse Froude number.
static const double Node_location_tolerance
Default value for the tolerance to be used when locating nodes via local coordinates.
Definition: elements.h:1334
unsigned nrecovery_order()
Order of recovery shape functions for Z2 error estimation: Same order as shape functions.
double * Density_Ratio_pt
Pointer to the density ratio (relative to the density used in the definition of the Reynolds number) ...
unsigned ninterpolating_node(const int &n_value)
The number of pressure nodes is 4. The number of velocity nodes is the same as the number of geometri...
virtual RefineableElement * father_element_pt() const
Return a pointer to the father element.
virtual unsigned u_index_spherical_nst(const unsigned &i) const
Return the index at which the i-th unknown velocity component.
virtual void unpin_elemental_pressure_dofs()=0
Unpin all pressure dofs in the element.
virtual Node * vertex_node_pt(const unsigned &j) const
Pointer to the j-th vertex node in the element. Broken virtual function in "pure" finite elements...
Definition: elements.h:2371
int son_type() const
Return son type.
Definition: tree.h:209
double * ReInvFr_pt
Pointer to global Reynolds number x inverse Froude number (= Bond number / Capillary number) ...
Node * get_interpolating_node_at_local_coordinate(const Vector< double > &s, const int &n_value)
The velocity nodes are the same as the geometric nodes. The pressure nodes must be calculated by usin...
double * Re_pt
Pointer to global Reynolds number.
double local_one_d_fraction_of_interpolating_node(const unsigned &n1d, const unsigned &i, const int &n_value)
The pressure nodes are the corner nodes, so when n_value==DIM, the fraction is the same as the 1d nod...
void rebuild_from_sons(Mesh *&mesh_pt)
Rebuild from sons: Reconstruct pressure from the (merged) sons.
void pin_elemental_redundant_nodal_pressure_dofs()
Unpin the proper nodal pressure dofs.
unsigned nnode() const
Return the number of nodes.
Definition: elements.h:2134
Node * vertex_node_pt(const unsigned &j) const
Pointer to the j-th vertex node in the element.
virtual unsigned nvertex_node() const
Definition: elements.h:2362
void unpin_elemental_pressure_dofs()
Unpin all the internal pressure freedoms.
Node * pressure_node_pt(const unsigned &n_p)
Pointer to n_p-th pressure node.
void get_Z2_flux(const Vector< double > &s, Vector< double > &flux)
Get 'flux' for Z2 error recovery: Upper triangular entries in strain rate tensor. ...
double *& re_st_pt()
Pointer to product of Reynolds and Strouhal number (=Womersley number)
SphericalNavierStokesBodyForceFctPt & body_force_fct_pt()
Access function for the body-force pointer.
double *& re_pt()
Pointer to Reynolds number.
Tree * father_pt() const
Return pointer to father: NULL if it's a root node.
Definition: tree.h:221
virtual double local_one_d_fraction_of_node(const unsigned &n1d, const unsigned &i)
Get the local fraction of any node in the n-th position in a one dimensional expansion along the i-th...
Definition: elements.h:1810
double value(const unsigned &i) const
Return i-th stored value. This function is not virtual so that it can be inlined. This means that if ...
Definition: nodes.h:291
double * Viscosity_Ratio_pt
Pointer to the viscosity ratio (relative to the viscosity used in the definition of the Reynolds numb...
static void unpin_all_pressure_dofs(const Vector< GeneralisedElement * > &element_pt)
Unpin all pressure dofs in elements listed in vector.
void get_interpolated_values(const Vector< double > &s, Vector< double > &values)
Get the function value u in Vector. Note: Given the generality of the interface (this function is usu...
Tree * son_pt(const int &son_index) const
Return pointer to the son for a given index. Note that to aid code readability specific enums have be...
Definition: tree.h:114
void pshape_spherical_nst(const Vector< double > &s, Shape &psi) const
Pressure shape functions at local coordinate s.
int p_nodal_index_spherical_nst() const
Set the value at which the pressure is stored in the nodes In this case the third index because there...
void interpolated_u_spherical_nst(const Vector< double > &s, Vector< double > &veloc) const
Compute vector of FE interpolated velocity u at local coordinate s.
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...
A general mesh class.
Definition: mesh.h:74
void get_interpolated_values(const Vector< double > &s, Vector< double > &values)
Get the function value u in Vector. Note: Given the generality of the interface (this function is usu...
double interpolated_p_spherical_nst(const Vector< double > &s) const
Return FE interpolated pressure at local coordinate s.
double *& viscosity_ratio_pt()
Pointer to Viscosity Ratio.
void strain_rate(const Vector< double > &s, DenseMatrix< double > &strain_rate) const
Strain-rate tensor: 1/2 (du_i/dx_j + du_j/dx_i)