11 #include "MooseMesh.h"
13 #include "NonlinearSystem.h"
14 #include "MooseVariable.h"
15 #include "ArbitraryQuadrature.h"
16 #include "DenseMatrix.h"
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"
30 params.addClassDescription(
"Compute a small strain increment for the shell.");
31 params.addRequiredCoupledVar(
32 "rotations",
"The rotations appropriate for the simulation geometry and coordinate system");
33 params.addRequiredCoupledVar(
35 "The displacements appropriate for the simulation geometry and coordinate system");
36 params.addRequiredCoupledVar(
38 "Thickness of the shell. Can be supplied as either a number or a variable name.");
39 params.addRequiredParam<std::string>(
"through_thickness_order",
40 "Quadrature order in out of plane direction");
41 params.addParam<
bool>(
"large_strain",
43 "Set to true to turn on finite strain calculations."););
45 template <ComputeStage compute_stage>
47 const InputParameters & parameters)
48 : ADMaterial<compute_stage>(parameters),
49 _nrot(coupledComponents(
"rotations")),
50 _ndisp(coupledComponents(
"displacements")),
53 _thickness(coupledValue(
"thickness")),
54 _large_strain(getParam<bool>(
"large_strain")),
58 _nonlinear_sys(_fe_problem.getNonlinearSystemBase()),
64 _node_normal(declareADProperty<RealVectorValue>(
"node_normal")),
65 _node_normal_old(getMaterialPropertyOldByName<RealVectorValue>(
"node_normal")),
81 _total_global_strain(),
82 _sol(_nonlinear_sys.currentSolution()),
83 _sol_old(_nonlinear_sys.solutionOld())
88 "ADComputeIncrementalShellStrain: The number of variables supplied in 'displacements' "
89 "must be 3 and that in 'rotations' must be 2.");
91 if (_mesh.hasSecondOrderElements())
93 "ADComputeIncrementalShellStrain: Shell element is implemented only for linear elements.");
96 for (
unsigned int i = 0; i <
_ndisp; ++i)
98 MooseVariable * disp_variable = getVar(
"displacements", i);
103 MooseVariable * rot_variable = getVar(
"rotations", i);
104 _rot_num[i] = rot_variable->number();
108 _t_qrule = libmesh_make_unique<QGauss>(
109 1, Utility::string_to_enum<Order>(getParam<std::string>(
"through_thickness_order")));
128 for (
unsigned int i = 0; i <
_t_points.size(); ++i)
131 &declareADProperty<RankTwoTensor>(
"strain_increment_t_points_" + std::to_string(i));
133 &declareADProperty<RankTwoTensor>(
"total_strain_t_points_" + std::to_string(i));
135 &getMaterialPropertyOldByName<RankTwoTensor>(
"total_strain_t_points_" + std::to_string(i));
136 _B[i] = &declareADProperty<DenseMatrix<Real>>(
"B_t_points_" + std::to_string(i));
137 _B_old[i] = &getMaterialPropertyOldByName<DenseMatrix<Real>>(
"B_t_points_" + std::to_string(i));
138 _ge[i] = &declareADProperty<RankTwoTensor>(
"ge_t_points_" + std::to_string(i));
139 _ge_old[i] = &getMaterialPropertyOldByName<RankTwoTensor>(
"ge_t_points_" + std::to_string(i));
140 _J_map[i] = &declareADProperty<Real>(
"J_mapping_t_points_" + std::to_string(i));
141 _J_map_old[i] = &getMaterialPropertyOldByName<Real>(
"J_mapping_t_points_" + std::to_string(i));
142 _dxyz_dxi[i] = &declareADProperty<RealVectorValue>(
"dxyz_dxi_t_points_" + std::to_string(i));
144 &getMaterialPropertyOldByName<RealVectorValue>(
"dxyz_dxi_t_points_" + std::to_string(i));
145 _dxyz_deta[i] = &declareADProperty<RealVectorValue>(
"dxyz_deta_t_points_" + std::to_string(i));
147 &getMaterialPropertyOldByName<RealVectorValue>(
"dxyz_deta_t_points_" + std::to_string(i));
149 &declareADProperty<RealVectorValue>(
"dxyz_dzeta_t_points_" + std::to_string(i));
151 &getMaterialPropertyOldByName<RealVectorValue>(
"dxyz_dzeta_t_points_" + std::to_string(i));
153 _rotation_matrix[i] = &declareProperty<RankTwoTensor>(
"rotation_t_points_" + std::to_string(i));
155 &declareProperty<RankTwoTensor>(
"total_global_strain_t_points_" + std::to_string(i));
163 template <ComputeStage compute_stage>
167 unsigned int dim = _current_elem->dim();
170 "ADComputeIncrementalShellStrain: Shell element is implemented only for 2D elements");
171 if (_current_elem->n_nodes() != 4)
172 mooseError(
"ADComputeIncrementalShellStrain: Shell element needs to have exactly four nodes.");
177 template <ComputeStage compute_stage>
182 _2d_points = _qrule->get_points();
186 unsigned int dim = _current_elem->dim();
187 FEType fe_type(Utility::string_to_enum<Order>(
"First"),
188 Utility::string_to_enum<FEFamily>(
"LAGRANGE"));
189 auto & fe = _fe_problem.assembly(_tid).getFE(fe_type, dim);
190 _dphidxi_map = fe->get_fe_map().get_dphidxi_map();
191 _dphideta_map = fe->get_fe_map().get_dphideta_map();
192 _phi_map = fe->get_fe_map().get_phi_map();
194 for (
unsigned int i = 0; i < 4; ++i)
195 _nodes[i] = _current_elem->node_ptr(i);
197 for (
unsigned int i = 0; i < _2d_points.size(); ++i)
199 for (
unsigned int j = 0; j < _t_points.size(); ++j)
201 (*_ge[j])[i] = (*_ge_old[j])[i];
202 (*_J_map[j])[i] = (*_J_map_old[j])[i];
203 (*_dxyz_dxi[j])[i] = (*_dxyz_dxi_old[j])[i];
204 (*_dxyz_deta[j])[i] = (*_dxyz_deta_old[j])[i];
205 (*_dxyz_dzeta[j])[i] = (*_dxyz_dzeta_old[j])[i];
206 (*_B[j])[i] = (*_B_old[j])[i];
214 for (
unsigned int i = 0; i < _2d_points.size(); ++i)
216 for (
unsigned int j = 0; j < _t_points.size(); ++j)
219 for (
unsigned int temp1 = 0; temp1 < 5; ++temp1)
221 _strain_vector(temp1) = 0.0;
222 for (
unsigned int temp2 = 0; temp2 < 20; ++temp2)
223 _strain_vector(temp1) += (*_B[j])[i](temp1, temp2) * _soln_vector(temp2);
225 (*_strain_increment[j])[i](0, 0) = _strain_vector(0);
226 (*_strain_increment[j])[i](1, 1) = _strain_vector(1);
227 (*_strain_increment[j])[i](0, 1) = _strain_vector(2);
228 (*_strain_increment[j])[i](0, 2) = _strain_vector(3);
229 (*_strain_increment[j])[i](1, 2) = _strain_vector(4);
230 (*_strain_increment[j])[i](1, 0) = (*_strain_increment[j])[i](0, 1);
231 (*_strain_increment[j])[i](2, 0) = (*_strain_increment[j])[i](0, 2);
232 (*_strain_increment[j])[i](2, 1) = (*_strain_increment[j])[i](1, 2);
234 (*_total_strain[j])[i] = (*_total_strain_old[j])[i] + (*_strain_increment[j])[i];
236 for (
unsigned int ii = 0; ii < 3; ++ii)
237 for (
unsigned int jj = 0; jj < 3; ++jj)
238 _unrotated_total_strain(ii, jj) = MetaPhysicL::raw_value((*_total_strain[j])[i](ii, jj));
239 (*_total_global_strain[j])[i] = (*_rotation_matrix[j])[i].transpose() *
240 _unrotated_total_strain * (*_rotation_matrix[j])[i];
243 copyDualNumbersToValues();
246 template <ComputeStage compute_stage>
251 _2d_points = _qrule->get_points();
253 unsigned int dim = _current_elem->dim();
257 FEType fe_type(Utility::string_to_enum<Order>(
"First"),
258 Utility::string_to_enum<FEFamily>(
"LAGRANGE"));
259 auto & fe = _fe_problem.assembly(_tid).getFE(fe_type, dim);
260 _dphidxi_map = fe->get_fe_map().get_dphidxi_map();
261 _dphideta_map = fe->get_fe_map().get_dphideta_map();
262 _phi_map = fe->get_fe_map().get_phi_map();
264 for (
unsigned int i = 0; i < 4; ++i)
265 _nodes[i] = _current_elem->node_ptr(i);
267 ADRealVectorValue x = (*_nodes[1] - *_nodes[0]);
268 ADRealVectorValue y = (*_nodes[3] - *_nodes[0]);
269 ADRealVectorValue normal = x.cross(y);
270 normal /= normal.norm();
272 for (
unsigned int k = 0; k < 4; ++k)
273 _node_normal[k] = normal;
276 ADDenseMatrix b(5, 20);
279 for (
unsigned int t = 0; t < _t_points.size(); ++t)
281 (*_strain_increment[t])[_qp] = a;
282 (*_total_strain[t])[_qp] = a;
285 (*_J_map[t])[_qp] = 0;
286 (*_dxyz_dxi[t])[_qp] = c;
287 (*_dxyz_deta[t])[_qp] = c;
288 (*_dxyz_dzeta[t])[_qp] = c;
289 (*_rotation_matrix[t])[_qp] = d;
294 for (
unsigned int i = 0; i < _2d_points.size(); ++i)
296 for (
unsigned int j = 0; j < _t_points.size(); ++j)
298 (*_dxyz_dxi[j])[i].zero();
305 for (
unsigned int k = 0; k < _nodes.size(); ++k)
308 _t_points[j](0) / 2.0 * _thickness[i] *
309 _dphidxi_map[k][i] * _node_normal[k](
component);
311 _t_points[j](0) / 2.0 * _thickness[i] *
312 _dphideta_map[k][i] * _node_normal[k](
component);
314 _thickness[i] * _phi_map[k][i] * _node_normal[k](
component) / 2.0;
320 for (
unsigned int i = 0; i < _2d_points.size(); ++i)
322 for (
unsigned int j = 0; j < _t_points.size(); ++j)
340 gmn(1, 0) = gmn(0, 1);
341 gmn(2, 0) = gmn(0, 2);
342 gmn(2, 1) = gmn(1, 2);
344 ADRankTwoTensor gmninv_temp = gmn.inverse();
345 (*_J_map[j])[i] = std::sqrt(gmn.det());
346 (*_rotation_matrix[j])[i] = J;
349 ADRealVectorValue e3 = (*_dxyz_dzeta[j])[i] / (*_dxyz_dzeta[j])[i].norm();
350 ADRealVectorValue e1 = (*_dxyz_deta[j])[i].cross(e3);
352 ADRealVectorValue e2 = e3.cross(e1);
355 ADRankTwoTensor local_rotation_mat;
356 local_rotation_mat(0, 0) = e1(0);
357 local_rotation_mat(0, 1) = e1(1);
358 local_rotation_mat(0, 2) = e1(2);
359 local_rotation_mat(1, 0) = e2(0);
360 local_rotation_mat(1, 1) = e2(1);
361 local_rotation_mat(1, 2) = e2(2);
362 local_rotation_mat(2, 0) = e3(0);
363 local_rotation_mat(2, 1) = e3(1);
364 local_rotation_mat(2, 2) = e3(2);
366 ADRankTwoTensor gmninv = local_rotation_mat.transpose() * gmninv_temp * local_rotation_mat;
368 (*_ge[j])[i](0, 0) = (gmninv * (*_dxyz_dxi[j])[i]) * e1;
369 (*_ge[j])[i](0, 1) = (gmninv * (*_dxyz_dxi[j])[i]) * e2;
370 (*_ge[j])[i](0, 2) = (gmninv * (*_dxyz_dxi[j])[i]) * e3;
371 (*_ge[j])[i](1, 0) = (gmninv * (*_dxyz_deta[j])[i]) * e1;
372 (*_ge[j])[i](1, 1) = (gmninv * (*_dxyz_deta[j])[i]) * e2;
373 (*_ge[j])[i](1, 2) = (gmninv * (*_dxyz_deta[j])[i]) * e3;
374 (*_ge[j])[i](2, 0) = (gmninv * (*_dxyz_dzeta[j])[i]) * e1;
375 (*_ge[j])[i](2, 1) = (gmninv * (*_dxyz_dzeta[j])[i]) * e2;
376 (*_ge[j])[i](2, 2) = (gmninv * (*_dxyz_dzeta[j])[i]) * e3;
381 template <ComputeStage compute_stage>
385 for (
unsigned int k = 0; k < _nodes.size(); ++k)
386 _node_normal[k] = _node_normal_old[k];
389 template <ComputeStage compute_stage>
394 for (
unsigned int k = 0; k < _nodes.size(); ++k)
396 _v1[k] = _x2.cross(_node_normal[k]);
397 _v1[k] /= _x2.norm() * _node_normal[k].norm();
400 if (MooseUtils::absoluteFuzzyEqual(_v1[k].norm(), 0.0, 1e-6))
403 _v2[k] = _node_normal[k].cross(_v1[k]);
408 for (
unsigned int i = 0; i < _2d_points.size(); ++i)
410 for (
unsigned int j = 0; j < _t_points.size(); ++j)
412 (*_B[j])[i].resize(5, 20);
414 for (
unsigned int k = 0; k < _nodes.size(); ++k)
417 (*_B[j])[i](0, k) += _dphidxi_map[k][i] * (*_dxyz_dxi[j])[i](0);
418 (*_B[j])[i](0, 4 + k) = _dphidxi_map[k][i] * (*_dxyz_dxi[j])[i](1);
419 (*_B[j])[i](0, 8 + k) = _dphidxi_map[k][i] * (*_dxyz_dxi[j])[i](2);
420 (*_B[j])[i](0, 12 + k) = _dphidxi_map[k][i] * _t_points[j](0) / 2.0 * _thickness[i] *
421 (-_v2[k] * (*_dxyz_dxi[j])[i]);
422 (*_B[j])[i](0, 16 + k) = _dphidxi_map[k][i] * _t_points[j](0) / 2.0 * _thickness[i] *
423 (_v1[k] * (*_dxyz_dxi[j])[i]);
426 (*_B[j])[i](1, k) = _dphideta_map[k][i] * (*_dxyz_deta[j])[i](0);
427 (*_B[j])[i](1, 4 + k) = _dphideta_map[k][i] * (*_dxyz_deta[j])[i](1);
428 (*_B[j])[i](1, 8 + k) = _dphideta_map[k][i] * (*_dxyz_deta[j])[i](2);
429 (*_B[j])[i](1, 12 + k) = _dphideta_map[k][i] * _t_points[j](0) / 2.0 * _thickness[i] *
430 (-_v2[k] * (*_dxyz_deta[j])[i]);
431 (*_B[j])[i](1, 16 + k) = _dphideta_map[k][i] * _t_points[j](0) / 2.0 * _thickness[i] *
432 (_v1[k] * (*_dxyz_deta[j])[i]);
437 (*_B[j])[i](2, k) = 0.5 * (_dphideta_map[k][i] * (*_dxyz_dxi[j])[i](0) +
438 _dphidxi_map[k][i] * (*_dxyz_deta[j])[i](0));
439 (*_B[j])[i](2, 4 + k) = 0.5 * (_dphideta_map[k][i] * (*_dxyz_dxi[j])[i](1) +
440 _dphidxi_map[k][i] * (*_dxyz_deta[j])[i](1));
441 (*_B[j])[i](2, 8 + k) = 0.5 * (_dphideta_map[k][i] * (*_dxyz_dxi[j])[i](2) +
442 _dphidxi_map[k][i] * (*_dxyz_deta[j])[i](2));
443 (*_B[j])[i](2, 12 + k) =
444 0.25 * _t_points[j](0) * _thickness[i] * -_v2[k] *
445 (_dphideta_map[k][i] * (*_dxyz_dxi[j])[i] + _dphidxi_map[k][i] * (*_dxyz_deta[j])[i]);
446 (*_B[j])[i](2, 16 + k) =
447 0.25 * _t_points[j](0) * _thickness[i] * _v1[k] *
448 ((*_dxyz_deta[j])[i] * _dphidxi_map[k][i] + (*_dxyz_dxi[j])[i] * _dphideta_map[k][i]);
451 _g3_a = _thickness[i] / 4.0 * (_node_normal[2] + _node_normal[3]);
452 _g3_c = _thickness[i] / 4.0 * (_node_normal[0] + _node_normal[1]);
453 _g3_b = _thickness[i] / 4.0 * (_node_normal[0] + _node_normal[3]);
454 _g3_d = _thickness[i] / 4.0 * (_node_normal[1] + _node_normal[2]);
456 _g1_a = 0.5 * ((*_nodes[2]) - (*_nodes[3])) +
457 _t_points[j](0) / 4.0 * _thickness[i] * (_node_normal[2] - _node_normal[3]);
458 _g1_c = 0.5 * ((*_nodes[1]) - (*_nodes[0])) +
459 _t_points[j](0) / 4.0 * _thickness[i] * (_node_normal[1] - _node_normal[0]);
460 _g2_b = 0.5 * ((*_nodes[3]) - (*_nodes[0])) +
461 _t_points[j](0) / 4.0 * _thickness[i] * (_node_normal[3] - _node_normal[0]);
462 _g2_d = 0.5 * ((*_nodes[2]) - (*_nodes[1])) +
463 _t_points[j](0) / 4.0 * _thickness[i] * (_node_normal[2] - _node_normal[1]);
470 (*_B[j])[i](3, 2 +
component * 4) = 0.125 * (1.0 + _2d_points[i](1)) * _g3_a(
component);
471 (*_B[j])[i](3, 3 +
component * 4) = 0.125 * (1.0 + _2d_points[i](1)) * -_g3_a(
component);
472 (*_B[j])[i](3, 1 +
component * 4) = 0.125 * (1.0 - _2d_points[i](1)) * _g3_c(
component);
475 (*_B[j])[i](3, 14) = 0.125 * (1.0 + _2d_points[i](1)) * 0.5 * _thickness[i] * _g1_a * -_v2[2];
476 (*_B[j])[i](3, 18) = 0.125 * (1.0 + _2d_points[i](1)) * 0.5 * _thickness[i] * _g1_a * _v1[2];
477 (*_B[j])[i](3, 15) = 0.125 * (1.0 + _2d_points[i](1)) * 0.5 * _thickness[i] * _g1_a * -_v2[3];
478 (*_B[j])[i](3, 19) = 0.125 * (1.0 + _2d_points[i](1)) * 0.5 * _thickness[i] * _g1_a * _v1[3];
480 (*_B[j])[i](3, 13) = 0.125 * (1.0 - _2d_points[i](1)) * 0.5 * _thickness[i] * _g1_c * -_v2[1];
481 (*_B[j])[i](3, 17) = 0.125 * (1.0 - _2d_points[i](1)) * 0.5 * _thickness[i] * _g1_c * _v1[1];
482 (*_B[j])[i](3, 12) = 0.125 * (1.0 - _2d_points[i](1)) * 0.5 * _thickness[i] * _g1_c * -_v2[0];
483 (*_B[j])[i](3, 16) = 0.125 * (1.0 - _2d_points[i](1)) * 0.5 * _thickness[i] * _g1_c * _v1[0];
488 (*_B[j])[i](4, 2 +
component * 4) = 0.125 * (1.0 + _2d_points[i](0)) * _g3_d(
component);
489 (*_B[j])[i](4, 1 +
component * 4) = 0.125 * (1.0 + _2d_points[i](0)) * -_g3_d(
component);
490 (*_B[j])[i](4, 3 +
component * 4) = 0.125 * (1.0 - _2d_points[i](0)) * _g3_b(
component);
493 (*_B[j])[i](4, 14) = 0.125 * (1.0 + _2d_points[i](0)) * 0.5 * _thickness[i] * _g2_d * -_v2[2];
494 (*_B[j])[i](4, 18) = 0.125 * (1.0 + _2d_points[i](0)) * 0.5 * _thickness[i] * _g2_d * _v1[2];
495 (*_B[j])[i](4, 13) = 0.125 * (1.0 + _2d_points[i](0)) * 0.5 * _thickness[i] * _g2_d * -_v2[1];
496 (*_B[j])[i](4, 17) = 0.125 * (1.0 + _2d_points[i](0)) * 0.5 * _thickness[i] * _g2_d * _v1[1];
498 (*_B[j])[i](4, 15) = 0.125 * (1.0 - _2d_points[i](0)) * 0.5 * _thickness[i] * _g2_b * -_v2[3];
499 (*_B[j])[i](4, 19) = 0.125 * (1.0 - _2d_points[i](0)) * 0.5 * _thickness[i] * _g2_b * _v1[3];
500 (*_B[j])[i](4, 12) = 0.125 * (1.0 - _2d_points[i](0)) * 0.5 * _thickness[i] * _g2_b * -_v2[0];
501 (*_B[j])[i](4, 16) = 0.125 * (1.0 - _2d_points[i](0)) * 0.5 * _thickness[i] * _g2_b * _v1[0];
512 for (
unsigned int j = 0; j < 4; ++j)
514 _soln_disp_index[j].resize(_ndisp);
515 _soln_rot_index[j].resize(_nrot);
517 for (
unsigned int i = 0; i < _ndisp; ++i)
519 _soln_disp_index[j][i] = _nodes[j]->dof_number(_nonlinear_sys.number(), _disp_num[i], 0);
520 _soln_vector(j + i * _nodes.size()) =
521 (*_sol)(_soln_disp_index[j][i]) - _sol_old(_soln_disp_index[j][i]);
524 for (
unsigned int i = 0; i < _nrot; ++i)
526 _soln_rot_index[j][i] = _nodes[j]->dof_number(_nonlinear_sys.number(), _rot_num[i], 0);
527 _soln_vector(j + 12 + i * _nodes.size()) =
528 (*_sol)(_soln_rot_index[j][i]) - _sol_old(_soln_rot_index[j][i]);
539 for (
unsigned int j = 0; j < 4; ++j)
541 _soln_disp_index[j].resize(_ndisp);
542 _soln_rot_index[j].resize(_nrot);
544 for (
unsigned int i = 0; i < _ndisp; ++i)
546 size_t ad_offset = _disp_num[i] * _nonlinear_sys.getMaxVarNDofsPerElem();
547 _soln_disp_index[j][i] = _nodes[j]->dof_number(_nonlinear_sys.number(), _disp_num[i], 0);
548 _soln_vector(j + i * _nodes.size()) =
549 (*_sol)(_soln_disp_index[j][i]) - _sol_old(_soln_disp_index[j][i]);
550 Moose::derivInsert(_soln_vector(j + i * _nodes.size()).derivatives(), ad_offset + j, 1.);
553 for (
unsigned int i = 0; i < _nrot; ++i)
555 size_t ad_offset = _rot_num[i] * _nonlinear_sys.getMaxVarNDofsPerElem();
556 _soln_rot_index[j][i] = _nodes[j]->dof_number(_nonlinear_sys.number(), _rot_num[i], 0);
557 _soln_vector(j + 12 + i * _nodes.size()) =
558 (*_sol)(_soln_rot_index[j][i]) - _sol_old(_soln_rot_index[j][i]);
559 Moose::derivInsert(_soln_vector(j + 12 + i * _nodes.size()).derivatives(), ad_offset + j, 1.);