https://mooseframework.inl.gov
Loading...
Searching...
No Matches
ADMortarLagrangeConstraint.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
12// MOOSE includes
13#include "MooseVariable.h"
14#include "MoosePreconditioner.h"
16#include "NonlinearSystemBase.h"
17#include "Assembly.h"
18#include "SystemBase.h"
19#include "ADUtils.h"
20#include "FEProblemBase.h"
22
23#include <algorithm>
24#include <vector>
25
28{
30 params.addParam<Real>(
31 "derivative_threshold",
32 1.0e-17,
33 "Threshold to discard automatic differentiation derivatives. This number is chosen on the "
34 "order of the machine epsilon based on current experience.");
35
36 return params;
37}
38
40 : ADMortarConstraint(parameters),
41 _ad_derivative_threshold(getParam<Real>("derivative_threshold")),
42 _apply_derivative_threshold(true)
43{
44}
45
46void
48{
50
51 // Detect if preconditioner is VCP. If so, disable automatic derivative trimming.
53
54 if (dynamic_cast<const VariableCondensationPreconditioner *>(mpc))
56}
57
58void
60{
63
65
66 unsigned int test_space_size = 0;
67 switch (mortar_type)
68 {
69 case Moose::MortarType::Secondary:
71 test_space_size = _test_secondary.size();
72 break;
73
74 case Moose::MortarType::Primary:
76 test_space_size = _test_primary.size();
77 break;
78
79 case Moose::MortarType::Lower:
80 mooseAssert(_var, "LM variable is null");
82 test_space_size = _test.size();
83 break;
84 }
85
86 std::vector<unsigned int> is_index_on_lower_dimension;
87 // Find out if nodes are on the surface
88 for (_i = 0; _i < test_space_size; _i++)
89 {
90 if (mortar_type == Moose::MortarType::Primary && !_primary_ip_lowerd_map.count(_i))
91 continue;
92
93 if (mortar_type == Moose::MortarType::Secondary && !_secondary_ip_lowerd_map.count(_i))
94 continue;
95
96 is_index_on_lower_dimension.push_back(_i);
97 }
98
99 for (_qp = 0; _qp < _qrule_msm->n_points(); _qp++)
100 {
102 for (const auto index : is_index_on_lower_dimension)
103 {
104 _i = index;
105 _local_re(_i) += raw_value(_JxW_msm[_qp] * _coord[_qp] * computeQpResidual(mortar_type));
106 }
107 }
108
110}
111
112void
114{
115 std::vector<ADReal> residuals;
116 size_t test_space_size = 0;
117 typedef Moose::ConstraintJacobianType JType;
118 typedef Moose::MortarType MType;
119 std::vector<JType> jacobian_types;
120 std::vector<dof_id_type> dof_indices;
121 Real scaling_factor = 1;
122
125
127
128 switch (mortar_type)
129 {
130 case MType::Secondary:
131 dof_indices = _secondary_var.dofIndices();
132 jacobian_types = {JType::SecondarySecondary, JType::SecondaryPrimary, JType::SecondaryLower};
133 scaling_factor = _secondary_var.scalingFactor();
134 break;
135
136 case MType::Primary:
137 dof_indices = _primary_var.dofIndicesNeighbor();
138 jacobian_types = {JType::PrimarySecondary, JType::PrimaryPrimary, JType::PrimaryLower};
139 scaling_factor = _primary_var.scalingFactor();
140 break;
141
142 case MType::Lower:
143 mooseAssert(_var, "This should be non-null");
144 dof_indices = _var->dofIndicesLower();
145 jacobian_types = {JType::LowerSecondary, JType::LowerPrimary, JType::LowerLower};
146 scaling_factor = _var->scalingFactor();
147 break;
148 }
149 test_space_size = dof_indices.size();
150
151 residuals.resize(test_space_size, 0);
152
153 std::vector<unsigned int> is_index_on_lower_dimension;
154 std::vector<dof_id_type> dof_indices_lower;
155
156 // Find out if nodes are on the surface
157 unsigned int number_indices_on_lowerd = 0;
158
159 for (_i = 0; _i < test_space_size; _i++)
160 {
161 if (mortar_type == Moose::MortarType::Primary && !_primary_ip_lowerd_map.count(_i))
162 continue;
163
164 if (mortar_type == Moose::MortarType::Secondary && !_secondary_ip_lowerd_map.count(_i))
165 continue;
166
167 is_index_on_lower_dimension.push_back(_i);
168 dof_indices_lower.push_back(dof_indices[_i]);
169 number_indices_on_lowerd++;
170 }
171
172 std::vector<ADReal> residuals_lower;
173 residuals_lower.resize(number_indices_on_lowerd, 0);
174
175 // Only populate nodal residuals on the primary/secondary surfaces
176 // We do this regardless of whether we are interpolating normals. Use of this class
177 // implies we have Lagrange elements, so internal (high-dimensional) normals have no meaning
178 // and should be zero. As such, we decide to omit them and avoid possible spurious population of
179 // automatic differentiation-generated derivatives.
180 for (_qp = 0; _qp < _qrule_msm->n_points(); _qp++)
181 {
183 unsigned int index_lower = 0;
184 for (const auto index : is_index_on_lower_dimension)
185 {
186 _i = index;
187 residuals_lower[index_lower] += _JxW_msm[_qp] * _coord[_qp] * computeQpResidual(mortar_type);
188
189 // Get rid of derivatives that we assume won't count (tolerance prescribed by user)
190 // This can cause zero diagonal terms with the variable condensation preconditioner when the
191 // no adaptivity option is used (dofs are not checked).
192 // Uncomment when https://github.com/libMesh/MetaPhysicL/pull/18 makes it to MOOSE
193
194 index_lower++;
195 }
196 }
197
198 // cacheJacobian() uses the first row's column layout. Every row here has that same derivative
199 // support because the interpolated quadrature-point traction is independent of the test-function
200 // index and multiplication by a Real preserves the AD sparsity pattern.
201 addResidualsAndJacobian(_assembly, residuals_lower, dof_indices_lower, scaling_factor);
202}
static InputParameters validParams()
virtual ADReal computeQpResidual(Moose::MortarType mortar_type)=0
ADMortarLagrangeConstraint(const InputParameters &parameters)
bool _apply_derivative_threshold
Whether to apply derivative trimming.
virtual void precomputeQpQuantities()
Compute quantities that depend on the quadrature point but not on the test function index.
std::map< unsigned int, unsigned int > _primary_ip_lowerd_map
Nodal map from primary interior parent to lower dimensional domain.
std::map< unsigned int, unsigned int > _secondary_ip_lowerd_map
Nodal map from secondary interior parent to lower dimensional domain.
virtual void computeJacobian() override
static InputParameters validParams()
virtual void computeResidual() override
std::map< unsigned int, unsigned int > getSecondaryIpToLowerElementMap(const Elem &lower_secondary_elem) const
std::map< unsigned int, unsigned int > getPrimaryIpToLowerElementMap(const Elem &primary_elem, const Elem &primary_elem_ip, const Elem &lower_secondary_elem) const
unsigned int _qp
unsigned int _i
NonlinearSystemBase & getNonlinearSystemBase(const unsigned int sys_num)
void addParam(const std::string &name, const std::initializer_list< typename T::value_type > &value, const std::string &doc_string)
virtual const std::vector< dof_id_type > & dofIndices() const
void scalingFactor(const std::vector< Real > &factor)
unsigned int number() const
const std::vector< dof_id_type > & dofIndicesLower() const final
virtual const std::vector< dof_id_type > & dofIndicesNeighbor() const=0
MooseVariableField< Real > & _primary_var
MooseVariable *const _var
const VariableTestValue & _test_secondary
const MooseArray< Real > & _coord
MooseVariableField< Real > & _secondary_var
const FEProblemBase & feProblem() const
const VariableTestValue & _test
const VariableTestValue & _test_primary
Elem const *const & _lower_secondary_elem
const libMesh::QBase *const & _qrule_msm
const AutomaticMortarGeneration & amg() const
Elem const *const & _lower_primary_elem
const std::vector< Real > & _JxW_msm
MoosePreconditioner const * getPreconditioner() const
Assembly & _assembly
SystemBase & _sys
virtual void initialSetup()
unsigned int number() const
void prepareVectorTagLower(Assembly &assembly, unsigned int ivar)
void accumulateTaggedLocalResidual()
void addResidualsAndJacobian(Assembly &assembly, const Residuals &residuals, const Indices &dof_indices, Real scaling_factor)
void prepareVectorTagNeighbor(Assembly &assembly, unsigned int ivar)
void prepareVectorTag(Assembly &assembly, unsigned int ivar)
DenseVector< Number > _local_re
unsigned int n_points() const
ConstraintJacobianType