linearised_navier_stokes_elements.cc
Go to the documentation of this file.
1 //LIC// ====================================================================
2 //LIC// This file forms part of oomph-lib, the object-oriented,
3 //LIC// multi-physics finite-element library, available
4 //LIC// at http://www.oomph-lib.org.
5 //LIC//
6 //LIC// Version 1.0; svn revision $LastChangedRevision: 1097 $
7 //LIC//
8 //LIC// $LastChangedDate: 2015-12-17 11:53:17 +0000 (Thu, 17 Dec 2015) $
9 //LIC//
10 //LIC// Copyright (C) 2006-2016 Matthias Heil and Andrew Hazel
11 //LIC//
12 //LIC// This library is free software; you can redistribute it and/or
13 //LIC// modify it under the terms of the GNU Lesser General Public
14 //LIC// License as published by the Free Software Foundation; either
15 //LIC// version 2.1 of the License, or (at your option) any later version.
16 //LIC//
17 //LIC// This library is distributed in the hope that it will be useful,
18 //LIC// but WITHOUT ANY WARRANTY; without even the implied warranty of
19 //LIC// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
20 //LIC// Lesser General Public License for more details.
21 //LIC//
22 //LIC// You should have received a copy of the GNU Lesser General Public
23 //LIC// License along with this library; if not, write to the Free Software
24 //LIC// Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA
25 //LIC// 02110-1301 USA.
26 //LIC//
27 //LIC// The authors may be contacted at oomph-lib@maths.man.ac.uk.
28 //LIC//
29 //LIC//====================================================================
30 // Non-inline functions for linearised axisymmetric Navier-Stokes elements
31 
32 // oomph-lib includes
34 
35 namespace oomph
36 {
37 
38  //=======================================================================
39  /// Linearised axisymmetric Navier--Stokes equations static data
40  //=======================================================================
41 
42  // Use the stress-divergence form by default (Gamma=1)
43  Vector<double> LinearisedNavierStokesEquations::Gamma(2,1.0);
44 
45  // "Magic" number to indicate pressure is not stored at node
46  int LinearisedNavierStokesEquations::
47  Pressure_not_stored_at_node = -100;
48 
49  // Physical constants default to zero
50  double LinearisedNavierStokesEquations::
51  Default_Physical_Constant_Value = 0.0;
52 
53  // Density/viscosity ratios default to one
54  double LinearisedNavierStokesEquations::
55  Default_Physical_Ratio_Value = 1.0;
56 
57 
58 
59  //=======================================================================
60  /// Output function in tecplot format: Velocities only
61  /// r, z, U^C, U^S, V^C, V^S, W^C, W^S
62  /// at specified previous timestep (t=0 present; t>0 previous timestep).
63  /// Specified number of plot points in each coordinate direction.
64  //=======================================================================
66  std::ostream &outfile, const unsigned &nplot, const unsigned &t)
67  {
68  // Determine number of nodes in element
69  const unsigned n_node = nnode();
70 
71  // Provide storage for local shape functions
72  Shape psi(n_node);
73 
74  // Provide storage for vectors of local coordinates and
75  // global coordinates and velocities
76  Vector<double> s(DIM);
78  Vector<double> interpolated_u(2*DIM);
79 
80  // Tecplot header info
81  outfile << tecplot_zone_string(nplot);
82 
83  // Determine number of plot points
84  const unsigned n_plot_points = nplot_points(nplot);
85 
86  // Loop over plot points
87  for(unsigned iplot=0;iplot<n_plot_points;iplot++)
88  {
89  // Get local coordinates of plot point
90  get_s_plot(iplot,nplot,s);
91 
92  // Get shape functions
93  shape(s,psi);
94 
95  // Loop over coordinate directions
96  for(unsigned i=0;i<DIM;i++)
97  {
98  // Initialise global coordinate
99  interpolated_x[i]=0.0;
100 
101  // Loop over the local nodes and sum
102  for(unsigned l=0;l<n_node;l++)
103  {
104  interpolated_x[i] += nodal_position(t,l,i)*psi[l];
105  }
106  }
107 
108  // Loop over the velocity components
109  for(unsigned i=0;i<(2*DIM);i++)
110  {
111  // Get the index at which the velocity is stored
112  const unsigned u_nodal_index = u_index_linearised_nst(i);
113 
114  // Initialise velocity
115  interpolated_u[i]=0.0;
116 
117  // Loop over the local nodes and sum
118  for(unsigned l=0;l<n_node;l++)
119  {
120  interpolated_u[i] += nodal_value(t,l,u_nodal_index)*psi[l];
121  }
122  }
123 
124  // Output global coordinates to file
125  for(unsigned i=0;i<DIM;i++) { outfile << interpolated_x[i] << " "; }
126 
127  // Output velocities to file
128  for(unsigned i=0;i<(2*DIM);i++) { outfile << interpolated_u[i] << " "; }
129 
130  outfile << std::endl;
131  }
132 
133  // Write tecplot footer (e.g. FE connectivity lists)
134  write_tecplot_zone_footer(outfile,nplot);
135 
136  } // End of output_veloc
137 
138 
139 
140  //=======================================================================
141  /// Output function in tecplot format:
142  /// r, z, U^C, U^S, V^C, V^S, W^C, W^S, P^C, P^S
143  /// in tecplot format. Specified number of plot points in each
144  /// coordinate direction.
145  //=======================================================================
147  std::ostream &outfile, const unsigned &nplot)
148  {
149  // Provide storage for vector of local coordinates
150  Vector<double> s(DIM);
151 
152  // Tecplot header info
153  outfile << tecplot_zone_string(nplot);
154 
155  // Determine number of plot points
156  const unsigned n_plot_points = nplot_points(nplot);
157 
158  // Loop over plot points
159  for(unsigned iplot=0;iplot<n_plot_points;iplot++)
160  {
161  // Get local coordinates of plot point
162  get_s_plot(iplot,nplot,s);
163 
164  // Output global coordinates to file
165  for(unsigned i=0;i<DIM;i++) { outfile << interpolated_x(s,i) << " "; }
166 
167  // Output velocities (and normalisation) to file
168  for(unsigned i=0;i<(4*DIM);i++)
169  {
170  outfile << interpolated_u_linearised_nst(s,i) << " ";
171  }
172 
173  // Output pressure to file
174  for(unsigned i=0;i<2;i++)
175  {
176  outfile << interpolated_p_linearised_nst(s,i) << " ";
177  }
178 
179  outfile << std::endl;
180  }
181  outfile << std::endl;
182 
183  // Write tecplot footer (e.g. FE connectivity lists)
184  write_tecplot_zone_footer(outfile,nplot);
185 
186  } // End of output
187 
188 
189 
190 
191  //=======================================================================
192  /// Output function in tecplot format:
193  /// r, z, U^C, U^S, V^C, V^S, W^C, W^S, P^C, P^S
194  /// Specified number of plot points in each coordinate direction.
195  //=======================================================================
197  FILE* file_pt, const unsigned &nplot)
198  {
199  // Provide storage for vector of local coordinates
200  Vector<double> s(2);
201 
202  // Tecplot header info
203  fprintf(file_pt,"%s ",tecplot_zone_string(nplot).c_str());
204 
205  // Determine number of plot points
206  const unsigned n_plot_points = nplot_points(nplot);
207 
208  // Loop over plot points
209  for(unsigned iplot=0;iplot<n_plot_points;iplot++)
210  {
211  // Get local coordinates of plot point
212  get_s_plot(iplot,nplot,s);
213 
214  // Output global coordinates to file
215  for(unsigned i=0;i<2;i++) { fprintf(file_pt,"%g ",interpolated_x(s,i)); }
216 
217  // Output velocities to file
218  for(unsigned i=0;i<(2*DIM);i++)
219  {
220  fprintf(file_pt,"%g ",interpolated_u_linearised_nst(s,i));
221  }
222 
223  // Output pressure to file
224  for(unsigned i=0;i<2;i++)
225  {
226  fprintf(file_pt,"%g ",interpolated_p_linearised_nst(s,i));
227  }
228 
229  fprintf(file_pt,"\n");
230  }
231 
232  fprintf(file_pt,"\n");
233 
234  // Write tecplot footer (e.g. FE connectivity lists)
235  write_tecplot_zone_footer(file_pt,nplot);
236 
237  } // End of output
238 
239 
240 
241  //=======================================================================
242  /// Get strain-rate tensor: \f$ e_{ij} \f$ where
243  /// \f$ i,j = r,z,\theta \f$ (in that order). We evaluate this tensor
244  /// at a value of theta such that the product of theta and the azimuthal
245  /// mode number (k) gives \f$ \pi/4 \f$. Therefore
246  /// \f$ \cos(k \theta) = \sin(k \theta) = 1/\sqrt{2} \f$.
247  //=======================================================================
250  const unsigned &real) const
251  {
252 #ifdef PARANOID
253  if ((strainrate.ncol()!=DIM)||(strainrate.nrow()!=DIM))
254  {
255  std::ostringstream error_message;
256  error_message << "The strain rate has incorrect dimensions "
257  << strainrate.ncol() << " x "
258  << strainrate.nrow() << " Not " << DIM << std::endl;
259 
260  throw OomphLibError(error_message.str(),
261  OOMPH_CURRENT_FUNCTION,
262  OOMPH_EXCEPTION_LOCATION);
263  }
264 #endif
265 
266  //The question is what to do about the real and imaginary parts
267  //The answer is that we know that the "real" velocity is
268  //U_r cos(omega t) - U_i sin(omega t) and we can choose omega t
269  //to be 7pi/4 so that cos = 1/sqrt(2) and sin = -1/sqrt(2)
270  //to get equal contributions
271  double cosomegat = 1.0/sqrt(2.0);
272  double sinomegat = cosomegat;
273 
274  //Find out how many nodes there are in the element
275  unsigned n_node = nnode();
276 
277  //Set up memory for the shape and test functions
278  Shape psif(n_node);
279  DShape dpsifdx(n_node,DIM);
280 
281  //Call the derivatives of the shape functions
282  dshape_eulerian(s,psif,dpsifdx);
283 
284  // Velocity gradient matrix
286  // Initialise to zero
287  for(unsigned i=0;i<DIM;++i)
288  {
289  dudx[i].resize(DIM);
290  for(unsigned j=0;j<DIM;++j)
291  {
292  dudx[i][j].real(0.0);
293  dudx[i][j].imag(0.0);
294  }
295  }
296 
297  // Get the nodal indices at which the velocity is stored
298  unsigned n_veloc = 2*DIM;
299  unsigned u_nodal_index[n_veloc];
300  for(unsigned i=0;i<n_veloc;++i)
301  {
302  u_nodal_index[i] = u_index_linearised_nst(i);
303  }
304 
305  // Loop over the element's nodes
306  for(unsigned l=0;l<n_node;l++)
307  {
308  // Loop over the DIM complex velocity components
309  for(unsigned i=0;i<DIM;i++)
310  {
311  // Get the value
312  const std::complex<double>
313  u_value(this->raw_nodal_value(l,u_nodal_index[2*i+0]),
314  this->raw_nodal_value(l,u_nodal_index[2*i+1]));
315 
316  // Loop over two coordinate directions (for derivatives)
317  for(unsigned j=0;j<DIM;j++)
318  {
319  dudx[i][j] += u_value*dpsifdx(l,j);
320  }
321  }
322  }
323 
324  //Take the real part of the velocity gradient matrix
325  DenseMatrix<double> real_dudx(DIM);
326  if(real==0) {cosomegat = 1.0; sinomegat = 0.0;}
327  else {cosomegat = 0.0; sinomegat = 1.0;}
328 
329  for(unsigned i=0;i<DIM;++i)
330  {
331  for(unsigned j=0;j<DIM;++j)
332  {
333  real_dudx(i,j) =
334  dudx[i][j].real()*cosomegat + dudx[i][j].imag()*sinomegat;
335  }
336  }
337 
338 
339 
340  //Now set the strain rate
341  //Loop over veclocity components
342  for(unsigned i=0;i<DIM;i++)
343  {
344  //Loop over derivative directions
345  for(unsigned j=0;j<DIM;j++)
346  {
347  strainrate(i,j)=0.5*(real_dudx(i,j)+real_dudx(j,i));
348  }
349  }
350 
351  } // End of strain_rate
352 
353 
354 
355  //=======================================================================
356  /// Compute the residuals for the linearised axisymmetric Navier--Stokes
357  /// equations; flag=1(or 0): do (or don't) compute the Jacobian as well.
358  //=======================================================================
361  Vector<double> &residuals,
362  DenseMatrix<double> &jacobian,
363  DenseMatrix<double> &mass_matrix,
364  unsigned flag)
365  {
366  // Get the time from the first node in the element
367  const double time = this->node_pt(0)->time_stepper_pt()->time();
368 
369  // Determine number of nodes in the element
370  const unsigned n_node = nnode();
371 
372  // Determine how many pressure values there are associated with
373  // a single pressure component
374  const unsigned n_pres = npres_linearised_nst();
375 
376  const unsigned n_veloc = 4*DIM;
377 
378  // Get the nodal indices at which the velocity is stored
379  unsigned u_nodal_index[n_veloc];
380  for(unsigned i=0;i<n_veloc;++i)
381  {
382  u_nodal_index[i] = u_index_linearised_nst(i);
383  }
384 
385  // Set up memory for the fluid shape and test functions
386  Shape psif(n_node), testf(n_node);
387  DShape dpsifdx(n_node,DIM), dtestfdx(n_node,DIM);
388 
389  // Set up memory for the pressure shape and test functions
390  Shape psip(n_pres), testp(n_pres);
391 
392  // Determine number of integration points
393  const unsigned n_intpt = integral_pt()->nweight();
394 
395  // Set up memory for the vector to hold local coordinates (two dimensions)
396  Vector<double> s(DIM);
397 
398  // Get physical variables from the element
399  // (Reynolds number must be multiplied by the density ratio)
400  const double scaled_re = re()*density_ratio();
401  const double scaled_re_st = re_st()*density_ratio();
402  const double visc_ratio = viscosity_ratio();
403 
404  const double eval_real = lambda();
405  const double eval_imag = omega();
406 
407  const std::complex<double> eigenvalue(eval_real,eval_imag);
408 
409  // Integers used to store the local equation and unknown numbers
410  int local_eqn = 0;
411 
412  // Loop over the integration points
413  for(unsigned ipt=0;ipt<n_intpt;ipt++)
414  {
415  // Assign values of the local coordinates s
416  for(unsigned i=0;i<DIM;i++) { s[i] = integral_pt()->knot(ipt,i); }
417 
418  // Get the integral weight
419  const double w = integral_pt()->weight(ipt);
420 
421  // Calculate the fluid shape and test functions, and their derivatives
422  // w.r.t. the global coordinates
423  const double J =
425  testf,dtestfdx);
426 
427  // Calculate the pressure shape and test functions
428  pshape_linearised_nst(s,psip,testp);
429 
430  // Premultiply the weights and the Jacobian of the mapping between
431  // local and global coordinates
432  const double W = w*J;
433 
434  // Allocate storage for the position and the derivative of the
435  // mesh positions w.r.t. time
437  //Vector<double> mesh_velocity(2,0.0);
438 
439  // Allocate storage for the velocity components (six of these)
440  // and their derivatives w.r.t. time
441  Vector<std::complex< double> > interpolated_u(DIM);
442  //Vector<double> dudt(6,0.0);
443  //Allocate storage for the eigen function normalisation
444  Vector<std::complex<double> >interpolated_u_normalisation(DIM);
445  for(unsigned i=0;i<DIM;++i)
446  {
447  interpolated_u[i].real(0.0); interpolated_u[i].imag(0.0);
448  interpolated_u_normalisation[i].real(0.0);
449  interpolated_u_normalisation[i].imag(0.0);
450  }
451 
452  // Allocate storage for the pressure components (two of these
453  std::complex<double> interpolated_p(0.0,0.0);
454  std::complex<double> interpolated_p_normalisation(0.0,0.0);
455 
456  // Allocate storage for the derivatives of the velocity components
457  // w.r.t. global coordinates (r and z)
458  Vector<Vector<std::complex<double> > >interpolated_dudx(DIM);
459  for(unsigned i=0;i<DIM;++i)
460  {
461  interpolated_dudx[i].resize(DIM);
462  for(unsigned j=0;j<DIM;++j)
463  {
464  interpolated_dudx[i][j].real(0.0);
465  interpolated_dudx[i][j].imag(0.0);
466  }
467  }
468 
469  // Calculate pressure at the integration point
470  // -------------------------------------------
471 
472  // Loop over pressure degrees of freedom (associated with a single
473  // pressure component) in the element
474  for(unsigned l=0;l<n_pres;l++)
475  {
476  // Cache the shape function
477  const double psip_ = psip(l);
478 
479  //Get the complex nodal pressure values
480  const std::complex<double>
481  p_value(this->p_linearised_nst(l,0),this->p_linearised_nst(l,1));
482 
483  // Add contribution
484  interpolated_p += p_value*psip_;
485 
486  //Repeat for normalisation
487  const std::complex<double>
488  p_norm_value(this->p_linearised_nst(l,2),this->p_linearised_nst(l,3));
489  interpolated_p_normalisation += p_norm_value*psip_;
490  }
491  // End of loop over the pressure degrees of freedom in the element
492 
493  // Calculate velocities and their derivatives at the integration point
494  // -------------------------------------------------------------------
495 
496  // Loop over the element's nodes
497  for(unsigned l=0;l<n_node;l++)
498  {
499  // Cache the shape function
500  const double psif_ = psif(l);
501 
502  // Loop over the DIM coordinate directions
503  for(unsigned i=0;i<DIM;i++)
504  {
505  interpolated_x[i] += this->raw_nodal_position(l,i)*psif_;
506  }
507 
508  // Loop over the DIM complex velocity components
509  for(unsigned i=0;i<DIM;i++)
510  {
511  // Get the value
512  const std::complex<double>
513  u_value(this->raw_nodal_value(l,u_nodal_index[2*i+0]),
514  this->raw_nodal_value(l,u_nodal_index[2*i+1]));
515 
516  // Add contribution
517  interpolated_u[i] += u_value*psif_;
518 
519  // Add contribution to dudt
520  //dudt[i] += du_dt_linearised_nst(l,i)*psif_;
521 
522  // Loop over two coordinate directions (for derivatives)
523  for(unsigned j=0;j<DIM;j++)
524  {
525  interpolated_dudx[i][j] += u_value*dpsifdx(l,j);
526  }
527 
528  //Interpolate the normalisation function
529  const std::complex<double>
530  normalisation_value(this->raw_nodal_value(l,u_nodal_index[2*(DIM+i)]),
531  this->raw_nodal_value(l,
532  u_nodal_index[2*(DIM+i)+1]));
533  interpolated_u_normalisation[i] += normalisation_value*psif_;
534  }
535  } // End of loop over the element's nodes
536 
537  // Get the mesh velocity if ALE is enabled
538  /*if(!ALE_is_disabled)
539  {
540  // Loop over the element's nodes
541  for(unsigned l=0;l<n_node;l++)
542  {
543  // Loop over the two coordinate directions
544  for(unsigned i=0;i<2;i++)
545  {
546  mesh_velocity[i] += this->raw_dnodal_position_dt(l,i)*psif(l);
547  }
548  }
549  }*/
550 
551  // Get velocities and their derivatives from base flow problem
552  // -----------------------------------------------------------
553 
554  // Allocate storage for the velocity components of the base state
555  // solution (initialise to zero)
556  Vector<double> base_flow_u(DIM,0.0);
557 
558  // Get the user-defined base state solution velocity components
559  get_base_flow_u(time,ipt,interpolated_x,base_flow_u);
560 
561  // Allocate storage for the derivatives of the base state solution's
562  // velocity components w.r.t. global coordinate (r and z)
563  // N.B. the derivatives of the base flow components w.r.t. the
564  // azimuthal coordinate direction (theta) are always zero since the
565  // base flow is axisymmetric
566  DenseMatrix<double> base_flow_dudx(DIM,DIM,0.0);
567 
568  // Get the derivatives of the user-defined base state solution
569  // velocity components w.r.t. global coordinates
570  get_base_flow_dudx(time,ipt,interpolated_x,base_flow_dudx);
571 
572 
573  //MOMENTUM EQUATIONS
574  //------------------
575 
576  //Loop over the test functions
577  for(unsigned l=0;l<n_node;l++)
578  {
579  //Loop over the velocity components
580  for(unsigned i=0;i<DIM;i++)
581  {
582  //Assemble the residuals
583  //Time dependent term
584  std::complex<double> residual_contribution
585  = -scaled_re_st*eigenvalue*interpolated_u[i]*testf[l]*W;
586  //Pressure term
587  residual_contribution += interpolated_p*dtestfdx(l,i)*W;
588  //Viscous terms
589  for(unsigned k=0;k<DIM;++k)
590  {
591  residual_contribution -= visc_ratio*
592  (interpolated_dudx[i][k] + Gamma[i]*interpolated_dudx[k][i])*
593  dtestfdx(l,k)*W;
594  }
595 
596  //Advective terms
597  for(unsigned k=0;k<DIM;++k)
598  {
599  residual_contribution -= scaled_re*(
600  base_flow_u[k]*interpolated_dudx[i][k]
601  + interpolated_u[k]*base_flow_dudx(i,k))*testf[l]*W;
602  }
603 
604  //Now separate real and imaginary parts
605 
606  /*IF it's not a boundary condition*/
607  //Here assume that we're only going to pin entire complex
608  //number or not
609  local_eqn = nodal_local_eqn(l,u_nodal_index[2*i]);
610  if(local_eqn >= 0)
611  {
612  residuals[local_eqn] += residual_contribution.real();
613  }
614 
615  local_eqn = nodal_local_eqn(l,u_nodal_index[2*i+1]);
616  if(local_eqn >= 0)
617  {
618  residuals[local_eqn] += residual_contribution.imag();
619  }
620 
621 
622  //CALCULATE THE JACOBIAN
623  /*if(flag)
624  {
625  //Loop over the velocity shape functions again
626  for(unsigned l2=0;l2<n_node;l2++)
627  {
628  //Loop over the velocity components again
629  for(unsigned i2=0;i2<DIM;i2++)
630  {
631  //If at a non-zero degree of freedom add in the entry
632  local_unknown = nodal_local_eqn(l2,u_nodal_index[i2]);
633  if(local_unknown >= 0)
634  {
635  //Add contribution to Elemental Matrix
636  jacobian(local_eqn,local_unknown)
637  -= visc_ratio*Gamma[i]*dpsifdx(l2,i)*dtestfdx(l,i2)*W;
638 
639  //Extra component if i2 = i
640  if(i2 == i)
641  {
642  //Loop over velocity components
643  for(unsigned k=0;k<DIM;k++)
644  {
645  jacobian(local_eqn,local_unknown)
646  -= visc_ratio*dpsifdx(l2,k)*dtestfdx(l,k)*W;
647  }
648  }
649 
650  //Now add in the inertial terms
651  jacobian(local_eqn,local_unknown)
652  -= scaled_re*psif[l2]*interpolated_dudx(i,i2)*testf[l]*W;
653 
654  //Extra component if i2=i
655  if(i2 == i)
656  {
657  //Add the mass matrix term (only diagonal entries)
658  //Note that this is positive because the mass matrix
659  //is taken to the other side of the equation when
660  //formulating the generalised eigenproblem.
661  if(flag==2)
662  {
663  mass_matrix(local_eqn,local_unknown) +=
664  scaled_re_st*psif[l2]*testf[l]*W;
665  }
666 
667  //du/dt term
668  jacobian(local_eqn,local_unknown)
669  -= scaled_re_st*
670  node_pt(l2)->time_stepper_pt()->weight(1,0)*
671  psif[l2]*testf[l]*W;
672 
673  //Loop over the velocity components
674  for(unsigned k=0;k<DIM;k++)
675  {
676  double tmp=scaled_re*interpolated_u[k];
677  if (!ALE_is_disabled) tmp-=scaled_re_st*mesh_velocity[k];
678  jacobian(local_eqn,local_unknown) -=
679  tmp*dpsifdx(l2,k)*testf[l]*W;
680  }
681  }
682 
683  }
684  }
685  }
686 
687  //Now loop over pressure shape functions
688  //This is the contribution from pressure gradient
689  for(unsigned l2=0;l2<n_pres;l2++)
690  {
691  //If we are at a non-zero degree of freedom in the entry
692  local_unknown = p_local_eqn(l2);
693  if(local_unknown >= 0)
694  {
695  jacobian(local_eqn,local_unknown)
696  += psip[l2]*dtestfdx(l,i)*W;
697  }
698  }
699  } //End of Jacobian calculation
700 
701  }*/ //End of if not boundary condition statement
702 
703  } //End of loop over dimension
704  } //End of loop over shape functions
705 
706 
707 
708  //CONTINUITY EQUATION
709  //-------------------
710 
711  //Loop over the shape functions
712  for(unsigned l=0;l<n_pres;l++)
713  {
714  //Assemble the residuals
715  std::complex<double> residual_contribution
716  = interpolated_dudx[0][0];
717  for(unsigned k=1;k<DIM;++k)
718  {
719  residual_contribution += interpolated_dudx[k][k];
720  }
721 
722  local_eqn = p_local_eqn(l,0);
723  //If not a boundary conditions
724  if(local_eqn >= 0)
725  {
726  residuals[local_eqn] += residual_contribution.real()*testp[l]*W;
727  }
728 
729  local_eqn = p_local_eqn(l,1);
730  //If not a boundary conditions
731  if(local_eqn >= 0)
732  {
733  residuals[local_eqn] += residual_contribution.imag()*testp[l]*W;
734  }
735 
736  } //End of loop over l
737 
738  //Normalisation condition
739  std::complex<double> residual_contribution =
740  interpolated_p_normalisation*interpolated_p;
741  for(unsigned k=0;k<DIM;++k)
742  {
743  residual_contribution +=
744  interpolated_u_normalisation[k]*interpolated_u[k];
745  }
746 
747  local_eqn = this->eigenvalue_local_eqn(0);
748  if(local_eqn >= 0)
749  {
750  residuals[local_eqn] += residual_contribution.real()*W;
751  }
752 
753  local_eqn = this->eigenvalue_local_eqn(1);
754  if(local_eqn >= 0)
755  {
756  residuals[local_eqn] += residual_contribution.imag()*W;
757  }
758 
759  } // End of loop over the integration points
760 
761  } // End of fill_in_generic_residual_contribution_linearised_nst
762 
763 
764 
765 ///////////////////////////////////////////////////////////////////////////
766 ///////////////////////////////////////////////////////////////////////////
767 ///////////////////////////////////////////////////////////////////////////
768 
769 
770  /// Linearised axisymmetric Crouzeix-Raviart elements
771  /// -------------------------------------------------
772 
773 
774  //=======================================================================
775  /// Set the data for the number of variables at each node
776  //=======================================================================
777  const unsigned LinearisedQCrouzeixRaviartElement::
778  Initial_Nvalue[9]={8,8,8,8,8,8,8,8,8};
779 
780 
781 
782  //========================================================================
783  /// Number of values (pinned or dofs) required at node n
784  //========================================================================
786  required_nvalue(const unsigned &n) const { return Initial_Nvalue[n]; }
787 
788 
789 
790 ///////////////////////////////////////////////////////////////////////////
791 ///////////////////////////////////////////////////////////////////////////
792 ///////////////////////////////////////////////////////////////////////////
793 
794 
795  /// Linearised axisymmetric Taylor-Hood elements
796  /// --------------------------------------------
797 
798 
799  //=======================================================================
800  /// Set the data for the number of variables at each node
801  //=======================================================================
802  const unsigned LinearisedQTaylorHoodElement::
803  Initial_Nvalue[9]={12,8,12,8,8,8,12,8,12};
804 
805 
806 
807  //=======================================================================
808  /// Set the data for the pressure conversion array
809  //=======================================================================
810  const unsigned LinearisedQTaylorHoodElement::
811  Pconv[4]={0,2,6,8};
812 
813 
814 
815 } // End of oomph namespace
virtual std::string tecplot_zone_string(const unsigned &nplot) const
Return string for tecplot zone header (when plotting nplot points in each "coordinate direction") ...
Definition: elements.h:2990
double raw_nodal_value(const unsigned &n, const unsigned &i) const
Return the i-th value stored at local node n but do NOT take hanging nodes into account.
Definition: elements.h:2458
unsigned long nrow() const
Return the number of rows of the matrix.
Definition: matrices.h:504
virtual double dshape_and_dtest_eulerian_at_knot_linearised_nst(const unsigned &ipt, Shape &psi, DShape &dpsidx, Shape &test, DShape &dtestdx) const =0
Compute the shape functions and their derivatives w.r.t. global coordinates at the ipt-th integration...
unsigned long ncol() const
Return the number of columns of the matrix.
Definition: matrices.h:507
virtual void get_s_plot(const unsigned &i, const unsigned &nplot, Vector< double > &s, const bool &shifted_to_interior=false) const
Get cector of local coordinates of plot point i (when plotting nplot points in each "coordinate direc...
Definition: elements.h:2978
double nodal_position(const unsigned &n, const unsigned &i) const
Return the i-th coordinate at local node n. If the node is hanging, the appropriate interpolation is ...
Definition: elements.h:2227
cstr elem_len * i
Definition: cfortran.h:607
double & time()
Return current value of continous time.
Definition: timesteppers.h:324
const double & re_st() const
Product of Reynolds and Strouhal number (=Womersley number)
const double & density_ratio() const
Density ratio for element: element&#39;s density relative to the viscosity used in the definition of the ...
char t
Definition: cfortran.h:572
virtual double p_linearised_nst(const unsigned &n_p, const unsigned &i) const =0
Return the i-th pressure value at local pressure "node" n_p. Uses suitably interpolated value for han...
virtual unsigned required_nvalue(const unsigned &n) const
Return number of values (pinned or dofs) required at local node n.
virtual double weight(const unsigned &i) const =0
Return weight of i-th integration point.
double interpolated_p_linearised_nst(const Vector< double > &s, const unsigned &i) const
Return the i-th component of the FE interpolated pressure p[i] at local coordinate s...
virtual unsigned nplot_points(const unsigned &nplot) const
Return total number of plot points (when plotting nplot points in each "coordinate direction") ...
Definition: elements.h:3017
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:3881
double dshape_eulerian(const Vector< double > &s, Shape &psi, DShape &dpsidx) const
Compute the geometric shape functions and also first derivatives w.r.t. global coordinates at local c...
Definition: elements.cc:3227
Integral *const & integral_pt() const
Return the pointer to the integration scheme (const version)
Definition: elements.h:1908
virtual unsigned u_index_linearised_nst(const unsigned &i) const
Return the index at which the i-th unknown velocity component is stored. The default value...
virtual void get_base_flow_dudx(const double &time, const unsigned &ipt, const Vector< double > &x, DenseMatrix< double > &result) const
Calculate the derivatives of the velocity components of the base flow solution w.r.t. global coordinates (r and z) at a given time and Eulerian position.
static char t char * s
Definition: cfortran.h:572
virtual double knot(const unsigned &i, const unsigned &j) const =0
Return local coordinate s[j] of i-th integration point.
virtual void write_tecplot_zone_footer(std::ostream &outfile, const unsigned &nplot) const
Add tecplot zone "footer" to output stream (when plotting nplot points in each "coordinate direction"...
Definition: elements.h:3003
static Vector< double > Gamma
Vector to decide whether the stress-divergence form is used or not.
virtual void fill_in_generic_residual_contribution_linearised_nst(Vector< double > &residuals, DenseMatrix< double > &jacobian, DenseMatrix< double > &mass_matrix, unsigned flag)
Compute the residuals for the Navier-Stokes equations; flag=1(or 0): do (or don&#39;t) compute the Jacobi...
void output(std::ostream &outfile)
Output function: r, z, U^C, U^S, V^C, V^S, W^C, W^S, P^C, P^S in tecplot format. Default number of pl...
virtual unsigned npres_linearised_nst() const =0
Return the number of pressure degrees of freedom associated with a single pressure component in the e...
void strain_rate(const Vector< double > &s, DenseMatrix< double > &strain_rate, const unsigned &real) const
Strain-rate tensor: where (in that order)
Node *& node_pt(const unsigned &n)
Return a pointer to the local node n.
Definition: elements.h:2109
double nodal_value(const unsigned &n, const unsigned &i) const
Return the i-th value stored at local node n. Produces suitably interpolated values for hanging nodes...
Definition: elements.h:2470
virtual void pshape_linearised_nst(const Vector< double > &s, Shape &psi) const =0
Compute the pressure shape functions at local coordinate s.
double interpolated_u_linearised_nst(const Vector< double > &s, const unsigned &i) const
Compute the element&#39;s residual Vector and the jacobian matrix. Virtual function can be overloaded by ...
double raw_nodal_position(const unsigned &n, const unsigned &i) const
Return the i-th coordinate at local node n. Do not use the hanging node representation. NOTE: Moved to cc file because of a possible compiler bug in gcc (yes, really!). The move to the cc file avoids inlining which appears to cause problems (only) when compiled with gcc and -O3; offensive "illegal read" is in optimised-out section of code and data that is allegedly illegal is readily readable (by other means) just before this function is called so I can&#39;t really see how we could possibly be responsible for this...
Definition: elements.cc:1659
virtual unsigned nweight() const =0
Return the number of integration points of the scheme.
TimeStepper *& time_stepper_pt()
Return the pointer to the timestepper.
Definition: nodes.h:246
void output_veloc(std::ostream &outfile, const unsigned &nplot, const unsigned &t)
Output function: r, z, U^C, U^S, V^C, V^S, W^C, W^S, in tecplot format. nplot points in each coordina...
virtual int p_local_eqn(const unsigned &n, const unsigned &i)=0
Access function for the local equation number information for the i-th component of the pressure...
virtual void get_base_flow_u(const double &time, const unsigned &ipt, const Vector< double > &x, Vector< double > &result) const
Calculate the velocity components of the base flow solution at a given time and Eulerian position...
const double & re() const
Reynolds number.
const double & viscosity_ratio() const
Viscosity ratio for element: element&#39;s viscosity relative to the viscosity used in the definition of ...
unsigned nnode() const
Return the number of nodes.
Definition: elements.h:2146
virtual void shape(const Vector< double > &s, Shape &psi) const =0
Calculate the geometric shape functions at local coordinate s. This function must be overloaded for e...
int nodal_local_eqn(const unsigned &n, const unsigned &i) const
Return the local equation number corresponding to the i-th value at the n-th local node...
Definition: elements.h:1386