GRINS-0.7.0
elastic_cable.C
Go to the documentation of this file.
1 //-----------------------------------------------------------------------bl-
2 //--------------------------------------------------------------------------
3 //
4 // GRINS - General Reacting Incompressible Navier-Stokes
5 //
6 // Copyright (C) 2014-2016 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_cable.h"
27 
28 // GRINS
29 #include "grins_config.h"
33 
34 // libMesh
35 #include "libmesh/getpot.h"
36 #include "libmesh/quadrature.h"
37 #include "libmesh/boundary_info.h"
38 #include "libmesh/fem_system.h"
39 #include "libmesh/elem.h"
40 
41 namespace GRINS
42 {
43  template<typename StressStrainLaw>
44  ElasticCable<StressStrainLaw>::ElasticCable( const PhysicsName& physics_name, const GetPot& input,
45  bool is_compressible )
46  : ElasticCableBase<StressStrainLaw>(physics_name,input,is_compressible)
47  {
48  this->_ic_handler = new GenericICHandler(physics_name, input);
49  }
50 
51  template<typename StressStrainLaw>
54  {
55  std::string section = "Physics/"+PhysicsNaming::elastic_cable()+"/output_vars";
56 
57  if( input.have_variable(section) )
58  {
59  unsigned int n_vars = input.vector_variable_size(section);
60 
61  for( unsigned int v = 0; v < n_vars; v++ )
62  {
63  std::string name = input(section,"DIE!",v);
64 
65  if( name == std::string("stress") )
66  {
67  // sigma_xx only, i.e., locally normal to the cutting plane
68  // sigma_yy=sigma_zz = 0 by assumption of this Physics
69  _stress_indices.resize(1);
70 
71  this->_stress_indices[0] = postprocessing.register_quantity("cable_stress");
72 
73  }
74  else if( name == std::string("strain") )
75  {
76  // eps_xx only, i.e., locally normal to the cutting plane
77  // eps_yy=eps_zz = 0 by assumption of this Physics
78  _strain_indices.resize(1);
79 
80  this->_strain_indices[0] = postprocessing.register_quantity("cable_strain");
81 
82  }
83  else if( name == std::string("force") )
84  {
85  // force_x only, i.e., locally normal to the cutting plane
86  // force_y=force_z=0 by assumption of this Physics
87  _force_indices.resize(1);
88 
89  this->_force_indices[0] = postprocessing.register_quantity("cable_force");
90 
91  }
92  else
93  {
94  std::cerr << "Error: Invalue output_vars value for "+PhysicsNaming::elastic_cable() << std::endl
95  << " Found " << name << std::endl
96  << " Acceptable values are: stress" << std::endl
97  << " strain" << std::endl
98  << " force " << std::endl;
99  libmesh_error();
100  }
101  }
102  }
103  return;
104  }
105 
106  template<typename StressStrainLaw>
108  const AssemblyContext& context,
109  const libMesh::Point& point,
110  libMesh::Real& value )
111  {
112  bool is_strain = false;
113  if( !_strain_indices.empty() )
114  is_strain = ( _strain_indices[0] == quantity_index );
115 
116  bool is_stress = false;
117  if( !_stress_indices.empty() )
118  is_stress = ( _stress_indices[0] == quantity_index );
119 
120  bool is_force = false;
121  if( !_force_indices.empty() )
122  is_force = ( _force_indices[0] == quantity_index );
123 
124  if( is_strain || is_stress || is_force )
125  {
126  const unsigned int n_u_dofs = context.get_dof_indices(this->_disp_vars.u()).size();
127 
128  const libMesh::DenseSubVector<libMesh::Number>& u_coeffs = context.get_elem_solution( this->_disp_vars.u() );
129  const libMesh::DenseSubVector<libMesh::Number>& v_coeffs = context.get_elem_solution( this->_disp_vars.v() );
130  const libMesh::DenseSubVector<libMesh::Number>& w_coeffs = context.get_elem_solution( this->_disp_vars.w() );
131 
132  // Build new FE for the current point. We need this to build tensors at point.
133  libMesh::UniquePtr<libMesh::FEGenericBase<libMesh::Real> > fe_new = this->build_new_fe( &context.get_elem(), this->get_fe(context), point );
134 
135  const std::vector<std::vector<libMesh::Real> >& dphi_dxi = fe_new->get_dphidxi();
136 
137  // Need these to build up the covariant and contravariant metric tensors
138  const std::vector<libMesh::RealGradient>& dxdxi = fe_new->get_dxyzdxi();
139 
140  // Gradients are w.r.t. master element coordinates
141  libMesh::Gradient grad_u, grad_v, grad_w;
142  for( unsigned int d = 0; d < n_u_dofs; d++ )
143  {
144  libMesh::RealGradient u_gradphi( dphi_dxi[d][0] );
145  grad_u += u_coeffs(d)*u_gradphi;
146  grad_v += v_coeffs(d)*u_gradphi;
147  grad_w += w_coeffs(d)*u_gradphi;
148  }
149 
150  libMesh::RealGradient grad_x( dxdxi[0](0) );
151  libMesh::RealGradient grad_y( dxdxi[0](1) );
152  libMesh::RealGradient grad_z( dxdxi[0](2) );
153 
154  libMesh::TensorValue<libMesh::Real> a_cov, a_contra, A_cov, A_contra;
155  libMesh::Real lambda_sq = 0;
156 
157  this->compute_metric_tensors(0, *fe_new, context, grad_u, grad_v, grad_w, a_cov, a_contra, A_cov, A_contra, lambda_sq );
158 
159  libMesh::Real det_a = a_cov(0,0)*a_cov(1,1) - a_cov(0,1)*a_cov(1,0);
160  libMesh::Real det_A = A_cov(0,0)*A_cov(1,1) - A_cov(0,1)*A_cov(1,0);
161 
162  libMesh::Real I3 = lambda_sq*det_A/det_a;
163 
165  this->_stress_strain_law.compute_stress(1,a_contra,a_cov,A_contra,A_cov,tau);
166 
167  // We have everything we need for strain now, so check if we are computing strain
168  if( is_strain )
169  {
170  if( _strain_indices[0] == quantity_index )
171  {
172  value = 0.5*(A_cov(0,0) - a_cov(0,0));
173  }
174  else
175  {
176  //Wat?!
177  libmesh_error();
178  }
179  return;
180  }
181 
182  if( is_stress )
183  {
184  if( _stress_indices[0] == quantity_index )
185  {
186  // Need to convert to Cauchy stress
187  value = tau(0,0)/std::sqrt(I3);
188  }
189  else
190  {
191  libmesh_error();
192  }
193  }
194  if( is_force )
195  {
196 
197  if( _force_indices[0] == quantity_index )
198  {
199  //This force is in deformed configuration and will be significantly influenced by large strains
200  value = tau(0,0)/std::sqrt(I3)*this->_A;
201  }
202  else
203  {
204  libmesh_error();
205  }
206  }
207  }
208  }
209 
210  template<typename StressStrainLaw>
212  AssemblyContext& context,
213  CachedValues& /*cache*/)
214  {
215  const unsigned int n_u_dofs = context.get_dof_indices(this->_disp_vars.u()).size();
216 
217  const std::vector<libMesh::Real> &JxW =
218  this->get_fe(context)->get_JxW();
219 
220  // Residuals that we're populating
221  libMesh::DenseSubVector<libMesh::Number> &Fu = context.get_elem_residual(this->_disp_vars.u());
222  libMesh::DenseSubVector<libMesh::Number> &Fv = context.get_elem_residual(this->_disp_vars.v());
223  libMesh::DenseSubVector<libMesh::Number> &Fw = context.get_elem_residual(this->_disp_vars.w());
224 
225  //Grab the Jacobian matrix as submatrices
226  //libMesh::DenseMatrix<libMesh::Number> &K = context.get_elem_jacobian();
227  libMesh::DenseSubMatrix<libMesh::Number> &Kuu = context.get_elem_jacobian(this->_disp_vars.u(),this->_disp_vars.u());
228  libMesh::DenseSubMatrix<libMesh::Number> &Kuv = context.get_elem_jacobian(this->_disp_vars.u(),this->_disp_vars.v());
229  libMesh::DenseSubMatrix<libMesh::Number> &Kuw = context.get_elem_jacobian(this->_disp_vars.u(),this->_disp_vars.w());
230  libMesh::DenseSubMatrix<libMesh::Number> &Kvu = context.get_elem_jacobian(this->_disp_vars.v(),this->_disp_vars.u());
231  libMesh::DenseSubMatrix<libMesh::Number> &Kvv = context.get_elem_jacobian(this->_disp_vars.v(),this->_disp_vars.v());
232  libMesh::DenseSubMatrix<libMesh::Number> &Kvw = context.get_elem_jacobian(this->_disp_vars.v(),this->_disp_vars.w());
233  libMesh::DenseSubMatrix<libMesh::Number> &Kwu = context.get_elem_jacobian(this->_disp_vars.w(),this->_disp_vars.u());
234  libMesh::DenseSubMatrix<libMesh::Number> &Kwv = context.get_elem_jacobian(this->_disp_vars.w(),this->_disp_vars.v());
235  libMesh::DenseSubMatrix<libMesh::Number> &Kww = context.get_elem_jacobian(this->_disp_vars.w(),this->_disp_vars.w());
236 
237 
238  unsigned int n_qpoints = context.get_element_qrule().n_points();
239 
240  // All shape function gradients are w.r.t. master element coordinates
241  const std::vector<std::vector<libMesh::Real> >& dphi_dxi = this->get_fe(context)->get_dphidxi();
242 
243  const libMesh::DenseSubVector<libMesh::Number>& u_coeffs = context.get_elem_solution( this->_disp_vars.u() );
244  const libMesh::DenseSubVector<libMesh::Number>& v_coeffs = context.get_elem_solution( this->_disp_vars.v() );
245  const libMesh::DenseSubVector<libMesh::Number>& w_coeffs = context.get_elem_solution( this->_disp_vars.w() );
246 
247  // Need these to build up the covariant and contravariant metric tensors
248  const std::vector<libMesh::RealGradient>& dxdxi = this->get_fe(context)->get_dxyzdxi();
249 
250  const unsigned int dim = 1; // The cable dimension is always 1 for this physics
251 
252  for (unsigned int qp=0; qp != n_qpoints; qp++)
253  {
254  // Gradients are w.r.t. master element coordinates
255  libMesh::Gradient grad_u, grad_v, grad_w;
256 
257  for( unsigned int d = 0; d < n_u_dofs; d++ )
258  {
259  libMesh::RealGradient u_gradphi( dphi_dxi[d][qp] );
260  grad_u += u_coeffs(d)*u_gradphi;
261  grad_v += v_coeffs(d)*u_gradphi;
262  grad_w += w_coeffs(d)*u_gradphi;
263  }
264 
265  libMesh::RealGradient grad_x( dxdxi[qp](0) );
266  libMesh::RealGradient grad_y( dxdxi[qp](1) );
267  libMesh::RealGradient grad_z( dxdxi[qp](2) );
268 
269  libMesh::TensorValue<libMesh::Real> a_cov, a_contra, A_cov, A_contra;
270  libMesh::Real lambda_sq = 0;
271 
272  this->compute_metric_tensors( qp, *(this->get_fe(context)), context,
273  grad_u, grad_v, grad_w,
274  a_cov, a_contra, A_cov, A_contra,
275  lambda_sq );
276 
277  // Compute stress tensor
280  this->_stress_strain_law.compute_stress_and_elasticity(dim,a_contra,a_cov,A_contra,A_cov,tau,C);
281 
282 
283  libMesh::Real jac = JxW[qp];
284 
285  for (unsigned int i=0; i != n_u_dofs; i++)
286  {
287  libMesh::RealGradient u_gradphi( dphi_dxi[i][qp] );
288 
289  const libMesh::Real res_term = tau(0,0)*this->_A*jac*u_gradphi(0);
290 
291  Fu(i) += res_term*(grad_x(0) + grad_u(0));
292 
293  Fv(i) += res_term*(grad_y(0) + grad_v(0));
294 
295  Fw(i) += res_term*(grad_z(0) + grad_w(0));
296  }
297 
298  if( compute_jacobian )
299  {
300  for(unsigned int i=0; i != n_u_dofs; i++)
301  {
302  libMesh::RealGradient u_gradphi_I( dphi_dxi[i][qp] );
303  for(unsigned int j=0; j != n_u_dofs; j++)
304  {
305  libMesh::RealGradient u_gradphi_J( dphi_dxi[j][qp] );
306 
307  const libMesh::Real diag_term = this->_A*jac*tau(0,0)*( u_gradphi_J(0)*u_gradphi_I(0))*context.get_elem_solution_derivative();
308 
309  Kuu(i,j) += diag_term;
310 
311  Kvv(i,j) += diag_term;
312 
313  Kww(i,j) += diag_term;
314 
315  const libMesh::Real dgamma_du = ( u_gradphi_J(0)*(grad_x(0)+grad_u(0)) );
316 
317  const libMesh::Real dgamma_dv = ( u_gradphi_J(0)*(grad_y(0)+grad_v(0)) );
318 
319  const libMesh::Real dgamma_dw = ( u_gradphi_J(0)*(grad_z(0)+grad_w(0)) );
320 
321  const libMesh::Real C1 = this->_A*jac*C(0,0,0,0)*context.get_elem_solution_derivative();
322 
323  const libMesh::Real x_term = C1*( (grad_x(0)+grad_u(0))*u_gradphi_I(0) );
324 
325  const libMesh::Real y_term = C1*( (grad_y(0)+grad_v(0))*u_gradphi_I(0) );
326 
327  const libMesh::Real z_term = C1*( (grad_z(0)+grad_w(0))*u_gradphi_I(0) );
328 
329  Kuu(i,j) += x_term*dgamma_du;
330 
331  Kuv(i,j) += x_term*dgamma_dv;
332 
333  Kuw(i,j) += x_term*dgamma_dw;
334 
335  Kvu(i,j) += y_term*dgamma_du;
336 
337  Kvv(i,j) += y_term*dgamma_dv;
338 
339  Kvw(i,j) += y_term*dgamma_dw;
340 
341  Kwu(i,j) += z_term*dgamma_du;
342 
343  Kwv(i,j) += z_term*dgamma_dv;
344 
345  Kww(i,j) += z_term*dgamma_dw;
346 
347  } // end j-loop
348  } // end i-loop
349  } // end if(compute_jacobian)
350  } // end qp loop
351  }
352 
353 } // end namespace GRINS
unsigned int register_quantity(std::string name)
Register quantity to be postprocessed.
GRINS::ICHandlingBase * _ic_handler
Definition: physics.h:269
virtual void compute_postprocessed_quantity(unsigned int quantity_index, const AssemblyContext &context, const libMesh::Point &point, libMesh::Real &value)
Compute the registered postprocessed quantities.
static PhysicsName elastic_cable()
Base class for reading and handling initial conditions for physics classes.
GRINS namespace.
virtual void register_postprocessing_vars(const GetPot &input, PostProcessedQuantities< libMesh::Real > &postprocessing)
Register postprocessing variables for ElasticCable.
Definition: elastic_cable.C:52
std::string PhysicsName
virtual void element_time_derivative(bool compute_jacobian, AssemblyContext &context, CachedValues &cache)
Time dependent part(s) of physics for element interiors.

Generated on Thu Jun 2 2016 21:52:27 for GRINS-0.7.0 by  doxygen 1.8.10