axisym_advection_diffusion_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$
7 //LIC//
8 //LIC// $LastChangedDate$
9 //LIC//
10 //LIC// Copyright (C) 2006-2016 Matthias Heil and Andrew Hazel
11 //LIC//
12 //LIC// This library is free software; you can redistribute it and/or
13 //LIC// modify it under the terms of the GNU Lesser General Public
14 //LIC// License as published by the Free Software Foundation; either
15 //LIC// version 2.1 of the License, or (at your option) any later version.
16 //LIC//
17 //LIC// This library is distributed in the hope that it will be useful,
18 //LIC// but WITHOUT ANY WARRANTY; without even the implied warranty of
19 //LIC// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
20 //LIC// Lesser General Public License for more details.
21 //LIC//
22 //LIC// You should have received a copy of the GNU Lesser General Public
23 //LIC// License along with this library; if not, write to the Free Software
24 //LIC// Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA
25 //LIC// 02110-1301 USA.
26 //LIC//
27 //LIC// The authors may be contacted at oomph-lib@maths.man.ac.uk.
28 //LIC//
29 //LIC//====================================================================
30 //Non-inline functions for Advection Diffusion elements in a cylindrical
31 //coordinate system
33 
34 namespace oomph
35 {
36 
37 // 2D Steady Axisymmetric Advection Diffusion elements
38 
39 /// Default value for Peclet number
41 
42 /// Default Diffusion coefficient
44 
45 
46 //======================================================================
47 /// \short Compute element residual Vector and/or element Jacobian matrix
48 ///
49 /// flag=1: compute both
50 /// flag=0: compute only residual Vector
51 ///
52 /// Pure version without hanging nodes
53 //======================================================================
55  Vector<double> &residuals, DenseMatrix<double> &jacobian,
56  DenseMatrix<double> &mass_matrix,
57  unsigned flag)
58 {
59  //Find out how many nodes there are
60  const unsigned n_node = nnode();
61 
62  //Get the nodal index at which the unknown is stored
63  const unsigned u_nodal_index = u_index_axi_adv_diff();
64 
65  //Set up memory for the shape and test functions
66  Shape psi(n_node), test(n_node);
67  DShape dpsidx(n_node,2), dtestdx(n_node,2);
68 
69  //Set the value of n_intpt
70  const unsigned n_intpt = integral_pt()->nweight();
71 
72  //Set the Vector to hold local coordinates
73  Vector<double> s(2);
74 
75  //Get Physical Variables from Element
76  const double scaled_peclet = pe();
77 
78  //Get peclet number multiplied by Strouhal number
79  const double scaled_peclet_st = pe_st();
80 
81  //Integers used to store the local equation number and local unknown
82  //indices for the residuals and jacobians
83  int local_eqn=0, local_unknown=0;
84 
85  //Loop over the integration points
86  for(unsigned ipt=0;ipt<n_intpt;ipt++)
87  {
88 
89  //Assign values of s
90  for(unsigned i=0;i<2;i++) s[i] = integral_pt()->knot(ipt,i);
91 
92  //Get the integral weight
93  double w = integral_pt()->weight(ipt);
94 
95  //Call the derivatives of the shape and test functions
96  double J =
98  ipt,psi,dpsidx,test,dtestdx);
99 
100  //Premultiply the weights and the Jacobian
101  double W = w*J;
102 
103  //Calculate local values of the solution and its derivatives
104  //Allocate
105  double interpolated_u = 0.0;
106  double dudt = 0.0;
108  Vector<double> interpolated_dudx(2,0.0);
109  Vector<double> mesh_velocity(2,0.0);
110 
111  //Calculate function value and derivatives:
112  //-----------------------------------------
113  //Loop over nodes
114  for(unsigned l=0;l<n_node;l++)
115  {
116  //Get the value at the node
117  double u_value = raw_nodal_value(l,u_nodal_index);
118  interpolated_u += u_value*psi(l);
119  dudt += du_dt_axi_adv_diff(l)*psi(l);
120  //Loop over the two coordinates directions
121  for(unsigned j=0;j<2;j++)
122  {
123  interpolated_x[j] += raw_nodal_position(l,j)*psi(l);
124  interpolated_dudx[j] += u_value*dpsidx(l,j);
125  }
126  }
127 
128  if(!ALE_is_disabled)
129  {
130  for(unsigned l=0;l<n_node;l++)
131  {
132  for(unsigned j=0;j<2;j++)
133  {
134  mesh_velocity[j] += raw_dnodal_position_dt(l,j)*psi(l);
135  }
136  }
137  }
138 
139 
140  //Get source function
141  //-------------------
142  double source;
143  get_source_axi_adv_diff(ipt,interpolated_x,source);
144 
145 
146  //Get wind three potential components
147  //---------------------------------------
148  Vector<double> wind(3);
149  get_wind_axi_adv_diff(ipt,s,interpolated_x,wind);
150 
151  //Get the diffusion
152  double diff = this->d();
153 
154  //r is the first position component
155  double r = interpolated_x[0];
156 
157  //TEMPERATURE EQUATION (Neglected viscous dissipation)
158  //Assemble residuals and Jacobian
159  //--------------------------------
160 
161  // Loop over the test functions
162  for(unsigned l=0;l<n_node;l++)
163  {
164  //Set the local equation number
165  local_eqn = nodal_local_eqn(l,u_nodal_index);
166 
167  /*IF it's not a boundary condition*/
168  if(local_eqn >= 0)
169  {
170  //Add body force/source term
171  residuals[local_eqn] -= (scaled_peclet_st*dudt + source)*r*test(l)*W;
172 
173  //The Advection Diffusion bit itself
174  residuals[local_eqn] -=
175  //radial terms
176  (interpolated_dudx[0]*
177  (scaled_peclet*wind[0]*test(l) + diff*dtestdx(l,0)) +
178  //azimuthal terms
179  (interpolated_dudx[1]*
180  (scaled_peclet*wind[1]*test(l) + diff*dtestdx(l,1))))*r*W;
181 
182  if(!ALE_is_disabled)
183  {
184  residuals[local_eqn] += scaled_peclet_st*(
185  mesh_velocity[0]*interpolated_dudx[0] +
186  mesh_velocity[1]*interpolated_dudx[1])*test(l)*r*W;
187  }
188 
189  // Calculate the jacobian
190  //-----------------------
191  if(flag)
192  {
193  //Loop over the velocity shape functions again
194  for(unsigned l2=0;l2<n_node;l2++)
195  {
196  //Set the number of the unknown
197  local_unknown = nodal_local_eqn(l2,u_nodal_index);
198 
199  //If at a non-zero degree of freedom add in the entry
200  if(local_unknown >= 0)
201  {
202  //Mass matrix term
203  jacobian(local_eqn,local_unknown)
204  -= scaled_peclet_st*test(l)*psi(l2)*
205  node_pt(l2)->time_stepper_pt()->weight(1,0)*r*W;
206 
207  //add the mass matrix term
208  if(flag==2)
209  {
210  mass_matrix(local_eqn,local_unknown)
211  += scaled_peclet_st*test(l)*psi(l2)*r*W;
212  }
213 
214  //Assemble Jacobian term
215  jacobian(local_eqn,local_unknown) -=
216  //radial terms
217  (dpsidx(l2,0)*
218  (scaled_peclet*wind[0]*test(l) + diff*dtestdx(l,0)) +
219  //azimuthal terms
220  (dpsidx(l2,1)*
221  (scaled_peclet*wind[1]*test(l) + diff*dtestdx(l,1))))*r*W;
222 
223  if(!ALE_is_disabled)
224  {
225  jacobian(local_eqn,local_unknown)
226  += scaled_peclet_st*(
227  mesh_velocity[0]*dpsidx(l2,0) +
228  mesh_velocity[1]*dpsidx(l2,1))*test(l)*r*W;
229  }
230  }
231  }
232  }
233  }
234  }
235 
236 
237  } // End of loop over integration points
238 }
239 
240 
241 
242 
243 //======================================================================
244 /// Self-test: Return 0 for OK
245 //======================================================================
246 //template <unsigned DIM>
248 {
249 
250  bool passed = true;
251 
252  // Check lower-level stuff
253  if (FiniteElement::self_test()!=0)
254  {
255  passed = false;
256  }
257 
258  // Return verdict
259  if (passed)
260  {
261  return 0;
262  }
263  else
264  {
265  return 1;
266  }
267 
268 }
269 
270 
271 
272 //======================================================================
273 /// \short Output function:
274 ///
275 /// r,z,u,w_r,w_z
276 ///
277 /// nplot points in each coordinate direction
278 //======================================================================
279 void AxisymAdvectionDiffusionEquations::output(std::ostream &outfile,
280  const unsigned &nplot)
281 {
282  //Vector of local coordinates
283  Vector<double> s(2);
284 
285  //Tecplot header info
286  outfile << tecplot_zone_string(nplot);
287 
288  //Loop over plot points
289  unsigned num_plot_points = nplot_points(nplot);
290  for (unsigned iplot=0;iplot<num_plot_points;iplot++)
291  {
292  //Get local coordinates of plot point
293  get_s_plot(iplot,nplot,s);
294 
295  //Get Eulerian coordinate of plot point
296  Vector<double> x(2);
297  interpolated_x(s,x);
298 
299  for(unsigned i=0;i<2;i++)
300  {
301  outfile << x[i] << " ";
302  }
303 
304  //Output concentration
305  outfile << this->interpolated_u_axi_adv_diff(s) << " ";
306 
307  //Get the wind
308  Vector<double> wind(3);
309  //Dummy ipt argument needed... ?
310  unsigned ipt = 0;
311  get_wind_axi_adv_diff(ipt,s,x,wind);
312  for(unsigned i=0;i<3;i++)
313  {
314  outfile << wind[i] << " ";
315  }
316  outfile << std::endl;
317 
318  }
319 
320  //Write tecplot footer (e.g. FE connectivity lists)
321  write_tecplot_zone_footer(outfile,nplot);
322 
323 }
324 
325 
326 //======================================================================
327 /// C-style output function:
328 ///
329 /// r,z,u
330 ///
331 /// nplot points in each coordinate direction
332 //======================================================================
333 //template <unsigned DIM>
335  const unsigned &nplot)
336 {
337  //Vector of local coordinates
338  Vector<double> s(2);
339 
340  //Tecplot header info
341  fprintf(file_pt,"%s",tecplot_zone_string(nplot).c_str());
342 
343  //Loop over plot points
344  unsigned num_plot_points = nplot_points(nplot);
345  for (unsigned iplot=0;iplot<num_plot_points;iplot++)
346  {
347 
348  //Get local coordinates of plot point
349  get_s_plot(iplot,nplot,s);
350 
351  for(unsigned i=0;i<2;i++)
352  {
353  fprintf(file_pt,"%g ",interpolated_x(s,i));
354 
355  }
356 
357  fprintf(file_pt,"%g \n",interpolated_u_axi_adv_diff(s));
358  }
359 
360  //Write tecplot footer (e.g. FE connectivity lists)
361  write_tecplot_zone_footer(file_pt,nplot);
362 
363 }
364 
365 //======================================================================
366  /// \short Output exact solution
367  ///
368  /// Solution is provided via function pointer.
369  /// Plot at a given number of plot points.
370  ///
371  /// r,z,u_exact
372 //======================================================================
373 //template <unsigned DIM>
375  std::ostream &outfile,
376  const unsigned &nplot,
378  {
379 
380  //Vector of local coordinates
381  Vector<double> s(2);
382 
383  //Vector for coordintes
384  Vector<double> x(2);
385 
386  //Tecplot header info
387  outfile << tecplot_zone_string(nplot);
388 
389  //Exact solution Vector (here a scalar)
390  Vector<double> exact_soln(1);
391 
392  //Loop over plot points
393  unsigned num_plot_points=nplot_points(nplot);
394  for (unsigned iplot=0;iplot<num_plot_points;iplot++)
395  {
396 
397  //Get local coordinates of plot point
398  get_s_plot(iplot,nplot,s);
399 
400  //Get x position as Vector
401  interpolated_x(s,x);
402 
403  //Get exact solution at this point
404  (*exact_soln_pt)(x,exact_soln);
405 
406  //Output x,y,...,u_exact
407  for(unsigned i=0;i<2;i++)
408  {
409  outfile << x[i] << " ";
410  }
411  outfile << exact_soln[0] << std::endl;
412  }
413 
414  //Write tecplot footer (e.g. FE connectivity lists)
415  write_tecplot_zone_footer(outfile,nplot);
416 
417  }
418 
419 
420 //======================================================================
421  /// \short Validate against exact solution
422  ///
423  /// Solution is provided via function pointer.
424  /// Plot error at a given number of plot points.
425  ///
426 //======================================================================
427 //template <unsigned DIM>
429  std::ostream &outfile,
431  double& error,
432  double& norm)
433 {
434 
435  //Initialise
436  error=0.0;
437  norm=0.0;
438 
439  //Vector of local coordinates
440  Vector<double> s(2);
441 
442  //Vector for coordintes
443  Vector<double> x(2);
444 
445  //Find out how many nodes there are in the element
446  unsigned n_node = nnode();
447 
448  Shape psi(n_node);
449 
450  //Set the value of n_intpt
451  unsigned n_intpt = integral_pt()->nweight();
452 
453  //Tecplot header info
454  outfile << "ZONE" << std::endl;
455 
456  //Exact solution Vector (here a scalar)
457  Vector<double> exact_soln(1);
458 
459  //Loop over the integration points
460  for(unsigned ipt=0;ipt<n_intpt;ipt++)
461  {
462 
463  //Assign values of s
464  for(unsigned i=0;i<2;i++)
465  {
466  s[i] = integral_pt()->knot(ipt,i);
467  }
468 
469  //Get the integral weight
470  double w = integral_pt()->weight(ipt);
471 
472  //Get jacobian of mapping
473  double J=J_eulerian(s);
474 
475  //Premultiply the weights and the Jacobian
476  double W = w*J;
477 
478  //Get x position as Vector
479  interpolated_x(s,x);
480 
481  //Get FE function value
482  double u_fe=interpolated_u_axi_adv_diff(s);
483 
484  //Get exact solution at this point
485  (*exact_soln_pt)(x,exact_soln);
486 
487  //Output x,y,...,error
488  for(unsigned i=0;i<2;i++)
489  {
490  outfile << x[i] << " ";
491  }
492  outfile << exact_soln[0] << " " << exact_soln[0]-u_fe << std::endl;
493 
494  //Add to error and norm
495  norm+=exact_soln[0]*exact_soln[0]*x[0]*W;
496  error+=(exact_soln[0]-u_fe)*(exact_soln[0]-u_fe)*x[0]*W;
497 
498  }
499 
500 }
501 
502 
503 //======================================================================
504 // Set the data for the number of Variables at each node
505 //======================================================================
506 template<unsigned NNODE_1D>
508 Initial_Nvalue = 1;
509 
510 //====================================================================
511 // Force build of templates
512 //====================================================================
513 
517 
518 
519 }
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
void compute_error(std::ostream &outfile, FiniteElement::SteadyExactSolutionFctPt exact_soln_pt, double &error, double &norm)
Get error against and norm of exact solution.
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
bool ALE_is_disabled
Boolean flag to indicate whether AlE formulation is disable.
cstr elem_len * i
Definition: cfortran.h:607
virtual unsigned self_test()
Self-test: Check inversion of element & do self-test for GeneralisedElement. Return 0 if OK...
Definition: elements.cc:4333
virtual double dshape_and_dtest_eulerian_at_knot_axi_adv_diff(const unsigned &ipt, Shape &psi, DShape &dpsidx, Shape &test, DShape &dtestdx) const =0
Shape/test functions and derivs w.r.t. to global coords at integration point ipt; return Jacobian of ...
const double & pe_st() const
Peclet number multiplied by Strouhal number.
virtual double weight(const unsigned &i) const =0
Return weight of i-th integration point.
virtual void get_wind_axi_adv_diff(const unsigned &ipt, const Vector< double > &s, const Vector< double > &x, Vector< double > &wind) const
Get wind at (Eulerian) position x and/or local coordinate s. This function is virtual to allow overlo...
virtual void fill_in_generic_residual_contribution_axi_adv_diff(Vector< double > &residuals, DenseMatrix< double > &jacobian, DenseMatrix< double > &mass_matrix, unsigned flag)
Add the element&#39;s contribution to its residual vector only (if flag=and/or element Jacobian matrix...
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
QAxisymAdvectionDiffusionElement elements are linear/quadrilateral/brick-shaped Axisymmetric Advectio...
void output(std::ostream &outfile)
Output with default number of plot points.
void(* SteadyExactSolutionFctPt)(const Vector< double > &, Vector< double > &)
Function pointer for function that computes vector-valued steady "exact solution" as ...
Definition: elements.h:1723
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
Integral *const & integral_pt() const
Return the pointer to the integration scheme (const version)
Definition: elements.h:1908
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
Node *& node_pt(const unsigned &n)
Return a pointer to the local node n.
Definition: elements.h:2109
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
static double Default_peclet_number
Static default value for the Peclet number.
double du_dt_axi_adv_diff(const unsigned &n) const
du/dt at local node n.
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_fct(std::ostream &outfile, const unsigned &nplot, FiniteElement::SteadyExactSolutionFctPt exact_soln_pt)
Output exact soln: r,z,u_exact at nplot^2 plot points.
double interpolated_u_axi_adv_diff(const Vector< double > &s) const
Return FE representation of function value u(s) at local coordinate s.
double raw_dnodal_position_dt(const unsigned &n, const unsigned &i) const
Return the i-th component of nodal velocity: dx/dt at local node n. Do not use the hanging node repre...
Definition: elements.h:2182
virtual unsigned u_index_axi_adv_diff() const
Broken assignment operator.
static double Default_diffusion_parameter
Static default value for the Peclet number.
virtual void get_source_axi_adv_diff(const unsigned &ipt, const Vector< double > &x, double &source) const
Get source term at (Eulerian) position x. This function is virtual to allow overloading in multi-phys...
unsigned nnode() const
Return the number of nodes.
Definition: elements.h:2146
virtual double weight(const unsigned &i, const unsigned &j) const
Access function for j-th weight for the i-th derivative.
Definition: timesteppers.h:557
virtual double J_eulerian(const Vector< double > &s) const
Return the Jacobian of mapping from local to global coordinates at local position s...
Definition: elements.cc:4022
const double & d() const
Peclet number multiplied by Strouhal number.
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