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"
17 
18 #include "libmesh/quadrature.h"
19 
20 #include <limits>
21 
24 {
28  params.addRequiredCoupledVar("disp_x", "The x displacement variable");
29  params.addRequiredCoupledVar("disp_y", "The y displacement variable");
30  params.addCoupledVar("disp_z", "The z displacement variable");
31  params.set<bool>("use_displaced_mesh") = true;
32  params.set<bool>("interpolate_normals") = false;
33  params.set<ExecFlagEnum>("execute_on") = {EXEC_LINEAR, EXEC_NONLINEAR};
34  params.suppressParameter<ExecFlagEnum>("execute_on");
35  return params;
36 }
37 
39  : MortarUserObject(parameters),
40  _fe_problem(*getCheckedPointerParam<FEProblemBase *>("_fe_problem_base")),
41  _nodal(getVar("disp_x", 0)->feType().family == LAGRANGE),
42  _disp_x_var(getVar("disp_x", 0)),
43  _disp_y_var(getVar("disp_y", 0)),
44  _has_disp_z(isCoupled("disp_z")),
45  _disp_z_var(_has_disp_z ? getVar("disp_z", 0) : nullptr),
46  _secondary_disp_x(_disp_x_var->adSln()),
47  _primary_disp_x(_disp_x_var->adSlnNeighbor()),
48  _secondary_disp_y(_disp_y_var->adSln()),
49  _primary_disp_y(_disp_y_var->adSlnNeighbor()),
50  _secondary_disp_z(_has_disp_z ? &_disp_z_var->adSln() : nullptr),
51  _primary_disp_z(_has_disp_z ? &_disp_z_var->adSlnNeighbor() : nullptr),
52  _coord(_assembly.mortarCoordTransformation())
53 {
54  if (!getParam<bool>("use_displaced_mesh"))
55  paramError("use_displaced_mesh",
56  "'use_displaced_mesh' must be true for the WeightedGapUserObject object");
57 }
58 
59 void
61 {
63  _test = &test();
64 }
65 
66 void
68 {
69  // Trim interior node variable derivatives
70  const auto & primary_ip_lowerd_map = amg().getPrimaryIpToLowerElementMap(
72  const auto & secondary_ip_lowerd_map =
74 
75  std::array<const MooseVariable *, 3> var_array{{_disp_x_var, _disp_y_var, _disp_z_var}};
76  std::array<ADReal, 3> primary_disp{
77  {_primary_disp_x[_qp], _primary_disp_y[_qp], _has_disp_z ? (*_primary_disp_z)[_qp] : 0}};
78  std::array<ADReal, 3> secondary_disp{{_secondary_disp_x[_qp],
80  _has_disp_z ? (*_secondary_disp_z)[_qp] : 0}};
81 
82  trimInteriorNodeDerivatives(primary_ip_lowerd_map, var_array, primary_disp, false);
83  trimInteriorNodeDerivatives(secondary_ip_lowerd_map, var_array, secondary_disp, true);
84 
85  const ADReal & prim_x = primary_disp[0];
86  const ADReal & prim_y = primary_disp[1];
87  const ADReal * prim_z = nullptr;
88  if (_has_disp_z)
89  prim_z = &primary_disp[2];
90 
91  const ADReal & sec_x = secondary_disp[0];
92  const ADReal & sec_y = secondary_disp[1];
93  const ADReal * sec_z = nullptr;
94  if (_has_disp_z)
95  sec_z = &secondary_disp[2];
96 
97  // Compute gap vector
99 
100  // Generic displacement for interface problems
101  _qp_displacement_nodal(0) = prim_x - sec_x;
102  _qp_displacement_nodal(1) = prim_y - sec_y;
103  if (_has_disp_z)
104  _qp_displacement_nodal(2) = *prim_z - *sec_z;
105 
107 
108  gap_vec(0).derivatives() = prim_x.derivatives() - sec_x.derivatives();
109  gap_vec(1).derivatives() = prim_y.derivatives() - sec_y.derivatives();
110  if (_has_disp_z)
111  gap_vec(2).derivatives() = prim_z->derivatives() - sec_z->derivatives();
112 
113  // Compute integration point quantities: Normals (geometry) is averaged at the node, but not
114  // interpolated within the weak integration.
115  _qp_gap_nodal = gap_vec * (_JxW_msm[_qp] * _coord[_qp]);
116 
117  // To do normalization of constraint coefficient (c_n)
119 }
120 
121 void
123 {
124  mooseAssert(_normals.size() == _lower_secondary_elem->n_nodes(),
125  "Making sure that _normals is the expected size");
126 
127  // Get the _dof_to_weighted_gap map
128  const auto * const dof = static_cast<const DofObject *>(_lower_secondary_elem->node_ptr(_i));
129 
130  auto & [weighted_gap, normalization] = _dof_to_weighted_gap[dof];
131 
132  weighted_gap += (*_test)[_i][_qp] * _qp_gap_nodal * _normals[_i];
133  normalization += (*_test)[_i][_qp] * _qp_factor;
134 
136 }
137 
138 void
140 {
141  _dof_to_weighted_gap.clear();
143 }
144 
145 void
147 {
148  // If the constraint is performed by the owner, then we don't need any data sent back; the owner
149  // will take care of it. But if the constraint is not performed by the owner and we might have to
150  // do some of the constraining ourselves, then we need data sent back to us
151  const bool send_data_back = !constrainedByOwner();
153  _subproblem.mesh(),
154  _nodal,
155  /*normalize_c*/ true,
157  send_data_back);
158 }
159 
160 void
162 {
163  for (_qp = 0; _qp < _qrule_msm->n_points(); _qp++)
164  {
166  for (_i = 0; _i < _test->size(); ++_i)
168  }
169 }
170 
171 Real
172 WeightedGapUserObject::getNormalGap(const Node * const node) const
173 {
174  const auto it = _dof_to_weighted_gap.find(_subproblem.mesh().nodePtr(node->id()));
175 
176  // We are returning the physical weighted gap for analysis purposes
177  if (it != _dof_to_weighted_gap.end())
178  return physicalGap(it->second);
179  else
180  return 0.0;
181 }
virtual MooseMesh & mesh()=0
LAGRANGE
static InputParameters validParams()
unsigned int _qp
Quadrature point index for the mortar segments.
void paramError(const std::string &param, Args... args) const
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
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