GRINS-0.6.0
elastic_membrane.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 // This class
26 #include "grins/elastic_membrane.h"
27 
28 // GRINS
29 #include "grins_config.h"
30 #include "grins/math_constants.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 #include "libmesh/fem_system.h"
42 #include "libmesh/fe_interface.h"
43 
44 namespace GRINS
45 {
46  template<typename StressStrainLaw>
47  ElasticMembrane<StressStrainLaw>::ElasticMembrane( const GRINS::PhysicsName& physics_name, const GetPot& input,
48  bool is_compressible )
49  : ElasticMembraneBase(physics_name,input),
50  _stress_strain_law(input),
51  _h0(1.0),
52  _is_compressible(is_compressible)
53  {
54  // Force the user to set h0
55  if( !input.have_variable("Physics/"+physics_name+"/h0") )
56  {
57  std::cerr << "Error: Must specify initial thickness for "+physics_name << std::endl
58  << " Input the option Physics/"+physics_name+"/h0" << std::endl;
59  libmesh_error();
60  }
61 
62  this->set_parameter
63  (_h0, input, "Physics/"+physics_name+"/h0", _h0 );
64 
65  this->_bc_handler = new SolidMechanicsBCHandling( physics_name, input );
66 
67  this->_ic_handler = new GenericICHandler(physics_name, input);
68 
69  return;
70  }
71 
72  template<typename StressStrainLaw>
74  {
75  return;
76  }
77 
78  template<typename StressStrainLaw>
79  void ElasticMembrane<StressStrainLaw>::init_variables( libMesh::FEMSystem* system )
80  {
81  // First call base class
83 
84  // Now build lambda_sq variable if we need it
85  if(_is_compressible)
86  {
88  _lambda_sq_var = system->add_variable( "lambda_sq", GRINSEnums::FIRST, GRINSEnums::LAGRANGE);
89  }
90 
91  return;
92  }
93 
94  template<typename StressStrainLaw>
97  {
98  std::string section = "Physics/"+elastic_membrane+"/output_vars";
99 
100  if( input.have_variable(section) )
101  {
102  unsigned int n_vars = input.vector_variable_size(section);
103 
104  for( unsigned int v = 0; v < n_vars; v++ )
105  {
106  std::string name = input(section,"DIE!",v);
107 
108  if( name == std::string("stress") )
109  {
110  // sigma_xx, sigma_xy, sigma_yy, sigma_yx = sigma_xy
111  // sigma_zz = 0 by assumption of this Physics
112  _stress_indices.resize(7);
113 
114  this->_stress_indices[0] = postprocessing.register_quantity("stress_xx");
115 
116  this->_stress_indices[1] = postprocessing.register_quantity("stress_xy");
117 
118  this->_stress_indices[2] = postprocessing.register_quantity("stress_yy");
119 
120  this->_stress_indices[3] = postprocessing.register_quantity("sigma_max");
121 
122  this->_stress_indices[4] = postprocessing.register_quantity("sigma_1");
123 
124  this->_stress_indices[5] = postprocessing.register_quantity("sigma_2");
125 
126  this->_stress_indices[6] = postprocessing.register_quantity("sigma_3");
127  }
128  else if( name == std::string( "stress_zz" ) )
129  {
130  // This is mostly for sanity checking the plane stress condition
131  this->_stress_zz_index = postprocessing.register_quantity("stress_zz");
132  }
133  else if( name == std::string("strain") )
134  {
135  // eps_xx, eps_xy, eps_yy, eps_yx = eps_xy
136  _strain_indices.resize(3);
137 
138  this->_strain_indices[0] = postprocessing.register_quantity("strain_xx");
139 
140  this->_strain_indices[1] = postprocessing.register_quantity("strain_xy");
141 
142  this->_strain_indices[2] = postprocessing.register_quantity("strain_yy");
143  }
144  else
145  {
146  std::cerr << "Error: Invalue output_vars value for "+elastic_membrane << std::endl
147  << " Found " << name << std::endl
148  << " Acceptable values are: stress" << std::endl
149  << " strain" << std::endl;
150  libmesh_error();
151  }
152  }
153  }
154 
155  return;
156  }
157 
158  template<typename StressStrainLaw>
160  AssemblyContext& context,
161  CachedValues& /*cache*/ )
162  {
163  const unsigned int n_u_dofs = context.get_dof_indices(_disp_vars.u_var()).size();
164 
165  const std::vector<libMesh::Real> &JxW =
166  this->get_fe(context)->get_JxW();
167 
168  // Residuals that we're populating
169  libMesh::DenseSubVector<libMesh::Number> &Fu = context.get_elem_residual(_disp_vars.u_var());
170  libMesh::DenseSubVector<libMesh::Number> &Fv = context.get_elem_residual(_disp_vars.v_var());
171  libMesh::DenseSubVector<libMesh::Number> &Fw = context.get_elem_residual(_disp_vars.w_var());
172 
173  libMesh::DenseSubMatrix<libMesh::Number>& Kuu = context.get_elem_jacobian(_disp_vars.u_var(),_disp_vars.u_var());
174  libMesh::DenseSubMatrix<libMesh::Number>& Kuv = context.get_elem_jacobian(_disp_vars.u_var(),_disp_vars.v_var());
175  libMesh::DenseSubMatrix<libMesh::Number>& Kuw = context.get_elem_jacobian(_disp_vars.u_var(),_disp_vars.w_var());
176 
177  libMesh::DenseSubMatrix<libMesh::Number>& Kvu = context.get_elem_jacobian(_disp_vars.v_var(),_disp_vars.u_var());
178  libMesh::DenseSubMatrix<libMesh::Number>& Kvv = context.get_elem_jacobian(_disp_vars.v_var(),_disp_vars.v_var());
179  libMesh::DenseSubMatrix<libMesh::Number>& Kvw = context.get_elem_jacobian(_disp_vars.v_var(),_disp_vars.w_var());
180 
181  libMesh::DenseSubMatrix<libMesh::Number>& Kwu = context.get_elem_jacobian(_disp_vars.w_var(),_disp_vars.u_var());
182  libMesh::DenseSubMatrix<libMesh::Number>& Kwv = context.get_elem_jacobian(_disp_vars.w_var(),_disp_vars.v_var());
183  libMesh::DenseSubMatrix<libMesh::Number>& Kww = context.get_elem_jacobian(_disp_vars.w_var(),_disp_vars.w_var());
184 
185  unsigned int n_qpoints = context.get_element_qrule().n_points();
186 
187  // All shape function gradients are w.r.t. master element coordinates
188  const std::vector<std::vector<libMesh::Real> >& dphi_dxi =
189  this->get_fe(context)->get_dphidxi();
190 
191  const std::vector<std::vector<libMesh::Real> >& dphi_deta =
192  this->get_fe(context)->get_dphideta();
193 
194  const libMesh::DenseSubVector<libMesh::Number>& u_coeffs = context.get_elem_solution( _disp_vars.u_var() );
195  const libMesh::DenseSubVector<libMesh::Number>& v_coeffs = context.get_elem_solution( _disp_vars.v_var() );
196  const libMesh::DenseSubVector<libMesh::Number>& w_coeffs = context.get_elem_solution( _disp_vars.w_var() );
197 
198  // Need these to build up the covariant and contravariant metric tensors
199  const std::vector<libMesh::RealGradient>& dxdxi = this->get_fe(context)->get_dxyzdxi();
200  const std::vector<libMesh::RealGradient>& dxdeta = this->get_fe(context)->get_dxyzdeta();
201 
202  const unsigned int dim = 2; // The manifold dimension is always 2 for this physics
203 
204  for (unsigned int qp=0; qp != n_qpoints; qp++)
205  {
206  // Gradients are w.r.t. master element coordinates
207  libMesh::Gradient grad_u, grad_v, grad_w;
208  for( unsigned int d = 0; d < n_u_dofs; d++ )
209  {
210  libMesh::RealGradient u_gradphi( dphi_dxi[d][qp], dphi_deta[d][qp] );
211  grad_u += u_coeffs(d)*u_gradphi;
212  grad_v += v_coeffs(d)*u_gradphi;
213  grad_w += w_coeffs(d)*u_gradphi;
214  }
215 
216  libMesh::RealGradient grad_x( dxdxi[qp](0), dxdeta[qp](0) );
217  libMesh::RealGradient grad_y( dxdxi[qp](1), dxdeta[qp](1) );
218  libMesh::RealGradient grad_z( dxdxi[qp](2), dxdeta[qp](2) );
219 
220 
221  libMesh::TensorValue<libMesh::Real> a_cov, a_contra, A_cov, A_contra;
222  libMesh::Real lambda_sq = 0;
223 
224  this->compute_metric_tensors( qp, *(this->get_fe(context)), context,
225  grad_u, grad_v, grad_w,
226  a_cov, a_contra, A_cov, A_contra,
227  lambda_sq );
228 
229  // Compute stress and elasticity tensors
232  _stress_strain_law.compute_stress_and_elasticity(dim,a_contra,a_cov,A_contra,A_cov,tau,C);
233 
234  libMesh::Real jac = JxW[qp];
235 
236  for (unsigned int i=0; i != n_u_dofs; i++)
237  {
238  libMesh::RealGradient u_gradphi( dphi_dxi[i][qp], dphi_deta[i][qp] );
239 
240  for( unsigned int alpha = 0; alpha < dim; alpha++ )
241  {
242  for( unsigned int beta = 0; beta < dim; beta++ )
243  {
244  Fu(i) -= 0.5*tau(alpha,beta)*_h0*( (grad_x(beta) + grad_u(beta))*u_gradphi(alpha) +
245  (grad_x(alpha) + grad_u(alpha))*u_gradphi(beta) )*jac;
246 
247  Fv(i) -= 0.5*tau(alpha,beta)*_h0*( (grad_y(beta) + grad_v(beta))*u_gradphi(alpha) +
248  (grad_y(alpha) + grad_v(alpha))*u_gradphi(beta) )*jac;
249 
250  Fw(i) -= 0.5*tau(alpha,beta)*_h0*( (grad_z(beta) + grad_w(beta))*u_gradphi(alpha) +
251  (grad_z(alpha) + grad_w(alpha))*u_gradphi(beta) )*jac;
252  }
253  }
254  }
255 
256  if( compute_jacobian )
257  {
258  for (unsigned int i=0; i != n_u_dofs; i++)
259  {
260  libMesh::RealGradient u_gradphi_i( dphi_dxi[i][qp], dphi_deta[i][qp] );
261 
262  for (unsigned int j=0; j != n_u_dofs; j++)
263  {
264  libMesh::RealGradient u_gradphi_j( dphi_dxi[j][qp], dphi_deta[j][qp] );
265 
266  for( unsigned int alpha = 0; alpha < dim; alpha++ )
267  {
268  for( unsigned int beta = 0; beta < dim; beta++ )
269  {
270  const libMesh::Real diag_term = 0.5*_h0*jac*tau(alpha,beta)*( u_gradphi_j(beta)*u_gradphi_i(alpha) +
271  u_gradphi_j(alpha)*u_gradphi_i(beta) );
272  Kuu(i,j) -= diag_term;
273 
274  Kvv(i,j) -= diag_term;
275 
276  Kww(i,j) -= diag_term;
277 
278  for( unsigned int lambda = 0; lambda < dim; lambda++ )
279  {
280  for( unsigned int mu = 0; mu < dim; mu++ )
281  {
282  const libMesh::Real dgamma_du = 0.5*( u_gradphi_j(lambda)*(grad_x(mu)+grad_u(mu)) +
283  (grad_x(lambda)+grad_u(lambda))*u_gradphi_j(mu) );
284 
285  const libMesh::Real dgamma_dv = 0.5*( u_gradphi_j(lambda)*(grad_y(mu)+grad_v(mu)) +
286  (grad_y(lambda)+grad_v(lambda))*u_gradphi_j(mu) );
287 
288  const libMesh::Real dgamma_dw = 0.5*( u_gradphi_j(lambda)*(grad_z(mu)+grad_w(mu)) +
289  (grad_z(lambda)+grad_w(lambda))*u_gradphi_j(mu) );
290 
291  const libMesh::Real C1 = 0.5*_h0*jac*C(alpha,beta,lambda,mu);
292 
293  const libMesh::Real x_term = C1*( (grad_x(beta)+grad_u(beta))*u_gradphi_i(alpha) +
294  (grad_x(alpha)+grad_u(alpha))*u_gradphi_i(beta) );
295 
296  const libMesh::Real y_term = C1*( (grad_y(beta)+grad_v(beta))*u_gradphi_i(alpha) +
297  (grad_y(alpha)+grad_v(alpha))*u_gradphi_i(beta) );
298 
299  const libMesh::Real z_term = C1*( (grad_z(beta)+grad_w(beta))*u_gradphi_i(alpha) +
300  (grad_z(alpha)+grad_w(alpha))*u_gradphi_i(beta) );
301 
302  Kuu(i,j) -= x_term*dgamma_du;
303 
304  Kuv(i,j) -= x_term*dgamma_dv;
305 
306  Kuw(i,j) -= x_term*dgamma_dw;
307 
308  Kvu(i,j) -= y_term*dgamma_du;
309 
310  Kvv(i,j) -= y_term*dgamma_dv;
311 
312  Kvw(i,j) -= y_term*dgamma_dw;
313 
314  Kwu(i,j) -= z_term*dgamma_du;
315 
316  Kwv(i,j) -= z_term*dgamma_dv;
317 
318  Kww(i,j) -= z_term*dgamma_dw;
319  }
320  }
321  }
322  }
323  }
324  }
325  }
326 
327  }
328 
329  return;
330  }
331 
332  template<typename StressStrainLaw>
334  AssemblyContext& context,
335  CachedValues& /*cache*/ )
336  {
337  // Only compute the constraint is tracking lambda_sq as an independent variable
338  if( _is_compressible )
339  {
340  unsigned int n_qpoints = context.get_element_qrule().n_points();
341 
342  const unsigned int n_u_dofs = context.get_dof_indices(_disp_vars.u_var()).size();
343 
344  const std::vector<libMesh::Real> &JxW = context.get_element_fe(this->_lambda_sq_var)->get_JxW();
345 
346  libMesh::DenseSubVector<libMesh::Number>& Fl = context.get_elem_residual(this->_lambda_sq_var);
347 
348  const std::vector<std::vector<libMesh::Real> >& phi =
349  context.get_element_fe(this->_lambda_sq_var)->get_phi();
350 
351  const unsigned int n_lambda_sq_dofs = context.get_dof_indices(this->_lambda_sq_var).size();
352 
353  const libMesh::DenseSubVector<libMesh::Number>& u_coeffs = context.get_elem_solution( _disp_vars.u_var() );
354  const libMesh::DenseSubVector<libMesh::Number>& v_coeffs = context.get_elem_solution( _disp_vars.v_var() );
355  const libMesh::DenseSubVector<libMesh::Number>& w_coeffs = context.get_elem_solution( _disp_vars.w_var() );
356 
357  // All shape function gradients are w.r.t. master element coordinates
358  const std::vector<std::vector<libMesh::Real> >& dphi_dxi =
359  this->get_fe(context)->get_dphidxi();
360 
361  const std::vector<std::vector<libMesh::Real> >& dphi_deta =
362  this->get_fe(context)->get_dphideta();
363 
364  for (unsigned int qp=0; qp != n_qpoints; qp++)
365  {
366  libMesh::Real jac = JxW[qp];
367 
368  libMesh::Gradient grad_u, grad_v, grad_w;
369  for( unsigned int d = 0; d < n_u_dofs; d++ )
370  {
371  libMesh::RealGradient u_gradphi( dphi_dxi[d][qp], dphi_deta[d][qp] );
372  grad_u += u_coeffs(d)*u_gradphi;
373  grad_v += v_coeffs(d)*u_gradphi;
374  grad_w += w_coeffs(d)*u_gradphi;
375  }
376 
377  libMesh::TensorValue<libMesh::Real> a_cov, a_contra, A_cov, A_contra;
378  libMesh::Real lambda_sq = 0;
379 
380  this->compute_metric_tensors( qp, *(this->get_fe(context)), context,
381  grad_u, grad_v, grad_w,
382  a_cov, a_contra, A_cov, A_contra,
383  lambda_sq );
384 
385  libMesh::Real stress_33 = _stress_strain_law.compute_33_stress( a_contra, a_cov, A_contra, A_cov );
386 
387  for (unsigned int i=0; i != n_lambda_sq_dofs; i++)
388  {
389  Fl(i) += stress_33*phi[i][qp]*jac;
390  }
391 
392  if( compute_jacobian )
393  {
394  libmesh_not_implemented();
395  }
396  }
397  } // is_compressible
398 
399  return;
400  }
401 
402  template<typename StressStrainLaw>
404  AssemblyContext& /*context*/,
405  CachedValues& /*cache*/ )
406  {
407  /*
408  std::vector<BoundaryID> ids = context.side_boundary_ids();
409 
410  for( std::vector<BoundaryID>::const_iterator it = ids.begin();
411  it != ids.end(); it++ )
412  {
413  libmesh_assert (*it != libMesh::BoundaryInfo::invalid_id);
414 
415  _bc_handler->apply_neumann_bcs( context, cache, compute_jacobian, *it );
416  }
417  */
418 
419  return;
420  }
421 
422  template<typename StressStrainLaw>
423  void ElasticMembrane<StressStrainLaw>::mass_residual( bool /*compute_jacobian*/,
424  AssemblyContext& /*context*/,
425  CachedValues& /*cache*/ )
426  {
427  libmesh_not_implemented();
428  return;
429  }
430 
431  template<typename StressStrainLaw>
433  const AssemblyContext& context,
434  const libMesh::Point& point,
435  libMesh::Real& value )
436  {
437  bool is_stress = false;
438  if( !_stress_indices.empty() )
439  is_stress= ( _stress_indices[0] == quantity_index ||
440  _stress_indices[1] == quantity_index ||
441  _stress_indices[2] == quantity_index ||
442  _stress_indices[3] == quantity_index ||
443  _stress_indices[4] == quantity_index ||
444  _stress_indices[5] == quantity_index ||
445  _stress_indices[6] == quantity_index ||
446  _stress_zz_index == quantity_index );
447 
448  bool is_strain = false;
449  if( !_strain_indices.empty() )
450  is_strain = ( _strain_indices[0] == quantity_index ||
451  _strain_indices[1] == quantity_index ||
452  _strain_indices[2] == quantity_index );
453 
454  if( is_stress || is_strain )
455  {
456  const unsigned int n_u_dofs = context.get_dof_indices(_disp_vars.u_var()).size();
457 
458  const libMesh::DenseSubVector<libMesh::Number>& u_coeffs = context.get_elem_solution( _disp_vars.u_var() );
459  const libMesh::DenseSubVector<libMesh::Number>& v_coeffs = context.get_elem_solution( _disp_vars.v_var() );
460  const libMesh::DenseSubVector<libMesh::Number>& w_coeffs = context.get_elem_solution( _disp_vars.w_var() );
461 
462  // Build new FE for the current point. We need this to build tensors at point.
463  libMesh::AutoPtr<libMesh::FEGenericBase<libMesh::Real> > fe_new =
464  this->build_new_fe( context.get_elem(), this->get_fe(context),
465  point );
466 
467  const std::vector<std::vector<libMesh::Real> >& dphi_dxi =
468  fe_new->get_dphidxi();
469 
470  const std::vector<std::vector<libMesh::Real> >& dphi_deta =
471  fe_new->get_dphideta();
472 
473  // Need these to build up the covariant and contravariant metric tensors
474  const std::vector<libMesh::RealGradient>& dxdxi = fe_new->get_dxyzdxi();
475  const std::vector<libMesh::RealGradient>& dxdeta = fe_new->get_dxyzdeta();
476 
477  // Gradients are w.r.t. master element coordinates
478  libMesh::Gradient grad_u, grad_v, grad_w;
479  for( unsigned int d = 0; d < n_u_dofs; d++ )
480  {
481  libMesh::RealGradient u_gradphi( dphi_dxi[d][0], dphi_deta[d][0] );
482  grad_u += u_coeffs(d)*u_gradphi;
483  grad_v += v_coeffs(d)*u_gradphi;
484  grad_w += w_coeffs(d)*u_gradphi;
485  }
486 
487  libMesh::RealGradient grad_x( dxdxi[0](0), dxdeta[0](0) );
488  libMesh::RealGradient grad_y( dxdxi[0](1), dxdeta[0](1) );
489  libMesh::RealGradient grad_z( dxdxi[0](2), dxdeta[0](2) );
490 
491  libMesh::TensorValue<libMesh::Real> a_cov, a_contra, A_cov, A_contra;
492  libMesh::Real lambda_sq = 0;
493 
494  // We're only computing one point at a time, so qp = 0 always
495  this->compute_metric_tensors(0, *fe_new, context, grad_u, grad_v, grad_w,
496  a_cov, a_contra, A_cov, A_contra, lambda_sq );
497 
498  // We have everything we need for strain now, so check if we are computing strain
499  if( is_strain )
500  {
501  if( _strain_indices[0] == quantity_index )
502  {
503  value = 0.5*(A_cov(0,0) - a_cov(0,0));
504  }
505  else if( _strain_indices[1] == quantity_index )
506  {
507  value = 0.5*(A_cov(0,1) - a_cov(0,1));
508  }
509  else if( _strain_indices[2] == quantity_index )
510  {
511  value = 0.5*(A_cov(1,1) - a_cov(1,1));
512  }
513  else
514  {
515  //Wat?!
516  libmesh_error();
517  }
518  return;
519  }
520 
521  if( is_stress )
522  {
523  libMesh::Real det_a = a_cov(0,0)*a_cov(1,1) - a_cov(0,1)*a_cov(1,0);
524  libMesh::Real det_A = A_cov(0,0)*A_cov(1,1) - A_cov(0,1)*A_cov(1,0);
525 
526  libMesh::Real I3 = lambda_sq*det_A/det_a;
527 
529  _stress_strain_law.compute_stress(2,a_contra,a_cov,A_contra,A_cov,tau);
530 
531  if( _stress_indices[0] == quantity_index )
532  {
533  // Need to convert to Cauchy stress
534  value = tau(0,0)/std::sqrt(I3);
535  }
536  else if( _stress_indices[1] == quantity_index )
537  {
538  // Need to convert to Cauchy stress
539  value = tau(0,1)/std::sqrt(I3);
540  }
541  else if( _stress_indices[2] == quantity_index )
542  {
543  // Need to convert to Cauchy stress
544  value = tau(1,1)/std::sqrt(I3);
545  }
546  else if( _stress_indices[3] == quantity_index )
547  {
548  value = 0.5*(tau(0,0) + tau(1,1)) + std::sqrt(0.25*(tau(0,0)-tau(1,1))*(tau(0,0)-tau(1,1))
549  + tau(0,1)*tau(0,1) );
550  }
551  else if( _stress_indices[4] == quantity_index ||
552  _stress_indices[5] == quantity_index ||
553  _stress_indices[6] == quantity_index )
554  {
555  if(_is_compressible)
556  {
557  tau(2,2) = _stress_strain_law.compute_33_stress( a_contra, a_cov, A_contra, A_cov );
558  }
559 
560  libMesh::Real stress_I1 = tau(0,0) + tau(1,1) + tau(2,2);
561  libMesh::Real stress_I2 = 0.5*(stress_I1*stress_I1 - (tau(0,0)*tau(0,0) + tau(1,1)*tau(1,1)
562  + tau(2,2)*tau(2,2) + tau(0,1)*tau(0,1)
563  + tau(1,0)*tau(1,0)) );
564 
565  libMesh::Real stress_I3 = tau(2,2)*( tau(0,0)*tau(1,1) - tau(1,0)*tau(0,1) );
566 
567  /* Formulae for principal stresses from:
568  http://en.wikiversity.org/wiki/Principal_stresses */
569 
570  // I_2^2 - 3*I_2
571  libMesh::Real C1 = (stress_I1*stress_I1 - 3*stress_I2);
572 
573  // 2*I_1^3 - 9*I_1*_I2 + 27*I_3
574  libMesh::Real C2 = (2*stress_I1*stress_I1*stress_I1 - 9*stress_I1*stress_I2 + 27*stress_I3)/54;
575 
576  libMesh::Real theta = std::acos( C2/(2*std::sqrt(C1*C1*C1)) )/3.0;
577 
578  if( _stress_indices[4] == quantity_index )
579  {
580  value = (stress_I1 + 2.0*std::sqrt(C1)*std::cos(theta))/3.0;
581  }
582 
583  if( _stress_indices[5] == quantity_index )
584  {
585  value = (stress_I1 + 2.0*std::sqrt(C1)*std::cos(theta+Constants::two_pi/3.0))/3.0;
586  }
587 
588  if( _stress_indices[6] == quantity_index )
589  {
590  value = (stress_I1 + 2.0*std::sqrt(C1)*std::cos(theta+2.0*Constants::two_pi/3.0))/3.0;
591  }
592  }
593  else if( _stress_zz_index == quantity_index )
594  {
595  value = _stress_strain_law.compute_33_stress( a_contra, a_cov, A_contra, A_cov );
596  }
597  else
598  {
599  //Wat?!
600  libmesh_error();
601  }
602  } // is_stress
603 
604  }
605 
606  return;
607  }
608 
609  template<typename StressStrainLaw>
610  libMesh::AutoPtr<libMesh::FEGenericBase<libMesh::Real> > ElasticMembrane<StressStrainLaw>::build_new_fe( const libMesh::Elem& elem,
611  const libMesh::FEGenericBase<libMesh::Real>* fe,
612  const libMesh::Point p )
613  {
614  using namespace libMesh;
615  FEType fe_type = fe->get_fe_type();
616 
617  // If we don't have an Elem to evaluate on, then the only functions
618  // we can sensibly evaluate are the scalar dofs which are the same
619  // everywhere.
620  libmesh_assert(&elem || fe_type.family == SCALAR);
621 
622  unsigned int elem_dim = &elem ? elem.dim() : 0;
623 
624  AutoPtr<FEGenericBase<libMesh::Real> >
625  fe_new(FEGenericBase<libMesh::Real>::build(elem_dim, fe_type));
626 
627  // Map the physical co-ordinates to the master co-ordinates using the inverse_map from fe_interface.h
628  // Build a vector of point co-ordinates to send to reinit
629  Point master_point = &elem ?
630  FEInterface::inverse_map(elem_dim, fe_type, &elem, p) :
631  Point(0);
632 
633  std::vector<Point> coor(1, master_point);
634 
635  // Reinitialize the element and compute the shape function values at coor
636  fe_new->reinit (&elem, &coor);
637 
638  return fe_new;
639  }
640 
641  template<typename StressStrainLaw>
643  const libMesh::FEBase& elem,
644  const AssemblyContext& context,
645  const libMesh::Gradient& grad_u,
646  const libMesh::Gradient& grad_v,
647  const libMesh::Gradient& grad_w,
652  libMesh::Real& lambda_sq )
653  {
654  const std::vector<libMesh::RealGradient>& dxdxi = elem.get_dxyzdxi();
655  const std::vector<libMesh::RealGradient>& dxdeta = elem.get_dxyzdeta();
656 
657  const std::vector<libMesh::Real>& dxidx = elem.get_dxidx();
658  const std::vector<libMesh::Real>& dxidy = elem.get_dxidy();
659  const std::vector<libMesh::Real>& dxidz = elem.get_dxidz();
660 
661  const std::vector<libMesh::Real>& detadx = elem.get_detadx();
662  const std::vector<libMesh::Real>& detady = elem.get_detady();
663  const std::vector<libMesh::Real>& detadz = elem.get_detadz();
664 
665  libMesh::RealGradient dxi( dxidx[qp], dxidy[qp], dxidz[qp] );
666  libMesh::RealGradient deta( detadx[qp], detady[qp], detadz[qp] );
667 
668  libMesh::RealGradient dudxi( grad_u(0), grad_v(0), grad_w(0) );
669  libMesh::RealGradient dudeta( grad_u(1), grad_v(1), grad_w(1) );
670 
671  // Covariant metric tensor of reference configuration
672  a_cov.zero();
673  a_cov(0,0) = dxdxi[qp]*dxdxi[qp];
674  a_cov(0,1) = dxdxi[qp]*dxdeta[qp];
675  a_cov(1,0) = dxdeta[qp]*dxdxi[qp];
676  a_cov(1,1) = dxdeta[qp]*dxdeta[qp];
677 
678  libMesh::Real det_a = a_cov(0,0)*a_cov(1,1) - a_cov(0,1)*a_cov(1,0);
679 
680  // Covariant metric tensor of current configuration
681  A_cov.zero();
682  A_cov(0,0) = (dxdxi[qp] + dudxi)*(dxdxi[qp] + dudxi);
683  A_cov(0,1) = (dxdxi[qp] + dudxi)*(dxdeta[qp] + dudeta);
684  A_cov(1,0) = (dxdeta[qp] + dudeta)*(dxdxi[qp] + dudxi);
685  A_cov(1,1) = (dxdeta[qp] + dudeta)*(dxdeta[qp] + dudeta);
686 
687  // Contravariant metric tensor of reference configuration
688  a_contra.zero();
689  a_contra(0,0) = dxi*dxi;
690  a_contra(0,1) = dxi*deta;
691  a_contra(1,0) = deta*dxi;
692  a_contra(1,1) = deta*deta;
693 
694  // Contravariant metric tensor in current configuration is A_cov^{-1}
695  libMesh::Real det_A = A_cov(0,0)*A_cov(1,1) - A_cov(0,1)*A_cov(1,0);
696 
697  A_contra.zero();
698  A_contra(0,0) = A_cov(1,1)/det_A;
699  A_contra(0,1) = -A_cov(0,1)/det_A;
700  A_contra(1,0) = -A_cov(1,0)/det_A;
701  A_contra(1,1) = A_cov(0,0)/det_A;
702 
703  a_cov(2,2) = 1.0;
704  a_contra(2,2) = 1.0;
705 
706 
707  // If the material is compressible, then lambda_sq is an independent variable
708  if( _is_compressible )
709  {
710  lambda_sq = context.interior_value(this->_lambda_sq_var, qp);
711  }
712  else
713  {
714  // If the material is incompressible, lambda^2 is known
715  lambda_sq = det_a/det_A;
716  }
717 
718  A_cov(2,2) = lambda_sq;
719  A_contra(2,2) = 1.0/lambda_sq;
720 
721  return;
722  }
723 
724 } // end namespace GRINS
virtual void set_parameter(libMesh::Number &param_variable, const GetPot &input, const std::string &param_name, libMesh::Number param_default)
Each subclass can simultaneously read a parameter value from.
unsigned int register_quantity(std::string name)
Register quantity to be postprocessed.
GRINS::ICHandlingBase * _ic_handler
Definition: physics.h:258
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...
Base class for reading and handling initial conditions for physics classes.
void compute_metric_tensors(unsigned int qp, const libMesh::FEBase &elem, const AssemblyContext &context, const libMesh::Gradient &grad_u, const libMesh::Gradient &grad_v, const libMesh::Gradient &grad_w, libMesh::TensorValue< libMesh::Real > &a_cov, libMesh::TensorValue< libMesh::Real > &a_contra, libMesh::TensorValue< libMesh::Real > &A_cov, libMesh::TensorValue< libMesh::Real > &A_contra, libMesh::Real &lambda_sq)
virtual void element_constraint(bool compute_jacobian, AssemblyContext &context, CachedValues &cache)
Constraint part(s) of physics for element interiors.
GRINS namespace.
const PhysicsName elastic_membrane
virtual void init_variables(libMesh::FEMSystem *system)
Initialize variables for this physics.
virtual void element_time_derivative(bool compute_jacobian, AssemblyContext &context, CachedValues &cache)
Time dependent part(s) of physics for element interiors.
virtual void register_postprocessing_vars(const GetPot &input, PostProcessedQuantities< libMesh::Real > &postprocessing)
Register postprocessing variables for ElasticMembrane.
std::string PhysicsName
virtual void compute_postprocessed_quantity(unsigned int quantity_index, const AssemblyContext &context, const libMesh::Point &point, libMesh::Real &value)
Compute the registered postprocessed quantities.
virtual void init_variables(libMesh::FEMSystem *system)
Initialize variables for this physics.
const libMesh::Real two_pi
libMesh::AutoPtr< libMesh::FEGenericBase< libMesh::Real > > build_new_fe(const libMesh::Elem &elem, const libMesh::FEGenericBase< libMesh::Real > *fe, const libMesh::Point p)
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.

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