https://mooseframework.inl.gov
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 
10 #include "MortarConstraintBase.h"
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",
61 
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),
123  true,
124  isParamValid("variable") ? "variable" : "secondary_variable",
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 
200 void
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 
219 void
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 
238 void
239 MortarConstraintBase::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 }
VarFieldType
Definition: MooseTypes.h:770
MooseVariableField< Real > & _secondary_var
Reference to the secondary variable.
Order
void setMortarQRule(Order order)
Specifies a custom qrule for integration on mortar segment mesh.
Definition: Assembly.C:735
void addDeprecatedParam(const std::string &name, const T &value, const std::string &doc_string, const std::string &deprecation_message)
Intermediate base class that ties together all the interfaces for getting MooseVariables with the Moo...
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:467
void setDocString(const std::string &name, const std::string &doc)
Set the doc string of a parameter.
unsigned int number() const
Get variable number coming from libMesh.
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 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.
Base class for all Constraint types.
Definition: Constraint.h:19
T & set(const std::string &name, bool quiet_mode=false)
Returns a writable reference to the named parameters.
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.
virtual void precalculateResidual()
The main MOOSE class responsible for handling user-defined parameters in almost every MOOSE system...
const bool _compute_primal_residuals
Whether to compute primal residuals.
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.
Specialization of SubProblem for solving nonlinear equations plus auxiliary equations.
MortarConstraintBase(const InputParameters &parameters)
virtual void computeResidual() override
Method for computing the residual.
An interface for accessing mortar mesh data.
static InputParameters validParams()
SystemBase & _sys
Reference to the EquationSystem object.
bool useDual() const
Get dual mortar option.
VarKindType
Framework-wide stuff.
Definition: MooseTypes.h:763
This is a "smart" enum class intended to replace many of the shortcomings in the C++ enum type It sho...
Definition: MooseEnum.h:54
std::vector< BoundaryID > getBoundaryIDs(const libMesh::MeshBase &mesh, const std::vector< BoundaryName > &boundary_name, bool generate_unknown, const std::set< BoundaryID > &mesh_boundary_ids)
Gets the boundary IDs with their names.
unsigned int number() const
Gets the number of this system.
Definition: SystemBase.C:1158
const bool _use_dual
Whether to use the dual motar approach.
Assembly & _assembly
Reference to this Kernel&#39;s assembly object.
void addCoupledVar(const std::string &name, const std::string &doc_string)
This method adds a coupled variable name pair.
bool isNodal() const override
Is this variable nodal.
void makeParamNotRequired(const std::string &name)
Changes the parameter to not be required.
MooseVariable *const _var
Pointer to the lagrange multipler variable. nullptr if none.
void addMooseVariableDependency(MooseVariableFieldBase *var)
Call this function to add the passed in MooseVariableFieldBase as a variable that this object depends...
const bool _use_petrov_galerkin
Whether to use Petrov-Galerkin approach.
DIE A HORRIBLE DEATH HERE typedef LIBMESH_DEFAULT_SCALAR_TYPE Real
const std::set< SubdomainID > EMPTY_BLOCK_IDS
Definition: MooseTypes.h:732
bool computingResidual() const
Definition: Assembly.h:1945
const MooseVariable *const _aux_lm_var
The auxiliary Lagrange multiplier variable (used together whith the Petrov-Galerkin approach) ...
void activateDual()
Indicates that dual shape functions are used for mortar constraint.
Definition: Assembly.h:617
static InputParameters validParams()
DofValue getNodalValue(const Node &node) const
Get the value of this variable at given node.
virtual void computeJacobian() override
Method for computing the Jacobian.
Interface for objects that need to get values of MooseVariables.
IntRange< T > make_range(T beg, T end)
This interface is designed for DGKernel, InternalSideUserObject, InterfaceUserObject, where material properties on a side of both its primary side (face) and its secondary side (neighbor) all required.
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...
bool isParamValid(const std::string &name) const
Test if the supplied parameter is valid.
Definition: MooseBase.h:209
MOOSE now contains C++17 code, so give a reasonable error message stating what the user can do to add...
bool computingJacobian() const
Definition: Assembly.h:1950
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.
DofValue getElementalValue(const Elem *elem, unsigned int idx=0) const
Get the current value of this variable on an element.
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:215
static InputParameters validParams()
Definition: Constraint.C:15
const bool _compute_lm_residuals
Whether to compute lagrange multiplier residuals.
MooseVariableField< Real > & _primary_var
Reference to the primary variable.