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 = "
84 "Node-based scaling is only implemented for first-order Lagrange multiplier and "
85 "displacement variables.");
88 if (!getParam<bool>(
"correct_edge_dropping"))
90 "Node-based scaling requires 'correct_edge_dropping = true'.");
93 const FEType fe_type(FIRST, LAGRANGE);
103 const std::string & var_param_name)
const
107 "The Lagrange multiplier variable must be an actual variable and not a constant.");
110 "The Lagrange multiplier variables must be provided and be actual variables.");
115 const std::string & var_param_name)
const
118 paramError(var_param_name,
"The Lagrange multiplier variables must be of Lagrange type");
123 const std::string & var_param_name,
125 const std::string & reference_var_param_name)
const
133 "' must use the same finite element type (order and family) as '",
134 reference_var_param_name,
141 "' must use the same dual/standard basis setting as '",
142 reference_var_param_name,
242 fraction_sum / libmesh_map_find(nodes_to_secondary_elem, dof->id()).size();
245const std::vector<Real> &
258 std::vector<Real> integrals(phi.size(), 0);
263 for (
const auto j : index_range(integrals))
264 integrals[j] += phi[j][qp] * JxW[qp] * coord;
281 mooseAssert(node.n_dofs(sys_num, var_num),
282 "The Lagrange multiplier must have a degree of freedom at this secondary node.");
285 const auto dof_index = node.dof_number(sys_num, var_num, 0);
299 if (!node->n_dofs(sys_num, var_num))
300 mooseError(
"No degrees of freedom for the Lagrange multiplier at the node. If this is being "
301 "called from an aux kernel make sure that your aux variable has the same order as "
302 "your Lagrange multiplier");
304 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
void checkPetrovGalerkinQuadraticFaces(const MooseObject &moose_object, const MooseVariableFieldBase &lm_var) 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)