https://mooseframework.inl.gov
Loading...
Searching...
No Matches
MortarConstraintBase.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 "FEProblemBase.h"
12#include "Assembly.h"
13#include "MooseVariableFE.h"
14
15#include "libmesh/string_to_enum.h"
16
19{
23
24 // Whether on a displaced or undisplaced mesh, coupling ghosting will only happen for
25 // cross-interface elements
26 params.addRelationshipManager("AugmentSparsityOnInterface",
28 [](const InputParameters & obj_params, InputParameters & rm_params)
29 {
30 rm_params.set<bool>("use_displaced_mesh") =
31 obj_params.get<bool>("use_displaced_mesh");
32 rm_params.set<BoundaryName>("secondary_boundary") =
33 obj_params.get<BoundaryName>("secondary_boundary");
34 rm_params.set<BoundaryName>("primary_boundary") =
35 obj_params.get<BoundaryName>("primary_boundary");
36 rm_params.set<SubdomainName>("secondary_subdomain") =
37 obj_params.get<SubdomainName>("secondary_subdomain");
38 rm_params.set<SubdomainName>("primary_subdomain") =
39 obj_params.get<SubdomainName>("primary_subdomain");
40 rm_params.set<bool>("ghost_point_neighbors") =
41 obj_params.get<bool>("ghost_point_neighbors");
42 rm_params.set<bool>("ghost_higher_d_neighbors") =
43 obj_params.get<bool>("ghost_higher_d_neighbors");
44 });
45
46 // If the LM is ever a Lagrange variable, we will attempt to obtain its dof indices from the
47 // process that owns the node. However, in order for the dof indices to get set for the Lagrange
48 // variable, the process that owns the node needs to have local copies of any lower-d elements
49 // that have the connected node. Note that the geometric ghosting done here is different than that
50 // done by the AugmentSparsityOnInterface RM, even when ghost_point_neighbors is true. The latter
51 // ghosts equal-manifold lower-dimensional secondary element point neighbors, their interior
52 // parents, and their interface couplings. This ghosts lower-dimensional point neighbors of
53 // higher-dimensional elements.
54 // Neither is guaranteed to be a superset of the other. For instance ghosting of lower-d point
55 // neighbors (AugmentSparsityOnInterface with ghost_point_neighbors = true) is only guaranteed to
56 // ghost those lower-d point neighbors on *processes that own lower-d elements*. And you may have
57 // a process that only owns higher-dimensional elements
58 //
59 // Note that in my experience it is only important for the higher-d lower-d point neighbors to be
60 // ghosted when forming sparsity patterns and so I'm putting this here instead of at the
61 // MortarConsumerInterface level
62 params.addRelationshipManager("GhostHigherDLowerDPointNeighbors",
64
65 params.addParam<VariableName>("secondary_variable", "Primal variable on secondary surface.");
66 params.addParam<VariableName>(
67 "primary_variable",
68 "Primal variable on primary surface. If this parameter is not provided then the primary "
69 "variable will be initialized to the secondary variable");
70 params.makeParamNotRequired<NonlinearVariableName>("variable");
71 params.setDocString(
72 "variable",
73 "The name of the lagrange multiplier variable that this constraint is applied to. This "
74 "parameter may not be supplied in the case of using penalty methods for example");
75 params.addParam<bool>(
76 "compute_primal_residuals", true, "Whether to compute residuals for the primal variable.");
77 params.addParam<bool>(
78 "compute_lm_residuals", true, "Whether to compute Lagrange Multiplier residuals");
80 "quadrature",
81 MooseEnum("DEFAULT FIRST SECOND THIRD FOURTH", "DEFAULT"),
82 "Polynomial basis order (think Variable order) to assume when building quadrature rules to "
83 "use on mortar segments. "
84 "For 2D mortar DEFAULT is recommended. "
85 "For 3D mortar, QUAD meshes are integrated using triangular mortar segments. "
86 "While DEFAULT order is typically sufficiently accurate, exact integration of "
87 "QUAD mortar faces with first order polynomial bases (bilinears) requires building a "
88 "quadrature rule based off of a *quadratic* (SECOND) polynomial basis on triangles. "
89 "Similarly, exact integration of QUAD mortar faces with second order polynomial bases "
90 "(biquadratics) requires building a quadrature rule based off of a *quartic* (FOURTH) "
91 "polynomial basis on triangles. Note that the actual quadrature order will be double this "
92 "parameter plus one.",
93 "This parameter is deprecated in favor of "
94 "'segment_quadrature' which directly specifies the quadrature order.");
95 params.addParam<MooseEnum>(
96 "segment_quadrature",
97 MooseEnum("DEFAULT FIRST SECOND THIRD FOURTH FIFTH SIXTH SEVENTH EIGHTH NINTH", "DEFAULT"),
98 "Mortar segment quadrature order. "
99 "For 2D mortar DEFAULT is recommended. "
100 "For 3D mortar, quad faces are integrated using triangular mortar segments. "
101 "A finite element family of order p based on a quadrilateral element actually has polynomial "
102 "order of 2*p because of the tensor-product nature of the element. Consequently, for exact "
103 "integraton of something like a mass matrix term, if one is using a first order Lagrange "
104 "variable (as an example), the 'segment_quadrature' should be set to 'fourth' because we "
105 "double the polynomial order on the triangle to match the tensor product order on the quad, "
106 "and then double again since we are multiplying the test and trial (shape) function "
107 "polynomials for the mass matrix term.");
108 params.addParam<bool>(
109 "use_petrov_galerkin",
110 false,
111 "Whether to use the Petrov-Galerkin approach for the mortar-based constraints. If set to "
112 "true, we use the standard basis as the test function and dual basis as "
113 "the shape function for the interpolation of the Lagrange multiplier variable.");
114 params.addCoupledVar("aux_lm",
115 "Auxiliary Lagrange multiplier variable that is utilized together with the "
116 "Petrov-Galerkin approach.");
117 return params;
118}
119
121 : Constraint(parameters),
124 TwoMaterialPropertyInterface(this, Moose::EMPTY_BLOCK_IDS, getBoundaryIDs()),
125 MooseVariableInterface<Real>(this,
126 true,
127 isParamValid("variable") ? "variable" : "secondary_variable",
128 Moose::VarKindType::VAR_SOLVER,
129 Moose::VarFieldType::VAR_FIELD_STANDARD),
130 _fe_problem(*getCheckedPointerParam<FEProblemBase *>("_fe_problem_base")),
131 _var(isParamValid("variable")
132 ? &_subproblem.getStandardVariable(_tid, parameters.getMooseType("variable"))
133 : nullptr),
134 _secondary_var(
135 isParamValid("secondary_variable")
136 ? _sys.getActualFieldVariable<Real>(_tid, parameters.getMooseType("secondary_variable"))
137 : _sys.getActualFieldVariable<Real>(_tid, parameters.getMooseType("primary_variable"))),
138 _primary_var(
139 isParamValid("primary_variable")
140 ? _sys.getActualFieldVariable<Real>(_tid, parameters.getMooseType("primary_variable"))
141 : _secondary_var),
142
143 _compute_primal_residuals(getParam<bool>("compute_primal_residuals")),
144 _compute_lm_residuals(!_var ? false : getParam<bool>("compute_lm_residuals")),
145 _test_dummy(),
146 _use_dual(_var ? _var->useDual() : false),
147 _tangents(_assembly.tangents()),
148 _coord(_assembly.mortarCoordTransformation()),
149 _q_point(_assembly.qPointsMortar()),
150 _use_petrov_galerkin(getParam<bool>("use_petrov_galerkin")),
151 _aux_lm_var(isCoupled("aux_lm") ? getVar("aux_lm", 0) : nullptr),
152 _test(_var
153 ? ((_use_petrov_galerkin && _aux_lm_var) ? _aux_lm_var->phiLower() : _var->phiLower())
154 : _test_dummy),
155 _test_secondary(_secondary_var.phiFace()),
156 _test_primary(_primary_var.phiFaceNeighbor()),
157 _grad_test_secondary(_secondary_var.gradPhiFace()),
158 _grad_test_primary(_primary_var.gradPhiFaceNeighbor()),
159 _interior_secondary_elem(_assembly.elem()),
160 _interior_primary_elem(_assembly.neighbor()),
161 _displaced(getParam<bool>("use_displaced_mesh"))
162{
163 if (_use_dual)
165
167 paramError("use_petrov_galerkin",
168 "We need to set `use_dual = true` while using the Petrov-Galerkin approach");
169
170 if (_use_petrov_galerkin && ((!isParamValid("aux_lm")) || _aux_lm_var == nullptr))
171 paramError("use_petrov_galerkin",
172 "We need to specify an auxiliary variable `aux_lm` while using the Petrov-Galerkin "
173 "approach");
174
176 paramError("aux_lm",
177 "Auxiliary LM variable needs to use standard shape function, i.e., set `use_dual = "
178 "false`.");
179 if (isParamSetByUser("quadrature") && isParamSetByUser("segment_quadrature"))
180 paramError("quadrature", "Only one of 'quadrature' and 'segment_quadrature' should be set.");
181
182 // Note parameter is discretization order, we then convert to quadrature order
183 const auto & p_order = getParam<MooseEnum>("quadrature");
184 // If quadrature not DEFAULT, set mortar qrule
185 if (p_order != "DEFAULT")
186 {
187 const Order q_order = static_cast<Order>(2 * Utility::string_to_enum<Order>(p_order) + 1);
188 _assembly.setMortarQRule(q_order);
189 }
190 const auto & q_order_enum = getParam<MooseEnum>("segment_quadrature");
191 if (q_order_enum != "DEFAULT")
192 {
193 const Order q_order = Utility::string_to_enum<Order>(q_order_enum);
194 _assembly.setMortarQRule(q_order);
195 }
196
197 if (_var)
201}
202
203void
205{
207
209 {
210 // Compute the residual for the secondary interior primal dofs
212
213 // Compute the residual for the primary interior primal dofs.
215 }
216
218 // Compute the residual for the lower dimensional LM dofs (if we even have an LM variable)
220}
221
222void
224{
226
228 {
229 // Compute the jacobian for the secondary interior primal dofs
231
232 // Compute the jacobian for the primary interior primal dofs.
234 }
235
237 // Compute the jacobian for the lower dimensional LM dofs (if we even have an LM variable)
239}
240
241void
242MortarConstraintBase::zeroInactiveLMDofs(const std::unordered_set<const Node *> & inactive_lm_nodes,
243 const std::unordered_set<const Elem *> & inactive_lm_elems)
244{
245 // If no LM variable has been defined, skip
246 if (!_var)
247 return;
248
249 const auto sn = _sys.number();
250 const auto vn = _var->number();
251
252 // If variable is nodal, zero DoFs based on inactive LM nodes
253 if (_var->isNodal())
254 {
255 for (const auto node : inactive_lm_nodes)
256 {
257 // AutomaticMortarGeneration::computeInactiveLMNodes and
258 // computeIncorrectEdgeDroppingInactiveLMNodes only return nodes owned by this processor.
259 // The ownership check guarantees that no node is zeroed by more than one processor, which
260 // would add its Jacobian/residual contribution once per processor and over-constrain the
261 // dof.
262 if (node->processor_id() != _subproblem.processor_id())
263 continue;
264
265 // Allow mixed Lagrange orders between primal and LM
266 if (!node->n_comp(sn, vn))
267 continue;
268
269 const auto dof_index = node->dof_number(sn, vn, 0);
270 // No scaling; this is not physics
273 _assembly, /*element_value=*/1, dof_index, dof_index, /*scaling_factor=*/1);
275 {
276 const Real lm_value = _var->getNodalValue(*node);
278 std::array<Real, 1>{{lm_value}},
279 std::array<dof_id_type, 1>{{dof_index}},
280 /*scaling_factor=*/1);
281 }
282 }
283 }
284 // If variable is elemental, zero based on inactive LM elems
285 else
286 {
287 for (const auto el : inactive_lm_elems)
288 {
289 const auto n_comp = el->n_comp(sn, vn);
290
291 for (const auto comp : make_range(n_comp))
292 {
293 const auto dof_index = el->dof_number(sn, vn, comp);
294 // No scaling; this is not physics
297 _assembly, /*element_value=*/1, dof_index, dof_index, /*scaling_factor=*/1);
299 {
300 const Real lm_value = _var->getElementalValue(el, comp);
302 std::array<Real, 1>{{lm_value}},
303 std::array<dof_id_type, 1>{{dof_index}},
304 /*scaling_factor=*/1);
305 }
306 }
307 }
308 }
309}
bool computingResidual() const
Definition Assembly.h:1938
void activateDual()
Indicates that dual shape functions are used for mortar constraint.
Definition Assembly.h:609
void setMortarQRule(Order order)
Specifies a custom qrule for integration on mortar segment mesh.
Definition Assembly.C:772
bool computingJacobian() const
Definition Assembly.h:1943
Base class for all Constraint types.
Definition Constraint.h:20
static InputParameters validParams()
Definition Constraint.C:15
Specialization of SubProblem for solving nonlinear equations plus auxiliary equations.
The main MOOSE class responsible for handling user-defined parameters in almost every MOOSE system.
void addParam(const std::string &name, const S &value, const std::string &doc_string)
These methods add an optional parameter and a documentation string to the InputParameters object.
void addDeprecatedParam(const std::string &name, const T &value, const std::string &doc_string, const std::string &deprecation_message)
void setDocString(const std::string &name, const std::string &doc)
Set the doc string of a parameter.
std::vector< std::pair< R1, R2 > > get(const std::string &param1, const std::string &param2) const
Combine two vector parameters into a single vector of pairs.
void addRelationshipManager(const std::string &name, Moose::RelationshipManagerType rm_type, Moose::RelationshipManagerInputParameterCallback input_parameter_callback=nullptr)
Tells MOOSE about a RelationshipManager that this object needs.
void makeParamNotRequired(const std::string &name)
Changes the parameter to not be required.
T & set(const std::string &name, bool quiet_mode=false)
Returns a writable reference to the named parameters.
void addCoupledVar(const std::string &name, const std::string &doc_string)
This method adds a coupled variable name pair.
void paramError(const std::string &param, Args... args) const
Emits an error prefixed with the file and line number of the given param (from the input file) along ...
Definition MooseBase.h:457
bool isParamSetByUser(const std::string &name) const
Test if the supplied parameter is set by a user, as opposed to not set or set to default.
Definition MooseBase.h:205
bool isParamValid(const std::string &name) const
Test if the supplied parameter is valid.
Definition MooseBase.h:199
This is a "smart" enum class intended to replace many of the shortcomings in the C++ enum type It sho...
Definition MooseEnum.h:55
bool useDual() const
Get dual mortar option.
unsigned int number() const
Get variable number coming from libMesh.
void addMooseVariableDependency(MooseVariableFieldBase *var)
Call this function to add the passed in MooseVariableFieldBase as a variable that this object depends...
DofValue getElementalValue(const Elem *elem, unsigned int idx=0) const
Get the current value of this variable on an element.
DofValue getNodalValue(const Node &node) const
Get the value of this variable at given node.
bool isNodal() const override
Is this variable nodal.
Interface for objects that need to get values of MooseVariables.
const bool _use_dual
Whether to use the dual motar approach.
void zeroInactiveLMDofs(const std::unordered_set< const Node * > &inactive_lm_nodes, const std::unordered_set< const Elem * > &inactive_lm_elems)
A post routine for zeroing all inactive LM DoFs.
MooseVariableField< Real > & _primary_var
Reference to the primary variable.
MooseVariable *const _var
Pointer to the lagrange multipler variable. nullptr if none.
const bool _compute_primal_residuals
Whether to compute primal residuals.
static InputParameters validParams()
MooseVariableField< Real > & _secondary_var
Reference to the secondary variable.
const bool _compute_lm_residuals
Whether to compute lagrange multiplier residuals.
const bool _use_petrov_galerkin
Whether to use Petrov-Galerkin approach.
virtual void computeJacobian() override
Method for computing the Jacobian.
MortarConstraintBase(const InputParameters &parameters)
virtual void computeResidual() override
Method for computing the residual.
const MooseVariable *const _aux_lm_var
The auxiliary Lagrange multiplier variable (used together whith the Petrov-Galerkin approach)
An interface for accessing mortar mesh data.
static InputParameters validParams()
Intermediate base class that ties together all the interfaces for getting MooseVariables with the Moo...
Assembly & _assembly
Reference to this Kernel's assembly object.
SubProblem & _subproblem
Reference to this kernel's SubProblem.
SystemBase & _sys
Reference to the EquationSystem object.
virtual void precalculateResidual()
unsigned int number() const
Gets the number of this system.
void addJacobianElement(Assembly &assembly, Real value, dof_id_type row_index, dof_id_type column_index, Real scaling_factor)
Add into a single Jacobian element.
void addResiduals(Assembly &assembly, const Residuals &residuals, const Indices &dof_indices, Real scaling_factor)
Add the provided incoming residuals corresponding to the provided dof indices.
This interface is designed for DGKernel, InternalSideUserObject, InterfaceUserObject,...
processor_id_type processor_id() const
MOOSE now contains C++17 code, so give a reasonable error message stating what the user can do to add...