https://mooseframework.inl.gov
Loading...
Searching...
No Matches
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
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
59void
65
66void
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
121void
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
138void
144
145void
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();
154 _nodal,
155 /*normalize_c*/ true,
157 send_data_back);
158}
159
160void
162{
163 for (_qp = 0; _qp < _qrule_msm->n_points(); _qp++)
164 {
166 for (_i = 0; _i < _test->size(); ++_i)
168 }
169}
170
171Real
172WeightedGapUserObject::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}
DualNumber< Real, DNDerivativeType, true > ADReal
const ExecFlagType EXEC_LINEAR
const ExecFlagType EXEC_NONLINEAR
std::map< unsigned int, unsigned int > getSecondaryIpToLowerElementMap(const Elem &lower_secondary_elem) const
std::map< unsigned int, unsigned int > getPrimaryIpToLowerElementMap(const Elem &primary_elem, const Elem &primary_elem_ip, const Elem &lower_secondary_elem) const
void suppressParameter(const std::string &name)
void addRequiredCoupledVar(const std::string &name, const std::string &doc_string)
T & set(const std::string &name, bool quiet_mode=false)
void addCoupledVar(const std::string &name, const std::string &doc_string)
void paramError(const std::string &param, Args... args) const
virtual const Node * nodePtr(const dof_id_type i) const
static InputParameters validParams()
Elem const *const & _lower_secondary_elem
const libMesh::QBase *const & _qrule_msm
const AutomaticMortarGeneration & amg() const
Elem const *const & _lower_primary_elem
const MooseArray< Point > & _phys_points_secondary
const MooseArray< Point > & _phys_points_primary
std::vector< Point > _normals
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 std::vector< Real > & _JxW_msm
static InputParameters validParams()
virtual void initialSetup()
virtual MooseMesh & mesh()=0
static InputParameters validParams()
SubProblem & _subproblem
static InputParameters validParams()
unsigned int _i
Test function index.
const ADVariableValue & _secondary_disp_x
x-displacement on the secondary face
const MooseVariable *const _disp_x_var
The x displacement variable.
virtual void computeQpProperties()
Computes properties that are functions only of the current quadrature point (_qp),...
const bool _has_disp_z
For 2D mortar contact no displacement will be specified, so const pointers used.
virtual void finalize() override
virtual void execute() override
ADRealVectorValue _qp_gap_nodal
Vector for computation of weighted gap with nodal normals.
virtual void initialSetup() override
unsigned int _qp
Quadrature point index for the mortar segments.
Real _qp_factor
The value of the LM at the current quadrature point.
virtual Real getNormalGap(const Node *const) const
const ADVariableValue & _primary_disp_y
y-displacement on the primary face
const MooseArray< Real > & _coord
Member for handling change of coordinate systems (xyz, rz, spherical)
const ADVariableValue & _secondary_disp_y
y-displacement on the secondary face
const ADVariableValue & _primary_disp_x
x-displacement on the primary face
const MooseVariable *const _disp_y_var
The y displacement variable.
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 const VariableTestValue & test() const =0
WeightedGapUserObject(const InputParameters &parameters)
const MooseVariable *const _disp_z_var
The z displacement variable.
ADRealVectorValue _qp_displacement_nodal
Vector for computation of relative displacement (determines mixity ratio in interface problems)
virtual void computeQpIProperties()
Computes properties that are functions both of _qp and _i, for example the weighted gap.
virtual void initialize() override
std::unordered_map< const DofObject *, ADRealVectorValue > _dof_to_weighted_displacements
A map from node to weighted displacements.
virtual bool constrainedByOwner() const =0
Real physicalGap(const std::pair< ADReal, Real > &gap) const
Compute physical gap from integration gap quantity.
const VariableTestValue * _test
A pointer to the test function associated with the weighted gap.
const bool _nodal
Whether the dof objects are nodal; if they're not, then they're elemental.
const Parallel::Communicator & _communicator
unsigned int n_points() const
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.