Line data Source code
1 : //* This file is part of the MOOSE framework 2 : //* https://www.mooseframework.org 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 : 10 : #include "ElementJacobianDamper.h" 11 : #include "FEProblem.h" 12 : #include "MooseMesh.h" 13 : #include "DisplacedProblem.h" 14 : #include "Assembly.h" 15 : 16 : #include "libmesh/quadrature.h" // _qrule 17 : 18 : registerMooseObject("TensorMechanicsApp", ElementJacobianDamper); 19 : 20 : InputParameters 21 12 : ElementJacobianDamper::validParams() 22 : { 23 12 : InputParameters params = GeneralDamper::validParams(); 24 12 : params.addClassDescription("Damper that limits the change in element Jacobians"); 25 24 : params.addParam<std::vector<VariableName>>( 26 : "displacements", {}, "The nonlinear displacement variables"); 27 24 : params.addParam<Real>( 28 : "max_increment", 29 24 : 0.1, 30 : "The maximum permissible relative increment in the Jacobian per Newton iteration"); 31 12 : params.set<bool>("use_displaced_mesh") = true; 32 12 : return params; 33 0 : } 34 : 35 6 : ElementJacobianDamper::ElementJacobianDamper(const InputParameters & parameters) 36 : : GeneralDamper(parameters), 37 6 : _tid(parameters.get<THREAD_ID>("_tid")), 38 6 : _assembly(_subproblem.assembly(_tid, _sys.number())), 39 6 : _qrule(_assembly.qRule()), 40 6 : _JxW(_assembly.JxW()), 41 6 : _fe_problem(*parameters.getCheckedPointerParam<FEProblemBase *>("_fe_problem_base")), 42 6 : _displaced_problem(_fe_problem.getDisplacedProblem()), 43 12 : _max_jacobian_diff(parameters.get<Real>("max_increment")) 44 : { 45 6 : if (_displaced_problem == NULL) 46 0 : mooseError("ElementJacobianDamper: Must use displaced problem"); 47 : 48 6 : _mesh = &_displaced_problem->mesh(); 49 : 50 12 : const std::vector<VariableName> & nl_vnames(getParam<std::vector<VariableName>>("displacements")); 51 6 : _ndisp = nl_vnames.size(); 52 : 53 24 : for (unsigned int i = 0; i < _ndisp; ++i) 54 : { 55 18 : _disp_var.push_back(&_sys.getFieldVariable<Real>(_tid, nl_vnames[i])); 56 18 : _disp_incr.push_back(_disp_var.back()->increment()); 57 : } 58 6 : } 59 : 60 : void 61 6 : ElementJacobianDamper::initialSetup() 62 : { 63 6 : } 64 : 65 : Real 66 126 : ElementJacobianDamper::computeDamping(const NumericVector<Number> & /* solution */, 67 : const NumericVector<Number> & update) 68 : { 69 : // Maximum difference in the Jacobian for this Newton iteration 70 126 : Real max_difference = 0.0; 71 : MooseArray<Real> JxW_displaced; 72 : 73 : // Vector for storing the original node coordinates 74 : std::vector<Point> point_copies; 75 : 76 : // Loop over elements in the mesh 77 420 : for (auto & current_elem : _mesh->getMesh().active_local_element_ptr_range()) 78 : { 79 : point_copies.clear(); 80 84 : point_copies.reserve(current_elem->n_nodes()); 81 : 82 : // Displace nodes with current Newton increment 83 756 : for (unsigned int i = 0; i < current_elem->n_nodes(); ++i) 84 : { 85 672 : Node & displaced_node = current_elem->node_ref(i); 86 : 87 672 : point_copies.push_back(displaced_node); 88 : 89 2688 : for (unsigned int j = 0; j < _ndisp; ++j) 90 : { 91 : dof_id_type disp_dof_num = 92 2016 : displaced_node.dof_number(_sys.number(), _disp_var[j]->number(), 0); 93 2016 : displaced_node(j) += update(disp_dof_num); 94 : } 95 : } 96 : 97 : // Reinit element to compute Jacobian of displaced element 98 84 : _assembly.reinit(current_elem); 99 84 : JxW_displaced = _JxW; 100 : 101 : // Un-displace nodes 102 756 : for (unsigned int i = 0; i < current_elem->n_nodes(); ++i) 103 : { 104 672 : Node & displaced_node = current_elem->node_ref(i); 105 : 106 2688 : for (unsigned int j = 0; j < _ndisp; ++j) 107 2016 : displaced_node(j) = point_copies[i](j); 108 : } 109 : 110 : // Reinit element to compute Jacobian before displacement 111 84 : _assembly.reinit(current_elem); 112 : 113 756 : for (unsigned int qp = 0; qp < _qrule->n_points(); ++qp) 114 : { 115 672 : Real diff = std::abs(JxW_displaced[qp] - _JxW[qp]) / _JxW[qp]; 116 672 : if (diff > max_difference) 117 244 : max_difference = diff; 118 : } 119 : 120 84 : JxW_displaced.release(); 121 126 : } 122 : 123 126 : _communicator.max(max_difference); 124 : 125 126 : if (max_difference > _max_jacobian_diff) 126 84 : return _max_jacobian_diff / max_difference; 127 : 128 : return 1.0; 129 : }