GRINS-0.6.0
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
27 #include "grins/heat_transfer.h"
28 
29 // GRINS
30 #include "grins_config.h"
31 #include "grins/assembly_context.h"
36 
37 // libMesh
38 #include "libmesh/getpot.h"
39 #include "libmesh/quadrature.h"
40 #include "libmesh/boundary_info.h"
41 
42 namespace GRINS
43 {
44 
45  template<class K>
46  HeatTransfer<K>::HeatTransfer( const std::string& physics_name, const GetPot& input )
47  : HeatTransferBase<K>(physics_name, input),
48  _k_index(0)
49  {
50  this->read_input_options(input);
51 
52  // This is deleted in the base class
53  this->_bc_handler = new HeatTransferBCHandling( physics_name, input );
54 
55  if( this->_bc_handler->is_axisymmetric() )
56  {
57  this->_is_axisymmetric = true;
58  }
59 
60  this->_ic_handler = new GenericICHandler( physics_name, input );
61 
62  return;
63  }
64 
65  template<class K>
67  {
68  return;
69  }
70 
71  template<class K>
72  void HeatTransfer<K>::read_input_options( const GetPot& /*input*/ )
73  {
74  return;
75  }
76 
77  template<class K>
80  {
81  std::string section = "Physics/"+heat_transfer+"/output_vars";
82 
83  if( input.have_variable(section) )
84  {
85  unsigned int n_vars = input.vector_variable_size(section);
86 
87  for( unsigned int v = 0; v < n_vars; v++ )
88  {
89  std::string name = input(section,"DIE!",v);
90 
91  if( name == std::string("k") )
92  {
93  this->_k_index = postprocessing.register_quantity( name );
94  }
95  else
96  {
97  std::cerr << "Error: Invalid output_vars value for "+heat_transfer << std::endl
98  << " Found " << name << std::endl
99  << " Acceptable values are: k" << std::endl;
100  libmesh_error();
101  }
102  }
103  }
104 
105  return;
106  }
107 
108  template<class K>
109  void HeatTransfer<K>::element_time_derivative( bool compute_jacobian,
110  AssemblyContext& context,
111  CachedValues& /*cache*/ )
112  {
113 #ifdef GRINS_USE_GRVY_TIMERS
114  this->_timer->BeginTimer("HeatTransfer::element_time_derivative");
115 #endif
116 
117  // The number of local degrees of freedom in each variable.
118  const unsigned int n_T_dofs = context.get_dof_indices(this->_temp_vars.T_var()).size();
119  const unsigned int n_u_dofs = context.get_dof_indices(this->_flow_vars.u_var()).size();
120 
121  //TODO: check n_T_dofs is same as n_u_dofs, n_v_dofs, n_w_dofs
122 
123  // We get some references to cell-specific data that
124  // will be used to assemble the linear system.
125 
126  // Element Jacobian * quadrature weights for interior integration.
127  const std::vector<libMesh::Real> &JxW =
128  context.get_element_fe(this->_temp_vars.T_var())->get_JxW();
129 
130  // The temperature shape functions at interior quadrature points.
131  const std::vector<std::vector<libMesh::Real> >& T_phi =
132  context.get_element_fe(this->_temp_vars.T_var())->get_phi();
133 
134  // The velocity shape functions at interior quadrature points.
135  const std::vector<std::vector<libMesh::Real> >& vel_phi =
136  context.get_element_fe(this->_flow_vars.u_var())->get_phi();
137 
138  // The temperature shape function gradients (in global coords.)
139  // at interior quadrature points.
140  const std::vector<std::vector<libMesh::RealGradient> >& T_gradphi =
141  context.get_element_fe(this->_temp_vars.T_var())->get_dphi();
142 
143  const std::vector<libMesh::Point>& u_qpoint =
144  context.get_element_fe(this->_flow_vars.u_var())->get_xyz();
145 
146  libMesh::DenseSubMatrix<libMesh::Number> &KTT = context.get_elem_jacobian(this->_temp_vars.T_var(), this->_temp_vars.T_var()); // R_{T},{T}
147 
148  libMesh::DenseSubMatrix<libMesh::Number> &KTu = context.get_elem_jacobian(this->_temp_vars.T_var(), this->_flow_vars.u_var()); // R_{T},{u}
149  libMesh::DenseSubMatrix<libMesh::Number> &KTv = context.get_elem_jacobian(this->_temp_vars.T_var(), this->_flow_vars.v_var()); // R_{T},{v}
150  libMesh::DenseSubMatrix<libMesh::Number>* KTw = NULL;
151 
152  libMesh::DenseSubVector<libMesh::Number> &FT = context.get_elem_residual(this->_temp_vars.T_var()); // R_{T}
153 
154  if( this->_dim == 3 )
155  {
156  KTw = &context.get_elem_jacobian(this->_temp_vars.T_var(), this->_flow_vars.w_var()); // R_{T},{w}
157  }
158 
159  // Now we will build the element Jacobian and residual.
160  // Constructing the residual requires the solution and its
161  // gradient from the previous timestep. This must be
162  // calculated at each quadrature point by summing the
163  // solution degree-of-freedom values by the appropriate
164  // weight functions.
165  unsigned int n_qpoints = context.get_element_qrule().n_points();
166 
167  for (unsigned int qp=0; qp != n_qpoints; qp++)
168  {
169  // Compute the solution & its gradient at the old Newton iterate.
170  libMesh::Number u, v;
171  u = context.interior_value(this->_flow_vars.u_var(), qp);
172  v = context.interior_value(this->_flow_vars.v_var(), qp);
173 
174  libMesh::Gradient grad_T;
175  grad_T = context.interior_gradient(this->_temp_vars.T_var(), qp);
176 
177  libMesh::NumberVectorValue U (u,v);
178  if (this->_dim == 3)
179  U(2) = context.interior_value(this->_flow_vars.w_var(), qp);
180 
181  const libMesh::Number r = u_qpoint[qp](0);
182 
183  libMesh::Real jac = JxW[qp];
184 
185  // Compute the conductivity at this qp
186  libMesh::Real _k_qp = this->_k(context, qp);
187 
188  if( this->_is_axisymmetric )
189  {
190  jac *= r;
191  }
192 
193  // First, an i-loop over the degrees of freedom.
194  for (unsigned int i=0; i != n_T_dofs; i++)
195  {
196  FT(i) += jac *
197  (-this->_rho*this->_Cp*T_phi[i][qp]*(U*grad_T) // convection term
198  -_k_qp*(T_gradphi[i][qp]*grad_T) ); // diffusion term
199 
200  if (compute_jacobian)
201  {
202  for (unsigned int j=0; j != n_T_dofs; j++)
203  {
204  // TODO: precompute some terms like:
205  // this->_rho*this->_Cp*T_phi[i][qp]*(vel_phi[j][qp]*T_grad_phi[j][qp])
206 
207  KTT(i,j) += jac * context.get_elem_solution_derivative() *
208  (-this->_rho*this->_Cp*T_phi[i][qp]*(U*T_gradphi[j][qp]) // convection term
209  -_k_qp*(T_gradphi[i][qp]*T_gradphi[j][qp])); // diffusion term
210  } // end of the inner dof (j) loop
211 
212  // Matrix contributions for the Tu, Tv and Tw couplings (n_T_dofs same as n_u_dofs, n_v_dofs and n_w_dofs)
213  for (unsigned int j=0; j != n_u_dofs; j++)
214  {
215  KTu(i,j) += jac * context.get_elem_solution_derivative()*(-this->_rho*this->_Cp*T_phi[i][qp]*(vel_phi[j][qp]*grad_T(0)));
216  KTv(i,j) += jac * context.get_elem_solution_derivative()*(-this->_rho*this->_Cp*T_phi[i][qp]*(vel_phi[j][qp]*grad_T(1)));
217  if (this->_dim == 3)
218  (*KTw)(i,j) += jac * context.get_elem_solution_derivative()*(-this->_rho*this->_Cp*T_phi[i][qp]*(vel_phi[j][qp]*grad_T(2)));
219  } // end of the inner dof (j) loop
220 
221  } // end - if (compute_jacobian && context.get_elem_solution_derivative())
222 
223  } // end of the outer dof (i) loop
224  } // end of the quadrature point (qp) loop
225 
226 #ifdef GRINS_USE_GRVY_TIMERS
227  this->_timer->EndTimer("HeatTransfer::element_time_derivative");
228 #endif
229 
230  return;
231  }
232 
233  template<class K>
234  void HeatTransfer<K>::side_time_derivative( bool compute_jacobian,
235  AssemblyContext& context,
236  CachedValues& cache )
237  {
238 #ifdef GRINS_USE_GRVY_TIMERS
239  this->_timer->BeginTimer("HeatTransfer::side_time_derivative");
240 #endif
241 
242  std::vector<BoundaryID> ids = context.side_boundary_ids();
243 
244  for( std::vector<BoundaryID>::const_iterator it = ids.begin();
245  it != ids.end(); it++ )
246  {
247  libmesh_assert (*it != libMesh::BoundaryInfo::invalid_id);
248 
249  this->_bc_handler->apply_neumann_bcs( context, cache, compute_jacobian, *it );
250  }
251 
252 #ifdef GRINS_USE_GRVY_TIMERS
253  this->_timer->EndTimer("HeatTransfer::side_time_derivative");
254 #endif
255 
256  return;
257  }
258 
259  template<class K>
260  void HeatTransfer<K>::mass_residual( bool compute_jacobian,
261  AssemblyContext& context,
262  CachedValues& /*cache*/ )
263  {
264 #ifdef GRINS_USE_GRVY_TIMERS
265  this->_timer->BeginTimer("HeatTransfer::mass_residual");
266 #endif
267 
268  // First we get some references to cell-specific data that
269  // will be used to assemble the linear system.
270 
271  // Element Jacobian * quadrature weights for interior integration
272  const std::vector<libMesh::Real> &JxW =
273  context.get_element_fe(this->_temp_vars.T_var())->get_JxW();
274 
275  // The shape functions at interior quadrature points.
276  const std::vector<std::vector<libMesh::Real> >& phi =
277  context.get_element_fe(this->_temp_vars.T_var())->get_phi();
278 
279  const std::vector<libMesh::Point>& u_qpoint =
280  context.get_element_fe(this->_flow_vars.u_var())->get_xyz();
281 
282  // The number of local degrees of freedom in each variable
283  const unsigned int n_T_dofs = context.get_dof_indices(this->_temp_vars.T_var()).size();
284 
285  // The subvectors and submatrices we need to fill:
286  libMesh::DenseSubVector<libMesh::Real> &F = context.get_elem_residual(this->_temp_vars.T_var());
287 
288  libMesh::DenseSubMatrix<libMesh::Real> &M = context.get_elem_jacobian(this->_temp_vars.T_var(), this->_temp_vars.T_var());
289 
290  unsigned int n_qpoints = context.get_element_qrule().n_points();
291 
292  for (unsigned int qp = 0; qp != n_qpoints; ++qp)
293  {
294  // For the mass residual, we need to be a little careful.
295  // The time integrator is handling the time-discretization
296  // for us so we need to supply M(u_fixed)*u' for the residual.
297  // u_fixed will be given by the fixed_interior_value function
298  // while u' will be given by the interior_rate function.
299  libMesh::Real T_dot;
300  context.interior_rate(this->_temp_vars.T_var(), qp, T_dot);
301 
302  const libMesh::Number r = u_qpoint[qp](0);
303 
304  libMesh::Real jac = JxW[qp];
305 
306  if( this->_is_axisymmetric )
307  {
308  jac *= r;
309  }
310 
311  for (unsigned int i = 0; i != n_T_dofs; ++i)
312  {
313  F(i) -= this->_rho*this->_Cp*T_dot*phi[i][qp]*jac;
314 
315  if( compute_jacobian )
316  {
317  for (unsigned int j=0; j != n_T_dofs; j++)
318  {
319  // We're assuming rho, cp are constant w.r.t. T here.
320  M(i,j) -= this->_rho*this->_Cp*phi[j][qp]*phi[i][qp]*jac * context.get_elem_solution_rate_derivative();
321  }
322  }// End of check on Jacobian
323 
324  } // End of element dof loop
325 
326  } // End of the quadrature point loop
327 
328 #ifdef GRINS_USE_GRVY_TIMERS
329  this->_timer->EndTimer("HeatTransfer::mass_residual");
330 #endif
331 
332  return;
333  }
334 
335  template<class K>
336  void HeatTransfer<K>::compute_postprocessed_quantity( unsigned int quantity_index,
337  const AssemblyContext& context,
338  const libMesh::Point& point,
339  libMesh::Real& value )
340  {
341  if( quantity_index == this->_k_index )
342  {
343  value = this->_k(point, context.get_time());
344  }
345 
346  return;
347  }
348 
349 } // namespace GRINS
350 
351 // Instantiate
Base class for reading and handling boundary conditions for physics classes.
unsigned int register_quantity(std::string name)
Register quantity to be postprocessed.
GRINS::ICHandlingBase * _ic_handler
Definition: physics.h:258
virtual void element_time_derivative(bool compute_jacobian, AssemblyContext &context, CachedValues &cache)
Time dependent part(s) of physics for element interiors.
GRINS::BCHandlingBase * _bc_handler
Definition: physics.h:256
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...
Physics class for Heat Transfer.
Base class for reading and handling initial conditions for physics classes.
virtual void read_input_options(const GetPot &input)
Read options from GetPot input file.
Definition: heat_transfer.C:72
GRINS namespace.
virtual void compute_postprocessed_quantity(unsigned int quantity_index, const AssemblyContext &context, const libMesh::Point &point, libMesh::Real &value)
Compute value of postprocessed quantities at libMesh::Point.
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.
bool is_axisymmetric() const
const PhysicsName heat_transfer
INSTANTIATE_HEAT_TRANSFER_SUBCLASS(HeatTransfer)
bool _is_axisymmetric
Definition: physics.h:268
virtual void register_postprocessing_vars(const GetPot &input, PostProcessedQuantities< libMesh::Real > &postprocessing)
Register postprocessing variables for HeatTransfer.
Definition: heat_transfer.C:78

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