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_higher_d_neighbors") =
41 obj_params.get<bool>("ghost_higher_d_neighbors");
42 });
43
44 // If the LM is ever a Lagrange variable, we will attempt to obtain its dof indices from the
45 // process that owns the node. However, in order for the dof indices to get set for the Lagrange
46 // variable, the process that owns the node needs to have local copies of any lower-d elements
47 // that have the connected node. Note that the geometric ghosting done here is different than that
48 // done by the AugmentSparsityOnInterface RM, even when ghost_point_neighbors is true. The latter
49 // ghosts equal-manifold lower-dimensional secondary element point neighbors and their interface
50 // couplings. This ghosts lower-dimensional point neighbors of higher-dimensional elements.
51 // Neither is guaranteed to be a superset of the other. For instance ghosting of lower-d point
52 // neighbors (AugmentSparsityOnInterface with ghost_point_neighbors = true) is only guaranteed to
53 // ghost those lower-d point neighbors on *processes that own lower-d elements*. And you may have
54 // a process that only owns higher-dimensional elements
55 //
56 // Note that in my experience it is only important for the higher-d lower-d point neighbors to be
57 // ghosted when forming sparsity patterns and so I'm putting this here instead of at the
58 // MortarConsumerInterface level
59 params.addRelationshipManager("GhostHigherDLowerDPointNeighbors",
62 params.addParam<VariableName>("secondary_variable", "Primal variable on secondary surface.");
63 params.addParam<VariableName>(
64 "primary_variable",
65 "Primal variable on primary surface. If this parameter is not provided then the primary "
66 "variable will be initialized to the secondary variable");
67 params.makeParamNotRequired<NonlinearVariableName>("variable");
68 params.setDocString(
69 "variable",
70 "The name of the lagrange multiplier variable that this constraint is applied to. This "
71 "parameter may not be supplied in the case of using penalty methods for example");
72 params.addParam<bool>(
73 "compute_primal_residuals", true, "Whether to compute residuals for the primal variable.");
74 params.addParam<bool>(
75 "compute_lm_residuals", true, "Whether to compute Lagrange Multiplier residuals");
77 "quadrature",
78 MooseEnum("DEFAULT FIRST SECOND THIRD FOURTH", "DEFAULT"),
79 "Polynomial basis order (think Variable order) to assume when building quadrature rules to "
80 "use on mortar segments. "
81 "For 2D mortar DEFAULT is recommended. "
82 "For 3D mortar, QUAD meshes are integrated using triangular mortar segments. "
83 "While DEFAULT order is typically sufficiently accurate, exact integration of "
84 "QUAD mortar faces with first order polynomial bases (bilinears) requires building a "
85 "quadrature rule based off of a *quadratic* (SECOND) polynomial basis on triangles. "
86 "Similarly, exact integration of QUAD mortar faces with second order polynomial bases "
87 "(biquadratics) requires building a quadrature rule based off of a *quartic* (FOURTH) "
88 "polynomial basis on triangles. Note that the actual quadrature order will be double this "
89 "parameter plus one.",
90 "This parameter is deprecated in favor of "
91 "'segment_quadrature' which directly specifies the quadrature order.");
92 params.addParam<MooseEnum>(
93 "segment_quadrature",
94 MooseEnum("DEFAULT FIRST SECOND THIRD FOURTH FIFTH SIXTH SEVENTH EIGHTH NINTH", "DEFAULT"),
95 "Mortar segment quadrature order. "
96 "For 2D mortar DEFAULT is recommended. "
97 "For 3D mortar, quad faces are integrated using triangular mortar segments. "
98 "A finite element family of order p based on a quadrilateral element actually has polynomial "
99 "order of 2*p because of the tensor-product nature of the element. Consequently, for exact "
100 "integraton of something like a mass matrix term, if one is using a first order Lagrange "
101 "variable (as an example), the 'segment_quadrature' should be set to 'fourth' because we "
102 "double the polynomial order on the triangle to match the tensor product order on the quad, "
103 "and then double again since we are multiplying the test and trial (shape) function "
104 "polynomials for the mass matrix term.");
105 params.addParam<bool>(
106 "use_petrov_galerkin",
107 false,
108 "Whether to use the Petrov-Galerkin approach for the mortar-based constraints. If set to "
109 "true, we use the standard basis as the test function and dual basis as "
110 "the shape function for the interpolation of the Lagrange multiplier variable.");
111 params.addCoupledVar("aux_lm",
112 "Auxiliary Lagrange multiplier variable that is utilized together with the "
113 "Petrov-Galerkin approach.");
114 return params;
115}
116
118 : Constraint(parameters),
121 TwoMaterialPropertyInterface(this, Moose::EMPTY_BLOCK_IDS, getBoundaryIDs()),
122 MooseVariableInterface<Real>(this,
123 true,
124 isParamValid("variable") ? "variable" : "secondary_variable",
125 Moose::VarKindType::VAR_SOLVER,
126 Moose::VarFieldType::VAR_FIELD_STANDARD),
127 _fe_problem(*getCheckedPointerParam<FEProblemBase *>("_fe_problem_base")),
128 _var(isParamValid("variable")
129 ? &_subproblem.getStandardVariable(_tid, parameters.getMooseType("variable"))
130 : nullptr),
131 _secondary_var(
132 isParamValid("secondary_variable")
133 ? _sys.getActualFieldVariable<Real>(_tid, parameters.getMooseType("secondary_variable"))
134 : _sys.getActualFieldVariable<Real>(_tid, parameters.getMooseType("primary_variable"))),
135 _primary_var(
136 isParamValid("primary_variable")
137 ? _sys.getActualFieldVariable<Real>(_tid, parameters.getMooseType("primary_variable"))
138 : _secondary_var),
139
140 _compute_primal_residuals(getParam<bool>("compute_primal_residuals")),
141 _compute_lm_residuals(!_var ? false : getParam<bool>("compute_lm_residuals")),
142 _test_dummy(),
143 _use_dual(_var ? _var->useDual() : false),
144 _tangents(_assembly.tangents()),
145 _coord(_assembly.mortarCoordTransformation()),
146 _q_point(_assembly.qPointsMortar()),
147 _use_petrov_galerkin(getParam<bool>("use_petrov_galerkin")),
148 _aux_lm_var(isCoupled("aux_lm") ? getVar("aux_lm", 0) : nullptr),
149 _test(_var
150 ? ((_use_petrov_galerkin && _aux_lm_var) ? _aux_lm_var->phiLower() : _var->phiLower())
151 : _test_dummy),
152 _test_secondary(_secondary_var.phiFace()),
153 _test_primary(_primary_var.phiFaceNeighbor()),
154 _grad_test_secondary(_secondary_var.gradPhiFace()),
155 _grad_test_primary(_primary_var.gradPhiFaceNeighbor()),
156 _interior_secondary_elem(_assembly.elem()),
157 _interior_primary_elem(_assembly.neighbor()),
158 _displaced(getParam<bool>("use_displaced_mesh"))
159{
160 if (_use_dual)
162
164 paramError("use_petrov_galerkin",
165 "We need to set `use_dual = true` while using the Petrov-Galerkin approach");
166
167 if (_use_petrov_galerkin && ((!isParamValid("aux_lm")) || _aux_lm_var == nullptr))
168 paramError("use_petrov_galerkin",
169 "We need to specify an auxiliary variable `aux_lm` while using the Petrov-Galerkin "
170 "approach");
171
173 paramError("aux_lm",
174 "Auxiliary LM variable needs to use standard shape function, i.e., set `use_dual = "
175 "false`.");
176 if (isParamSetByUser("quadrature") && isParamSetByUser("segment_quadrature"))
177 paramError("quadrature", "Only one of 'quadrature' and 'segment_quadrature' should be set.");
178
179 // Note parameter is discretization order, we then convert to quadrature order
180 const auto & p_order = getParam<MooseEnum>("quadrature");
181 // If quadrature not DEFAULT, set mortar qrule
182 if (p_order != "DEFAULT")
183 {
184 const Order q_order = static_cast<Order>(2 * Utility::string_to_enum<Order>(p_order) + 1);
185 _assembly.setMortarQRule(q_order);
186 }
187 const auto & q_order_enum = getParam<MooseEnum>("segment_quadrature");
188 if (q_order_enum != "DEFAULT")
189 {
190 const Order q_order = Utility::string_to_enum<Order>(q_order_enum);
191 _assembly.setMortarQRule(q_order);
192 }
193
194 if (_var)
198}
199
200void
202{
204
206 {
207 // Compute the residual for the secondary interior primal dofs
209
210 // Compute the residual for the primary interior primal dofs.
212 }
213
215 // Compute the residual for the lower dimensional LM dofs (if we even have an LM variable)
217}
218
219void
221{
223
225 {
226 // Compute the jacobian for the secondary interior primal dofs
228
229 // Compute the jacobian for the primary interior primal dofs.
231 }
232
234 // Compute the jacobian for the lower dimensional LM dofs (if we even have an LM variable)
236}
237
238void
239MortarConstraintBase::zeroInactiveLMDofs(const std::unordered_set<const Node *> & inactive_lm_nodes,
240 const std::unordered_set<const Elem *> & inactive_lm_elems)
241{
242 // If no LM variable has been defined, skip
243 if (!_var)
244 return;
245
246 const auto sn = _sys.number();
247 const auto vn = _var->number();
248
249 // If variable is nodal, zero DoFs based on inactive LM nodes
250 if (_var->isNodal())
251 {
252 for (const auto node : inactive_lm_nodes)
253 {
254 // Allow mixed Lagrange orders between primal and LM
255 if (!node->n_comp(sn, vn))
256 continue;
257
258 const auto dof_index = node->dof_number(sn, vn, 0);
259 // No scaling; this is not physics
262 _assembly, /*element_value=*/1, dof_index, dof_index, /*scaling_factor=*/1);
264 {
265 const Real lm_value = _var->getNodalValue(*node);
267 std::array<Real, 1>{{lm_value}},
268 std::array<dof_id_type, 1>{{dof_index}},
269 /*scaling_factor=*/1);
270 }
271 }
272 }
273 // If variable is elemental, zero based on inactive LM elems
274 else
275 {
276 for (const auto el : inactive_lm_elems)
277 {
278 const auto n_comp = el->n_comp(sn, vn);
279
280 for (const auto comp : make_range(n_comp))
281 {
282 const auto dof_index = el->dof_number(sn, vn, comp);
283 // No scaling; this is not physics
286 _assembly, /*element_value=*/1, dof_index, dof_index, /*scaling_factor=*/1);
288 {
289 const Real lm_value = _var->getElementalValue(el, comp);
291 std::array<Real, 1>{{lm_value}},
292 std::array<dof_id_type, 1>{{dof_index}},
293 /*scaling_factor=*/1);
294 }
295 }
296 }
297 }
298}
bool computingResidual() const
Definition Assembly.h:1946
void activateDual()
Indicates that dual shape functions are used for mortar constraint.
Definition Assembly.h:617
void setMortarQRule(Order order)
Specifies a custom qrule for integration on mortar segment mesh.
Definition Assembly.C:737
bool computingJacobian() const
Definition Assembly.h:1951
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.
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,...
MOOSE now contains C++17 code, so give a reasonable error message stating what the user can do to add...