https://mooseframework.inl.gov
Loading...
Searching...
No Matches
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),
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
53Real
54ReferenceElementJacobianDamper::computeDamping(const NumericVector<Number> & solution,
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
96void
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);
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}
unsigned int THREAD_ID
registerMooseObject("SolidMechanicsApp", ReferenceElementJacobianDamper)
void setCurrentSubdomainID(SubdomainID i)
void reinit(const Elem *elem)
bool hasBlocks(const SubdomainName &name) const
virtual void checkVariable(const MooseVariableFieldBase &variable) const
static InputParameters validParams()
SystemBase & _sys
static InputParameters validParams()
void addRequiredCoupledVar(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)
MeshBase & getMesh()
void addIa(const T &a)
void fillColumn(unsigned int c, const libMesh::TypeVector< T > &v)
This class implements a damper that limits the change in the Jacobian of elements without relying on ...
const QBase *const & _qrule
Quadrature rule.
MooseMesh & _mesh
The undisplaced mesh.
const Real _max_jacobian_diff
Maximum allowed relative increment in Jacobian.
std::vector< std::vector< RealVectorValue > > _grad_disp_update
The displacement gradients after this update.
std::vector< const VariablePhiGradient * > _grad_phi
shape function gradients
void computeGradDisp(const Elem *elem, const NumericVector< Number > &solution, const NumericVector< Number > &update)
Fill the displacement gradients.
std::vector< std::vector< RealVectorValue > > _grad_disp
The current displacement gradients.
virtual Real computeDamping(const NumericVector< Number > &solution, const NumericVector< Number > &update) override
std::vector< unsigned int > _disp_num
The displacement variable numbers.
ReferenceElementJacobianDamper(const InputParameters &parameters)
const unsigned int _ndisp
Number of displacement variables.
Assembly & _assembly
The undisplaced assembly.
MooseVariableFE< T > & getFieldVariable(THREAD_ID tid, const std::string &var_name)
virtual libMesh::DofMap & dofMap()
void max(const T &r, T &o, Request &req) const
void dof_indices(const Elem *const elem, std::vector< dof_id_type > &di) const
const Parallel::Communicator & _communicator
MeshBase & mesh