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 fe_type.set_p_refinement(false);
230 auto & fe = _fe_problem.assembly(_tid, _nonlinear_sys.number()).getFE(fe_type, dim);
231 _dphidxi_map = fe->get_fe_map().get_dphidxi_map();
232 _dphideta_map = fe->get_fe_map().get_dphideta_map();
233 _phi_map = fe->get_fe_map().get_phi_map();
234
235 for (unsigned int i = 0; i < 4; ++i)
236 _nodes[i] = _current_elem->node_ptr(i);
237
238 for (unsigned int i = 0; i < _2d_points.size(); ++i)
239 {
240 for (unsigned int j = 0; j < _t_points.size(); ++j)
241 {
242 (*_ge[j])[i] = (*_ge_old[j])[i];
243 (*_J_map[j])[i] = (*_J_map_old[j])[i];
244 (*_dxyz_dxi[j])[i] = (*_dxyz_dxi_old[j])[i];
245 (*_dxyz_deta[j])[i] = (*_dxyz_deta_old[j])[i];
246 (*_dxyz_dzeta[j])[i] = (*_dxyz_dzeta_old[j])[i];
247 (*_B[j])[i] = (*_B_old[j])[i];
252 }
253 }
254
256
258
259 for (unsigned int i = 0; i < _2d_points.size(); ++i)
260 {
261 for (unsigned int j = 0; j < _t_points.size(); ++j)
262 {
263 // compute strain increment in covariant coordinate system using B and _soln_vector
264 for (unsigned int temp1 = 0; temp1 < 5; ++temp1)
265 {
266 _strain_vector(temp1) = 0.0;
267 for (unsigned int temp2 = 0; temp2 < 20; ++temp2)
268 _strain_vector(temp1) += (*_B[j])[i](temp1, temp2) * _soln_vector(temp2);
269 }
270 (*_strain_increment[j])[i](0, 0) = _strain_vector(0);
271 (*_strain_increment[j])[i](1, 1) = _strain_vector(1);
272 (*_strain_increment[j])[i](0, 1) = _strain_vector(2);
273 (*_strain_increment[j])[i](0, 2) = _strain_vector(3);
274 (*_strain_increment[j])[i](1, 2) = _strain_vector(4);
275 (*_strain_increment[j])[i](1, 0) = (*_strain_increment[j])[i](0, 1);
276 (*_strain_increment[j])[i](2, 0) = (*_strain_increment[j])[i](0, 2);
277 (*_strain_increment[j])[i](2, 1) = (*_strain_increment[j])[i](1, 2);
278
279 (*_total_strain[j])[i] = (*_total_strain_old[j])[i] + (*_strain_increment[j])[i];
280
281 for (unsigned int ii = 0; ii < 3; ++ii)
282 for (unsigned int jj = 0; jj < 3; ++jj)
286 (*_contravariant_transformation_matrix[j])[i].transpose();
287 }
288 }
289}
290
291void
293{
294 using std::sqrt;
295
296 // quadrature points in isoparametric space
297 _2d_points = _qrule->get_points(); // would be in 2D
298
299 unsigned int dim = _current_elem->dim();
300
301 // derivatives of shape functions (dphidxi, dphideta and dphidzeta) evaluated at quadrature points
302 // (in isoparametric space).
303 FEType fe_type(Utility::string_to_enum<Order>("First"),
304 Utility::string_to_enum<FEFamily>("LAGRANGE"));
305 fe_type.set_p_refinement(false);
306 auto & fe = _fe_problem.assembly(_tid, _nonlinear_sys.number()).getFE(fe_type, dim);
307 _dphidxi_map = fe->get_fe_map().get_dphidxi_map();
308 _dphideta_map = fe->get_fe_map().get_dphideta_map();
309 _phi_map = fe->get_fe_map().get_phi_map();
310
311 for (unsigned int i = 0; i < _nodes.size(); ++i)
312 _nodes[i] = _current_elem->node_ptr(i);
313
314 ADRealVectorValue x = (*_nodes[1] - *_nodes[0]);
315 ADRealVectorValue y = (*_nodes[3] - *_nodes[0]);
316 ADRealVectorValue normal = x.cross(y);
317 normal /= normal.norm();
318
319 for (unsigned int k = 0; k < 4; ++k)
320 _node_normal[k] = normal;
321
323 ADDenseMatrix b(5, 20);
326 RealVectorValue f;
327 for (unsigned int t = 0; t < _t_points.size(); ++t)
328 {
329 (*_strain_increment[t])[_qp] = a;
330 (*_total_strain[t])[_qp] = a;
331 (*_B[t])[_qp] = b;
332 (*_ge[t])[_qp] = a;
333 (*_J_map[t])[_qp] = 0;
334 (*_dxyz_dxi[t])[_qp] = c;
335 (*_dxyz_deta[t])[_qp] = c;
336 (*_dxyz_dzeta[t])[_qp] = c;
340 }
341
342 // calculating derivatives of shape function in physical space (dphi/dx, dphi/dy, dphi/dz) at
343 // quadrature points these are g_{i} in Dvorkin's paper
344 for (unsigned int i = 0; i < _2d_points.size(); ++i)
345 {
346 for (unsigned int j = 0; j < _t_points.size(); ++j)
347 {
348 (*_dxyz_dxi[j])[i].zero();
349 for (unsigned int component = 0; component < 3; ++component)
350 {
351 (*_dxyz_dxi[j])[i](component) = 0.0;
352 (*_dxyz_deta[j])[i](component) = 0.0;
353 (*_dxyz_dzeta[j])[i](component) = 0.0;
354
355 for (unsigned int k = 0; k < _nodes.size(); ++k)
356 {
357 (*_dxyz_dxi[j])[i](component) += _dphidxi_map[k][i] * ((*_nodes[k])(component)) +
358 _t_points[j](0) / 2.0 * _thickness[i] *
359 _dphidxi_map[k][i] * _node_normal[k](component);
360 (*_dxyz_deta[j])[i](component) += _dphideta_map[k][i] * ((*_nodes[k])(component)) +
361 _t_points[j](0) / 2.0 * _thickness[i] *
362 _dphideta_map[k][i] * _node_normal[k](component);
363 (*_dxyz_dzeta[j])[i](component) +=
364 _thickness[i] * _phi_map[k][i] * _node_normal[k](component) / 2.0;
365 }
366 }
367 }
368 }
369
370 for (unsigned int i = 0; i < _2d_points.size(); ++i)
371 {
372 for (unsigned int j = 0; j < _t_points.size(); ++j)
373 {
374 // calculate gij for elasticity tensor
375 ADRankTwoTensor gmn;
377 for (unsigned int component = 0; component < 3; ++component)
378 {
379 gmn(0, 0) += (*_dxyz_dxi[j])[i](component) * (*_dxyz_dxi[j])[i](component);
380 gmn(1, 1) += (*_dxyz_deta[j])[i](component) * (*_dxyz_deta[j])[i](component);
381 gmn(2, 2) += (*_dxyz_dzeta[j])[i](component) * (*_dxyz_dzeta[j])[i](component);
382 gmn(0, 1) += (*_dxyz_dxi[j])[i](component) * (*_dxyz_deta[j])[i](component);
383 gmn(0, 2) += (*_dxyz_dxi[j])[i](component) * (*_dxyz_dzeta[j])[i](component);
384 gmn(1, 2) += (*_dxyz_deta[j])[i](component) * (*_dxyz_dzeta[j])[i](component);
385
386 // why are we dropping derivatives here?!
387 J(0, component) = MetaPhysicL::raw_value((*_dxyz_dxi[j])[i](component));
388 J(1, component) = MetaPhysicL::raw_value((*_dxyz_deta[j])[i](component));
389 J(2, component) = MetaPhysicL::raw_value((*_dxyz_dzeta[j])[i](component));
390 }
391 gmn(1, 0) = gmn(0, 1);
392 gmn(2, 0) = gmn(0, 2);
393 gmn(2, 1) = gmn(1, 2);
394
395 ADRankTwoTensor gmninv_temp = gmn.inverse();
396 (*_J_map[j])[i] = sqrt(gmn.det());
398
401
402 Real normx = sqrt(J(0, 0) * J(0, 0) + J(0, 1) * J(0, 1) + J(0, 2) * J(0, 2));
403 Real normy = sqrt(J(1, 0) * J(1, 0) + J(1, 1) * J(1, 1) + J(1, 2) * J(1, 2));
404 Real normz = sqrt(J(2, 0) * J(2, 0) + J(2, 1) * J(2, 1) + J(2, 2) * J(2, 2));
405
406 J(0, 0) /= normx;
407 J(0, 1) /= normx;
408 J(0, 2) /= normx;
409
410 J(1, 0) /= normy;
411 J(1, 1) /= normy;
412 J(1, 2) /= normy;
413
414 J(2, 0) /= normz;
415 J(2, 1) /= normz;
416 J(2, 2) /= normz;
417
418 // _transformation_matrix is an AD property, but we're not setting the derivatives!
419 (*_transformation_matrix)[i] = J;
420
421 // compute element's local coordinate
423
424 // calculate the local transformation matrix to be used to map the global stresses to the
425 // local element coordinate
426 const auto local_rotation_mat = ADRankTwoTensor::initializeFromRows(_e1, _e2, _e3);
427
428 for (const auto ii : make_range(Moose::dim))
429 for (const auto jj : make_range(Moose::dim))
430 (*_local_transformation_matrix[j])[i](ii, jj) =
431 MetaPhysicL::raw_value(local_rotation_mat(ii, jj));
432
433 // Calculate the contravariant base vectors g^0, g^1, g^2
434 // The base vectors for the strain tensor in the convected coordinate
435 // are g_0, g_1, g_2 (g_i=dx/dr_i)
436 // The following contravariant base vectors have the property:
437 // g^i*g_j= 1 if {i=j} otherwise g^i*g_j= 0
438
439 const auto denom = (*_dxyz_dxi[j])[i] * (*_dxyz_deta[j])[i].cross((*_dxyz_dzeta[j])[i]);
440 const auto gi0 = (*_dxyz_deta[j])[i].cross((*_dxyz_dzeta[j])[i]) / denom;
441 const auto gi1 = (*_dxyz_dzeta[j])[i].cross((*_dxyz_dxi[j])[i]) / denom;
442 const auto gi2 = (*_dxyz_dxi[j])[i].cross((*_dxyz_deta[j])[i]) / denom;
443
444 // Calculate the rotation matrix for the elasticity tensor that maps
445 // the strain tensor (with g_1, g2_, g_3 base vectors) to
446 // the stress tensor (with base vectors e1, e2, e3)
447
448 (*_ge[j])[i](0, 0) = gi0 * _e1;
449 (*_ge[j])[i](0, 1) = gi0 * _e2;
450 (*_ge[j])[i](0, 2) = gi0 * _e3;
451 (*_ge[j])[i](1, 0) = gi1 * _e1;
452 (*_ge[j])[i](1, 1) = gi1 * _e2;
453 (*_ge[j])[i](1, 2) = gi1 * _e3;
454 (*_ge[j])[i](2, 0) = gi2 * _e1;
455 (*_ge[j])[i](2, 1) = gi2 * _e2;
456 (*_ge[j])[i](2, 2) = gi2 * _e3;
457 }
458 }
459}
460
461void
463{
464 using std::abs;
465
466 // default option for the first local vector:the global X-axis is projected on the shell plane
467 // alternatively the reference first local vector provided by the user can be used to define the
468 // 1st local axis
469
470 // All nodes in an element have the same normal vector. Therefore, here, we use only the normal
471 // vecor of the first node as "the element's normal vector"
472 _e3 = _node_normal[0];
473
475
476 _e1 /= _e1.norm();
477
478 // The reference first local axis and the normal are considered parallel if the angle between them
479 // is less than 0.05 degrees
480 if (MooseUtils::absoluteFuzzyEqual(abs(_e1 * _e3), 1.0, 0.05 * libMesh::pi / 180.0))
481 {
482 mooseError("The reference first local axis must not be perpendicular to any of the shell "
483 "elements ");
484 }
485
486 // we project the reference first local vector on the shell element and calculate the in-plane e1
487 // and e2 vectors
488 _e2 = _e3.cross(_e1);
489 _e2 /= _e2.norm();
490
491 _e1 = _e2.cross(_e3);
492 _e1 /= _e1.norm();
493}
494
495void
497{
498 for (unsigned int k = 0; k < _nodes.size(); ++k)
500}
501
502void
504{
505 // compute nodal local axis
507 for (unsigned int k = 0; k < _nodes.size(); ++k)
508 {
509 _v1[k] = _e1;
510 _v2[k] = _e2;
511 }
512
513 // compute B matrix rows correspond to [ux1, ux2, ux3, ux4, uy1, uy2, uy3, uy4, uz1, uz2, uz3,
514 // uz4, a1, a2, a3, a4, b1, b2, b3, b4]
515 for (unsigned int i = 0; i < _2d_points.size(); ++i)
516 {
517 for (unsigned int j = 0; j < _t_points.size(); ++j)
518 {
519 (*_B[j])[i].resize(5, 20);
520 (*_B[j])[i].zero();
521 for (unsigned int k = 0; k < _nodes.size(); ++k)
522 {
523 // corresponding to strain(0,0)
524 (*_B[j])[i](0, k) += _dphidxi_map[k][i] * (*_dxyz_dxi[j])[i](0);
525 (*_B[j])[i](0, 4 + k) = _dphidxi_map[k][i] * (*_dxyz_dxi[j])[i](1);
526 (*_B[j])[i](0, 8 + k) = _dphidxi_map[k][i] * (*_dxyz_dxi[j])[i](2);
527 (*_B[j])[i](0, 12 + k) = _dphidxi_map[k][i] * _t_points[j](0) / 2.0 * _thickness[i] *
528 (-_v2[k] * (*_dxyz_dxi[j])[i]);
529 (*_B[j])[i](0, 16 + k) = _dphidxi_map[k][i] * _t_points[j](0) / 2.0 * _thickness[i] *
530 (_v1[k] * (*_dxyz_dxi[j])[i]);
531
532 // corresponding to strain(1,1)
533 (*_B[j])[i](1, k) = _dphideta_map[k][i] * (*_dxyz_deta[j])[i](0);
534 (*_B[j])[i](1, 4 + k) = _dphideta_map[k][i] * (*_dxyz_deta[j])[i](1);
535 (*_B[j])[i](1, 8 + k) = _dphideta_map[k][i] * (*_dxyz_deta[j])[i](2);
536 (*_B[j])[i](1, 12 + k) = _dphideta_map[k][i] * _t_points[j](0) / 2.0 * _thickness[i] *
537 (-_v2[k] * (*_dxyz_deta[j])[i]);
538 (*_B[j])[i](1, 16 + k) = _dphideta_map[k][i] * _t_points[j](0) / 2.0 * _thickness[i] *
539 (_v1[k] * (*_dxyz_deta[j])[i]);
540
541 // corresponding to strain(2,2) = 0
542
543 // corresponding to strain(0,1)
544 (*_B[j])[i](2, k) = 0.5 * (_dphideta_map[k][i] * (*_dxyz_dxi[j])[i](0) +
545 _dphidxi_map[k][i] * (*_dxyz_deta[j])[i](0));
546 (*_B[j])[i](2, 4 + k) = 0.5 * (_dphideta_map[k][i] * (*_dxyz_dxi[j])[i](1) +
547 _dphidxi_map[k][i] * (*_dxyz_deta[j])[i](1));
548 (*_B[j])[i](2, 8 + k) = 0.5 * (_dphideta_map[k][i] * (*_dxyz_dxi[j])[i](2) +
549 _dphidxi_map[k][i] * (*_dxyz_deta[j])[i](2));
550 (*_B[j])[i](2, 12 + k) =
551 0.25 * _t_points[j](0) * _thickness[i] * -_v2[k] *
552 (_dphideta_map[k][i] * (*_dxyz_dxi[j])[i] + _dphidxi_map[k][i] * (*_dxyz_deta[j])[i]);
553 (*_B[j])[i](2, 16 + k) =
554 0.25 * _t_points[j](0) * _thickness[i] * _v1[k] *
555 ((*_dxyz_deta[j])[i] * _dphidxi_map[k][i] + (*_dxyz_dxi[j])[i] * _dphideta_map[k][i]);
556 }
557
558 _g3_a = _thickness[i] / 4.0 * (_node_normal[2] + _node_normal[3]);
559 _g3_c = _thickness[i] / 4.0 * (_node_normal[0] + _node_normal[1]);
560 _g3_b = _thickness[i] / 4.0 * (_node_normal[0] + _node_normal[3]);
561 _g3_d = _thickness[i] / 4.0 * (_node_normal[1] + _node_normal[2]);
562
563 _g1_a = 0.5 * ((*_nodes[2]) - (*_nodes[3])) +
564 _t_points[j](0) / 4.0 * _thickness[i] * (_node_normal[2] - _node_normal[3]);
565 _g1_c = 0.5 * ((*_nodes[1]) - (*_nodes[0])) +
566 _t_points[j](0) / 4.0 * _thickness[i] * (_node_normal[1] - _node_normal[0]);
567 _g2_b = 0.5 * ((*_nodes[3]) - (*_nodes[0])) +
568 _t_points[j](0) / 4.0 * _thickness[i] * (_node_normal[3] - _node_normal[0]);
569 _g2_d = 0.5 * ((*_nodes[2]) - (*_nodes[1])) +
570 _t_points[j](0) / 4.0 * _thickness[i] * (_node_normal[2] - _node_normal[1]);
571
572 updateGVectors(); // for large strain problems
573
574 // corresponding to strain(0,2)
575 for (unsigned int component = 0; component < 3; component++)
576 {
577 (*_B[j])[i](3, 2 + component * 4) = 0.125 * (1.0 + _2d_points[i](1)) * _g3_a(component);
578 (*_B[j])[i](3, 3 + component * 4) = 0.125 * (1.0 + _2d_points[i](1)) * -_g3_a(component);
579 (*_B[j])[i](3, 1 + component * 4) = 0.125 * (1.0 - _2d_points[i](1)) * _g3_c(component);
580 (*_B[j])[i](3, component * 4) = 0.125 * (1.0 - _2d_points[i](1)) * -_g3_c(component);
581 }
582 (*_B[j])[i](3, 14) = 0.125 * (1.0 + _2d_points[i](1)) * 0.5 * _thickness[i] * _g1_a * -_v2[2];
583 (*_B[j])[i](3, 18) = 0.125 * (1.0 + _2d_points[i](1)) * 0.5 * _thickness[i] * _g1_a * _v1[2];
584 (*_B[j])[i](3, 15) = 0.125 * (1.0 + _2d_points[i](1)) * 0.5 * _thickness[i] * _g1_a * -_v2[3];
585 (*_B[j])[i](3, 19) = 0.125 * (1.0 + _2d_points[i](1)) * 0.5 * _thickness[i] * _g1_a * _v1[3];
586
587 (*_B[j])[i](3, 13) = 0.125 * (1.0 - _2d_points[i](1)) * 0.5 * _thickness[i] * _g1_c * -_v2[1];
588 (*_B[j])[i](3, 17) = 0.125 * (1.0 - _2d_points[i](1)) * 0.5 * _thickness[i] * _g1_c * _v1[1];
589 (*_B[j])[i](3, 12) = 0.125 * (1.0 - _2d_points[i](1)) * 0.5 * _thickness[i] * _g1_c * -_v2[0];
590 (*_B[j])[i](3, 16) = 0.125 * (1.0 - _2d_points[i](1)) * 0.5 * _thickness[i] * _g1_c * _v1[0];
591
592 // corresponding to strain(1,2)
593 for (unsigned int component = 0; component < 3; component++)
594 {
595 (*_B[j])[i](4, 2 + component * 4) = 0.125 * (1.0 + _2d_points[i](0)) * _g3_d(component);
596 (*_B[j])[i](4, 1 + component * 4) = 0.125 * (1.0 + _2d_points[i](0)) * -_g3_d(component);
597 (*_B[j])[i](4, 3 + component * 4) = 0.125 * (1.0 - _2d_points[i](0)) * _g3_b(component);
598 (*_B[j])[i](4, component * 4) = 0.125 * (1.0 - _2d_points[i](0)) * -_g3_b(component);
599 }
600 (*_B[j])[i](4, 14) = 0.125 * (1.0 + _2d_points[i](0)) * 0.5 * _thickness[i] * _g2_d * -_v2[2];
601 (*_B[j])[i](4, 18) = 0.125 * (1.0 + _2d_points[i](0)) * 0.5 * _thickness[i] * _g2_d * _v1[2];
602 (*_B[j])[i](4, 13) = 0.125 * (1.0 + _2d_points[i](0)) * 0.5 * _thickness[i] * _g2_d * -_v2[1];
603 (*_B[j])[i](4, 17) = 0.125 * (1.0 + _2d_points[i](0)) * 0.5 * _thickness[i] * _g2_d * _v1[1];
604
605 (*_B[j])[i](4, 15) = 0.125 * (1.0 - _2d_points[i](0)) * 0.5 * _thickness[i] * _g2_b * -_v2[3];
606 (*_B[j])[i](4, 19) = 0.125 * (1.0 - _2d_points[i](0)) * 0.5 * _thickness[i] * _g2_b * _v1[3];
607 (*_B[j])[i](4, 12) = 0.125 * (1.0 - _2d_points[i](0)) * 0.5 * _thickness[i] * _g2_b * -_v2[0];
608 (*_B[j])[i](4, 16) = 0.125 * (1.0 - _2d_points[i](0)) * 0.5 * _thickness[i] * _g2_b * _v1[0];
609 }
610 }
611}
612
613void
615{
617
618 for (unsigned int j = 0; j < 4; ++j)
619 {
620 _soln_disp_index[j].resize(_ndisp);
621 _soln_rot_index[j].resize(_nrot);
622
623 for (unsigned int i = 0; i < _ndisp; ++i)
624 {
625 _soln_disp_index[j][i] = _nodes[j]->dof_number(_nonlinear_sys.number(), _disp_num[i], 0);
626 _soln_vector(j + i * _nodes.size()) =
627 (*_sol)(_soln_disp_index[j][i]) - _sol_old(_soln_disp_index[j][i]);
628 if (ADReal::do_derivatives)
630 _soln_vector(j + i * _nodes.size()).derivatives(), _soln_disp_index[j][i], 1.);
631 }
632
633 for (unsigned int i = 0; i < _nrot; ++i)
634 {
635 _soln_rot_index[j][i] = _nodes[j]->dof_number(_nonlinear_sys.number(), _rot_num[i], 0);
636 _soln_vector(j + 12 + i * _nodes.size()) =
637 (*_sol)(_soln_rot_index[j][i]) - _sol_old(_soln_rot_index[j][i]);
638 if (ADReal::do_derivatives)
640 _soln_vector(j + 12 + i * _nodes.size()).derivatives(), _soln_rot_index[j][i], 1.);
641 }
642 }
643}
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