https://mooseframework.inl.gov
ReferenceElementJacobianDamper.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 "FEProblem.h"
12 #include "MooseMesh.h"
13 #include "Assembly.h"
14 #include "SystemBase.h"
15 
16 #include "libmesh/quadrature.h" // _qrule
17 
19 
22 {
25  params.addClassDescription("Damper that limits the change in element Jacobians");
26  params.addRequiredCoupledVar("displacements", "The nonlinear displacement variables");
27  params.addParam<Real>(
28  "max_increment", 0.1, "The maximum permissible incremental Jacobian per Newton iteration");
29  return params;
30 }
31 
33  : GeneralDamper(parameters),
34  Coupleable(this, /*nodal=*/true),
35  BlockRestrictable(this),
36  _max_jacobian_diff(getParam<Real>("max_increment")),
37  _tid(getParam<THREAD_ID>("_tid")),
38  _mesh(_subproblem.mesh()),
39  _assembly(_subproblem.assembly(_tid, _sys.number())),
40  _qrule(_assembly.qRule()),
41  _ndisp(coupledComponents("displacements")),
42  _disp_num(coupledIndices("displacements"))
43 {
44  _grad_phi.resize(_ndisp);
45  for (auto i : make_range(_ndisp))
46  {
47  const auto & disp_var = _sys.getFieldVariable<Real>(_tid, _disp_num[i]);
48  checkVariable(disp_var);
49  _grad_phi[i] = &disp_var.gradPhi();
50  }
51 }
52 
53 Real
55  const NumericVector<Number> & update)
56 {
57  // Maximum difference in the Jacobian for this Newton iteration
58  Real max_difference = 0.0;
59 
60  // Loop over elements in the mesh
61  for (const auto & elem : _mesh.getMesh().active_local_element_ptr_range())
62  {
63  if (!hasBlocks(elem->subdomain_id()))
64  continue;
65 
66  // Compute gradients of displacements before and after this update
67  computeGradDisp(elem, solution, update);
68 
69  // Compute the element Jacobian difference
70  for (unsigned int qp = 0; qp < _qrule->n_points(); ++qp)
71  {
73  for (auto i : make_range(_ndisp))
74  F.fillColumn(i, _grad_disp[i][qp]);
75  F.addIa(1);
76 
77  RankTwoTensor F_update;
78  for (auto i : make_range(_ndisp))
79  F_update.fillColumn(i, _grad_disp_update[i][qp]);
80  F_update.addIa(1);
81 
82  Real diff = std::abs(F_update.det() - F.det()) / F.det();
83  if (diff > max_difference)
84  max_difference = diff;
85  }
86  }
87 
88  _communicator.max(max_difference);
89 
90  if (max_difference > _max_jacobian_diff)
91  return _max_jacobian_diff / max_difference;
92 
93  return 1.0;
94 }
95 
96 void
98  const NumericVector<Number> & solution,
99  const NumericVector<Number> & update)
100 {
101  // Reinit variable shape functions
102  _assembly.setCurrentSubdomainID(elem->subdomain_id());
103  _assembly.reinit(elem);
104 
105  _grad_disp.resize(_ndisp);
106  _grad_disp_update.resize(_ndisp);
107  for (auto i : make_range(_ndisp))
108  {
109  std::vector<dof_id_type> dof_indices;
110  _sys.dofMap().dof_indices(elem, dof_indices, _disp_num[i]);
111  _grad_disp[i].resize(_qrule->n_points());
112  _grad_disp_update[i].resize(_qrule->n_points());
113  for (unsigned int qp = 0; qp < _qrule->n_points(); ++qp)
114  {
115  _grad_disp[i][qp].zero();
116  _grad_disp_update[i][qp].zero();
117  for (auto dof_idx : index_range(dof_indices))
118  {
119  _grad_disp[i][qp] += (*_grad_phi[i])[dof_idx][qp] *
120  (solution(dof_indices[dof_idx]) + update(dof_indices[dof_idx]));
121  _grad_disp_update[i][qp] += (*_grad_phi[i])[dof_idx][qp] * solution(dof_indices[dof_idx]);
122  }
123  }
124  }
125 }
void computeGradDisp(const Elem *elem, const NumericVector< Number > &solution, const NumericVector< Number > &update)
Fill the displacement gradients.
void addParam(const std::string &name, const std::initializer_list< typename T::value_type > &value, const std::string &doc_string)
void dof_indices(const Elem *const elem, std::vector< dof_id_type > &di) const
registerMooseObject("SolidMechanicsApp", ReferenceElementJacobianDamper)
MooseMesh & _mesh
The undisplaced mesh.
static InputParameters validParams()
MeshBase & mesh
virtual void checkVariable(const MooseVariableFieldBase &variable) const
const Parallel::Communicator & _communicator
Assembly & _assembly
The undisplaced assembly.
static const std::string F
Definition: NS.h:165
void reinit(const Elem *elem)
static InputParameters validParams()
void fillColumn(unsigned int c, const libMesh::TypeVector< Real > &v)
virtual Real computeDamping(const NumericVector< Number > &solution, const NumericVector< Number > &update) override
virtual libMesh::DofMap & dofMap()
const Real _max_jacobian_diff
Maximum allowed relative increment in Jacobian.
MeshBase & getMesh()
void addIa(const Real &a)
This class implements a damper that limits the change in the Jacobian of elements without relying on ...
void addRequiredCoupledVar(const std::string &name, const std::string &doc_string)
std::vector< unsigned int > _disp_num
The displacement variable numbers.
void setCurrentSubdomainID(SubdomainID i)
DIE A HORRIBLE DEATH HERE typedef LIBMESH_DEFAULT_SCALAR_TYPE Real
void max(const T &r, T &o, Request &req) const
MooseVariableFE< T > & getFieldVariable(THREAD_ID tid, const std::string &var_name)
IntRange< T > make_range(T beg, T end)
ReferenceElementJacobianDamper(const InputParameters &parameters)
void addClassDescription(const std::string &doc_string)
std::vector< std::vector< RealVectorValue > > _grad_disp
The current displacement gradients.
std::vector< const VariablePhiGradient * > _grad_phi
shape function gradients
bool hasBlocks(const SubdomainName &name) const
const unsigned int _ndisp
Number of displacement variables.
auto index_range(const T &sizable)
SystemBase & _sys
const QBase *const & _qrule
Quadrature rule.
unsigned int THREAD_ID
std::vector< std::vector< RealVectorValue > > _grad_disp_update
The displacement gradients after this update.