GRINS-0.6.0
axisym_heat_transfer.C
Go to the documentation of this file.
1 //-----------------------------------------------------------------------bl-
2 //--------------------------------------------------------------------------
3 //
4 // GRINS - General Reacting Incompressible Navier-Stokes
5 //
6 // Copyright (C) 2014-2015 Paul T. Bauman, Roy H. Stogner
7 // Copyright (C) 2010-2013 The PECOS Development Team
8 //
9 // This library is free software; you can redistribute it and/or
10 // modify it under the terms of the Version 2.1 GNU Lesser General
11 // Public License as published by the Free Software Foundation.
12 //
13 // This library is distributed in the hope that it will be useful,
14 // but WITHOUT ANY WARRANTY; without even the implied warranty of
15 // MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
16 // Lesser General Public License for more details.
17 //
18 // You should have received a copy of the GNU Lesser General Public
19 // License along with this library; if not, write to the Free Software
20 // Foundation, Inc. 51 Franklin Street, Fifth Floor,
21 // Boston, MA 02110-1301 USA
22 //
23 //-----------------------------------------------------------------------el-
24 
25 
26 // This class
28 
29 // GRINS
30 #include "grins/assembly_context.h"
33 #include "grins/grins_enums.h"
35 
36 // libMesh
37 #include "libmesh/utility.h"
38 #include "libmesh/string_to_enum.h"
39 #include "libmesh/getpot.h"
40 #include "libmesh/fem_system.h"
41 #include "libmesh/quadrature.h"
42 
43 namespace GRINS
44 {
45 
46  template< class Conductivity>
48  const GetPot& input)
49  : Physics(physics_name, input),
50  _k(input)
51  {
52  this->read_input_options(input);
53 
54  // This is deleted in the base class
55  this->_bc_handler = new AxisymmetricHeatTransferBCHandling( physics_name, input );
56  this->_ic_handler = new GenericICHandler( physics_name, input );
57 
58  return;
59  }
60 
61  template< class Conductivity>
63  {
64  return;
65  }
66 
67  template< class Conductivity>
69  {
70  this->_T_FE_family =
71  libMesh::Utility::string_to_enum<GRINSEnums::FEFamily>( input("Physics/"+axisymmetric_heat_transfer+"/FE_family", "LAGRANGE") );
72 
73  this->_T_order =
74  libMesh::Utility::string_to_enum<GRINSEnums::Order>( input("Physics/"+axisymmetric_heat_transfer+"/T_order", "SECOND") );
75 
76  this->_V_FE_family =
77  libMesh::Utility::string_to_enum<GRINSEnums::FEFamily>( input("Physics/"+incompressible_navier_stokes+"/FE_family", "LAGRANGE") );
78 
79  this->_V_order =
80  libMesh::Utility::string_to_enum<GRINSEnums::Order>( input("Physics/"+incompressible_navier_stokes+"/V_order", "SECOND") );
81 
82  //TODO: same as Incompressible NS
83  this->set_parameter
84  (this->_rho, input,
85  "Physics/"+axisymmetric_heat_transfer+"/rho", 1.0);
86 
87  this->set_parameter
88  (this->_Cp, input,
89  "Physics/"+axisymmetric_heat_transfer+"/Cp", 1.0);
90 
91  this->_T_var_name = input("Physics/VariableNames/Temperature", T_var_name_default );
92 
93  // registered/non-owned variable names
94  this->_u_r_var_name = input("Physics/VariableNames/r_velocity", u_r_var_name_default );
95  this->_u_z_var_name = input("Physics/VariableNames/z_velocity", u_z_var_name_default );
96 
97  return;
98  }
99 
100  template< class Conductivity>
102  {
103  // Get libMesh to assign an index for each variable
104  this->_dim = system->get_mesh().mesh_dimension();
105 
106  _T_var = system->add_variable( _T_var_name, _T_order, _T_FE_family);
107 
108  // If these are already added, then we just get the index.
109  _u_r_var = system->add_variable(_u_r_var_name, _V_order, _V_FE_family);
110  _u_z_var = system->add_variable(_u_z_var_name, _V_order, _V_FE_family);
111 
112  return;
113  }
114 
115  template< class Conductivity>
117  {
118  // Tell the system to march temperature forward in time
119  system->time_evolving(_T_var);
120  return;
121  }
122 
123  template< class Conductivity>
125  {
126  // We should prerequest all the data
127  // we will need to build the linear system
128  // or evaluate a quantity of interest.
129  context.get_element_fe(_T_var)->get_JxW();
130  context.get_element_fe(_T_var)->get_phi();
131  context.get_element_fe(_T_var)->get_dphi();
132  context.get_element_fe(_T_var)->get_xyz();
133 
134  context.get_side_fe(_T_var)->get_JxW();
135  context.get_side_fe(_T_var)->get_phi();
136  context.get_side_fe(_T_var)->get_dphi();
137  context.get_side_fe(_T_var)->get_xyz();
138 
139  // _u_var is registered so can we assume things related to _u_var
140  // are available in FEMContext
141 
142  return;
143  }
144 
145  template< class Conductivity>
147  AssemblyContext& context,
148  CachedValues& /*cache*/ )
149  {
150 #ifdef GRINS_USE_GRVY_TIMERS
151  this->_timer->BeginTimer("AxisymmetricHeatTransfer::element_time_derivative");
152 #endif
153 
154  // The number of local degrees of freedom in each variable.
155  const unsigned int n_T_dofs = context.get_dof_indices(_T_var).size();
156  const unsigned int n_u_dofs = context.get_dof_indices(_u_r_var).size();
157 
158  //TODO: check n_T_dofs is same as n_u_dofs, n_v_dofs, n_w_dofs
159 
160  // We get some references to cell-specific data that
161  // will be used to assemble the linear system.
162 
163  // Element Jacobian * quadrature weights for interior integration.
164  const std::vector<libMesh::Real> &JxW =
165  context.get_element_fe(_T_var)->get_JxW();
166 
167  // The temperature shape functions at interior quadrature points.
168  const std::vector<std::vector<libMesh::Real> >& T_phi =
169  context.get_element_fe(_T_var)->get_phi();
170 
171  // The velocity shape functions at interior quadrature points.
172  const std::vector<std::vector<libMesh::Real> >& vel_phi =
173  context.get_element_fe(_u_r_var)->get_phi();
174 
175  // The temperature shape function gradients (in global coords.)
176  // at interior quadrature points.
177  const std::vector<std::vector<libMesh::RealGradient> >& T_gradphi =
178  context.get_element_fe(_T_var)->get_dphi();
179 
180  // Physical location of the quadrature points
181  const std::vector<libMesh::Point>& u_qpoint =
182  context.get_element_fe(_u_r_var)->get_xyz();
183 
184  // The subvectors and submatrices we need to fill:
185  libMesh::DenseSubVector<libMesh::Number> &FT = context.get_elem_residual(_T_var); // R_{T}
186 
187  libMesh::DenseSubMatrix<libMesh::Number> &KTT = context.get_elem_jacobian(_T_var, _T_var); // R_{T},{T}
188 
189  libMesh::DenseSubMatrix<libMesh::Number> &KTr = context.get_elem_jacobian(_T_var, _u_r_var); // R_{T},{r}
190  libMesh::DenseSubMatrix<libMesh::Number> &KTz = context.get_elem_jacobian(_T_var, _u_z_var); // R_{T},{z}
191 
192 
193  // Now we will build the element Jacobian and residual.
194  // Constructing the residual requires the solution and its
195  // gradient from the previous timestep. This must be
196  // calculated at each quadrature point by summing the
197  // solution degree-of-freedom values by the appropriate
198  // weight functions.
199  unsigned int n_qpoints = context.get_element_qrule().n_points();
200 
201  for (unsigned int qp=0; qp != n_qpoints; qp++)
202  {
203  const libMesh::Number r = u_qpoint[qp](0);
204 
205  // Compute the solution & its gradient at the old Newton iterate.
206  libMesh::Number u_r, u_z;
207  u_r = context.interior_value(_u_r_var, qp);
208  u_z = context.interior_value(_u_z_var, qp);
209 
210  libMesh::Gradient grad_T;
211  grad_T = context.interior_gradient(_T_var, qp);
212 
213  libMesh::NumberVectorValue U (u_r,u_z);
214 
215  libMesh::Number k = this->_k( context, qp );
216 
217  // FIXME - once we have T-dependent k, we'll need its
218  // derivatives in Jacobians
219  // libMesh::Number dk_dT = this->_k.deriv( T );
220 
221  // First, an i-loop over the degrees of freedom.
222  for (unsigned int i=0; i != n_T_dofs; i++)
223  {
224  FT(i) += JxW[qp]*r*
225  (-_rho*_Cp*T_phi[i][qp]*(U*grad_T) // convection term
226  -k*(T_gradphi[i][qp]*grad_T) ); // diffusion term
227 
228  if (compute_jacobian)
229  {
230  libmesh_assert (context.get_elem_solution_derivative() == 1.0);
231 
232  for (unsigned int j=0; j != n_T_dofs; j++)
233  {
234  // TODO: precompute some terms like:
235  // _rho*_Cp*T_phi[i][qp]*(vel_phi[j][qp]*T_grad_phi[j][qp])
236 
237  KTT(i,j) += JxW[qp] * context.get_elem_solution_derivative() *r*
238  (-_rho*_Cp*T_phi[i][qp]*(U*T_gradphi[j][qp]) // convection term
239  -k*(T_gradphi[i][qp]*T_gradphi[j][qp])); // diffusion term
240  } // end of the inner dof (j) loop
241 
242 #if 0
243  if( dk_dT != 0.0 )
244  {
245  for (unsigned int j=0; j != n_T_dofs; j++)
246  {
247  // TODO: precompute some terms like:
248  KTT(i,j) -= JxW[qp] * context.get_elem_solution_derivative() *r*( dk_dT*T_phi[j][qp]*T_gradphi[i][qp]*grad_T );
249  }
250  }
251 #endif
252 
253  // Matrix contributions for the Tu, Tv and Tw couplings (n_T_dofs same as n_u_dofs, n_v_dofs and n_w_dofs)
254  for (unsigned int j=0; j != n_u_dofs; j++)
255  {
256  KTr(i,j) += JxW[qp] * context.get_elem_solution_derivative() *r*(-_rho*_Cp*T_phi[i][qp]*(vel_phi[j][qp]*grad_T(0)));
257  KTz(i,j) += JxW[qp] * context.get_elem_solution_derivative() *r*(-_rho*_Cp*T_phi[i][qp]*(vel_phi[j][qp]*grad_T(1)));
258  } // end of the inner dof (j) loop
259 
260  } // end - if (compute_jacobian && context.get_elem_solution_derivative())
261 
262  } // end of the outer dof (i) loop
263  } // end of the quadrature point (qp) loop
264 
265 #ifdef GRINS_USE_GRVY_TIMERS
266  this->_timer->EndTimer("AxisymmetricHeatTransfer::element_time_derivative");
267 #endif
268 
269  return;
270  }
271 
272  template< class Conductivity>
274  AssemblyContext& context,
275  CachedValues& cache )
276  {
277 #ifdef GRINS_USE_GRVY_TIMERS
278  this->_timer->BeginTimer("AxisymmetricHeatTransfer::side_time_derivative");
279 #endif
280 
281  std::vector<BoundaryID> ids = context.side_boundary_ids();
282 
283  for( std::vector<BoundaryID>::const_iterator it = ids.begin();
284  it != ids.end(); it++ )
285  {
286  libmesh_assert (*it != libMesh::BoundaryInfo::invalid_id);
287 
288  _bc_handler->apply_neumann_bcs( context, cache, compute_jacobian, *it );
289  }
290 
291 #ifdef GRINS_USE_GRVY_TIMERS
292  this->_timer->EndTimer("AxisymmetricHeatTransfer::side_time_derivative");
293 #endif
294 
295  return;
296  }
297 
298  template< class Conductivity>
300  AssemblyContext& context,
301  CachedValues& /*cache*/ )
302  {
303 #ifdef GRINS_USE_GRVY_TIMERS
304  this->_timer->BeginTimer("AxisymmetricHeatTransfer::mass_residual");
305 #endif
306 
307  // First we get some references to cell-specific data that
308  // will be used to assemble the linear system.
309 
310  // Element Jacobian * quadrature weights for interior integration
311  const std::vector<libMesh::Real> &JxW =
312  context.get_element_fe(_T_var)->get_JxW();
313 
314  // The shape functions at interior quadrature points.
315  const std::vector<std::vector<libMesh::Real> >& phi =
316  context.get_element_fe(_T_var)->get_phi();
317 
318  // The number of local degrees of freedom in each variable
319  const unsigned int n_T_dofs = context.get_dof_indices(_T_var).size();
320 
321  // Physical location of the quadrature points
322  const std::vector<libMesh::Point>& u_qpoint =
323  context.get_element_fe(_u_r_var)->get_xyz();
324 
325  // The subvectors and submatrices we need to fill:
326  libMesh::DenseSubVector<libMesh::Real> &F =
327  context.get_elem_residual(_T_var);
328 
329  libMesh::DenseSubMatrix<libMesh::Real> &M =
330  context.get_elem_jacobian(_T_var, _T_var);
331 
332  unsigned int n_qpoints = context.get_element_qrule().n_points();
333 
334  for (unsigned int qp = 0; qp != n_qpoints; ++qp)
335  {
336  const libMesh::Number r = u_qpoint[qp](0);
337 
338  // For the mass residual, we need to be a little careful.
339  // The time integrator is handling the time-discretization
340  // for us so we need to supply M(u_fixed)*u' for the residual.
341  // u_fixed will be given by the fixed_interior_value function
342  // while u' will be given by the interior_rate function.
343  libMesh::Real T_dot;
344  context.interior_rate(_T_var, qp, T_dot);
345 
346  for (unsigned int i = 0; i != n_T_dofs; ++i)
347  {
348  F(i) -= JxW[qp]*r*(_rho*_Cp*T_dot*phi[i][qp] );
349 
350  if( compute_jacobian )
351  {
352  for (unsigned int j=0; j != n_T_dofs; j++)
353  {
354  // We're assuming rho, cp are constant w.r.t. T here.
355  M(i,j) -= JxW[qp] * context.get_elem_solution_rate_derivative() *r*_rho*_Cp*phi[j][qp]*phi[i][qp] ;
356  }
357  }// End of check on Jacobian
358 
359  } // End of element dof loop
360 
361  } // End of the quadrature point loop
362 
363 #ifdef GRINS_USE_GRVY_TIMERS
364  this->_timer->EndTimer("AxisymmetricHeatTransfer::mass_residual");
365 #endif
366 
367  return;
368  }
369 
370  template< class Conductivity>
372  ( const std::string & param_name,
374  const
375  {
376  ParameterUser::register_parameter(param_name, param_pointer);
377  _k.register_parameter(param_name, param_pointer);
378  }
379 
380 
381 } // namespace GRINS
382 
383 // Instantiate
384 INSTANTIATE_HEAT_TRANSFER_SUBCLASS(AxisymmetricHeatTransfer);
virtual void read_input_options(const GetPot &input)
Read options from GetPot input file.
const PhysicsName incompressible_navier_stokes
GRINS::ICHandlingBase * _ic_handler
Definition: physics.h:258
virtual void side_time_derivative(bool compute_jacobian, AssemblyContext &context, CachedValues &cache)
Time dependent part(s) of physics for boundaries of elements on the domain boundary.
GRINS::BCHandlingBase * _bc_handler
Definition: physics.h:256
INSTANTIATE_HEAT_TRANSFER_SUBCLASS(AxisymmetricHeatTransfer)
Physics abstract base class. Defines API for physics to be added to MultiphysicsSystem.
Definition: physics.h:106
const PhysicsName axisymmetric_heat_transfer
virtual void register_parameter(const std::string &param_name, libMesh::ParameterMultiPointer< libMesh::Number > &param_pointer) const
Each subclass will register its copy of an independent.
virtual void init_variables(libMesh::FEMSystem *system)
Initialization AxisymmetricHeatTransfer variables.
Base class for reading and handling initial conditions for physics classes.
virtual void set_time_evolving_vars(libMesh::FEMSystem *system)
Sets velocity variables to be time-evolving.
GRINS namespace.
virtual void init_context(AssemblyContext &context)
Initialize context for added physics variables.
const std::string T_var_name_default
temperature
virtual void register_parameter(const std::string &param_name, libMesh::ParameterMultiPointer< libMesh::Number > &param_pointer) const
Each subclass will register its copy of an independent.
virtual void mass_residual(bool compute_jacobian, AssemblyContext &context, CachedValues &cache)
Mass matrix part(s) for element interiors. All boundary terms lie within the time_derivative part...
Base class for reading and handling boundary conditions for physics classes.
const std::string u_z_var_name_default
z-velocity (axisymmetric case)
virtual void element_time_derivative(bool compute_jacobian, AssemblyContext &context, CachedValues &cache)
Time dependent part(s) of physics for element interiors.
const std::string u_r_var_name_default
r-velocity (axisymmetric case)

Generated on Mon Jun 22 2015 21:32:20 for GRINS-0.6.0 by  doxygen 1.8.9.1