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 Navier Stokes elements
27 
28 #ifndef OOMPH_NAVIER_STOKES_ELEMENTS_HEADER
29 #define OOMPH_NAVIER_STOKES_ELEMENTS_HEADER
30 
31 // Config header generated by autoconfig
32 #ifdef HAVE_CONFIG_H
33 #include <oomph-lib-config.h>
34 #endif
35 
36 
37 // OOMPH-LIB headers
38 #include "../generic/Qelements.h"
39 #include "../generic/fsi.h"
40 #include "../generic/projection.h"
41 
42 #include <algorithm>
43 #include <iterator>
44 
45 namespace oomph
46 {
47  //======================================================================
51  //======================================================================
53  {
54  public:
57 
60 
65  Vector<double>& residuals,
66  DenseMatrix<double>& jacobian,
67  unsigned flag) = 0;
68  };
69 
70 
74 
75 
76  //======================================================================
83  //======================================================================
84  template<class ELEMENT>
86  : public virtual FaceGeometry<ELEMENT>,
87  public virtual FaceElement,
89  {
90  public:
93  // refineable constructor.
95  FiniteElement* const& element_pt,
96  const int& face_index,
97  const bool& called_from_refineable_constructor = false)
98  : FaceGeometry<ELEMENT>(), FaceElement()
99  {
100  // Attach the geometrical information to the element. N.B. This function
101  // also assigns nbulk_value from the required_nvalue of the bulk element
102  element_pt->build_face_element(face_index, this);
103 
104 #ifdef PARANOID
105  {
106  // Check that the element is not a refineable 3d element
107  if (!called_from_refineable_constructor)
108  {
109  // If it's three-d
110  if (element_pt->dim() == 3)
111  {
112  // Is it refineable
113  RefineableElement* ref_el_pt =
114  dynamic_cast<RefineableElement*>(element_pt);
115  if (ref_el_pt != 0)
116  {
117  if (this->has_hanging_nodes())
118  {
119  throw OomphLibError("This flux element will not work correctly "
120  "if nodes are hanging\n",
123  }
124  }
125  }
126  }
127  }
128 #endif
129  }
130 
133 
138  Vector<double>& residuals, DenseMatrix<double>& jacobian, unsigned flag);
139 
140 
143  {
144  std::ostringstream error_message;
145  error_message
146  << "fill_in_contribution_to_residuals() must not be called directly.\n"
147  << "since it uses the local equation numbering of the bulk element\n"
148  << "which calls the relevant helper function directly.\n";
149  throw OomphLibError(
150  error_message.str(), OOMPH_CURRENT_FUNCTION, OOMPH_EXCEPTION_LOCATION);
151  }
152 
155  DenseMatrix<double>& jacobian)
156  {
157  std::ostringstream error_message;
158  error_message
159  << "fill_in_contribution_to_jacobian() must not be called directly.\n"
160  << "since it uses the local equation numbering of the bulk element\n"
161  << "which calls the relevant helper function directly.\n";
162  throw OomphLibError(
163  error_message.str(), OOMPH_CURRENT_FUNCTION, OOMPH_EXCEPTION_LOCATION);
164  }
165 
167  void output(std::ostream& outfile)
168  {
169  FiniteElement::output(outfile);
170  }
171 
173  void output(std::ostream& outfile, const unsigned& nplot)
174  {
175  FiniteElement::output(outfile, nplot);
176  }
177  };
178 
182 
183 
184  //============================================================================
187  //============================================================================
188  template<class ELEMENT>
191  Vector<double>& residuals, DenseMatrix<double>& jacobian, unsigned flag)
192  {
193  // Storage for local coordinates in FaceElement and associted bulk element
194  unsigned my_dim = this->dim();
195  Vector<double> s(my_dim);
196  Vector<double> s_bulk(my_dim + 1);
197 
198  // Storage for outer unit normal
199  Vector<double> unit_normal(my_dim + 1);
200 
201  // Storage for veloc in bulk element
202  Vector<double> veloc(my_dim + 1);
203 
204  // Set the value of n_intpt
205  unsigned n_intpt = this->integral_pt()->nweight();
206 
207  // Integers to store local equation numbers
208  int local_eqn = 0;
209  int local_unknown = 0;
210 
211  // Get cast bulk element
212  ELEMENT* bulk_el_pt = dynamic_cast<ELEMENT*>(this->bulk_element_pt());
213 
214  // Find out how many pressure dofs there are in the bulk element
215  unsigned n_pres = bulk_el_pt->npres_nst();
216 
217  // Get the Reynolds number from the bulk element
218  double re = bulk_el_pt->re();
219 
220  // Set up memory for pressure shape and test functions
221  Shape psip(n_pres), testp(n_pres);
222 
223  // Loop over the integration points
224  for (unsigned ipt = 0; ipt < n_intpt; ipt++)
225  {
226  // Get the integral weight
227  double w = this->integral_pt()->weight(ipt);
228 
229  // Assign values of local coordinate in FaceElement
230  for (unsigned i = 0; i < my_dim; i++)
231  s[i] = this->integral_pt()->knot(ipt, i);
232 
233  // Find corresponding coordinate in the the bulk element
234  s_bulk = this->local_coordinate_in_bulk(s);
235 
237  this->outer_unit_normal(ipt, unit_normal);
238 
239  // Get velocity in bulk element
240  bulk_el_pt->interpolated_u_nst(s_bulk, veloc);
241 
242  // Get normal component of veloc
243  double flux = 0.0;
244  for (unsigned i = 0; i < my_dim + 1; i++)
245  {
246  flux += veloc[i] * unit_normal[i];
247  }
248 
249  // Modify bc: If outflow (flux>0) apply Neumann condition instead
250  if (flux > 0.0) flux = 0.0;
251 
252  // Get pressure
253  double interpolated_press = bulk_el_pt->interpolated_p_nst(s_bulk);
254 
255  // Call the pressure shape and test functions in bulk element
256  bulk_el_pt->pshape_nst(s_bulk, psip, testp);
257 
258  // Find the Jacobian of the mapping within the FaceElement
259  double J = this->J_eulerian(s);
260 
261  // Premultiply the weights and the Jacobian
262  double W = w * J;
263 
264  // Loop over the pressure shape functions in bulk
265  //(wasteful but they'll be zero on the boundary)
266  for (unsigned l = 0; l < n_pres; l++)
267  {
268  local_eqn = bulk_el_pt->p_local_eqn(l);
269 
270  // If not a boundary conditions
271  if (local_eqn >= 0)
272  {
273  residuals[local_eqn] -= re * flux * interpolated_press * testp[l] * W;
274 
275  // Jacobian too?
276  if (flag)
277  {
278  // Loop over the shape functions in bulk
279  for (unsigned l2 = 0; l2 < n_pres; l2++)
280  {
281  local_unknown = bulk_el_pt->p_local_eqn(l2);
282 
283  // If not a boundary conditions
284  if (local_unknown >= 0)
285  {
286  jacobian(local_eqn, local_unknown) -=
287  re * flux * psip[l2] * testp[l] * W;
288  }
289  }
290  } /*End of Jacobian calculation*/
291  } // End of if not boundary condition
292  } // End of loop over l
293  }
294  }
295 
299 
300 
301  //======================================================================
304  //======================================================================
307  public virtual FiniteElement
308  {
309  public:
312 
315 
319  Vector<double>& residuals) = 0;
320 
324  Vector<double>& residuals, DenseMatrix<double>& jacobian) = 0;
325 
329  virtual int p_nodal_index_nst() const = 0;
330 
334  virtual int p_local_eqn(const unsigned& n) const = 0;
335 
338  virtual int& pinned_fp_pressure_eqn() = 0;
339 
340 
343  std::map<Data*, std::vector<int>>& eqn_number_backup) = 0;
344 
349  const unsigned& face_index) = 0;
350 
355 
356 
362  Vector<double>& press_mass_diag,
363  Vector<double>& veloc_mass_diag,
364  const unsigned& which_one = 0) = 0;
365  };
366 
367 
371 
372 
373  //======================================================================
390  //======================================================================
391  template<unsigned DIM>
393  : public virtual FSIFluidElement,
395  {
396  public:
399  typedef void (*NavierStokesBodyForceFctPt)(const double& time,
400  const Vector<double>& x,
402 
405  typedef double (*NavierStokesSourceFctPt)(const double& time,
406  const Vector<double>& x);
407 
408 
413  const Vector<double>& x);
414 
415  private:
419 
423 
427 
430 
431  protected:
432  // Physical constants
433 
437 
441 
442  // Pointers to global physical constants
443 
445  double* Re_pt;
446 
448  double* ReSt_pt;
449 
452  double* ReInvFr_pt;
453 
456 
459 
462 
466 
471 
476 
480 
485  Shape& psi,
486  DShape& dpsidx,
487  Shape& test,
488  DShape& dtestdx) const = 0;
489 
494  const unsigned& ipt,
495  Shape& psi,
496  DShape& dpsidx,
497  Shape& test,
498  DShape& dtestdx) const = 0;
499 
504  const unsigned& ipt,
505  Shape& psi,
506  DShape& dpsidx,
507  RankFourTensor<double>& d_dpsidx_dX,
508  Shape& test,
509  DShape& dtestdx,
510  RankFourTensor<double>& d_dtestdx_dX,
511  DenseMatrix<double>& djacobian_dX) const = 0;
512 
517  virtual void get_body_force_nst(const double& time,
518  const unsigned& ipt,
519  const Vector<double>& s,
520  const Vector<double>& x,
521  Vector<double>& result)
522  {
523  // If the function pointer is zero return zero
524  if (Body_force_fct_pt == 0)
525  {
526  // Loop over dimensions and set body forces to zero
527  for (unsigned i = 0; i < DIM; i++)
528  {
529  result[i] = 0.0;
530  }
531  }
532  // Otherwise call the function
533  else
534  {
535  (*Body_force_fct_pt)(time, x, result);
536  }
537  }
538 
544  inline virtual void get_body_force_gradient_nst(
545  const double& time,
546  const unsigned& ipt,
547  const Vector<double>& s,
548  const Vector<double>& x,
549  DenseMatrix<double>& d_body_force_dx)
550  {
551  // hierher: Implement function pointer version
552  /* //If no gradient function has been set, FD it */
553  /* if(Body_force_fct_gradient_pt==0) */
554  {
555  // Reference value
557  get_body_force_nst(time, ipt, s, x, body_force);
558 
559  // FD it
561  Vector<double> body_force_pls(DIM, 0.0);
562  Vector<double> x_pls(x);
563  for (unsigned i = 0; i < DIM; i++)
564  {
565  x_pls[i] += eps_fd;
566  get_body_force_nst(time, ipt, s, x_pls, body_force_pls);
567  for (unsigned j = 0; j < DIM; j++)
568  {
569  d_body_force_dx(j, i) =
570  (body_force_pls[j] - body_force[j]) / eps_fd;
571  }
572  x_pls[i] = x[i];
573  }
574  }
575  /* else */
576  /* { */
577  /* // Get gradient */
578  /* (*Source_fct_gradient_pt)(time,x,gradient); */
579  /* } */
580  }
581 
582 
585  virtual double get_source_nst(const double& time,
586  const unsigned& ipt,
587  const Vector<double>& x)
588  {
589  // If the function pointer is zero return zero
590  if (Source_fct_pt == 0)
591  {
592  return 0;
593  }
594  // Otherwise call the function
595  else
596  {
597  return (*Source_fct_pt)(time, x);
598  }
599  }
600 
601 
607  inline virtual void get_source_gradient_nst(const double& time,
608  const unsigned& ipt,
609  const Vector<double>& x,
610  Vector<double>& gradient)
611  {
612  // hierher: Implement function pointer version
613  /* //If no gradient function has been set, FD it */
614  /* if(Source_fct_gradient_pt==0) */
615  {
616  // Reference value
617  double source = get_source_nst(time, ipt, x);
618 
619  // FD it
621  double source_pls = 0.0;
622  Vector<double> x_pls(x);
623  for (unsigned i = 0; i < DIM; i++)
624  {
625  x_pls[i] += eps_fd;
626  source_pls = get_source_nst(time, ipt, x_pls);
627  gradient[i] = (source_pls - source) / eps_fd;
628  x_pls[i] = x[i];
629  }
630  }
631  /* else */
632  /* { */
633  /* // Get gradient */
634  /* (*Source_fct_gradient_pt)(time,x,gradient); */
635  /* } */
636  }
637 
638 
643  Vector<double>& residuals,
644  DenseMatrix<double>& jacobian,
645  DenseMatrix<double>& mass_matrix,
646  unsigned flag);
647 
648 
653  Vector<double>& residuals, DenseMatrix<double>& jacobian, unsigned flag);
654 
660  double* const& parameter_pt,
661  Vector<double>& dres_dparam,
662  DenseMatrix<double>& djac_dparam,
663  DenseMatrix<double>& dmass_matrix_dparam,
664  unsigned flag);
665 
669  Vector<double> const& Y,
670  DenseMatrix<double> const& C,
672 
673 
674  public:
678  : Body_force_fct_pt(0),
679  Source_fct_pt(0),
681  ALE_is_disabled(false),
683  {
684  // Set all the Physical parameter pointers to the default value zero
689  // Set the Physical ratios to the default value of 1
692  }
693 
695  // N.B. This needs to be public so that the intel compiler gets things
696  // correct somehow the access function messes things up when going to
697  // refineable navier--stokes
699 
700  // Access functions for the physical constants
701 
703  const double& re() const
704  {
705  return *Re_pt;
706  }
707 
709  const double& re_st() const
710  {
711  return *ReSt_pt;
712  }
713 
715  double*& re_pt()
716  {
717  return Re_pt;
718  }
719 
721  double*& re_st_pt()
722  {
723  return ReSt_pt;
724  }
725 
728  const double& viscosity_ratio() const
729  {
730  return *Viscosity_Ratio_pt;
731  }
732 
735  {
736  return Viscosity_Ratio_pt;
737  }
738 
741  const double& density_ratio() const
742  {
743  return *Density_Ratio_pt;
744  }
745 
747  double*& density_ratio_pt()
748  {
749  return Density_Ratio_pt;
750  }
751 
753  const double& re_invfr() const
754  {
755  return *ReInvFr_pt;
756  }
757 
759  double*& re_invfr_pt()
760  {
761  return ReInvFr_pt;
762  }
763 
765  const Vector<double>& g() const
766  {
767  return *G_pt;
768  }
769 
772  {
773  return G_pt;
774  }
775 
778  {
779  return Body_force_fct_pt;
780  }
781 
784  {
785  return Body_force_fct_pt;
786  }
787 
790  {
791  return Source_fct_pt;
792  }
793 
796  {
797  return Source_fct_pt;
798  }
799 
803  {
805  }
806 
810  const
811  {
813  }
814 
818  {
819  return Pinned_fp_pressure_eqn;
820  }
821 
823  virtual unsigned npres_nst() const = 0;
824 
826  virtual void pshape_nst(const Vector<double>& s, Shape& psi) const = 0;
827 
830  virtual void pshape_nst(const Vector<double>& s,
831  Shape& psi,
832  Shape& test) const = 0;
833 
838  Shape& ppsi,
839  DShape& dppsidx,
840  Shape& ptest,
841  DShape& dptestdx) const = 0;
842 
848  double u_nst(const unsigned& n, const unsigned& i) const
849  {
850  return nodal_value(n, u_index_nst(i));
851  }
852 
855  double u_nst(const unsigned& t, const unsigned& n, const unsigned& i) const
856  {
857  return nodal_value(t, n, u_index_nst(i));
858  }
859 
866  virtual inline unsigned u_index_nst(const unsigned& i) const
867  {
868  return i;
869  }
870 
873  inline unsigned n_u_nst() const
874  {
875  return DIM;
876  }
877 
880  double du_dt_nst(const unsigned& n, const unsigned& i) const
881  {
882  // Get the data's timestepper
884 
885  // Initialise dudt
886  double dudt = 0.0;
887 
888  // Loop over the timesteps, if there is a non Steady timestepper
889  if (!time_stepper_pt->is_steady())
890  {
891  // Find the index at which the dof is stored
892  const unsigned u_nodal_index = this->u_index_nst(i);
893 
894  // Number of timsteps (past & present)
895  const unsigned n_time = time_stepper_pt->ntstorage();
896  // Loop over the timesteps
897  for (unsigned t = 0; t < n_time; t++)
898  {
899  dudt +=
900  time_stepper_pt->weight(1, t) * nodal_value(t, n, u_nodal_index);
901  }
902  }
903 
904  return dudt;
905  }
906 
909  void disable_ALE()
910  {
911  ALE_is_disabled = true;
912  }
913 
918  void enable_ALE()
919  {
920  ALE_is_disabled = false;
921  }
922 
925  virtual double p_nst(const unsigned& n_p) const = 0;
926 
928  virtual double p_nst(const unsigned& t, const unsigned& n_p) const = 0;
929 
931  virtual void fix_pressure(const unsigned& p_dof, const double& p_value) = 0;
932 
936  virtual int p_nodal_index_nst() const
937  {
939  }
940 
942  double pressure_integral() const;
943 
945  double dissipation() const;
946 
948  double dissipation(const Vector<double>& s) const;
949 
952  Vector<double>& vorticity) const;
953 
955  void get_vorticity(const Vector<double>& s, double& vorticity) const;
956 
958  double kin_energy() const;
959 
961  double d_kin_energy_dt() const;
962 
964  void strain_rate(const Vector<double>& s,
966 
970  void get_traction(const Vector<double>& s,
971  const Vector<double>& N,
972  Vector<double>& traction);
973 
978  void get_traction(const Vector<double>& s,
979  const Vector<double>& N,
980  Vector<double>& traction_p,
981  Vector<double>& traction_visc_n,
982  Vector<double>& traction_visc_t);
983 
992  void get_load(const Vector<double>& s,
993  const Vector<double>& N,
995  {
996  // Note: get_traction() computes the traction onto the fluid
997  // if N is the outer unit normal onto the fluid; here we're
998  // exepcting N to point into the fluid so we're getting the
999  // traction onto the adjacent wall instead!
1000  get_traction(s, N, load);
1001  }
1002 
1008  Vector<double>& press_mass_diag,
1009  Vector<double>& veloc_mass_diag,
1010  const unsigned& which_one = 0);
1011 
1014  unsigned nscalar_paraview() const
1015  {
1016  return DIM + 1;
1017  }
1018 
1021  void scalar_value_paraview(std::ofstream& file_out,
1022  const unsigned& i,
1023  const unsigned& nplot) const
1024  {
1025  // Vector of local coordinates
1026  Vector<double> s(DIM);
1027 
1028 
1029  // Loop over plot points
1030  unsigned num_plot_points = nplot_points_paraview(nplot);
1031  for (unsigned iplot = 0; iplot < num_plot_points; iplot++)
1032  {
1033  // Get local coordinates of plot point
1034  get_s_plot(iplot, nplot, s);
1035 
1036  // Velocities
1037  if (i < DIM)
1038  {
1039  file_out << interpolated_u_nst(s, i) << std::endl;
1040  }
1041 
1042  // Pressure
1043  else if (i == DIM)
1044  {
1045  file_out << interpolated_p_nst(s) << std::endl;
1046  }
1047 
1048  // Never get here
1049  else
1050  {
1051 #ifdef PARANOID
1052  std::stringstream error_stream;
1053  error_stream << "These Navier Stokes elements only store " << DIM + 1
1054  << " fields, "
1055  << "but i is currently " << i << std::endl;
1056  throw OomphLibError(error_stream.str(),
1059 #endif
1060  }
1061  }
1062  }
1063 
1064 
1068  std::ofstream& file_out,
1069  const unsigned& i,
1070  const unsigned& nplot,
1071  const double& time,
1072  FiniteElement::UnsteadyExactSolutionFctPt exact_soln_pt) const
1073  {
1074 #ifdef PARANOID
1075  if (i > DIM)
1076  {
1077  // Create an output stream
1078  std::stringstream error_stream;
1079 
1080  // Create the error message
1081  error_stream << "These Navier Stokes elements only store " << DIM + 1
1082  << " fields, but i is currently " << i << std::endl;
1083 
1084  // Throw the error message
1085  throw OomphLibError(
1086  error_stream.str(), OOMPH_CURRENT_FUNCTION, OOMPH_EXCEPTION_LOCATION);
1087  }
1088 #endif
1089 
1090  // Vector of local coordinates
1091  Vector<double> s(DIM + 1, 0.0);
1092 
1093  // Storage for the spatial coordinates
1094  Vector<double> spatial_coordinates(DIM, 0.0);
1095 
1096  // How many plot points do we have in total?
1097  unsigned num_plot_points = nplot_points_paraview(nplot);
1098 
1099  // Loop over plot points
1100  for (unsigned iplot = 0; iplot < num_plot_points; iplot++)
1101  {
1102  // Get the local coordinates of the iplot-th plot point
1103  get_s_plot(iplot, nplot, s);
1104 
1105  // Loop over the spatial coordinates
1106  for (unsigned j = 0; j < DIM; j++)
1107  {
1108  // Assign the i-th spatial coordinate
1109  spatial_coordinates[j] = interpolated_x(s, j);
1110  }
1111 
1112  // Exact solution vector (here it's simply a scalar)
1113  Vector<double> exact_soln(DIM + 1, 0.0);
1114 
1115  // Get the exact solution at this point
1116  (*exact_soln_pt)(time, spatial_coordinates, exact_soln);
1117 
1118  // Output the interpolated solution value
1119  file_out << exact_soln[i] << std::endl;
1120  } // for (unsigned iplot=0;iplot<num_plot_points;iplot++)
1121  } // End of scalar_value_fct_paraview
1122 
1123 
1127  std::string scalar_name_paraview(const unsigned& i) const
1128  {
1129  // Velocities
1130  if (i < DIM)
1131  {
1132  return "Velocity " + StringConversion::to_string(i);
1133  }
1134  // Preussre
1135  else if (i == DIM)
1136  {
1137  return "Pressure";
1138  }
1139  // Never get here
1140  else
1141  {
1142  std::stringstream error_stream;
1143  error_stream << "These Navier Stokes elements only store " << DIM + 1
1144  << " fields,\n"
1145  << "but i is currently " << i << std::endl;
1146  throw OomphLibError(
1147  error_stream.str(), OOMPH_CURRENT_FUNCTION, OOMPH_EXCEPTION_LOCATION);
1148  // Dummy return
1149  return " ";
1150  }
1151  }
1152 
1155  void output(std::ostream& outfile)
1156  {
1157  unsigned nplot = 5;
1158  output(outfile, nplot);
1159  }
1160 
1163  void output(std::ostream& outfile, const unsigned& nplot);
1164 
1167  void output(FILE* file_pt)
1168  {
1169  unsigned nplot = 5;
1170  output(file_pt, nplot);
1171  }
1172 
1175  void output(FILE* file_pt, const unsigned& nplot);
1176 
1180  void full_output(std::ostream& outfile)
1181  {
1182  unsigned nplot = 5;
1183  full_output(outfile, nplot);
1184  }
1185 
1189  void full_output(std::ostream& outfile, const unsigned& nplot);
1190 
1191 
1195  void output_veloc(std::ostream& outfile,
1196  const unsigned& nplot,
1197  const unsigned& t);
1198 
1199 
1202  void output_vorticity(std::ostream& outfile, const unsigned& nplot);
1203 
1207  void output_fct(std::ostream& outfile,
1208  const unsigned& nplot,
1210 
1214  void output_fct(std::ostream& outfile,
1215  const unsigned& nplot,
1216  const double& time,
1218 
1220  void compute_norm(double& norm);
1221 
1223  void compute_norm(Vector<double>& norm);
1224 
1229  void compute_error(std::ostream& outfile,
1231  const double& time,
1232  double& error,
1233  double& norm);
1234 
1239  void compute_error(std::ostream& outfile,
1241  double& error,
1242  double& norm);
1243 
1248  const double& time,
1249  double& error,
1250  double& norm);
1251 
1256  double& error,
1257  double& norm);
1258 
1261  {
1262  // Call the generic residuals function with flag set to 0
1263  // and using a dummy matrix argument
1265  residuals,
1268  0);
1269  }
1270 
1274  DenseMatrix<double>& jacobian)
1275  {
1276  // Call the generic routine with the flag set to 1
1278  residuals, jacobian, GeneralisedElement::Dummy_matrix, 1);
1279  }
1280 
1284  Vector<double>& residuals,
1285  DenseMatrix<double>& jacobian,
1286  DenseMatrix<double>& mass_matrix)
1287  {
1288  // Call the generic routine with the flag set to 2
1290  residuals, jacobian, mass_matrix, 2);
1291  }
1292 
1295  double* const& parameter_pt, Vector<double>& dres_dparam)
1296  {
1297  // Call the generic residuals function with flag set to 0
1298  // and using a dummy matrix argument
1300  parameter_pt,
1301  dres_dparam,
1304  0);
1305  }
1306 
1310  double* const& parameter_pt,
1311  Vector<double>& dres_dparam,
1312  DenseMatrix<double>& djac_dparam)
1313  {
1314  // Call the generic routine with the flag set to 1
1316  parameter_pt,
1317  dres_dparam,
1318  djac_dparam,
1320  1);
1321  }
1322 
1326  double* const& parameter_pt,
1327  Vector<double>& dres_dparam,
1328  DenseMatrix<double>& djac_dparam,
1329  DenseMatrix<double>& dmass_matrix_dparam)
1330  {
1331  // Call the generic routine with the flag set to 2
1333  parameter_pt, dres_dparam, djac_dparam, dmass_matrix_dparam, 2);
1334  }
1335 
1336 
1340  Vector<double>& residuals)
1341  {
1343  residuals, GeneralisedElement::Dummy_matrix, 0);
1344  }
1345 
1349  Vector<double>& residuals, DenseMatrix<double>& jacobian)
1350  {
1352  residuals, jacobian, 1);
1353  }
1354 
1355 
1358  std::map<Data*, std::vector<int>>& eqn_number_backup)
1359  {
1360  // Loop over internal data and pin the values (having established that
1361  // pressure dofs aren't amongst those)
1362  unsigned nint = this->ninternal_data();
1363  for (unsigned j = 0; j < nint; j++)
1364  {
1365  Data* data_pt = this->internal_data_pt(j);
1366  if (eqn_number_backup[data_pt].size() == 0)
1367  {
1368  unsigned nvalue = data_pt->nvalue();
1369  eqn_number_backup[data_pt].resize(nvalue);
1370  for (unsigned i = 0; i < nvalue; i++)
1371  {
1372  // Backup
1373  eqn_number_backup[data_pt][i] = data_pt->eqn_number(i);
1374 
1375  // Pin everything
1376  data_pt->pin(i);
1377  }
1378  }
1379  }
1380 
1381  // Now deal with nodal values
1382  unsigned nnod = this->nnode();
1383  for (unsigned j = 0; j < nnod; j++)
1384  {
1385  Node* nod_pt = this->node_pt(j);
1386  if (eqn_number_backup[nod_pt].size() == 0)
1387  {
1388  unsigned nvalue = nod_pt->nvalue();
1389  eqn_number_backup[nod_pt].resize(nvalue);
1390  for (unsigned i = 0; i < nvalue; i++)
1391  {
1392  // Pin everything apart from the nodal pressure
1393  // value
1394  if (int(i) != this->p_nodal_index_nst())
1395  {
1396  // Backup
1397  eqn_number_backup[nod_pt][i] = nod_pt->eqn_number(i);
1398 
1399  // Pin
1400  nod_pt->pin(i);
1401  }
1402  // Else it's a pressure value
1403  else
1404  {
1405  // Exclude non-nodal pressure based elements
1406  if (this->p_nodal_index_nst() >= 0)
1407  {
1408  // Backup
1409  eqn_number_backup[nod_pt][i] = nod_pt->eqn_number(i);
1410  }
1411  }
1412  }
1413 
1414 
1415  // If it's a solid node deal with its positional data too
1416  SolidNode* solid_nod_pt = dynamic_cast<SolidNode*>(nod_pt);
1417  if (solid_nod_pt != 0)
1418  {
1419  Data* solid_posn_data_pt = solid_nod_pt->variable_position_pt();
1420  if (eqn_number_backup[solid_posn_data_pt].size() == 0)
1421  {
1422  unsigned nvalue = solid_posn_data_pt->nvalue();
1423  eqn_number_backup[solid_posn_data_pt].resize(nvalue);
1424  for (unsigned i = 0; i < nvalue; i++)
1425  {
1426  // Backup
1427  eqn_number_backup[solid_posn_data_pt][i] =
1428  solid_posn_data_pt->eqn_number(i);
1429 
1430  // Pin
1431  solid_posn_data_pt->pin(i);
1432  }
1433  }
1434  }
1435  }
1436  }
1437  }
1438 
1439 
1444  const unsigned& face_index) = 0;
1445 
1450  std::ostream& outfile)
1451  {
1452  unsigned nel = Pressure_advection_diffusion_robin_element_pt.size();
1453  for (unsigned e = 0; e < nel; e++)
1454  {
1455  FaceElement* face_el_pt =
1457  outfile << "ZONE" << std::endl;
1458  Vector<double> unit_normal(DIM);
1459  Vector<double> x(DIM);
1460  Vector<double> s(DIM - 1);
1461  unsigned n = face_el_pt->integral_pt()->nweight();
1462  for (unsigned ipt = 0; ipt < n; ipt++)
1463  {
1464  for (unsigned i = 0; i < DIM - 1; i++)
1465  {
1466  s[i] = face_el_pt->integral_pt()->knot(ipt, i);
1467  }
1468  face_el_pt->interpolated_x(s, x);
1469  face_el_pt->outer_unit_normal(ipt, unit_normal);
1470  for (unsigned i = 0; i < DIM; i++)
1471  {
1472  outfile << x[i] << " ";
1473  }
1474  for (unsigned i = 0; i < DIM; i++)
1475  {
1476  outfile << unit_normal[i] << " ";
1477  }
1478  outfile << std::endl;
1479  }
1480  }
1481  }
1482 
1487  {
1488  unsigned nel = Pressure_advection_diffusion_robin_element_pt.size();
1489  for (unsigned e = 0; e < nel; e++)
1490  {
1492  }
1494  }
1495 
1500  virtual void get_dresidual_dnodal_coordinates(
1501  RankThreeTensor<double>& dresidual_dnodal_coordinates);
1502 
1503 
1506  Vector<double>& veloc) const
1507  {
1508  // Find number of nodes
1509  unsigned n_node = nnode();
1510  // Local shape function
1511  Shape psi(n_node);
1512  // Find values of shape function
1513  shape(s, psi);
1514 
1515  for (unsigned i = 0; i < DIM; i++)
1516  {
1517  // Index at which the nodal value is stored
1518  unsigned u_nodal_index = u_index_nst(i);
1519  // Initialise value of u
1520  veloc[i] = 0.0;
1521  // Loop over the local nodes and sum
1522  for (unsigned l = 0; l < n_node; l++)
1523  {
1524  veloc[i] += nodal_value(l, u_nodal_index) * psi[l];
1525  }
1526  }
1527  }
1528 
1530  double interpolated_u_nst(const Vector<double>& s, const unsigned& i) const
1531  {
1532  // Find number of nodes
1533  unsigned n_node = nnode();
1534  // Local shape function
1535  Shape psi(n_node);
1536  // Find values of shape function
1537  shape(s, psi);
1538 
1539  // Get nodal index at which i-th velocity is stored
1540  unsigned u_nodal_index = u_index_nst(i);
1541 
1542  // Initialise value of u
1543  double interpolated_u = 0.0;
1544  // Loop over the local nodes and sum
1545  for (unsigned l = 0; l < n_node; l++)
1546  {
1547  interpolated_u += nodal_value(l, u_nodal_index) * psi[l];
1548  }
1549 
1550  return (interpolated_u);
1551  }
1552 
1555  double interpolated_u_nst(const unsigned& t,
1556  const Vector<double>& s,
1557  const unsigned& i) const
1558  {
1559  // Find number of nodes
1560  unsigned n_node = nnode();
1561 
1562  // Local shape function
1563  Shape psi(n_node);
1564 
1565  // Find values of shape function
1566  shape(s, psi);
1567 
1568  // Get nodal index at which i-th velocity is stored
1569  unsigned u_nodal_index = u_index_nst(i);
1570 
1571  // Initialise value of u
1572  double interpolated_u = 0.0;
1573  // Loop over the local nodes and sum
1574  for (unsigned l = 0; l < n_node; l++)
1575  {
1576  interpolated_u += nodal_value(t, l, u_nodal_index) * psi[l];
1577  }
1578 
1579  return (interpolated_u);
1580  }
1581 
1588  const unsigned& i,
1589  Vector<double>& du_ddata,
1590  Vector<unsigned>& global_eqn_number)
1591  {
1592  // Find number of nodes
1593  unsigned n_node = nnode();
1594  // Local shape function
1595  Shape psi(n_node);
1596  // Find values of shape function
1597  shape(s, psi);
1598 
1599  // Find the index at which the velocity component is stored
1600  const unsigned u_nodal_index = u_index_nst(i);
1601 
1602  // Find the number of dofs associated with interpolated u
1603  unsigned n_u_dof = 0;
1604  for (unsigned l = 0; l < n_node; l++)
1605  {
1606  int global_eqn = this->node_pt(l)->eqn_number(u_nodal_index);
1607  // If it's positive add to the count
1608  if (global_eqn >= 0)
1609  {
1610  ++n_u_dof;
1611  }
1612  }
1613 
1614  // Now resize the storage schemes
1615  du_ddata.resize(n_u_dof, 0.0);
1616  global_eqn_number.resize(n_u_dof, 0);
1617 
1618  // Loop over th nodes again and set the derivatives
1619  unsigned count = 0;
1620  // Loop over the local nodes and sum
1621  for (unsigned l = 0; l < n_node; l++)
1622  {
1623  // Get the global equation number
1624  int global_eqn = this->node_pt(l)->eqn_number(u_nodal_index);
1625  if (global_eqn >= 0)
1626  {
1627  // Set the global equation number
1628  global_eqn_number[count] = global_eqn;
1629  // Set the derivative with respect to the unknown
1630  du_ddata[count] = psi[l];
1631  // Increase the counter
1632  ++count;
1633  }
1634  }
1635  }
1636 
1637 
1639  virtual double interpolated_p_nst(const Vector<double>& s) const
1640  {
1641  // Find number of nodes
1642  unsigned n_pres = npres_nst();
1643  // Local shape function
1644  Shape psi(n_pres);
1645  // Find values of shape function
1646  pshape_nst(s, psi);
1647 
1648  // Initialise value of p
1649  double interpolated_p = 0.0;
1650  // Loop over the local nodes and sum
1651  for (unsigned l = 0; l < n_pres; l++)
1652  {
1653  interpolated_p += p_nst(l) * psi[l];
1654  }
1655 
1656  return (interpolated_p);
1657  }
1658 
1659 
1661  double interpolated_p_nst(const unsigned& t, const Vector<double>& s) const
1662  {
1663  // Find number of nodes
1664  unsigned n_pres = npres_nst();
1665  // Local shape function
1666  Shape psi(n_pres);
1667  // Find values of shape function
1668  pshape_nst(s, psi);
1669 
1670  // Initialise value of p
1671  double interpolated_p = 0.0;
1672  // Loop over the local nodes and sum
1673  for (unsigned l = 0; l < n_pres; l++)
1674  {
1675  interpolated_p += p_nst(t, l) * psi[l];
1676  }
1677 
1678  return (interpolated_p);
1679  }
1680 
1681 
1685  const unsigned& i,
1686  const unsigned& j) const
1687  {
1688  // Determine number of nodes
1689  const unsigned n_node = nnode();
1690 
1691  // Allocate storage for local shape function and its derivatives
1692  // with respect to space
1693  Shape psif(n_node);
1694  DShape dpsifdx(n_node, DIM);
1695 
1696  // Find values of shape function (ignore jacobian)
1697  (void)this->dshape_eulerian(s, psif, dpsifdx);
1698 
1699  // Get the index at which the velocity is stored
1700  const unsigned u_nodal_index = u_index_nst(i);
1701 
1702  // Initialise value of dudx
1703  double interpolated_dudx = 0.0;
1704 
1705  // Loop over the local nodes and sum
1706  for (unsigned l = 0; l < n_node; l++)
1707  {
1708  interpolated_dudx += nodal_value(l, u_nodal_index) * dpsifdx(l, j);
1709  }
1710 
1711  return (interpolated_dudx);
1712  }
1713 
1714 
1718  {
1719  // Dimension
1720  unsigned dim = s.size();
1721 
1722  // Resize data for values
1723  data.resize(2 * dim + 1);
1724 
1725  // Write values in the vector
1726  for (unsigned i = 0; i < dim; i++)
1727  {
1728  data[i] = interpolated_x(s, i);
1729  data[i + dim] = this->interpolated_u_nst(s, i);
1730  }
1731  data[2 * dim] = this->interpolated_p_nst(s);
1732  }
1733  };
1734 
1738 
1739 
1740  //==========================================================================
1745  //==========================================================================
1746  template<unsigned DIM>
1747  class QCrouzeixRaviartElement : public virtual QElement<DIM, 3>,
1748  public virtual NavierStokesEquations<DIM>
1749  {
1750  private:
1752  static const unsigned Initial_Nvalue[];
1753 
1754  protected:
1758 
1759 
1763  inline double dshape_and_dtest_eulerian_nst(const Vector<double>& s,
1764  Shape& psi,
1765  DShape& dpsidx,
1766  Shape& test,
1767  DShape& dtestdx) const;
1768 
1772  inline double dshape_and_dtest_eulerian_at_knot_nst(const unsigned& ipt,
1773  Shape& psi,
1774  DShape& dpsidx,
1775  Shape& test,
1776  DShape& dtestdx) const;
1777 
1782  const unsigned& ipt,
1783  Shape& psi,
1784  DShape& dpsidx,
1785  RankFourTensor<double>& d_dpsidx_dX,
1786  Shape& test,
1787  DShape& dtestdx,
1788  RankFourTensor<double>& d_dtestdx_dX,
1789  DenseMatrix<double>& djacobian_dX) const;
1790 
1791 
1792  public:
1795  {
1796  // Allocate and add one Internal data object that stored DIM+1 pressure
1797  // values;
1798  P_nst_internal_index = this->add_internal_data(new Data(DIM + 1));
1799  }
1800 
1802  virtual unsigned required_nvalue(const unsigned& n) const;
1803 
1804 
1806  inline void pshape_nst(const Vector<double>& s, Shape& psi) const;
1807 
1809  inline void pshape_nst(const Vector<double>& s,
1810  Shape& psi,
1811  Shape& test) const;
1812 
1816  double p_nst(const unsigned& i) const
1817  {
1818  return this->internal_data_pt(P_nst_internal_index)->value(i);
1819  }
1820 
1824  double p_nst(const unsigned& t, const unsigned& i) const
1825  {
1826  return this->internal_data_pt(P_nst_internal_index)->value(t, i);
1827  }
1828 
1830  unsigned npres_nst() const
1831  {
1832  return DIM + 1;
1833  }
1834 
1839  Shape& ppsi,
1840  DShape& dppsidx,
1841  Shape& ptest,
1842  DShape& dptestdx) const;
1843 
1845  inline int p_local_eqn(const unsigned& n) const
1846  {
1847  return this->internal_local_eqn(P_nst_internal_index, n);
1848  }
1849 
1851  void fix_pressure(const unsigned& p_dof, const double& p_value)
1852  {
1853  this->internal_data_pt(P_nst_internal_index)->pin(p_dof);
1854  this->internal_data_pt(P_nst_internal_index)->set_value(p_dof, p_value);
1855  }
1856 
1857 
1861  void build_fp_press_adv_diff_robin_bc_element(const unsigned& face_index)
1862  {
1865  this, face_index));
1866  }
1867 
1875  void identify_load_data(
1876  std::set<std::pair<Data*, unsigned>>& paired_load_data);
1877 
1887  std::set<std::pair<Data*, unsigned>>& paired_pressure_data);
1888 
1889 
1891  void output(std::ostream& outfile)
1892  {
1894  }
1895 
1897  void output(std::ostream& outfile, const unsigned& nplot)
1898  {
1899  NavierStokesEquations<DIM>::output(outfile, nplot);
1900  }
1901 
1902 
1904  void output(FILE* file_pt)
1905  {
1907  }
1908 
1910  void output(FILE* file_pt, const unsigned& nplot)
1911  {
1912  NavierStokesEquations<DIM>::output(file_pt, nplot);
1913  }
1914 
1915 
1919  void full_output(std::ostream& outfile)
1920  {
1922  }
1923 
1927  void full_output(std::ostream& outfile, const unsigned& nplot)
1928  {
1930  }
1931 
1932 
1935  unsigned ndof_types() const
1936  {
1937  return DIM + 1;
1938  }
1939 
1947  std::list<std::pair<unsigned long, unsigned>>& dof_lookup_list) const;
1948  };
1949 
1950  // Inline functions
1951 
1952  //=======================================================================
1956  //=======================================================================
1957  template<unsigned DIM>
1959  const Vector<double>& s,
1960  Shape& psi,
1961  DShape& dpsidx,
1962  Shape& test,
1963  DShape& dtestdx) const
1964  {
1965  // Call the geometrical shape functions and derivatives
1966  double J = this->dshape_eulerian(s, psi, dpsidx);
1967  // The test functions are equal to the shape functions
1968  test = psi;
1969  dtestdx = dpsidx;
1970  // Return the jacobian
1971  return J;
1972  }
1973 
1974  //=======================================================================
1978  //=======================================================================
1979  template<unsigned DIM>
1980  inline double QCrouzeixRaviartElement<
1981  DIM>::dshape_and_dtest_eulerian_at_knot_nst(const unsigned& ipt,
1982  Shape& psi,
1983  DShape& dpsidx,
1984  Shape& test,
1985  DShape& dtestdx) const
1986  {
1987  // Call the geometrical shape functions and derivatives
1988  double J = this->dshape_eulerian_at_knot(ipt, psi, dpsidx);
1989  // The test functions are equal to the shape functions
1990  test = psi;
1991  dtestdx = dpsidx;
1992  // Return the jacobian
1993  return J;
1994  }
1995 
1996 
1997  //=======================================================================
2005  //=======================================================================
2006  template<>
2009  const unsigned& ipt,
2010  Shape& psi,
2011  DShape& dpsidx,
2012  RankFourTensor<double>& d_dpsidx_dX,
2013  Shape& test,
2014  DShape& dtestdx,
2015  RankFourTensor<double>& d_dtestdx_dX,
2016  DenseMatrix<double>& djacobian_dX) const
2017  {
2018  // Call the geometrical shape functions and derivatives
2019  const double J = this->dshape_eulerian_at_knot(
2020  ipt, psi, dpsidx, djacobian_dX, d_dpsidx_dX);
2021 
2022  // Loop over the test functions and derivatives and set them equal to the
2023  // shape functions
2024  for (unsigned i = 0; i < 9; i++)
2025  {
2026  test[i] = psi[i];
2027 
2028  for (unsigned k = 0; k < 2; k++)
2029  {
2030  dtestdx(i, k) = dpsidx(i, k);
2031 
2032  for (unsigned p = 0; p < 2; p++)
2033  {
2034  for (unsigned q = 0; q < 9; q++)
2035  {
2036  d_dtestdx_dX(p, q, i, k) = d_dpsidx_dX(p, q, i, k);
2037  }
2038  }
2039  }
2040  }
2041 
2042  // Return the jacobian
2043  return J;
2044  }
2045 
2046 
2047  //=======================================================================
2055  //=======================================================================
2056  template<>
2059  const unsigned& ipt,
2060  Shape& psi,
2061  DShape& dpsidx,
2062  RankFourTensor<double>& d_dpsidx_dX,
2063  Shape& test,
2064  DShape& dtestdx,
2065  RankFourTensor<double>& d_dtestdx_dX,
2066  DenseMatrix<double>& djacobian_dX) const
2067  {
2068  // Call the geometrical shape functions and derivatives
2069  const double J = this->dshape_eulerian_at_knot(
2070  ipt, psi, dpsidx, djacobian_dX, d_dpsidx_dX);
2071 
2072  // Loop over the test functions and derivatives and set them equal to the
2073  // shape functions
2074  for (unsigned i = 0; i < 27; i++)
2075  {
2076  test[i] = psi[i];
2077 
2078  for (unsigned k = 0; k < 3; k++)
2079  {
2080  dtestdx(i, k) = dpsidx(i, k);
2081 
2082  for (unsigned p = 0; p < 3; p++)
2083  {
2084  for (unsigned q = 0; q < 27; q++)
2085  {
2086  d_dtestdx_dX(p, q, i, k) = d_dpsidx_dX(p, q, i, k);
2087  }
2088  }
2089  }
2090  }
2091 
2092  // Return the jacobian
2093  return J;
2094  }
2095 
2096 
2097  //=======================================================================
2100  //=======================================================================
2101  template<>
2103  Shape& psi) const
2104  {
2105  psi[0] = 1.0;
2106  psi[1] = s[0];
2107  psi[2] = s[1];
2108  }
2109 
2110 
2111  //==========================================================================
2115  //==========================================================================
2116  template<>
2118  const Vector<double>& s,
2119  Shape& ppsi,
2120  DShape& dppsidx,
2121  Shape& ptest,
2122  DShape& dptestdx) const
2123  {
2124  // Initalise with shape fcts and derivs. w.r.t. to local coordinates
2125  ppsi[0] = 1.0;
2126  ppsi[1] = s[0];
2127  ppsi[2] = s[1];
2128 
2129  dppsidx(0, 0) = 0.0;
2130  dppsidx(1, 0) = 1.0;
2131  dppsidx(2, 0) = 0.0;
2132 
2133  dppsidx(0, 1) = 0.0;
2134  dppsidx(1, 1) = 0.0;
2135  dppsidx(2, 1) = 1.0;
2136 
2137 
2138  // Get the values of the shape functions and their local derivatives
2139  Shape psi(9);
2140  DShape dpsi(9, 2);
2141  dshape_local(s, psi, dpsi);
2142 
2143  // Allocate memory for the inverse 2x2 jacobian
2144  DenseMatrix<double> inverse_jacobian(2);
2145 
2146  // Now calculate the inverse jacobian
2147  const double det = local_to_eulerian_mapping(dpsi, inverse_jacobian);
2148 
2149  // Now set the values of the derivatives to be derivs w.r.t. to the
2150  // Eulerian coordinates
2151  transform_derivatives(inverse_jacobian, dppsidx);
2152 
2153  // The test functions are equal to the shape functions
2154  ptest = ppsi;
2155  dptestdx = dppsidx;
2156 
2157  // Return the determinant of the jacobian
2158  return det;
2159  }
2160 
2161 
2162  //=======================================================================
2164  //=======================================================================
2165  template<unsigned DIM>
2167  Shape& psi,
2168  Shape& test) const
2169  {
2170  // Call the pressure shape functions
2171  this->pshape_nst(s, psi);
2172  // Test functions are equal to shape functions
2173  test = psi;
2174  }
2175 
2176 
2177  //=======================================================================
2180  //=======================================================================
2181  template<>
2183  Shape& psi) const
2184  {
2185  psi[0] = 1.0;
2186  psi[1] = s[0];
2187  psi[2] = s[1];
2188  psi[3] = s[2];
2189  }
2190 
2191 
2192  //==========================================================================
2196  //==========================================================================
2197  template<>
2199  const Vector<double>& s,
2200  Shape& ppsi,
2201  DShape& dppsidx,
2202  Shape& ptest,
2203  DShape& dptestdx) const
2204  {
2205  // Initalise with shape fcts and derivs. w.r.t. to local coordinates
2206  ppsi[0] = 1.0;
2207  ppsi[1] = s[0];
2208  ppsi[2] = s[1];
2209  ppsi[3] = s[2];
2210 
2211  dppsidx(0, 0) = 0.0;
2212  dppsidx(1, 0) = 1.0;
2213  dppsidx(2, 0) = 0.0;
2214  dppsidx(3, 0) = 0.0;
2215 
2216  dppsidx(0, 1) = 0.0;
2217  dppsidx(1, 1) = 0.0;
2218  dppsidx(2, 1) = 1.0;
2219  dppsidx(3, 1) = 0.0;
2220 
2221  dppsidx(0, 2) = 0.0;
2222  dppsidx(1, 2) = 0.0;
2223  dppsidx(2, 2) = 0.0;
2224  dppsidx(3, 2) = 1.0;
2225 
2226 
2227  // Get the values of the shape functions and their local derivatives
2228  Shape psi(27);
2229  DShape dpsi(27, 3);
2230  dshape_local(s, psi, dpsi);
2231 
2232  // Allocate memory for the inverse 3x3 jacobian
2233  DenseMatrix<double> inverse_jacobian(3);
2234 
2235  // Now calculate the inverse jacobian
2236  const double det = local_to_eulerian_mapping(dpsi, inverse_jacobian);
2237 
2238  // Now set the values of the derivatives to be derivs w.r.t. to the
2239  // Eulerian coordinates
2240  transform_derivatives(inverse_jacobian, dppsidx);
2241 
2242  // The test functions are equal to the shape functions
2243  ptest = ppsi;
2244  dptestdx = dppsidx;
2245 
2246  // Return the determinant of the jacobian
2247  return det;
2248  }
2249 
2250 
2251  //=======================================================================
2253  //=======================================================================
2254  template<>
2255  class FaceGeometry<QCrouzeixRaviartElement<2>> : public virtual QElement<1, 3>
2256  {
2257  public:
2258  FaceGeometry() : QElement<1, 3>() {}
2259  };
2260 
2261  //=======================================================================
2263  //=======================================================================
2264  template<>
2265  class FaceGeometry<QCrouzeixRaviartElement<3>> : public virtual QElement<2, 3>
2266  {
2267  public:
2268  FaceGeometry() : QElement<2, 3>() {}
2269  };
2270 
2271  //=======================================================================
2273  //=======================================================================
2274  template<>
2276  : public virtual PointElement
2277  {
2278  public:
2280  };
2281 
2282 
2283  //=======================================================================
2285  //=======================================================================
2286  template<>
2288  : public virtual QElement<1, 3>
2289  {
2290  public:
2291  FaceGeometry() : QElement<1, 3>() {}
2292  };
2293 
2294 
2297 
2298 
2299  //=======================================================================
2304  //=======================================================================
2305  template<unsigned DIM>
2306  class QTaylorHoodElement : public virtual QElement<DIM, 3>,
2307  public virtual NavierStokesEquations<DIM>
2308  {
2309  private:
2311  static const unsigned Initial_Nvalue[];
2312 
2313  protected:
2316  static const unsigned Pconv[];
2317 
2322  Shape& psi,
2323  DShape& dpsidx,
2324  Shape& test,
2325  DShape& dtestdx) const;
2326 
2330  inline double dshape_and_dtest_eulerian_at_knot_nst(const unsigned& ipt,
2331  Shape& psi,
2332  DShape& dpsidx,
2333  Shape& test,
2334  DShape& dtestdx) const;
2335 
2340  const unsigned& ipt,
2341  Shape& psi,
2342  DShape& dpsidx,
2343  RankFourTensor<double>& d_dpsidx_dX,
2344  Shape& test,
2345  DShape& dtestdx,
2346  RankFourTensor<double>& d_dtestdx_dX,
2347  DenseMatrix<double>& djacobian_dX) const;
2348 
2349  public:
2352 
2355  inline virtual unsigned required_nvalue(const unsigned& n) const
2356  {
2357  return Initial_Nvalue[n];
2358  }
2359 
2360 
2362  inline void pshape_nst(const Vector<double>& s, Shape& psi) const;
2363 
2365  inline void pshape_nst(const Vector<double>& s,
2366  Shape& psi,
2367  Shape& test) const;
2368 
2370  virtual int p_nodal_index_nst() const
2371  {
2372  return static_cast<int>(DIM);
2373  }
2374 
2376  inline int p_local_eqn(const unsigned& n) const
2377  {
2378  return this->nodal_local_eqn(Pconv[n], p_nodal_index_nst());
2379  }
2380 
2383  double p_nst(const unsigned& n_p) const
2384  {
2385  return this->nodal_value(Pconv[n_p], this->p_nodal_index_nst());
2386  }
2387 
2390  double p_nst(const unsigned& t, const unsigned& n_p) const
2391  {
2392  return this->nodal_value(t, Pconv[n_p], this->p_nodal_index_nst());
2393  }
2394 
2399  Shape& ppsi,
2400  DShape& dppsidx,
2401  Shape& ptest,
2402  DShape& dptestdx) const;
2403 
2405  unsigned npres_nst() const
2406  {
2407  return static_cast<unsigned>(pow(2.0, static_cast<int>(DIM)));
2408  }
2409 
2410 
2412  bool is_pressure_node(const unsigned& n) const
2413  {
2414  // The number of pressure nodes
2415  unsigned n_p = npres_nst();
2416 
2417  // See if the value n is in the array Pconv
2418  return std::find(this->Pconv, this->Pconv + n_p, n) != this->Pconv + n_p;
2419  } // End of is_pressure_node
2420 
2421 
2423  void fix_pressure(const unsigned& p_dof, const double& p_value)
2424  {
2425  this->node_pt(Pconv[p_dof])->pin(this->p_nodal_index_nst());
2426  this->node_pt(Pconv[p_dof])
2427  ->set_value(this->p_nodal_index_nst(), p_value);
2428  }
2429 
2430 
2434  void build_fp_press_adv_diff_robin_bc_element(const unsigned& face_index)
2435  {
2438  this, face_index));
2439  }
2440 
2441 
2449  void identify_load_data(
2450  std::set<std::pair<Data*, unsigned>>& paired_load_data);
2451 
2452 
2462  std::set<std::pair<Data*, unsigned>>& paired_pressure_data);
2463 
2464 
2466  void output(std::ostream& outfile)
2467  {
2469  }
2470 
2472  void output(std::ostream& outfile, const unsigned& nplot)
2473  {
2474  NavierStokesEquations<DIM>::output(outfile, nplot);
2475  }
2476 
2478  void output(FILE* file_pt)
2479  {
2481  }
2482 
2484  void output(FILE* file_pt, const unsigned& nplot)
2485  {
2486  NavierStokesEquations<DIM>::output(file_pt, nplot);
2487  }
2488 
2489 
2492  unsigned ndof_types() const
2493  {
2494  return DIM + 1;
2495  }
2496 
2504  std::list<std::pair<unsigned long, unsigned>>& dof_lookup_list) const;
2505  };
2506 
2507  // Inline functions
2508 
2509  //==========================================================================
2513  //==========================================================================
2514  template<unsigned DIM>
2516  const Vector<double>& s,
2517  Shape& psi,
2518  DShape& dpsidx,
2519  Shape& test,
2520  DShape& dtestdx) const
2521  {
2522  // Call the geometrical shape functions and derivatives
2523  double J = this->dshape_eulerian(s, psi, dpsidx);
2524 
2525  // The test functions are equal to the shape functions
2526  test = psi;
2527  dtestdx = dpsidx;
2528 
2529  // Return the jacobian
2530  return J;
2531  }
2532 
2533 
2534  //==========================================================================
2538  //==========================================================================
2539  template<unsigned DIM>
2541  const unsigned& ipt,
2542  Shape& psi,
2543  DShape& dpsidx,
2544  Shape& test,
2545  DShape& dtestdx) const
2546  {
2547  // Call the geometrical shape functions and derivatives
2548  double J = this->dshape_eulerian_at_knot(ipt, psi, dpsidx);
2549 
2550  // The test functions are equal to the shape functions
2551  test = psi;
2552  dtestdx = dpsidx;
2553 
2554  // Return the jacobian
2555  return J;
2556  }
2557 
2558 
2559  //==========================================================================
2563  //==========================================================================
2564  template<>
2566  const Vector<double>& s,
2567  Shape& ppsi,
2568  DShape& dppsidx,
2569  Shape& ptest,
2570  DShape& dptestdx) const
2571  {
2572  // Local storage
2573  double psi1[2], psi2[2];
2574  double dpsi1[2], dpsi2[2];
2575 
2576  // Call the OneDimensional Shape functions
2577  OneDimLagrange::shape<2>(s[0], psi1);
2578  OneDimLagrange::shape<2>(s[1], psi2);
2579  OneDimLagrange::dshape<2>(s[0], dpsi1);
2580  OneDimLagrange::dshape<2>(s[1], dpsi2);
2581 
2582  // Now let's loop over the nodal points in the element
2583  // s1 is the "x" coordinate, s2 the "y"
2584  for (unsigned i = 0; i < 2; i++)
2585  {
2586  for (unsigned j = 0; j < 2; j++)
2587  {
2588  /*Multiply the two 1D functions together to get the 2D function*/
2589  ppsi[2 * i + j] = psi2[i] * psi1[j];
2590  dppsidx(2 * i + j, 0) = psi2[i] * dpsi1[j];
2591  dppsidx(2 * i + j, 1) = dpsi2[i] * psi1[j];
2592  }
2593  }
2594 
2595 
2596  // Get the values of the shape functions and their local derivatives
2597  Shape psi(9);
2598  DShape dpsi(9, 2);
2599  dshape_local(s, psi, dpsi);
2600 
2601  // Allocate memory for the inverse 2x2 jacobian
2602  DenseMatrix<double> inverse_jacobian(2);
2603 
2604  // Now calculate the inverse jacobian
2605  const double det = local_to_eulerian_mapping(dpsi, inverse_jacobian);
2606 
2607  // Now set the values of the derivatives to be derivs w.r.t. to the
2608  // Eulerian coordinates
2609  transform_derivatives(inverse_jacobian, dppsidx);
2610 
2611  // The test functions are equal to the shape functions
2612  ptest = ppsi;
2613  dptestdx = dppsidx;
2614 
2615  // Return the determinant of the jacobian
2616  return det;
2617  }
2618 
2619 
2620  //==========================================================================
2628  //==========================================================================
2629  template<>
2631  const unsigned& ipt,
2632  Shape& psi,
2633  DShape& dpsidx,
2634  RankFourTensor<double>& d_dpsidx_dX,
2635  Shape& test,
2636  DShape& dtestdx,
2637  RankFourTensor<double>& d_dtestdx_dX,
2638  DenseMatrix<double>& djacobian_dX) const
2639  {
2640  // Call the geometrical shape functions and derivatives
2641  const double J = this->dshape_eulerian_at_knot(
2642  ipt, psi, dpsidx, djacobian_dX, d_dpsidx_dX);
2643 
2644  // Loop over the test functions and derivatives and set them equal to the
2645  // shape functions
2646  for (unsigned i = 0; i < 9; i++)
2647  {
2648  test[i] = psi[i];
2649 
2650  for (unsigned k = 0; k < 2; k++)
2651  {
2652  dtestdx(i, k) = dpsidx(i, k);
2653 
2654  for (unsigned p = 0; p < 2; p++)
2655  {
2656  for (unsigned q = 0; q < 9; q++)
2657  {
2658  d_dtestdx_dX(p, q, i, k) = d_dpsidx_dX(p, q, i, k);
2659  }
2660  }
2661  }
2662  }
2663 
2664  // Return the jacobian
2665  return J;
2666  }
2667 
2668 
2669  //==========================================================================
2677  //==========================================================================
2678  template<>
2680  const unsigned& ipt,
2681  Shape& psi,
2682  DShape& dpsidx,
2683  RankFourTensor<double>& d_dpsidx_dX,
2684  Shape& test,
2685  DShape& dtestdx,
2686  RankFourTensor<double>& d_dtestdx_dX,
2687  DenseMatrix<double>& djacobian_dX) const
2688  {
2689  // Call the geometrical shape functions and derivatives
2690  const double J = this->dshape_eulerian_at_knot(
2691  ipt, psi, dpsidx, djacobian_dX, d_dpsidx_dX);
2692 
2693  // Loop over the test functions and derivatives and set them equal to the
2694  // shape functions
2695  for (unsigned i = 0; i < 27; i++)
2696  {
2697  test[i] = psi[i];
2698 
2699  for (unsigned k = 0; k < 3; k++)
2700  {
2701  dtestdx(i, k) = dpsidx(i, k);
2702 
2703  for (unsigned p = 0; p < 3; p++)
2704  {
2705  for (unsigned q = 0; q < 27; q++)
2706  {
2707  d_dtestdx_dX(p, q, i, k) = d_dpsidx_dX(p, q, i, k);
2708  }
2709  }
2710  }
2711  }
2712 
2713  // Return the jacobian
2714  return J;
2715  }
2716 
2717 
2718  //==========================================================================
2721  //==========================================================================
2722  template<>
2724  Shape& psi) const
2725  {
2726  // Local storage
2727  double psi1[2], psi2[2];
2728  // Call the OneDimensional Shape functions
2729  OneDimLagrange::shape<2>(s[0], psi1);
2730  OneDimLagrange::shape<2>(s[1], psi2);
2731 
2732  // Now let's loop over the nodal points in the element
2733  // s1 is the "x" coordinate, s2 the "y"
2734  for (unsigned i = 0; i < 2; i++)
2735  {
2736  for (unsigned j = 0; j < 2; j++)
2737  {
2738  /*Multiply the two 1D functions together to get the 2D function*/
2739  psi[2 * i + j] = psi2[i] * psi1[j];
2740  }
2741  }
2742  }
2743 
2744 
2745  //==========================================================================
2749  //==========================================================================
2750  template<>
2752  const Vector<double>& s,
2753  Shape& ppsi,
2754  DShape& dppsidx,
2755  Shape& ptest,
2756  DShape& dptestdx) const
2757  {
2758  // Local storage
2759  double psi1[2], psi2[2], psi3[2];
2760  double dpsi1[2], dpsi2[2], dpsi3[2];
2761 
2762  // Call the OneDimensional Shape functions
2763  OneDimLagrange::shape<2>(s[0], psi1);
2764  OneDimLagrange::shape<2>(s[1], psi2);
2765  OneDimLagrange::shape<2>(s[2], psi3);
2766  OneDimLagrange::dshape<2>(s[0], dpsi1);
2767  OneDimLagrange::dshape<2>(s[1], dpsi2);
2768  OneDimLagrange::dshape<2>(s[2], dpsi3);
2769 
2770  // Now let's loop over the nodal points in the element
2771  // s0 is the "x" coordinate, s1 the "y", s2 is the "z"
2772  for (unsigned i = 0; i < 2; i++)
2773  {
2774  for (unsigned j = 0; j < 2; j++)
2775  {
2776  for (unsigned k = 0; k < 2; k++)
2777  {
2778  /*Multiply the three 1D functions together to get the 3D function*/
2779  ppsi[4 * i + 2 * j + k] = psi3[i] * psi2[j] * psi1[k];
2780  dppsidx(4 * i + 2 * j + k, 0) = psi3[i] * psi2[j] * dpsi1[k];
2781  dppsidx(4 * i + 2 * j + k, 1) = psi3[i] * dpsi2[j] * psi1[k];
2782  dppsidx(4 * i + 2 * j + k, 2) = dpsi3[i] * psi2[j] * psi1[k];
2783  }
2784  }
2785  }
2786 
2787 
2788  // Get the values of the shape functions and their local derivatives
2789  Shape psi(27);
2790  DShape dpsi(27, 3);
2791  dshape_local(s, psi, dpsi);
2792 
2793  // Allocate memory for the inverse 3x3 jacobian
2794  DenseMatrix<double> inverse_jacobian(3);
2795 
2796  // Now calculate the inverse jacobian
2797  const double det = local_to_eulerian_mapping(dpsi, inverse_jacobian);
2798 
2799  // Now set the values of the derivatives to be derivs w.r.t. to the
2800  // Eulerian coordinates
2801  transform_derivatives(inverse_jacobian, dppsidx);
2802 
2803  // The test functions are equal to the shape functions
2804  ptest = ppsi;
2805  dptestdx = dppsidx;
2806 
2807  // Return the determinant of the jacobian
2808  return det;
2809  }
2810 
2811  //==========================================================================
2814  //==========================================================================
2815  template<>
2817  Shape& psi) const
2818  {
2819  // Local storage
2820  double psi1[2], psi2[2], psi3[2];
2821 
2822  // Call the OneDimensional Shape functions
2823  OneDimLagrange::shape<2>(s[0], psi1);
2824  OneDimLagrange::shape<2>(s[1], psi2);
2825  OneDimLagrange::shape<2>(s[2], psi3);
2826 
2827  // Now let's loop over the nodal points in the element
2828  // s0 is the "x" coordinate, s1 the "y", s2 is the "z"
2829  for (unsigned i = 0; i < 2; i++)
2830  {
2831  for (unsigned j = 0; j < 2; j++)
2832  {
2833  for (unsigned k = 0; k < 2; k++)
2834  {
2835  /*Multiply the three 1D functions together to get the 3D function*/
2836  psi[4 * i + 2 * j + k] = psi3[i] * psi2[j] * psi1[k];
2837  }
2838  }
2839  }
2840  }
2841 
2842 
2843  //==========================================================================
2845  //==========================================================================
2846  template<unsigned DIM>
2848  Shape& psi,
2849  Shape& test) const
2850  {
2851  // Call the pressure shape functions
2852  this->pshape_nst(s, psi);
2853  // Test functions are shape functions
2854  test = psi;
2855  }
2856 
2857 
2858  //=======================================================================
2860  //=======================================================================
2861  template<>
2862  class FaceGeometry<QTaylorHoodElement<2>> : public virtual QElement<1, 3>
2863  {
2864  public:
2865  FaceGeometry() : QElement<1, 3>() {}
2866  };
2867 
2868  //=======================================================================
2870  //=======================================================================
2871  template<>
2872  class FaceGeometry<QTaylorHoodElement<3>> : public virtual QElement<2, 3>
2873  {
2874  public:
2875  FaceGeometry() : QElement<2, 3>() {}
2876  };
2877 
2878 
2879  //=======================================================================
2881  //=======================================================================
2882  template<>
2884  : public virtual PointElement
2885  {
2886  public:
2888  };
2889 
2890 
2891  //=======================================================================
2893  //=======================================================================
2894  template<>
2896  : public virtual QElement<1, 3>
2897  {
2898  public:
2899  FaceGeometry() : QElement<1, 3>() {}
2900  };
2901 
2902 
2906 
2907 
2908  //==========================================================
2910  //==========================================================
2911  template<class TAYLOR_HOOD_ELEMENT>
2913  : public virtual ProjectableElement<TAYLOR_HOOD_ELEMENT>
2914  {
2915  public:
2919 
2920 
2928  {
2929  // Create the vector
2930  Vector<std::pair<Data*, unsigned>> data_values;
2931 
2932  // Velocities dofs
2933  if (fld < this->dim())
2934  {
2935  // Loop over all nodes
2936  unsigned nnod = this->nnode();
2937  for (unsigned j = 0; j < nnod; j++)
2938  {
2939  // Add the data value associated with the velocity components
2940  data_values.push_back(std::make_pair(this->node_pt(j), fld));
2941  }
2942  }
2943  // Pressure
2944  else
2945  {
2946  // Loop over all vertex nodes
2947  unsigned Pconv_size = this->dim() + 1;
2948  for (unsigned j = 0; j < Pconv_size; j++)
2949  {
2950  // Add the data value associated with the pressure components
2951  unsigned vertex_index = this->Pconv[j];
2952  data_values.push_back(
2953  std::make_pair(this->node_pt(vertex_index), fld));
2954  }
2955  }
2956 
2957  // Return the vector
2958  return data_values;
2959  }
2960 
2964  {
2965  return this->dim() + 1;
2966  }
2967 
2972  unsigned nhistory_values_for_projection(const unsigned& fld)
2973  {
2974  if (fld == this->dim())
2975  {
2976  // pressure doesn't have history values
2977  return this->node_pt(0)->ntstorage(); // 1;
2978  }
2979  else
2980  {
2981  return this->node_pt(0)->ntstorage();
2982  }
2983  }
2984 
2988  {
2989  return this->node_pt(0)->position_time_stepper_pt()->ntstorage();
2990  }
2991 
2994  double jacobian_and_shape_of_field(const unsigned& fld,
2995  const Vector<double>& s,
2996  Shape& psi)
2997  {
2998  unsigned n_dim = this->dim();
2999  unsigned n_node = this->nnode();
3000 
3001  if (fld == n_dim)
3002  {
3003  // We are dealing with the pressure
3004  this->pshape_nst(s, psi);
3005 
3006  Shape psif(n_node), testf(n_node);
3007  DShape dpsifdx(n_node, n_dim), dtestfdx(n_node, n_dim);
3008 
3009  // Domain Shape
3010  double J = this->dshape_and_dtest_eulerian_nst(
3011  s, psif, dpsifdx, testf, dtestfdx);
3012  return J;
3013  }
3014  else
3015  {
3016  Shape testf(n_node);
3017  DShape dpsifdx(n_node, n_dim), dtestfdx(n_node, n_dim);
3018 
3019  // Domain Shape
3020  double J =
3021  this->dshape_and_dtest_eulerian_nst(s, psi, dpsifdx, testf, dtestfdx);
3022  return J;
3023  }
3024  }
3025 
3026 
3029  double get_field(const unsigned& t,
3030  const unsigned& fld,
3031  const Vector<double>& s)
3032  {
3033  unsigned n_dim = this->dim();
3034  unsigned n_node = this->nnode();
3035 
3036  // If fld=n_dim, we deal with the pressure
3037  if (fld == n_dim)
3038  {
3039  return this->interpolated_p_nst(t, s);
3040  }
3041  // Velocity
3042  else
3043  {
3044  // Find the index at which the variable is stored
3045  unsigned u_nodal_index = this->u_index_nst(fld);
3046 
3047  // Local shape function
3048  Shape psi(n_node);
3049 
3050  // Find values of shape function
3051  this->shape(s, psi);
3052 
3053  // Initialise value of u
3054  double interpolated_u = 0.0;
3055 
3056  // Sum over the local nodes at that time
3057  for (unsigned l = 0; l < n_node; l++)
3058  {
3059  interpolated_u += this->nodal_value(t, l, u_nodal_index) * psi[l];
3060  }
3061  return interpolated_u;
3062  }
3063  }
3064 
3065 
3067  unsigned nvalue_of_field(const unsigned& fld)
3068  {
3069  if (fld == this->dim())
3070  {
3071  return this->npres_nst();
3072  }
3073  else
3074  {
3075  return this->nnode();
3076  }
3077  }
3078 
3079 
3081  int local_equation(const unsigned& fld, const unsigned& j)
3082  {
3083  if (fld == this->dim())
3084  {
3085  return this->p_local_eqn(j);
3086  }
3087  else
3088  {
3089  const unsigned u_nodal_index = this->u_index_nst(fld);
3090  return this->nodal_local_eqn(j, u_nodal_index);
3091  }
3092  }
3093  };
3094 
3095 
3096  //=======================================================================
3099  //=======================================================================
3100  template<class ELEMENT>
3102  : public virtual FaceGeometry<ELEMENT>
3103  {
3104  public:
3105  FaceGeometry() : FaceGeometry<ELEMENT>() {}
3106  };
3107 
3108 
3109  //=======================================================================
3112  //=======================================================================
3113  template<class ELEMENT>
3115  : public virtual FaceGeometry<FaceGeometry<ELEMENT>>
3116  {
3117  public:
3119  };
3120 
3121 
3122  //==========================================================
3124  //==========================================================
3125  template<class CROUZEIX_RAVIART_ELEMENT>
3127  : public virtual ProjectableElement<CROUZEIX_RAVIART_ELEMENT>
3128  {
3129  public:
3133 
3141  {
3142  // Create the vector
3143  Vector<std::pair<Data*, unsigned>> data_values;
3144 
3145  // Velocities dofs
3146  if (fld < this->dim())
3147  {
3148  // Loop over all nodes
3149  const unsigned n_node = this->nnode();
3150  for (unsigned n = 0; n < n_node; n++)
3151  {
3152  // Add the data value associated with the velocity components
3153  data_values.push_back(std::make_pair(this->node_pt(n), fld));
3154  }
3155  }
3156  // Pressure
3157  else
3158  {
3159  // Need to push back the internal data
3160  const unsigned n_press = this->npres_nst();
3161  // Loop over all pressure values
3162  for (unsigned j = 0; j < n_press; j++)
3163  {
3164  data_values.push_back(std::make_pair(
3165  this->internal_data_pt(this->P_nst_internal_index), j));
3166  }
3167  }
3168 
3169  // Return the vector
3170  return data_values;
3171  }
3172 
3176  {
3177  return this->dim() + 1;
3178  }
3179 
3184  unsigned nhistory_values_for_projection(const unsigned& fld)
3185  {
3186  if (fld == this->dim())
3187  {
3188  // pressure doesn't have history values
3189  return 1;
3190  }
3191  else
3192  {
3193  return this->node_pt(0)->ntstorage();
3194  }
3195  }
3196 
3200  {
3201  return this->node_pt(0)->position_time_stepper_pt()->ntstorage();
3202  }
3203 
3206  double jacobian_and_shape_of_field(const unsigned& fld,
3207  const Vector<double>& s,
3208  Shape& psi)
3209  {
3210  unsigned n_dim = this->dim();
3211  unsigned n_node = this->nnode();
3212 
3213  if (fld == n_dim)
3214  {
3215  // We are dealing with the pressure
3216  this->pshape_nst(s, psi);
3217 
3218  Shape psif(n_node), testf(n_node);
3219  DShape dpsifdx(n_node, n_dim), dtestfdx(n_node, n_dim);
3220 
3221  // Domain Shape
3222  double J = this->dshape_and_dtest_eulerian_nst(
3223  s, psif, dpsifdx, testf, dtestfdx);
3224  return J;
3225  }
3226  else
3227  {
3228  Shape testf(n_node);
3229  DShape dpsifdx(n_node, n_dim), dtestfdx(n_node, n_dim);
3230 
3231  // Domain Shape
3232  double J =
3233  this->dshape_and_dtest_eulerian_nst(s, psi, dpsifdx, testf, dtestfdx);
3234  return J;
3235  }
3236  }
3237 
3238 
3241  double get_field(const unsigned& t,
3242  const unsigned& fld,
3243  const Vector<double>& s)
3244  {
3245  unsigned n_dim = this->dim();
3246 
3247  // If fld=n_dim, we deal with the pressure
3248  if (fld == n_dim)
3249  {
3250  return this->interpolated_p_nst(s);
3251  }
3252  // Velocity
3253  else
3254  {
3255  return this->interpolated_u_nst(t, s, fld);
3256  }
3257  }
3258 
3259 
3261  unsigned nvalue_of_field(const unsigned& fld)
3262  {
3263  if (fld == this->dim())
3264  {
3265  return this->npres_nst();
3266  }
3267  else
3268  {
3269  return this->nnode();
3270  }
3271  }
3272 
3273 
3275  int local_equation(const unsigned& fld, const unsigned& j)
3276  {
3277  if (fld == this->dim())
3278  {
3279  return this->p_local_eqn(j);
3280  }
3281  else
3282  {
3283  const unsigned u_nodal_index = this->u_index_nst(fld);
3284  return this->nodal_local_eqn(j, u_nodal_index);
3285  }
3286  }
3287  };
3288 
3289 
3290  //=======================================================================
3293  //=======================================================================
3294  template<class ELEMENT>
3296  : public virtual FaceGeometry<ELEMENT>
3297  {
3298  public:
3299  FaceGeometry() : FaceGeometry<ELEMENT>() {}
3300  };
3301 
3302 
3303  //=======================================================================
3306  //=======================================================================
3307  template<class ELEMENT>
3309  : public virtual FaceGeometry<FaceGeometry<ELEMENT>>
3310  {
3311  public:
3313  };
3314 
3315 
3316 } // namespace oomph
3317 
3318 #endif
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
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
TimeStepper *& time_stepper_pt()
Return the pointer to the timestepper.
Definition: nodes.h:238
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
double value(const unsigned &i) const
Definition: nodes.h:293
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: navier_stokes_elements.h:2279
FaceGeometry()
Definition: navier_stokes_elements.h:2291
FaceGeometry()
Definition: navier_stokes_elements.h:2887
FaceGeometry()
Definition: navier_stokes_elements.h:2899
FaceGeometry()
Definition: navier_stokes_elements.h:3299
FaceGeometry()
Definition: navier_stokes_elements.h:3105
FaceGeometry()
Definition: navier_stokes_elements.h:2258
FaceGeometry()
Definition: navier_stokes_elements.h:2268
FaceGeometry()
Definition: navier_stokes_elements.h:2865
FaceGeometry()
Definition: navier_stokes_elements.h:2875
Definition: elements.h:4998
Definition: elements.h:1313
virtual unsigned nplot_points_paraview(const unsigned &nplot) const
Definition: elements.h:2862
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: navier_stokes_elements.h:53
FpPressureAdvDiffRobinBCElementBase()
Constructor.
Definition: navier_stokes_elements.h:56
virtual ~FpPressureAdvDiffRobinBCElementBase()
Empty virtual destructor.
Definition: navier_stokes_elements.h:59
virtual void fill_in_generic_residual_contribution_fp_press_adv_diff_robin_bc(Vector< double > &residuals, DenseMatrix< double > &jacobian, unsigned flag)=0
Definition: navier_stokes_elements.h:89
void output(std::ostream &outfile)
Overload the output function.
Definition: navier_stokes_elements.h:167
virtual void fill_in_generic_residual_contribution_fp_press_adv_diff_robin_bc(Vector< double > &residuals, DenseMatrix< double > &jacobian, unsigned flag)
Definition: navier_stokes_elements.h:190
FpPressureAdvDiffRobinBCElement(FiniteElement *const &element_pt, const int &face_index, const bool &called_from_refineable_constructor=false)
Definition: navier_stokes_elements.h:94
void fill_in_contribution_to_jacobian(Vector< double > &residuals, DenseMatrix< double > &jacobian)
This function returns the residuals and the jacobian.
Definition: navier_stokes_elements.h:154
void fill_in_contribution_to_residuals(Vector< double > &residuals)
This function returns just the residuals.
Definition: navier_stokes_elements.h:142
void output(std::ostream &outfile, const unsigned &nplot)
Output function: x,y,[z],u,v,[w],p in tecplot format.
Definition: navier_stokes_elements.h:173
~FpPressureAdvDiffRobinBCElement()
Empty destructor.
Definition: navier_stokes_elements.h:132
static double Default_fd_jacobian_step
Definition: elements.h:1198
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
int internal_local_eqn(const unsigned &i, const unsigned &j) const
Definition: elements.h:267
static DenseMatrix< double > Dummy_matrix
Definition: elements.h:227
unsigned add_internal_data(Data *const &data_pt, const bool &fd=true)
Definition: elements.cc:62
TimeStepper *& time_stepper_pt()
Definition: geom_objects.h:192
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: navier_stokes_elements.h:395
unsigned nscalar_paraview() const
Definition: navier_stokes_elements.h:1014
void(* NavierStokesBodyForceFctPt)(const double &time, const Vector< double > &x, Vector< double > &body_force)
Definition: navier_stokes_elements.h:399
double * Viscosity_Ratio_pt
Definition: navier_stokes_elements.h:436
void disable_ALE()
Definition: navier_stokes_elements.h:909
virtual double p_nst(const unsigned &t, const unsigned &n_p) const =0
Pressure at local pressure "node" n_p at time level t.
double interpolated_u_nst(const unsigned &t, const Vector< double > &s, const unsigned &i) const
Definition: navier_stokes_elements.h:1555
void get_vorticity(const Vector< double > &s, Vector< double > &vorticity) const
Compute the vorticity vector at local coordinate s.
NavierStokesSourceFctPt Source_fct_pt
Pointer to volumetric source function.
Definition: navier_stokes_elements.h:461
double kin_energy() const
Get integral of kinetic energy over element.
Definition: navier_stokes_elements.cc:1416
virtual unsigned u_index_nst(const unsigned &i) const
Definition: navier_stokes_elements.h:866
virtual void build_fp_press_adv_diff_robin_bc_element(const unsigned &face_index)=0
double * Re_pt
Pointer to global Reynolds number.
Definition: navier_stokes_elements.h:445
double(* NavierStokesSourceFctPt)(const double &time, const Vector< double > &x)
Definition: navier_stokes_elements.h:405
NavierStokesSourceFctPt & source_fct_pt()
Access function for the source-function pointer.
Definition: navier_stokes_elements.h:789
static int Pressure_not_stored_at_node
Definition: navier_stokes_elements.h:418
double *& density_ratio_pt()
Pointer to Density ratio.
Definition: navier_stokes_elements.h:747
NavierStokesBodyForceFctPt body_force_fct_pt() const
Access function for the body-force pointer. Const version.
Definition: navier_stokes_elements.h:783
void fill_in_contribution_to_dresiduals_dparameter(double *const &parameter_pt, Vector< double > &dres_dparam)
Compute the element's residual Vector.
Definition: navier_stokes_elements.h:1294
void fill_in_contribution_to_hessian_vector_products(Vector< double > const &Y, DenseMatrix< double > const &C, DenseMatrix< double > &product)
Definition: navier_stokes_elements.cc:2105
void get_pressure_and_velocity_mass_matrix_diagonal(Vector< double > &press_mass_diag, Vector< double > &veloc_mass_diag, const unsigned &which_one=0)
Definition: navier_stokes_elements.cc:71
void get_vorticity(const Vector< double > &s, double &vorticity) const
Compute the scalar vorticity at local coordinate s (2D)
virtual double dpshape_and_dptest_eulerian_nst(const Vector< double > &s, Shape &ppsi, DShape &dppsidx, Shape &ptest, DShape &dptestdx) const =0
void fill_in_contribution_to_residuals(Vector< double > &residuals)
Compute the element's residual Vector.
Definition: navier_stokes_elements.h:1260
void interpolated_u_nst(const Vector< double > &s, Vector< double > &veloc) const
Compute vector of FE interpolated velocity u at local coordinate s.
Definition: navier_stokes_elements.h:1505
virtual int p_nodal_index_nst() const
Definition: navier_stokes_elements.h:936
void compute_error(std::ostream &outfile, FiniteElement::UnsteadyExactSolutionFctPt exact_soln_pt, const double &time, double &error, double &norm)
Definition: navier_stokes_elements.cc:289
double interpolated_dudx_nst(const Vector< double > &s, const unsigned &i, const unsigned &j) const
Definition: navier_stokes_elements.h:1684
void fill_in_pressure_advection_diffusion_jacobian(Vector< double > &residuals, DenseMatrix< double > &jacobian)
Definition: navier_stokes_elements.h:1348
virtual double dshape_and_dtest_eulerian_at_knot_nst(const unsigned &ipt, Shape &psi, DShape &dpsidx, Shape &test, DShape &dtestdx) const =0
virtual void pshape_nst(const Vector< double > &s, Shape &psi) const =0
Compute the pressure shape functions at local coordinate s.
virtual unsigned npres_nst() const =0
Function to return number of pressure degrees of freedom.
NavierStokesPressureAdvDiffSourceFctPt Press_adv_diff_source_fct_pt
Definition: navier_stokes_elements.h:465
virtual void fill_in_generic_pressure_advection_diffusion_contribution_nst(Vector< double > &residuals, DenseMatrix< double > &jacobian, unsigned flag)
Definition: navier_stokes_elements.cc:1605
void fill_in_contribution_to_jacobian_and_mass_matrix(Vector< double > &residuals, DenseMatrix< double > &jacobian, DenseMatrix< double > &mass_matrix)
Definition: navier_stokes_elements.h:1283
virtual void pshape_nst(const Vector< double > &s, Shape &psi, Shape &test) const =0
virtual void get_dresidual_dnodal_coordinates(RankThreeTensor< double > &dresidual_dnodal_coordinates)
Definition: navier_stokes_elements.cc:2123
virtual void get_source_gradient_nst(const double &time, const unsigned &ipt, const Vector< double > &x, Vector< double > &gradient)
Definition: navier_stokes_elements.h:607
void scalar_value_paraview(std::ofstream &file_out, const unsigned &i, const unsigned &nplot) const
Definition: navier_stokes_elements.h:1021
double interpolated_u_nst(const Vector< double > &s, const unsigned &i) const
Return FE interpolated velocity u[i] at local coordinate s.
Definition: navier_stokes_elements.h:1530
double *& viscosity_ratio_pt()
Pointer to Viscosity Ratio.
Definition: navier_stokes_elements.h:734
double u_nst(const unsigned &n, const unsigned &i) const
Definition: navier_stokes_elements.h:848
NavierStokesPressureAdvDiffSourceFctPt & source_fct_for_pressure_adv_diff()
Definition: navier_stokes_elements.h:802
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: navier_stokes_elements.h:1067
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)
Definition: navier_stokes_elements.cc:1185
NavierStokesPressureAdvDiffSourceFctPt source_fct_for_pressure_adv_diff() const
Definition: navier_stokes_elements.h:809
double d_kin_energy_dt() const
Get integral of time derivative of kinetic energy over element.
Definition: navier_stokes_elements.cc:1460
const double & re_st() const
Product of Reynolds and Strouhal number (=Womersley number)
Definition: navier_stokes_elements.h:709
virtual void get_body_force_nst(const double &time, const unsigned &ipt, const Vector< double > &s, const Vector< double > &x, Vector< double > &result)
Definition: navier_stokes_elements.h:517
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: navier_stokes_elements.h:1661
void enable_ALE()
Definition: navier_stokes_elements.h:918
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: navier_stokes_elements.h:544
void compute_norm(double &norm)
Compute norm of solution: square of the L2 norm of the velocities.
Definition: navier_stokes_elements.cc:186
double *& re_st_pt()
Pointer to product of Reynolds and Strouhal number (=Womersley number)
Definition: navier_stokes_elements.h:721
void fill_in_contribution_to_djacobian_dparameter(double *const &parameter_pt, Vector< double > &dres_dparam, DenseMatrix< double > &djac_dparam)
Definition: navier_stokes_elements.h:1309
NavierStokesBodyForceFctPt & body_force_fct_pt()
Access function for the body-force pointer.
Definition: navier_stokes_elements.h:777
const double & re_invfr() const
Global inverse Froude number.
Definition: navier_stokes_elements.h:753
int & pinned_fp_pressure_eqn()
Definition: navier_stokes_elements.h:817
int Pinned_fp_pressure_eqn
Definition: navier_stokes_elements.h:479
const double & viscosity_ratio() const
Definition: navier_stokes_elements.h:728
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.
NavierStokesSourceFctPt source_fct_pt() const
Access function for the source-function pointer. Const version.
Definition: navier_stokes_elements.h:795
virtual void dinterpolated_u_nst_ddata(const Vector< double > &s, const unsigned &i, Vector< double > &du_ddata, Vector< unsigned > &global_eqn_number)
Definition: navier_stokes_elements.h:1587
Vector< double > * G_pt
Pointer to global gravity Vector.
Definition: navier_stokes_elements.h:455
static double Default_Physical_Constant_Value
Navier–Stokes equations static data.
Definition: navier_stokes_elements.h:422
void output_pressure_advection_diffusion_robin_elements(std::ostream &outfile)
Definition: navier_stokes_elements.h:1449
void full_output(std::ostream &outfile)
Definition: navier_stokes_elements.h:1180
void delete_pressure_advection_diffusion_robin_elements()
Definition: navier_stokes_elements.h:1486
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, unsigned flag)
Definition: navier_stokes_elements.cc:2087
virtual double interpolated_p_nst(const Vector< double > &s) const
Return FE interpolated pressure at local coordinate s.
Definition: navier_stokes_elements.h:1639
double * ReInvFr_pt
Definition: navier_stokes_elements.h:452
Vector< double > *& g_pt()
Pointer to Vector of gravitational components.
Definition: navier_stokes_elements.h:771
void output_veloc(std::ostream &outfile, const unsigned &nplot, const unsigned &t)
Definition: navier_stokes_elements.cc:687
static double Default_Physical_Ratio_Value
Navier–Stokes equations static data.
Definition: navier_stokes_elements.h:426
void fill_in_contribution_to_jacobian(Vector< double > &residuals, DenseMatrix< double > &jacobian)
Definition: navier_stokes_elements.h:1273
void fill_in_pressure_advection_diffusion_residuals(Vector< double > &residuals)
Definition: navier_stokes_elements.h:1339
void get_traction(const Vector< double > &s, const Vector< double > &N, Vector< double > &traction)
Definition: navier_stokes_elements.cc:1098
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: navier_stokes_elements.h:1357
virtual double get_source_nst(const double &time, const unsigned &ipt, const Vector< double > &x)
Definition: navier_stokes_elements.h:585
double *& re_invfr_pt()
Pointer to global inverse Froude number.
Definition: navier_stokes_elements.h:759
double u_nst(const unsigned &t, const unsigned &n, const unsigned &i) const
Definition: navier_stokes_elements.h:855
const double & re() const
Reynolds number.
Definition: navier_stokes_elements.h:703
virtual void fill_in_generic_residual_contribution_nst(Vector< double > &residuals, DenseMatrix< double > &jacobian, DenseMatrix< double > &mass_matrix, unsigned flag)
Definition: navier_stokes_elements.cc:1774
void output(FILE *file_pt)
Definition: navier_stokes_elements.h:1167
double * Density_Ratio_pt
Definition: navier_stokes_elements.h:440
double *& re_pt()
Pointer to Reynolds number.
Definition: navier_stokes_elements.h:715
double pressure_integral() const
Integral of pressure over element.
Definition: navier_stokes_elements.cc:1558
static Vector< double > Default_Gravity_vector
Static default value for the gravity vector.
Definition: navier_stokes_elements.h:429
unsigned n_u_nst() const
Definition: navier_stokes_elements.h:873
double du_dt_nst(const unsigned &n, const unsigned &i) const
Definition: navier_stokes_elements.h:880
NavierStokesBodyForceFctPt Body_force_fct_pt
Pointer to body force function.
Definition: navier_stokes_elements.h:458
virtual double p_nst(const unsigned &n_p) const =0
const double & density_ratio() const
Definition: navier_stokes_elements.h:741
void output(std::ostream &outfile)
Definition: navier_stokes_elements.h:1155
void output_vorticity(std::ostream &outfile, const unsigned &nplot)
Definition: navier_stokes_elements.cc:978
double * ReSt_pt
Pointer to global Reynolds number x Strouhal number (=Womersley)
Definition: navier_stokes_elements.h:448
double(* NavierStokesPressureAdvDiffSourceFctPt)(const Vector< double > &x)
Definition: navier_stokes_elements.h:412
bool ALE_is_disabled
Definition: navier_stokes_elements.h:470
NavierStokesEquations()
Definition: navier_stokes_elements.h:677
virtual double dshape_and_dtest_eulerian_nst(const Vector< double > &s, Shape &psi, DShape &dpsidx, Shape &test, DShape &dtestdx) const =0
const Vector< double > & g() const
Vector of gravitational components.
Definition: navier_stokes_elements.h:765
void get_load(const Vector< double > &s, const Vector< double > &N, Vector< double > &load)
Definition: navier_stokes_elements.h:992
double dissipation() const
Return integral of dissipation over element.
Definition: navier_stokes_elements.cc:1046
Vector< FpPressureAdvDiffRobinBCElementBase * > Pressure_advection_diffusion_robin_element_pt
Definition: navier_stokes_elements.h:475
std::string scalar_name_paraview(const unsigned &i) const
Definition: navier_stokes_elements.h:1127
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
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: navier_stokes_elements.h:1325
void output_fct(std::ostream &outfile, const unsigned &nplot, FiniteElement::SteadyExactSolutionFctPt exact_soln_pt)
Definition: navier_stokes_elements.cc:573
void point_output_data(const Vector< double > &s, Vector< double > &data)
Definition: navier_stokes_elements.h:1717
static Vector< double > Gamma
Vector to decide whether the stress-divergence form is used or not.
Definition: navier_stokes_elements.h:698
Definition: nodes.h:906
Definition: oomph_definitions.h:222
Definition: elements.h:3439
Crouzeix Raviart upgraded to become projectable.
Definition: navier_stokes_elements.h:3128
Vector< std::pair< Data *, unsigned > > data_values_of_field(const unsigned &fld)
Definition: navier_stokes_elements.h:3140
int local_equation(const unsigned &fld, const unsigned &j)
Return local equation number of value j in field fld.
Definition: navier_stokes_elements.h:3275
ProjectableCrouzeixRaviartElement()
Definition: navier_stokes_elements.h:3132
double get_field(const unsigned &t, const unsigned &fld, const Vector< double > &s)
Definition: navier_stokes_elements.h:3241
unsigned nfields_for_projection()
Definition: navier_stokes_elements.h:3175
double jacobian_and_shape_of_field(const unsigned &fld, const Vector< double > &s, Shape &psi)
Definition: navier_stokes_elements.h:3206
unsigned nhistory_values_for_coordinate_projection()
Definition: navier_stokes_elements.h:3199
unsigned nhistory_values_for_projection(const unsigned &fld)
Definition: navier_stokes_elements.h:3184
unsigned nvalue_of_field(const unsigned &fld)
Return number of values in field fld.
Definition: navier_stokes_elements.h:3261
Definition: projection.h:183
Taylor Hood upgraded to become projectable.
Definition: navier_stokes_elements.h:2914
Vector< std::pair< Data *, unsigned > > data_values_of_field(const unsigned &fld)
Definition: navier_stokes_elements.h:2927
double jacobian_and_shape_of_field(const unsigned &fld, const Vector< double > &s, Shape &psi)
Definition: navier_stokes_elements.h:2994
unsigned nhistory_values_for_projection(const unsigned &fld)
Definition: navier_stokes_elements.h:2972
unsigned nhistory_values_for_coordinate_projection()
Definition: navier_stokes_elements.h:2987
unsigned nfields_for_projection()
Definition: navier_stokes_elements.h:2963
int local_equation(const unsigned &fld, const unsigned &j)
Return local equation number of value j in field fld.
Definition: navier_stokes_elements.h:3081
unsigned nvalue_of_field(const unsigned &fld)
Return number of values in field fld.
Definition: navier_stokes_elements.h:3067
ProjectableTaylorHoodElement()
Definition: navier_stokes_elements.h:2918
double get_field(const unsigned &t, const unsigned &fld, const Vector< double > &s)
Definition: navier_stokes_elements.h:3029
Definition: navier_stokes_elements.h:1749
virtual unsigned required_nvalue(const unsigned &n) const
Number of values (pinned or dofs) required at local node n.
Definition: navier_stokes_elements.cc:2581
unsigned npres_nst() const
Return number of pressure values.
Definition: navier_stokes_elements.h:1830
void output(std::ostream &outfile)
Redirect output to NavierStokesEquations output.
Definition: navier_stokes_elements.h:1891
void pshape_nst(const Vector< double > &s, Shape &psi) const
Pressure shape functions at local coordinate s.
int p_local_eqn(const unsigned &n) const
Return the local equation numbers for the pressure values.
Definition: navier_stokes_elements.h:1845
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, Shape &test, DShape &dtestdx) const
Definition: navier_stokes_elements.h:1981
double p_nst(const unsigned &i) const
Definition: navier_stokes_elements.h:1816
unsigned P_nst_internal_index
Definition: navier_stokes_elements.h:1757
void identify_load_data(std::set< std::pair< Data *, unsigned >> &paired_load_data)
Definition: navier_stokes_elements.cc:2598
void build_fp_press_adv_diff_robin_bc_element(const unsigned &face_index)
Definition: navier_stokes_elements.h:1861
void output(std::ostream &outfile, const unsigned &nplot)
Redirect output to NavierStokesEquations output.
Definition: navier_stokes_elements.h:1897
static const unsigned Initial_Nvalue[]
Static array of ints to hold required number of variables at nodes.
Definition: navier_stokes_elements.h:1752
void output(FILE *file_pt, const unsigned &nplot)
Redirect output to NavierStokesEquations output.
Definition: navier_stokes_elements.h:1910
QCrouzeixRaviartElement()
Constructor, there are DIM+1 internal values (for the pressure)
Definition: navier_stokes_elements.h:1794
void full_output(std::ostream &outfile)
Definition: navier_stokes_elements.h:1919
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
void full_output(std::ostream &outfile, const unsigned &nplot)
Definition: navier_stokes_elements.h:1927
void identify_pressure_data(std::set< std::pair< Data *, unsigned >> &paired_pressure_data)
Definition: navier_stokes_elements.cc:2635
void get_dof_numbers_for_unknowns(std::list< std::pair< unsigned long, unsigned >> &dof_lookup_list) const
Definition: navier_stokes_elements.cc:2662
double p_nst(const unsigned &t, const unsigned &i) const
Definition: navier_stokes_elements.h:1824
void output(FILE *file_pt)
Redirect output to NavierStokesEquations output.
Definition: navier_stokes_elements.h:1904
unsigned ndof_types() const
Definition: navier_stokes_elements.h:1935
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: navier_stokes_elements.h:1851
double dshape_and_dtest_eulerian_nst(const Vector< double > &s, Shape &psi, DShape &dpsidx, Shape &test, DShape &dtestdx) const
Definition: navier_stokes_elements.h:1958
Definition: Qelements.h:459
Definition: navier_stokes_elements.h:2308
void output(FILE *file_pt, const unsigned &nplot)
Redirect output to NavierStokesEquations output.
Definition: navier_stokes_elements.h:2484
int p_local_eqn(const unsigned &n) const
Return the local equation numbers for the pressure values.
Definition: navier_stokes_elements.h:2376
unsigned ndof_types() const
Definition: navier_stokes_elements.h:2492
double dshape_and_dtest_eulerian_at_knot_nst(const unsigned &ipt, Shape &psi, DShape &dpsidx, Shape &test, DShape &dtestdx) const
Definition: navier_stokes_elements.h:2540
double dpshape_and_dptest_eulerian_nst(const Vector< double > &s, Shape &ppsi, DShape &dppsidx, Shape &ptest, DShape &dptestdx) const
double dshape_and_dtest_eulerian_nst(const Vector< double > &s, Shape &psi, DShape &dpsidx, Shape &test, DShape &dtestdx) const
Definition: navier_stokes_elements.h:2515
double p_nst(const unsigned &n_p) const
Definition: navier_stokes_elements.h:2383
void pshape_nst(const Vector< double > &s, Shape &psi, Shape &test) const
Pressure shape and test functions at local coordinte s.
Definition: navier_stokes_elements.h:2847
void identify_pressure_data(std::set< std::pair< Data *, unsigned >> &paired_pressure_data)
Definition: navier_stokes_elements.cc:2798
void output(std::ostream &outfile)
Redirect output to NavierStokesEquations output.
Definition: navier_stokes_elements.h:2466
void identify_load_data(std::set< std::pair< Data *, unsigned >> &paired_load_data)
Definition: navier_stokes_elements.cc:2762
void output(FILE *file_pt)
Redirect output to NavierStokesEquations output.
Definition: navier_stokes_elements.h:2478
void pshape_nst(const Vector< double > &s, Shape &psi) const
Pressure shape functions at local coordinate s.
virtual unsigned required_nvalue(const unsigned &n) const
Definition: navier_stokes_elements.h:2355
virtual int p_nodal_index_nst() const
Set the value at which the pressure is stored in the nodes.
Definition: navier_stokes_elements.h:2370
static const unsigned Pconv[]
Definition: navier_stokes_elements.h:2316
double p_nst(const unsigned &t, const unsigned &n_p) const
Definition: navier_stokes_elements.h:2390
void output(std::ostream &outfile, const unsigned &nplot)
Redirect output to NavierStokesEquations output.
Definition: navier_stokes_elements.h:2472
void get_dof_numbers_for_unknowns(std::list< std::pair< unsigned long, unsigned >> &dof_lookup_list) const
Definition: navier_stokes_elements.cc:2825
void build_fp_press_adv_diff_robin_bc_element(const unsigned &face_index)
Definition: navier_stokes_elements.h:2434
unsigned npres_nst() const
Return number of pressure values.
Definition: navier_stokes_elements.h:2405
QTaylorHoodElement()
Constructor, no internal data points.
Definition: navier_stokes_elements.h:2351
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: navier_stokes_elements.h:2423
static const unsigned Initial_Nvalue[]
Static array of ints to hold number of variables at node.
Definition: navier_stokes_elements.h:2311
bool is_pressure_node(const unsigned &n) const
Deduce whether or not the provided node is a pressure node.
Definition: navier_stokes_elements.h:2412
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
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: navier_stokes_elements.h:308
TemplateFreeNavierStokesEquationsBase()
Constructor (empty)
Definition: navier_stokes_elements.h:311
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 ~TemplateFreeNavierStokesEquationsBase()
Virtual destructor (empty)
Definition: navier_stokes_elements.h:314
virtual int p_local_eqn(const unsigned &n) const =0
virtual void fill_in_pressure_advection_diffusion_jacobian(Vector< double > &residuals, DenseMatrix< double > &jacobian)=0
virtual void build_fp_press_adv_diff_robin_bc_element(const unsigned &face_index)=0
virtual void delete_pressure_advection_diffusion_robin_elements()=0
virtual void fill_in_pressure_advection_diffusion_residuals(Vector< double > &residuals)=0
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
Definition: timesteppers.h:231
unsigned ntstorage() const
Definition: timesteppers.h:601
virtual double weight(const unsigned &i, const unsigned &j) const
Access function for j-th weight for the i-th derivative.
Definition: timesteppers.h:594
bool is_steady() const
Definition: timesteppers.h:389
@ 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
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 shape(const double &s, double *Psi)
Definition: shape.h:564
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< 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
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