discontinuous_galerkin_spacetime_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// Copyright (C) 2006-2022 Matthias Heil and Andrew Hazel
7 // LIC//
8 // LIC// This library is free software; you can redistribute it and/or
9 // LIC// modify it under the terms of the GNU Lesser General Public
10 // LIC// License as published by the Free Software Foundation; either
11 // LIC// version 2.1 of the License, or (at your option) any later version.
12 // LIC//
13 // LIC// This library is distributed in the hope that it will be useful,
14 // LIC// but WITHOUT ANY WARRANTY; without even the implied warranty of
15 // LIC// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
16 // LIC// Lesser General Public License for more details.
17 // LIC//
18 // LIC// You should have received a copy of the GNU Lesser General Public
19 // LIC// License along with this library; if not, write to the Free Software
20 // LIC// Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA
21 // LIC// 02110-1301 USA.
22 // LIC//
23 // LIC// The authors may be contacted at oomph-lib@maths.man.ac.uk.
24 // LIC//
25 // LIC//====================================================================
26 // Header file for SpaceTimeNavierStokes elements
27 #ifndef OOMPH_DISCONTINUOUS_GALERKIN_SPACETIME_NAVIER_STOKES_ELEMENTS_HEADER
28 #define OOMPH_DISCONTINUOUS_GALERKIN_SPACETIME_NAVIER_STOKES_ELEMENTS_HEADER
29 
30 // Config header generated by autoconfig
31 #ifdef HAVE_CONFIG_H
32 #include <oomph-lib-config.h>
33 #endif
34 
35 // Oomph-lib headers
36 #include "generic.h"
37 
38 namespace oomph
39 {
40  //======================================================================
44  //======================================================================
45  class FpPressureAdvDiffRobinBCSpaceTimeElementBase
46  : public virtual FaceElement
47  {
48  public:
51 
54 
59  Vector<double>& residuals,
60  DenseMatrix<double>& jacobian,
61  const unsigned& compute_jacobian_flag) = 0;
62  };
63 
67 
68  //======================================================================
75  //======================================================================
76  template<class ELEMENT>
78  : public virtual FaceGeometry<ELEMENT>,
79  public virtual FaceElement,
81  {
82  public:
87  FiniteElement* const& element_pt,
88  const int& face_index,
89  const bool& called_from_refineable_constructor = false)
90  : FaceGeometry<ELEMENT>(), FaceElement()
91  {
92  // Attach the geometrical information to the element. N.B. This function
93  // also assigns nbulk_value from the required_nvalue of the bulk element
94  element_pt->build_face_element(face_index, this);
95 
96 #ifdef PARANOID
97  // Check that the element is not a refineable 3D element
98  if (!called_from_refineable_constructor)
99  {
100  // If it's a three-dimensional element
101  if (element_pt->dim() == 3)
102  {
103  // Upcast the element to a RefineableElement
104  RefineableElement* ref_el_pt =
105  dynamic_cast<RefineableElement*>(element_pt);
106 
107  // Is it actually refineable?
108  if (ref_el_pt != 0)
109  {
110  // If it is refineable then check if it has any hanging nodes
111  if (this->has_hanging_nodes())
112  {
113  // Create an output stream
114  std::ostringstream error_message_stream;
115 
116  // Create an error message
117  error_message_stream
118  << "This flux element will not work correctly "
119  << "if nodes are hanging!" << std::endl;
120 
121  // Throw an error message
122  throw OomphLibError(error_message_stream.str(),
125  }
126  } // if (ref_el_pt!=0)
127  } // if (element_pt->dim()==3)
128  } // if (!called_from_refineable_constructor)
129 #endif
130  } // End of FpPressureAdvDiffRobinBCSpaceTimeElement
131 
132 
135 
136 
141  Vector<double>& residuals,
142  DenseMatrix<double>& jacobian,
143  const unsigned& flag);
144 
145 
148  {
149  // Create an output stream
150  std::ostringstream error_message;
151 
152  // Create an error message
153  error_message << "fill_in_contribution_to_residuals() must not be "
154  << "called directly.\nsince it uses the local equation "
155  << "numbering of the bulk element\nwhich calls the "
156  << "relevant helper function directly." << std::endl;
157 
158  // Throw an error
159  throw OomphLibError(
160  error_message.str(), OOMPH_CURRENT_FUNCTION, OOMPH_EXCEPTION_LOCATION);
161  } // End of fill_in_contribution_to_residuals
162 
163 
166  DenseMatrix<double>& jacobian)
167  {
168  // Create an output stream
169  std::ostringstream error_message;
170 
171  // Create an error message
172  error_message << "fill_in_contribution_to_jacobian() must not be "
173  << "called directly.\nsince it uses the local equation "
174  << "numbering of the bulk element\nwhich calls the "
175  << "relevant helper function directly." << std::endl;
176 
177  // Throw an error
178  throw OomphLibError(
179  error_message.str(), OOMPH_CURRENT_FUNCTION, OOMPH_EXCEPTION_LOCATION);
180  } // End of fill_in_contribution_to_jacobian
181 
182 
184  void output(std::ostream& outfile)
185  {
186  // Call the output function from the FiniteElement base class
187  FiniteElement::output(outfile);
188  } // End of output
189 
190 
192  void output(std::ostream& outfile, const unsigned& nplot)
193  {
194  // Call the output function from the FiniteElement base class
195  FiniteElement::output(outfile, nplot);
196  } // End of output
197  };
198 
202 
203  //============================================================================
209  //============================================================================
210  template<class ELEMENT>
213  Vector<double>& residuals,
214  DenseMatrix<double>& jacobian,
215  const unsigned& flag)
216  {
217  // Throw a warning
218  throw OomphLibError("You shouldn't be using this just yet!",
221 
222  // Get the dimension of the element
223  // DRAIG: Should be 2 as bulk (space-time) element is 3D...
224  unsigned my_dim = this->dim();
225 
226  // Storage for local coordinates in FaceElement
227  Vector<double> s(my_dim, 0.0);
228 
229  // Storage for local coordinates in the associated bulk element
230  Vector<double> s_bulk(my_dim + 1, 0.0);
231 
232  // Storage for outer unit normal
233  // DRAIG: Need to be careful here...
234  Vector<double> unit_normal(my_dim + 1, 0.0);
235 
236  // Storage for velocity in bulk element
237  // DRAIG: Need to be careful here...
238  Vector<double> velocity(my_dim, 0.0);
239 
240  // Set the value of n_intpt
241  unsigned n_intpt = this->integral_pt()->nweight();
242 
243  // Integer to store local equation number
244  int local_eqn = 0;
245 
246  // Integer to store local unknown number
247  int local_unknown = 0;
248 
249  // Get upcast bulk element
250  ELEMENT* bulk_el_pt = dynamic_cast<ELEMENT*>(this->bulk_element_pt());
251 
252  // Find out how many pressure dofs there are in the bulk element
253  unsigned n_pres = bulk_el_pt->npres_nst();
254 
255  // Get the Reynolds number from the bulk element
256  double re = bulk_el_pt->re();
257 
258  // Set up memory for pressure shape functions
259  Shape psip(n_pres);
260 
261  // Set up memory for pressure test functions
262  Shape testp(n_pres);
263 
264  // Loop over the integration points
265  for (unsigned ipt = 0; ipt < n_intpt; ipt++)
266  {
267  // Get the integral weight
268  double w = this->integral_pt()->weight(ipt);
269 
270  // Assign values of local coordinate in FaceElement
271  for (unsigned i = 0; i < my_dim; i++)
272  {
273  // Get the i-th local coordinate at this knot point
274  s[i] = this->integral_pt()->knot(ipt, i);
275  }
276 
277  // Find corresponding coordinate in the bulk element
278  s_bulk = this->local_coordinate_in_bulk(s);
279 
280  // Get outer unit normal
281  // DRAIG: Make sure the normal is calculated properly; i.e.
282  // the normal needs to be calculated in the spatial direction
283  // and NOT in the temporal direction!!!
284  this->outer_unit_normal(ipt, unit_normal);
285 
286  // Get velocity in bulk element
287  bulk_el_pt->interpolated_u_nst(s_bulk, velocity);
288 
289  // Get normal component of velocity
290  double flux = 0.0;
291 
292  // Loop over the velocity components
293  for (unsigned i = 0; i < my_dim; i++)
294  {
295  // Update the flux quantity
296  flux += velocity[i] * unit_normal[i];
297  }
298 
299  // Modify BC: If outflow (flux>0) apply Neumann condition instead
300  if (flux > 0.0)
301  {
302  // Apply no flux condition
303  flux = 0.0;
304  }
305 
306  // Get the pressure at these local coordinates
307  double interpolated_press = bulk_el_pt->interpolated_p_nst(s_bulk);
308 
309  // Call the pressure shape and test functions in bulk element
310  bulk_el_pt->pshape_nst(s_bulk, psip, testp);
311 
312  // Find the Jacobian of the mapping within the FaceElement
313  double J = this->J_eulerian(s);
314 
315  // Premultiply the weights and the Jacobian
316  double W = w * J;
317 
318  // Loop over the pressure shape functions in bulk
319  // (wasteful but they'll be zero on the boundary)
320  for (unsigned l = 0; l < n_pres; l++)
321  {
322  // Get the local equation number associated with this pressure dof
323  local_eqn = bulk_el_pt->p_local_eqn(l);
324 
325  // If it's not a boundary condition
326  if (local_eqn >= 0)
327  {
328  // Update the residuals
329  residuals[local_eqn] -= re * flux * interpolated_press * testp[l] * W;
330 
331  // If the Jacobian needs to be computed too
332  if (flag)
333  {
334  // Loop over the shape functions in bulk
335  for (unsigned l2 = 0; l2 < n_pres; l2++)
336  {
337  // Get the equation number associated with this pressure dof
338  local_unknown = bulk_el_pt->p_local_eqn(l2);
339 
340  // If it's not a boundary condition
341  if (local_unknown >= 0)
342  {
343  // Update the appropriate Jacobian entry
344  jacobian(local_eqn, local_unknown) -=
345  re * flux * psip[l2] * testp[l] * W;
346  }
347  } // for (unsigned l2=0;l2<n_pres;l2++)
348  } // if (flag)
349  } // if (local_eqn>=0)
350  } // for (unsigned l=0;l<n_pres;l++)
351  } // for (unsigned ipt=0;ipt<n_intpt;ipt++)
352  } // End of fill_in_generic_residual_contribution_fp_press_adv_diff_robin_bc
353 
357 
358  //======================================================================
361  //======================================================================
362  class TemplateFreeSpaceTimeNavierStokesEquationsBase
363  : public virtual NavierStokesElementWithDiagonalMassMatrices,
364  public virtual FiniteElement
365  {
366  public:
369 
370 
373 
374 
378  Vector<double>& residuals) = 0;
379 
380 
384  Vector<double>& residuals, DenseMatrix<double>& jacobian) = 0;
385 
386 
390  virtual int p_nodal_index_nst() const = 0;
391 
392 
396  virtual int p_local_eqn(const unsigned& n) const = 0;
397 
398 
401  virtual int& pinned_fp_pressure_eqn() = 0;
402 
403 
406  std::map<Data*, std::vector<int>>& eqn_number_backup) = 0;
407 
408 
413  const unsigned& face_index) = 0;
414 
415 
420 
421 
427  Vector<double>& press_mass_diag,
428  Vector<double>& veloc_mass_diag,
429  const unsigned& which_one = 0) = 0;
430  };
431 
435 
436  //======================================================================
461  //======================================================================
462  template<unsigned DIM>
464  : public virtual FSIFluidElement,
466  {
467  public:
470  typedef void (*NavierStokesBodyForceFctPt)(const double& time,
471  const Vector<double>& x,
473 
475  typedef double (*NavierStokesSourceFctPt)(const double& time,
476  const Vector<double>& x);
477 
482  const Vector<double>& x);
483 
484  private:
487  static int Pressure_not_stored_at_node;
488 
491  static double Default_Physical_Constant_Value;
492 
495  static double Default_Physical_Ratio_Value;
496 
499 
500  protected:
501  // Physical constants:
502 
505  double* Viscosity_Ratio_pt;
506 
509  double* Density_Ratio_pt;
510 
511  // Pointers to global physical constants:
512 
514  double* Re_pt;
515 
517  double* St_pt;
518 
522 
525  double* ReInvFr_pt;
526 
529 
532 
535 
539 
543  bool ALE_is_disabled;
544 
549 
553 
554 
559  Shape& psi,
560  DShape& dpsidx,
561  Shape& test,
562  DShape& dtestdx) const = 0;
563 
564 
569  const unsigned& ipt,
570  Shape& psi,
571  DShape& dpsidx,
572  Shape& test,
573  DShape& dtestdx) const = 0;
574 
575 
580  const unsigned& ipt,
581  Shape& psi,
582  DShape& dpsidx,
583  RankFourTensor<double>& d_dpsidx_dX,
584  Shape& test,
585  DShape& dtestdx,
586  RankFourTensor<double>& d_dtestdx_dX,
587  DenseMatrix<double>& djacobian_dX) const = 0;
588 
589 
593  virtual double dpshape_eulerian(const Vector<double>& s,
594  Shape& ppsi,
595  DShape& dppsidx) const = 0;
596 
597 
601  virtual double dptest_eulerian(const Vector<double>& s,
602  Shape& ptest,
603  DShape& dptestdx) const = 0;
604 
605 
610  Shape& ppsi,
611  DShape& dppsidx,
612  Shape& ptest,
613  DShape& dptestdx) const = 0;
614 
615 
620  virtual void get_body_force_nst(const double& time,
621  const unsigned& ipt,
622  const Vector<double>& s,
623  const Vector<double>& x,
624  Vector<double>& result)
625  {
626  // If a function has not been provided
627  if (Body_force_fct_pt == 0)
628  {
629  // Set the body forces to zero
630  result.initialise(0.0);
631  }
632  // If the function pointer is non-zero
633  else
634  {
635  // Call the function
636  (*Body_force_fct_pt)(time, x, result);
637  } // if (Body_force_fct_pt!=0)
638  } // End of get_body_force_nst
639 
640 
646  inline virtual void get_body_force_gradient_nst(
647  const double& time,
648  const unsigned& ipt,
649  const Vector<double>& s,
650  const Vector<double>& x,
651  DenseMatrix<double>& d_body_force_dx)
652  {
653  // Reference value
655 
656  // Get the body force vector
657  get_body_force_nst(time, ipt, s, x, body_force);
658 
659  // Get the finite-difference step size
661 
662  // The body force computed at the perturbed coordinates
663  Vector<double> body_force_pls(DIM, 0.0);
664 
665  // Copy the (Eulerian) coordinate vector x
666  Vector<double> x_pls(x);
667 
668  // Loop over the coordinate directions
669  for (unsigned i = 0; i < DIM; i++)
670  {
671  // Update the i-th entry
672  x_pls[i] += eps_fd;
673 
674  // Get the body force at the current time
675  get_body_force_nst(time, ipt, s, x_pls, body_force_pls);
676 
677  // Loop over the coordinate directions
678  for (unsigned j = 0; j < DIM; j++)
679  {
680  // Finite-difference the body force derivative
681  d_body_force_dx(j, i) = (body_force_pls[j] - body_force[j]) / eps_fd;
682  }
683 
684  // Reset the i-th entry
685  x_pls[i] = x[i];
686  }
687  } // End of get_body_force_gradient_nst
688 
689 
691  virtual double get_source_nst(const double& time,
692  const unsigned& ipt,
693  const Vector<double>& x)
694  {
695  // If the function pointer is null
696  if (Source_fct_pt == 0)
697  {
698  // Set the source function value to zero
699  return 0;
700  }
701  // Otherwise call the function pointer
702  else
703  {
704  // Return the appropriate value
705  return (*Source_fct_pt)(time, x);
706  }
707  } // End of get_source_nst
708 
709 
715  inline virtual void get_source_gradient_nst(const double& time,
716  const unsigned& ipt,
717  const Vector<double>& x,
718  Vector<double>& gradient)
719  {
720  // Reference value
721  double source = get_source_nst(time, ipt, x);
722 
723  // Get the finite-difference step size
725 
726  // The source function value computed at the perturbed coordinates
727  double source_pls = 0.0;
728 
729  // Copy the (Eulerian) coordinate vector, x
730  Vector<double> x_pls(x);
731 
732  // Loop over the coordinate directions
733  for (unsigned i = 0; i < DIM; i++)
734  {
735  // Update the i-th entry
736  x_pls[i] += eps_fd;
737 
738  // Get the body force at the current time
739  source_pls = get_source_nst(time, ipt, x_pls);
740 
741  // Loop over the coordinate directions
742  for (unsigned j = 0; j < DIM; j++)
743  {
744  // Finite-difference the source function gradient
745  gradient[i] = (source_pls - source) / eps_fd;
746  }
747 
748  // Reset the i-th entry
749  x_pls[i] = x[i];
750  }
751  } // End of get_source_gradient_nst
752 
753 
758  Vector<double>& residuals,
759  DenseMatrix<double>& jacobian,
760  DenseMatrix<double>& mass_matrix,
761  const unsigned& flag);
762 
763 
768  Vector<double>& residuals,
769  DenseMatrix<double>& jacobian,
770  const unsigned& flag);
771 
772 
778  double* const& parameter_pt,
779  Vector<double>& dres_dparam,
780  DenseMatrix<double>& djac_dparam,
781  DenseMatrix<double>& dmass_matrix_dparam,
782  const unsigned& flag);
783 
784 
788  Vector<double> const& Y,
789  DenseMatrix<double> const& C,
791 
792  public:
796  : Body_force_fct_pt(0),
797  Source_fct_pt(0),
799  ALE_is_disabled(false),
801  {
802  // Set all the Physical parameter pointers:
803 
804  // Set the Reynolds number to the value zero
806 
807  // Set the Strouhal number to the value zero
809 
810  // The Strouhal number (which is a proxy for the period here) is not
811  // stored as external data
813 
814  // Set the Reynolds / Froude value to zero
816 
817  // Set the gravity vector to be the zero vector
819 
820  // Set the Physical ratios:
821 
822  // Set the viscosity ratio to the value one
824 
825  // Set the density ratio to the value one
827  }
828 
833  static Vector<double> Gamma;
834 
835 
837  void store_strouhal_as_external_data(Data* strouhal_data_pt)
838  {
839 #ifdef PARANOID
840  // Sanity check; make sure it's not a null pointer
841  if (strouhal_data_pt == 0)
842  {
843  // Create an output stream
844  std::ostringstream error_message_stream;
845 
846  // Create an error message
847  error_message_stream
848  << "User supplied Strouhal number as external data\n"
849  << "but the pointer provided is a null pointer!" << std::endl;
850 
851  // Throw an error
852  throw OomphLibError(error_message_stream.str(),
855  }
856 #endif
857 
858  // Set the Strouhal value pointer (the Strouhal number is stored as the
859  // only piece of internal data in the phase condition element)
860  this->add_external_data(strouhal_data_pt);
861 
862  // Indicate that the Strouhal number is store as external data
864  } // End of store_strouhal_as_external_data
865 
866 
867  // Access functions for the physical constants:
868 
870  const double& re() const
871  {
872  // Use the Reynolds number pointer to get the Reynolds value
873  return *Re_pt;
874  } // End of re
875 
876 
878  double*& re_pt()
879  {
880  // Return the Reynolds number pointer
881  return Re_pt;
882  } // End of re_pt
883 
884 
887  {
888  // Return the flags value
890  } // End of is_strouhal_stored_as_external_data
891 
892 
894  const double& st() const
895  {
896  // If the st is stored as external data
898  {
899  // The index of the external data (which contains the st)
900  unsigned data_index = 0;
901 
902  // The index of the value at which the Strouhal is stored
903  unsigned strouhal_index = 0;
904 
905  // Return the value of the st in the external data
906  return *(this->external_data_pt(data_index)->value_pt(strouhal_index));
907  }
908  // Otherwise the st is just stored as a pointer
909  else
910  {
911  // Return the value of St
912  return *St_pt;
913  }
914  } // End of st
915 
916 
918  double* st_pt() const
919  {
920  // If the strouhal is stored as external data
922  {
923  // The index of the external data (which contains the strouhal)
924  unsigned data_index = 0;
925 
926  // The index of the value at which the strouhal is stored (the only
927  // value)
928  unsigned strouhal_index = 0;
929 
930  // Return the value of the strouhal in the external data
931  return this->external_data_pt(data_index)->value_pt(strouhal_index);
932  }
933  // Otherwise the strouhal is just stored as a pointer
934  else
935  {
936  // Return the value of Strouhal
937  return St_pt;
938  }
939  } // End of st_pt
940 
941 
943  double*& st_pt()
944  {
945  // Return the Strouhal number pointer
946  return St_pt;
947  } // End of st_pt
948 
949 
951  double re_st() const
952  {
953  // Return the product of the appropriate physical constants
954  return (*Re_pt) * (*st_pt());
955  } // End of re_st
956 
957 
960  const double& viscosity_ratio() const
961  {
962  return *Viscosity_Ratio_pt;
963  }
964 
967  {
968  return Viscosity_Ratio_pt;
969  }
970 
973  const double& density_ratio() const
974  {
975  return *Density_Ratio_pt;
976  }
977 
979  double*& density_ratio_pt()
980  {
981  return Density_Ratio_pt;
982  }
983 
985  const double& re_invfr() const
986  {
987  return *ReInvFr_pt;
988  }
989 
991  double*& re_invfr_pt()
992  {
993  return ReInvFr_pt;
994  }
995 
997  const Vector<double>& g() const
998  {
999  return *G_pt;
1000  }
1001 
1004  {
1005  return G_pt;
1006  }
1007 
1010  {
1011  return Body_force_fct_pt;
1012  }
1013 
1016  {
1017  return Body_force_fct_pt;
1018  }
1019 
1022  {
1023  return Source_fct_pt;
1024  }
1025 
1028  {
1029  return Source_fct_pt;
1030  }
1031 
1035  {
1037  }
1038 
1042  const
1043  {
1045  }
1046 
1050  {
1051  // Return the appropriate equation number
1052  return Pinned_fp_pressure_eqn;
1053  }
1054 
1056  virtual unsigned npres_nst() const = 0;
1057 
1059  virtual void pshape_nst(const Vector<double>& s, Shape& psi) const = 0;
1060 
1063  virtual void pshape_nst(const Vector<double>& s,
1064  Shape& psi,
1065  Shape& test) const = 0;
1066 
1072  double u_nst(const unsigned& n, const unsigned& i) const
1073  {
1074  return nodal_value(n, u_index_nst(i));
1075  }
1076 
1079  double u_nst(const unsigned& t, const unsigned& n, const unsigned& i) const
1080  {
1081 #ifdef PARANOID
1082  // Since we're using space-time elements, this only makes sense if t=0
1083  if (t != 0)
1084  {
1085  // Throw an error
1086  throw OomphLibError("Space-time elements cannot have history values!",
1089  }
1090 #endif
1091 
1092  // Return the appropriate nodal value (noting that t=0 here)
1093  return nodal_value(t, n, u_index_nst(i));
1094  } // End of u_nst
1095 
1102  virtual inline unsigned u_index_nst(const unsigned& i) const
1103  {
1104 #ifdef PARANOID
1105  if (i > DIM - 1)
1106  {
1107  // Create an output stream
1108  std::ostringstream error_message_stream;
1109 
1110  // Create an error message
1111  error_message_stream << "Input index " << i << " does not correspond "
1112  << "to a velocity component when DIM=" << DIM
1113  << "!" << std::endl;
1114 
1115  // Throw an error
1116  throw OomphLibError(error_message_stream.str(),
1119  }
1120 #endif
1121 
1122  // Return the appropriate entry
1123  return i;
1124  } // End of u_index_nst
1125 
1126 
1129  inline unsigned n_u_nst() const
1130  {
1131  // Return the number of equations to solve
1132  return DIM;
1133  } // End of n_u_nst
1134 
1135 
1140  double get_du_dt(const unsigned& n, const unsigned& i) const
1141  {
1142  // Return the value calculated by du_dt_vdp
1143  return du_dt_nst(n, i);
1144  } // End of get_du_dt
1145 
1146 
1149  double du_dt_nst(const unsigned& n, const unsigned& i) const
1150  {
1151  // Storage for the local coordinates
1152  Vector<double> s(DIM + 1, 0.0);
1153 
1154  // Get the local coordinate at the n-th node
1156 
1157  // Return the interpolated du_i/dt value
1158  return interpolated_du_dt_nst(s, i);
1159  } // End of du_dt_nst
1160 
1161 
1165  const unsigned& i) const
1166  {
1167  // Find number of nodes
1168  unsigned n_node = nnode();
1169 
1170  // Local shape function
1171  Shape psi(n_node);
1172 
1173  // Allocate space for the derivatives of the shape functions
1174  DShape dpsidx(n_node, DIM + 1);
1175 
1176  // Compute the geometric shape functions and also first derivatives
1177  // w.r.t. global coordinates at local coordinate s
1178  dshape_eulerian(s, psi, dpsidx);
1179 
1180  // Initialise value of du_i/dt
1181  double interpolated_dudt = 0.0;
1182 
1183  // Find the index at which the variable is stored
1184  unsigned u_nodal_index = u_index_nst(i);
1185 
1186  // Loop over the local nodes and sum
1187  for (unsigned l = 0; l < n_node; l++)
1188  {
1189  // Update the interpolated du_i/dt value
1190  interpolated_dudt += nodal_value(l, u_nodal_index) * dpsidx(l, DIM);
1191  }
1192 
1193  // Return the interpolated du_i/dt value
1194  return interpolated_dudt;
1195  } // End of interpolated_du_dt_nst
1196 
1197 
1201  {
1202  ALE_is_disabled = true;
1203  } // End of disable_ALE
1204 
1205 
1210  void enable_ALE()
1211  {
1212  ALE_is_disabled = false;
1213  } // End of enable_ALE
1214 
1215 
1218  virtual double p_nst(const unsigned& n_p) const = 0;
1219 
1221  virtual double p_nst(const unsigned& t, const unsigned& n_p) const = 0;
1222 
1224  virtual void fix_pressure(const unsigned& p_dof, const double& p_value) = 0;
1225 
1229  virtual int p_nodal_index_nst() const
1230  {
1232  }
1233 
1235  double pressure_integral() const;
1236 
1238  double dissipation() const;
1239 
1241  double dissipation(const Vector<double>& s) const;
1242 
1245  Vector<double>& vorticity) const;
1246 
1248  void get_vorticity(const Vector<double>& s, double& vorticity) const;
1249 
1251  double kin_energy() const;
1252 
1254  double d_kin_energy_dt() const;
1255 
1259 
1264  const Vector<double>& N,
1265  Vector<double>& traction);
1266 
1272  const Vector<double>& N,
1273  Vector<double>& traction_p,
1274  Vector<double>& traction_visc_n,
1275  Vector<double>& traction_visc_t);
1276 
1286  const Vector<double>& N,
1288  {
1289  // Note: get_traction() computes the traction onto the fluid
1290  // if N is the outer unit normal onto the fluid; here we're
1291  // expecting N to point into the fluid so we're getting the
1292  // traction onto the adjacent wall instead!
1293  get_traction(s, N, load);
1294  }
1295 
1301  Vector<double>& press_mass_diag,
1302  Vector<double>& veloc_mass_diag,
1303  const unsigned& which_one = 0);
1304 
1307  unsigned nscalar_paraview() const
1308  {
1309  // The number of velocity components plus the pressure field
1310  return DIM + 1;
1311  }
1312 
1315  void scalar_value_paraview(std::ofstream& file_out,
1316  const unsigned& i,
1317  const unsigned& nplot) const
1318  {
1319  // Vector of local coordinates
1320  Vector<double> s(DIM + 1, 0.0);
1321 
1322  // How many plot points do we have in total?
1323  unsigned num_plot_points = nplot_points_paraview(nplot);
1324 
1325  // Loop over plot points
1326  for (unsigned iplot = 0; iplot < num_plot_points; iplot++)
1327  {
1328  // Get the local coordinates of the iplot-th plot point
1329  get_s_plot(iplot, nplot, s);
1330 
1331  // Velocities
1332  if (i < DIM)
1333  {
1334  // Output the i-th velocity component
1335  file_out << interpolated_u_nst(s, i) << std::endl;
1336  }
1337  // Pressure
1338  else if (i == DIM)
1339  {
1340  // Output the pressure at this point
1341  file_out << interpolated_p_nst(s) << std::endl;
1342  }
1343  // Never get here
1344  else
1345  {
1346 #ifdef PARANOID
1347  // Create an output stream
1348  std::stringstream error_stream;
1349 
1350  // Create the error message
1351  error_stream << "These Navier Stokes elements only store " << DIM + 1
1352  << " fields, "
1353  << "but i is currently " << i << std::endl;
1354 
1355  // Throw the error message
1356  throw OomphLibError(error_stream.str(),
1359 #endif
1360  }
1361  } // for (unsigned iplot=0;iplot<num_plot_points;iplot++)
1362  } // End of scalar_value_paraview
1363 
1364 
1368  std::ofstream& file_out,
1369  const unsigned& i,
1370  const unsigned& nplot,
1371  const double& time,
1372  FiniteElement::UnsteadyExactSolutionFctPt exact_soln_pt) const
1373  {
1374 #ifdef PARANOID
1375  if (i > DIM)
1376  {
1377  // Create an output stream
1378  std::stringstream error_stream;
1379 
1380  // Create the error message
1381  error_stream << "These Navier Stokes elements only store " << DIM + 1
1382  << " fields, but i is currently " << i << std::endl;
1383 
1384  // Throw the error message
1385  throw OomphLibError(
1386  error_stream.str(), OOMPH_CURRENT_FUNCTION, OOMPH_EXCEPTION_LOCATION);
1387  }
1388 #endif
1389 
1390  // Vector of local coordinates
1391  Vector<double> s(DIM + 1, 0.0);
1392 
1393  // Storage for the time value
1394  double interpolated_t = 0.0;
1395 
1396  // Storage for the spatial coordinates
1397  Vector<double> spatial_coordinates(DIM, 0.0);
1398 
1399  // How many plot points do we have in total?
1400  unsigned num_plot_points = nplot_points_paraview(nplot);
1401 
1402  // Loop over plot points
1403  for (unsigned iplot = 0; iplot < num_plot_points; iplot++)
1404  {
1405  // Get the local coordinates of the iplot-th plot point
1406  get_s_plot(iplot, nplot, s);
1407 
1408  // Loop over the spatial coordinates
1409  for (unsigned i = 0; i < DIM; i++)
1410  {
1411  // Assign the i-th spatial coordinate
1412  spatial_coordinates[i] = interpolated_x(s, i);
1413  }
1414 
1415  // Get the time value
1416  interpolated_t = interpolated_x(s, DIM);
1417 
1418  // ------ DRAIG: REMOVE ----------------------------------------
1419  // Exact solution vector (here it's simply a scalar)
1420  Vector<double> exact_soln(DIM + 1, 0.0);
1421  // DRAIG: Needs to be changed to a Vector of size DIM
1422  // ------ DRAIG: REMOVE ----------------------------------------
1423 
1424  // Get the exact solution at this point
1425  (*exact_soln_pt)(interpolated_t, spatial_coordinates, exact_soln);
1426 
1427  // Output the interpolated solution value
1428  file_out << exact_soln[i] << std::endl;
1429  } // for (unsigned iplot=0;iplot<num_plot_points;iplot++)
1430  } // End of scalar_value_fct_paraview
1431 
1432 
1436  std::string scalar_name_paraview(const unsigned& i) const
1437  {
1438  // Velocities
1439  if (i < DIM)
1440  {
1441  // Return the appropriate string for the i-th velocity component
1442  return "Velocity " + StringConversion::to_string(i);
1443  }
1444  // Pressure
1445  else if (i == DIM)
1446  {
1447  // Return the name for the pressure
1448  return "Pressure";
1449  }
1450  // Never get here
1451  else
1452  {
1453  // Create an output stream
1454  std::stringstream error_stream;
1455 
1456  // Create the error message
1457  error_stream << "These Navier Stokes elements only store " << DIM + 1
1458  << " fields,\nbut i is currently " << i << std::endl;
1459 
1460  // Throw the error message
1461  throw OomphLibError(
1462  error_stream.str(), OOMPH_CURRENT_FUNCTION, OOMPH_EXCEPTION_LOCATION);
1463 
1464  // Dummy return so the compiler doesn't complain
1465  return " ";
1466  }
1467  } // End of scalar_name_paraview
1468 
1469 
1472  void output(std::ostream& outfile)
1473  {
1474  // Set the number of plot points in each direction
1475  unsigned n_plot = 5;
1476 
1477  // Forward the call to the appropriate output function
1478  output(outfile, n_plot);
1479  } // End of output
1480 
1481 
1484  void output(std::ostream& outfile, const unsigned& n_plot);
1485 
1486 
1489  void output(FILE* file_pt)
1490  {
1491  // Set the number of plot points in each direction
1492  unsigned n_plot = 5;
1493 
1494  // Forward the call to the appropriate output function
1495  output(file_pt, n_plot);
1496  } // End of output
1497 
1498 
1501  void output(FILE* file_pt, const unsigned& n_plot);
1502 
1503 
1507  void full_output(std::ostream& outfile)
1508  {
1509  // Set the number of plot points in each direction
1510  unsigned n_plot = 5;
1511 
1512  // Forward the call to the appropriate output function
1513  full_output(outfile, n_plot);
1514  } // End of full_output
1515 
1516 
1520  void full_output(std::ostream& outfile, const unsigned& n_plot);
1521 
1522 
1526  void output_veloc(std::ostream& outfile,
1527  const unsigned& nplot,
1528  const unsigned& t);
1529 
1530 
1533  void output_vorticity(std::ostream& outfile, const unsigned& nplot);
1534 
1535 
1539  void output_fct(std::ostream& outfile,
1540  const unsigned& nplot,
1542 
1543 
1547  void output_fct(std::ostream& outfile,
1548  const unsigned& nplot,
1549  const double& time,
1551 
1552 
1555 
1556 
1561  void compute_error(std::ostream& outfile,
1563  const double& time,
1564  double& error,
1565  double& norm);
1566 
1567 
1572  void compute_error(std::ostream& outfile,
1574  const double& time,
1576  Vector<double>& norm);
1577 
1578 
1583  void compute_error(std::ostream& outfile,
1585  double& error,
1586  double& norm);
1587 
1588 
1593  const double& time,
1594  double& error,
1595  double& norm);
1596 
1597 
1602  double& error,
1603  double& norm);
1604 
1605 
1608  {
1609  // Do we want to compute the Jacobian? ANSWER: No!
1610  unsigned compute_jacobian_flag = 0;
1611 
1612  // Call the generic residuals function using a dummy matrix argument
1614  residuals,
1617  compute_jacobian_flag);
1618  } // End of fill_in_contribution_to_residuals
1619 
1620 
1624  DenseMatrix<double>& jacobian)
1625  {
1626  // Do we want to compute the Jacobian? ANSWER: Yes!
1627  unsigned compute_jacobian_flag = 1;
1628 
1629  // Call the generic routine with the flag set to 1
1631  residuals,
1632  jacobian,
1634  compute_jacobian_flag);
1635  } // End of fill_in_contribution_to_residuals
1636 
1637 
1641  Vector<double>& residuals,
1642  DenseMatrix<double>& jacobian,
1643  DenseMatrix<double>& mass_matrix)
1644  {
1645  // Do we want to compute the Jacobian AND mass matrix? ANSWER: Yes!
1646  unsigned compute_matrices_flag = 2;
1647 
1648  // Call the generic routine with the flag set to 2
1650  residuals, jacobian, mass_matrix, compute_matrices_flag);
1651  } // End of fill_in_contribution_to_jacobian_and_mass_matrix
1652 
1653 
1657  double* const& parameter_pt, Vector<double>& dres_dparam)
1658  {
1659  // Do we want to compute the Jacobian? ANSWER: No!
1660  unsigned compute_jacobian_flag = 0;
1661 
1662  // Call the generic residuals function using a dummy matrix argument
1664  parameter_pt,
1665  dres_dparam,
1668  compute_jacobian_flag);
1669  } // End of fill_in_contribution_to_dresiduals_dparameter
1670 
1671 
1675  double* const& parameter_pt,
1676  Vector<double>& dres_dparam,
1677  DenseMatrix<double>& djac_dparam)
1678  {
1679  // Do we want to compute the Jacobian? ANSWER: Yes!
1680  unsigned compute_jacobian_flag = 1;
1681 
1682  // Call the generic routine with the flag set to 1
1684  parameter_pt,
1685  dres_dparam,
1686  djac_dparam,
1688  compute_jacobian_flag);
1689  } // End of fill_in_contribution_to_djacobian_dparameter
1690 
1691 
1695  double* const& parameter_pt,
1696  Vector<double>& dres_dparam,
1697  DenseMatrix<double>& djac_dparam,
1698  DenseMatrix<double>& dmass_matrix_dparam)
1699  {
1700  // Do we want to compute the Jacobian AND mass matrix? ANSWER: Yes!
1701  unsigned compute_matrices_flag = 2;
1702 
1703  // Call the generic routine with the appropriate flag
1705  dres_dparam,
1706  djac_dparam,
1707  dmass_matrix_dparam,
1708  compute_matrices_flag);
1709  } // End of fill_in_contribution_to_djacobian_and_dmass_matrix_dparameter
1710 
1711 
1715  Vector<double>& residuals)
1716  {
1717  // Do we want to compute the Jacobian? ANSWER: No!
1718  unsigned compute_jacobian_flag = 0;
1719 
1720  // Call the generic routine with the appropriate flag
1722  residuals, GeneralisedElement::Dummy_matrix, compute_jacobian_flag);
1723  } // End of fill_in_pressure_advection_diffusion_residuals
1724 
1725 
1729  Vector<double>& residuals, DenseMatrix<double>& jacobian)
1730  {
1731  // Do we want to compute the Jacobian? ANSWER: Yes!
1732  unsigned compute_jacobian_flag = 1;
1733 
1734  // Call the generic routine with the appropriate flag
1736  residuals, jacobian, compute_jacobian_flag);
1737  } // End of fill_in_pressure_advection_diffusion_jacobian
1738 
1739 
1742  std::map<Data*, std::vector<int>>& eqn_number_backup)
1743  {
1744  // Loop over internal data and pin the values (having established that
1745  // pressure dofs aren't amongst those)
1746  unsigned nint = this->ninternal_data();
1747  for (unsigned j = 0; j < nint; j++)
1748  {
1749  Data* data_pt = this->internal_data_pt(j);
1750  if (eqn_number_backup[data_pt].size() == 0)
1751  {
1752  unsigned nvalue = data_pt->nvalue();
1753  eqn_number_backup[data_pt].resize(nvalue);
1754  for (unsigned i = 0; i < nvalue; i++)
1755  {
1756  // Backup
1757  eqn_number_backup[data_pt][i] = data_pt->eqn_number(i);
1758 
1759  // Pin everything
1760  data_pt->pin(i);
1761  }
1762  }
1763  }
1764 
1765  // Now deal with nodal values
1766  unsigned nnod = this->nnode();
1767  for (unsigned j = 0; j < nnod; j++)
1768  {
1769  Node* nod_pt = this->node_pt(j);
1770  if (eqn_number_backup[nod_pt].size() == 0)
1771  {
1772  unsigned nvalue = nod_pt->nvalue();
1773  eqn_number_backup[nod_pt].resize(nvalue);
1774  for (unsigned i = 0; i < nvalue; i++)
1775  {
1776  // Pin everything apart from the nodal pressure
1777  // value
1778  if (int(i) != this->p_nodal_index_nst())
1779  {
1780  // Backup
1781  eqn_number_backup[nod_pt][i] = nod_pt->eqn_number(i);
1782 
1783  // Pin
1784  nod_pt->pin(i);
1785  }
1786  // Else it's a pressure value
1787  else
1788  {
1789  // Exclude non-nodal pressure based elements
1790  if (this->p_nodal_index_nst() >= 0)
1791  {
1792  // Backup
1793  eqn_number_backup[nod_pt][i] = nod_pt->eqn_number(i);
1794  }
1795  }
1796  }
1797 
1798 
1799  // If it's a solid node deal with its positional data too
1800  SolidNode* solid_nod_pt = dynamic_cast<SolidNode*>(nod_pt);
1801  if (solid_nod_pt != 0)
1802  {
1803  Data* solid_posn_data_pt = solid_nod_pt->variable_position_pt();
1804  if (eqn_number_backup[solid_posn_data_pt].size() == 0)
1805  {
1806  unsigned nvalue = solid_posn_data_pt->nvalue();
1807  eqn_number_backup[solid_posn_data_pt].resize(nvalue);
1808  for (unsigned i = 0; i < nvalue; i++)
1809  {
1810  // Backup
1811  eqn_number_backup[solid_posn_data_pt][i] =
1812  solid_posn_data_pt->eqn_number(i);
1813 
1814  // Pin
1815  solid_posn_data_pt->pin(i);
1816  }
1817  }
1818  }
1819  }
1820  }
1821  } // End of pin_all_non_pressure_dofs
1822 
1823 
1828  const unsigned& face_index) = 0;
1829 
1830 
1835  std::ostream& outfile)
1836  {
1837  unsigned nel = Pressure_advection_diffusion_robin_element_pt.size();
1838  for (unsigned e = 0; e < nel; e++)
1839  {
1840  FaceElement* face_el_pt =
1842  outfile << "ZONE" << std::endl;
1843  Vector<double> unit_normal(DIM);
1844  Vector<double> x(DIM + 1);
1845  Vector<double> s(DIM);
1846  unsigned n = face_el_pt->integral_pt()->nweight();
1847  for (unsigned ipt = 0; ipt < n; ipt++)
1848  {
1849  for (unsigned i = 0; i < DIM; i++)
1850  {
1851  s[i] = face_el_pt->integral_pt()->knot(ipt, i);
1852  }
1853  face_el_pt->interpolated_x(s, x);
1854  face_el_pt->outer_unit_normal(ipt, unit_normal);
1855  for (unsigned i = 0; i < DIM + 1; i++)
1856  {
1857  outfile << x[i] << " ";
1858  }
1859  for (unsigned i = 0; i < DIM; i++)
1860  {
1861  outfile << unit_normal[i] << " ";
1862  }
1863  outfile << std::endl;
1864  }
1865  }
1866  } // End of output_pressure_advection_diffusion_robin_elements
1867 
1868 
1873  {
1874  unsigned nel = Pressure_advection_diffusion_robin_element_pt.size();
1875  for (unsigned e = 0; e < nel; e++)
1876  {
1878  }
1880  } // End of delete_pressure_advection_diffusion_robin_elements
1881 
1882 
1888  RankThreeTensor<double>& dresidual_dnodal_coordinates);
1889 
1890 
1893  Vector<double>& velocity) const
1894  {
1895  // Find the number of nodes
1896  unsigned n_node = nnode();
1897 
1898  // Local shape function
1899  Shape psi(n_node);
1900 
1901  // Find values of shape function
1902  shape(s, psi);
1903 
1904  // Loop over the velocity components
1905  for (unsigned i = 0; i < DIM; i++)
1906  {
1907  // Index at which the nodal value is stored
1908  unsigned u_nodal_index = u_index_nst(i);
1909 
1910  // Initialise the i-th value of the velocity vector
1911  velocity[i] = 0.0;
1912 
1913  // Loop over the local nodes and sum
1914  for (unsigned l = 0; l < n_node; l++)
1915  {
1916  // Update the i-th velocity component approximation
1917  velocity[i] += nodal_value(l, u_nodal_index) * psi[l];
1918  }
1919  } // for (unsigned i=0;i<DIM;i++)
1920  } // End of interpolated_u_nst
1921 
1922 
1924  double interpolated_u_nst(const Vector<double>& s, const unsigned& i) const
1925  {
1926  // Find the number of nodes
1927  unsigned n_node = nnode();
1928 
1929  // Local shape function
1930  Shape psi(n_node);
1931 
1932  // Find values of shape function
1933  shape(s, psi);
1934 
1935  // Get nodal index at which i-th velocity is stored
1936  unsigned u_nodal_index = u_index_nst(i);
1937 
1938  // Initialise value of u
1939  double interpolated_u = 0.0;
1940 
1941  // Loop over the local nodes and sum
1942  for (unsigned l = 0; l < n_node; l++)
1943  {
1944  // Update the i-th velocity component approximation
1945  interpolated_u += nodal_value(l, u_nodal_index) * psi[l];
1946  }
1947 
1948  // Return the calculated approximation to the i-th velocity component
1949  return interpolated_u;
1950  } // End of interpolated_u_nst
1951 
1952 
1955  double interpolated_u_nst(const unsigned& t,
1956  const Vector<double>& s,
1957  const unsigned& i) const
1958  {
1959  // Create an output stream
1960  std::ostringstream error_message_stream;
1961 
1962  // Create an error message
1963  error_message_stream << "This interface doesn't make sense in "
1964  << "space-time elements!" << std::endl;
1965 
1966  // Throw an error
1967  throw OomphLibError(error_message_stream.str(),
1970  } // End of interpolated_u_nst
1971 
1972 
1979  const unsigned& i,
1980  Vector<double>& du_ddata,
1981  Vector<unsigned>& global_eqn_number)
1982  {
1983  // Find the number of nodes
1984  unsigned n_node = nnode();
1985 
1986  // Local shape function
1987  Shape psi(n_node);
1988 
1989  // Find values of shape function
1990  shape(s, psi);
1991 
1992  // Get nodal index at which i-th velocity is stored
1993  unsigned u_nodal_index = u_index_nst(i);
1994 
1995  // Find the number of dofs associated with interpolated u
1996  unsigned n_u_dof = 0;
1997 
1998  // Loop over the nodes
1999  for (unsigned l = 0; l < n_node; l++)
2000  {
2001  // Get the global equation number of the dof
2002  int global_eqn = this->node_pt(l)->eqn_number(u_nodal_index);
2003 
2004  // If it's positive add to the count
2005  if (global_eqn >= 0)
2006  {
2007  // Increment the counter
2008  n_u_dof++;
2009  }
2010  } // End of dinterpolated_u_nst_ddata
2011 
2012  // Now resize the storage schemes
2013  du_ddata.resize(n_u_dof, 0.0);
2014  global_eqn_number.resize(n_u_dof, 0);
2015 
2016  // Loop over th nodes again and set the derivatives
2017  unsigned count = 0;
2018  // Loop over the local nodes and sum
2019  for (unsigned l = 0; l < n_node; l++)
2020  {
2021  // Get the global equation number
2022  int global_eqn = this->node_pt(l)->eqn_number(u_nodal_index);
2023  if (global_eqn >= 0)
2024  {
2025  // Set the global equation number
2026  global_eqn_number[count] = global_eqn;
2027  // Set the derivative with respect to the unknown
2028  du_ddata[count] = psi[l];
2029  // Increase the counter
2030  ++count;
2031  }
2032  }
2033  } // End of dinterpolated_u_nst_ddata
2034 
2035 
2037  virtual double interpolated_p_nst(const Vector<double>& s) const
2038  {
2039  // Find number of nodes
2040  unsigned n_pres = npres_nst();
2041  // Local shape function
2042  Shape psi(n_pres);
2043  // Find values of shape function
2044  pshape_nst(s, psi);
2045 
2046  // Initialise value of p
2047  double interpolated_p = 0.0;
2048  // Loop over the local nodes and sum
2049  for (unsigned l = 0; l < n_pres; l++)
2050  {
2051  interpolated_p += p_nst(l) * psi[l];
2052  }
2053 
2054  return (interpolated_p);
2055  }
2056 
2057 
2059  double interpolated_p_nst(const unsigned& t, const Vector<double>& s) const
2060  {
2061  // Find number of nodes
2062  unsigned n_pres = npres_nst();
2063  // Local shape function
2064  Shape psi(n_pres);
2065  // Find values of shape function
2066  pshape_nst(s, psi);
2067 
2068  // Initialise value of p
2069  double interpolated_p = 0.0;
2070  // Loop over the local nodes and sum
2071  for (unsigned l = 0; l < n_pres; l++)
2072  {
2073  interpolated_p += p_nst(t, l) * psi[l];
2074  }
2075 
2076  return (interpolated_p);
2077  }
2078 
2079 
2083  {
2084  // Resize data for values
2085  data.resize(2 * DIM + 2);
2086 
2087  // Write values in the vector
2088  for (unsigned i = 0; i < DIM + 1; i++)
2089  {
2090  // Output the i-th (Eulerian) coordinate at these local coordinates
2091  data[i] = interpolated_x(s, i);
2092  }
2093 
2094  // Write values in the vector
2095  for (unsigned i = 0; i < DIM; i++)
2096  {
2097  // Output the i-th velocity component at these local coordinates
2098  data[i + (DIM + 1)] = this->interpolated_u_nst(s, i);
2099  }
2100 
2101  // Output the pressure field value at these local coordinates
2102  data[2 * DIM + 1] = this->interpolated_p_nst(s);
2103  } // End of point_output_data
2104  };
2105 
2109 
2110  //=======================================================================
2115  //=======================================================================
2116  template<unsigned DIM>
2117  class QTaylorHoodSpaceTimeElement
2118  : public virtual QElement<DIM + 1, 3>,
2119  public virtual SpaceTimeNavierStokesEquations<DIM>
2120  {
2121  private:
2123  static const unsigned Initial_Nvalue[];
2124 
2125  protected:
2128  static const unsigned Pconv[];
2129 
2130 
2135  Shape& psi,
2136  DShape& dpsidx,
2137  Shape& test,
2138  DShape& dtestdx) const;
2139 
2140 
2144  inline double dshape_and_dtest_eulerian_at_knot_nst(const unsigned& ipt,
2145  Shape& psi,
2146  DShape& dpsidx,
2147  Shape& test,
2148  DShape& dtestdx) const;
2149 
2150 
2155  const unsigned& ipt,
2156  Shape& psi,
2157  DShape& dpsidx,
2158  RankFourTensor<double>& d_dpsidx_dX,
2159  Shape& test,
2160  DShape& dtestdx,
2161  RankFourTensor<double>& d_dtestdx_dX,
2162  DenseMatrix<double>& djacobian_dX) const;
2163 
2164 
2168  inline double dpshape_eulerian(const Vector<double>& s,
2169  Shape& ppsi,
2170  DShape& dppsidx) const;
2171 
2172 
2176  inline double dptest_eulerian(const Vector<double>& s,
2177  Shape& ptest,
2178  DShape& dptestdx) const;
2179 
2180 
2185  Shape& ppsi,
2186  DShape& dppsidx,
2187  Shape& ptest,
2188  DShape& dptestdx) const;
2189 
2190  public:
2194  {
2195  }
2196 
2197  // Destructor: delete the integration scheme
2199  {
2200  // Delete the integral pointer
2201  delete this->integral_pt();
2202  } // End of ~QTaylorHoodSpaceTimeElement
2203 
2206  inline virtual unsigned required_nvalue(const unsigned& n) const
2207  {
2208  // Return the appropriate entry from Initial_Nvalue
2209  return Initial_Nvalue[n];
2210  } // End of required_nvalue
2211 
2212 
2214  inline void pshape_nst(const Vector<double>& s, Shape& psi) const;
2215 
2216 
2218  inline void ptest_nst(const Vector<double>& s, Shape& psi) const;
2219 
2220 
2222  inline void pshape_nst(const Vector<double>& s,
2223  Shape& psi,
2224  Shape& test) const;
2225 
2226 
2228  virtual int p_nodal_index_nst() const
2229  {
2230  // The pressure is stored straight after the velocity components
2231  return static_cast<int>(DIM);
2232  } // End of p_nodal_index_nst
2233 
2234 
2236  inline int p_local_eqn(const unsigned& n) const
2237  {
2238  // Get the local equation number associated with the n-th pressure dof
2239  return this->nodal_local_eqn(Pconv[n], p_nodal_index_nst());
2240  } // End of p_local_eqn
2241 
2242 
2245  double p_nst(const unsigned& n_p) const
2246  {
2247  // Get the nodal value associated with the n_p-th pressure dof
2248  return this->nodal_value(Pconv[n_p], this->p_nodal_index_nst());
2249  } // End of p_nst
2250 
2251 
2254  double p_nst(const unsigned& t, const unsigned& n_p) const
2255  {
2256  // Return the pressure value of the n_p-th pressure dof at time-level t
2257  return this->nodal_value(t, Pconv[n_p], this->p_nodal_index_nst());
2258  } // End of p_nst
2259 
2260 
2262  unsigned npres_nst() const
2263  {
2264  // There are 2^{DIM+1} pressure dofs where DIM is the spatial dimension
2265  // (rememebering that these are space-time elements)
2266  return static_cast<unsigned>(pow(2.0, static_cast<int>(DIM + 1)));
2267  } // End of npres_nst
2268 
2269 
2271  void fix_pressure(const unsigned& p_dof, const double& p_value)
2272  {
2273  // Pin the pressure dof
2274  this->node_pt(Pconv[p_dof])->pin(this->p_nodal_index_nst());
2275 
2276  // Now set its value
2277  this->node_pt(Pconv[p_dof])
2278  ->set_value(this->p_nodal_index_nst(), p_value);
2279  } // End of fix_pressure
2280 
2281 
2285  void build_fp_press_adv_diff_robin_bc_element(const unsigned& face_index)
2286  {
2287  // Create a new Robic BC element and add it to the storage
2290  QTaylorHoodSpaceTimeElement<DIM>>(this, face_index));
2291  } // End of build_fp_press_adv_diff_robin_bc_element
2292 
2293 
2302  std::set<std::pair<Data*, unsigned>>& paired_load_data);
2303 
2304 
2314  std::set<std::pair<Data*, unsigned>>& paired_pressure_data);
2315 
2316 
2318  void output(std::ostream& outfile)
2319  {
2320  // Call the base class implementation
2322  } // End of output
2323 
2324 
2326  void output(std::ostream& outfile, const unsigned& nplot)
2327  {
2328  // Call the base class implementation
2330  } // End of output
2331 
2332 
2334  void output(FILE* file_pt)
2335  {
2336  // Call the base class implementation
2338  } // End of output
2339 
2340 
2342  void output(FILE* file_pt, const unsigned& nplot)
2343  {
2344  // Call the base class implementation
2346  } // End of output
2347 
2348  /*
2352  unsigned ndof_types() const
2353  {
2354  // Return the number of dof types being used in the mesh
2355  return DIM+1;
2356  } // End of ndof_types
2357 
2369  void get_dof_numbers_for_unknowns(
2370  std::list<std::pair<unsigned long,unsigned> >& dof_lookup_list) const;
2371  */
2372  };
2373 
2374  // Inline functions:
2375 
2376  //==========================================================================
2380  //==========================================================================
2381  template<unsigned DIM>
2383  const Vector<double>& s,
2384  Shape& psi,
2385  DShape& dpsidx,
2386  Shape& test,
2387  DShape& dtestdx) const
2388  {
2389  //--------------------------
2390  // Call the shape functions:
2391  //--------------------------
2392  // Find the element dimension
2393  const unsigned el_dim = this->dim();
2394 
2395  // Get the values of the shape functions and their local derivatives,
2396  // temporarily stored in dpsi
2397  this->dshape_local(s, psi, dpsidx);
2398 
2399  // Allocate memory for the inverse jacobian
2400  DenseMatrix<double> inverse_jacobian(el_dim);
2401 
2402  // Now calculate the inverse jacobian
2403  const double det =
2404  this->local_to_eulerian_mapping(dpsidx, inverse_jacobian);
2405 
2406  // Now set the values of the derivatives to be dpsidx
2407  this->transform_derivatives(inverse_jacobian, dpsidx);
2408 
2409  //-------------------------
2410  // Call the test functions:
2411  //-------------------------
2412  // Make sure we're using 3D elements
2413  if (el_dim != 3)
2414  {
2415  // Create an output stream
2416  std::ostringstream error_message_stream;
2417 
2418  // Create an error message
2419  error_message_stream << "Need 3D space-time elements for this to work!"
2420  << std::endl;
2421 
2422  // Throw the error message
2423  throw OomphLibError(error_message_stream.str(),
2426  }
2427 
2428  //--------start_of_dshape_local--------------------------------------
2429  // Local storage
2430  double test_values[3][3];
2431  double dtest_values[3][3];
2432 
2433  // Index of the total shape function
2434  unsigned index = 0;
2435 
2436  // Call the 1D shape functions and derivatives
2437  OneDimLagrange::shape<3>(s[0], test_values[0]);
2438  OneDimLagrange::shape<3>(s[1], test_values[1]);
2439  OneDimLagrange::dshape<3>(s[0], dtest_values[0]);
2440  OneDimLagrange::dshape<3>(s[1], dtest_values[1]);
2441 
2442  // Set the time discretisation
2443  // OneDimLagrange::shape<3>(s[2],test_values[2]);
2444  // OneDimLagrange::dshape<3>(s[2],dtest_values[2]);
2445  OneDimDiscontinuousGalerkin::shape<3>(s[2], test_values[2]);
2446  OneDimDiscontinuousGalerkin::dshape<3>(s[2], dtest_values[2]);
2447 
2448  // Loop over the nodes in the third local coordinate direction
2449  for (unsigned k = 0; k < 3; k++)
2450  {
2451  // Loop over the nodes in the second local coordinate direction
2452  for (unsigned j = 0; j < 3; j++)
2453  {
2454  // Loop over the nodes in the first local coordinate direction
2455  for (unsigned i = 0; i < 3; i++)
2456  {
2457  // Calculate dtest/ds_0
2458  dtestdx(index, 0) =
2459  dtest_values[0][i] * test_values[1][j] * test_values[2][k];
2460 
2461  // Calculate dtest/ds_1
2462  dtestdx(index, 1) =
2463  test_values[0][i] * dtest_values[1][j] * test_values[2][k];
2464 
2465  // Calculate dtest/ds_2
2466  dtestdx(index, 2) =
2467  test_values[0][i] * test_values[1][j] * dtest_values[2][k];
2468 
2469  // Calculate the index-th entry of test
2470  test[index] =
2471  test_values[0][i] * test_values[1][j] * test_values[2][k];
2472 
2473  // Increment the index
2474  index++;
2475  }
2476  } // for (unsigned j=0;j<3;j++)
2477  } // for (unsigned k=0;k<3;k++)
2478  //--------end_of_dshape_local----------------------------------------
2479 
2480  // Transform derivatives from dtest/ds to dtest/dx
2481  this->transform_derivatives(inverse_jacobian, dtestdx);
2482 
2483  // Return the determinant value
2484  return det;
2485  } // End of dshape_and_dtest_eulerian_nst
2486 
2487  //==========================================================================
2491  //==========================================================================
2492  template<unsigned DIM>
2493  inline double QTaylorHoodSpaceTimeElement<
2494  DIM>::dshape_and_dtest_eulerian_at_knot_nst(const unsigned& ipt,
2495  Shape& psi,
2496  DShape& dpsidx,
2497  Shape& test,
2498  DShape& dtestdx) const
2499  {
2500  // Calculate the element dimension
2501  const unsigned el_dim = DIM + 1;
2502 
2503  // Storage for the local coordinates of the integration point
2504  Vector<double> s(el_dim, 0.0);
2505 
2506  // Set the local coordinate
2507  for (unsigned i = 0; i < el_dim; i++)
2508  {
2509  // Calculate the i-th local coordinate at the ipt-th knot point
2510  s[i] = this->integral_pt()->knot(ipt, i);
2511  }
2512 
2513  // Return the Jacobian of the geometrical shape functions and derivatives
2514  return dshape_and_dtest_eulerian_nst(s, psi, dpsidx, test, dtestdx);
2515  } // End of dshape_and_dtest_eulerian_at_knot_nst
2516 
2517 
2518  //==========================================================================
2522  //==========================================================================
2523  template<>
2525  const Vector<double>& s, Shape& ppsi, DShape& dppsidx) const
2526  {
2527  // Local storage for the shape function (x-direction)
2528  double psi1[2];
2529 
2530  // Local storage for the shape function (y-direction)
2531  double psi2[2];
2532 
2533  // Local storage for the shape function (z-direction)
2534  double psi3[2];
2535 
2536  // Local storage for the shape function derivatives (x-direction)
2537  double dpsi1[2];
2538 
2539  // Local storage for the test function derivatives (y-direction)
2540  double dpsi2[2];
2541 
2542  // Local storage for the test function derivatives (z-direction)
2543  double dpsi3[2];
2544 
2545  // Call the OneDimensional Shape functions
2546  OneDimLagrange::shape<2>(s[0], psi1);
2547 
2548  // Call the OneDimensional Shape functions
2549  OneDimLagrange::shape<2>(s[1], psi2);
2550 
2551  // Call the OneDimensional Shape functions
2552  OneDimLagrange::shape<2>(s[2], psi3);
2553 
2554  // Call the OneDimensional Shape functions
2555  OneDimLagrange::dshape<2>(s[0], dpsi1);
2556 
2557  // Call the OneDimensional Shape functions
2558  OneDimLagrange::dshape<2>(s[1], dpsi2);
2559 
2560  // Call the OneDimensional Shape functions
2561  OneDimLagrange::dshape<2>(s[2], dpsi3);
2562 
2563  //--------------------------------------------------------------------
2564  // Now let's loop over the nodal points in the element with s1 being
2565  // the "x" coordinate, s2 being the "y" coordinate and s3 being the
2566  // "z" coordinate:
2567  //--------------------------------------------------------------------
2568  // Loop over the points in the z-direction
2569  for (unsigned i = 0; i < 2; i++)
2570  {
2571  // Loop over the points in the y-direction
2572  for (unsigned j = 0; j < 2; j++)
2573  {
2574  // Loop over the points in the x-direction
2575  for (unsigned k = 0; k < 2; k++)
2576  {
2577  // Multiply the three 1D functions together to get the 3D function
2578  ppsi[4 * i + 2 * j + k] = psi3[i] * psi2[j] * psi1[k];
2579 
2580  // Multiply the appropriate shape and shape function derivatives
2581  // together
2582  dppsidx(4 * i + 2 * j + k, 0) = psi3[i] * psi2[j] * dpsi1[k];
2583 
2584  // Multiply the appropriate shape and shape function derivatives
2585  // together
2586  dppsidx(4 * i + 2 * j + k, 1) = psi3[i] * dpsi2[j] * psi1[k];
2587 
2588  // Multiply the appropriate shape and shape function derivatives
2589  // together
2590  dppsidx(4 * i + 2 * j + k, 2) = dpsi3[i] * psi2[j] * psi1[k];
2591  }
2592  } // for (unsigned j=0;j<2;j++)
2593  } // for (unsigned i=0;i<2;i++)
2594 
2595  // Allocate space for the geometrical shape functions
2596  Shape psi(27);
2597 
2598  // Allocate space for the geometrical shape function derivatives
2599  DShape dpsi(27, 3);
2600 
2601  // Get the values of the shape functions and their derivatives
2602  dshape_local(s, psi, dpsi);
2603 
2604  // Allocate memory for the 3x3 inverse jacobian
2605  DenseMatrix<double> inverse_jacobian(3);
2606 
2607  // Now calculate the inverse jacobian
2608  const double det = local_to_eulerian_mapping(dpsi, inverse_jacobian);
2609 
2610  // Now set the values of the derivatives to be derivatives w.r.t. to
2611  // the Eulerian coordinates
2612  transform_derivatives(inverse_jacobian, dppsidx);
2613 
2614  // Return the determinant of the jacobian
2615  return det;
2616  } // End of dpshape_eulerian
2617 
2618 
2619  //==========================================================================
2623  //==========================================================================
2624  template<>
2626  const Vector<double>& s, Shape& ptest, DShape& dptestdx) const
2627  {
2628  // Local storage for the shape function (x-direction)
2629  double test1[2];
2630 
2631  // Local storage for the shape function (y-direction)
2632  double test2[2];
2633 
2634  // Local storage for the shape function (z-direction)
2635  double test3[2];
2636 
2637  // Local storage for the shape function derivatives (x-direction)
2638  double dtest1[2];
2639 
2640  // Local storage for the test function derivatives (y-direction)
2641  double dtest2[2];
2642 
2643  // Local storage for the test function derivatives (z-direction)
2644  double dtest3[2];
2645 
2646  // Call the OneDimensional Shape functions
2648 
2649  // Call the OneDimensional Shape functions
2651 
2652  // Call the OneDimensional Shape functions
2653  // OneDimLagrange::shape<2>(s[2],test3);
2655 
2656  // Call the OneDimensional Shape functions
2657  OneDimLagrange::dshape<2>(s[0], dtest1);
2658 
2659  // Call the OneDimensional Shape functions
2660  OneDimLagrange::dshape<2>(s[1], dtest2);
2661 
2662  // Call the OneDimensional Shape functions
2663  // OneDimLagrange::dshape<2>(s[2],dtest3);
2665 
2666  //--------------------------------------------------------------------
2667  // Now let's loop over the nodal points in the element with s1 being
2668  // the "x" coordinate, s2 being the "y" coordinate and s3 being the
2669  // "z" coordinate:
2670  //--------------------------------------------------------------------
2671  // Loop over the points in the z-direction
2672  for (unsigned i = 0; i < 2; i++)
2673  {
2674  // Loop over the points in the y-direction
2675  for (unsigned j = 0; j < 2; j++)
2676  {
2677  // Loop over the points in the x-direction
2678  for (unsigned k = 0; k < 2; k++)
2679  {
2680  // Multiply the three 1D functions together to get the 3D function
2681  ptest[4 * i + 2 * j + k] = test3[i] * test2[j] * test1[k];
2682 
2683  // Multiply the appropriate shape and shape function derivatives
2684  // together
2685  dptestdx(4 * i + 2 * j + k, 0) = test3[i] * test2[j] * dtest1[k];
2686 
2687  // Multiply the appropriate shape and shape function derivatives
2688  // together
2689  dptestdx(4 * i + 2 * j + k, 1) = test3[i] * dtest2[j] * test1[k];
2690 
2691  // Multiply the appropriate shape and shape function derivatives
2692  // together
2693  dptestdx(4 * i + 2 * j + k, 2) = dtest3[i] * test2[j] * test1[k];
2694  }
2695  } // for (unsigned j=0;j<2;j++)
2696  } // for (unsigned i=0;i<2;i++)
2697 
2698  // Allocate space for the geometrical shape functions
2699  Shape psi(27);
2700 
2701  // Allocate space for the geometrical shape function derivatives
2702  DShape dpsi(27, 3);
2703 
2704  // Get the values of the shape functions and their derivatives
2705  dshape_local(s, psi, dpsi);
2706 
2707  // Allocate memory for the 3x3 inverse jacobian
2708  DenseMatrix<double> inverse_jacobian(3);
2709 
2710  // Now calculate the inverse jacobian
2711  const double det = local_to_eulerian_mapping(dpsi, inverse_jacobian);
2712 
2713  // Now set the values of the derivatives to be derivatives w.r.t. to
2714  // the Eulerian coordinates
2715  transform_derivatives(inverse_jacobian, dptestdx);
2716 
2717  // Return the determinant of the jacobian
2718  return det;
2719  } // End of dptest_eulerian
2720 
2721 
2722  //==========================================================================
2726  //==========================================================================
2727  template<>
2729  const Vector<double>& s,
2730  Shape& ppsi,
2731  DShape& dppsidx,
2732  Shape& ptest,
2733  DShape& dptestdx) const
2734  {
2735  // Call the test functions and derivatives
2736  dptest_eulerian(s, ptest, dptestdx);
2737 
2738  // Call the shape functions and derivatives and the Jacobian of the mapping
2739  return this->dpshape_eulerian(s, ppsi, dppsidx);
2740  } // End of dpshape_and_dptest_eulerian_nst
2741 
2742 
2743  //==========================================================================
2751  //==========================================================================
2752  template<>
2755  const unsigned& ipt,
2756  Shape& psi,
2757  DShape& dpsidx,
2758  RankFourTensor<double>& d_dpsidx_dX,
2759  Shape& test,
2760  DShape& dtestdx,
2761  RankFourTensor<double>& d_dtestdx_dX,
2762  DenseMatrix<double>& djacobian_dX) const
2763  {
2764  // Call the geometrical shape functions and derivatives
2765  const double J = this->dshape_eulerian_at_knot(
2766  ipt, psi, dpsidx, djacobian_dX, d_dpsidx_dX);
2767 
2768  // DRAIG: Delete!
2769  throw OomphLibError("Hasn't been implemented properly yet!",
2772 
2773  // Loop over the test functions and derivatives
2774  for (unsigned i = 0; i < 27; i++)
2775  {
2776  // The test functions are the same as the shape functions
2777  test[i] = psi[i];
2778 
2779  // Loop over the spatial derivatives
2780  for (unsigned k = 0; k < 3; k++)
2781  {
2782  // Set the test function derivatives to the shape function derivatives
2783  dtestdx(i, k) = dpsidx(i, k);
2784 
2785  // Loop over the dimensions
2786  for (unsigned p = 0; p < 3; p++)
2787  {
2788  // Loop over test functions
2789  for (unsigned q = 0; q < 27; q++)
2790  {
2791  // Set the test function derivatives to the shape function
2792  // derivatives
2793  d_dtestdx_dX(p, q, i, k) = d_dpsidx_dX(p, q, i, k);
2794  }
2795  } // for (unsigned p=0;p<3;p++)
2796  } // for (unsigned k=0;k<3;k++)
2797  } // for (unsigned i=0;i<27;i++)
2798 
2799  // Return the jacobian
2800  return J;
2801  } // End of dshape_and_dtest_eulerian_at_knot_nst
2802 
2803 
2804  //==========================================================================
2806  //==========================================================================
2807  template<>
2809  const Vector<double>& s, Shape& psi) const
2810  {
2811  // Local storage for the shape function value (in the x-direction)
2812  double psi1[2];
2813 
2814  // Local storage for the shape function value (in the y-direction)
2815  double psi2[2];
2816 
2817  // Local storage for the shape function value (in the z-direction)
2818  double psi3[2];
2819 
2820  // Call the OneDimensional Shape functions
2821  OneDimLagrange::shape<2>(s[0], psi1);
2822 
2823  // Call the OneDimensional Shape functions
2824  OneDimLagrange::shape<2>(s[1], psi2);
2825 
2826  // Call the OneDimensional Shape functions
2827  OneDimLagrange::shape<2>(s[2], psi3);
2828 
2829  //--------------------------------------------------------------------
2830  // Now let's loop over the nodal points in the element with s1 being
2831  // the "x" coordinate, s2 being the "y" coordinate and s3 being the
2832  // "z" coordinate:
2833  //--------------------------------------------------------------------
2834  // Loop over the points in the z-direction
2835  for (unsigned i = 0; i < 2; i++)
2836  {
2837  // Loop over the points in the y-direction
2838  for (unsigned j = 0; j < 2; j++)
2839  {
2840  // Loop over the points in the x-direction
2841  for (unsigned k = 0; k < 2; k++)
2842  {
2843  // Multiply the three 1D functions together to get the 3D function
2844  psi[4 * i + 2 * j + k] = psi3[i] * psi2[j] * psi1[k];
2845  }
2846  } // for (unsigned j=0;j<2;j++)
2847  } // for (unsigned i=0;i<2;i++)
2848  } // End of pshape_nst
2849 
2850 
2851  //==========================================================================
2853  //==========================================================================
2854  template<>
2856  Shape& test) const
2857  {
2858  // Local storage for the shape function value (in the x-direction)
2859  double test1[2];
2860 
2861  // Local storage for the shape function value (in the y-direction)
2862  double test2[2];
2863 
2864  // Local storage for the shape function value (in the z-direction)
2865  double test3[2];
2866 
2867  // Call the OneDimensional Shape functions
2869 
2870  // Call the OneDimensional Shape functions
2872 
2873  // Call the OneDimensional Shape functions
2875 
2876  //--------------------------------------------------------------------
2877  // Now let's loop over the nodal points in the element with s1 being
2878  // the "x" coordinate, s2 being the "y" coordinate and s3 being the
2879  // "z" coordinate:
2880  //--------------------------------------------------------------------
2881  // Loop over the points in the z-direction
2882  for (unsigned i = 0; i < 2; i++)
2883  {
2884  // Loop over the points in the y-direction
2885  for (unsigned j = 0; j < 2; j++)
2886  {
2887  // Loop over the points in the x-direction
2888  for (unsigned k = 0; k < 2; k++)
2889  {
2890  // Multiply the three 1D functions together to get the 3D function
2891  test[4 * i + 2 * j + k] = test3[i] * test2[j] * test1[k];
2892  }
2893  } // for (unsigned j=0;j<2;j++)
2894  } // for (unsigned i=0;i<2;i++)
2895  } // End of ptest_nst
2896 
2897 
2898  //==========================================================================
2900  //==========================================================================
2901  template<unsigned DIM>
2903  const Vector<double>& s, Shape& psi, Shape& test) const
2904  {
2905  // Call the pressure shape functions
2906  pshape_nst(s, psi);
2907 
2908  // Call the pressure test functions
2909  ptest_nst(s, test);
2910  } // End of pshape_nst
2911 
2912 
2913  //=======================================================================
2915  //=======================================================================
2916  template<>
2917  class FaceGeometry<QTaylorHoodSpaceTimeElement<2>>
2918  : public virtual QElement<2, 3>
2919  {
2920  public:
2922  FaceGeometry() : QElement<2, 3>() {}
2923  };
2924 
2925  //=======================================================================
2927  //=======================================================================
2928  template<>
2929  class FaceGeometry<FaceGeometry<QTaylorHoodSpaceTimeElement<2>>>
2930  : public virtual QElement<1, 3>
2931  {
2932  public:
2934  FaceGeometry() : QElement<1, 3>() {}
2935  };
2936 
2940 
2941  //==========================================================
2943  //==========================================================
2944  template<class TAYLOR_HOOD_ELEMENT>
2945  class ProjectableTaylorHoodSpaceTimeElement
2946  : public virtual ProjectableElement<TAYLOR_HOOD_ELEMENT>
2947  {
2948  public:
2952 
2953 
2961  {
2962  // Create the vector
2963  Vector<std::pair<Data*, unsigned>> data_values;
2964 
2965  // If we're dealing with the velocity dofs
2966  if (fld < this->dim() - 1)
2967  {
2968  // How many nodes in the element?
2969  unsigned nnod = this->nnode();
2970 
2971  // Loop over all nodes
2972  for (unsigned j = 0; j < nnod; j++)
2973  {
2974  // Add the data value associated with the velocity components
2975  data_values.push_back(std::make_pair(this->node_pt(j), fld));
2976  }
2977  }
2978  // If we're dealing with the pressure dof
2979  else
2980  {
2981  // How many pressure dofs are there?
2982  // DRAIG: Shouldn't there be more?
2983  unsigned Pconv_size = this->dim();
2984 
2985  // Loop over all vertex nodes
2986  for (unsigned j = 0; j < Pconv_size; j++)
2987  {
2988  // Get the vertex index associated with the j-th pressure dof
2989  unsigned vertex_index = this->Pconv[j];
2990 
2991  // Add the data value associated with the pressure components
2992  data_values.push_back(
2993  std::make_pair(this->node_pt(vertex_index), fld));
2994  }
2995  } // if (fld<this->dim())
2996 
2997  // Return the vector
2998  return data_values;
2999  } // End of data_values_of_field
3000 
3001 
3005  {
3006  // There are dim velocity dofs and 1 pressure dof
3007  return this->dim();
3008  } // End of nfields_for_projection
3009 
3010 
3014  unsigned nhistory_values_for_projection(const unsigned& fld)
3015  {
3016  // If we're dealing with the pressure dof
3017  if (fld == this->dim())
3018  {
3019  // Pressure doesn't have history values
3020  return this->node_pt(0)->ntstorage();
3021  }
3022  // If we're dealing with the velocity dofs
3023  else
3024  {
3025  // The velocity dofs have ntstorage() history values
3026  return this->node_pt(0)->ntstorage();
3027  }
3028  } // End of nhistory_values_for_projection
3029 
3030 
3034  {
3035  // Return the number of positional history values
3036  return this->node_pt(0)->position_time_stepper_pt()->ntstorage();
3037  } // End of nhistory_values_for_coordinate_projection
3038 
3039 
3042  double jacobian_and_shape_of_field(const unsigned& fld,
3043  const Vector<double>& s,
3044  Shape& psi)
3045  {
3046  // How many dimensions in this element?
3047  unsigned n_dim = this->dim();
3048 
3049  // How many nodes in this element?
3050  unsigned n_node = this->nnode();
3051 
3052  // If we're on the pressure dof
3053  if (fld == n_dim)
3054  {
3055  // Call the pressure interpolation function
3056  this->pshape_nst(s, psi);
3057 
3058  // Allocate space for the pressure shape function
3059  Shape psif(n_node);
3060 
3061  // Allocate space for the pressure test function
3062  Shape testf(n_node);
3063 
3064  // Allocate space for the pressure shape function derivatives
3065  DShape dpsifdx(n_node, n_dim);
3066 
3067  // Allocate space for the pressure test function derivatives
3068  DShape dtestfdx(n_node, n_dim);
3069 
3070  // Calculate the Jacobian of the mapping
3071  double J = this->dshape_and_dtest_eulerian_nst(
3072  s, psif, dpsifdx, testf, dtestfdx);
3073 
3074  // Return the Jacobian
3075  return J;
3076  }
3077  // If we're on the velocity components
3078  else
3079  {
3080  // Allocate space for the test functions
3081  Shape testf(n_node);
3082 
3083  // Allocate space for the shape function derivatives
3084  DShape dpsifdx(n_node, n_dim);
3085 
3086  // Allocate space for the test function derivatives
3087  DShape dtestfdx(n_node, n_dim);
3088 
3089  // Calculate the Jacobian of the mapping
3090  double J =
3091  this->dshape_and_dtest_eulerian_nst(s, psi, dpsifdx, testf, dtestfdx);
3092 
3093  // Return the Jacobian
3094  return J;
3095  }
3096  } // End of jacobian_and_shape_of_field
3097 
3098 
3101  double get_field(const unsigned& t,
3102  const unsigned& fld,
3103  const Vector<double>& s)
3104  {
3105  unsigned n_dim = this->dim();
3106  unsigned n_node = this->nnode();
3107 
3108  // If fld=n_dim, we deal with the pressure
3109  if (fld == n_dim)
3110  {
3111  return this->interpolated_p_nst(t, s);
3112  }
3113  // Velocity
3114  else
3115  {
3116  // Find the index at which the variable is stored
3117  unsigned u_nodal_index = this->u_index_nst(fld);
3118 
3119  // Local shape function
3120  Shape psi(n_node);
3121 
3122  // Find values of shape function
3123  this->shape(s, psi);
3124 
3125  // Initialise value of u
3126  double interpolated_u = 0.0;
3127 
3128  // Sum over the local nodes at that time
3129  for (unsigned l = 0; l < n_node; l++)
3130  {
3131  interpolated_u += this->nodal_value(t, l, u_nodal_index) * psi[l];
3132  }
3133  return interpolated_u;
3134  }
3135  }
3136 
3137 
3139  unsigned nvalue_of_field(const unsigned& fld)
3140  {
3141  if (fld == this->dim())
3142  {
3143  return this->npres_nst();
3144  }
3145  else
3146  {
3147  return this->nnode();
3148  }
3149  }
3150 
3151 
3153  int local_equation(const unsigned& fld, const unsigned& j)
3154  {
3155  if (fld == this->dim())
3156  {
3157  return this->p_local_eqn(j);
3158  }
3159  else
3160  {
3161  const unsigned u_nodal_index = this->u_index_nst(fld);
3162  return this->nodal_local_eqn(j, u_nodal_index);
3163  }
3164  }
3165  };
3166 
3167 
3168  //=======================================================================
3171  //=======================================================================
3172  template<class ELEMENT>
3173  class FaceGeometry<ProjectableTaylorHoodSpaceTimeElement<ELEMENT>>
3174  : public virtual FaceGeometry<ELEMENT>
3175  {
3176  public:
3177  FaceGeometry() : FaceGeometry<ELEMENT>() {}
3178  };
3179 
3180  //=======================================================================
3183  //=======================================================================
3184  template<class ELEMENT>
3185  class FaceGeometry<
3186  FaceGeometry<ProjectableTaylorHoodSpaceTimeElement<ELEMENT>>>
3187  : public virtual FaceGeometry<FaceGeometry<ELEMENT>>
3188  {
3189  public:
3191  };
3192 
3193 } // End of namespace oomph
3194 
3195 #endif
Matrix< Scalar, Dynamic, Dynamic > DenseMatrix
Definition: BenchSparseUtil.h:23
int i
Definition: BiCGSTAB_step_by_step.cpp:9
const unsigned n
Definition: CG3DPackingUnitTest.cpp:11
Array< double, 1, 3 > e(1./3., 0.5, 2.)
JacobiRotation< float > J
Definition: Jacobi_makeJacobi.cpp:3
int data[]
Definition: Map_placement_new.cpp:1
RowVector3d w
Definition: Matrix_resize_int.cpp:3
void load(Archive &ar, ParticleHandler &handl)
Definition: Particles.h:21
void test2()
Definition: QuaternionUnitTest.cpp:65
void test1()
Definition: QuaternionUnitTest.cpp:9
float * p
Definition: Tutorial_Map_using.cpp:9
Definition: shape.h:278
Definition: nodes.h:86
long & eqn_number(const unsigned &i)
Return the equation number of the i-th stored variable.
Definition: nodes.h:367
void pin(const unsigned &i)
Pin the i-th stored variable.
Definition: nodes.h:385
double * value_pt(const unsigned &i) const
Definition: nodes.h:324
void set_value(const unsigned &i, const double &value_)
Definition: nodes.h:271
unsigned nvalue() const
Return number of values stored in data object (incl pinned ones).
Definition: nodes.h:483
Definition: fsi.h:63
Definition: elements.h:4338
int & face_index()
Definition: elements.h:4626
void outer_unit_normal(const Vector< double > &s, Vector< double > &unit_normal) const
Compute outer unit normal at the specified local coordinate.
Definition: elements.cc:6006
double interpolated_x(const Vector< double > &s, const unsigned &i) const
Definition: elements.h:4528
FaceGeometry()
Definition: discontinuous_galerkin_spacetime_navier_stokes_elements.h:3190
FaceGeometry()
Constructor; empty.
Definition: discontinuous_galerkin_spacetime_navier_stokes_elements.h:2934
FaceGeometry()
Definition: discontinuous_galerkin_spacetime_navier_stokes_elements.h:3177
FaceGeometry()
Constructor; empty.
Definition: discontinuous_galerkin_spacetime_navier_stokes_elements.h:2922
Definition: elements.h:4998
Definition: elements.h:1313
virtual unsigned nplot_points_paraview(const unsigned &nplot) const
Definition: elements.h:2862
virtual void local_coordinate_of_node(const unsigned &j, Vector< double > &s) const
Definition: elements.h:1842
Node *& node_pt(const unsigned &n)
Return a pointer to the local node n.
Definition: elements.h:2175
double nodal_value(const unsigned &n, const unsigned &i) const
Definition: elements.h:2593
virtual void output(std::ostream &outfile)
Definition: elements.h:3050
double size() const
Definition: elements.cc:4290
virtual void build_face_element(const int &face_index, FaceElement *face_element_pt)
Definition: elements.cc:5132
virtual double interpolated_x(const Vector< double > &s, const unsigned &i) const
Return FE interpolated coordinate x[i] at local coordinate s.
Definition: elements.cc:3962
virtual void shape(const Vector< double > &s, Shape &psi) const =0
int nodal_local_eqn(const unsigned &n, const unsigned &i) const
Definition: elements.h:1432
unsigned dim() const
Definition: elements.h:2611
unsigned nnode() const
Return the number of nodes.
Definition: elements.h:2210
void(* SteadyExactSolutionFctPt)(const Vector< double > &, Vector< double > &)
Definition: elements.h:1759
Integral *const & integral_pt() const
Return the pointer to the integration scheme (const version)
Definition: elements.h:1963
virtual void get_s_plot(const unsigned &i, const unsigned &nplot, Vector< double > &s, const bool &shifted_to_interior=false) const
Definition: elements.h:3148
void(* UnsteadyExactSolutionFctPt)(const double &, const Vector< double > &, Vector< double > &)
Definition: elements.h:1765
double dshape_eulerian(const Vector< double > &s, Shape &psi, DShape &dpsidx) const
Definition: elements.cc:3298
bool has_hanging_nodes() const
Definition: elements.h:2470
Definition: discontinuous_galerkin_equal_order_pressure_spacetime_navier_stokes_elements.h:47
virtual ~FpPressureAdvDiffRobinBCSpaceTimeElementBase()
Empty virtual destructor.
Definition: discontinuous_galerkin_spacetime_navier_stokes_elements.h:53
FpPressureAdvDiffRobinBCSpaceTimeElementBase()
Constructor.
Definition: discontinuous_galerkin_spacetime_navier_stokes_elements.h:50
virtual void fill_in_generic_residual_contribution_fp_press_adv_diff_robin_bc(Vector< double > &residuals, DenseMatrix< double > &jacobian, const unsigned &compute_jacobian_flag)=0
Definition: discontinuous_galerkin_equal_order_pressure_spacetime_navier_stokes_elements.h:81
void output(std::ostream &outfile, const unsigned &nplot)
Output function: x,y,[z],u,v,[w],p in tecplot format.
Definition: discontinuous_galerkin_spacetime_navier_stokes_elements.h:192
void output(std::ostream &outfile)
Overload the output function.
Definition: discontinuous_galerkin_spacetime_navier_stokes_elements.h:184
void fill_in_contribution_to_residuals(Vector< double > &residuals)
This function returns just the residuals.
Definition: discontinuous_galerkin_spacetime_navier_stokes_elements.h:147
virtual void fill_in_generic_residual_contribution_fp_press_adv_diff_robin_bc(Vector< double > &residuals, DenseMatrix< double > &jacobian, const unsigned &flag)
Definition: discontinuous_galerkin_equal_order_pressure_spacetime_navier_stokes_elements.h:212
FpPressureAdvDiffRobinBCSpaceTimeElement(FiniteElement *const &element_pt, const int &face_index, const bool &called_from_refineable_constructor=false)
Definition: discontinuous_galerkin_spacetime_navier_stokes_elements.h:86
~FpPressureAdvDiffRobinBCSpaceTimeElement()
Empty destructor.
Definition: discontinuous_galerkin_spacetime_navier_stokes_elements.h:134
void fill_in_contribution_to_jacobian(Vector< double > &residuals, DenseMatrix< double > &jacobian)
This function returns the residuals and the jacobian.
Definition: discontinuous_galerkin_spacetime_navier_stokes_elements.h:165
virtual void fill_in_generic_residual_contribution_fp_press_adv_diff_robin_bc(Vector< double > &residuals, DenseMatrix< double > &jacobian, const unsigned &flag)
static double Default_fd_jacobian_step
Definition: elements.h:1198
Data *& external_data_pt(const unsigned &i)
Return a pointer to i-th external data object.
Definition: elements.h:659
Data *& internal_data_pt(const unsigned &i)
Return a pointer to i-th internal data object.
Definition: elements.h:622
unsigned ninternal_data() const
Return the number of internal data objects.
Definition: elements.h:823
unsigned add_external_data(Data *const &data_pt, const bool &fd=true)
Definition: elements.cc:307
static DenseMatrix< double > Dummy_matrix
Definition: elements.h:227
virtual double knot(const unsigned &i, const unsigned &j) const =0
Return local coordinate s[j] of i-th integration point.
virtual unsigned nweight() const =0
Return the number of integration points of the scheme.
Definition: matrices.h:74
Definition: nodes.h:906
Definition: oomph_definitions.h:222
double get_field(const unsigned &t, const unsigned &fld, const Vector< double > &s)
Definition: discontinuous_galerkin_spacetime_navier_stokes_elements.h:3101
unsigned nfields_for_projection()
Definition: discontinuous_galerkin_spacetime_navier_stokes_elements.h:3004
unsigned nvalue_of_field(const unsigned &fld)
Return number of values in field fld.
Definition: discontinuous_galerkin_spacetime_navier_stokes_elements.h:3139
unsigned nhistory_values_for_coordinate_projection()
Definition: discontinuous_galerkin_spacetime_navier_stokes_elements.h:3033
Vector< std::pair< Data *, unsigned > > data_values_of_field(const unsigned &fld)
Definition: discontinuous_galerkin_spacetime_navier_stokes_elements.h:2960
int local_equation(const unsigned &fld, const unsigned &j)
Return local equation number of value j in field fld.
Definition: discontinuous_galerkin_spacetime_navier_stokes_elements.h:3153
double jacobian_and_shape_of_field(const unsigned &fld, const Vector< double > &s, Shape &psi)
Definition: discontinuous_galerkin_spacetime_navier_stokes_elements.h:3042
ProjectableTaylorHoodSpaceTimeElement()
Definition: discontinuous_galerkin_spacetime_navier_stokes_elements.h:2951
unsigned nhistory_values_for_projection(const unsigned &fld)
Definition: discontinuous_galerkin_spacetime_navier_stokes_elements.h:3014
Definition: Qelements.h:459
Definition: discontinuous_galerkin_equal_order_pressure_spacetime_navier_stokes_elements.h:2120
void output(std::ostream &outfile)
Redirect output to NavierStokesEquations output.
Definition: discontinuous_galerkin_spacetime_navier_stokes_elements.h:2318
virtual int p_nodal_index_nst() const
Set the value at which the pressure is stored in the nodes.
Definition: discontinuous_galerkin_spacetime_navier_stokes_elements.h:2228
void output(FILE *file_pt, const unsigned &nplot)
Redirect output to NavierStokesEquations output.
Definition: discontinuous_galerkin_spacetime_navier_stokes_elements.h:2342
double dptest_eulerian(const Vector< double > &s, Shape &ptest, DShape &dptestdx) const
QTaylorHoodSpaceTimeElement()
Constructor, no internal data points.
Definition: discontinuous_galerkin_spacetime_navier_stokes_elements.h:2192
double p_nst(const unsigned &t, const unsigned &n_p) const
Definition: discontinuous_galerkin_spacetime_navier_stokes_elements.h:2254
double dpshape_eulerian(const Vector< double > &s, Shape &ppsi, DShape &dppsidx) const
static const unsigned Initial_Nvalue[]
Static array of ints to hold number of variables at node.
Definition: discontinuous_galerkin_equal_order_pressure_spacetime_navier_stokes_elements.h:2123
void pshape_nst(const Vector< double > &s, Shape &psi) const
Pressure shape functions at local coordinate s.
void fix_pressure(const unsigned &p_dof, const double &p_value)
Pin p_dof-th pressure dof and set it to value specified by p_value.
Definition: discontinuous_galerkin_spacetime_navier_stokes_elements.h:2271
static const unsigned Pconv[]
Definition: discontinuous_galerkin_equal_order_pressure_spacetime_navier_stokes_elements.h:2128
void output(std::ostream &outfile, const unsigned &nplot)
Redirect output to NavierStokesEquations output.
Definition: discontinuous_galerkin_spacetime_navier_stokes_elements.h:2326
virtual unsigned required_nvalue(const unsigned &n) const
Definition: discontinuous_galerkin_spacetime_navier_stokes_elements.h:2206
int p_local_eqn(const unsigned &n) const
Return the local equation numbers for the pressure values.
Definition: discontinuous_galerkin_spacetime_navier_stokes_elements.h:2236
double p_nst(const unsigned &n_p) const
Definition: discontinuous_galerkin_spacetime_navier_stokes_elements.h:2245
void pshape_nst(const Vector< double > &s, Shape &psi, Shape &test) const
Pressure shape and test functions at local coordinte s.
void build_fp_press_adv_diff_robin_bc_element(const unsigned &face_index)
Definition: discontinuous_galerkin_spacetime_navier_stokes_elements.h:2285
void identify_load_data(std::set< std::pair< Data *, unsigned >> &paired_load_data)
void ptest_nst(const Vector< double > &s, Shape &psi) const
Pressure test functions at local coordinate s.
void identify_pressure_data(std::set< std::pair< Data *, unsigned >> &paired_pressure_data)
double dpshape_and_dptest_eulerian_nst(const Vector< double > &s, Shape &ppsi, DShape &dppsidx, Shape &ptest, DShape &dptestdx) const
double dshape_and_dtest_eulerian_at_knot_nst(const unsigned &ipt, Shape &psi, DShape &dpsidx, RankFourTensor< double > &d_dpsidx_dX, Shape &test, DShape &dtestdx, RankFourTensor< double > &d_dtestdx_dX, DenseMatrix< double > &djacobian_dX) const
double dshape_and_dtest_eulerian_at_knot_nst(const unsigned &ipt, Shape &psi, DShape &dpsidx, Shape &test, DShape &dtestdx) const
~QTaylorHoodSpaceTimeElement()
Definition: discontinuous_galerkin_spacetime_navier_stokes_elements.h:2198
void output(FILE *file_pt)
Redirect output to NavierStokesEquations output.
Definition: discontinuous_galerkin_spacetime_navier_stokes_elements.h:2334
unsigned npres_nst() const
Return number of pressure values.
Definition: discontinuous_galerkin_spacetime_navier_stokes_elements.h:2262
double dshape_and_dtest_eulerian_nst(const Vector< double > &s, Shape &psi, DShape &dpsidx, Shape &test, DShape &dtestdx) const
A Rank 4 Tensor class.
Definition: matrices.h:1701
A Rank 3 Tensor class.
Definition: matrices.h:1370
Definition: refineable_elements.h:97
Definition: shape.h:76
Definition: nodes.h:1686
Data *const & variable_position_pt() const
Pointer to variable_position data (const version)
Definition: nodes.h:1765
Definition: discontinuous_galerkin_equal_order_pressure_spacetime_navier_stokes_elements.h:466
virtual double dpshape_and_dptest_eulerian_nst(const Vector< double > &s, Shape &ppsi, DShape &dppsidx, Shape &ptest, DShape &dptestdx) const =0
NavierStokesBodyForceFctPt & body_force_fct_pt()
Access function for the body-force pointer.
Definition: discontinuous_galerkin_spacetime_navier_stokes_elements.h:1009
void get_pressure_and_velocity_mass_matrix_diagonal(Vector< double > &press_mass_diag, Vector< double > &veloc_mass_diag, const unsigned &which_one=0)
virtual void dinterpolated_u_nst_ddata(const Vector< double > &s, const unsigned &i, Vector< double > &du_ddata, Vector< unsigned > &global_eqn_number)
Definition: discontinuous_galerkin_spacetime_navier_stokes_elements.h:1978
void fill_in_pressure_advection_diffusion_jacobian(Vector< double > &residuals, DenseMatrix< double > &jacobian)
Definition: discontinuous_galerkin_spacetime_navier_stokes_elements.h:1728
static Vector< double > Gamma
Navier-Stokes equations static data.
Definition: discontinuous_galerkin_equal_order_pressure_spacetime_navier_stokes_elements.h:833
double *& st_pt()
Pointer to Strouhal number (can only assign to private member data)
Definition: discontinuous_galerkin_spacetime_navier_stokes_elements.h:943
double * ReInvFr_pt
Definition: discontinuous_galerkin_equal_order_pressure_spacetime_navier_stokes_elements.h:525
int Pinned_fp_pressure_eqn
Definition: discontinuous_galerkin_equal_order_pressure_spacetime_navier_stokes_elements.h:552
void disable_ALE()
Definition: discontinuous_galerkin_spacetime_navier_stokes_elements.h:1200
void compute_error(std::ostream &outfile, FiniteElement::UnsteadyExactSolutionFctPt exact_soln_pt, const double &time, Vector< double > &error, Vector< double > &norm)
virtual void fill_in_generic_residual_contribution_nst(Vector< double > &residuals, DenseMatrix< double > &jacobian, DenseMatrix< double > &mass_matrix, const unsigned &flag)
void get_traction(const Vector< double > &s, const Vector< double > &N, Vector< double > &traction)
NavierStokesBodyForceFctPt Body_force_fct_pt
Pointer to body force function.
Definition: discontinuous_galerkin_equal_order_pressure_spacetime_navier_stokes_elements.h:531
void compute_error(FiniteElement::UnsteadyExactSolutionFctPt exact_soln_pt, const double &time, double &error, double &norm)
void full_output(std::ostream &outfile)
Definition: discontinuous_galerkin_spacetime_navier_stokes_elements.h:1507
const double & st() const
Strouhal parameter (const. version)
Definition: discontinuous_galerkin_spacetime_navier_stokes_elements.h:894
double dissipation(const Vector< double > &s) const
Return dissipation at local coordinate s.
virtual double dshape_and_dtest_eulerian_nst(const Vector< double > &s, Shape &psi, DShape &dpsidx, Shape &test, DShape &dtestdx) const =0
NavierStokesPressureAdvDiffSourceFctPt Press_adv_diff_source_fct_pt
Definition: discontinuous_galerkin_equal_order_pressure_spacetime_navier_stokes_elements.h:538
virtual int p_nodal_index_nst() const
Definition: discontinuous_galerkin_spacetime_navier_stokes_elements.h:1229
void delete_pressure_advection_diffusion_robin_elements()
Definition: discontinuous_galerkin_spacetime_navier_stokes_elements.h:1872
void compute_norm(Vector< double > &norm)
Compute the vector norm of the FEM solution.
void output_fct(std::ostream &outfile, const unsigned &nplot, FiniteElement::SteadyExactSolutionFctPt exact_soln_pt)
virtual double dshape_and_dtest_eulerian_at_knot_nst(const unsigned &ipt, Shape &psi, DShape &dpsidx, RankFourTensor< double > &d_dpsidx_dX, Shape &test, DShape &dtestdx, RankFourTensor< double > &d_dtestdx_dX, DenseMatrix< double > &djacobian_dX) const =0
unsigned n_u_nst() const
Definition: discontinuous_galerkin_spacetime_navier_stokes_elements.h:1129
double * St_pt
Pointer to global Reynolds number x Strouhal number (=Womersley)
Definition: discontinuous_galerkin_equal_order_pressure_spacetime_navier_stokes_elements.h:517
void compute_error(FiniteElement::SteadyExactSolutionFctPt exact_soln_pt, double &error, double &norm)
void get_vorticity(const Vector< double > &s, double &vorticity) const
Compute the vorticity vector at local coordinate s.
double * Density_Ratio_pt
Definition: discontinuous_galerkin_equal_order_pressure_spacetime_navier_stokes_elements.h:509
Vector< double > * G_pt
Pointer to global gravity Vector.
Definition: discontinuous_galerkin_equal_order_pressure_spacetime_navier_stokes_elements.h:528
double du_dt_nst(const unsigned &n, const unsigned &i) const
Definition: discontinuous_galerkin_equal_order_pressure_spacetime_navier_stokes_elements.h:1149
NavierStokesBodyForceFctPt body_force_fct_pt() const
Access function for the body-force pointer. Const version.
Definition: discontinuous_galerkin_spacetime_navier_stokes_elements.h:1015
virtual double interpolated_p_nst(const Vector< double > &s) const
Return FE interpolated pressure at local coordinate s.
Definition: discontinuous_galerkin_equal_order_pressure_spacetime_navier_stokes_elements.h:2037
static double Default_Physical_Constant_Value
Navier-Stokes equations static data.
Definition: discontinuous_galerkin_equal_order_pressure_spacetime_navier_stokes_elements.h:491
void fill_in_contribution_to_hessian_vector_products(Vector< double > const &Y, DenseMatrix< double > const &C, DenseMatrix< double > &product)
NavierStokesSourceFctPt & source_fct_pt()
Access function for the source-function pointer.
Definition: discontinuous_galerkin_spacetime_navier_stokes_elements.h:1021
virtual double dshape_and_dtest_eulerian_at_knot_nst(const unsigned &ipt, Shape &psi, DShape &dpsidx, Shape &test, DShape &dtestdx) const =0
void output(FILE *file_pt)
Definition: discontinuous_galerkin_spacetime_navier_stokes_elements.h:1489
const double & re() const
Reynolds number.
Definition: discontinuous_galerkin_spacetime_navier_stokes_elements.h:870
double kin_energy() const
Get integral of kinetic energy over element.
void point_output_data(const Vector< double > &s, Vector< double > &data)
Definition: discontinuous_galerkin_spacetime_navier_stokes_elements.h:2082
void output_fct(std::ostream &outfile, const unsigned &nplot, const double &time, FiniteElement::UnsteadyExactSolutionFctPt exact_soln_pt)
const double & density_ratio() const
Definition: discontinuous_galerkin_spacetime_navier_stokes_elements.h:973
int & pinned_fp_pressure_eqn()
Definition: discontinuous_galerkin_spacetime_navier_stokes_elements.h:1049
NavierStokesSourceFctPt source_fct_pt() const
Access function for the source-function pointer. Const version.
Definition: discontinuous_galerkin_spacetime_navier_stokes_elements.h:1027
void fill_in_contribution_to_residuals(Vector< double > &residuals)
Compute the element's residual Vector.
Definition: discontinuous_galerkin_spacetime_navier_stokes_elements.h:1607
void(* NavierStokesBodyForceFctPt)(const double &time, const Vector< double > &x, Vector< double > &body_force)
Definition: discontinuous_galerkin_equal_order_pressure_spacetime_navier_stokes_elements.h:470
void store_strouhal_as_external_data(Data *strouhal_data_pt)
Function that tells us whether the period is stored as external data.
Definition: discontinuous_galerkin_spacetime_navier_stokes_elements.h:837
virtual void fill_in_generic_pressure_advection_diffusion_contribution_nst(Vector< double > &residuals, DenseMatrix< double > &jacobian, const unsigned &flag)
Definition: discontinuous_galerkin_equal_order_pressure_spacetime_navier_stokes_elements.cc:1812
Vector< FpPressureAdvDiffRobinBCSpaceTimeElementBase * > Pressure_advection_diffusion_robin_element_pt
Definition: discontinuous_galerkin_equal_order_pressure_spacetime_navier_stokes_elements.h:548
double * st_pt() const
Pointer to Strouhal parameter (const. version)
Definition: discontinuous_galerkin_spacetime_navier_stokes_elements.h:918
virtual double p_nst(const unsigned &n_p) const =0
virtual void fill_in_generic_dresidual_contribution_nst(double *const &parameter_pt, Vector< double > &dres_dparam, DenseMatrix< double > &djac_dparam, DenseMatrix< double > &dmass_matrix_dparam, const unsigned &flag)
Definition: discontinuous_galerkin_equal_order_pressure_spacetime_navier_stokes_elements.cc:2443
void fill_in_contribution_to_jacobian_and_mass_matrix(Vector< double > &residuals, DenseMatrix< double > &jacobian, DenseMatrix< double > &mass_matrix)
Definition: discontinuous_galerkin_spacetime_navier_stokes_elements.h:1640
double interpolated_du_dt_nst(const Vector< double > &s, const unsigned &i) const
Definition: discontinuous_galerkin_equal_order_pressure_spacetime_navier_stokes_elements.h:1164
virtual double p_nst(const unsigned &t, const unsigned &n_p) const =0
Pressure at local pressure "node" n_p at time level t.
void output(std::ostream &outfile, const unsigned &n_plot)
double * Viscosity_Ratio_pt
Definition: discontinuous_galerkin_equal_order_pressure_spacetime_navier_stokes_elements.h:505
void fill_in_contribution_to_dresiduals_dparameter(double *const &parameter_pt, Vector< double > &dres_dparam)
Definition: discontinuous_galerkin_spacetime_navier_stokes_elements.h:1656
bool is_strouhal_stored_as_external_data() const
Are we storing the Strouhal number as external data?
Definition: discontinuous_galerkin_spacetime_navier_stokes_elements.h:886
const Vector< double > & g() const
Vector of gravitational components.
Definition: discontinuous_galerkin_spacetime_navier_stokes_elements.h:997
NavierStokesPressureAdvDiffSourceFctPt & source_fct_for_pressure_adv_diff()
Definition: discontinuous_galerkin_spacetime_navier_stokes_elements.h:1034
static int Pressure_not_stored_at_node
Definition: discontinuous_galerkin_equal_order_pressure_spacetime_navier_stokes_elements.h:487
virtual void get_body_force_nst(const double &time, const unsigned &ipt, const Vector< double > &s, const Vector< double > &x, Vector< double > &result)
Definition: discontinuous_galerkin_spacetime_navier_stokes_elements.h:620
void output(std::ostream &outfile)
Definition: discontinuous_galerkin_spacetime_navier_stokes_elements.h:1472
void compute_error(std::ostream &outfile, FiniteElement::SteadyExactSolutionFctPt exact_soln_pt, double &error, double &norm)
double d_kin_energy_dt() const
Get integral of time derivative of kinetic energy over element.
double dissipation() const
Return integral of dissipation over element.
double *& re_pt()
Pointer to Reynolds number.
Definition: discontinuous_galerkin_spacetime_navier_stokes_elements.h:878
void fill_in_pressure_advection_diffusion_residuals(Vector< double > &residuals)
Definition: discontinuous_galerkin_spacetime_navier_stokes_elements.h:1714
double * Re_pt
Pointer to global Reynolds number.
Definition: discontinuous_galerkin_equal_order_pressure_spacetime_navier_stokes_elements.h:514
virtual void pshape_nst(const Vector< double > &s, Shape &psi, Shape &test) const =0
virtual unsigned npres_nst() const =0
Function to return number of pressure degrees of freedom.
virtual void fill_in_generic_pressure_advection_diffusion_contribution_nst(Vector< double > &residuals, DenseMatrix< double > &jacobian, const unsigned &flag)
double interpolated_u_nst(const Vector< double > &s, const unsigned &i) const
Return FE interpolated velocity u[i] at local coordinate s.
Definition: discontinuous_galerkin_spacetime_navier_stokes_elements.h:1924
static Vector< double > Default_Gravity_vector
Static default value for the gravity vector.
Definition: discontinuous_galerkin_equal_order_pressure_spacetime_navier_stokes_elements.h:498
virtual void fill_in_generic_residual_contribution_nst(Vector< double > &residuals, DenseMatrix< double > &jacobian, DenseMatrix< double > &mass_matrix, const unsigned &flag)
Definition: discontinuous_galerkin_equal_order_pressure_spacetime_navier_stokes_elements.cc:1994
NavierStokesSourceFctPt Source_fct_pt
Pointer to volumetric source function.
Definition: discontinuous_galerkin_equal_order_pressure_spacetime_navier_stokes_elements.h:534
double(* NavierStokesSourceFctPt)(const double &time, const Vector< double > &x)
Function pointer to source function fct(t,x) (x is a Vector!)
Definition: discontinuous_galerkin_equal_order_pressure_spacetime_navier_stokes_elements.h:475
void scalar_value_fct_paraview(std::ofstream &file_out, const unsigned &i, const unsigned &nplot, const double &time, FiniteElement::UnsteadyExactSolutionFctPt exact_soln_pt) const
Definition: discontinuous_galerkin_spacetime_navier_stokes_elements.h:1367
const double & re_invfr() const
Global inverse Froude number.
Definition: discontinuous_galerkin_spacetime_navier_stokes_elements.h:985
void get_load(const Vector< double > &s, const Vector< double > &N, Vector< double > &load)
Definition: discontinuous_galerkin_spacetime_navier_stokes_elements.h:1285
double u_nst(const unsigned &t, const unsigned &n, const unsigned &i) const
Definition: discontinuous_galerkin_spacetime_navier_stokes_elements.h:1079
double *& density_ratio_pt()
Pointer to Density ratio.
Definition: discontinuous_galerkin_spacetime_navier_stokes_elements.h:979
void fill_in_contribution_to_djacobian_and_dmass_matrix_dparameter(double *const &parameter_pt, Vector< double > &dres_dparam, DenseMatrix< double > &djac_dparam, DenseMatrix< double > &dmass_matrix_dparam)
Definition: discontinuous_galerkin_spacetime_navier_stokes_elements.h:1694
NavierStokesPressureAdvDiffSourceFctPt source_fct_for_pressure_adv_diff() const
Definition: discontinuous_galerkin_spacetime_navier_stokes_elements.h:1041
unsigned nscalar_paraview() const
Definition: discontinuous_galerkin_spacetime_navier_stokes_elements.h:1307
void get_traction(const Vector< double > &s, const Vector< double > &N, Vector< double > &traction_p, Vector< double > &traction_visc_n, Vector< double > &traction_visc_t)
double re_st() const
Product of Reynolds and Strouhal number (=Womersley number)
Definition: discontinuous_galerkin_spacetime_navier_stokes_elements.h:951
void pin_all_non_pressure_dofs(std::map< Data *, std::vector< int >> &eqn_number_backup)
Pin all non-pressure dofs and backup eqn numbers.
Definition: discontinuous_galerkin_spacetime_navier_stokes_elements.h:1741
void interpolated_u_nst(const Vector< double > &s, Vector< double > &velocity) const
Compute vector of FE interpolated velocity u at local coordinate s.
Definition: discontinuous_galerkin_equal_order_pressure_spacetime_navier_stokes_elements.h:1892
SpaceTimeNavierStokesEquations()
Definition: discontinuous_galerkin_spacetime_navier_stokes_elements.h:795
virtual double dptest_eulerian(const Vector< double > &s, Shape &ptest, DShape &dptestdx) const =0
double pressure_integral() const
Integral of pressure over element.
virtual void pshape_nst(const Vector< double > &s, Shape &psi) const =0
Compute the pressure shape functions at local coordinate s.
virtual unsigned u_index_nst(const unsigned &i) const
Definition: discontinuous_galerkin_equal_order_pressure_spacetime_navier_stokes_elements.h:1102
virtual double get_source_nst(const double &time, const unsigned &ipt, const Vector< double > &x)
Calculate the source fct at a given time and Eulerian position.
Definition: discontinuous_galerkin_spacetime_navier_stokes_elements.h:691
void output_veloc(std::ostream &outfile, const unsigned &nplot, const unsigned &t)
double interpolated_u_nst(const unsigned &t, const Vector< double > &s, const unsigned &i) const
Definition: discontinuous_galerkin_spacetime_navier_stokes_elements.h:1955
void compute_error(std::ostream &outfile, FiniteElement::UnsteadyExactSolutionFctPt exact_soln_pt, const double &time, double &error, double &norm)
virtual void get_dresidual_dnodal_coordinates(RankThreeTensor< double > &dresidual_dnodal_coordinates)
virtual void fill_in_generic_dresidual_contribution_nst(double *const &parameter_pt, Vector< double > &dres_dparam, DenseMatrix< double > &djac_dparam, DenseMatrix< double > &dmass_matrix_dparam, const unsigned &flag)
void get_vorticity(const Vector< double > &s, Vector< double > &vorticity) const
Compute the vorticity vector at local coordinate s.
void output(FILE *file_pt, const unsigned &n_plot)
void fill_in_contribution_to_djacobian_dparameter(double *const &parameter_pt, Vector< double > &dres_dparam, DenseMatrix< double > &djac_dparam)
Definition: discontinuous_galerkin_spacetime_navier_stokes_elements.h:1674
virtual void get_body_force_gradient_nst(const double &time, const unsigned &ipt, const Vector< double > &s, const Vector< double > &x, DenseMatrix< double > &d_body_force_dx)
Definition: discontinuous_galerkin_spacetime_navier_stokes_elements.h:646
double u_nst(const unsigned &n, const unsigned &i) const
Definition: discontinuous_galerkin_spacetime_navier_stokes_elements.h:1072
double(* NavierStokesPressureAdvDiffSourceFctPt)(const Vector< double > &x)
Definition: discontinuous_galerkin_equal_order_pressure_spacetime_navier_stokes_elements.h:481
const double & viscosity_ratio() const
Definition: discontinuous_galerkin_spacetime_navier_stokes_elements.h:960
virtual void fix_pressure(const unsigned &p_dof, const double &p_value)=0
Pin p_dof-th pressure dof and set it to value specified by p_value.
virtual double dpshape_eulerian(const Vector< double > &s, Shape &ppsi, DShape &dppsidx) const =0
void output_pressure_advection_diffusion_robin_elements(std::ostream &outfile)
Definition: discontinuous_galerkin_spacetime_navier_stokes_elements.h:1834
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)
double *& re_invfr_pt()
Pointer to global inverse Froude number.
Definition: discontinuous_galerkin_spacetime_navier_stokes_elements.h:991
virtual void get_source_gradient_nst(const double &time, const unsigned &ipt, const Vector< double > &x, Vector< double > &gradient)
Definition: discontinuous_galerkin_spacetime_navier_stokes_elements.h:715
static double Default_Physical_Ratio_Value
Navier-Stokes equations static data.
Definition: discontinuous_galerkin_equal_order_pressure_spacetime_navier_stokes_elements.h:495
double *& viscosity_ratio_pt()
Pointer to Viscosity Ratio.
Definition: discontinuous_galerkin_spacetime_navier_stokes_elements.h:966
void enable_ALE()
Definition: discontinuous_galerkin_spacetime_navier_stokes_elements.h:1210
virtual void build_fp_press_adv_diff_robin_bc_element(const unsigned &face_index)=0
bool Strouhal_is_stored_as_external_data
Definition: discontinuous_galerkin_equal_order_pressure_spacetime_navier_stokes_elements.h:521
bool ALE_is_disabled
Definition: discontinuous_galerkin_equal_order_pressure_spacetime_navier_stokes_elements.h:543
void full_output(std::ostream &outfile, const unsigned &n_plot)
Vector< double > *& g_pt()
Pointer to Vector of gravitational components.
Definition: discontinuous_galerkin_spacetime_navier_stokes_elements.h:1003
void scalar_value_paraview(std::ofstream &file_out, const unsigned &i, const unsigned &nplot) const
Definition: discontinuous_galerkin_spacetime_navier_stokes_elements.h:1315
void fill_in_contribution_to_jacobian(Vector< double > &residuals, DenseMatrix< double > &jacobian)
Definition: discontinuous_galerkin_spacetime_navier_stokes_elements.h:1623
double interpolated_p_nst(const unsigned &t, const Vector< double > &s) const
Return FE interpolated pressure at local coordinate s at time level t.
Definition: discontinuous_galerkin_spacetime_navier_stokes_elements.h:2059
void output_vorticity(std::ostream &outfile, const unsigned &nplot)
std::string scalar_name_paraview(const unsigned &i) const
Definition: discontinuous_galerkin_spacetime_navier_stokes_elements.h:1436
double get_du_dt(const unsigned &n, const unsigned &i) const
Definition: discontinuous_galerkin_spacetime_navier_stokes_elements.h:1140
Definition: discontinuous_galerkin_equal_order_pressure_spacetime_navier_stokes_elements.h:365
virtual void get_pressure_and_velocity_mass_matrix_diagonal(Vector< double > &press_mass_diag, Vector< double > &veloc_mass_diag, const unsigned &which_one=0)=0
virtual void build_fp_press_adv_diff_robin_bc_element(const unsigned &face_index)=0
virtual void fill_in_pressure_advection_diffusion_jacobian(Vector< double > &residuals, DenseMatrix< double > &jacobian)=0
TemplateFreeSpaceTimeNavierStokesEquationsBase()
Constructor (empty)
Definition: discontinuous_galerkin_spacetime_navier_stokes_elements.h:368
virtual ~TemplateFreeSpaceTimeNavierStokesEquationsBase()
Virtual destructor (empty)
Definition: discontinuous_galerkin_spacetime_navier_stokes_elements.h:372
virtual int p_local_eqn(const unsigned &n) const =0
virtual void pin_all_non_pressure_dofs(std::map< Data *, std::vector< int >> &eqn_number_backup)=0
Pin all non-pressure dofs and backup eqn numbers of all Data.
virtual void fill_in_pressure_advection_diffusion_residuals(Vector< double > &residuals)=0
void initialise(const _Tp &__value)
Iterate over all values and set to the desired value.
Definition: oomph-lib/src/generic/Vector.h:167
@ N
Definition: constructor.cpp:22
RealScalar s
Definition: level1_cplx_impl.h:130
char char char int int * k
Definition: level2_impl.h:374
#define DIM
Definition: linearised_navier_stokes_elements.h:44
EIGEN_STRONG_INLINE EIGEN_DEVICE_FUNC bfloat16 pow(const bfloat16 &a, const bfloat16 &b)
Definition: BFloat16.h:625
EIGEN_DEVICE_FUNC const Scalar & q
Definition: SpecialFunctionsImpl.h:2019
void body_force(const double &time, const Vector< double > &x, Vector< double > &result)
Definition: axisym_linear_elasticity/cylinder/cylinder.cc:96
double velocity(const double &t)
Angular velocity as function of time t.
Definition: jeffery_orbit.cc:107
void flux(const double &time, const Vector< double > &x, double &flux)
Get flux applied along boundary x=0.
Definition: pretend_melt.cc:59
void exact_soln(const double &time, const Vector< double > &x, Vector< double > &soln)
Definition: unstructured_two_d_curved.cc:301
void source(const Vector< double > &x, Vector< double > &f)
Source function.
Definition: unstructured_two_d_circle.cc:46
int error
Definition: calibrate.py:297
std::string string(const unsigned &i)
Definition: oomph_definitions.cc:286
void dshape< 3 >(const double &s, double *DPsi)
Definition: shape.h:820
void shape< 3 >(const double &s, double *Psi)
1D shape functions specialised to quadratic order (3 Nodes)
Definition: shape.h:810
void shape(const double &s, double *Psi)
Definition: shape.h:564
void dshape< 3 >(const double &s, double *DPsi)
Definition: shape.h:645
void dshape< 2 >(const double &s, double *DPsi)
Derivatives of 1D shape functions specialised to linear order (2 Nodes)
Definition: shape.h:616
void shape< 3 >(const double &s, double *Psi)
1D shape functions specialised to quadratic order (3 Nodes)
Definition: shape.h:635
void shape< 2 >(const double &s, double *Psi)
1D shape functions specialised to linear order (2 Nodes)
Definition: shape.h:608
@ W
Definition: quadtree.h:63
std::string to_string(T object, unsigned float_precision=8)
Definition: oomph_utilities.h:189
DRAIG: Change all instances of (SPATIAL_DIM) to (DIM-1).
Definition: AnisotropicHookean.h:10
list x
Definition: plotDoE.py:28
t
Definition: plotPSD.py:36
Definition: indexed_view.cpp:20
#define OOMPH_EXCEPTION_LOCATION
Definition: oomph_definitions.h:61
#define OOMPH_CURRENT_FUNCTION
Definition: oomph_definitions.h:86
unsigned el_dim
dimension
Definition: overloaded_cartesian_element_body.h:30
void product(const MatrixType &m)
Definition: product.h:42
void set(Container &c, Position position, const Value &value)
Definition: stdlist_overload.cpp:36
const char Y
Definition: test/EulerAngles.cpp:32
std::ptrdiff_t j
Definition: tut_arithmetic_redux_minmax.cpp:2