https://mooseframework.inl.gov
EqualValueEmbeddedConstraint.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 // MOOSE includes
11 #include "EigenADReal.h"
13 #include "FEProblem.h"
14 #include "DisplacedProblem.h"
15 #include "AuxiliarySystem.h"
16 #include "SystemBase.h"
17 #include "Assembly.h"
18 #include "MooseMesh.h"
19 #include "AddVariableAction.h"
20 
21 #include "libmesh/sparse_matrix.h"
22 
25 
26 template <bool is_ad>
29 {
32  params.addClassDescription("This is a constraint enforcing overlapping portions of two blocks to "
33  "have the same variable value");
34  params.set<bool>("use_displaced_mesh") = false;
35  MooseEnum formulation(getFormulationOptions(), "kinematic");
36  params.addParam<MooseEnum>(
37  "formulation", formulation, "Formulation used to enforce the constraint");
38  params.addRequiredParam<Real>(
39  "penalty",
40  "Penalty parameter used in constraint enforcement for kinematic and penalty formulations.");
41 
42  return params;
43 }
44 
45 template <bool is_ad>
47  const InputParameters & parameters)
48  : GenericNodeElemConstraint<is_ad>(parameters),
49  _displaced_problem(parameters.get<FEProblemBase *>("_fe_problem_base")->getDisplacedProblem()),
50  _fe_problem(*parameters.get<FEProblem *>("_fe_problem")),
51  _formulation(this->template getParam<MooseEnum>("formulation").template getEnum<Formulation>()),
52  _penalty(this->template getParam<Real>("penalty")),
53  _residual_copy(_sys.residualGhosted())
54 {
57  if constexpr (is_ad)
58  {
59  if (_formulation == Formulation::KINEMATIC)
60  this->paramError("formulation", "AD constraints cannot be used with KINEMATIC formulation.");
61  }
62 }
63 
64 template <bool is_ad>
65 void
67 {
68  // get mesh pointLocator
69  std::unique_ptr<libMesh::PointLocatorBase> pointLocator = _mesh.getPointLocator();
70  pointLocator->enable_out_of_mesh_mode();
71  const std::set<subdomain_id_type> allowed_subdomains{_primary};
72 
73  // secondary id and primary id
74  dof_id_type sid, mid;
75 
76  // prepare _secondary_to_primary_map
77  std::set<dof_id_type> unique_secondary_node_ids;
78  const MeshBase & meshhelper = _mesh.getMesh();
79  for (const auto & elem : as_range(meshhelper.active_subdomain_elements_begin(_secondary),
80  meshhelper.active_subdomain_elements_end(_secondary)))
81  {
82  for (auto & sn : elem->node_ref_range())
83  {
84  sid = sn.id();
85  if (_secondary_to_primary_map.find(sid) == _secondary_to_primary_map.end())
86  {
87  // primary element
88  const Elem * me = pointLocator->operator()(sn, &allowed_subdomains);
89  if (me != NULL)
90  {
91  mid = me->id();
92  _secondary_to_primary_map.insert(std::pair<dof_id_type, dof_id_type>(sid, mid));
93  _subproblem.addGhostedElem(mid);
94  }
95  }
96  }
97  }
98 }
99 
100 template <bool is_ad>
101 bool
103 {
104  // primary element
105  auto it = _secondary_to_primary_map.find(_current_node->id());
106 
107  if (it != _secondary_to_primary_map.end())
108  {
109  const Elem * primary_elem = _mesh.elemPtr(it->second);
110  std::vector<Point> points = {*_current_node};
111 
112  // reinit variables on the primary element at the secondary point
113  _fe_problem.setNeighborSubdomainID(primary_elem, 0);
114  _fe_problem.reinitNeighborPhys(primary_elem, points, 0);
115 
116  reinitConstraint();
117 
118  return true;
119  }
120  return false;
121 }
122 
123 template <bool is_ad>
124 void
126 {
127  const Node * node = _current_node;
128  unsigned int sys_num = _sys.number();
129  dof_id_type dof_number = node->dof_number(sys_num, _var.number(), 0);
130 
131  switch (_formulation)
132  {
133  case Formulation::KINEMATIC:
134  _constraint_residual = -_residual_copy(dof_number);
135  break;
136 
137  case Formulation::PENALTY:
138  _constraint_residual = _penalty * (_u_secondary[0] - _u_primary[0]);
139  break;
140 
141  default:
142  mooseError("Invalid formulation");
143  break;
144  }
145 }
146 
147 template <bool is_ad>
148 Real
150 {
151  return MetaPhysicL::raw_value(_u_secondary[_qp]);
152 }
153 
154 template <bool is_ad>
157 {
158  GenericReal<is_ad> resid = _constraint_residual;
159 
160  switch (type)
161  {
162  case Moose::Secondary:
163  {
164  if (_formulation == Formulation::KINEMATIC)
165  {
166  GenericReal<is_ad> pen_force = _penalty * (_u_secondary[_qp] - _u_primary[_qp]);
167  resid += pen_force;
168  }
169  return _test_secondary[_i][_qp] * resid;
170  }
171 
172  case Moose::Primary:
173  return _test_primary[_i][_qp] * -resid;
174  }
175 
176  return 0.0;
177 }
178 
179 template <bool is_ad>
180 Real
182 {
183  mooseAssert(!is_ad,
184  "In ADEqualValueEmbeddedConstraint, computeQpJacobian should not be called. "
185  "Check computeJacobian implementation.");
186 
187  unsigned int sys_num = _sys.number();
188  const Real penalty = MetaPhysicL::raw_value(_penalty);
189  Real curr_jac, secondary_jac;
190 
191  switch (type)
192  {
194  switch (_formulation)
195  {
196  case Formulation::KINEMATIC:
197  curr_jac = (*_jacobian)(_current_node->dof_number(sys_num, _var.number(), 0),
198  _connected_dof_indices[_j]);
199  return -curr_jac + _phi_secondary[_j][_qp] * penalty * _test_secondary[_i][_qp];
200  case Formulation::PENALTY:
201  return _phi_secondary[_j][_qp] * penalty * _test_secondary[_i][_qp];
202  default:
203  mooseError("Invalid formulation");
204  }
205 
207  switch (_formulation)
208  {
209  case Formulation::KINEMATIC:
210  return -_phi_primary[_j][_qp] * penalty * _test_secondary[_i][_qp];
211  case Formulation::PENALTY:
212  return -_phi_primary[_j][_qp] * penalty * _test_secondary[_i][_qp];
213  default:
214  mooseError("Invalid formulation");
215  }
216 
218  switch (_formulation)
219  {
220  case Formulation::KINEMATIC:
221  secondary_jac = (*_jacobian)(_current_node->dof_number(sys_num, _var.number(), 0),
222  _connected_dof_indices[_j]);
223  return secondary_jac * _test_primary[_i][_qp];
224  case Formulation::PENALTY:
225  return -_phi_secondary[_j][_qp] * penalty * _test_primary[_i][_qp];
226  default:
227  mooseError("Invalid formulation");
228  }
229 
231  switch (_formulation)
232  {
233  case Formulation::KINEMATIC:
234  return 0.0;
235  case Formulation::PENALTY:
236  return _test_primary[_i][_qp] * penalty * _phi_primary[_j][_qp];
237  default:
238  mooseError("Invalid formulation");
239  }
240 
241  default:
242  mooseError("Unsupported type");
243  break;
244  }
245  return 0.0;
246 }
247 
248 template <bool is_ad>
249 Real
251  Moose::ConstraintJacobianType type, unsigned int /*jvar*/)
252 {
253  mooseAssert(!is_ad,
254  "In ADEqualValueEmbeddedConstraint, computeQpOffDiagJacobian should not be called. "
255  "Check computeJacobian implementation.");
256 
257  Real curr_jac, secondary_jac;
258  unsigned int sys_num = _sys.number();
259 
260  switch (type)
261  {
263  curr_jac = (*_jacobian)(_current_node->dof_number(sys_num, _var.number(), 0),
264  _connected_dof_indices[_j]);
265  return -curr_jac;
266 
268  return 0.0;
269 
271  switch (_formulation)
272  {
273  case Formulation::KINEMATIC:
274  secondary_jac = (*_jacobian)(_current_node->dof_number(sys_num, _var.number(), 0),
275  _connected_dof_indices[_j]);
276  return secondary_jac * _test_primary[_i][_qp];
277  case Formulation::PENALTY:
278  return 0.0;
279  default:
280  mooseError("Invalid formulation");
281  }
282 
284  return 0.0;
285 
286  default:
287  mooseError("Unsupported type");
288  break;
289  }
290 
291  return 0.0;
292 }
293 
virtual GenericReal< is_ad > computeQpResidual(Moose::ConstraintType type) override
This is the virtual method that derived classes should override for computing the residual...
Moose::GenericType< Real, is_ad > GenericReal
Definition: MooseTypes.h:693
ConstraintType
Definition: MooseTypes.h:806
virtual Real computeQpJacobian(Moose::ConstraintJacobianType type) override
This is the virtual method that derived classes should override for computing the Jacobian...
A EqualValueEmbeddedConstraint forces the value of a variable to be the same on overlapping portion o...
virtual void reinitConstraint()
Prepare the residual contribution of the current constraint required to enforce it based on the speci...
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
Specialization of SubProblem for solving nonlinear equations plus auxiliary equations.
Definition: FEProblem.h:20
void mooseError(Args &&... args)
Emit an error message with the given stringified, concatenated args and terminate the application...
Definition: MooseError.h:311
virtual void prepareSecondaryToPrimaryMap() override
prepare the _secondary_to_primary_map (see NodeElemConstraintBase)
T & set(const std::string &name, bool quiet_mode=false)
Returns a writable reference to the named parameters.
auto raw_value(const Eigen::Map< T > &in)
Definition: EigenADReal.h:100
The main MOOSE class responsible for handling user-defined parameters in almost every MOOSE system...
bool _overwrite_secondary_residual
Whether or not the secondary&#39;s residual should be overwritten.
Specialization of SubProblem for solving nonlinear equations plus auxiliary equations.
void addRequiredParam(const std::string &name, const std::string &doc_string)
This method adds a parameter and documentation string to the InputParameters object that will be extr...
static MooseEnum getNonlinearVariableOrders()
Get the possible variable orders.
registerMooseObject("MooseApp", EqualValueEmbeddedConstraint)
bool shouldApply() override final
Whether or not this constraint should be applied.
SimpleRange< IndexType > as_range(const std::pair< IndexType, IndexType > &p)
This is a "smart" enum class intended to replace many of the shortcomings in the C++ enum type It sho...
Definition: MooseEnum.h:54
virtual Real computeQpOffDiagJacobian(Moose::ConstraintJacobianType type, unsigned int jvar) override
This is the virtual method that derived classes should override for computing the off-diag Jacobian...
virtual Real computeQpSecondaryValue() override
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
ConstraintJacobianType
Definition: MooseTypes.h:845
void addClassDescription(const std::string &doc_string)
This method adds a description of the class that will be displayed in the input file syntax dump...
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...
EqualValueEmbeddedConstraintTempl(const InputParameters &parameters)
static InputParameters validParams()
const Elem & get(const ElemType type_in)
uint8_t dof_id_type