https://mooseframework.inl.gov
Loading...
Searching...
No Matches
ADComputeIncrementalShellStrain.C
Go to the documentation of this file.
1//* This file is part of the MOOSE framework
2//* https://mooseframework.inl.gov
3//*
4//* All rights reserved, see COPYRIGHT for full restrictions
5//* https://github.com/idaholab/moose/blob/master/COPYRIGHT
6//*
7//* Licensed under LGPL 2.1, please see LICENSE for details
8//* https://www.gnu.org/licenses/lgpl-2.1.html
9
11#include "MooseMesh.h"
12#include "Assembly.h"
13#include "NonlinearSystem.h"
14#include "MooseVariable.h"
15#include "ArbitraryQuadrature.h"
16#include "DenseMatrix.h"
17
18#include "libmesh/quadrature.h"
19#include "libmesh/utility.h"
20#include "libmesh/enum_quadrature_type.h"
21#include "libmesh/fe_type.h"
22#include "libmesh/string_to_enum.h"
23#include "libmesh/quadrature_gauss.h"
24
26
29{
31 params.addClassDescription("Compute a small strain increment for the shell.");
33 "rotations", "The rotations appropriate for the simulation geometry and coordinate system");
35 "displacements",
36 "The displacements appropriate for the simulation geometry and coordinate system");
38 "thickness",
39 "Thickness of the shell. Can be supplied as either a number or a variable name.");
40 params.addRequiredParam<std::string>("through_thickness_order",
41 "Quadrature order in out of plane direction");
42 params.addParam<bool>(
43 "large_strain", false, "Set to true to turn on finite strain calculations.");
44 params.addParam<RealVectorValue>("reference_first_local_direction",
45 RealVectorValue(1, 0, 0),
46 "Vector that is projected onto an element to define the "
47 "direction for the first local coordinate direction e1.");
48 return params;
49}
50
52 : Material(parameters),
53 _nrot(coupledComponents("rotations")),
54 _ndisp(coupledComponents("displacements")),
55 _rot_num(_nrot),
56 _disp_num(_ndisp),
57 _thickness(coupledValue("thickness")),
58 _large_strain(getParam<bool>("large_strain")),
59 _strain_increment(),
60 _total_strain(),
61 _total_strain_old(),
62 _nonlinear_sys(_fe_problem.getNonlinearSystemBase(/*nl_sys_num=*/0)),
63 _soln_disp_index(4),
64 _soln_rot_index(4),
65 _soln_vector(20, 1),
66 _strain_vector(5, 1),
67 _nodes(4),
68 _node_normal(declareADProperty<RealVectorValue>("node_normal")),
69 _node_normal_old(getMaterialPropertyOldByName<RealVectorValue>("node_normal")),
70 _dxyz_dxi(),
71 _dxyz_deta(),
72 _dxyz_dzeta(),
73 _dxyz_dxi_old(),
74 _dxyz_deta_old(),
75 _dxyz_dzeta_old(),
76 _v1(4),
77 _v2(4),
78 _B(),
79 _B_old(),
80 _ge(),
81 _ge_old(),
82 _J_map(),
83 _J_map_old(),
84 _local_transformation_matrix(),
85 _local_transformation_matrix_old(),
86 _covariant_transformation_matrix(),
87 _covariant_transformation_matrix_old(),
88 _contravariant_transformation_matrix(),
89 _contravariant_transformation_matrix_old(),
90 _total_global_strain(),
91 _sol(_nonlinear_sys.currentSolution()),
92 _sol_old(_nonlinear_sys.solutionOld()),
93 _ref_first_local_dir(getParam<RealVectorValue>("reference_first_local_direction"))
94
95{
96 // Checking for consistency between length of the provided displacements and rotations vector
97 if (_ndisp != 3 || _nrot != 2)
99 "ADComputeIncrementalShellStrain: The number of variables supplied in 'displacements' "
100 "must be 3 and that in 'rotations' must be 2.");
101
104 "ADComputeIncrementalShellStrain: Shell element is implemented only for linear elements.");
105
106 // Checking if the size of the first local vector is within an acceptable range
107 if (MooseUtils::absoluteFuzzyEqual(_ref_first_local_dir.norm(), 0.0, 1e-3))
109 "The norm of the defined first local axis is less than the acceptable telerance (1e-3)");
110
111 // fetch coupled variables and gradients (as stateful properties if necessary)
112 for (unsigned int i = 0; i < _ndisp; ++i)
113 {
114 MooseVariable * disp_variable = getVar("displacements", i);
115 _disp_num[i] = disp_variable->number();
116
117 if (i < _nrot)
118 {
119 MooseVariable * rot_variable = getVar("rotations", i);
120 _rot_num[i] = rot_variable->number();
121 }
122 }
123
124 _t_qrule = std::make_unique<libMesh::QGauss>(
125 1, Utility::string_to_enum<Order>(getParam<std::string>("through_thickness_order")));
126 _t_points = _t_qrule->get_points();
127 _strain_increment.resize(_t_points.size());
128 _total_strain.resize(_t_points.size());
129 _total_strain_old.resize(_t_points.size());
130 _B.resize(_t_points.size());
131 _B_old.resize(_t_points.size());
132 _ge.resize(_t_points.size());
133 _ge_old.resize(_t_points.size());
134 _J_map.resize(_t_points.size());
135 _J_map_old.resize(_t_points.size());
136 _dxyz_dxi.resize(_t_points.size());
137 _dxyz_deta.resize(_t_points.size());
138 _dxyz_dzeta.resize(_t_points.size());
139 _dxyz_dxi_old.resize(_t_points.size());
140 _dxyz_deta_old.resize(_t_points.size());
141 _dxyz_dzeta_old.resize(_t_points.size());
148 _total_global_strain.resize(_t_points.size());
149
150 _transformation_matrix = &declareADProperty<RankTwoTensor>("transformation_matrix_element");
151
152 for (unsigned int i = 0; i < _t_points.size(); ++i)
153 {
155 &declareADProperty<RankTwoTensor>("strain_increment_t_points_" + std::to_string(i));
156 _total_strain[i] =
157 &declareADProperty<RankTwoTensor>("total_strain_t_points_" + std::to_string(i));
159 &getMaterialPropertyOldByName<RankTwoTensor>("total_strain_t_points_" + std::to_string(i));
160 _B[i] = &declareADProperty<DenseMatrix<Real>>("B_t_points_" + std::to_string(i));
161 _B_old[i] = &getMaterialPropertyOldByName<DenseMatrix<Real>>("B_t_points_" + std::to_string(i));
162 _ge[i] = &declareADProperty<RankTwoTensor>("ge_t_points_" + std::to_string(i));
163 _ge_old[i] = &getMaterialPropertyOldByName<RankTwoTensor>("ge_t_points_" + std::to_string(i));
164 _J_map[i] = &declareADProperty<Real>("J_mapping_t_points_" + std::to_string(i));
165 _J_map_old[i] = &getMaterialPropertyOldByName<Real>("J_mapping_t_points_" + std::to_string(i));
166 _dxyz_dxi[i] = &declareADProperty<RealVectorValue>("dxyz_dxi_t_points_" + std::to_string(i));
167 _dxyz_dxi_old[i] =
168 &getMaterialPropertyOldByName<RealVectorValue>("dxyz_dxi_t_points_" + std::to_string(i));
169 _dxyz_deta[i] = &declareADProperty<RealVectorValue>("dxyz_deta_t_points_" + std::to_string(i));
170 _dxyz_deta_old[i] =
171 &getMaterialPropertyOldByName<RealVectorValue>("dxyz_deta_t_points_" + std::to_string(i));
172 _dxyz_dzeta[i] =
173 &declareADProperty<RealVectorValue>("dxyz_dzeta_t_points_" + std::to_string(i));
174 _dxyz_dzeta_old[i] =
175 &getMaterialPropertyOldByName<RealVectorValue>("dxyz_dzeta_t_points_" + std::to_string(i));
176 // Create rotation matrix and total strain global for output purposes only
178 &declareProperty<RankTwoTensor>("local_transformation_t_points_" + std::to_string(i));
179 _local_transformation_matrix_old[i] = &getMaterialPropertyOldByName<RankTwoTensor>(
180 "local_transformation_t_points_" + std::to_string(i));
182 &declareProperty<RankTwoTensor>("covariant_transformation_t_points_" + std::to_string(i));
183 _covariant_transformation_matrix_old[i] = &getMaterialPropertyOldByName<RankTwoTensor>(
184 "covariant_transformation_t_points_" + std::to_string(i));
185 _contravariant_transformation_matrix[i] = &declareProperty<RankTwoTensor>(
186 "contravariant_transformation_t_points_" + std::to_string(i));
187 _contravariant_transformation_matrix_old[i] = &getMaterialPropertyOldByName<RankTwoTensor>(
188 "contravariant_transformation_t_points_" + std::to_string(i));
190 &declareProperty<RankTwoTensor>("total_global_strain_t_points_" + std::to_string(i));
191 }
192
193 // used later for computing local coordinate system
194 _x2(1) = 1;
195 _x3(2) = 1;
196 _e1(0) = 1;
197 _e2(1) = 1;
198 _e3(2) = 1;
199}
200
201void
203{
204 unsigned int dim = _current_elem->dim();
205 if ((dim != 2))
207 "ADComputeIncrementalShellStrain: Shell element is implemented only for 2D elements");
208 if (_current_elem->n_nodes() != 4)
209 mooseError("ADComputeIncrementalShellStrain: Shell element needs to have exactly four nodes.");
210 if (_qrule->get_points().size() != 4)
211 mooseError("ADComputeIncrementalShellStrain: Shell element needs to have exactly four "
212 "quadrature points.");
213
216}
217
218void
220{
221 // quadrature points in isoparametric space
222 _2d_points = _qrule->get_points(); // would be in 2D
223
224 // derivatives of shape functions (dphidxi, dphideta and dphidzeta) evaluated at quadrature points
225 // (in isoparametric space).
226 unsigned int dim = _current_elem->dim();
227 FEType fe_type(Utility::string_to_enum<Order>("First"),
228 Utility::string_to_enum<FEFamily>("LAGRANGE"));
229 auto & fe = _fe_problem.assembly(_tid, _nonlinear_sys.number()).getFE(fe_type, dim);
230 _dphidxi_map = fe->get_fe_map().get_dphidxi_map();
231 _dphideta_map = fe->get_fe_map().get_dphideta_map();
232 _phi_map = fe->get_fe_map().get_phi_map();
233
234 for (unsigned int i = 0; i < 4; ++i)
235 _nodes[i] = _current_elem->node_ptr(i);
236
237 for (unsigned int i = 0; i < _2d_points.size(); ++i)
238 {
239 for (unsigned int j = 0; j < _t_points.size(); ++j)
240 {
241 (*_ge[j])[i] = (*_ge_old[j])[i];
242 (*_J_map[j])[i] = (*_J_map_old[j])[i];
243 (*_dxyz_dxi[j])[i] = (*_dxyz_dxi_old[j])[i];
244 (*_dxyz_deta[j])[i] = (*_dxyz_deta_old[j])[i];
245 (*_dxyz_dzeta[j])[i] = (*_dxyz_dzeta_old[j])[i];
246 (*_B[j])[i] = (*_B_old[j])[i];
251 }
252 }
253
255
257
258 for (unsigned int i = 0; i < _2d_points.size(); ++i)
259 {
260 for (unsigned int j = 0; j < _t_points.size(); ++j)
261 {
262 // compute strain increment in covariant coordinate system using B and _soln_vector
263 for (unsigned int temp1 = 0; temp1 < 5; ++temp1)
264 {
265 _strain_vector(temp1) = 0.0;
266 for (unsigned int temp2 = 0; temp2 < 20; ++temp2)
267 _strain_vector(temp1) += (*_B[j])[i](temp1, temp2) * _soln_vector(temp2);
268 }
269 (*_strain_increment[j])[i](0, 0) = _strain_vector(0);
270 (*_strain_increment[j])[i](1, 1) = _strain_vector(1);
271 (*_strain_increment[j])[i](0, 1) = _strain_vector(2);
272 (*_strain_increment[j])[i](0, 2) = _strain_vector(3);
273 (*_strain_increment[j])[i](1, 2) = _strain_vector(4);
274 (*_strain_increment[j])[i](1, 0) = (*_strain_increment[j])[i](0, 1);
275 (*_strain_increment[j])[i](2, 0) = (*_strain_increment[j])[i](0, 2);
276 (*_strain_increment[j])[i](2, 1) = (*_strain_increment[j])[i](1, 2);
277
278 (*_total_strain[j])[i] = (*_total_strain_old[j])[i] + (*_strain_increment[j])[i];
279
280 for (unsigned int ii = 0; ii < 3; ++ii)
281 for (unsigned int jj = 0; jj < 3; ++jj)
285 (*_contravariant_transformation_matrix[j])[i].transpose();
286 }
287 }
288}
289
290void
292{
293 using std::sqrt;
294
295 // quadrature points in isoparametric space
296 _2d_points = _qrule->get_points(); // would be in 2D
297
298 unsigned int dim = _current_elem->dim();
299
300 // derivatives of shape functions (dphidxi, dphideta and dphidzeta) evaluated at quadrature points
301 // (in isoparametric space).
302 FEType fe_type(Utility::string_to_enum<Order>("First"),
303 Utility::string_to_enum<FEFamily>("LAGRANGE"));
304 auto & fe = _fe_problem.assembly(_tid, _nonlinear_sys.number()).getFE(fe_type, dim);
305 _dphidxi_map = fe->get_fe_map().get_dphidxi_map();
306 _dphideta_map = fe->get_fe_map().get_dphideta_map();
307 _phi_map = fe->get_fe_map().get_phi_map();
308
309 for (unsigned int i = 0; i < _nodes.size(); ++i)
310 _nodes[i] = _current_elem->node_ptr(i);
311
312 ADRealVectorValue x = (*_nodes[1] - *_nodes[0]);
313 ADRealVectorValue y = (*_nodes[3] - *_nodes[0]);
314 ADRealVectorValue normal = x.cross(y);
315 normal /= normal.norm();
316
317 for (unsigned int k = 0; k < 4; ++k)
318 _node_normal[k] = normal;
319
321 ADDenseMatrix b(5, 20);
324 RealVectorValue f;
325 for (unsigned int t = 0; t < _t_points.size(); ++t)
326 {
327 (*_strain_increment[t])[_qp] = a;
328 (*_total_strain[t])[_qp] = a;
329 (*_B[t])[_qp] = b;
330 (*_ge[t])[_qp] = a;
331 (*_J_map[t])[_qp] = 0;
332 (*_dxyz_dxi[t])[_qp] = c;
333 (*_dxyz_deta[t])[_qp] = c;
334 (*_dxyz_dzeta[t])[_qp] = c;
338 }
339
340 // calculating derivatives of shape function in physical space (dphi/dx, dphi/dy, dphi/dz) at
341 // quadrature points these are g_{i} in Dvorkin's paper
342 for (unsigned int i = 0; i < _2d_points.size(); ++i)
343 {
344 for (unsigned int j = 0; j < _t_points.size(); ++j)
345 {
346 (*_dxyz_dxi[j])[i].zero();
347 for (unsigned int component = 0; component < 3; ++component)
348 {
349 (*_dxyz_dxi[j])[i](component) = 0.0;
350 (*_dxyz_deta[j])[i](component) = 0.0;
351 (*_dxyz_dzeta[j])[i](component) = 0.0;
352
353 for (unsigned int k = 0; k < _nodes.size(); ++k)
354 {
355 (*_dxyz_dxi[j])[i](component) += _dphidxi_map[k][i] * ((*_nodes[k])(component)) +
356 _t_points[j](0) / 2.0 * _thickness[i] *
357 _dphidxi_map[k][i] * _node_normal[k](component);
358 (*_dxyz_deta[j])[i](component) += _dphideta_map[k][i] * ((*_nodes[k])(component)) +
359 _t_points[j](0) / 2.0 * _thickness[i] *
360 _dphideta_map[k][i] * _node_normal[k](component);
361 (*_dxyz_dzeta[j])[i](component) +=
362 _thickness[i] * _phi_map[k][i] * _node_normal[k](component) / 2.0;
363 }
364 }
365 }
366 }
367
368 for (unsigned int i = 0; i < _2d_points.size(); ++i)
369 {
370 for (unsigned int j = 0; j < _t_points.size(); ++j)
371 {
372 // calculate gij for elasticity tensor
373 ADRankTwoTensor gmn;
375 for (unsigned int component = 0; component < 3; ++component)
376 {
377 gmn(0, 0) += (*_dxyz_dxi[j])[i](component) * (*_dxyz_dxi[j])[i](component);
378 gmn(1, 1) += (*_dxyz_deta[j])[i](component) * (*_dxyz_deta[j])[i](component);
379 gmn(2, 2) += (*_dxyz_dzeta[j])[i](component) * (*_dxyz_dzeta[j])[i](component);
380 gmn(0, 1) += (*_dxyz_dxi[j])[i](component) * (*_dxyz_deta[j])[i](component);
381 gmn(0, 2) += (*_dxyz_dxi[j])[i](component) * (*_dxyz_dzeta[j])[i](component);
382 gmn(1, 2) += (*_dxyz_deta[j])[i](component) * (*_dxyz_dzeta[j])[i](component);
383
384 // why are we dropping derivatives here?!
385 J(0, component) = MetaPhysicL::raw_value((*_dxyz_dxi[j])[i](component));
386 J(1, component) = MetaPhysicL::raw_value((*_dxyz_deta[j])[i](component));
387 J(2, component) = MetaPhysicL::raw_value((*_dxyz_dzeta[j])[i](component));
388 }
389 gmn(1, 0) = gmn(0, 1);
390 gmn(2, 0) = gmn(0, 2);
391 gmn(2, 1) = gmn(1, 2);
392
393 ADRankTwoTensor gmninv_temp = gmn.inverse();
394 (*_J_map[j])[i] = sqrt(gmn.det());
396
399
400 Real normx = sqrt(J(0, 0) * J(0, 0) + J(0, 1) * J(0, 1) + J(0, 2) * J(0, 2));
401 Real normy = sqrt(J(1, 0) * J(1, 0) + J(1, 1) * J(1, 1) + J(1, 2) * J(1, 2));
402 Real normz = sqrt(J(2, 0) * J(2, 0) + J(2, 1) * J(2, 1) + J(2, 2) * J(2, 2));
403
404 J(0, 0) /= normx;
405 J(0, 1) /= normx;
406 J(0, 2) /= normx;
407
408 J(1, 0) /= normy;
409 J(1, 1) /= normy;
410 J(1, 2) /= normy;
411
412 J(2, 0) /= normz;
413 J(2, 1) /= normz;
414 J(2, 2) /= normz;
415
416 // _transformation_matrix is an AD property, but we're not setting the derivatives!
417 (*_transformation_matrix)[i] = J;
418
419 // compute element's local coordinate
421
422 // calculate the local transformation matrix to be used to map the global stresses to the
423 // local element coordinate
424 const auto local_rotation_mat = ADRankTwoTensor::initializeFromRows(_e1, _e2, _e3);
425
426 for (const auto ii : make_range(Moose::dim))
427 for (const auto jj : make_range(Moose::dim))
428 (*_local_transformation_matrix[j])[i](ii, jj) =
429 MetaPhysicL::raw_value(local_rotation_mat(ii, jj));
430
431 // Calculate the contravariant base vectors g^0, g^1, g^2
432 // The base vectors for the strain tensor in the convected coordinate
433 // are g_0, g_1, g_2 (g_i=dx/dr_i)
434 // The following contravariant base vectors have the property:
435 // g^i*g_j= 1 if {i=j} otherwise g^i*g_j= 0
436
437 const auto denom = (*_dxyz_dxi[j])[i] * (*_dxyz_deta[j])[i].cross((*_dxyz_dzeta[j])[i]);
438 const auto gi0 = (*_dxyz_deta[j])[i].cross((*_dxyz_dzeta[j])[i]) / denom;
439 const auto gi1 = (*_dxyz_dzeta[j])[i].cross((*_dxyz_dxi[j])[i]) / denom;
440 const auto gi2 = (*_dxyz_dxi[j])[i].cross((*_dxyz_deta[j])[i]) / denom;
441
442 // Calculate the rotation matrix for the elasticity tensor that maps
443 // the strain tensor (with g_1, g2_, g_3 base vectors) to
444 // the stress tensor (with base vectors e1, e2, e3)
445
446 (*_ge[j])[i](0, 0) = gi0 * _e1;
447 (*_ge[j])[i](0, 1) = gi0 * _e2;
448 (*_ge[j])[i](0, 2) = gi0 * _e3;
449 (*_ge[j])[i](1, 0) = gi1 * _e1;
450 (*_ge[j])[i](1, 1) = gi1 * _e2;
451 (*_ge[j])[i](1, 2) = gi1 * _e3;
452 (*_ge[j])[i](2, 0) = gi2 * _e1;
453 (*_ge[j])[i](2, 1) = gi2 * _e2;
454 (*_ge[j])[i](2, 2) = gi2 * _e3;
455 }
456 }
457}
458
459void
461{
462 using std::abs;
463
464 // default option for the first local vector:the global X-axis is projected on the shell plane
465 // alternatively the reference first local vector provided by the user can be used to define the
466 // 1st local axis
467
468 // All nodes in an element have the same normal vector. Therefore, here, we use only the normal
469 // vecor of the first node as "the element's normal vector"
470 _e3 = _node_normal[0];
471
473
474 _e1 /= _e1.norm();
475
476 // The reference first local axis and the normal are considered parallel if the angle between them
477 // is less than 0.05 degrees
478 if (MooseUtils::absoluteFuzzyEqual(abs(_e1 * _e3), 1.0, 0.05 * libMesh::pi / 180.0))
479 {
480 mooseError("The reference first local axis must not be perpendicular to any of the shell "
481 "elements ");
482 }
483
484 // we project the reference first local vector on the shell element and calculate the in-plane e1
485 // and e2 vectors
486 _e2 = _e3.cross(_e1);
487 _e2 /= _e2.norm();
488
489 _e1 = _e2.cross(_e3);
490 _e1 /= _e1.norm();
491}
492
493void
495{
496 for (unsigned int k = 0; k < _nodes.size(); ++k)
498}
499
500void
502{
503 // compute nodal local axis
505 for (unsigned int k = 0; k < _nodes.size(); ++k)
506 {
507 _v1[k] = _e1;
508 _v2[k] = _e2;
509 }
510
511 // compute B matrix rows correspond to [ux1, ux2, ux3, ux4, uy1, uy2, uy3, uy4, uz1, uz2, uz3,
512 // uz4, a1, a2, a3, a4, b1, b2, b3, b4]
513 for (unsigned int i = 0; i < _2d_points.size(); ++i)
514 {
515 for (unsigned int j = 0; j < _t_points.size(); ++j)
516 {
517 (*_B[j])[i].resize(5, 20);
518 (*_B[j])[i].zero();
519 for (unsigned int k = 0; k < _nodes.size(); ++k)
520 {
521 // corresponding to strain(0,0)
522 (*_B[j])[i](0, k) += _dphidxi_map[k][i] * (*_dxyz_dxi[j])[i](0);
523 (*_B[j])[i](0, 4 + k) = _dphidxi_map[k][i] * (*_dxyz_dxi[j])[i](1);
524 (*_B[j])[i](0, 8 + k) = _dphidxi_map[k][i] * (*_dxyz_dxi[j])[i](2);
525 (*_B[j])[i](0, 12 + k) = _dphidxi_map[k][i] * _t_points[j](0) / 2.0 * _thickness[i] *
526 (-_v2[k] * (*_dxyz_dxi[j])[i]);
527 (*_B[j])[i](0, 16 + k) = _dphidxi_map[k][i] * _t_points[j](0) / 2.0 * _thickness[i] *
528 (_v1[k] * (*_dxyz_dxi[j])[i]);
529
530 // corresponding to strain(1,1)
531 (*_B[j])[i](1, k) = _dphideta_map[k][i] * (*_dxyz_deta[j])[i](0);
532 (*_B[j])[i](1, 4 + k) = _dphideta_map[k][i] * (*_dxyz_deta[j])[i](1);
533 (*_B[j])[i](1, 8 + k) = _dphideta_map[k][i] * (*_dxyz_deta[j])[i](2);
534 (*_B[j])[i](1, 12 + k) = _dphideta_map[k][i] * _t_points[j](0) / 2.0 * _thickness[i] *
535 (-_v2[k] * (*_dxyz_deta[j])[i]);
536 (*_B[j])[i](1, 16 + k) = _dphideta_map[k][i] * _t_points[j](0) / 2.0 * _thickness[i] *
537 (_v1[k] * (*_dxyz_deta[j])[i]);
538
539 // corresponding to strain(2,2) = 0
540
541 // corresponding to strain(0,1)
542 (*_B[j])[i](2, k) = 0.5 * (_dphideta_map[k][i] * (*_dxyz_dxi[j])[i](0) +
543 _dphidxi_map[k][i] * (*_dxyz_deta[j])[i](0));
544 (*_B[j])[i](2, 4 + k) = 0.5 * (_dphideta_map[k][i] * (*_dxyz_dxi[j])[i](1) +
545 _dphidxi_map[k][i] * (*_dxyz_deta[j])[i](1));
546 (*_B[j])[i](2, 8 + k) = 0.5 * (_dphideta_map[k][i] * (*_dxyz_dxi[j])[i](2) +
547 _dphidxi_map[k][i] * (*_dxyz_deta[j])[i](2));
548 (*_B[j])[i](2, 12 + k) =
549 0.25 * _t_points[j](0) * _thickness[i] * -_v2[k] *
550 (_dphideta_map[k][i] * (*_dxyz_dxi[j])[i] + _dphidxi_map[k][i] * (*_dxyz_deta[j])[i]);
551 (*_B[j])[i](2, 16 + k) =
552 0.25 * _t_points[j](0) * _thickness[i] * _v1[k] *
553 ((*_dxyz_deta[j])[i] * _dphidxi_map[k][i] + (*_dxyz_dxi[j])[i] * _dphideta_map[k][i]);
554 }
555
556 _g3_a = _thickness[i] / 4.0 * (_node_normal[2] + _node_normal[3]);
557 _g3_c = _thickness[i] / 4.0 * (_node_normal[0] + _node_normal[1]);
558 _g3_b = _thickness[i] / 4.0 * (_node_normal[0] + _node_normal[3]);
559 _g3_d = _thickness[i] / 4.0 * (_node_normal[1] + _node_normal[2]);
560
561 _g1_a = 0.5 * ((*_nodes[2]) - (*_nodes[3])) +
562 _t_points[j](0) / 4.0 * _thickness[i] * (_node_normal[2] - _node_normal[3]);
563 _g1_c = 0.5 * ((*_nodes[1]) - (*_nodes[0])) +
564 _t_points[j](0) / 4.0 * _thickness[i] * (_node_normal[1] - _node_normal[0]);
565 _g2_b = 0.5 * ((*_nodes[3]) - (*_nodes[0])) +
566 _t_points[j](0) / 4.0 * _thickness[i] * (_node_normal[3] - _node_normal[0]);
567 _g2_d = 0.5 * ((*_nodes[2]) - (*_nodes[1])) +
568 _t_points[j](0) / 4.0 * _thickness[i] * (_node_normal[2] - _node_normal[1]);
569
570 updateGVectors(); // for large strain problems
571
572 // corresponding to strain(0,2)
573 for (unsigned int component = 0; component < 3; component++)
574 {
575 (*_B[j])[i](3, 2 + component * 4) = 0.125 * (1.0 + _2d_points[i](1)) * _g3_a(component);
576 (*_B[j])[i](3, 3 + component * 4) = 0.125 * (1.0 + _2d_points[i](1)) * -_g3_a(component);
577 (*_B[j])[i](3, 1 + component * 4) = 0.125 * (1.0 - _2d_points[i](1)) * _g3_c(component);
578 (*_B[j])[i](3, component * 4) = 0.125 * (1.0 - _2d_points[i](1)) * -_g3_c(component);
579 }
580 (*_B[j])[i](3, 14) = 0.125 * (1.0 + _2d_points[i](1)) * 0.5 * _thickness[i] * _g1_a * -_v2[2];
581 (*_B[j])[i](3, 18) = 0.125 * (1.0 + _2d_points[i](1)) * 0.5 * _thickness[i] * _g1_a * _v1[2];
582 (*_B[j])[i](3, 15) = 0.125 * (1.0 + _2d_points[i](1)) * 0.5 * _thickness[i] * _g1_a * -_v2[3];
583 (*_B[j])[i](3, 19) = 0.125 * (1.0 + _2d_points[i](1)) * 0.5 * _thickness[i] * _g1_a * _v1[3];
584
585 (*_B[j])[i](3, 13) = 0.125 * (1.0 - _2d_points[i](1)) * 0.5 * _thickness[i] * _g1_c * -_v2[1];
586 (*_B[j])[i](3, 17) = 0.125 * (1.0 - _2d_points[i](1)) * 0.5 * _thickness[i] * _g1_c * _v1[1];
587 (*_B[j])[i](3, 12) = 0.125 * (1.0 - _2d_points[i](1)) * 0.5 * _thickness[i] * _g1_c * -_v2[0];
588 (*_B[j])[i](3, 16) = 0.125 * (1.0 - _2d_points[i](1)) * 0.5 * _thickness[i] * _g1_c * _v1[0];
589
590 // corresponding to strain(1,2)
591 for (unsigned int component = 0; component < 3; component++)
592 {
593 (*_B[j])[i](4, 2 + component * 4) = 0.125 * (1.0 + _2d_points[i](0)) * _g3_d(component);
594 (*_B[j])[i](4, 1 + component * 4) = 0.125 * (1.0 + _2d_points[i](0)) * -_g3_d(component);
595 (*_B[j])[i](4, 3 + component * 4) = 0.125 * (1.0 - _2d_points[i](0)) * _g3_b(component);
596 (*_B[j])[i](4, component * 4) = 0.125 * (1.0 - _2d_points[i](0)) * -_g3_b(component);
597 }
598 (*_B[j])[i](4, 14) = 0.125 * (1.0 + _2d_points[i](0)) * 0.5 * _thickness[i] * _g2_d * -_v2[2];
599 (*_B[j])[i](4, 18) = 0.125 * (1.0 + _2d_points[i](0)) * 0.5 * _thickness[i] * _g2_d * _v1[2];
600 (*_B[j])[i](4, 13) = 0.125 * (1.0 + _2d_points[i](0)) * 0.5 * _thickness[i] * _g2_d * -_v2[1];
601 (*_B[j])[i](4, 17) = 0.125 * (1.0 + _2d_points[i](0)) * 0.5 * _thickness[i] * _g2_d * _v1[1];
602
603 (*_B[j])[i](4, 15) = 0.125 * (1.0 - _2d_points[i](0)) * 0.5 * _thickness[i] * _g2_b * -_v2[3];
604 (*_B[j])[i](4, 19) = 0.125 * (1.0 - _2d_points[i](0)) * 0.5 * _thickness[i] * _g2_b * _v1[3];
605 (*_B[j])[i](4, 12) = 0.125 * (1.0 - _2d_points[i](0)) * 0.5 * _thickness[i] * _g2_b * -_v2[0];
606 (*_B[j])[i](4, 16) = 0.125 * (1.0 - _2d_points[i](0)) * 0.5 * _thickness[i] * _g2_b * _v1[0];
607 }
608 }
609}
610
611void
613{
615
616 for (unsigned int j = 0; j < 4; ++j)
617 {
618 _soln_disp_index[j].resize(_ndisp);
619 _soln_rot_index[j].resize(_nrot);
620
621 for (unsigned int i = 0; i < _ndisp; ++i)
622 {
623 _soln_disp_index[j][i] = _nodes[j]->dof_number(_nonlinear_sys.number(), _disp_num[i], 0);
624 _soln_vector(j + i * _nodes.size()) =
625 (*_sol)(_soln_disp_index[j][i]) - _sol_old(_soln_disp_index[j][i]);
626 if (ADReal::do_derivatives)
628 _soln_vector(j + i * _nodes.size()).derivatives(), _soln_disp_index[j][i], 1.);
629 }
630
631 for (unsigned int i = 0; i < _nrot; ++i)
632 {
633 _soln_rot_index[j][i] = _nodes[j]->dof_number(_nonlinear_sys.number(), _rot_num[i], 0);
634 _soln_vector(j + 12 + i * _nodes.size()) =
635 (*_sol)(_soln_rot_index[j][i]) - _sol_old(_soln_rot_index[j][i]);
636 if (ADReal::do_derivatives)
638 _soln_vector(j + 12 + i * _nodes.size()).derivatives(), _soln_rot_index[j][i], 1.);
639 }
640 }
641}
registerMooseObject("SolidMechanicsApp", ADComputeIncrementalShellStrain)
Real f(Real x)
Test function for Brents method.
const std::vector< double > y
const std::vector< double > x
unsigned int dim
std::vector< const MaterialProperty< RankTwoTensor > * > _covariant_transformation_matrix_old
ADMaterialProperty< RankTwoTensor > * _transformation_matrix
Rotation matrix material property.
virtual void computeSolnVector()
Computes the 20x1 soln vector and its derivatives for each shell element.
std::vector< ADRealVectorValue > _v1
First tangential vectors at nodes.
std::vector< const Node * > _nodes
Vector storing pointers to the nodes of the shell element.
virtual void updateGVectors()
Updates the vectors required for shear locking computation for finite rotations.
std::vector< MaterialProperty< RankTwoTensor > * > _covariant_transformation_matrix
Covariant base vector matrix material property to transform stress.
virtual void computeGMatrix()
Computes the transformation matrix from natural coordinates to local cartesian coordinates for elasti...
std::vector< std::vector< Real > > _dphidxi_map
Derivatives of shape functions w.r.t isoparametric coordinates xi.
std::vector< const MaterialProperty< RankTwoTensor > * > _ge_old
Old ge matrix for elasticity tensor conversion.
const MaterialProperty< RealVectorValue > & _node_normal_old
Material property storing the old normal to the element at the 4 nodes.
std::vector< Point > _2d_points
Quadrature points in the in-plane direction in isoparametric coordinate system.
std::unique_ptr< libMesh::QGauss > _t_qrule
Quadrature rule in the out of plane direction.
std::vector< const MaterialProperty< RealVectorValue > * > _dxyz_dxi_old
Old derivative of global x, y and z w.r.t isoparametric coordinate xi.
std::vector< ADMaterialProperty< RealVectorValue > * > _dxyz_dxi
Derivative of global x, y and z w.r.t isoparametric coordinate xi.
virtual void computeNodeNormal()
Computes the node normal at each node.
std::vector< ADMaterialProperty< Real > * > _J_map
Material property containing jacobian of transformation.
std::vector< unsigned int > _disp_num
Variable numbers corresponding to the displacement variables.
const VariableValue & _thickness
Coupled variable for the shell thickness.
NonlinearSystemBase & _nonlinear_sys
Reference to the nonlinear system object.
ADDenseVector _soln_vector
Vector that stores the incremental solution at all the 20 DOFs in the 4 noded element.
std::vector< std::vector< Real > > _dphideta_map
Derivatives of shape functions w.r.t isoparametric coordinates eta.
std::vector< ADMaterialProperty< DenseMatrix< Real > > * > _B
B_matrix for small strain.
std::vector< const MaterialProperty< RealVectorValue > * > _dxyz_dzeta_old
Old derivative of global x, y and z w.r.t isoparametric coordinate zeta.
std::vector< MaterialProperty< RankTwoTensor > * > _contravariant_transformation_matrix
Contravariant base vector matrix material property to transform strain.
std::vector< ADRealVectorValue > _v2
First tangential vectors at nodes.
std::vector< std::vector< unsigned int > > _soln_rot_index
Indices of solution vector corresponding to rotation DOFs in 2 directions at the 4 nodes.
ADRealVectorValue _x2
simulation variables
std::vector< const MaterialProperty< RankTwoTensor > * > _local_transformation_matrix_old
ADDenseVector _strain_vector
Vector that stores the strain in the the 2 axial and 3 shear directions.
std::vector< ADMaterialProperty< RealVectorValue > * > _dxyz_deta
Derivative of global x, y and z w.r.t isoparametric coordinate eta.
std::vector< ADMaterialProperty< RankTwoTensor > * > _ge
ge matrix for elasticity tensor conversion
unsigned int _ndisp
Number of coupled displacement variables.
std::vector< std::vector< Real > > _phi_map
Shape function value.
std::vector< const MaterialProperty< DenseMatrix< Real > > * > _B_old
Old B_matrix for small strain.
std::vector< ADMaterialProperty< RankTwoTensor > * > _strain_increment
Strain increment in the covariant coordinate system.
std::vector< Point > _t_points
Quadrature points in the out of plane direction in isoparametric coordinate system.
std::vector< const MaterialProperty< Real > * > _J_map_old
Old material property containing jacobian of transformation.
std::vector< const MaterialProperty< RankTwoTensor > * > _total_strain_old
Old total strain increment in the covariant coordinate system.
virtual void computeLocalCoordinates()
Computes the element's local coordinates and store in _e1, _e2 and _e3.
unsigned int _nrot
Number of coupled rotational variables.
virtual void computeBMatrix()
Computes the B matrix that connects strains to nodal displacements and rotations.
std::vector< const MaterialProperty< RealVectorValue > * > _dxyz_deta_old
Old derivative of global x, y and z w.r.t isoparametric coordinate eta.
ADComputeIncrementalShellStrain(const InputParameters &parameters)
ADMaterialProperty< RealVectorValue > & _node_normal
Material property storing the normal to the element at the 4 nodes. Stored as a material property for...
std::vector< ADMaterialProperty< RankTwoTensor > * > _total_strain
Total strain increment in the covariant coordinate system.
std::vector< std::vector< unsigned int > > _soln_disp_index
Indices of solution vector corresponding to displacement DOFs in 3 directions at the 4 nodes.
std::vector< MaterialProperty< RankTwoTensor > * > _total_global_strain
Total strain in global coordinate system.
std::vector< ADMaterialProperty< RealVectorValue > * > _dxyz_dzeta
Derivative of global x, y and z w.r.t isoparametric coordinate zeta.
std::vector< unsigned int > _rot_num
Variable numbers corresponding to the rotational variables.
std::vector< const MaterialProperty< RankTwoTensor > * > _contravariant_transformation_matrix_old
std::vector< MaterialProperty< RankTwoTensor > * > _local_transformation_matrix
Transformation matrix to map stresses from global coordinate to the element's local coordinate.
const FEBase *const & getFE(FEType type, unsigned int dim) const
MooseVariable * getVar(const std::string &var_name, unsigned int comp)
virtual Assembly & assembly(const THREAD_ID tid, const unsigned int sys_num) override
void addRequiredCoupledVar(const std::string &name, const std::string &doc_string)
void addRequiredParam(const std::string &name, const std::string &doc_string)
void addParam(const std::string &name, const std::initializer_list< typename T::value_type > &value, const std::string &doc_string)
void addClassDescription(const std::string &doc_string)
THREAD_ID _tid
unsigned int _qp
MooseMesh & _mesh
FEProblemBase & _fe_problem
static InputParameters validParams()
const Elem *const & _current_elem
const QBase *const & _qrule
void mooseError(Args &&... args) const
bool hasSecondOrderElements()
unsigned int number() const
static RankTwoTensorTempl initializeFromRows(const libMesh::TypeVector< T > &row0, const libMesh::TypeVector< T > &row1, const libMesh::TypeVector< T > &row2)
RankTwoTensorTempl< T > inverse() const
unsigned int number() const
virtual void zero() override final
TypeVector< typename CompareTypes< T, T2 >::supertype > cross(const TypeVector< T2 > &v) const
auto raw_value(const Eigen::Map< T > &in)
static constexpr std::size_t dim
void derivInsert(SemiDynamicSparseNumberArray< Real, libMesh::dof_id_type, NWrapper< N > > &derivs, libMesh::dof_id_type index, Real value)
const Real pi