16#include "libmesh/fe.h"
24 params.addRequiredCoupledVar(
25 "lm_variable",
"The Lagrange multiplier variable representing the contact pressure.");
26 params.addParam<
bool>(
27 "use_petrov_galerkin",
false,
"Whether to use the Petrov-Galerkin approach.");
28 params.addCoupledVar(
"aux_lm",
29 "Auxiliary Lagrange multiplier variable that is utilized together with the "
30 "Petrov-Galerkin approach.");
31 params.addParam<
bool>(
34 "Whether to apply the node-based Lagrange-multiplier scaling of Popp et al. (2013) to "
35 "improve the conditioning of the linear system when secondary elements are only partially "
36 "covered (edge dropping). See the documentation for the current limitations.");
45 "Provides the mortar normal Lagrange multiplier for constraint enforcement.");
54 _lm_var(getVar(
"lm_variable", 0)),
55 _use_petrov_galerkin(getParam<bool>(
"use_petrov_galerkin")),
56 _aux_lm_var(isCoupled(
"aux_lm") ? getVar(
"aux_lm", 0) : nullptr),
57 _use_nodal_scaling(getParam<bool>(
"use_nodal_scaling"))
64 "We need to specify an auxiliary variable `aux_lm` while using the Petrov-Galerkin "
69 "Auxiliary LM variable needs to use standard shape function, i.e., set `use_dual = "
80 "Node-based scaling is only implemented for first-order Lagrange multiplier and "
81 "displacement variables.");
84 if (!getParam<bool>(
"correct_edge_dropping"))
86 "Node-based scaling requires 'correct_edge_dropping = true'.");
89 const FEType fe_type(FIRST, LAGRANGE);
99 const std::string & var_param_name)
const
103 "The Lagrange multiplier variable must be an actual variable and not a constant.");
106 "The Lagrange multiplier variables must be provided and be actual variables.");
111 const std::string & var_param_name)
const
114 paramError(var_param_name,
"The Lagrange multiplier variables must be of Lagrange type");
119 const std::string & var_param_name,
121 const std::string & reference_var_param_name)
const
129 "' must use the same finite element type (order and family) as '",
130 reference_var_param_name,
137 "' must use the same dual/standard basis setting as '",
138 reference_var_param_name,
238 fraction_sum / libmesh_map_find(nodes_to_secondary_elem, dof->id()).size();
241const std::vector<Real> &
254 std::vector<Real> integrals(phi.size(), 0);
259 for (
const auto j : index_range(integrals))
260 integrals[j] += phi[j][qp] * JxW[qp] * coord;
277 mooseAssert(node.n_dofs(sys_num, var_num),
278 "The Lagrange multiplier must have a degree of freedom at this secondary node.");
281 const auto dof_index = node.dof_number(sys_num, var_num, 0);
295 if (!node->n_dofs(sys_num, var_num))
296 mooseError(
"No degrees of freedom for the Lagrange multiplier at the node. If this is being "
297 "called from an aux kernel make sure that your aux variable has the same order as "
298 "your Lagrange multiplier");
300 const auto dof_number = node->dof_number(sys_num, var_num, 0);
DualNumber< Real, DNDerivativeType, true > ADReal
void coordTransformFactor(const SubProblem &s, SubdomainID sub_id, const P &point, C &factor, SubdomainID neighbor_sub_id=libMesh::Elem::invalid_subdomain_id)
registerMooseObject("ContactApp", LMWeightedGapUserObject)
const OutputTools< OutputType >::VariablePhiValue & fePhiLower(FEType type) const
const std::unordered_map< dof_id_type, std::vector< const Elem * > > & nodesToSecondaryElem() const
virtual bool isCoupledConstant(const std::string &var_name) const
User object for computing weighted gaps and contact pressure for Lagrange multipler based mortar cons...
const std::vector< Real > & fullNodalIntegrals(const Elem *elem)
Full coordinate-weighted integral int_e N_j per local node on the secondary lower-dimensional element...
void initializeNodalScaling()
The node-based scaling steps, kept out of initialize()/finalize()/computeQpIProperties() so that a cl...
void computeQpINodalScaling()
std::unordered_map< const DofObject *, std::unordered_set< dof_id_type > > _full_normalization_elems
Elements already folded into _dof_to_full_normalization for a given node, to avoid double counting wh...
std::unordered_map< const DofObject *, Real > _dof_to_full_normalization
Per-node sum, over each distinct adjacent secondary element, of the full-element integral int_e N_j (...
const bool _use_nodal_scaling
Whether to apply the Popp et al.
void finalizeNodalScaling()
virtual void initialize() override
virtual Real nodalScale(const DofObject *const dof) const override
Node-based Lagrange-multiplier scaling factor kappa_j of Popp et al.
virtual void finalize() override
LMWeightedGapUserObject(const InputParameters ¶meters)
std::unordered_map< dof_id_type, std::vector< Real > > _elem_to_full_nodal_integral
Cache of the per-node full integrals int_e N_j (see fullNodalIntegrals()), keyed by element id; clear...
static InputParameters validParams()
const MooseVariable *const _aux_lm_var
The auxiliary Lagrange multiplier variable (used together whith the Petrov-Galerkin approach)
virtual const ADVariableValue & contactPressure() const override
virtual const VariableTestValue & tractionBasis() const override
The traction stays on the Lagrange multiplier's own basis, which is the basis adSlnLower() uses.
std::unique_ptr< libMesh::FEBase > _nodal_scaling_fe
Finite element and quadrature rule used to evaluate fullNodalIntegrals()
const bool _use_petrov_galerkin
Whether to use Petrov-Galerkin approach.
void verifyLagrange(const MooseVariable &var, const std::string &var_name) const
Verify that the provided variables have degrees of freedom at nodes.
std::unordered_map< const DofObject *, Real > _dof_to_covered_fraction_sum
Per-node numerator of kappa_j (Popp 2013 eq.
void checkInput(const MooseVariable *const var, const std::string &var_name) const
Check user input validity for provided variable.
virtual void computeQpIProperties() override
Computes properties that are functions both of _qp and _i, for example the weighted gap.
std::unique_ptr< libMesh::QGauss > _nodal_scaling_qrule
virtual ADReal nodalContactPressure(const Node &node) const override
virtual Real getNormalContactPressure(const Node *const) const override
virtual const VariableTestValue & test() const override
const MooseVariableFE< Real > *const _lm_var
The Lagrange multiplier variable representing the contact pressure.
std::unordered_map< const DofObject *, Real > _dof_to_nodal_scale
A map from node to its node-based scaling factor kappa_j (see nodalScale())
static InputParameters newParams()
New parameters that this sub-class introduces.
void paramError(const std::string ¶m, Args... args) const
void mooseError(Args &&... args) const
bool isParamValid(const std::string &name) const
virtual unsigned int dimension() const
virtual const Node * nodePtr(const dof_id_type i) const
const libMesh::FEType & feType() const
unsigned int number() const
const ADTemplateVariableValue< OutputType > & adSlnLower() const
virtual const FieldVariablePhiValue & phiLower() const override
Elem const *const & _lower_secondary_elem
const AutomaticMortarGeneration & amg() const
virtual MooseMesh & mesh()=0
virtual const NumericVector< Number > *const & currentSolution() const=0
unsigned int number() const
Creates dof object to weighted gap map.
static InputParameters validParams()
unsigned int _i
Test function index.
const MooseVariable *const _disp_x_var
The x displacement variable.
virtual void finalize() override
unsigned int _qp
Quadrature point index for the mortar segments.
Real _qp_factor
The value of the LM at the current quadrature point.
static void addNodalNormalCoupling(InputParameters ¶ms)
Request the secondary face point-neighbor matrix coupling that nodal-normal derivatives need.
virtual void computeQpIProperties()
Computes properties that are functions both of _qp and _i, for example the weighted gap.
virtual void initialize() override
const bool _nodal
Whether the dof objects are nodal; if they're not, then they're elemental.
const Parallel::Communicator & _communicator
VariableShapeValue< true > VariableTestValue
VariableValueTempl< true > ADVariableValue
bool doDerivatives(const SubProblem &subproblem, const SystemBase &sys)
void derivInsert(SemiDynamicSparseNumberArray< Real, libMesh::dof_id_type, NWrapper< N > > &derivs, libMesh::dof_id_type index, Real value)