https://mooseframework.inl.gov
WeightedGapUserObject.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 "WeightedGapUserObject.h"
11 #include "MooseVariableField.h"
12 #include "SubProblem.h"
13 #include "MortarUtils.h"
14 #include "MooseUtils.h"
15 #include "MortarContactUtils.h"
16 
17 #include "libmesh/quadrature.h"
18 
19 #include <limits>
20 
23 {
27  params.addRequiredCoupledVar("disp_x", "The x displacement variable");
28  params.addRequiredCoupledVar("disp_y", "The y displacement variable");
29  params.addCoupledVar("disp_z", "The z displacement variable");
30  params.set<bool>("use_displaced_mesh") = true;
31  params.set<bool>("interpolate_normals") = false;
32  params.set<ExecFlagEnum>("execute_on") = {EXEC_LINEAR, EXEC_NONLINEAR};
33  params.suppressParameter<ExecFlagEnum>("execute_on");
34  return params;
35 }
36 
38  : MortarUserObject(parameters),
39  _fe_problem(*getCheckedPointerParam<FEProblemBase *>("_fe_problem_base")),
40  _nodal(getVar("disp_x", 0)->feType().family == LAGRANGE),
41  _disp_x_var(getVar("disp_x", 0)),
42  _disp_y_var(getVar("disp_y", 0)),
43  _has_disp_z(isCoupled("disp_z")),
44  _disp_z_var(_has_disp_z ? getVar("disp_z", 0) : nullptr),
45  _secondary_disp_x(_disp_x_var->adSln()),
46  _primary_disp_x(_disp_x_var->adSlnNeighbor()),
47  _secondary_disp_y(_disp_y_var->adSln()),
48  _primary_disp_y(_disp_y_var->adSlnNeighbor()),
49  _secondary_disp_z(_has_disp_z ? &_disp_z_var->adSln() : nullptr),
50  _primary_disp_z(_has_disp_z ? &_disp_z_var->adSlnNeighbor() : nullptr),
51  _coord(_assembly.mortarCoordTransformation())
52 {
53  if (!getParam<bool>("use_displaced_mesh"))
54  paramError("use_displaced_mesh",
55  "'use_displaced_mesh' must be true for the WeightedGapUserObject object");
56 }
57 
58 void
60 {
62  _test = &test();
63 }
64 
65 void
67 {
68  // Trim interior node variable derivatives
69  const auto & primary_ip_lowerd_map = amg().getPrimaryIpToLowerElementMap(
71  const auto & secondary_ip_lowerd_map =
73 
74  std::array<const MooseVariable *, 3> var_array{{_disp_x_var, _disp_y_var, _disp_z_var}};
75  std::array<ADReal, 3> primary_disp{
76  {_primary_disp_x[_qp], _primary_disp_y[_qp], _has_disp_z ? (*_primary_disp_z)[_qp] : 0}};
77  std::array<ADReal, 3> secondary_disp{{_secondary_disp_x[_qp],
79  _has_disp_z ? (*_secondary_disp_z)[_qp] : 0}};
80 
81  trimInteriorNodeDerivatives(primary_ip_lowerd_map, var_array, primary_disp, false);
82  trimInteriorNodeDerivatives(secondary_ip_lowerd_map, var_array, secondary_disp, true);
83 
84  const ADReal & prim_x = primary_disp[0];
85  const ADReal & prim_y = primary_disp[1];
86  const ADReal * prim_z = nullptr;
87  if (_has_disp_z)
88  prim_z = &primary_disp[2];
89 
90  const ADReal & sec_x = secondary_disp[0];
91  const ADReal & sec_y = secondary_disp[1];
92  const ADReal * sec_z = nullptr;
93  if (_has_disp_z)
94  sec_z = &secondary_disp[2];
95 
96  // Compute gap vector
98 
99  // Generic displacement for interface problems
100  _qp_displacement_nodal(0) = prim_x - sec_x;
101  _qp_displacement_nodal(1) = prim_y - sec_y;
102  if (_has_disp_z)
103  _qp_displacement_nodal(2) = *prim_z - *sec_z;
104 
106 
107  gap_vec(0).derivatives() = prim_x.derivatives() - sec_x.derivatives();
108  gap_vec(1).derivatives() = prim_y.derivatives() - sec_y.derivatives();
109  if (_has_disp_z)
110  gap_vec(2).derivatives() = prim_z->derivatives() - sec_z->derivatives();
111 
112  // Compute integration point quantities: Normals (geometry) is averaged at the node, but not
113  // interpolated within the weak integration.
114  _qp_gap_nodal = gap_vec * (_JxW_msm[_qp] * _coord[_qp]);
115 
116  // To do normalization of constraint coefficient (c_n)
118 }
119 
120 void
122 {
123  mooseAssert(_normals.size() == _lower_secondary_elem->n_nodes(),
124  "Making sure that _normals is the expected size");
125 
126  // Get the _dof_to_weighted_gap map
127  const auto * const dof = static_cast<const DofObject *>(_lower_secondary_elem->node_ptr(_i));
128 
129  auto & [weighted_gap, normalization] = _dof_to_weighted_gap[dof];
130 
131  weighted_gap += (*_test)[_i][_qp] * _qp_gap_nodal * _normals[_i];
132  normalization += (*_test)[_i][_qp] * _qp_factor;
133 
135 }
136 
137 void
139 {
140  _dof_to_weighted_gap.clear();
142 }
143 
144 void
146 {
147  // If the constraint is performed by the owner, then we don't need any data sent back; the owner
148  // will take care of it. But if the constraint is not performed by the owner and we might have to
149  // do some of the constraining ourselves, then we need data sent back to us
150  const bool send_data_back = !constrainedByOwner();
152  _subproblem.mesh(),
153  _nodal,
154  /*normalize_c*/ true,
156  send_data_back);
157 }
158 
159 void
161 {
162  for (_qp = 0; _qp < _qrule_msm->n_points(); _qp++)
163  {
165  for (_i = 0; _i < _test->size(); ++_i)
167  }
168 }
169 
170 Real
171 WeightedGapUserObject::getNormalGap(const Node * const node) const
172 {
173  const auto it = _dof_to_weighted_gap.find(_subproblem.mesh().nodePtr(node->id()));
174 
175  // We are returning the physical weighted gap for analysis purposes
176  if (it != _dof_to_weighted_gap.end())
177  return physicalGap(it->second);
178  else
179  return 0.0;
180 }
virtual MooseMesh & mesh()=0
LAGRANGE
static InputParameters validParams()
unsigned int _qp
Quadrature point index for the mortar segments.
const ADVariableValue & _secondary_disp_y
y-displacement on the secondary face
std::map< unsigned int, unsigned int > getPrimaryIpToLowerElementMap(const Elem &primary_elem, const Elem &primary_elem_ip, const Elem &lower_secondary_elem) const
Real _qp_factor
The value of the LM at the current quadrature point.
virtual const VariableTestValue & test() const =0
virtual void initialSetup() override
WeightedGapUserObject(const InputParameters &parameters)
T & set(const std::string &name, bool quiet_mode=false)
virtual void initialize() override
const MooseVariable *const _disp_z_var
The z displacement variable.
static InputParameters validParams()
ADRealVectorValue _qp_displacement_nodal
Vector for computation of relative displacement (determines mixity ratio in interface problems) ...
std::unordered_map< const DofObject *, ADRealVectorValue > _dof_to_weighted_displacements
A map from node to weighted displacements.
const MooseArray< Point > & _phys_points_primary
Elem const *const & _lower_primary_elem
const ADVariableValue & _secondary_disp_x
x-displacement on the secondary face
const bool _nodal
Whether the dof objects are nodal; if they&#39;re not, then they&#39;re elemental.
const bool _has_disp_z
For 2D mortar contact no displacement will be specified, so const pointers used.
const ADVariableValue & _primary_disp_x
x-displacement on the primary face
const std::vector< Real > & _JxW_msm
const Parallel::Communicator & _communicator
ADRealVectorValue _qp_gap_nodal
Vector for computation of weighted gap with nodal normals.
DualNumber< Real, DNDerivativeType, true > ADReal
const libMesh::QBase *const & _qrule_msm
void suppressParameter(const std::string &name)
SubProblem & _subproblem
void communicateGaps(std::unordered_map< const DofObject *, std::pair< ADReal, Real >> &dof_to_weighted_gap, const MooseMesh &mesh, bool nodal, bool normalize_c, const Parallel::Communicator &communicator, bool send_data_back)
This function is used to communicate gaps across processes.
virtual Real getNormalGap(const Node *const) const
Elem const *const & _lower_secondary_elem
const AutomaticMortarGeneration & amg() const
static void trimInteriorNodeDerivatives(const std::map< unsigned int, unsigned int > &primary_ip_lowerd_map, const Variables &moose_var, DualNumbers &ad_vars, const bool is_secondary)
const ADVariableValue & _primary_disp_y
y-displacement on the primary face
std::vector< Point > _normals
const VariableTestValue * _test
A pointer to the test function associated with the weighted gap.
virtual const Node * nodePtr(const dof_id_type i) const
virtual void computeQpProperties()
Computes properties that are functions only of the current quadrature point (_qp), e.g.
unsigned int n_points() const
std::map< unsigned int, unsigned int > getSecondaryIpToLowerElementMap(const Elem &lower_secondary_elem) const
void paramError(const std::string &param, Args... args) const
const MooseArray< Point > & _phys_points_secondary
const ExecFlagType EXEC_LINEAR
virtual void execute() override
void addCoupledVar(const std::string &name, const std::string &doc_string)
void addRequiredCoupledVar(const std::string &name, const std::string &doc_string)
const MooseArray< Real > & _coord
Member for handling change of coordinate systems (xyz, rz, spherical)
const ExecFlagType EXEC_NONLINEAR
DIE A HORRIBLE DEATH HERE typedef LIBMESH_DEFAULT_SCALAR_TYPE Real
const MooseVariable *const _disp_y_var
The y displacement variable.
static InputParameters validParams()
static InputParameters validParams()
virtual bool constrainedByOwner() const =0
unsigned int _i
Test function index.
Real physicalGap(const std::pair< ADReal, Real > &gap) const
Compute physical gap from integration gap quantity.
const MooseVariable *const _disp_x_var
The x displacement variable.
virtual void initialSetup()
virtual void computeQpIProperties()
Computes properties that are functions both of _qp and _i, for example the weighted gap...
std::unordered_map< const DofObject *, std::pair< ADReal, Real > > _dof_to_weighted_gap
A map from node to weighted gap and normalization (if requested)
virtual void finalize() override