https://mooseframework.inl.gov
NodeFaceConstraint.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 "NodeFaceConstraint.h"
11 
12 // MOOSE includes
13 #include "Assembly.h"
14 #include "MooseEnum.h"
15 #include "MooseMesh.h"
16 #include "MooseVariableFE.h"
17 #include "PenetrationLocator.h"
18 #include "SystemBase.h"
19 
20 #include "libmesh/string_to_enum.h"
21 
24 {
25  MooseEnum orders("FIRST SECOND THIRD FOURTH", "FIRST");
27  params.addParam<BoundaryName>("secondary", "The boundary ID associated with the secondary side");
28  params.addParam<BoundaryName>("primary", "The boundary ID associated with the primary side");
29  params.addParam<Real>("tangential_tolerance",
30  "Tangential distance to extend edges of contact surfaces");
31  params.addParam<Real>(
32  "normal_smoothing_distance",
33  "Distance from edge in parametric coordinates over which to smooth contact normal");
34  params.addParam<std::string>("normal_smoothing_method",
35  "Method to use to smooth normals (edge_based|nodal_normal_based)");
36  params.addParam<MooseEnum>("order", orders, "The finite element order used for projections");
37  params.addParam<bool>(
38  "ghost_whole_interface",
39  false,
40  "Whether to geometrically and algebraically ghost the entire primary side of the interface "
41  "for node-face constraints.");
43  "GhostPrimaryFace",
45  [](const InputParameters & obj_params, InputParameters & rm_params)
46  {
47  const auto enabled = obj_params.get<bool>("ghost_whole_interface");
48  rm_params.set<bool>("enabled") = enabled;
49  // If we don't actually want this object to ghost anything, then let's not have it impede
50  // possibly early (more like on-time) remote element deletion
51  rm_params.set<bool>("attach_geometric_early") = !enabled;
52  rm_params.set<bool>("use_displaced_mesh") = obj_params.get<bool>("use_displaced_mesh");
53  rm_params.set<BoundaryName>("secondary_boundary") =
54  obj_params.get<BoundaryName>("secondary");
55  rm_params.set<BoundaryName>("primary_boundary") = obj_params.get<BoundaryName>("primary");
56  });
57 
58  params.addCoupledVar("primary_variable", "The variable on the primary side of the domain");
59 
60  return params;
61 }
62 
64  : Constraint(parameters),
65  // The secondary side is at nodes (hence passing 'true'). The neighbor side is the primary side
66  // and it is not at nodes (so passing false)
70  _secondary(_mesh.getBoundaryID(getParam<BoundaryName>("secondary"))),
71  _primary(_mesh.getBoundaryID(getParam<BoundaryName>("primary"))),
72  _var(_sys.getFieldVariable<Real>(_tid, parameters.get<NonlinearVariableName>("variable"))),
73 
74  _primary_q_point(_assembly.qPointsFace()),
75  _primary_qrule(_assembly.qRuleFace()),
76 
77  _penetration_locator(
78  getPenetrationLocator(getParam<BoundaryName>("primary"),
79  getParam<BoundaryName>("secondary"),
80  Utility::string_to_enum<Order>(getParam<MooseEnum>("order")))),
81 
82  _current_node(_var.node()),
83  _current_primary(_var.neighbor()),
84  _u_secondary(_var.dofValues()),
85  _phi_secondary(1), // One entry
86  _test_secondary(1), // One entry
87 
88  _primary_var(*getVar("primary_variable", 0)),
89  _primary_var_num(_primary_var.number()),
90 
91  _phi_primary(_assembly.phiFaceNeighbor(_primary_var)),
92  _grad_phi_primary(_assembly.gradPhiFaceNeighbor(_primary_var)),
93 
94  _test_primary(_var.phiFaceNeighbor()),
95  _grad_test_primary(_var.gradPhiFaceNeighbor()),
96 
97  _u_primary(_primary_var.slnNeighbor()),
98  _grad_u_primary(_primary_var.gradSlnNeighbor()),
99 
100  _dof_map(_sys.dofMap()),
101  _node_to_elem_map(_mesh.nodeToElemMap()),
102 
103  _overwrite_secondary_residual(true),
104  _primary_JxW(_assembly.JxWNeighbor())
105 {
107 
108  if (parameters.isParamValid("tangential_tolerance"))
109  {
110  _penetration_locator.setTangentialTolerance(getParam<Real>("tangential_tolerance"));
111  }
112  if (parameters.isParamValid("normal_smoothing_distance"))
113  {
114  _penetration_locator.setNormalSmoothingDistance(getParam<Real>("normal_smoothing_distance"));
115  }
116  if (parameters.isParamValid("normal_smoothing_method"))
117  {
119  parameters.get<std::string>("normal_smoothing_method"));
120  }
121  // Put a "1" into test_secondary
122  // will always only have one entry that is 1
123  _test_secondary[0].push_back(1);
124 }
125 
127 {
129  _test_secondary.release();
130 }
131 
132 void
134 {
135  const dof_id_type & dof_idx = _var.nodalDofIndex();
136  _qp = 0;
137  current_solution.set(dof_idx, computeQpSecondaryValue());
138 }
139 
140 void
142 {
144 }
145 
146 Real
148 {
149  mooseAssert(_secondary_residual_computed,
150  "The secondary residual has not yet been computed, so the value will be garbage!");
151  return _secondary_residual;
152 }
153 
154 void
156 {
157  _qp = 0;
158 
160  for (_i = 0; _i < _test_primary.size(); _i++)
163 
165  _i = 0;
169 }
170 
171 void
173 {
175 
178 
180 
181  _qp = 0;
182 
183  // Fill up _phi_secondary so that it is 1 when j corresponds to this dof and 0 for every other dof
184  // This corresponds to evaluating all of the connected shape functions at _this_ node
185  for (unsigned int j = 0; j < _connected_dof_indices.size(); j++)
186  {
187  _phi_secondary[j].resize(1);
188 
190  _phi_secondary[j][_qp] = 1.0;
191  else
192  _phi_secondary[j][_qp] = 0.0;
193  }
194 
195  for (_i = 0; _i < _test_secondary.size(); _i++)
196  // Loop over the connected dof indices so we can get all the jacobian contributions
197  for (_j = 0; _j < _connected_dof_indices.size(); _j++)
199 
200  // Just do a direct assignment here because the Jacobian coming from assembly has already been
201  // properly sized according to the neighbor _var dof indices. It has also been zeroed
203  if (_Ken.m() && _Ken.n())
204  for (_i = 0; _i < _test_secondary.size(); _i++)
205  for (_j = 0; _j < _phi_primary.size(); _j++)
207  // Don't accumulate here
208 
209  for (_i = 0; _i < _test_primary.size(); _i++)
210  // Loop over the connected dof indices so we can get all the jacobian contributions
211  for (_j = 0; _j < _connected_dof_indices.size(); _j++)
213 
216  if (_local_ke.m() && _local_ke.n())
217  for (_i = 0; _i < _test_primary.size(); _i++)
218  for (_j = 0; _j < _phi_primary.size(); _j++)
221 }
222 
223 void
224 NodeFaceConstraint::computeOffDiagJacobian(const unsigned int jvar_num)
225 {
226  getConnectedDofIndices(jvar_num);
227 
230 
232 
233  _qp = 0;
234 
235  auto primary_jsize = getVariable(jvar_num).dofIndicesNeighbor().size();
236 
237  // Fill up _phi_secondary so that it is 1 when j corresponds to this dof and 0 for every other dof
238  // This corresponds to evaluating all of the connected shape functions at _this_ node
239  for (unsigned int j = 0; j < _connected_dof_indices.size(); j++)
240  {
241  _phi_secondary[j].resize(1);
242 
244  _phi_secondary[j][_qp] = 1.0;
245  else
246  _phi_secondary[j][_qp] = 0.0;
247  }
248 
249  for (_i = 0; _i < _test_secondary.size(); _i++)
250  // Loop over the connected dof indices so we can get all the jacobian contributions
251  for (_j = 0; _j < _connected_dof_indices.size(); _j++)
253 
254  // Just do a direct assignment here because the Jacobian coming from assembly has already been
255  // properly sized according to the jvar neighbor dof indices. It has also been zeroed
257  for (_i = 0; _i < _test_secondary.size(); _i++)
258  for (_j = 0; _j < primary_jsize; _j++)
260  // Don't accumulate here
261 
262  if (_Kne.m() && _Kne.n())
263  for (_i = 0; _i < _test_primary.size(); _i++)
264  // Loop over the connected dof indices so we can get all the jacobian contributions
265  for (_j = 0; _j < _connected_dof_indices.size(); _j++)
267 
269  for (_i = 0; _i < _test_primary.size(); _i++)
270  for (_j = 0; _j < primary_jsize; _j++)
273 }
274 
275 void
277 {
278  MooseVariableFEBase & var = _sys.getVariable(0, var_num);
279 
280  _connected_dof_indices.clear();
281  std::set<dof_id_type> unique_dof_indices;
282 
283  auto node_to_elem_pair = _node_to_elem_map.find(_current_node->id());
284  mooseAssert(node_to_elem_pair != _node_to_elem_map.end(), "Missing entry in node to elem map");
285  const std::vector<dof_id_type> & elems = node_to_elem_pair->second;
286 
287  // Get the dof indices from each elem connected to the node
288  for (const auto & cur_elem : elems)
289  {
290  std::vector<dof_id_type> dof_indices;
291 
292  var.getDofIndices(_mesh.elemPtr(cur_elem), dof_indices);
293 
294  for (const auto & dof : dof_indices)
295  unique_dof_indices.insert(dof);
296  }
297 
298  for (const auto & dof : unique_dof_indices)
299  _connected_dof_indices.push_back(dof);
300 }
301 
302 bool
304 {
306 }
307 
308 const std::set<BoundaryID> &
310 {
311  _boundary_ids.insert(_primary);
312  _boundary_ids.insert(_secondary);
313  return _boundary_ids;
314 }
315 
316 std::set<SubdomainID>
318 {
320 }
MooseMesh & _mesh
Reference to this Kernel&#39;s mesh object.
bool _secondary_residual_computed
Whether the secondary residual has been computed.
VarFieldType
Definition: MooseTypes.h:770
BoundaryID _secondary
Boundary ID for the secondary surface.
virtual void computeResidual() override
Computes the residual Nodal residual.
Order
void accumulateTaggedLocalResidual()
Local residual blocks will be appended by adding the current local kernel residual.
virtual void computeSecondaryValue(NumericVector< Number > &current_solution)
Compute the value the secondary node should have at the beginning of a timestep.
Intermediate base class that ties together all the interfaces for getting MooseVariables with the Moo...
virtual Elem * elemPtr(const dof_id_type i)
Definition: MooseMesh.C:3213
void setNormalSmoothingDistance(Real normal_smoothing_distance)
MooseVariable & _var
unsigned int number() const
Get variable number coming from libMesh.
virtual Real computeQpResidual(Moose::ConstraintType type)=0
This is the virtual that derived classes should override for computing the residual on neighboring el...
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.
const std::unordered_map< dof_id_type, std::vector< dof_id_type > > & _node_to_elem_map
MooseVariable & _primary_var
Primary side variable.
std::set< SubdomainID > getSecondaryConnectedBlocks() const
const InputParameters & parameters() const
Get the parameters of the object.
Definition: MooseBase.h:131
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.
DenseMatrix< Number > _Kne
The Jacobian corresponding to the derivatives of the neighbor/primary residual with respect to the el...
Real secondaryResidual() const
void assignTaggedLocalResidual()
Local residual blocks will assigned as the current local kernel residual.
DenseMatrix< Number > _Ken
The Jacobian corresponding to the derivatives of the elemental/secondary residual with respect to the...
The main MOOSE class responsible for handling user-defined parameters in almost every MOOSE system...
static InputParameters validParams()
virtual void getDofIndices(const Elem *, std::vector< dof_id_type > &) const
unsigned int m() const
This class provides an interface for common operations on field variables of both FE and FV types wit...
unsigned int _i
Definition: Constraint.h:35
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.
const VariableTestValue & _test_primary
Side test function.
void setTangentialTolerance(Real tangential_tolerance)
DenseMatrix< Number > _local_ke
Holds local Jacobian entries as they are accumulated by this Kernel.
const MooseVariableFieldBase & getVariable(unsigned int jvar_num) const
Retrieve the variable object from our system associated with jvar_num.
void residualSetup() override
Gets called just before the residual is computed and before this object is asked to do its job...
const Node *const & _current_node
current node being processed
DenseMatrix< Number > _Kee
The Jacobian corresponding to the derivatives of the elemental/secondary residual with respect to the...
SystemBase & _sys
Reference to the EquationSystem object.
void prepareMatrixTagNeighbor(Assembly &assembly, unsigned int ivar, unsigned int jvar, Moose::DGJacobianType type)
Prepare data for computing element jacobian according to the active tags for DG and interface kernels...
BoundaryID getBoundaryID(const BoundaryName &boundary_name, const MeshBase &mesh)
Gets the boundary ID associated with the given BoundaryName.
unsigned int _j
Definition: Constraint.h:35
NodeFaceConstraint(const InputParameters &parameters)
Enhances MooseVariableInterface interface provide values from neighbor elements.
virtual const std::vector< dof_id_type > & dofIndicesNeighbor() const =0
Get neighbor DOF indices for currently selected element.
unsigned int size() const
The number of elements that can currently be stored in the array.
Definition: MooseArray.h:259
virtual void computeJacobian() override
Computes the jacobian for the current element.
std::set< BoundaryID > _boundary_ids
the union of the secondary and primary boundary ids
T string_to_enum(const std::string &s)
VarKindType
Framework-wide stuff.
Definition: MooseTypes.h:763
virtual void getConnectedDofIndices(unsigned int var_num)
Gets the indices for all dofs connected to the constraint.
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::set< SubdomainID > getBoundaryConnectedBlocks(const BoundaryID bid) const
Get the list of subdomains associated with the given boundary.
Definition: MooseMesh.C:3621
Real _secondary_residual
The value of the secondary residual.
void accumulateTaggedLocalMatrix()
Local Jacobian blocks will be appended by adding the current local kernel Jacobian.
const std::set< BoundaryID > & buildBoundaryIDs()
Builds the _boundary_ids data member and returns it.
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.
virtual void computeOffDiagJacobian(unsigned int jvar) override
Computes d-residual / d-jvar...
VariableTestValue _test_secondary
Shape function on the secondary side. This will always only have one entry and that entry will always...
void addMooseVariableDependency(MooseVariableFieldBase *var)
Call this function to add the passed in MooseVariableFieldBase as a variable that this object depends...
void prepareVectorTagNeighbor(Assembly &assembly, unsigned int ivar)
Prepare data for computing element residual the according to active tags for DG and interface kernels...
virtual Real computeQpSecondaryValue()=0
Compute the value the secondary node should have at the beginning of a timestep.
DIE A HORRIBLE DEATH HERE typedef LIBMESH_DEFAULT_SCALAR_TYPE Real
const dof_id_type & nodalDofIndex() const override
void release()
Manually deallocates the data pointer.
Definition: MooseArray.h:66
DenseVector< Number > _local_re
Holds local residual entries as they are accumulated by this Kernel.
void resize(const unsigned int new_m, const unsigned int new_n)
void resize(unsigned int size)
Change the number of elements the array can store.
Definition: MooseArray.h:216
std::vector< dof_id_type > _connected_dof_indices
const VariablePhiValue & _phi_primary
Side shape function.
BoundaryID _primary
Boundary ID for the primary surface.
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 _overwrite_secondary_residual
Whether or not the secondary&#39;s residual should be overwritten.
virtual void set(const numeric_index_type i, const Number value)=0
VariablePhiValue _phi_secondary
Shape function on the secondary side. This will always.
MOOSE now contains C++17 code, so give a reasonable error message stating what the user can do to add...
void setNormalSmoothingMethod(std::string nsmString)
MooseVariableFieldBase & getVariable(THREAD_ID tid, const std::string &var_name) const
Gets a reference to a variable of with specified name.
Definition: SystemBase.C:91
unsigned int n() const
PenetrationLocator & _penetration_locator
void prepareVectorTag(Assembly &assembly, unsigned int ivar)
Prepare data for computing element residual according to active tags.
virtual bool overwriteSecondaryResidual()
Whether or not the secondary&#39;s residual should be overwritten.
static InputParameters validParams()
Definition: Constraint.C:15
virtual Real computeQpJacobian(Moose::ConstraintJacobianType type)=0
This is the virtual that derived classes should override for computing the Jacobian on neighboring el...
unsigned int _qp
Definition: Constraint.h:36
virtual bool enabled() const
Return the enabled status of the object.
Definition: MooseObject.h:49
const Elem & get(const ElemType type_in)
virtual Real computeQpOffDiagJacobian(Moose::ConstraintJacobianType, unsigned int)
This is the virtual that derived classes should override for computing the off-diag Jacobian...
uint8_t dof_id_type
bool isParamValid(const std::string &name) const
This method returns parameters that have been initialized in one fashion or another, i.e.