refineable_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: 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//====================================================================
31 
32 namespace oomph
33 {
34 
35 
36 //==========================================================================
37 /// Add the element's contribution to the elemental residual vector
38 /// and/or elemental jacobian matrix.
39 /// This function overloads the standard version so that the possible
40 /// presence of hanging nodes is taken into account.
41 //=========================================================================
44  Vector<double> &residuals,
45  DenseMatrix<double> &jacobian,
47  &mass_matrix,
48  unsigned flag)
49 {
50 
51 //Find out how many nodes there are in the element
52 const unsigned n_node = nnode();
53 
54 //Get the nodal index at which the unknown is stored
55  const unsigned u_nodal_index = this->u_index_axi_adv_diff();
56 
57 //Set up memory for the shape and test functions
58  Shape psi(n_node), test(n_node);
59  DShape dpsidx(n_node,2), dtestdx(n_node,2);
60 
61 //Set the value of n_intpt
62 const unsigned n_intpt = integral_pt()->nweight();
63 
64 //Set the Vector to hold local coordinates
65 Vector<double> s(2);
66 
67 //Get Peclet number
68 const double scaled_peclet = this->pe();
69 
70 //Get the Peclet number multiplied by the Strouhal number
71 const double scaled_peclet_st = this->pe_st();
72 
73 //Integers used to store the local equation number and local unknown
74 //indices for the residuals and jacobians
75 int local_eqn=0, local_unknown=0;
76 
77 // Local storage for pointers to hang_info objects
78 HangInfo *hang_info_pt=0, *hang_info2_pt=0;
79 
80 //Local variable to determine the ALE stuff
81 bool ALE_is_disabled_flag = this->ALE_is_disabled;
82 
83 //Loop over the integration points
84 for(unsigned ipt=0;ipt<n_intpt;ipt++)
85  {
86 
87  //Assign values of s
88  for(unsigned i=0;i<2;i++) s[i] = integral_pt()->knot(ipt,i);
89 
90  //Get the integral weight
91  double w = integral_pt()->weight(ipt);
92 
93  //Call the derivatives of the shape and test functions
94  double J =
96  test,dtestdx);
97 
98  //Premultiply the weights and the Jacobian
99  double W = w*J;
100 
101  //Calculate local values of the function, initialise to zero
102  double dudt=0.0;
103  double interpolated_u=0.0;
104 
105  //These need to be a Vector to be ANSI C++, initialise to zero
107  Vector<double> interpolated_dudx(2,0.0);
108  Vector<double> mesh_velocity(2,0.0);
109 
110  //Calculate function value and derivatives:
111  //-----------------------------------------
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 = this->nodal_value(l,u_nodal_index);
118  interpolated_u += u_value*psi(l);
119  dudt += this->du_dt_axi_adv_diff(l)*psi(l);
120  // Loop over directions
121  for(unsigned j=0;j<2;j++)
122  {
123  interpolated_x[j] += nodal_position(l,j)*psi(l);
124  interpolated_dudx[j] += u_value*dpsidx(l,j);
125  }
126  }
127 
128  //Get the mesh velocity, if required
129  if (!ALE_is_disabled_flag)
130  {
131  for(unsigned l=0;l<n_node;l++)
132  {
133  // Loop over directions
134  for(unsigned j=0;j<2;j++)
135  {
136  mesh_velocity[j] += dnodal_position_dt(l,j)*psi(l);
137  }
138  }
139  }
140 
141 
142  //Get body force
143  double source;
144  this->get_source_axi_adv_diff(ipt,interpolated_x,source);
145 
146 
147  //Get wind
148  //--------
149  Vector<double> wind(3);
150  this->get_wind_axi_adv_diff(ipt,s,interpolated_x,wind);
151 
152  //r is the first position component
153  double r = interpolated_x[0];
154 
155  // Assemble residuals and Jacobian
156  //================================
157 
158  // Loop over the nodes for the test functions
159  for(unsigned l=0;l<n_node;l++)
160  {
161  //Local variables to store the number of master nodes and
162  //the weight associated with the shape function if the node is hanging
163  unsigned n_master=1; double hang_weight=1.0;
164  //Local bool (is the node hanging)
165  bool is_node_hanging = this->node_pt(l)->is_hanging();
166 
167  //If the node is hanging, get the number of master nodes
168  if(is_node_hanging)
169  {
170  hang_info_pt = this->node_pt(l)->hanging_pt();
171  n_master = hang_info_pt->nmaster();
172  }
173  //Otherwise there is just one master node, the node itself
174  else
175  {
176  n_master = 1;
177  }
178 
179  //Loop over the number of master nodes
180  for(unsigned m=0;m<n_master;m++)
181  {
182  //Get the local equation number and hang_weight
183  //If the node is hanging
184  if(is_node_hanging)
185  {
186  //Read out the local equation from the master node
187  local_eqn = this->local_hang_eqn(hang_info_pt->master_node_pt(m),
188  u_nodal_index);
189  //Read out the weight from the master node
190  hang_weight = hang_info_pt->master_weight(m);
191  }
192  //If the node is not hanging
193  else
194  {
195  //The local equation number comes from the node itself
196  local_eqn = this->nodal_local_eqn(l,u_nodal_index);
197  //The hang weight is one
198  hang_weight = 1.0;
199  }
200 
201  //If the nodal equation is not a boundary conditino
202  if(local_eqn >= 0)
203  {
204  //Add du/dt and body force/source term here
205  residuals[local_eqn] -=
206  (scaled_peclet_st*dudt + source)*r*test(l)*W*hang_weight;
207 
208  //The Advection Diffusion bit itself
209  residuals[local_eqn] -=
210  //radial terms
211  (interpolated_dudx[0]*
212  (scaled_peclet*wind[0]*test(l) + dtestdx(l,0)) +
213  //azimuthal terms
214  (interpolated_dudx[1]*
215  (scaled_peclet*wind[1]*test(l) + dtestdx(l,1))))*r*W*hang_weight;
216 
217  //ALE terms
218  if(!ALE_is_disabled)
219  {
220  residuals[local_eqn] += scaled_peclet_st*(
221  mesh_velocity[0]*interpolated_dudx[0] +
222  mesh_velocity[1]*interpolated_dudx[1])*test(l)*r*W*hang_weight;
223  }
224 
225 
226  // Calculate the Jacobian
227  if(flag)
228  {
229  //Local variables to store the number of master nodes
230  //and the weights associated with each hanging node
231  unsigned n_master2=1; double hang_weight2=1.0;
232  //Loop over the nodes for the variables
233  for(unsigned l2=0;l2<n_node;l2++)
234  {
235  //Local bool (is the node hanging)
236  bool is_node2_hanging = this->node_pt(l2)->is_hanging();
237  //If the node is hanging, get the number of master nodes
238  if(is_node2_hanging)
239  {
240  hang_info2_pt = this->node_pt(l2)->hanging_pt();
241  n_master2 = hang_info2_pt->nmaster();
242  }
243  //Otherwise there is one master node, the node itself
244  else
245  {
246  n_master2 = 1;
247  }
248 
249  //Loop over the master nodes
250  for(unsigned m2=0;m2<n_master2;m2++)
251  {
252  //Get the local unknown and weight
253  //If the node is hanging
254  if(is_node2_hanging)
255  {
256  //Read out the local unknown from the master node
257  local_unknown =
258  this->local_hang_eqn(hang_info2_pt->master_node_pt(m2),
259  u_nodal_index);
260  //Read out the hanging weight from the master node
261  hang_weight2 = hang_info2_pt->master_weight(m2);
262  }
263  //If the node is not hanging
264  else
265  {
266  //The local unknown number comes from the node
267  local_unknown = this->nodal_local_eqn(l2,u_nodal_index);
268  //The hang weight is one
269  hang_weight2 = 1.0;
270  }
271 
272  //If the unknown is not pinned
273  if(local_unknown >= 0)
274  {
275  //Add contribution to Elemental Matrix
276  // Mass matrix du/dt term
277  jacobian(local_eqn,local_unknown)
278  -= scaled_peclet_st*test(l)*psi(l2)*
279  this->node_pt(l2)->time_stepper_pt()->weight(1,0)
280  *r*W*hang_weight*hang_weight2;
281 
282  //Add contribution to mass matrix
283  if(flag==2)
284  {
285  mass_matrix(local_eqn,local_unknown) +=
286  scaled_peclet_st*test(l)*psi(l2)*r*W*hang_weight*hang_weight2;
287  }
288 
289  //Add contribution to Elemental Matrix
290  //Assemble Jacobian term
291  jacobian(local_eqn,local_unknown) -=
292  //radial terms
293  (dpsidx(l2,0)*
294  (scaled_peclet*wind[0]*test(l) + dtestdx(l,0)) +
295  //azimuthal terms
296  (dpsidx(l2,1)*
297  (scaled_peclet*wind[1]*test(l) + dtestdx(l,1))))*r*W*
298  hang_weight*hang_weight2;
299 
300  if(!ALE_is_disabled)
301  {
302  jacobian(local_eqn,local_unknown)
303  += scaled_peclet_st*(
304  mesh_velocity[0]*dpsidx(l2,0) +
305  mesh_velocity[1]*dpsidx(l2,1))*test(l)*r*W*hang_weight*hang_weight2;
306  }
307 
308  }
309  } //End of loop over master nodes
310  } //End of loop over nodes
311  } //End of Jacobian calculation
312 
313  } //End of non-zero equation
314 
315  } //End of loop over the master nodes for residual
316  } //End of loop over nodes
317 
318  } // End of loop over integration points
319 }
320 
321 
322 
323 //====================================================================
324 // Force build of templates
325 //====================================================================
329 
330 }
int local_hang_eqn(Node *const &node_pt, const unsigned &i)
Access function that returns the local equation number for the hanging node variables (values stored ...
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...
bool ALE_is_disabled
Boolean flag to indicate whether AlE formulation is disable.
cstr elem_len * i
Definition: cfortran.h:607
const double & pe_st() const
Peclet number multiplied by Strouhal number.
double nodal_value(const unsigned &n, const unsigned &i) const
Return the i-th value stored at local node n. Produces suitably interpolated values for hanging nodes...
Definition: elements.h:2458
double dnodal_position_dt(const unsigned &n, const unsigned &i) const
Return the i-th component of nodal velocity: dx/dt at local node n.
Definition: elements.h:2226
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 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 ...
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...
HangInfo *const & hanging_pt() const
Return pointer to hanging node data (this refers to the geometric hanging node status) (const version...
Definition: nodes.h:1148
virtual double weight(const unsigned &i) const =0
Return weight of i-th integration point.
unsigned nmaster() const
Return the number of master nodes.
Definition: nodes.h:733
virtual unsigned u_index_axi_adv_diff() const
Broken assignment operator.
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:3841
bool is_hanging() const
Test whether the node is geometrically hanging.
Definition: nodes.h:1207
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.
Refineable version of QAxisymAdvectionDiffusionElement. Inherit from the standard QAxisymAdvectionDif...
Integral *const & integral_pt() const
Return the pointer to the integration scheme (const version)
Definition: elements.h:1900
double const & master_weight(const unsigned &i) const
Return weight for dofs on i-th master node.
Definition: nodes.h:753
Node *& node_pt(const unsigned &n)
Return a pointer to the local node n.
Definition: elements.h:2097
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:1383
Class that contains data for hanging nodes.
Definition: nodes.h:684
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:2215
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
unsigned nnode() const
Return the number of nodes.
Definition: elements.h:2134
void fill_in_generic_residual_contribution_axi_adv_diff(Vector< double > &residuals, DenseMatrix< double > &jacobian, DenseMatrix< double > &mass_matrix, unsigned flag)
Add the element's contribution to the elemental residual vector and/or Jacobian matrix flag=1: comput...
Node *const & master_node_pt(const unsigned &i) const
Return a pointer to the i-th master node.
Definition: nodes.h:736
double du_dt_axi_adv_diff(const unsigned &n) const
du/dt at local node n.