www.mooseframework.org
Assembly.C
Go to the documentation of this file.
1 //* This file is part of the MOOSE framework
2 //* https://www.mooseframework.org
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 "Assembly.h"
11 
12 // MOOSE includes
13 #include "SubProblem.h"
14 #include "ArbitraryQuadrature.h"
15 #include "SystemBase.h"
16 #include "MooseTypes.h"
17 #include "MooseMesh.h"
18 #include "MooseVariableFE.h"
19 #include "MooseVariableScalar.h"
20 #include "XFEMInterface.h"
21 #include "DisplacedSystem.h"
22 #include "MooseMeshUtils.h"
23 
24 // libMesh
25 #include "libmesh/coupling_matrix.h"
26 #include "libmesh/dof_map.h"
27 #include "libmesh/elem.h"
28 #include "libmesh/equation_systems.h"
29 #include "libmesh/fe_interface.h"
30 #include "libmesh/node.h"
31 #include "libmesh/quadrature_gauss.h"
32 #include "libmesh/sparse_matrix.h"
33 #include "libmesh/tensor_value.h"
34 #include "libmesh/vector_value.h"
35 #include "libmesh/fe.h"
36 
37 template <typename P, typename C>
38 void
40  const SubdomainID sub_id,
41  const P & point,
42  C & factor,
43  const SubdomainID neighbor_sub_id)
44 {
45  coordTransformFactor(s.mesh(), sub_id, point, factor, neighbor_sub_id);
46 }
47 
48 template <typename P, typename C>
49 void
51  const SubdomainID sub_id,
52  const P & point,
53  C & factor,
54  const SubdomainID libmesh_dbg_var(neighbor_sub_id))
55 {
56  mooseAssert(neighbor_sub_id != libMesh::Elem::invalid_subdomain_id
57  ? mesh.getCoordSystem(sub_id) == mesh.getCoordSystem(neighbor_sub_id)
58  : true,
59  "Coordinate systems must be the same between element and neighbor");
60  const auto coord_type = mesh.getCoordSystem(sub_id);
61 
62  if (coord_type == Moose::COORD_RZ)
63  {
64  if (mesh.usingGeneralAxisymmetricCoordAxes())
65  {
66  const auto & axis = mesh.getGeneralAxisymmetricCoordAxis(sub_id);
68  }
69  else
71  point, factor, coord_type, mesh.getAxisymmetricRadialCoord());
72  }
73  else
75 }
76 
78  : _sys(sys),
79  _subproblem(_sys.subproblem()),
80  _displaced(dynamic_cast<DisplacedSystem *>(&sys) ? true : false),
81  _nonlocal_cm(_subproblem.nonlocalCouplingMatrix(_sys.number())),
82  _computing_residual(_subproblem.currentlyComputingResidual()),
83  _computing_jacobian(_subproblem.currentlyComputingJacobian()),
84  _computing_residual_and_jacobian(_subproblem.currentlyComputingResidualAndJacobian()),
85  _dof_map(_sys.dofMap()),
86  _tid(tid),
87  _mesh(sys.mesh()),
88  _mesh_dimension(_mesh.dimension()),
89  _helper_type(_mesh.hasSecondOrderElements() ? SECOND : FIRST, LAGRANGE),
90  _user_added_fe_of_helper_type(false),
91  _user_added_fe_face_of_helper_type(false),
92  _user_added_fe_face_neighbor_of_helper_type(false),
93  _user_added_fe_neighbor_of_helper_type(false),
94  _user_added_fe_lower_of_helper_type(false),
95  _building_helpers(false),
96  _current_qrule(nullptr),
97  _current_qrule_volume(nullptr),
98  _current_qrule_arbitrary(nullptr),
99  _coord_type(Moose::COORD_XYZ),
100  _current_qrule_face(nullptr),
101  _current_qface_arbitrary(nullptr),
102  _current_qrule_neighbor(nullptr),
103  _need_JxW_neighbor(false),
104  _qrule_msm(nullptr),
105  _custom_mortar_qrule(false),
106  _current_qrule_lower(nullptr),
107 
108  _current_elem(nullptr),
109  _current_elem_volume(0),
110  _current_side(0),
111  _current_side_elem(nullptr),
112  _current_side_volume(0),
113  _current_neighbor_elem(nullptr),
114  _current_neighbor_side(0),
115  _current_neighbor_side_elem(nullptr),
116  _need_neighbor_elem_volume(false),
117  _current_neighbor_volume(0),
118  _current_node(nullptr),
119  _current_neighbor_node(nullptr),
120  _current_elem_volume_computed(false),
121  _current_side_volume_computed(false),
122 
123  _current_lower_d_elem(nullptr),
124  _current_neighbor_lower_d_elem(nullptr),
125  _need_lower_d_elem_volume(false),
126  _need_neighbor_lower_d_elem_volume(false),
127  _need_dual(false),
128 
129  _residual_vector_tags(_subproblem.getVectorTags(Moose::VECTOR_TAG_RESIDUAL)),
130  _cached_residual_values(2), // The 2 is for TIME and NONTIME
131  _cached_residual_rows(2), // The 2 is for TIME and NONTIME
132  _max_cached_residuals(0),
133  _max_cached_jacobians(0),
134 
135  _block_diagonal_matrix(false),
136  _calculate_xyz(false),
137  _calculate_face_xyz(false),
138  _calculate_curvatures(false),
139  _calculate_ad_coord(false),
140  _have_p_refinement(false)
141 {
142  const Order helper_order = _mesh.hasSecondOrderElements() ? SECOND : FIRST;
143  _building_helpers = true;
144  // Build fe's for the helpers
145  buildFE(FEType(helper_order, LAGRANGE));
146  buildFaceFE(FEType(helper_order, LAGRANGE));
147  buildNeighborFE(FEType(helper_order, LAGRANGE));
148  buildFaceNeighborFE(FEType(helper_order, LAGRANGE));
149  buildLowerDFE(FEType(helper_order, LAGRANGE));
150  _building_helpers = false;
151 
152  // Build an FE helper object for this type for each dimension up to the dimension of the current
153  // mesh
154  for (unsigned int dim = 0; dim <= _mesh_dimension; dim++)
155  {
156  _holder_fe_helper[dim] = _fe[dim][FEType(helper_order, LAGRANGE)];
157  _holder_fe_face_helper[dim] = _fe_face[dim][FEType(helper_order, LAGRANGE)];
159  _holder_fe_neighbor_helper[dim] = _fe_neighbor[dim][FEType(helper_order, LAGRANGE)];
160  }
161 
162  for (unsigned int dim = 0; dim < _mesh_dimension; dim++)
163  _holder_fe_lower_helper[dim] = _fe_lower[dim][FEType(helper_order, LAGRANGE)];
164 
165  // request phi, dphi, xyz, JxW, etc. data
167 
168  // For 3D mortar, mortar segments are always TRI3 elements so we want FIRST LAGRANGE regardless
169  // of discretization
170  _fe_msm = (_mesh_dimension == 2)
171  ? FEGenericBase<Real>::build(_mesh_dimension - 1, FEType(helper_order, LAGRANGE))
172  : FEGenericBase<Real>::build(_mesh_dimension - 1, FEType(FIRST, LAGRANGE));
173  // This FE object should not take part in p-refinement
174  _fe_msm->add_p_level_in_reinit(false);
175  _JxW_msm = &_fe_msm->get_JxW();
176  // Prerequest xyz so that it is computed for _fe_msm so that it can be used for calculating
177  // _coord_msm
178  _fe_msm->get_xyz();
179 
180  _extra_elem_ids.resize(_mesh.getMesh().n_elem_integers() + 1);
181  _neighbor_extra_elem_ids.resize(_mesh.getMesh().n_elem_integers() + 1);
182 }
183 
185 {
186  for (unsigned int dim = 0; dim <= _mesh_dimension; dim++)
187  for (auto & it : _fe[dim])
188  delete it.second;
189 
190  for (unsigned int dim = 0; dim <= _mesh_dimension; dim++)
191  for (auto & it : _fe_face[dim])
192  delete it.second;
193 
194  for (unsigned int dim = 0; dim <= _mesh_dimension; dim++)
195  for (auto & it : _fe_neighbor[dim])
196  delete it.second;
197 
198  for (unsigned int dim = 0; dim <= _mesh_dimension; dim++)
199  for (auto & it : _fe_face_neighbor[dim])
200  delete it.second;
201 
202  for (unsigned int dim = 0; dim <= _mesh_dimension - 1; dim++)
203  for (auto & it : _fe_lower[dim])
204  delete it.second;
205 
206  for (unsigned int dim = 0; dim <= _mesh_dimension; dim++)
207  for (auto & it : _vector_fe[dim])
208  delete it.second;
209 
210  for (unsigned int dim = 0; dim <= _mesh_dimension; dim++)
211  for (auto & it : _vector_fe_face[dim])
212  delete it.second;
213 
214  for (unsigned int dim = 0; dim <= _mesh_dimension; dim++)
215  for (auto & it : _vector_fe_neighbor[dim])
216  delete it.second;
217 
218  for (unsigned int dim = 0; dim <= _mesh_dimension; dim++)
219  for (auto & it : _vector_fe_face_neighbor[dim])
220  delete it.second;
221 
222  for (unsigned int dim = 0; dim <= _mesh_dimension - 1; dim++)
223  for (auto & it : _vector_fe_lower[dim])
224  delete it.second;
225 
226  for (auto & it : _ad_grad_phi_data)
227  it.second.release();
228 
229  for (auto & it : _ad_vector_grad_phi_data)
230  it.second.release();
231 
232  for (auto & it : _ad_grad_phi_data_face)
233  it.second.release();
234 
235  for (auto & it : _ad_vector_grad_phi_data_face)
236  it.second.release();
237 
239 
240  _coord.release();
243 
244  _ad_JxW.release();
251  _ad_coord.release();
252 
253  delete _qrule_msm;
254 }
255 
256 const MooseArray<Real> &
258 {
259  _need_JxW_neighbor = true;
260  return _current_JxW_neighbor;
261 }
262 
263 void
264 Assembly::buildFE(FEType type) const
265 {
266  if (!_building_helpers && type == _helper_type)
268 
269  if (!_fe_shape_data[type])
270  _fe_shape_data[type] = std::make_unique<FEShapeData>();
271 
272  // Build an FE object for this type for each dimension up to the dimension of the current mesh
273  for (unsigned int dim = 0; dim <= _mesh_dimension; dim++)
274  {
275  if (!_fe[dim][type])
276  _fe[dim][type] = FEGenericBase<Real>::build(dim, type).release();
277 
278  _fe[dim][type]->get_phi();
279  _fe[dim][type]->get_dphi();
280  // Pre-request xyz. We have always computed xyz, but due to
281  // recent optimizations in libmesh, we now need to explicity
282  // request it, since apps (Yak) may rely on it being computed.
283  _fe[dim][type]->get_xyz();
284  if (_need_second_derivative.find(type) != _need_second_derivative.end())
285  _fe[dim][type]->get_d2phi();
286  }
287 }
288 
289 void
290 Assembly::buildFaceFE(FEType type) const
291 {
292  if (!_building_helpers && type == _helper_type)
294 
295  if (!_fe_shape_data_face[type])
296  _fe_shape_data_face[type] = std::make_unique<FEShapeData>();
297 
298  // Build an FE object for this type for each dimension up to the dimension of the current mesh
299  for (unsigned int dim = 0; dim <= _mesh_dimension; dim++)
300  {
301  if (!_fe_face[dim][type])
302  _fe_face[dim][type] = FEGenericBase<Real>::build(dim, type).release();
303 
304  _fe_face[dim][type]->get_phi();
305  _fe_face[dim][type]->get_dphi();
306  if (_need_second_derivative.find(type) != _need_second_derivative.end())
307  _fe_face[dim][type]->get_d2phi();
308  }
309 }
310 
311 void
312 Assembly::buildNeighborFE(FEType type) const
313 {
314  if (!_building_helpers && type == _helper_type)
316 
317  if (!_fe_shape_data_neighbor[type])
318  _fe_shape_data_neighbor[type] = std::make_unique<FEShapeData>();
319 
320  // Build an FE object for this type for each dimension up to the dimension of the current mesh
321  for (unsigned int dim = 0; dim <= _mesh_dimension; dim++)
322  {
323  if (!_fe_neighbor[dim][type])
324  _fe_neighbor[dim][type] = FEGenericBase<Real>::build(dim, type).release();
325 
326  _fe_neighbor[dim][type]->get_phi();
327  _fe_neighbor[dim][type]->get_dphi();
329  _fe_neighbor[dim][type]->get_d2phi();
330  }
331 }
332 
333 void
335 {
336  if (!_building_helpers && type == _helper_type)
338 
339  if (!_fe_shape_data_face_neighbor[type])
340  _fe_shape_data_face_neighbor[type] = std::make_unique<FEShapeData>();
341 
342  // Build an FE object for this type for each dimension up to the dimension of the current mesh
343  for (unsigned int dim = 0; dim <= _mesh_dimension; dim++)
344  {
345  if (!_fe_face_neighbor[dim][type])
346  _fe_face_neighbor[dim][type] = FEGenericBase<Real>::build(dim, type).release();
347 
348  _fe_face_neighbor[dim][type]->get_phi();
349  _fe_face_neighbor[dim][type]->get_dphi();
351  _fe_face_neighbor[dim][type]->get_d2phi();
352  }
353 }
354 
355 void
356 Assembly::buildLowerDFE(FEType type) const
357 {
358  if (!_building_helpers && type == _helper_type)
360 
361  if (!_fe_shape_data_lower[type])
362  _fe_shape_data_lower[type] = std::make_unique<FEShapeData>();
363 
364  // Build an FE object for this type for each dimension up to the dimension of
365  // the current mesh minus one (because this is for lower-dimensional
366  // elements!)
367  for (unsigned int dim = 0; dim <= _mesh_dimension - 1; dim++)
368  {
369  if (!_fe_lower[dim][type])
370  _fe_lower[dim][type] = FEGenericBase<Real>::build(dim, type).release();
371 
372  _fe_lower[dim][type]->get_phi();
373  _fe_lower[dim][type]->get_dphi();
374  if (_need_second_derivative.find(type) != _need_second_derivative.end())
375  _fe_lower[dim][type]->get_d2phi();
376  }
377 }
378 
379 void
380 Assembly::buildLowerDDualFE(FEType type) const
381 {
382  if (!_fe_shape_data_dual_lower[type])
383  _fe_shape_data_dual_lower[type] = std::make_unique<FEShapeData>();
384 
385  // Build an FE object for this type for each dimension up to the dimension of
386  // the current mesh minus one (because this is for lower-dimensional
387  // elements!)
388  for (unsigned int dim = 0; dim <= _mesh_dimension - 1; dim++)
389  {
390  if (!_fe_lower[dim][type])
391  _fe_lower[dim][type] = FEGenericBase<Real>::build(dim, type).release();
392 
393  _fe_lower[dim][type]->get_dual_phi();
394  _fe_lower[dim][type]->get_dual_dphi();
395  if (_need_second_derivative.find(type) != _need_second_derivative.end())
396  _fe_lower[dim][type]->get_dual_d2phi();
397  }
398 }
399 
400 void
402 {
403  if (!_vector_fe_shape_data_lower[type])
404  _vector_fe_shape_data_lower[type] = std::make_unique<VectorFEShapeData>();
405 
406  // Build an FE object for this type for each dimension up to the dimension of
407  // the current mesh minus one (because this is for lower-dimensional
408  // elements!)
409  unsigned int dim = ((type.family == LAGRANGE_VEC) || (type.family == MONOMIAL_VEC)) ? 0 : 2;
410  const auto ending_dim = cast_int<unsigned int>(_mesh_dimension - 1);
411  if (ending_dim < dim)
412  return;
413  for (; dim <= ending_dim; dim++)
414  {
415  if (!_vector_fe_lower[dim][type])
416  _vector_fe_lower[dim][type] = FEVectorBase::build(dim, type).release();
417 
418  _vector_fe_lower[dim][type]->get_phi();
419  _vector_fe_lower[dim][type]->get_dphi();
420  if (_need_second_derivative.find(type) != _need_second_derivative.end())
421  _vector_fe_lower[dim][type]->get_d2phi();
422  }
423 }
424 
425 void
427 {
429  _vector_fe_shape_data_dual_lower[type] = std::make_unique<VectorFEShapeData>();
430 
431  // Build an FE object for this type for each dimension up to the dimension of
432  // the current mesh minus one (because this is for lower-dimensional
433  // elements!)
434  unsigned int dim = ((type.family == LAGRANGE_VEC) || (type.family == MONOMIAL_VEC)) ? 0 : 2;
435  const auto ending_dim = cast_int<unsigned int>(_mesh_dimension - 1);
436  if (ending_dim < dim)
437  return;
438  for (; dim <= ending_dim; dim++)
439  {
440  if (!_vector_fe_lower[dim][type])
441  _vector_fe_lower[dim][type] = FEVectorBase::build(dim, type).release();
442 
443  _vector_fe_lower[dim][type]->get_dual_phi();
444  _vector_fe_lower[dim][type]->get_dual_dphi();
445  if (_need_second_derivative.find(type) != _need_second_derivative.end())
446  _vector_fe_lower[dim][type]->get_dual_d2phi();
447  }
448 }
449 
450 void
451 Assembly::buildVectorFE(FEType type) const
452 {
453  if (!_vector_fe_shape_data[type])
454  _vector_fe_shape_data[type] = std::make_unique<VectorFEShapeData>();
455 
456  // Note that NEDELEC_ONE and RAVIART_THOMAS elements can only be built for dimension > 2
457  unsigned int min_dim;
458  if (type.family == LAGRANGE_VEC || type.family == MONOMIAL_VEC)
459  min_dim = 0;
460  else
461  min_dim = 2;
462 
463  // Build an FE object for this type for each dimension from the min_dim up to the dimension of the
464  // current mesh
465  for (unsigned int dim = min_dim; dim <= _mesh_dimension; dim++)
466  {
467  if (!_vector_fe[dim][type])
468  _vector_fe[dim][type] = FEGenericBase<VectorValue<Real>>::build(dim, type).release();
469 
470  _vector_fe[dim][type]->get_phi();
471  _vector_fe[dim][type]->get_dphi();
472  if (type.family == NEDELEC_ONE)
473  _vector_fe[dim][type]->get_curl_phi();
474  if (type.family == RAVIART_THOMAS)
475  _vector_fe[dim][type]->get_div_phi();
476  // Pre-request xyz. We have always computed xyz, but due to
477  // recent optimizations in libmesh, we now need to explicity
478  // request it, since apps (Yak) may rely on it being computed.
479  _vector_fe[dim][type]->get_xyz();
480  }
481 }
482 
483 void
484 Assembly::buildVectorFaceFE(FEType type) const
485 {
486  if (!_vector_fe_shape_data_face[type])
487  _vector_fe_shape_data_face[type] = std::make_unique<VectorFEShapeData>();
488 
489  // Note that NEDELEC_ONE and RAVIART_THOMAS elements can only be built for dimension > 2
490  unsigned int min_dim;
491  if (type.family == LAGRANGE_VEC || type.family == MONOMIAL_VEC)
492  min_dim = 0;
493  else
494  min_dim = 2;
495 
496  // Build an FE object for this type for each dimension from the min_dim up to the dimension of the
497  // current mesh
498  for (unsigned int dim = min_dim; dim <= _mesh_dimension; dim++)
499  {
500  if (!_vector_fe_face[dim][type])
501  _vector_fe_face[dim][type] = FEGenericBase<VectorValue<Real>>::build(dim, type).release();
502 
503  _vector_fe_face[dim][type]->get_phi();
504  _vector_fe_face[dim][type]->get_dphi();
505  if (type.family == NEDELEC_ONE)
506  _vector_fe_face[dim][type]->get_curl_phi();
507  if (type.family == RAVIART_THOMAS)
508  _vector_fe_face[dim][type]->get_div_phi();
509  }
510 }
511 
512 void
514 {
516  _vector_fe_shape_data_neighbor[type] = std::make_unique<VectorFEShapeData>();
517 
518  // Note that NEDELEC_ONE and RAVIART_THOMAS elements can only be built for dimension > 2
519  unsigned int min_dim;
520  if (type.family == LAGRANGE_VEC || type.family == MONOMIAL_VEC)
521  min_dim = 0;
522  else
523  min_dim = 2;
524 
525  // Build an FE object for this type for each dimension from the min_dim up to the dimension of the
526  // current mesh
527  for (unsigned int dim = min_dim; dim <= _mesh_dimension; dim++)
528  {
529  if (!_vector_fe_neighbor[dim][type])
530  _vector_fe_neighbor[dim][type] = FEGenericBase<VectorValue<Real>>::build(dim, type).release();
531 
532  _vector_fe_neighbor[dim][type]->get_phi();
533  _vector_fe_neighbor[dim][type]->get_dphi();
534  if (type.family == NEDELEC_ONE)
535  _vector_fe_neighbor[dim][type]->get_curl_phi();
536  if (type.family == RAVIART_THOMAS)
537  _vector_fe_neighbor[dim][type]->get_div_phi();
538  }
539 }
540 
541 void
543 {
545  _vector_fe_shape_data_face_neighbor[type] = std::make_unique<VectorFEShapeData>();
546 
547  // Note that NEDELEC_ONE and RAVIART_THOMAS elements can only be built for dimension > 2
548  unsigned int min_dim;
549  if (type.family == LAGRANGE_VEC || type.family == MONOMIAL_VEC)
550  min_dim = 0;
551  else
552  min_dim = 2;
553 
554  // Build an FE object for this type for each dimension from the min_dim up to the dimension of the
555  // current mesh
556  for (unsigned int dim = min_dim; dim <= _mesh_dimension; dim++)
557  {
558  if (!_vector_fe_face_neighbor[dim][type])
560  FEGenericBase<VectorValue<Real>>::build(dim, type).release();
561 
562  _vector_fe_face_neighbor[dim][type]->get_phi();
563  _vector_fe_face_neighbor[dim][type]->get_dphi();
564  if (type.family == NEDELEC_ONE)
565  _vector_fe_face_neighbor[dim][type]->get_curl_phi();
566  if (type.family == RAVIART_THOMAS)
567  _vector_fe_face_neighbor[dim][type]->get_div_phi();
568  }
569 }
570 
571 void
573 {
574  auto & qdefault = _qrules[Moose::ANY_BLOCK_ID];
575  mooseAssert(qdefault.size() > 0, "default quadrature must be initialized before order bumps");
576 
577  unsigned int ndims = _mesh_dimension + 1; // must account for 0-dimensional quadrature.
578  auto & qvec = _qrules[block];
579  if (qvec.size() != ndims || !qvec[0].vol)
580  createQRules(qdefault[0].vol->type(),
581  qdefault[0].arbitrary_vol->get_order(),
582  volume_order,
583  qdefault[0].face->get_order(),
584  block);
585  else if (qvec[0].vol->get_order() < volume_order)
586  createQRules(qvec[0].vol->type(),
587  qvec[0].arbitrary_vol->get_order(),
588  volume_order,
589  qvec[0].face->get_order(),
590  block);
591  // otherwise do nothing - quadrature order is already as high as requested
592 }
593 
594 void
596 {
597  auto & qdefault = _qrules[Moose::ANY_BLOCK_ID];
598  mooseAssert(qdefault.size() > 0, "default quadrature must be initialized before order bumps");
599 
600  unsigned int ndims = _mesh_dimension + 1; // must account for 0-dimensional quadrature.
601  auto & qvec = _qrules[block];
602  if (qvec.size() != ndims || !qvec[0].vol)
603  createQRules(qdefault[0].vol->type(), order, order, order, block);
604  else if (qvec[0].vol->get_order() < order || qvec[0].face->get_order() < order)
605  createQRules(qvec[0].vol->type(),
606  std::max(order, qvec[0].arbitrary_vol->get_order()),
607  std::max(order, qvec[0].vol->get_order()),
608  std::max(order, qvec[0].face->get_order()),
609  block);
610  // otherwise do nothing - quadrature order is already as high as requested
611 }
612 
613 void
615  Order order,
616  Order volume_order,
617  Order face_order,
618  SubdomainID block,
619  bool allow_negative_qweights)
620 {
621  auto & qvec = _qrules[block];
622  unsigned int ndims = _mesh_dimension + 1; // must account for 0-dimensional quadrature.
623  if (qvec.size() != ndims)
624  qvec.resize(ndims);
625 
626  for (unsigned int i = 0; i < qvec.size(); i++)
627  {
628  int dim = i;
629  auto & q = qvec[dim];
630  q.vol = QBase::build(type, dim, volume_order);
631  q.vol->allow_rules_with_negative_weights = allow_negative_qweights;
632  q.face = QBase::build(type, dim - 1, face_order);
633  q.face->allow_rules_with_negative_weights = allow_negative_qweights;
634  q.fv_face = QBase::build(QMONOMIAL, dim - 1, CONSTANT);
635  q.fv_face->allow_rules_with_negative_weights = allow_negative_qweights;
636  q.neighbor = std::make_unique<ArbitraryQuadrature>(dim - 1, face_order);
637  q.neighbor->allow_rules_with_negative_weights = allow_negative_qweights;
638  q.arbitrary_vol = std::make_unique<ArbitraryQuadrature>(dim, order);
639  q.arbitrary_vol->allow_rules_with_negative_weights = allow_negative_qweights;
640  q.arbitrary_face = std::make_unique<ArbitraryQuadrature>(dim - 1, face_order);
641  q.arbitrary_face->allow_rules_with_negative_weights = allow_negative_qweights;
642  }
643 
644  delete _qrule_msm;
645  _custom_mortar_qrule = false;
646  _qrule_msm = QBase::build(type, _mesh_dimension - 1, face_order).release();
647  _qrule_msm->allow_rules_with_negative_weights = allow_negative_qweights;
648  _fe_msm->attach_quadrature_rule(_qrule_msm);
649 }
650 
651 void
652 Assembly::setVolumeQRule(QBase * qrule, unsigned int dim)
653 {
654  _current_qrule = qrule;
655 
656  if (qrule) // Don't set a NULL qrule
657  {
658  for (auto & it : _fe[dim])
659  it.second->attach_quadrature_rule(qrule);
660  for (auto & it : _vector_fe[dim])
661  it.second->attach_quadrature_rule(qrule);
662  if (!_unique_fe_helper.empty())
663  {
664  mooseAssert(dim < _unique_fe_helper.size(), "We should not be indexing out of bounds");
665  _unique_fe_helper[dim]->attach_quadrature_rule(qrule);
666  }
667  }
668 }
669 
670 void
671 Assembly::setFaceQRule(QBase * qrule, unsigned int dim)
672 {
673  _current_qrule_face = qrule;
674 
675  for (auto & it : _fe_face[dim])
676  it.second->attach_quadrature_rule(qrule);
677  for (auto & it : _vector_fe_face[dim])
678  it.second->attach_quadrature_rule(qrule);
679  if (!_unique_fe_face_helper.empty())
680  {
681  mooseAssert(dim < _unique_fe_face_helper.size(), "We should not be indexing out of bounds");
682  _unique_fe_face_helper[dim]->attach_quadrature_rule(qrule);
683  }
684 }
685 
686 void
687 Assembly::setLowerQRule(QBase * qrule, unsigned int dim)
688 {
689  // The lower-dimensional quadrature rule matches the face quadrature rule
690  setFaceQRule(qrule, dim);
691 
692  _current_qrule_lower = qrule;
693 
694  for (auto & it : _fe_lower[dim])
695  it.second->attach_quadrature_rule(qrule);
696  for (auto & it : _vector_fe_lower[dim])
697  it.second->attach_quadrature_rule(qrule);
698  if (!_unique_fe_lower_helper.empty())
699  {
700  mooseAssert(dim < _unique_fe_lower_helper.size(), "We should not be indexing out of bounds");
701  _unique_fe_lower_helper[dim]->attach_quadrature_rule(qrule);
702  }
703 }
704 
705 void
706 Assembly::setNeighborQRule(QBase * qrule, unsigned int dim)
707 {
708  _current_qrule_neighbor = qrule;
709 
710  for (auto & it : _fe_face_neighbor[dim])
711  it.second->attach_quadrature_rule(qrule);
712  for (auto & it : _vector_fe_face_neighbor[dim])
713  it.second->attach_quadrature_rule(qrule);
714  if (!_unique_fe_face_neighbor_helper.empty())
715  {
716  mooseAssert(dim < _unique_fe_face_neighbor_helper.size(),
717  "We should not be indexing out of bounds");
718  _unique_fe_face_neighbor_helper[dim]->attach_quadrature_rule(qrule);
719  }
720 }
721 
722 void
724 {
725  _current_qrule = nullptr;
726  _current_qrule_face = nullptr;
727  _current_qrule_lower = nullptr;
728  _current_qrule_neighbor = nullptr;
729 }
730 
731 void
733 {
734  if (order != _qrule_msm->get_order())
735  {
736  // If custom mortar qrule has not yet been specified
738  {
739  _custom_mortar_qrule = true;
740  const unsigned int dim = _qrule_msm->get_dim();
741  const QuadratureType type = _qrule_msm->type();
742  delete _qrule_msm;
743 
744  _qrule_msm = QBase::build(type, dim, order).release();
745  _fe_msm->attach_quadrature_rule(_qrule_msm);
746  }
747  else
748  mooseError("Mortar quadrature_order: ",
749  order,
750  " does not match previously specified quadrature_order: ",
751  _qrule_msm->get_order(),
752  ". Quadrature_order (when specified) must match for all mortar constraints.");
753  }
754 }
755 
756 void
757 Assembly::reinitFE(const Elem * elem)
758 {
759  unsigned int dim = elem->dim();
760 
761  for (const auto & it : _fe[dim])
762  {
763  FEBase & fe = *it.second;
764  const FEType & fe_type = it.first;
765 
766  _current_fe[fe_type] = &fe;
767 
768  FEShapeData & fesd = *_fe_shape_data[fe_type];
769 
770  fe.reinit(elem);
771 
772  fesd._phi.shallowCopy(const_cast<std::vector<std::vector<Real>> &>(fe.get_phi()));
773  fesd._grad_phi.shallowCopy(
774  const_cast<std::vector<std::vector<VectorValue<Real>>> &>(fe.get_dphi()));
775  if (_need_second_derivative.find(fe_type) != _need_second_derivative.end())
776  fesd._second_phi.shallowCopy(
777  const_cast<std::vector<std::vector<TensorValue<Real>>> &>(fe.get_d2phi()));
778  }
779  for (const auto & it : _vector_fe[dim])
780  {
781  FEVectorBase & fe = *it.second;
782  const FEType & fe_type = it.first;
783 
784  _current_vector_fe[fe_type] = &fe;
785 
786  VectorFEShapeData & fesd = *_vector_fe_shape_data[fe_type];
787 
788  fe.reinit(elem);
789 
790  fesd._phi.shallowCopy(const_cast<std::vector<std::vector<VectorValue<Real>>> &>(fe.get_phi()));
791  fesd._grad_phi.shallowCopy(
792  const_cast<std::vector<std::vector<TensorValue<Real>>> &>(fe.get_dphi()));
793  if (_need_second_derivative.find(fe_type) != _need_second_derivative.end())
794  fesd._second_phi.shallowCopy(
795  const_cast<std::vector<std::vector<TypeNTensor<3, Real>>> &>(fe.get_d2phi()));
796  if (_need_curl.find(fe_type) != _need_curl.end())
797  fesd._curl_phi.shallowCopy(
798  const_cast<std::vector<std::vector<VectorValue<Real>>> &>(fe.get_curl_phi()));
799  if (_need_div.find(fe_type) != _need_div.end())
800  fesd._div_phi.shallowCopy(const_cast<std::vector<std::vector<Real>> &>(fe.get_div_phi()));
801  }
802  if (!_unique_fe_helper.empty())
803  {
804  mooseAssert(dim < _unique_fe_helper.size(), "We should be in bounds here");
805  _unique_fe_helper[dim]->reinit(elem);
806  }
807 
808  // During that last loop the helper objects will have been reinitialized as well
809  // We need to dig out the q_points and JxW from it.
811  const_cast<std::vector<Point> &>(_holder_fe_helper[dim]->get_xyz()));
812  _current_JxW.shallowCopy(const_cast<std::vector<Real> &>(_holder_fe_helper[dim]->get_JxW()));
813 
815  {
816  auto n_qp = _current_qrule->n_points();
818  if (_displaced)
819  {
820  const auto & qw = _current_qrule->get_weights();
821  for (unsigned int qp = 0; qp != n_qp; qp++)
823  }
824  else
825  for (unsigned qp = 0; qp < n_qp; ++qp)
826  {
827  _ad_JxW[qp] = _current_JxW[qp];
828  if (_calculate_xyz)
830  }
831 
832  for (const auto & it : _fe[dim])
833  {
834  FEBase & fe = *it.second;
835  auto fe_type = it.first;
836  auto num_shapes = fe.n_shape_functions();
837  auto & grad_phi = _ad_grad_phi_data[fe_type];
838 
839  grad_phi.resize(num_shapes);
840  for (decltype(num_shapes) i = 0; i < num_shapes; ++i)
841  grad_phi[i].resize(n_qp);
842 
843  if (_displaced)
844  computeGradPhiAD(elem, n_qp, grad_phi, &fe);
845  else
846  {
847  const auto & regular_grad_phi = _fe_shape_data[fe_type]->_grad_phi;
848  for (unsigned qp = 0; qp < n_qp; ++qp)
849  for (decltype(num_shapes) i = 0; i < num_shapes; ++i)
850  grad_phi[i][qp] = regular_grad_phi[i][qp];
851  }
852  }
853  for (const auto & it : _vector_fe[dim])
854  {
855  FEVectorBase & fe = *it.second;
856  auto fe_type = it.first;
857  auto num_shapes = fe.n_shape_functions();
858  auto & grad_phi = _ad_vector_grad_phi_data[fe_type];
859 
860  grad_phi.resize(num_shapes);
861  for (decltype(num_shapes) i = 0; i < num_shapes; ++i)
862  grad_phi[i].resize(n_qp);
863 
864  if (_displaced)
865  computeGradPhiAD(elem, n_qp, grad_phi, &fe);
866  else
867  {
868  const auto & regular_grad_phi = _vector_fe_shape_data[fe_type]->_grad_phi;
869  for (unsigned qp = 0; qp < n_qp; ++qp)
870  for (decltype(num_shapes) i = 0; i < num_shapes; ++i)
871  grad_phi[i][qp] = regular_grad_phi[i][qp];
872  }
873  }
874  }
875 
876  auto n = numExtraElemIntegers();
877  for (auto i : make_range(n))
878  _extra_elem_ids[i] = _current_elem->get_extra_integer(i);
879  _extra_elem_ids[n] = _current_elem->subdomain_id();
880 
881  if (_xfem != nullptr)
883 }
884 
885 template <typename OutputType>
886 void
887 Assembly::computeGradPhiAD(const Elem * elem,
888  unsigned int n_qp,
890  FEGenericBase<OutputType> * fe)
891 {
892  // This function relies on the fact that FE::reinit has already been called. FE::reinit will
893  // importantly have already called FEMap::init_shape_functions which will have computed
894  // these quantities at the integration/quadrature points: dphidxi,
895  // dphideta, and dphidzeta (e.g. \nabla phi w.r.t. reference coordinates). These *phi* quantities
896  // are independent of mesh displacements when using a quadrature rule.
897  //
898  // Note that a user could have specified custom integration points (e.g. independent of a
899  // quadrature rule) which could very well depend on displacements. In that case even the *phi*
900  // quantities from the above paragraph would be a function of the displacements and we would be
901  // missing that derivative information in the calculations below
902 
903  auto dim = elem->dim();
904  const auto & dphidxi = fe->get_dphidxi();
905  const auto & dphideta = fe->get_dphideta();
906  const auto & dphidzeta = fe->get_dphidzeta();
907  auto num_shapes = grad_phi.size();
908 
909  switch (dim)
910  {
911  case 0:
912  {
913  for (decltype(num_shapes) i = 0; i < num_shapes; ++i)
914  for (unsigned qp = 0; qp < n_qp; ++qp)
915  grad_phi[i][qp] = 0;
916  break;
917  }
918 
919  case 1:
920  {
921  for (decltype(num_shapes) i = 0; i < num_shapes; ++i)
922  for (unsigned qp = 0; qp < n_qp; ++qp)
923  {
924  grad_phi[i][qp].slice(0) = dphidxi[i][qp] * _ad_dxidx_map[qp];
925  grad_phi[i][qp].slice(1) = dphidxi[i][qp] * _ad_dxidy_map[qp];
926  grad_phi[i][qp].slice(2) = dphidxi[i][qp] * _ad_dxidz_map[qp];
927  }
928  break;
929  }
930 
931  case 2:
932  {
933  for (decltype(num_shapes) i = 0; i < num_shapes; ++i)
934  for (unsigned qp = 0; qp < n_qp; ++qp)
935  {
936  grad_phi[i][qp].slice(0) =
937  dphidxi[i][qp] * _ad_dxidx_map[qp] + dphideta[i][qp] * _ad_detadx_map[qp];
938  grad_phi[i][qp].slice(1) =
939  dphidxi[i][qp] * _ad_dxidy_map[qp] + dphideta[i][qp] * _ad_detady_map[qp];
940  grad_phi[i][qp].slice(2) =
941  dphidxi[i][qp] * _ad_dxidz_map[qp] + dphideta[i][qp] * _ad_detadz_map[qp];
942  }
943  break;
944  }
945 
946  case 3:
947  {
948  for (decltype(num_shapes) i = 0; i < num_shapes; ++i)
949  for (unsigned qp = 0; qp < n_qp; ++qp)
950  {
951  grad_phi[i][qp].slice(0) = dphidxi[i][qp] * _ad_dxidx_map[qp] +
952  dphideta[i][qp] * _ad_detadx_map[qp] +
953  dphidzeta[i][qp] * _ad_dzetadx_map[qp];
954  grad_phi[i][qp].slice(1) = dphidxi[i][qp] * _ad_dxidy_map[qp] +
955  dphideta[i][qp] * _ad_detady_map[qp] +
956  dphidzeta[i][qp] * _ad_dzetady_map[qp];
957  grad_phi[i][qp].slice(2) = dphidxi[i][qp] * _ad_dxidz_map[qp] +
958  dphideta[i][qp] * _ad_detadz_map[qp] +
959  dphidzeta[i][qp] * _ad_dzetadz_map[qp];
960  }
961  break;
962  }
963  }
964 }
965 
966 void
967 Assembly::resizeADMappingObjects(unsigned int n_qp, unsigned int dim)
968 {
969  _ad_dxyzdxi_map.resize(n_qp);
970  _ad_dxidx_map.resize(n_qp);
971  _ad_dxidy_map.resize(n_qp); // 1D element may live in 2D ...
972  _ad_dxidz_map.resize(n_qp); // ... or 3D
973 
974  if (dim > 1)
975  {
976  _ad_dxyzdeta_map.resize(n_qp);
977  _ad_detadx_map.resize(n_qp);
978  _ad_detady_map.resize(n_qp);
979  _ad_detadz_map.resize(n_qp);
980 
981  if (dim > 2)
982  {
983  _ad_dxyzdzeta_map.resize(n_qp);
984  _ad_dzetadx_map.resize(n_qp);
985  _ad_dzetady_map.resize(n_qp);
986  _ad_dzetadz_map.resize(n_qp);
987  }
988  }
989 
990  _ad_jac.resize(n_qp);
991  _ad_JxW.resize(n_qp);
992  if (_calculate_xyz)
993  _ad_q_points.resize(n_qp);
994 }
995 
996 void
998  const std::vector<Real> & qw,
999  unsigned p,
1000  FEBase * fe)
1001 {
1002  // This function relies on the fact that FE::reinit has already been called. FE::reinit will
1003  // importantly have already called FEMap::init_reference_to_physical_map which will have computed
1004  // these quantities at the integration/quadrature points: phi_map, dphidxi_map,
1005  // dphideta_map, and dphidzeta_map (e.g. phi and \nabla phi w.r.t reference coordinates). *_map is
1006  // used to denote that quantities are in reference to a mapping Lagrange FE object. The FE<Dim,
1007  // LAGRANGE> objects used for mapping will in general have an order matching the order of the
1008  // mesh. These *phi*_map quantities are independent of mesh displacements when using a quadrature
1009  // rule.
1010  //
1011  // Note that a user could have specified custom integration points (e.g. independent of a
1012  // quadrature rule) which could very well depend on displacements. In that case even the *phi*_map
1013  // quantities from the above paragraph would be a function of the displacements and we would be
1014  // missing that derivative information in the calculations below
1015  //
1016  // Important quantities calculated by this method:
1017  // - _ad_JxW;
1018  // - _ad_q_points;
1019  // And the following quantities are important because they are used in the computeGradPhiAD method
1020  // to calculate the shape function gradients with respect to the physical coordinates
1021  // dphi/dphys = dphi/dref * dref/dphys:
1022  // - _ad_dxidx_map;
1023  // - _ad_dxidy_map;
1024  // - _ad_dxidz_map;
1025  // - _ad_detadx_map;
1026  // - _ad_detady_map;
1027  // - _ad_detadz_map;
1028  // - _ad_dzetadx_map;
1029  // - _ad_dzetady_map;
1030  // - _ad_dzetadz_map;
1031  //
1032  // Some final notes. This method will be called both when we are reinit'ing in the volume and on
1033  // faces. When reinit'ing on faces, computation of _ad_JxW will be garbage because we will be
1034  // using dummy quadrature weights. _ad_q_points computation is also currently extraneous during
1035  // face reinit because we compute _ad_q_points_face in the computeFaceMap method. However,
1036  // computation of dref/dphys is absolutely necessary (and the reason we call this method for the
1037  // face case) for both volume and face reinit
1038 
1039  auto dim = elem->dim();
1040  const auto & elem_nodes = elem->get_nodes();
1041  auto num_shapes = fe->n_shape_functions();
1042  const auto & phi_map = fe->get_fe_map().get_phi_map();
1043  const auto & dphidxi_map = fe->get_fe_map().get_dphidxi_map();
1044  const auto & dphideta_map = fe->get_fe_map().get_dphideta_map();
1045  const auto & dphidzeta_map = fe->get_fe_map().get_dphidzeta_map();
1046  const auto sys_num = _sys.number();
1047  const bool do_derivatives =
1048  ADReal::do_derivatives && _sys.number() == _subproblem.currentNlSysNum();
1049 
1050  switch (dim)
1051  {
1052  case 0:
1053  {
1054  _ad_jac[p] = 1.0;
1055  _ad_JxW[p] = qw[p];
1056  if (_calculate_xyz)
1057  _ad_q_points[p] = *elem_nodes[0];
1058  break;
1059  }
1060 
1061  case 1:
1062  {
1063  if (_calculate_xyz)
1064  _ad_q_points[p].zero();
1065 
1066  _ad_dxyzdxi_map[p].zero();
1067 
1068  for (std::size_t i = 0; i < num_shapes; i++)
1069  {
1070  libmesh_assert(elem_nodes[i]);
1071  const Node & node = *elem_nodes[i];
1072  libMesh::VectorValue<DualReal> elem_point = node;
1073  if (do_derivatives)
1074  for (const auto & [disp_num, direction] : _disp_numbers_and_directions)
1075  if (node.n_dofs(sys_num, disp_num))
1077  elem_point(direction).derivatives(), node.dof_number(sys_num, disp_num, 0), 1.);
1078 
1079  _ad_dxyzdxi_map[p].add_scaled(elem_point, dphidxi_map[i][p]);
1080 
1081  if (_calculate_xyz)
1082  _ad_q_points[p].add_scaled(elem_point, phi_map[i][p]);
1083  }
1084 
1085  _ad_jac[p] = _ad_dxyzdxi_map[p].norm();
1086 
1087  if (_ad_jac[p].value() <= -TOLERANCE * TOLERANCE)
1088  {
1089  static bool failing = false;
1090  if (!failing)
1091  {
1092  failing = true;
1093  elem->print_info(libMesh::err);
1094  libmesh_error_msg("ERROR: negative Jacobian " << _ad_jac[p].value() << " at point index "
1095  << p << " in element " << elem->id());
1096  }
1097  else
1098  return;
1099  }
1100 
1101  const auto jacm2 = 1. / _ad_jac[p] / _ad_jac[p];
1102  _ad_dxidx_map[p] = jacm2 * _ad_dxyzdxi_map[p](0);
1103  _ad_dxidy_map[p] = jacm2 * _ad_dxyzdxi_map[p](1);
1104  _ad_dxidz_map[p] = jacm2 * _ad_dxyzdxi_map[p](2);
1105 
1106  _ad_JxW[p] = _ad_jac[p] * qw[p];
1107 
1108  break;
1109  }
1110 
1111  case 2:
1112  {
1113  if (_calculate_xyz)
1114  _ad_q_points[p].zero();
1115  _ad_dxyzdxi_map[p].zero();
1116  _ad_dxyzdeta_map[p].zero();
1117 
1118  for (std::size_t i = 0; i < num_shapes; i++)
1119  {
1120  libmesh_assert(elem_nodes[i]);
1121  const Node & node = *elem_nodes[i];
1122  libMesh::VectorValue<DualReal> elem_point = node;
1123  if (do_derivatives)
1124  for (const auto & [disp_num, direction] : _disp_numbers_and_directions)
1126  elem_point(direction).derivatives(), node.dof_number(sys_num, disp_num, 0), 1.);
1127 
1128  _ad_dxyzdxi_map[p].add_scaled(elem_point, dphidxi_map[i][p]);
1129  _ad_dxyzdeta_map[p].add_scaled(elem_point, dphideta_map[i][p]);
1130 
1131  if (_calculate_xyz)
1132  _ad_q_points[p].add_scaled(elem_point, phi_map[i][p]);
1133  }
1134 
1135  const auto &dx_dxi = _ad_dxyzdxi_map[p](0), dx_deta = _ad_dxyzdeta_map[p](0),
1136  dy_dxi = _ad_dxyzdxi_map[p](1), dy_deta = _ad_dxyzdeta_map[p](1),
1137  dz_dxi = _ad_dxyzdxi_map[p](2), dz_deta = _ad_dxyzdeta_map[p](2);
1138 
1139  const auto g11 = (dx_dxi * dx_dxi + dy_dxi * dy_dxi + dz_dxi * dz_dxi);
1140 
1141  const auto g12 = (dx_dxi * dx_deta + dy_dxi * dy_deta + dz_dxi * dz_deta);
1142 
1143  const auto g21 = g12;
1144 
1145  const auto g22 = (dx_deta * dx_deta + dy_deta * dy_deta + dz_deta * dz_deta);
1146 
1147  auto det = (g11 * g22 - g12 * g21);
1148 
1149  if (det.value() <= -TOLERANCE * TOLERANCE)
1150  {
1151  static bool failing = false;
1152  if (!failing)
1153  {
1154  failing = true;
1155  elem->print_info(libMesh::err);
1156  libmesh_error_msg("ERROR: negative Jacobian " << det << " at point index " << p
1157  << " in element " << elem->id());
1158  }
1159  else
1160  return;
1161  }
1162  else if (det.value() <= 0.)
1163  det.value() = TOLERANCE * TOLERANCE;
1164 
1165  const auto inv_det = 1. / det;
1166  _ad_jac[p] = std::sqrt(det);
1167 
1168  _ad_JxW[p] = _ad_jac[p] * qw[p];
1169 
1170  const auto g11inv = g22 * inv_det;
1171  const auto g12inv = -g12 * inv_det;
1172  const auto g21inv = -g21 * inv_det;
1173  const auto g22inv = g11 * inv_det;
1174 
1175  _ad_dxidx_map[p] = g11inv * dx_dxi + g12inv * dx_deta;
1176  _ad_dxidy_map[p] = g11inv * dy_dxi + g12inv * dy_deta;
1177  _ad_dxidz_map[p] = g11inv * dz_dxi + g12inv * dz_deta;
1178 
1179  _ad_detadx_map[p] = g21inv * dx_dxi + g22inv * dx_deta;
1180  _ad_detady_map[p] = g21inv * dy_dxi + g22inv * dy_deta;
1181  _ad_detadz_map[p] = g21inv * dz_dxi + g22inv * dz_deta;
1182 
1183  break;
1184  }
1185 
1186  case 3:
1187  {
1188  if (_calculate_xyz)
1189  _ad_q_points[p].zero();
1190  _ad_dxyzdxi_map[p].zero();
1191  _ad_dxyzdeta_map[p].zero();
1192  _ad_dxyzdzeta_map[p].zero();
1193 
1194  for (std::size_t i = 0; i < num_shapes; i++)
1195  {
1196  libmesh_assert(elem_nodes[i]);
1197  const Node & node = *elem_nodes[i];
1198  libMesh::VectorValue<DualReal> elem_point = node;
1199  if (do_derivatives)
1200  for (const auto & [disp_num, direction] : _disp_numbers_and_directions)
1202  elem_point(direction).derivatives(), node.dof_number(sys_num, disp_num, 0), 1.);
1203 
1204  _ad_dxyzdxi_map[p].add_scaled(elem_point, dphidxi_map[i][p]);
1205  _ad_dxyzdeta_map[p].add_scaled(elem_point, dphideta_map[i][p]);
1206  _ad_dxyzdzeta_map[p].add_scaled(elem_point, dphidzeta_map[i][p]);
1207 
1208  if (_calculate_xyz)
1209  _ad_q_points[p].add_scaled(elem_point, phi_map[i][p]);
1210  }
1211 
1212  const auto dx_dxi = _ad_dxyzdxi_map[p](0), dy_dxi = _ad_dxyzdxi_map[p](1),
1213  dz_dxi = _ad_dxyzdxi_map[p](2), dx_deta = _ad_dxyzdeta_map[p](0),
1214  dy_deta = _ad_dxyzdeta_map[p](1), dz_deta = _ad_dxyzdeta_map[p](2),
1215  dx_dzeta = _ad_dxyzdzeta_map[p](0), dy_dzeta = _ad_dxyzdzeta_map[p](1),
1216  dz_dzeta = _ad_dxyzdzeta_map[p](2);
1217 
1218  _ad_jac[p] = (dx_dxi * (dy_deta * dz_dzeta - dz_deta * dy_dzeta) +
1219  dy_dxi * (dz_deta * dx_dzeta - dx_deta * dz_dzeta) +
1220  dz_dxi * (dx_deta * dy_dzeta - dy_deta * dx_dzeta));
1221 
1222  if (_ad_jac[p].value() <= -TOLERANCE * TOLERANCE)
1223  {
1224  static bool failing = false;
1225  if (!failing)
1226  {
1227  failing = true;
1228  elem->print_info(libMesh::err);
1229  libmesh_error_msg("ERROR: negative Jacobian " << _ad_jac[p].value() << " at point index "
1230  << p << " in element " << elem->id());
1231  }
1232  else
1233  return;
1234  }
1235 
1236  _ad_JxW[p] = _ad_jac[p] * qw[p];
1237 
1238  const auto inv_jac = 1. / _ad_jac[p];
1239 
1240  _ad_dxidx_map[p] = (dy_deta * dz_dzeta - dz_deta * dy_dzeta) * inv_jac;
1241  _ad_dxidy_map[p] = (dz_deta * dx_dzeta - dx_deta * dz_dzeta) * inv_jac;
1242  _ad_dxidz_map[p] = (dx_deta * dy_dzeta - dy_deta * dx_dzeta) * inv_jac;
1243 
1244  _ad_detadx_map[p] = (dz_dxi * dy_dzeta - dy_dxi * dz_dzeta) * inv_jac;
1245  _ad_detady_map[p] = (dx_dxi * dz_dzeta - dz_dxi * dx_dzeta) * inv_jac;
1246  _ad_detadz_map[p] = (dy_dxi * dx_dzeta - dx_dxi * dy_dzeta) * inv_jac;
1247 
1248  _ad_dzetadx_map[p] = (dy_dxi * dz_deta - dz_dxi * dy_deta) * inv_jac;
1249  _ad_dzetady_map[p] = (dz_dxi * dx_deta - dx_dxi * dz_deta) * inv_jac;
1250  _ad_dzetadz_map[p] = (dx_dxi * dy_deta - dy_dxi * dx_deta) * inv_jac;
1251 
1252  break;
1253  }
1254 
1255  default:
1256  libmesh_error_msg("Invalid dim = " << dim);
1257  }
1258 }
1259 
1260 void
1261 Assembly::reinitFEFace(const Elem * elem, unsigned int side)
1262 {
1263  unsigned int dim = elem->dim();
1264 
1265  for (const auto & it : _fe_face[dim])
1266  {
1267  FEBase & fe_face = *it.second;
1268  const FEType & fe_type = it.first;
1269  FEShapeData & fesd = *_fe_shape_data_face[fe_type];
1270  fe_face.reinit(elem, side);
1271  _current_fe_face[fe_type] = &fe_face;
1272 
1273  fesd._phi.shallowCopy(const_cast<std::vector<std::vector<Real>> &>(fe_face.get_phi()));
1274  fesd._grad_phi.shallowCopy(
1275  const_cast<std::vector<std::vector<VectorValue<Real>>> &>(fe_face.get_dphi()));
1276  if (_need_second_derivative.find(fe_type) != _need_second_derivative.end())
1277  fesd._second_phi.shallowCopy(
1278  const_cast<std::vector<std::vector<TensorValue<Real>>> &>(fe_face.get_d2phi()));
1279  }
1280  for (const auto & it : _vector_fe_face[dim])
1281  {
1282  FEVectorBase & fe_face = *it.second;
1283  const FEType & fe_type = it.first;
1284 
1285  _current_vector_fe_face[fe_type] = &fe_face;
1286 
1287  VectorFEShapeData & fesd = *_vector_fe_shape_data_face[fe_type];
1288 
1289  fe_face.reinit(elem, side);
1290 
1291  fesd._phi.shallowCopy(
1292  const_cast<std::vector<std::vector<VectorValue<Real>>> &>(fe_face.get_phi()));
1293  fesd._grad_phi.shallowCopy(
1294  const_cast<std::vector<std::vector<TensorValue<Real>>> &>(fe_face.get_dphi()));
1295  if (_need_second_derivative.find(fe_type) != _need_second_derivative.end())
1296  fesd._second_phi.shallowCopy(
1297  const_cast<std::vector<std::vector<TypeNTensor<3, Real>>> &>(fe_face.get_d2phi()));
1298  if (_need_curl.find(fe_type) != _need_curl.end())
1299  fesd._curl_phi.shallowCopy(
1300  const_cast<std::vector<std::vector<VectorValue<Real>>> &>(fe_face.get_curl_phi()));
1301  if (_need_div.find(fe_type) != _need_div.end())
1302  fesd._div_phi.shallowCopy(
1303  const_cast<std::vector<std::vector<Real>> &>(fe_face.get_div_phi()));
1304  }
1305  if (!_unique_fe_face_helper.empty())
1306  {
1307  mooseAssert(dim < _unique_fe_face_helper.size(), "We should be in bounds here");
1308  _unique_fe_face_helper[dim]->reinit(elem, side);
1309  }
1310 
1311  // During that last loop the helper objects will have been reinitialized as well
1312  // We need to dig out the q_points and JxW from it.
1314  const_cast<std::vector<Point> &>(_holder_fe_face_helper[dim]->get_xyz()));
1316  const_cast<std::vector<Real> &>(_holder_fe_face_helper[dim]->get_JxW()));
1318  const_cast<std::vector<Point> &>(_holder_fe_face_helper[dim]->get_normals()));
1319 
1320  _mapped_normals.resize(_current_normals.size(), Eigen::Map<RealDIMValue>(nullptr));
1321  for (unsigned int i = 0; i < _current_normals.size(); i++)
1322  // Note: this does NOT do any allocation. It is "reconstructing" the object in place
1323  new (&_mapped_normals[i]) Eigen::Map<RealDIMValue>(const_cast<Real *>(&_current_normals[i](0)));
1324 
1327  const_cast<std::vector<Real> &>(_holder_fe_face_helper[dim]->get_curvatures()));
1328 
1329  computeADFace(*elem, side);
1330 
1331  if (_xfem != nullptr)
1333 
1334  auto n = numExtraElemIntegers();
1335  for (auto i : make_range(n))
1336  _extra_elem_ids[i] = _current_elem->get_extra_integer(i);
1337  _extra_elem_ids[n] = _current_elem->subdomain_id();
1338 }
1339 
1340 void
1341 Assembly::computeFaceMap(const Elem & elem, const unsigned int side, const std::vector<Real> & qw)
1342 {
1343  // Important quantities calculated by this method:
1344  // - _ad_JxW_face
1345  // - _ad_q_points_face
1346  // - _ad_normals
1347  // - _ad_curvatures
1348 
1349  const Elem & side_elem = _compute_face_map_side_elem_builder(elem, side);
1350  const auto dim = elem.dim();
1351  const auto n_qp = qw.size();
1352  const auto & dpsidxi_map = _holder_fe_face_helper[dim]->get_fe_map().get_dpsidxi();
1353  const auto & dpsideta_map = _holder_fe_face_helper[dim]->get_fe_map().get_dpsideta();
1354  const auto & psi_map = _holder_fe_face_helper[dim]->get_fe_map().get_psi();
1355  std::vector<std::vector<Real>> const * d2psidxi2_map = nullptr;
1356  std::vector<std::vector<Real>> const * d2psidxideta_map = nullptr;
1357  std::vector<std::vector<Real>> const * d2psideta2_map = nullptr;
1358  const auto sys_num = _sys.number();
1359  const bool do_derivatives = ADReal::do_derivatives && sys_num == _subproblem.currentNlSysNum();
1360 
1362  {
1363  d2psidxi2_map = &_holder_fe_face_helper[dim]->get_fe_map().get_d2psidxi2();
1364  d2psidxideta_map = &_holder_fe_face_helper[dim]->get_fe_map().get_d2psidxideta();
1365  d2psideta2_map = &_holder_fe_face_helper[dim]->get_fe_map().get_d2psideta2();
1366  }
1367 
1368  switch (dim)
1369  {
1370  case 1:
1371  {
1372  if (!n_qp)
1373  break;
1374 
1375  if (side_elem.node_id(0) == elem.node_id(0))
1376  _ad_normals[0] = Point(-1.);
1377  else
1378  _ad_normals[0] = Point(1.);
1379 
1380  VectorValue<DualReal> side_point;
1381  if (_calculate_face_xyz)
1382  {
1383  const Node & node = side_elem.node_ref(0);
1384  side_point = node;
1385 
1386  if (do_derivatives)
1387  for (const auto & [disp_num, direction] : _disp_numbers_and_directions)
1389  side_point(direction).derivatives(), node.dof_number(sys_num, disp_num, 0), 1.);
1390  }
1391 
1392  for (unsigned int p = 0; p < n_qp; p++)
1393  {
1394  if (_calculate_face_xyz)
1395  {
1396  _ad_q_points_face[p].zero();
1397  _ad_q_points_face[p].add_scaled(side_point, psi_map[0][p]);
1398  }
1399 
1400  _ad_normals[p] = _ad_normals[0];
1401  _ad_JxW_face[p] = 1.0 * qw[p];
1402  }
1403 
1404  break;
1405  }
1406 
1407  case 2:
1408  {
1409  _ad_dxyzdxi_map.resize(n_qp);
1411  _ad_d2xyzdxi2_map.resize(n_qp);
1412 
1413  for (unsigned int p = 0; p < n_qp; p++)
1414  {
1415  _ad_dxyzdxi_map[p].zero();
1416  if (_calculate_face_xyz)
1417  _ad_q_points_face[p].zero();
1419  _ad_d2xyzdxi2_map[p].zero();
1420  }
1421 
1422  const auto n_mapping_shape_functions =
1423  FE<2, LAGRANGE>::n_shape_functions(side_elem.type(), side_elem.default_order());
1424 
1425  for (unsigned int i = 0; i < n_mapping_shape_functions; i++)
1426  {
1427  const Node & node = side_elem.node_ref(i);
1428  VectorValue<DualReal> side_point = node;
1429 
1430  if (do_derivatives)
1431  for (const auto & [disp_num, direction] : _disp_numbers_and_directions)
1433  side_point(direction).derivatives(), node.dof_number(sys_num, disp_num, 0), 1.);
1434 
1435  for (unsigned int p = 0; p < n_qp; p++)
1436  {
1437  _ad_dxyzdxi_map[p].add_scaled(side_point, dpsidxi_map[i][p]);
1438  if (_calculate_face_xyz)
1439  _ad_q_points_face[p].add_scaled(side_point, psi_map[i][p]);
1441  _ad_d2xyzdxi2_map[p].add_scaled(side_point, (*d2psidxi2_map)[i][p]);
1442  }
1443  }
1444 
1445  for (unsigned int p = 0; p < n_qp; p++)
1446  {
1447  _ad_normals[p] =
1448  (VectorValue<DualReal>(_ad_dxyzdxi_map[p](1), -_ad_dxyzdxi_map[p](0), 0.)).unit();
1449  const auto the_jac = _ad_dxyzdxi_map[p].norm();
1450  _ad_JxW_face[p] = the_jac * qw[p];
1452  {
1453  const auto numerator = _ad_d2xyzdxi2_map[p] * _ad_normals[p];
1454  const auto denominator = _ad_dxyzdxi_map[p].norm_sq();
1455  libmesh_assert_not_equal_to(denominator, 0);
1456  _ad_curvatures[p] = numerator / denominator;
1457  }
1458  }
1459 
1460  break;
1461  }
1462 
1463  case 3:
1464  {
1465  _ad_dxyzdxi_map.resize(n_qp);
1466  _ad_dxyzdeta_map.resize(n_qp);
1468  {
1469  _ad_d2xyzdxi2_map.resize(n_qp);
1470  _ad_d2xyzdxideta_map.resize(n_qp);
1471  _ad_d2xyzdeta2_map.resize(n_qp);
1472  }
1473 
1474  for (unsigned int p = 0; p < n_qp; p++)
1475  {
1476  _ad_dxyzdxi_map[p].zero();
1477  _ad_dxyzdeta_map[p].zero();
1478  if (_calculate_face_xyz)
1479  _ad_q_points_face[p].zero();
1481  {
1482  _ad_d2xyzdxi2_map[p].zero();
1483  _ad_d2xyzdxideta_map[p].zero();
1484  _ad_d2xyzdeta2_map[p].zero();
1485  }
1486  }
1487 
1488  const unsigned int n_mapping_shape_functions =
1489  FE<3, LAGRANGE>::n_shape_functions(side_elem.type(), side_elem.default_order());
1490 
1491  for (unsigned int i = 0; i < n_mapping_shape_functions; i++)
1492  {
1493  const Node & node = side_elem.node_ref(i);
1494  VectorValue<DualReal> side_point = node;
1495 
1496  if (do_derivatives)
1497  for (const auto & [disp_num, direction] : _disp_numbers_and_directions)
1499  side_point(direction).derivatives(), node.dof_number(sys_num, disp_num, 0), 1.);
1500 
1501  for (unsigned int p = 0; p < n_qp; p++)
1502  {
1503  _ad_dxyzdxi_map[p].add_scaled(side_point, dpsidxi_map[i][p]);
1504  _ad_dxyzdeta_map[p].add_scaled(side_point, dpsideta_map[i][p]);
1505  if (_calculate_face_xyz)
1506  _ad_q_points_face[p].add_scaled(side_point, psi_map[i][p]);
1508  {
1509  _ad_d2xyzdxi2_map[p].add_scaled(side_point, (*d2psidxi2_map)[i][p]);
1510  _ad_d2xyzdxideta_map[p].add_scaled(side_point, (*d2psidxideta_map)[i][p]);
1511  _ad_d2xyzdeta2_map[p].add_scaled(side_point, (*d2psideta2_map)[i][p]);
1512  }
1513  }
1514  }
1515 
1516  for (unsigned int p = 0; p < n_qp; p++)
1517  {
1518  _ad_normals[p] = _ad_dxyzdxi_map[p].cross(_ad_dxyzdeta_map[p]).unit();
1519 
1520  const auto &dxdxi = _ad_dxyzdxi_map[p](0), dxdeta = _ad_dxyzdeta_map[p](0),
1521  dydxi = _ad_dxyzdxi_map[p](1), dydeta = _ad_dxyzdeta_map[p](1),
1522  dzdxi = _ad_dxyzdxi_map[p](2), dzdeta = _ad_dxyzdeta_map[p](2);
1523 
1524  const auto g11 = (dxdxi * dxdxi + dydxi * dydxi + dzdxi * dzdxi);
1525 
1526  const auto g12 = (dxdxi * dxdeta + dydxi * dydeta + dzdxi * dzdeta);
1527 
1528  const auto g21 = g12;
1529 
1530  const auto g22 = (dxdeta * dxdeta + dydeta * dydeta + dzdeta * dzdeta);
1531 
1532  const auto the_jac = std::sqrt(g11 * g22 - g12 * g21);
1533 
1534  _ad_JxW_face[p] = the_jac * qw[p];
1535 
1537  {
1538  const auto L = -_ad_d2xyzdxi2_map[p] * _ad_normals[p];
1539  const auto M = -_ad_d2xyzdxideta_map[p] * _ad_normals[p];
1540  const auto N = -_ad_d2xyzdeta2_map[p] * _ad_normals[p];
1541  const auto E = _ad_dxyzdxi_map[p].norm_sq();
1542  const auto F = _ad_dxyzdxi_map[p] * _ad_dxyzdeta_map[p];
1543  const auto G = _ad_dxyzdeta_map[p].norm_sq();
1544 
1545  const auto numerator = E * N - 2. * F * M + G * L;
1546  const auto denominator = E * G - F * F;
1547  libmesh_assert_not_equal_to(denominator, 0.);
1548  _ad_curvatures[p] = 0.5 * numerator / denominator;
1549  }
1550  }
1551 
1552  break;
1553  }
1554 
1555  default:
1556  mooseError("Invalid dimension dim = ", dim);
1557  }
1558 }
1559 
1560 void
1561 Assembly::reinitFEFaceNeighbor(const Elem * neighbor, const std::vector<Point> & reference_points)
1562 {
1563  unsigned int neighbor_dim = neighbor->dim();
1564 
1565  // reinit neighbor face
1566  for (const auto & it : _fe_face_neighbor[neighbor_dim])
1567  {
1568  FEBase & fe_face_neighbor = *it.second;
1569  FEType fe_type = it.first;
1570  FEShapeData & fesd = *_fe_shape_data_face_neighbor[fe_type];
1571 
1572  fe_face_neighbor.reinit(neighbor, &reference_points);
1573 
1574  _current_fe_face_neighbor[fe_type] = &fe_face_neighbor;
1575 
1576  fesd._phi.shallowCopy(const_cast<std::vector<std::vector<Real>> &>(fe_face_neighbor.get_phi()));
1577  fesd._grad_phi.shallowCopy(
1578  const_cast<std::vector<std::vector<RealGradient>> &>(fe_face_neighbor.get_dphi()));
1580  fesd._second_phi.shallowCopy(
1581  const_cast<std::vector<std::vector<TensorValue<Real>>> &>(fe_face_neighbor.get_d2phi()));
1582  }
1583  for (const auto & it : _vector_fe_face_neighbor[neighbor_dim])
1584  {
1585  FEVectorBase & fe_face_neighbor = *it.second;
1586  const FEType & fe_type = it.first;
1587 
1588  _current_vector_fe_face_neighbor[fe_type] = &fe_face_neighbor;
1589 
1591 
1592  fe_face_neighbor.reinit(neighbor, &reference_points);
1593 
1594  fesd._phi.shallowCopy(
1595  const_cast<std::vector<std::vector<VectorValue<Real>>> &>(fe_face_neighbor.get_phi()));
1596  fesd._grad_phi.shallowCopy(
1597  const_cast<std::vector<std::vector<TensorValue<Real>>> &>(fe_face_neighbor.get_dphi()));
1598  if (_need_second_derivative.find(fe_type) != _need_second_derivative.end())
1599  fesd._second_phi.shallowCopy(const_cast<std::vector<std::vector<TypeNTensor<3, Real>>> &>(
1600  fe_face_neighbor.get_d2phi()));
1601  if (_need_curl.find(fe_type) != _need_curl.end())
1602  fesd._curl_phi.shallowCopy(const_cast<std::vector<std::vector<VectorValue<Real>>> &>(
1603  fe_face_neighbor.get_curl_phi()));
1604  if (_need_div.find(fe_type) != _need_div.end())
1605  fesd._div_phi.shallowCopy(
1606  const_cast<std::vector<std::vector<Real>> &>(fe_face_neighbor.get_div_phi()));
1607  }
1608  if (!_unique_fe_face_neighbor_helper.empty())
1609  {
1610  mooseAssert(neighbor_dim < _unique_fe_face_neighbor_helper.size(),
1611  "We should be in bounds here");
1612  _unique_fe_face_neighbor_helper[neighbor_dim]->reinit(neighbor, &reference_points);
1613  }
1614 
1616  const_cast<std::vector<Point> &>(_holder_fe_face_neighbor_helper[neighbor_dim]->get_xyz()));
1617 }
1618 
1619 void
1620 Assembly::reinitFENeighbor(const Elem * neighbor, const std::vector<Point> & reference_points)
1621 {
1622  unsigned int neighbor_dim = neighbor->dim();
1623 
1624  // reinit neighbor face
1625  for (const auto & it : _fe_neighbor[neighbor_dim])
1626  {
1627  FEBase & fe_neighbor = *it.second;
1628  FEType fe_type = it.first;
1629  FEShapeData & fesd = *_fe_shape_data_neighbor[fe_type];
1630 
1631  fe_neighbor.reinit(neighbor, &reference_points);
1632 
1633  _current_fe_neighbor[fe_type] = &fe_neighbor;
1634 
1635  fesd._phi.shallowCopy(const_cast<std::vector<std::vector<Real>> &>(fe_neighbor.get_phi()));
1636  fesd._grad_phi.shallowCopy(
1637  const_cast<std::vector<std::vector<RealGradient>> &>(fe_neighbor.get_dphi()));
1639  fesd._second_phi.shallowCopy(
1640  const_cast<std::vector<std::vector<TensorValue<Real>>> &>(fe_neighbor.get_d2phi()));
1641  }
1642  for (const auto & it : _vector_fe_neighbor[neighbor_dim])
1643  {
1644  FEVectorBase & fe_neighbor = *it.second;
1645  const FEType & fe_type = it.first;
1646 
1647  _current_vector_fe_neighbor[fe_type] = &fe_neighbor;
1648 
1650 
1651  fe_neighbor.reinit(neighbor, &reference_points);
1652 
1653  fesd._phi.shallowCopy(
1654  const_cast<std::vector<std::vector<VectorValue<Real>>> &>(fe_neighbor.get_phi()));
1655  fesd._grad_phi.shallowCopy(
1656  const_cast<std::vector<std::vector<TensorValue<Real>>> &>(fe_neighbor.get_dphi()));
1657  if (_need_second_derivative.find(fe_type) != _need_second_derivative.end())
1658  fesd._second_phi.shallowCopy(
1659  const_cast<std::vector<std::vector<TypeNTensor<3, Real>>> &>(fe_neighbor.get_d2phi()));
1660  if (_need_curl.find(fe_type) != _need_curl.end())
1661  fesd._curl_phi.shallowCopy(
1662  const_cast<std::vector<std::vector<VectorValue<Real>>> &>(fe_neighbor.get_curl_phi()));
1663  if (_need_div.find(fe_type) != _need_div.end())
1664  fesd._div_phi.shallowCopy(
1665  const_cast<std::vector<std::vector<Real>> &>(fe_neighbor.get_div_phi()));
1666  }
1667  if (!_unique_fe_neighbor_helper.empty())
1668  {
1669  mooseAssert(neighbor_dim < _unique_fe_neighbor_helper.size(), "We should be in bounds here");
1670  _unique_fe_neighbor_helper[neighbor_dim]->reinit(neighbor, &reference_points);
1671  }
1672 }
1673 
1674 void
1675 Assembly::reinitNeighbor(const Elem * neighbor, const std::vector<Point> & reference_points)
1676 {
1677  unsigned int neighbor_dim = neighbor->dim();
1678  mooseAssert(_current_neighbor_subdomain_id == neighbor->subdomain_id(),
1679  "Neighbor subdomain ID has not been correctly set");
1680 
1681  ArbitraryQuadrature * neighbor_rule =
1682  qrules(neighbor_dim, _current_neighbor_subdomain_id).neighbor.get();
1683  neighbor_rule->setPoints(reference_points);
1684  setNeighborQRule(neighbor_rule, neighbor_dim);
1685 
1687  mooseAssert(_current_neighbor_subdomain_id == _current_neighbor_elem->subdomain_id(),
1688  "current neighbor subdomain has been set incorrectly");
1689 
1690  // Calculate the volume of the neighbor
1692  {
1693  unsigned int dim = neighbor->dim();
1695  QBase * qrule = qrules(dim).vol.get();
1696 
1697  fe.attach_quadrature_rule(qrule);
1698  fe.reinit(neighbor);
1699 
1700  const std::vector<Real> & JxW = fe.get_JxW();
1701  MooseArray<Point> q_points;
1702  q_points.shallowCopy(const_cast<std::vector<Point> &>(fe.get_xyz()));
1703 
1705 
1707  for (unsigned int qp = 0; qp < qrule->n_points(); qp++)
1709  }
1710 
1711  auto n = numExtraElemIntegers();
1712  for (auto i : make_range(n))
1713  _neighbor_extra_elem_ids[i] = _current_neighbor_elem->get_extra_integer(i);
1714  _neighbor_extra_elem_ids[n] = _current_neighbor_elem->subdomain_id();
1715 }
1716 
1717 template <typename Points, typename Coords>
1718 void
1720  const Points & q_points,
1721  Coords & coord,
1722  SubdomainID sub_id)
1723 {
1724 
1725  mooseAssert(qrule, "The quadrature rule is null in Assembly::setCoordinateTransformation");
1726  auto n_points = qrule->n_points();
1727  mooseAssert(n_points == q_points.size(),
1728  "The number of points in the quadrature rule doesn't match the number of passed-in "
1729  "points in Assembly::setCoordinateTransformation");
1730 
1731  // Make sure to honor the name of this method and set the _coord_type member because users may
1732  // make use of the const Moose::CoordinateSystem & coordTransformation() { return _coord_type; }
1733  // API. MaterialBase for example uses it
1735 
1736  coord.resize(n_points);
1737  for (unsigned int qp = 0; qp < n_points; qp++)
1738  coordTransformFactor(_subproblem, sub_id, q_points[qp], coord[qp]);
1739 }
1740 
1741 void
1743 {
1745  return;
1746 
1749  if (_calculate_ad_coord)
1751  _current_qrule, _ad_q_points, _ad_coord, _current_elem->subdomain_id());
1752 
1753  _current_elem_volume = 0.;
1754  for (unsigned int qp = 0; qp < _current_qrule->n_points(); qp++)
1756 
1758 }
1759 
1760 void
1762 {
1764  return;
1765 
1768  if (_calculate_ad_coord)
1771 
1772  _current_side_volume = 0.;
1773  for (unsigned int qp = 0; qp < _current_qrule_face->n_points(); qp++)
1775 
1777 }
1778 
1779 void
1780 Assembly::reinitAtPhysical(const Elem * elem, const std::vector<Point> & physical_points)
1781 {
1782  _current_elem = elem;
1783  _current_neighbor_elem = nullptr;
1784  mooseAssert(_current_subdomain_id == _current_elem->subdomain_id(),
1785  "current subdomain has been set incorrectly");
1787 
1788  FEInterface::inverse_map(elem->dim(),
1789  _holder_fe_helper[elem->dim()]->get_fe_type(),
1790  elem,
1791  physical_points,
1793 
1795 
1796  // Save off the physical points
1797  _current_physical_points = physical_points;
1798 }
1799 
1800 void
1801 Assembly::setVolumeQRule(const Elem * const elem)
1802 {
1803  unsigned int elem_dimension = elem->dim();
1804  _current_qrule_volume = qrules(elem_dimension).vol.get();
1805  // Make sure the qrule is the right one
1807  setVolumeQRule(_current_qrule_volume, elem_dimension);
1808 }
1809 
1810 void
1811 Assembly::reinit(const Elem * elem)
1812 {
1813  _current_elem = elem;
1814  _current_neighbor_elem = nullptr;
1815  mooseAssert(_current_subdomain_id == _current_elem->subdomain_id(),
1816  "current subdomain has been set incorrectly");
1818 
1820  reinitFE(elem);
1821 
1823 }
1824 
1825 void
1826 Assembly::reinit(const Elem * elem, const std::vector<Point> & reference_points)
1827 {
1828  _current_elem = elem;
1829  _current_neighbor_elem = nullptr;
1830  mooseAssert(_current_subdomain_id == _current_elem->subdomain_id(),
1831  "current subdomain has been set incorrectly");
1833 
1834  unsigned int elem_dimension = _current_elem->dim();
1835 
1836  _current_qrule_arbitrary = qrules(elem_dimension).arbitrary_vol.get();
1837 
1838  // Make sure the qrule is the right one
1840  setVolumeQRule(_current_qrule_arbitrary, elem_dimension);
1841 
1842  _current_qrule_arbitrary->setPoints(reference_points);
1843 
1844  reinitFE(elem);
1845 
1847 }
1848 
1849 void
1851 {
1852  _current_elem = &fi.elem();
1854  _current_side = fi.elemSideID();
1856  mooseAssert(_current_subdomain_id == _current_elem->subdomain_id(),
1857  "current subdomain has been set incorrectly");
1858 
1861 
1862  prepareResidual();
1863  prepareNeighbor();
1865 
1866  unsigned int dim = _current_elem->dim();
1867  if (_current_qrule_face != qrules(dim).fv_face.get())
1868  {
1869  setFaceQRule(qrules(dim).fv_face.get(), dim);
1870  // The order of the element that is used for initing here doesn't matter since this will just
1871  // be used for constant monomials (which only need a single integration point)
1872  if (dim == 3)
1873  _current_qrule_face->init(QUAD4);
1874  else
1875  _current_qrule_face->init(EDGE2);
1876  }
1877 
1879 
1880  mooseAssert(_current_qrule_face->n_points() == 1,
1881  "Our finite volume quadrature rule should always yield a single point");
1882 
1883  // We've initialized the reference points. Now we need to compute the physical location of the
1884  // quadrature points. We do not do any FE initialization so we cannot simply copy over FE
1885  // results like we do in reinitFEFace. Instead we handle the computation of the physical
1886  // locations manually
1888  const auto & ref_points = _current_qrule_face->get_points();
1889  const auto & ref_point = ref_points[0];
1890  auto physical_point = FEMap::map(_current_side_elem->dim(), _current_side_elem, ref_point);
1891  _current_q_points_face[0] = physical_point;
1892 
1894  {
1895  mooseAssert(_current_neighbor_subdomain_id == _current_neighbor_elem->subdomain_id(),
1896  "current neighbor subdomain has been set incorrectly");
1897  // Now handle the neighbor qrule/qpoints
1898  ArbitraryQuadrature * const neighbor_rule =
1900  // Here we are setting a reference point that is correct for the neighbor *side* element. It
1901  // would be wrong if this reference point is used for a volumetric FE reinit with the neighbor
1902  neighbor_rule->setPoints(ref_points);
1903  setNeighborQRule(neighbor_rule, _current_neighbor_elem->dim());
1905  _current_q_points_face_neighbor[0] = std::move(physical_point);
1906  }
1907 }
1908 
1909 QBase *
1910 Assembly::qruleFace(const Elem * elem, unsigned int side)
1911 {
1912  return qruleFaceHelper<QBase>(elem, side, [](QRules & q) { return q.face.get(); });
1913 }
1914 
1916 Assembly::qruleArbitraryFace(const Elem * elem, unsigned int side)
1917 {
1918  return qruleFaceHelper<ArbitraryQuadrature>(
1919  elem, side, [](QRules & q) { return q.arbitrary_face.get(); });
1920 }
1921 
1922 void
1923 Assembly::setFaceQRule(const Elem * const elem, const unsigned int side)
1924 {
1925  const auto elem_dimension = elem->dim();
1927  auto rule = qruleFace(elem, side);
1928  if (_current_qrule_face != rule)
1929  setFaceQRule(rule, elem_dimension);
1930 }
1931 
1932 void
1933 Assembly::reinit(const Elem * const elem, const unsigned int side)
1934 {
1935  _current_elem = elem;
1936  _current_neighbor_elem = nullptr;
1937  mooseAssert(_current_subdomain_id == _current_elem->subdomain_id(),
1938  "current subdomain has been set incorrectly");
1939  _current_side = side;
1942 
1944 
1947 
1949 }
1950 
1951 void
1952 Assembly::reinit(const Elem * elem, unsigned int side, const std::vector<Point> & reference_points)
1953 {
1954  _current_elem = elem;
1955  _current_neighbor_elem = nullptr;
1956  mooseAssert(_current_subdomain_id == _current_elem->subdomain_id(),
1957  "current subdomain has been set incorrectly");
1958  _current_side = side;
1961 
1962  unsigned int elem_dimension = _current_elem->dim();
1963 
1965 
1966  // Make sure the qrule is the right one
1969 
1970  _current_qrule_arbitrary->setPoints(reference_points);
1971 
1973 
1975 
1977 }
1978 
1979 void
1980 Assembly::reinit(const Node * node)
1981 {
1982  _current_node = node;
1983  _current_neighbor_node = NULL;
1984 }
1985 
1986 void
1988  unsigned int side,
1989  const Elem * neighbor,
1990  unsigned int neighbor_side,
1991  const std::vector<Point> * neighbor_reference_points)
1992 {
1993  _current_neighbor_side = neighbor_side;
1994 
1995  reinit(elem, side);
1996 
1997  unsigned int neighbor_dim = neighbor->dim();
1998 
1999  if (neighbor_reference_points)
2000  _current_neighbor_ref_points = *neighbor_reference_points;
2001  else
2002  FEInterface::inverse_map(neighbor_dim,
2003  FEType(),
2004  neighbor,
2007 
2009 
2012 }
2013 
2014 void
2016  unsigned int elem_side,
2017  Real tolerance,
2018  const std::vector<Point> * const pts,
2019  const std::vector<Real> * const weights)
2020 {
2021  _current_elem = elem;
2022 
2023  unsigned int elem_dim = elem->dim();
2024 
2025  // Attach the quadrature rules
2026  if (pts)
2027  {
2028  auto face_rule = qruleArbitraryFace(elem, elem_side);
2029  face_rule->setPoints(*pts);
2030  setFaceQRule(face_rule, elem_dim);
2031  }
2032  else
2033  {
2034  auto rule = qruleFace(elem, elem_side);
2035  if (_current_qrule_face != rule)
2036  setFaceQRule(rule, elem_dim);
2037  }
2038 
2039  // reinit face
2040  for (const auto & it : _fe_face[elem_dim])
2041  {
2042  FEBase & fe_face = *it.second;
2043  FEType fe_type = it.first;
2044  FEShapeData & fesd = *_fe_shape_data_face[fe_type];
2045 
2046  fe_face.reinit(elem, elem_side, tolerance, pts, weights);
2047 
2048  _current_fe_face[fe_type] = &fe_face;
2049 
2050  fesd._phi.shallowCopy(const_cast<std::vector<std::vector<Real>> &>(fe_face.get_phi()));
2051  fesd._grad_phi.shallowCopy(
2052  const_cast<std::vector<std::vector<RealGradient>> &>(fe_face.get_dphi()));
2054  fesd._second_phi.shallowCopy(
2055  const_cast<std::vector<std::vector<TensorValue<Real>>> &>(fe_face.get_d2phi()));
2056  }
2057  for (const auto & it : _vector_fe_face[elem_dim])
2058  {
2059  FEVectorBase & fe_face = *it.second;
2060  const FEType & fe_type = it.first;
2061 
2062  _current_vector_fe_face[fe_type] = &fe_face;
2063 
2064  VectorFEShapeData & fesd = *_vector_fe_shape_data_face[fe_type];
2065 
2066  fe_face.reinit(elem, elem_side, tolerance, pts, weights);
2067 
2068  fesd._phi.shallowCopy(
2069  const_cast<std::vector<std::vector<VectorValue<Real>>> &>(fe_face.get_phi()));
2070  fesd._grad_phi.shallowCopy(
2071  const_cast<std::vector<std::vector<TensorValue<Real>>> &>(fe_face.get_dphi()));
2072  if (_need_second_derivative.find(fe_type) != _need_second_derivative.end())
2073  fesd._second_phi.shallowCopy(
2074  const_cast<std::vector<std::vector<TypeNTensor<3, Real>>> &>(fe_face.get_d2phi()));
2075  if (_need_curl.find(fe_type) != _need_curl.end())
2076  fesd._curl_phi.shallowCopy(
2077  const_cast<std::vector<std::vector<VectorValue<Real>>> &>(fe_face.get_curl_phi()));
2078  if (_need_div.find(fe_type) != _need_div.end())
2079  fesd._div_phi.shallowCopy(
2080  const_cast<std::vector<std::vector<Real>> &>(fe_face.get_div_phi()));
2081  }
2082  if (!_unique_fe_face_helper.empty())
2083  {
2084  mooseAssert(elem_dim < _unique_fe_face_helper.size(), "We should be in bounds here");
2085  _unique_fe_face_helper[elem_dim]->reinit(elem, elem_side, tolerance, pts, weights);
2086  }
2087 
2088  // During that last loop the helper objects will have been reinitialized
2090  const_cast<std::vector<Point> &>(_holder_fe_face_helper[elem_dim]->get_xyz()));
2092  const_cast<std::vector<Point> &>(_holder_fe_face_helper[elem_dim]->get_normals()));
2093  _current_tangents.shallowCopy(const_cast<std::vector<std::vector<Point>> &>(
2094  _holder_fe_face_helper[elem_dim]->get_tangents()));
2095  // Note that if the user did pass in points and not weights to this method, JxW will be garbage
2096  // and should not be used
2098  const_cast<std::vector<Real> &>(_holder_fe_face_helper[elem_dim]->get_JxW()));
2101  const_cast<std::vector<Real> &>(_holder_fe_face_helper[elem_dim]->get_curvatures()));
2102 
2103  computeADFace(*elem, elem_side);
2104 }
2105 
2106 void
2107 Assembly::computeADFace(const Elem & elem, const unsigned int side)
2108 {
2109  const auto dim = elem.dim();
2110 
2111  if (_subproblem.haveADObjects())
2112  {
2113  auto n_qp = _current_qrule_face->n_points();
2114  resizeADMappingObjects(n_qp, dim);
2115  _ad_normals.resize(n_qp);
2116  _ad_JxW_face.resize(n_qp);
2117  if (_calculate_face_xyz)
2118  _ad_q_points_face.resize(n_qp);
2120  _ad_curvatures.resize(n_qp);
2121 
2122  if (_displaced)
2123  {
2124  const auto & qw = _current_qrule_face->get_weights();
2125  computeFaceMap(elem, side, qw);
2126  const std::vector<Real> dummy_qw(n_qp, 1.);
2127 
2128  for (unsigned int qp = 0; qp != n_qp; qp++)
2130  }
2131  else
2132  for (unsigned qp = 0; qp < n_qp; ++qp)
2133  {
2134  _ad_JxW_face[qp] = _current_JxW_face[qp];
2135  if (_calculate_face_xyz)
2137  _ad_normals[qp] = _current_normals[qp];
2139  _ad_curvatures[qp] = _curvatures[qp];
2140  }
2141 
2142  for (const auto & it : _fe_face[dim])
2143  {
2144  FEBase & fe = *it.second;
2145  auto fe_type = it.first;
2146  auto num_shapes = fe.n_shape_functions();
2147  auto & grad_phi = _ad_grad_phi_data_face[fe_type];
2148 
2149  grad_phi.resize(num_shapes);
2150  for (decltype(num_shapes) i = 0; i < num_shapes; ++i)
2151  grad_phi[i].resize(n_qp);
2152 
2153  const auto & regular_grad_phi = _fe_shape_data_face[fe_type]->_grad_phi;
2154 
2155  if (_displaced)
2156  computeGradPhiAD(&elem, n_qp, grad_phi, &fe);
2157  else
2158  for (unsigned qp = 0; qp < n_qp; ++qp)
2159  for (decltype(num_shapes) i = 0; i < num_shapes; ++i)
2160  grad_phi[i][qp] = regular_grad_phi[i][qp];
2161  }
2162  for (const auto & it : _vector_fe_face[dim])
2163  {
2164  FEVectorBase & fe = *it.second;
2165  auto fe_type = it.first;
2166  auto num_shapes = fe.n_shape_functions();
2167  auto & grad_phi = _ad_vector_grad_phi_data_face[fe_type];
2168 
2169  grad_phi.resize(num_shapes);
2170  for (decltype(num_shapes) i = 0; i < num_shapes; ++i)
2171  grad_phi[i].resize(n_qp);
2172 
2173  const auto & regular_grad_phi = _vector_fe_shape_data_face[fe_type]->_grad_phi;
2174 
2175  if (_displaced)
2176  computeGradPhiAD(&elem, n_qp, grad_phi, &fe);
2177  else
2178  for (unsigned qp = 0; qp < n_qp; ++qp)
2179  for (decltype(num_shapes) i = 0; i < num_shapes; ++i)
2180  grad_phi[i][qp] = regular_grad_phi[i][qp];
2181  }
2182  }
2183 }
2184 
2185 void
2186 Assembly::reinitNeighborFaceRef(const Elem * neighbor,
2187  unsigned int neighbor_side,
2188  Real tolerance,
2189  const std::vector<Point> * const pts,
2190  const std::vector<Real> * const weights)
2191 {
2193 
2194  unsigned int neighbor_dim = neighbor->dim();
2195 
2196  ArbitraryQuadrature * neighbor_rule =
2197  qrules(neighbor_dim, neighbor->subdomain_id()).neighbor.get();
2198  neighbor_rule->setPoints(*pts);
2199 
2200  // Attach this quadrature rule to all the _fe_face_neighbor FE objects. This
2201  // has to have garbage quadrature weights but that's ok because we never
2202  // actually use the JxW coming from these FE reinit'd objects, e.g. we use the
2203  // JxW coming from the element face reinit for DGKernels or we use the JxW
2204  // coming from reinit of the mortar segment element in the case of mortar
2205  setNeighborQRule(neighbor_rule, neighbor_dim);
2206 
2207  // reinit neighbor face
2208  for (const auto & it : _fe_face_neighbor[neighbor_dim])
2209  {
2210  FEBase & fe_face_neighbor = *it.second;
2211  FEType fe_type = it.first;
2212  FEShapeData & fesd = *_fe_shape_data_face_neighbor[fe_type];
2213 
2214  fe_face_neighbor.reinit(neighbor, neighbor_side, tolerance, pts, weights);
2215 
2216  _current_fe_face_neighbor[fe_type] = &fe_face_neighbor;
2217 
2218  fesd._phi.shallowCopy(const_cast<std::vector<std::vector<Real>> &>(fe_face_neighbor.get_phi()));
2219  fesd._grad_phi.shallowCopy(
2220  const_cast<std::vector<std::vector<RealGradient>> &>(fe_face_neighbor.get_dphi()));
2222  fesd._second_phi.shallowCopy(
2223  const_cast<std::vector<std::vector<TensorValue<Real>>> &>(fe_face_neighbor.get_d2phi()));
2224  }
2225  for (const auto & it : _vector_fe_face_neighbor[neighbor_dim])
2226  {
2227  FEVectorBase & fe_face_neighbor = *it.second;
2228  const FEType & fe_type = it.first;
2229 
2230  _current_vector_fe_face_neighbor[fe_type] = &fe_face_neighbor;
2231 
2233 
2234  fe_face_neighbor.reinit(neighbor, neighbor_side, tolerance, pts, weights);
2235 
2236  fesd._phi.shallowCopy(
2237  const_cast<std::vector<std::vector<VectorValue<Real>>> &>(fe_face_neighbor.get_phi()));
2238  fesd._grad_phi.shallowCopy(
2239  const_cast<std::vector<std::vector<TensorValue<Real>>> &>(fe_face_neighbor.get_dphi()));
2240  if (_need_second_derivative.find(fe_type) != _need_second_derivative.end())
2241  fesd._second_phi.shallowCopy(const_cast<std::vector<std::vector<TypeNTensor<3, Real>>> &>(
2242  fe_face_neighbor.get_d2phi()));
2243  if (_need_curl.find(fe_type) != _need_curl.end())
2244  fesd._curl_phi.shallowCopy(const_cast<std::vector<std::vector<VectorValue<Real>>> &>(
2245  fe_face_neighbor.get_curl_phi()));
2246  if (_need_div.find(fe_type) != _need_div.end())
2247  fesd._div_phi.shallowCopy(
2248  const_cast<std::vector<std::vector<Real>> &>(fe_face_neighbor.get_div_phi()));
2249  }
2250  if (!_unique_fe_face_neighbor_helper.empty())
2251  {
2252  mooseAssert(neighbor_dim < _unique_fe_face_neighbor_helper.size(),
2253  "We should be in bounds here");
2254  _unique_fe_face_neighbor_helper[neighbor_dim]->reinit(
2255  neighbor, neighbor_side, tolerance, pts, weights);
2256  }
2257  // During that last loop the helper objects will have been reinitialized as well
2258  // We need to dig out the q_points from it
2260  const_cast<std::vector<Point> &>(_holder_fe_face_neighbor_helper[neighbor_dim]->get_xyz()));
2261 }
2262 
2263 void
2264 Assembly::reinitDual(const Elem * elem,
2265  const std::vector<Point> & pts,
2266  const std::vector<Real> & JxW)
2267 {
2268  const unsigned int elem_dim = elem->dim();
2269  mooseAssert(elem_dim == _mesh_dimension - 1,
2270  "Dual shape functions should only be computed on lower dimensional face elements");
2271 
2272  for (const auto & it : _fe_lower[elem_dim])
2273  {
2274  FEBase & fe_lower = *it.second;
2275  // We use customized quadrature rule for integration along the mortar segment elements
2276  fe_lower.set_calculate_default_dual_coeff(false);
2277  fe_lower.reinit_dual_shape_coeffs(elem, pts, JxW);
2278  }
2279 }
2280 
2281 void
2282 Assembly::reinitLowerDElem(const Elem * elem,
2283  const std::vector<Point> * const pts,
2284  const std::vector<Real> * const weights)
2285 {
2287 
2288  const unsigned int elem_dim = elem->dim();
2289  mooseAssert(elem_dim < _mesh_dimension,
2290  "The lower dimensional element should truly be a lower dimensional element");
2291 
2292  if (pts)
2293  {
2294  // Lower rule matches the face rule for the higher dimensional element
2295  ArbitraryQuadrature * lower_rule = qrules(elem_dim + 1).arbitrary_face.get();
2296 
2297  // This also sets the quadrature weights to unity
2298  lower_rule->setPoints(*pts);
2299 
2300  if (weights)
2301  lower_rule->setWeights(*weights);
2302 
2303  setLowerQRule(lower_rule, elem_dim);
2304  }
2305  else if (_current_qrule_lower != qrules(elem_dim + 1).face.get())
2306  setLowerQRule(qrules(elem_dim + 1).face.get(), elem_dim);
2307 
2308  for (const auto & it : _fe_lower[elem_dim])
2309  {
2310  FEBase & fe_lower = *it.second;
2311  FEType fe_type = it.first;
2312 
2313  fe_lower.reinit(elem);
2314 
2315  if (FEShapeData * fesd = _fe_shape_data_lower[fe_type].get())
2316  {
2317  fesd->_phi.shallowCopy(const_cast<std::vector<std::vector<Real>> &>(fe_lower.get_phi()));
2318  fesd->_grad_phi.shallowCopy(
2319  const_cast<std::vector<std::vector<RealGradient>> &>(fe_lower.get_dphi()));
2321  fesd->_second_phi.shallowCopy(
2322  const_cast<std::vector<std::vector<TensorValue<Real>>> &>(fe_lower.get_d2phi()));
2323  }
2324 
2325  // Dual shape functions need to be computed after primal basis being initialized
2326  if (FEShapeData * fesd = _fe_shape_data_dual_lower[fe_type].get())
2327  {
2328  fesd->_phi.shallowCopy(const_cast<std::vector<std::vector<Real>> &>(fe_lower.get_dual_phi()));
2329  fesd->_grad_phi.shallowCopy(
2330  const_cast<std::vector<std::vector<RealGradient>> &>(fe_lower.get_dual_dphi()));
2332  fesd->_second_phi.shallowCopy(
2333  const_cast<std::vector<std::vector<TensorValue<Real>>> &>(fe_lower.get_dual_d2phi()));
2334  }
2335  }
2336  if (!_unique_fe_lower_helper.empty())
2337  {
2338  mooseAssert(elem_dim < _unique_fe_lower_helper.size(), "We should be in bounds here");
2339  _unique_fe_lower_helper[elem_dim]->reinit(elem);
2340  }
2341 
2343  return;
2344 
2345  if (pts && !weights)
2346  {
2347  // We only have dummy weights so the JxWs computed during our FE reinits are meaningless and
2348  // we cannot use them
2349 
2351  // We are in a Cartesian coordinate system and we can just use the element volume method
2352  // which has fast computation for certain element types
2353  _current_lower_d_elem_volume = elem->volume();
2354  else
2355  // We manually compute the volume taking the curvilinear coordinate transformations into
2356  // account
2358  }
2359  else
2360  {
2361  // During that last loop the helper objects will have been reinitialized as well
2362  FEBase & helper_fe = *_holder_fe_lower_helper[elem_dim];
2363  const auto & physical_q_points = helper_fe.get_xyz();
2364  const auto & JxW = helper_fe.get_JxW();
2365  MooseArray<Real> coord;
2367  _current_qrule_lower, physical_q_points, coord, elem->subdomain_id());
2369  for (const auto qp : make_range(_current_qrule_lower->n_points()))
2370  _current_lower_d_elem_volume += JxW[qp] * coord[qp];
2371  }
2372 }
2373 
2374 void
2376 {
2377  mooseAssert(elem->dim() < _mesh_dimension,
2378  "You should be calling reinitNeighborLowerDElem on a lower dimensional element");
2379 
2381 
2383  return;
2384 
2386  // We are in a Cartesian coordinate system and we can just use the element volume method which
2387  // has fast computation for certain element types
2389  else
2390  // We manually compute the volume taking the curvilinear coordinate transformations into
2391  // account
2393 }
2394 
2395 void
2396 Assembly::reinitMortarElem(const Elem * elem)
2397 {
2398  mooseAssert(elem->dim() == _mesh_dimension - 1,
2399  "You should be calling reinitMortarElem on a lower dimensional element");
2400 
2401  _fe_msm->reinit(elem);
2402  _msm_elem = elem;
2403 
2404  MooseArray<Point> array_q_points;
2405  array_q_points.shallowCopy(const_cast<std::vector<Point> &>(_fe_msm->get_xyz()));
2406  setCoordinateTransformation(_qrule_msm, array_q_points, _coord_msm, elem->subdomain_id());
2407 }
2408 
2409 void
2411  unsigned int neighbor_side,
2412  const std::vector<Point> & physical_points)
2413 {
2414  unsigned int neighbor_dim = neighbor->dim();
2415  FEInterface::inverse_map(
2416  neighbor_dim, FEType(), neighbor, physical_points, _current_neighbor_ref_points);
2417 
2418  if (_need_JxW_neighbor)
2419  {
2420  mooseAssert(
2421  physical_points.size() == 1,
2422  "If reinitializing with more than one point, then I am dubious of your use case. Perhaps "
2423  "you are performing a DG type method and you are reinitializing using points from the "
2424  "element face. In such a case your neighbor JxW must have its index order 'match' the "
2425  "element JxW index order, e.g. imagining a vertical 1D face with two quadrature points, "
2426  "if "
2427  "index 0 for elem JxW corresponds to the 'top' quadrature point, then index 0 for "
2428  "neighbor "
2429  "JxW must also correspond to the 'top' quadrature point. And libMesh/MOOSE has no way to "
2430  "guarantee that with multiple quadrature points.");
2431 
2433 
2434  // With a single point our size-1 JxW should just be the element volume
2437  }
2438 
2441 
2442  // Save off the physical points
2443  _current_physical_points = physical_points;
2444 }
2445 
2446 void
2448  const std::vector<Point> & physical_points)
2449 {
2450  unsigned int neighbor_dim = neighbor->dim();
2451  FEInterface::inverse_map(
2452  neighbor_dim, FEType(), neighbor, physical_points, _current_neighbor_ref_points);
2453 
2456  // Save off the physical points
2457  _current_physical_points = physical_points;
2458 }
2459 
2460 void
2461 Assembly::init(const CouplingMatrix * cm)
2462 {
2463  _cm = cm;
2464 
2465  unsigned int n_vars = _sys.nVariables();
2466 
2467  _cm_ss_entry.clear();
2468  _cm_sf_entry.clear();
2469  _cm_fs_entry.clear();
2470  _cm_ff_entry.clear();
2471 
2472  auto & vars = _sys.getVariables(_tid);
2473 
2474  _block_diagonal_matrix = true;
2475  for (auto & ivar : vars)
2476  {
2477  auto i = ivar->number();
2478  if (i >= _component_block_diagonal.size())
2479  _component_block_diagonal.resize(i + 1, true);
2480 
2481  auto ivar_start = _cm_ff_entry.size();
2482  for (unsigned int k = 0; k < ivar->count(); ++k)
2483  {
2484  unsigned int iv = i + k;
2485  for (const auto & j : ConstCouplingRow(iv, *_cm))
2486  {
2487  if (_sys.isScalarVariable(j))
2488  {
2489  auto & jvar = _sys.getScalarVariable(_tid, j);
2490  _cm_fs_entry.push_back(std::make_pair(ivar, &jvar));
2491  _block_diagonal_matrix = false;
2492  }
2493  else
2494  {
2495  auto & jvar = _sys.getVariable(_tid, j);
2496  auto pair = std::make_pair(ivar, &jvar);
2497  auto c = ivar_start;
2498  // check if the pair has been pushed or not
2499  bool has_pair = false;
2500  for (; c < _cm_ff_entry.size(); ++c)
2501  if (_cm_ff_entry[c] == pair)
2502  {
2503  has_pair = true;
2504  break;
2505  }
2506  if (!has_pair)
2507  _cm_ff_entry.push_back(pair);
2508  // only set having diagonal matrix to false when ivar and jvar numbers are different
2509  // Note: for array variables, since we save the entire local Jacobian of all components,
2510  // even there are couplings among components of the same array variable, we still
2511  // do not set the flag to false.
2512  if (i != jvar.number())
2513  _block_diagonal_matrix = false;
2514  else if (iv != j)
2515  _component_block_diagonal[i] = false;
2516  }
2517  }
2518  }
2519  }
2520 
2521  auto & scalar_vars = _sys.getScalarVariables(_tid);
2522 
2523  for (auto & ivar : scalar_vars)
2524  {
2525  auto i = ivar->number();
2526  if (i >= _component_block_diagonal.size())
2527  _component_block_diagonal.resize(i + 1, true);
2528 
2529  for (const auto & j : ConstCouplingRow(i, *_cm))
2530  if (_sys.isScalarVariable(j))
2531  {
2532  auto & jvar = _sys.getScalarVariable(_tid, j);
2533  _cm_ss_entry.push_back(std::make_pair(ivar, &jvar));
2534  }
2535  else
2536  {
2537  auto & jvar = _sys.getVariable(_tid, j);
2538  _cm_sf_entry.push_back(std::make_pair(ivar, &jvar));
2539  }
2540  }
2541 
2542  if (_block_diagonal_matrix && scalar_vars.size() != 0)
2543  _block_diagonal_matrix = false;
2544 
2545  auto num_vector_tags = _residual_vector_tags.size();
2546 
2547  _sub_Re.resize(num_vector_tags);
2548  _sub_Rn.resize(num_vector_tags);
2549  _sub_Rl.resize(num_vector_tags);
2550  for (MooseIndex(_sub_Re) i = 0; i < _sub_Re.size(); i++)
2551  {
2552  _sub_Re[i].resize(n_vars);
2553  _sub_Rn[i].resize(n_vars);
2554  _sub_Rl[i].resize(n_vars);
2555  }
2556 
2557  _cached_residual_values.resize(num_vector_tags);
2558  _cached_residual_rows.resize(num_vector_tags);
2559 
2560  auto num_matrix_tags = _subproblem.numMatrixTags();
2561 
2562  _cached_jacobian_values.resize(num_matrix_tags);
2563  _cached_jacobian_rows.resize(num_matrix_tags);
2564  _cached_jacobian_cols.resize(num_matrix_tags);
2565 
2566  // Element matrices
2567  _sub_Kee.resize(num_matrix_tags);
2568  _sub_Keg.resize(num_matrix_tags);
2569  _sub_Ken.resize(num_matrix_tags);
2570  _sub_Kne.resize(num_matrix_tags);
2571  _sub_Knn.resize(num_matrix_tags);
2572  _sub_Kll.resize(num_matrix_tags);
2573  _sub_Kle.resize(num_matrix_tags);
2574  _sub_Kln.resize(num_matrix_tags);
2575  _sub_Kel.resize(num_matrix_tags);
2576  _sub_Knl.resize(num_matrix_tags);
2577 
2578  _jacobian_block_used.resize(num_matrix_tags);
2579  _jacobian_block_neighbor_used.resize(num_matrix_tags);
2580  _jacobian_block_lower_used.resize(num_matrix_tags);
2581  _jacobian_block_nonlocal_used.resize(num_matrix_tags);
2582 
2583  for (MooseIndex(num_matrix_tags) tag = 0; tag < num_matrix_tags; tag++)
2584  {
2585  _sub_Keg[tag].resize(n_vars);
2586  _sub_Ken[tag].resize(n_vars);
2587  _sub_Kne[tag].resize(n_vars);
2588  _sub_Knn[tag].resize(n_vars);
2589  _sub_Kee[tag].resize(n_vars);
2590  _sub_Kll[tag].resize(n_vars);
2591  _sub_Kle[tag].resize(n_vars);
2592  _sub_Kln[tag].resize(n_vars);
2593  _sub_Kel[tag].resize(n_vars);
2594  _sub_Knl[tag].resize(n_vars);
2595 
2596  _jacobian_block_used[tag].resize(n_vars);
2598  _jacobian_block_lower_used[tag].resize(n_vars);
2600  for (MooseIndex(n_vars) i = 0; i < n_vars; ++i)
2601  {
2603  {
2604  _sub_Kee[tag][i].resize(n_vars);
2605  _sub_Keg[tag][i].resize(n_vars);
2606  _sub_Ken[tag][i].resize(n_vars);
2607  _sub_Kne[tag][i].resize(n_vars);
2608  _sub_Knn[tag][i].resize(n_vars);
2609  _sub_Kll[tag][i].resize(n_vars);
2610  _sub_Kle[tag][i].resize(n_vars);
2611  _sub_Kln[tag][i].resize(n_vars);
2612  _sub_Kel[tag][i].resize(n_vars);
2613  _sub_Knl[tag][i].resize(n_vars);
2614 
2615  _jacobian_block_used[tag][i].resize(n_vars);
2616  _jacobian_block_neighbor_used[tag][i].resize(n_vars);
2617  _jacobian_block_lower_used[tag][i].resize(n_vars);
2618  _jacobian_block_nonlocal_used[tag][i].resize(n_vars);
2619  }
2620  else
2621  {
2622  _sub_Kee[tag][i].resize(1);
2623  _sub_Keg[tag][i].resize(1);
2624  _sub_Ken[tag][i].resize(1);
2625  _sub_Kne[tag][i].resize(1);
2626  _sub_Knn[tag][i].resize(1);
2627  _sub_Kll[tag][i].resize(1);
2628  _sub_Kle[tag][i].resize(1);
2629  _sub_Kln[tag][i].resize(1);
2630  _sub_Kel[tag][i].resize(1);
2631  _sub_Knl[tag][i].resize(1);
2632 
2633  _jacobian_block_used[tag][i].resize(1);
2634  _jacobian_block_neighbor_used[tag][i].resize(1);
2635  _jacobian_block_lower_used[tag][i].resize(1);
2636  _jacobian_block_nonlocal_used[tag][i].resize(1);
2637  }
2638  }
2639  }
2640 }
2641 
2642 void
2644 {
2645  _cm_nonlocal_entry.clear();
2646 
2647  auto & vars = _sys.getVariables(_tid);
2648 
2649  for (auto & ivar : vars)
2650  {
2651  auto i = ivar->number();
2652  auto ivar_start = _cm_nonlocal_entry.size();
2653  for (unsigned int k = 0; k < ivar->count(); ++k)
2654  {
2655  unsigned int iv = i + k;
2656  for (const auto & j : ConstCouplingRow(iv, _nonlocal_cm))
2657  if (!_sys.isScalarVariable(j))
2658  {
2659  auto & jvar = _sys.getVariable(_tid, j);
2660  auto pair = std::make_pair(ivar, &jvar);
2661  auto c = ivar_start;
2662  // check if the pair has been pushed or not
2663  bool has_pair = false;
2664  for (; c < _cm_nonlocal_entry.size(); ++c)
2665  if (_cm_nonlocal_entry[c] == pair)
2666  {
2667  has_pair = true;
2668  break;
2669  }
2670  if (!has_pair)
2671  _cm_nonlocal_entry.push_back(pair);
2672  }
2673  }
2674  }
2675 }
2676 
2677 void
2679 {
2680  for (const auto & it : _cm_ff_entry)
2681  {
2682  MooseVariableFEBase & ivar = *(it.first);
2683  MooseVariableFEBase & jvar = *(it.second);
2684 
2685  unsigned int vi = ivar.number();
2686  unsigned int vj = jvar.number();
2687 
2688  unsigned int jcount = (vi == vj && _component_block_diagonal[vi]) ? 1 : jvar.count();
2689 
2690  for (MooseIndex(_jacobian_block_used) tag = 0; tag < _jacobian_block_used.size(); tag++)
2691  {
2692  jacobianBlock(vi, vj, LocalDataKey{}, tag)
2693  .resize(ivar.dofIndices().size() * ivar.count(), jvar.dofIndices().size() * jcount);
2694  jacobianBlockUsed(tag, vi, vj, false);
2695  }
2696  }
2697 }
2698 
2699 void
2701 {
2702  const std::vector<MooseVariableFEBase *> & vars = _sys.getVariables(_tid);
2703  for (const auto & var : vars)
2704  for (auto & tag_Re : _sub_Re)
2705  tag_Re[var->number()].resize(var->dofIndices().size() * var->count());
2706 }
2707 
2708 void
2710 {
2712  prepareResidual();
2713 }
2714 
2715 void
2717 {
2718  for (const auto & it : _cm_nonlocal_entry)
2719  {
2720  MooseVariableFEBase & ivar = *(it.first);
2721  MooseVariableFEBase & jvar = *(it.second);
2722 
2723  unsigned int vi = ivar.number();
2724  unsigned int vj = jvar.number();
2725 
2726  unsigned int jcount = (vi == vj && _component_block_diagonal[vi]) ? 1 : jvar.count();
2727 
2728  for (MooseIndex(_jacobian_block_nonlocal_used) tag = 0;
2729  tag < _jacobian_block_nonlocal_used.size();
2730  tag++)
2731  {
2732  jacobianBlockNonlocal(vi, vj, LocalDataKey{}, tag)
2733  .resize(ivar.dofIndices().size() * ivar.count(), jvar.allDofIndices().size() * jcount);
2734  jacobianBlockNonlocalUsed(tag, vi, vj, false);
2735  }
2736  }
2737 }
2738 
2739 void
2741 {
2742  for (const auto & it : _cm_ff_entry)
2743  {
2744  MooseVariableFEBase & ivar = *(it.first);
2745  MooseVariableFEBase & jvar = *(it.second);
2746 
2747  unsigned int vi = ivar.number();
2748  unsigned int vj = jvar.number();
2749 
2750  unsigned int jcount = (vi == vj && _component_block_diagonal[vi]) ? 1 : jvar.count();
2751 
2752  if (vi == var->number() || vj == var->number())
2753  {
2754  for (MooseIndex(_jacobian_block_used) tag = 0; tag < _jacobian_block_used.size(); tag++)
2755  {
2756  jacobianBlock(vi, vj, LocalDataKey{}, tag)
2757  .resize(ivar.dofIndices().size() * ivar.count(), jvar.dofIndices().size() * jcount);
2758  jacobianBlockUsed(tag, vi, vj, false);
2759  }
2760  }
2761  }
2762 
2763  for (auto & tag_Re : _sub_Re)
2764  tag_Re[var->number()].resize(var->dofIndices().size() * var->count());
2765 }
2766 
2767 void
2769 {
2770  for (const auto & it : _cm_nonlocal_entry)
2771  {
2772  MooseVariableFEBase & ivar = *(it.first);
2773  MooseVariableFEBase & jvar = *(it.second);
2774 
2775  unsigned int vi = ivar.number();
2776  unsigned int vj = jvar.number();
2777 
2778  unsigned int jcount = (vi == vj && _component_block_diagonal[vi]) ? 1 : jvar.count();
2779 
2780  if (vi == var->number() || vj == var->number())
2781  {
2782  for (MooseIndex(_jacobian_block_nonlocal_used) tag = 0;
2783  tag < _jacobian_block_nonlocal_used.size();
2784  tag++)
2785  {
2786  jacobianBlockNonlocal(vi, vj, LocalDataKey{}, tag)
2787  .resize(ivar.dofIndices().size() * ivar.count(), jvar.allDofIndices().size() * jcount);
2788  jacobianBlockNonlocalUsed(tag, vi, vj);
2789  }
2790  }
2791  }
2792 }
2793 
2794 void
2796 {
2797  for (const auto & it : _cm_ff_entry)
2798  {
2799  MooseVariableFEBase & ivar = *(it.first);
2800  MooseVariableFEBase & jvar = *(it.second);
2801 
2802  unsigned int vi = ivar.number();
2803  unsigned int vj = jvar.number();
2804 
2805  unsigned int jcount = (vi == vj && _component_block_diagonal[vi]) ? 1 : jvar.count();
2806 
2807  for (MooseIndex(_jacobian_block_neighbor_used) tag = 0;
2808  tag < _jacobian_block_neighbor_used.size();
2809  tag++)
2810  {
2812  .resize(ivar.dofIndices().size() * ivar.count(),
2813  jvar.dofIndicesNeighbor().size() * jcount);
2814 
2816  .resize(ivar.dofIndicesNeighbor().size() * ivar.count(),
2817  jvar.dofIndices().size() * jcount);
2818 
2820  .resize(ivar.dofIndicesNeighbor().size() * ivar.count(),
2821  jvar.dofIndicesNeighbor().size() * jcount);
2822 
2823  jacobianBlockNeighborUsed(tag, vi, vj, false);
2824  }
2825  }
2826 
2827  const std::vector<MooseVariableFEBase *> & vars = _sys.getVariables(_tid);
2828  for (const auto & var : vars)
2829  for (auto & tag_Rn : _sub_Rn)
2830  tag_Rn[var->number()].resize(var->dofIndicesNeighbor().size() * var->count());
2831 }
2832 
2833 void
2835 {
2836  for (const auto & it : _cm_ff_entry)
2837  {
2838  MooseVariableFEBase & ivar = *(it.first);
2839  MooseVariableFEBase & jvar = *(it.second);
2840 
2841  unsigned int vi = ivar.number();
2842  unsigned int vj = jvar.number();
2843 
2844  unsigned int jcount = (vi == vj && _component_block_diagonal[vi]) ? 1 : jvar.count();
2845 
2846  for (MooseIndex(_jacobian_block_lower_used) tag = 0; tag < _jacobian_block_lower_used.size();
2847  tag++)
2848  {
2849  // To cover all possible cases we should have 9 combinations below for every 2-permutation
2850  // of Lower,Secondary,Primary. However, 4 cases will in general be covered by calls to
2851  // prepare() and prepareNeighbor(). These calls will cover SecondarySecondary
2852  // (ElementElement), SecondaryPrimary (ElementNeighbor), PrimarySecondary (NeighborElement),
2853  // and PrimaryPrimary (NeighborNeighbor). With these covered we only need to prepare the 5
2854  // remaining below
2855 
2856  // derivatives w.r.t. lower dimensional residuals
2858  .resize(ivar.dofIndicesLower().size() * ivar.count(),
2859  jvar.dofIndicesLower().size() * jcount);
2860 
2862  .resize(ivar.dofIndicesLower().size() * ivar.count(),
2863  jvar.dofIndices().size() * jvar.count());
2864 
2866  .resize(ivar.dofIndicesLower().size() * ivar.count(),
2867  jvar.dofIndicesNeighbor().size() * jvar.count());
2868 
2869  // derivatives w.r.t. interior secondary residuals
2871  .resize(ivar.dofIndices().size() * ivar.count(),
2872  jvar.dofIndicesLower().size() * jvar.count());
2873 
2874  // derivatives w.r.t. interior primary residuals
2876  .resize(ivar.dofIndicesNeighbor().size() * ivar.count(),
2877  jvar.dofIndicesLower().size() * jvar.count());
2878 
2879  jacobianBlockLowerUsed(tag, vi, vj, false);
2880  }
2881  }
2882 
2883  const std::vector<MooseVariableFEBase *> & vars = _sys.getVariables(_tid);
2884  for (const auto & var : vars)
2885  for (auto & tag_Rl : _sub_Rl)
2886  tag_Rl[var->number()].resize(var->dofIndicesLower().size() * var->count());
2887 }
2888 
2889 void
2890 Assembly::prepareBlock(unsigned int ivar,
2891  unsigned int jvar,
2892  const std::vector<dof_id_type> & dof_indices)
2893 {
2894  const auto & iv = _sys.getVariable(_tid, ivar);
2895  const auto & jv = _sys.getVariable(_tid, jvar);
2896  const unsigned int ivn = iv.number();
2897  const unsigned int jvn = jv.number();
2898  const unsigned int icount = iv.count();
2899  unsigned int jcount = jv.count();
2900  if (ivn == jvn && _component_block_diagonal[ivn])
2901  jcount = 1;
2902 
2903  for (MooseIndex(_jacobian_block_used) tag = 0; tag < _jacobian_block_used.size(); tag++)
2904  {
2905  jacobianBlock(ivn, jvn, LocalDataKey{}, tag)
2906  .resize(dof_indices.size() * icount, dof_indices.size() * jcount);
2907  jacobianBlockUsed(tag, ivn, jvn, false);
2908  }
2909 
2910  for (auto & tag_Re : _sub_Re)
2911  tag_Re[ivn].resize(dof_indices.size() * icount);
2912 }
2913 
2914 void
2916  unsigned int jvar,
2917  const std::vector<dof_id_type> & idof_indices,
2918  const std::vector<dof_id_type> & jdof_indices)
2919 {
2920  const auto & iv = _sys.getVariable(_tid, ivar);
2921  const auto & jv = _sys.getVariable(_tid, jvar);
2922  const unsigned int ivn = iv.number();
2923  const unsigned int jvn = jv.number();
2924  const unsigned int icount = iv.count();
2925  unsigned int jcount = jv.count();
2926  if (ivn == jvn && _component_block_diagonal[ivn])
2927  jcount = 1;
2928 
2929  for (MooseIndex(_jacobian_block_nonlocal_used) tag = 0;
2930  tag < _jacobian_block_nonlocal_used.size();
2931  tag++)
2932  {
2933  jacobianBlockNonlocal(ivn, jvn, LocalDataKey{}, tag)
2934  .resize(idof_indices.size() * icount, jdof_indices.size() * jcount);
2935 
2936  jacobianBlockNonlocalUsed(tag, ivn, jvn, false);
2937  }
2938 }
2939 
2940 void
2942 {
2943  const std::vector<MooseVariableScalar *> & vars = _sys.getScalarVariables(_tid);
2944  for (const auto & ivar : vars)
2945  {
2946  auto idofs = ivar->dofIndices().size();
2947 
2948  for (auto & tag_Re : _sub_Re)
2949  tag_Re[ivar->number()].resize(idofs);
2950 
2951  for (const auto & jvar : vars)
2952  {
2953  auto jdofs = jvar->dofIndices().size();
2954 
2955  for (MooseIndex(_jacobian_block_used) tag = 0; tag < _jacobian_block_used.size(); tag++)
2956  {
2957  jacobianBlock(ivar->number(), jvar->number(), LocalDataKey{}, tag).resize(idofs, jdofs);
2958  jacobianBlockUsed(tag, ivar->number(), jvar->number(), false);
2959  }
2960  }
2961  }
2962 }
2963 
2964 void
2966 {
2967  const std::vector<MooseVariableFEBase *> & vars = _sys.getVariables(_tid);
2968  const std::vector<MooseVariableScalar *> & scalar_vars = _sys.getScalarVariables(_tid);
2969 
2970  for (const auto & ivar : scalar_vars)
2971  {
2972  auto idofs = ivar->dofIndices().size();
2973 
2974  for (const auto & jvar : vars)
2975  {
2976  auto jdofs = jvar->dofIndices().size() * jvar->count();
2977  for (MooseIndex(_jacobian_block_used) tag = 0; tag < _jacobian_block_used.size(); tag++)
2978  {
2979  jacobianBlock(ivar->number(), jvar->number(), LocalDataKey{}, tag).resize(idofs, jdofs);
2980  jacobianBlockUsed(tag, ivar->number(), jvar->number(), false);
2981 
2982  jacobianBlock(jvar->number(), ivar->number(), LocalDataKey{}, tag).resize(jdofs, idofs);
2983  jacobianBlockUsed(tag, jvar->number(), ivar->number(), false);
2984  }
2985  }
2986  }
2987 }
2988 
2989 template <typename T>
2990 void
2992 {
2993  phi(v).shallowCopy(v.phi());
2994  gradPhi(v).shallowCopy(v.gradPhi());
2995  if (v.computingSecond())
2996  secondPhi(v).shallowCopy(v.secondPhi());
2997 }
2998 
2999 void
3000 Assembly::copyShapes(unsigned int var)
3001 {
3002  auto & v = _sys.getVariable(_tid, var);
3003  if (v.fieldType() == Moose::VarFieldType::VAR_FIELD_STANDARD)
3004  {
3005  auto & v = _sys.getActualFieldVariable<Real>(_tid, var);
3006  copyShapes(v);
3007  }
3008  else if (v.fieldType() == Moose::VarFieldType::VAR_FIELD_ARRAY)
3009  {
3010  auto & v = _sys.getActualFieldVariable<RealEigenVector>(_tid, var);
3011  copyShapes(v);
3012  }
3013  else if (v.fieldType() == Moose::VarFieldType::VAR_FIELD_VECTOR)
3014  {
3015  auto & v = _sys.getActualFieldVariable<RealVectorValue>(_tid, var);
3016  copyShapes(v);
3017  if (v.computingCurl())
3018  curlPhi(v).shallowCopy(v.curlPhi());
3019  if (v.computingDiv())
3020  divPhi(v).shallowCopy(v.divPhi());
3021  }
3022  else
3023  mooseError("Unsupported variable field type!");
3024 }
3025 
3026 template <typename T>
3027 void
3029 {
3030  phiFace(v).shallowCopy(v.phiFace());
3031  gradPhiFace(v).shallowCopy(v.gradPhiFace());
3032  if (v.computingSecond())
3033  secondPhiFace(v).shallowCopy(v.secondPhiFace());
3034 }
3035 
3036 void
3037 Assembly::copyFaceShapes(unsigned int var)
3038 {
3039  auto & v = _sys.getVariable(_tid, var);
3040  if (v.fieldType() == Moose::VarFieldType::VAR_FIELD_STANDARD)
3041  {
3042  auto & v = _sys.getActualFieldVariable<Real>(_tid, var);
3043  copyFaceShapes(v);
3044  }
3045  else if (v.fieldType() == Moose::VarFieldType::VAR_FIELD_ARRAY)
3046  {
3047  auto & v = _sys.getActualFieldVariable<RealEigenVector>(_tid, var);
3048  copyFaceShapes(v);
3049  }
3050  else if (v.fieldType() == Moose::VarFieldType::VAR_FIELD_VECTOR)
3051  {
3052  auto & v = _sys.getActualFieldVariable<RealVectorValue>(_tid, var);
3053  copyFaceShapes(v);
3054  if (v.computingCurl())
3055  _vector_curl_phi_face.shallowCopy(v.curlPhi());
3056  if (v.computingDiv())
3057  _vector_div_phi_face.shallowCopy(v.divPhi());
3058  }
3059  else
3060  mooseError("Unsupported variable field type!");
3061 }
3062 
3063 template <typename T>
3064 void
3066 {
3067  if (v.usesPhiNeighbor())
3068  {
3069  phiFaceNeighbor(v).shallowCopy(v.phiFaceNeighbor());
3070  phiNeighbor(v).shallowCopy(v.phiNeighbor());
3071  }
3072  if (v.usesGradPhiNeighbor())
3073  {
3074  gradPhiFaceNeighbor(v).shallowCopy(v.gradPhiFaceNeighbor());
3075  gradPhiNeighbor(v).shallowCopy(v.gradPhiNeighbor());
3076  }
3077  if (v.usesSecondPhiNeighbor())
3078  {
3079  secondPhiFaceNeighbor(v).shallowCopy(v.secondPhiFaceNeighbor());
3080  secondPhiNeighbor(v).shallowCopy(v.secondPhiNeighbor());
3081  }
3082 }
3083 
3084 void
3086 {
3087  auto & v = _sys.getVariable(_tid, var);
3088  if (v.fieldType() == Moose::VarFieldType::VAR_FIELD_STANDARD)
3089  {
3090  auto & v = _sys.getActualFieldVariable<Real>(_tid, var);
3091  copyNeighborShapes(v);
3092  }
3093  else if (v.fieldType() == Moose::VarFieldType::VAR_FIELD_ARRAY)
3094  {
3095  auto & v = _sys.getActualFieldVariable<RealEigenVector>(_tid, var);
3096  copyNeighborShapes(v);
3097  }
3098  else if (v.fieldType() == Moose::VarFieldType::VAR_FIELD_VECTOR)
3099  {
3100  auto & v = _sys.getActualFieldVariable<RealVectorValue>(_tid, var);
3101  copyNeighborShapes(v);
3102  }
3103  else
3104  mooseError("Unsupported variable field type!");
3105 }
3106 
3109  Moose::DGJacobianType type, unsigned int ivar, unsigned int jvar, LocalDataKey, TagID tag)
3110 {
3111  if (type == Moose::ElementElement)
3112  jacobianBlockUsed(tag, ivar, jvar, true);
3113  else
3114  jacobianBlockNeighborUsed(tag, ivar, jvar, true);
3115 
3117  {
3118  switch (type)
3119  {
3120  default:
3121  case Moose::ElementElement:
3122  return _sub_Kee[tag][ivar][0];
3124  return _sub_Ken[tag][ivar][0];
3126  return _sub_Kne[tag][ivar][0];
3128  return _sub_Knn[tag][ivar][0];
3129  }
3130  }
3131  else
3132  {
3133  switch (type)
3134  {
3135  default:
3136  case Moose::ElementElement:
3137  return _sub_Kee[tag][ivar][jvar];
3139  return _sub_Ken[tag][ivar][jvar];
3141  return _sub_Kne[tag][ivar][jvar];
3143  return _sub_Knn[tag][ivar][jvar];
3144  }
3145  }
3146 }
3147 
3150  unsigned int ivar,
3151  unsigned int jvar,
3152  LocalDataKey,
3153  TagID tag)
3154 {
3155  jacobianBlockLowerUsed(tag, ivar, jvar, true);
3157  {
3158  switch (type)
3159  {
3160  default:
3161  case Moose::LowerLower:
3162  return _sub_Kll[tag][ivar][0];
3163  case Moose::LowerSecondary:
3164  return _sub_Kle[tag][ivar][0];
3165  case Moose::LowerPrimary:
3166  return _sub_Kln[tag][ivar][0];
3167  case Moose::SecondaryLower:
3168  return _sub_Kel[tag][ivar][0];
3170  return _sub_Kee[tag][ivar][0];
3172  return _sub_Ken[tag][ivar][0];
3173  case Moose::PrimaryLower:
3174  return _sub_Knl[tag][ivar][0];
3176  return _sub_Kne[tag][ivar][0];
3177  case Moose::PrimaryPrimary:
3178  return _sub_Knn[tag][ivar][0];
3179  }
3180  }
3181  else
3182  {
3183  switch (type)
3184  {
3185  default:
3186  case Moose::LowerLower:
3187  return _sub_Kll[tag][ivar][jvar];
3188  case Moose::LowerSecondary:
3189  return _sub_Kle[tag][ivar][jvar];
3190  case Moose::LowerPrimary:
3191  return _sub_Kln[tag][ivar][jvar];
3192  case Moose::SecondaryLower:
3193  return _sub_Kel[tag][ivar][jvar];
3195  return _sub_Kee[tag][ivar][jvar];
3197  return _sub_Ken[tag][ivar][jvar];
3198  case Moose::PrimaryLower:
3199  return _sub_Knl[tag][ivar][jvar];
3201  return _sub_Kne[tag][ivar][jvar];
3202  case Moose::PrimaryPrimary:
3203  return _sub_Knn[tag][ivar][jvar];
3204  }
3205  }
3206 }
3207 
3208 void
3210  std::vector<dof_id_type> & dof_indices,
3211  const std::vector<Real> & scaling_factor,
3212  bool is_nodal)
3213 {
3214  // For an array variable, ndof is the number of dofs of the zero-th component and
3215  // ntdof is the number of dofs of all components.
3216  // For standard or vector variables, ndof will be the same as ntdof.
3217  auto ndof = dof_indices.size();
3218  auto ntdof = res_block.size();
3219  auto count = ntdof / ndof;
3220  mooseAssert(count == scaling_factor.size(), "Inconsistent of number of components");
3221  mooseAssert(count * ndof == ntdof, "Inconsistent of number of components");
3222  if (count > 1)
3223  {
3224  // expanding dof indices
3225  dof_indices.resize(ntdof);
3226  unsigned int p = 0;
3227  for (MooseIndex(count) j = 0; j < count; ++j)
3228  for (MooseIndex(ndof) i = 0; i < ndof; ++i)
3229  {
3230  dof_indices[p] = dof_indices[i] + (is_nodal ? j : j * ndof);
3231  res_block(p) *= scaling_factor[j];
3232  ++p;
3233  }
3234  }
3235  else
3236  {
3237  if (scaling_factor[0] != 1.0)
3238  res_block *= scaling_factor[0];
3239  }
3240 
3241  _dof_map.constrain_element_vector(res_block, dof_indices, false);
3242 }
3243 
3244 void
3246  DenseVector<Number> & res_block,
3247  const std::vector<dof_id_type> & dof_indices,
3248  const std::vector<Real> & scaling_factor,
3249  bool is_nodal)
3250 {
3251  if (dof_indices.size() > 0 && res_block.size())
3252  {
3253  _temp_dof_indices = dof_indices;
3254  _tmp_Re = res_block;
3255  processLocalResidual(_tmp_Re, _temp_dof_indices, scaling_factor, is_nodal);
3257  }
3258 }
3259 
3260 void
3261 Assembly::cacheResidualBlock(std::vector<Real> & cached_residual_values,
3262  std::vector<dof_id_type> & cached_residual_rows,
3263  DenseVector<Number> & res_block,
3264  const std::vector<dof_id_type> & dof_indices,
3265  const std::vector<Real> & scaling_factor,
3266  bool is_nodal)
3267 {
3268  if (dof_indices.size() > 0 && res_block.size())
3269  {
3270  _temp_dof_indices = dof_indices;
3271  _tmp_Re = res_block;
3272  processLocalResidual(_tmp_Re, _temp_dof_indices, scaling_factor, is_nodal);
3273 
3274  for (MooseIndex(_tmp_Re) i = 0; i < _tmp_Re.size(); i++)
3275  {
3276  cached_residual_values.push_back(_tmp_Re(i));
3277  cached_residual_rows.push_back(_temp_dof_indices[i]);
3278  }
3279  }
3280 
3281  res_block.zero();
3282 }
3283 
3284 void
3286  DenseVector<Number> & res_block,
3287  const std::vector<dof_id_type> & dof_indices,
3288  const std::vector<Real> & scaling_factor,
3289  bool is_nodal)
3290 {
3291  if (dof_indices.size() > 0)
3292  {
3293  std::vector<dof_id_type> di(dof_indices);
3294  _tmp_Re = res_block;
3295  processLocalResidual(_tmp_Re, di, scaling_factor, is_nodal);
3296  residual.insert(_tmp_Re, di);
3297  }
3298 }
3299 
3300 void
3302 {
3303  mooseAssert(vector_tag._type == Moose::VECTOR_TAG_RESIDUAL,
3304  "Non-residual tag in Assembly::addResidual");
3305 
3306  auto & tag_Re = _sub_Re[vector_tag._type_id];
3307  NumericVector<Number> & residual = _sys.getVector(vector_tag._id);
3308  const std::vector<MooseVariableFEBase *> & vars = _sys.getVariables(_tid);
3309  for (const auto & var : vars)
3310  addResidualBlock(residual,
3311  tag_Re[var->number()],
3312  var->dofIndices(),
3313  var->arrayScalingFactor(),
3314  var->isNodal());
3315 }
3316 
3317 void
3318 Assembly::addResidual(GlobalDataKey, const std::vector<VectorTag> & vector_tags)
3319 {
3320  for (const auto & vector_tag : vector_tags)
3321  if (_sys.hasVector(vector_tag._id))
3322  addResidual(vector_tag);
3323 }
3324 
3325 void
3327 {
3328  mooseAssert(vector_tag._type == Moose::VECTOR_TAG_RESIDUAL,
3329  "Non-residual tag in Assembly::addResidualNeighbor");
3330 
3331  auto & tag_Rn = _sub_Rn[vector_tag._type_id];
3332  NumericVector<Number> & residual = _sys.getVector(vector_tag._id);
3333  const std::vector<MooseVariableFEBase *> & vars = _sys.getVariables(_tid);
3334  for (const auto & var : vars)
3335  addResidualBlock(residual,
3336  tag_Rn[var->number()],
3337  var->dofIndicesNeighbor(),
3338  var->arrayScalingFactor(),
3339  var->isNodal());
3340 }
3341 
3342 void
3343 Assembly::addResidualNeighbor(GlobalDataKey, const std::vector<VectorTag> & vector_tags)
3344 {
3345  for (const auto & vector_tag : vector_tags)
3346  if (_sys.hasVector(vector_tag._id))
3347  addResidualNeighbor(vector_tag);
3348 }
3349 
3350 void
3352 {
3353  mooseAssert(vector_tag._type == Moose::VECTOR_TAG_RESIDUAL,
3354  "Non-residual tag in Assembly::addResidualLower");
3355 
3356  auto & tag_Rl = _sub_Rl[vector_tag._type_id];
3357  NumericVector<Number> & residual = _sys.getVector(vector_tag._id);
3358  const std::vector<MooseVariableFEBase *> & vars = _sys.getVariables(_tid);
3359  for (const auto & var : vars)
3360  addResidualBlock(residual,
3361  tag_Rl[var->number()],
3362  var->dofIndicesLower(),
3363  var->arrayScalingFactor(),
3364  var->isNodal());
3365 }
3366 
3367 void
3368 Assembly::addResidualLower(GlobalDataKey, const std::vector<VectorTag> & vector_tags)
3369 {
3370  for (const auto & vector_tag : vector_tags)
3371  if (_sys.hasVector(vector_tag._id))
3372  addResidualLower(vector_tag);
3373 }
3374 
3375 // private method, so no key required
3376 void
3378 {
3379  mooseAssert(vector_tag._type == Moose::VECTOR_TAG_RESIDUAL,
3380  "Non-residual tag in Assembly::addResidualScalar");
3381 
3382  // add the scalar variables residuals
3383  auto & tag_Re = _sub_Re[vector_tag._type_id];
3384  NumericVector<Number> & residual = _sys.getVector(vector_tag._id);
3385  const std::vector<MooseVariableScalar *> & vars = _sys.getScalarVariables(_tid);
3386  for (const auto & var : vars)
3388  residual, tag_Re[var->number()], var->dofIndices(), var->arrayScalingFactor(), false);
3389 }
3390 
3391 void
3392 Assembly::addResidualScalar(GlobalDataKey, const std::vector<VectorTag> & vector_tags)
3393 {
3394  for (const auto & vector_tag : vector_tags)
3395  if (_sys.hasVector(vector_tag._id))
3396  addResidualScalar(vector_tag);
3397 }
3398 
3399 void
3400 Assembly::cacheResidual(GlobalDataKey, const std::vector<VectorTag> & tags)
3401 {
3402  const std::vector<MooseVariableFEBase *> & vars = _sys.getVariables(_tid);
3403  for (const auto & var : vars)
3404  for (const auto & vector_tag : tags)
3405  if (_sys.hasVector(vector_tag._id))
3406  cacheResidualBlock(_cached_residual_values[vector_tag._type_id],
3407  _cached_residual_rows[vector_tag._type_id],
3408  _sub_Re[vector_tag._type_id][var->number()],
3409  var->dofIndices(),
3410  var->arrayScalingFactor(),
3411  var->isNodal());
3412 }
3413 
3414 // private method, so no key required
3415 void
3417 {
3418  const VectorTag & tag = _subproblem.getVectorTag(tag_id);
3419 
3420  _cached_residual_values[tag._type_id].push_back(value);
3421  _cached_residual_rows[tag._type_id].push_back(dof);
3422 }
3423 
3424 // private method, so no key required
3425 void
3426 Assembly::cacheResidual(dof_id_type dof, Real value, const std::set<TagID> & tags)
3427 {
3428  for (auto & tag : tags)
3429  cacheResidual(dof, value, tag);
3430 }
3431 
3432 void
3434  const std::vector<dof_id_type> & dof_index,
3435  LocalDataKey,
3436  TagID tag)
3437 {
3438  // Add the residual value and dof_index to cached_residual_values and cached_residual_rows
3439  // respectively.
3440  // This is used by NodalConstraint.C to cache the residual calculated for primary and secondary
3441  // node.
3442  const VectorTag & vector_tag = _subproblem.getVectorTag(tag);
3443  for (MooseIndex(dof_index) i = 0; i < dof_index.size(); ++i)
3444  {
3445  _cached_residual_values[vector_tag._type_id].push_back(res(i));
3446  _cached_residual_rows[vector_tag._type_id].push_back(dof_index[i]);
3447  }
3448 }
3449 
3450 void
3451 Assembly::cacheResidualNeighbor(GlobalDataKey, const std::vector<VectorTag> & tags)
3452 {
3453  const std::vector<MooseVariableFEBase *> & vars = _sys.getVariables(_tid);
3454  for (const auto & var : vars)
3455  for (const auto & vector_tag : tags)
3456  if (_sys.hasVector(vector_tag._id))
3457  cacheResidualBlock(_cached_residual_values[vector_tag._type_id],
3458  _cached_residual_rows[vector_tag._type_id],
3459  _sub_Rn[vector_tag._type_id][var->number()],
3460  var->dofIndicesNeighbor(),
3461  var->arrayScalingFactor(),
3462  var->isNodal());
3463 }
3464 
3465 void
3466 Assembly::cacheResidualLower(GlobalDataKey, const std::vector<VectorTag> & tags)
3467 {
3468  const std::vector<MooseVariableFEBase *> & vars = _sys.getVariables(_tid);
3469  for (const auto & var : vars)
3470  for (const auto & vector_tag : tags)
3471  if (_sys.hasVector(vector_tag._id))
3472  cacheResidualBlock(_cached_residual_values[vector_tag._type_id],
3473  _cached_residual_rows[vector_tag._type_id],
3474  _sub_Rl[vector_tag._type_id][var->number()],
3475  var->dofIndicesLower(),
3476  var->arrayScalingFactor(),
3477  var->isNodal());
3478 }
3479 
3480 void
3481 Assembly::addCachedResiduals(GlobalDataKey, const std::vector<VectorTag> & tags)
3482 {
3483  for (const auto & vector_tag : tags)
3484  {
3485  if (!_sys.hasVector(vector_tag._id))
3486  {
3487  _cached_residual_values[vector_tag._type_id].clear();
3488  _cached_residual_rows[vector_tag._type_id].clear();
3489  continue;
3490  }
3491  addCachedResidualDirectly(_sys.getVector(vector_tag._id), GlobalDataKey{}, vector_tag);
3492  }
3493 }
3494 
3495 void
3497 {
3498  for (const auto & vector_tag : _residual_vector_tags)
3499  clearCachedResiduals(vector_tag);
3500 }
3501 
3502 // private method, so no key required
3503 void
3505 {
3506  auto & values = _cached_residual_values[vector_tag._type_id];
3507  auto & rows = _cached_residual_rows[vector_tag._type_id];
3508 
3509  mooseAssert(values.size() == rows.size(),
3510  "Number of cached residuals and number of rows must match!");
3511 
3512  // Keep track of the largest size so we can use it to reserve and avoid
3513  // as much dynamic allocation as possible
3514  if (_max_cached_residuals < values.size())
3515  _max_cached_residuals = values.size();
3516 
3517  // Clear both vectors (keeps the capacity the same)
3518  values.clear();
3519  rows.clear();
3520  // And then reserve: use 2 as a fudge factor to *really* avoid dynamic allocation!
3521  values.reserve(_max_cached_residuals * 2);
3522  rows.reserve(_max_cached_residuals * 2);
3523 }
3524 
3525 void
3527  GlobalDataKey,
3528  const VectorTag & vector_tag)
3529 {
3530  const auto & values = _cached_residual_values[vector_tag._type_id];
3531  const auto & rows = _cached_residual_rows[vector_tag._type_id];
3532 
3533  mooseAssert(values.size() == rows.size(),
3534  "Number of cached residuals and number of rows must match!");
3535 
3536  if (!values.empty())
3537  {
3538  residual.add_vector(values, rows);
3539  clearCachedResiduals(vector_tag);
3540  }
3541 }
3542 
3543 void
3545 {
3546  auto & tag_Re = _sub_Re[vector_tag._type_id];
3547  const std::vector<MooseVariableFEBase *> & vars = _sys.getVariables(_tid);
3548  for (const auto & var : vars)
3549  setResidualBlock(residual,
3550  tag_Re[var->number()],
3551  var->dofIndices(),
3552  var->arrayScalingFactor(),
3553  var->isNodal());
3554 }
3555 
3556 void
3558  GlobalDataKey,
3559  const VectorTag & vector_tag)
3560 {
3561  auto & tag_Rn = _sub_Rn[vector_tag._type_id];
3562  const std::vector<MooseVariableFEBase *> & vars = _sys.getVariables(_tid);
3563  for (const auto & var : vars)
3564  setResidualBlock(residual,
3565  tag_Rn[var->number()],
3566  var->dofIndicesNeighbor(),
3567  var->arrayScalingFactor(),
3568  var->isNodal());
3569 }
3570 
3571 // private method, so no key required
3572 void
3574  DenseMatrix<Number> & jac_block,
3575  const MooseVariableBase & ivar,
3576  const MooseVariableBase & jvar,
3577  const std::vector<dof_id_type> & idof_indices,
3578  const std::vector<dof_id_type> & jdof_indices)
3579 {
3580  if (idof_indices.size() == 0 || jdof_indices.size() == 0)
3581  return;
3582  if (jac_block.n() == 0 || jac_block.m() == 0)
3583  return;
3584 
3585  auto & scaling_factor = ivar.arrayScalingFactor();
3586 
3587  for (unsigned int i = 0; i < ivar.count(); ++i)
3588  {
3589  unsigned int iv = ivar.number();
3590  for (const auto & jt : ConstCouplingRow(iv + i, *_cm))
3591  {
3592  unsigned int jv = jvar.number();
3593  if (jt < jv || jt >= jv + jvar.count())
3594  continue;
3595  unsigned int j = jt - jv;
3596 
3597  auto di = ivar.componentDofIndices(idof_indices, i);
3598  auto dj = jvar.componentDofIndices(jdof_indices, j);
3599  auto indof = di.size();
3600  auto jndof = dj.size();
3601 
3602  unsigned int jj = j;
3603  if (iv == jv && _component_block_diagonal[iv])
3604  // here i must be equal to j
3605  jj = 0;
3606 
3607  auto sub = jac_block.sub_matrix(i * indof, indof, jj * jndof, jndof);
3608  if (scaling_factor[i] != 1.0)
3609  sub *= scaling_factor[i];
3610 
3611  // If we're computing the jacobian for automatically scaling variables we do not want
3612  // to constrain the element matrix because it introduces 1s on the diagonal for the
3613  // constrained dofs
3615  _dof_map.constrain_element_matrix(sub, di, dj, false);
3616 
3617  jacobian.add_matrix(sub, di, dj);
3618  }
3619  }
3620 }
3621 
3622 // private method, so no key required
3623 void
3625  const MooseVariableBase & ivar,
3626  const MooseVariableBase & jvar,
3627  const std::vector<dof_id_type> & idof_indices,
3628  const std::vector<dof_id_type> & jdof_indices,
3629  TagID tag)
3630 {
3631  if (idof_indices.size() == 0 || jdof_indices.size() == 0)
3632  return;
3633  if (jac_block.n() == 0 || jac_block.m() == 0)
3634  return;
3635  if (!_sys.hasMatrix(tag))
3636  return;
3637 
3638  auto & scaling_factor = ivar.arrayScalingFactor();
3639 
3640  for (unsigned int i = 0; i < ivar.count(); ++i)
3641  {
3642  unsigned int iv = ivar.number();
3643  for (const auto & jt : ConstCouplingRow(iv + i, *_cm))
3644  {
3645  unsigned int jv = jvar.number();
3646  if (jt < jv || jt >= jv + jvar.count())
3647  continue;
3648  unsigned int j = jt - jv;
3649 
3650  auto di = ivar.componentDofIndices(idof_indices, i);
3651  auto dj = jvar.componentDofIndices(jdof_indices, j);
3652  auto indof = di.size();
3653  auto jndof = dj.size();
3654 
3655  unsigned int jj = j;
3656  if (iv == jv && _component_block_diagonal[iv])
3657  // here i must be equal to j
3658  jj = 0;
3659 
3660  auto sub = jac_block.sub_matrix(i * indof, indof, jj * jndof, jndof);
3661  if (scaling_factor[i] != 1.0)
3662  sub *= scaling_factor[i];
3663 
3664  // If we're computing the jacobian for automatically scaling variables we do not want
3665  // to constrain the element matrix because it introduces 1s on the diagonal for the
3666  // constrained dofs
3668  _dof_map.constrain_element_matrix(sub, di, dj, false);
3669 
3670  for (MooseIndex(di) i = 0; i < di.size(); i++)
3671  for (MooseIndex(dj) j = 0; j < dj.size(); j++)
3672  {
3673  _cached_jacobian_values[tag].push_back(sub(i, j));
3674  _cached_jacobian_rows[tag].push_back(di[i]);
3675  _cached_jacobian_cols[tag].push_back(dj[j]);
3676  }
3677  }
3678  }
3679 
3680  jac_block.zero();
3681 }
3682 
3683 // private method, so no key required
3684 void
3686  const MooseVariableBase & ivar,
3687  const MooseVariableBase & jvar,
3688  const std::vector<dof_id_type> & idof_indices,
3689  const std::vector<dof_id_type> & jdof_indices,
3690  TagID tag)
3691 {
3692  if (idof_indices.size() == 0 || jdof_indices.size() == 0)
3693  return;
3694  if (jac_block.n() == 0 || jac_block.m() == 0)
3695  return;
3696  if (!_sys.hasMatrix(tag))
3697  return;
3698 
3699  auto & scaling_factor = ivar.arrayScalingFactor();
3700 
3701  for (unsigned int i = 0; i < ivar.count(); ++i)
3702  {
3703  unsigned int iv = ivar.number();
3704  for (const auto & jt : ConstCouplingRow(iv + i, *_cm))
3705  {
3706  unsigned int jv = jvar.number();
3707  if (jt < jv || jt >= jv + jvar.count())
3708  continue;
3709  unsigned int j = jt - jv;
3710 
3711  auto di = ivar.componentDofIndices(idof_indices, i);
3712  auto dj = jvar.componentDofIndices(jdof_indices, j);
3713  auto indof = di.size();
3714  auto jndof = dj.size();
3715 
3716  unsigned int jj = j;
3717  if (iv == jv && _component_block_diagonal[iv])
3718  // here i must be equal to j
3719  jj = 0;
3720 
3721  auto sub = jac_block.sub_matrix(i * indof, indof, jj * jndof, jndof);
3722  if (scaling_factor[i] != 1.0)
3723  sub *= scaling_factor[i];
3724 
3725  _dof_map.constrain_element_matrix(sub, di, dj, false);
3726 
3727  for (MooseIndex(di) i = 0; i < di.size(); i++)
3728  for (MooseIndex(dj) j = 0; j < dj.size(); j++)
3729  if (sub(i, j) != 0.0) // no storage allocated for unimplemented jacobian terms,
3730  // maintaining maximum sparsity possible
3731  {
3732  _cached_jacobian_values[tag].push_back(sub(i, j));
3733  _cached_jacobian_rows[tag].push_back(di[i]);
3734  _cached_jacobian_cols[tag].push_back(dj[j]);
3735  }
3736  }
3737  }
3738 
3739  jac_block.zero();
3740 }
3741 
3742 void
3744  const std::vector<dof_id_type> & idof_indices,
3745  const std::vector<dof_id_type> & jdof_indices,
3746  Real scaling_factor,
3747  LocalDataKey,
3748  TagID tag)
3749 {
3750  // Only cache data when the matrix exists
3751  if ((idof_indices.size() > 0) && (jdof_indices.size() > 0) && jac_block.n() && jac_block.m() &&
3752  _sys.hasMatrix(tag))
3753  {
3754  std::vector<dof_id_type> di(idof_indices);
3755  std::vector<dof_id_type> dj(jdof_indices);
3756 
3757  // If we're computing the jacobian for automatically scaling variables we do not want to
3758  // constrain the element matrix because it introduces 1s on the diagonal for the constrained
3759  // dofs
3761  _dof_map.constrain_element_matrix(jac_block, di, dj, false);
3762 
3763  if (scaling_factor != 1.0)
3764  jac_block *= scaling_factor;
3765 
3766  for (MooseIndex(di) i = 0; i < di.size(); i++)
3767  for (MooseIndex(dj) j = 0; j < dj.size(); j++)
3768  {
3769  _cached_jacobian_values[tag].push_back(jac_block(i, j));
3770  _cached_jacobian_rows[tag].push_back(di[i]);
3771  _cached_jacobian_cols[tag].push_back(dj[j]);
3772  }
3773  }
3774  jac_block.zero();
3775 }
3776 
3777 Real
3778 Assembly::elementVolume(const Elem * elem) const
3779 {
3780  FEType fe_type(elem->default_order(), LAGRANGE);
3781  std::unique_ptr<FEBase> fe(FEBase::build(elem->dim(), fe_type));
3782 
3783  // references to the quadrature points and weights
3784  const std::vector<Real> & JxW = fe->get_JxW();
3785  const std::vector<Point> & q_points = fe->get_xyz();
3786 
3787  // The default quadrature rule should integrate the mass matrix,
3788  // thus it should be plenty to compute the volume
3789  QGauss qrule(elem->dim(), fe_type.default_quadrature_order());
3790  fe->attach_quadrature_rule(&qrule);
3791  fe->reinit(elem);
3792 
3793  // perform a sanity check to ensure that size of quad rule and size of q_points is
3794  // identical
3795  mooseAssert(qrule.n_points() == q_points.size(),
3796  "The number of points in the quadrature rule doesn't match the number of passed-in "
3797  "points in Assembly::setCoordinateTransformation");
3798 
3799  // compute the coordinate transformation
3800  Real vol = 0;
3801  for (unsigned int qp = 0; qp < qrule.n_points(); ++qp)
3802  {
3803  Real coord;
3804  coordTransformFactor(_subproblem, elem->subdomain_id(), q_points[qp], coord);
3805  vol += JxW[qp] * coord;
3806  }
3807  return vol;
3808 }
3809 
3810 void
3812 {
3814  {
3815  mooseAssert(_cached_jacobian_rows.size() == _cached_jacobian_cols.size(),
3816  "Error: Cached data sizes MUST be the same!");
3817  for (MooseIndex(_cached_jacobian_rows) i = 0; i < _cached_jacobian_rows.size(); i++)
3818  mooseAssert(_cached_jacobian_rows[i].size() == _cached_jacobian_cols[i].size(),
3819  "Error: Cached data sizes MUST be the same for a given tag!");
3820  }
3821 
3822  for (MooseIndex(_cached_jacobian_rows) i = 0; i < _cached_jacobian_rows.size(); i++)
3823  if (_sys.hasMatrix(i))
3824  for (MooseIndex(_cached_jacobian_rows[i]) j = 0; j < _cached_jacobian_rows[i].size(); j++)
3826  _cached_jacobian_cols[i][j],
3827  _cached_jacobian_values[i][j]);
3828 
3829  for (MooseIndex(_cached_jacobian_rows) i = 0; i < _cached_jacobian_rows.size(); i++)
3830  {
3831  if (!_sys.hasMatrix(i))
3832  continue;
3833 
3836 
3837  // Try to be more efficient from now on
3838  // The 2 is just a fudge factor to keep us from having to grow the vector during assembly
3839  _cached_jacobian_values[i].clear();
3841 
3842  _cached_jacobian_rows[i].clear();
3844 
3845  _cached_jacobian_cols[i].clear();
3847  }
3848 }
3849 
3850 inline void
3852 {
3853  auto i = ivar.number();
3854  auto j = jvar.number();
3855  for (MooseIndex(_jacobian_block_used) tag = 0; tag < _jacobian_block_used.size(); tag++)
3856  if (jacobianBlockUsed(tag, i, j) && _sys.hasMatrix(tag))
3858  jacobianBlock(i, j, LocalDataKey{}, tag),
3859  ivar,
3860  jvar,
3861  ivar.dofIndices(),
3862  jvar.dofIndices());
3863 }
3864 
3865 void
3867 {
3868  for (const auto & it : _cm_ff_entry)
3869  addJacobianCoupledVarPair(*it.first, *it.second);
3870 
3871  for (const auto & it : _cm_sf_entry)
3872  addJacobianCoupledVarPair(*it.first, *it.second);
3873 
3874  for (const auto & it : _cm_fs_entry)
3875  addJacobianCoupledVarPair(*it.first, *it.second);
3876 }
3877 
3878 void
3880 {
3881  for (const auto & it : _cm_nonlocal_entry)
3882  {
3883  auto ivar = it.first;
3884  auto jvar = it.second;
3885  auto i = ivar->number();
3886  auto j = jvar->number();
3887  for (MooseIndex(_jacobian_block_nonlocal_used) tag = 0;
3888  tag < _jacobian_block_nonlocal_used.size();
3889  tag++)
3890  if (jacobianBlockNonlocalUsed(tag, i, j) && _sys.hasMatrix(tag))
3892  jacobianBlockNonlocal(i, j, LocalDataKey{}, tag),
3893  *ivar,
3894  *jvar,
3895  ivar->dofIndices(),
3896  jvar->allDofIndices());
3897  }
3898 }
3899 
3900 void
3902 {
3903  for (const auto & it : _cm_ff_entry)
3904  {
3905  auto ivar = it.first;
3906  auto jvar = it.second;
3907  auto i = ivar->number();
3908  auto j = jvar->number();
3909  for (MooseIndex(_jacobian_block_neighbor_used) tag = 0;
3910  tag < _jacobian_block_neighbor_used.size();
3911  tag++)
3912  if (jacobianBlockNeighborUsed(tag, i, j) && _sys.hasMatrix(tag))
3913  {
3916  *ivar,
3917  *jvar,
3918  ivar->dofIndices(),
3919  jvar->dofIndicesNeighbor());
3920 
3923  *ivar,
3924  *jvar,
3925  ivar->dofIndicesNeighbor(),
3926  jvar->dofIndices());
3927 
3930  *ivar,
3931  *jvar,
3932  ivar->dofIndicesNeighbor(),
3933  jvar->dofIndicesNeighbor());
3934  }
3935  }
3936 }
3937 
3938 void
3940 {
3941  for (const auto & it : _cm_ff_entry)
3942  {
3943  auto ivar = it.first;
3944  auto jvar = it.second;
3945  auto i = ivar->number();
3946  auto j = jvar->number();
3947  for (MooseIndex(_jacobian_block_lower_used) tag = 0; tag < _jacobian_block_lower_used.size();
3948  tag++)
3949  if (jacobianBlockLowerUsed(tag, i, j) && _sys.hasMatrix(tag))
3950  {
3953  *ivar,
3954  *jvar,
3955  ivar->dofIndicesLower(),
3956  jvar->dofIndicesLower());
3957 
3960  *ivar,
3961  *jvar,
3962  ivar->dofIndicesLower(),
3963  jvar->dofIndicesNeighbor());
3964 
3967  *ivar,
3968  *jvar,
3969  ivar->dofIndicesLower(),
3970  jvar->dofIndices());
3971 
3974  *ivar,
3975  *jvar,
3976  ivar->dofIndicesNeighbor(),
3977  jvar->dofIndicesLower());
3978 
3981  *ivar,
3982  *jvar,
3983  ivar->dofIndices(),
3984  jvar->dofIndicesLower());
3985  }
3986 
3987  for (MooseIndex(_jacobian_block_neighbor_used) tag = 0;
3988  tag < _jacobian_block_neighbor_used.size();
3989  tag++)
3990  if (jacobianBlockNeighborUsed(tag, i, j) && _sys.hasMatrix(tag))
3991  {
3994  *ivar,
3995  *jvar,
3996  ivar->dofIndices(),
3997  jvar->dofIndicesNeighbor());
3998 
4001  *ivar,
4002  *jvar,
4003  ivar->dofIndicesNeighbor(),
4004  jvar->dofIndices());
4005 
4008  *ivar,
4009  *jvar,
4010  ivar->dofIndicesNeighbor(),
4011  jvar->dofIndicesNeighbor());
4012  }
4013  }
4014 }
4015 
4016 void
4018 {
4019  for (const auto & it : _cm_ff_entry)
4020  {
4021  auto ivar = it.first;
4022  auto jvar = it.second;
4023  auto i = ivar->number();
4024  auto j = jvar->number();
4025  for (MooseIndex(_jacobian_block_lower_used) tag = 0; tag < _jacobian_block_lower_used.size();
4026  tag++)
4027  if (jacobianBlockLowerUsed(tag, i, j) && _sys.hasMatrix(tag))
4028  {
4031  *ivar,
4032  *jvar,
4033  ivar->dofIndicesLower(),
4034  jvar->dofIndicesLower());
4035 
4038  *ivar,
4039  *jvar,
4040  ivar->dofIndicesLower(),
4041  jvar->dofIndices());
4042 
4045  *ivar,
4046  *jvar,
4047  ivar->dofIndices(),
4048  jvar->dofIndicesLower());
4049  }
4050  }
4051 }
4052 
4053 void
4055 {
4056  for (const auto & it : _cm_ff_entry)
4057  cacheJacobianCoupledVarPair(*it.first, *it.second);
4058 
4059  for (const auto & it : _cm_fs_entry)
4060  cacheJacobianCoupledVarPair(*it.first, *it.second);
4061 
4062  for (const auto & it : _cm_sf_entry)
4063  cacheJacobianCoupledVarPair(*it.first, *it.second);
4064 }
4065 
4066 // private method, so no key required
4067 void
4069  const MooseVariableBase & jvar)
4070 {
4071  auto i = ivar.number();
4072  auto j = jvar.number();
4073  for (MooseIndex(_jacobian_block_used) tag = 0; tag < _jacobian_block_used.size(); tag++)
4074  if (jacobianBlockUsed(tag, i, j) && _sys.hasMatrix(tag))
4076  ivar,
4077  jvar,
4078  ivar.dofIndices(),
4079  jvar.dofIndices(),
4080  tag);
4081 }
4082 
4083 void
4085 {
4086  for (const auto & it : _cm_nonlocal_entry)
4087  {
4088  auto ivar = it.first;
4089  auto jvar = it.second;
4090  auto i = ivar->number();
4091  auto j = jvar->number();
4092  for (MooseIndex(_jacobian_block_nonlocal_used) tag = 0;
4093  tag < _jacobian_block_nonlocal_used.size();
4094  tag++)
4095  if (jacobianBlockNonlocalUsed(tag, i, j) && _sys.hasMatrix(tag))
4097  *ivar,
4098  *jvar,
4099  ivar->dofIndices(),
4100  jvar->allDofIndices(),
4101  tag);
4102  }
4103 }
4104 
4105 void
4107 {
4108  for (const auto & it : _cm_ff_entry)
4109  {
4110  auto ivar = it.first;
4111  auto jvar = it.second;
4112  auto i = ivar->number();
4113  auto j = jvar->number();
4114 
4115  for (MooseIndex(_jacobian_block_neighbor_used) tag = 0;
4116  tag < _jacobian_block_neighbor_used.size();
4117  tag++)
4118  if (jacobianBlockNeighborUsed(tag, i, j) && _sys.hasMatrix(tag))
4119  {
4121  *ivar,
4122  *jvar,
4123  ivar->dofIndices(),
4124  jvar->dofIndicesNeighbor(),
4125  tag);
4127  *ivar,
4128  *jvar,
4129  ivar->dofIndicesNeighbor(),
4130  jvar->dofIndices(),
4131  tag);
4134  *ivar,
4135  *jvar,
4136  ivar->dofIndicesNeighbor(),
4137  jvar->dofIndicesNeighbor(),
4138  tag);
4139  }
4140  }
4141 }
4142 
4143 void
4145 {
4146  for (const auto & it : _cm_ff_entry)
4147  {
4148  auto ivar = it.first;
4149  auto jvar = it.second;
4150  auto i = ivar->number();
4151  auto j = jvar->number();
4152  for (MooseIndex(_jacobian_block_lower_used) tag = 0; tag < _jacobian_block_lower_used.size();
4153  tag++)
4154  if (jacobianBlockLowerUsed(tag, i, j) && _sys.hasMatrix(tag))
4155  {
4157  *ivar,
4158  *jvar,
4159  ivar->dofIndicesLower(),
4160  jvar->dofIndicesLower(),
4161  tag);
4162 
4164  *ivar,
4165  *jvar,
4166  ivar->dofIndicesLower(),
4167  jvar->dofIndices(),
4168  tag);
4169 
4171  *ivar,
4172  *jvar,
4173  ivar->dofIndicesLower(),
4174  jvar->dofIndicesNeighbor(),
4175  tag);
4176 
4178  *ivar,
4179  *jvar,
4180  ivar->dofIndices(),
4181  jvar->dofIndicesLower(),
4182  tag);
4183 
4186  *ivar,
4187  *jvar,
4188  ivar->dofIndices(),
4189  jvar->dofIndices(),
4190  tag);
4191 
4193  *ivar,
4194  *jvar,
4195  ivar->dofIndices(),
4196  jvar->dofIndicesNeighbor(),
4197  tag);
4198 
4200  *ivar,
4201  *jvar,
4202  ivar->dofIndicesNeighbor(),
4203  jvar->dofIndicesLower(),
4204  tag);
4205 
4207  *ivar,
4208  *jvar,
4209  ivar->dofIndicesNeighbor(),
4210  jvar->dofIndices(),
4211  tag);
4212 
4214  *ivar,
4215  *jvar,
4216  ivar->dofIndicesNeighbor(),
4217  jvar->dofIndicesNeighbor(),
4218  tag);
4219  }
4220  }
4221 }
4222 
4223 void
4225  unsigned int ivar,
4226  unsigned int jvar,
4227  const DofMap & dof_map,
4228  std::vector<dof_id_type> & dof_indices,
4229  GlobalDataKey,
4230  const std::set<TagID> & tags)
4231 {
4232  for (auto tag : tags)
4233  addJacobianBlock(jacobian, ivar, jvar, dof_map, dof_indices, GlobalDataKey{}, tag);
4234 }
4235 
4236 void
4238  unsigned int ivar,
4239  unsigned int jvar,
4240  const DofMap & dof_map,
4241  std::vector<dof_id_type> & dof_indices,
4242  GlobalDataKey,
4243  TagID tag)
4244 {
4245  if (dof_indices.size() == 0)
4246  return;
4247  if (!(*_cm)(ivar, jvar))
4248  return;
4249 
4250  auto & iv = _sys.getVariable(_tid, ivar);
4251  auto & jv = _sys.getVariable(_tid, jvar);
4252  auto & scaling_factor = iv.arrayScalingFactor();
4253 
4254  const unsigned int ivn = iv.number();
4255  const unsigned int jvn = jv.number();
4256  auto & ke = jacobianBlock(ivn, jvn, LocalDataKey{}, tag);
4257 
4258  // It is guaranteed by design iv.number <= ivar since iv is obtained
4259  // through SystemBase::getVariable with ivar.
4260  // Most of times ivar will just be equal to iv.number except for array variables,
4261  // where ivar could be a number for a component of an array variable but calling
4262  // getVariable will return the array variable that has the number of the 0th component.
4263  // It is the same for jvar.
4264  const unsigned int i = ivar - ivn;
4265  const unsigned int j = jvar - jvn;
4266 
4267  // DoF indices are independently given
4268  auto di = dof_indices;
4269  auto dj = dof_indices;
4270 
4271  auto indof = di.size();
4272  auto jndof = dj.size();
4273 
4274  unsigned int jj = j;
4275  if (ivar == jvar && _component_block_diagonal[ivn])
4276  jj = 0;
4277 
4278  auto sub = ke.sub_matrix(i * indof, indof, jj * jndof, jndof);
4279  // If we're computing the jacobian for automatically scaling variables we do not want to
4280  // constrain the element matrix because it introduces 1s on the diagonal for the constrained
4281  // dofs
4283  dof_map.constrain_element_matrix(sub, di, dj, false);
4284 
4285  if (scaling_factor[i] != 1.0)
4286  sub *= scaling_factor[i];
4287 
4288  jacobian.add_matrix(sub, di, dj);
4289 }
4290 
4291 void
4293  const unsigned int ivar,
4294  const unsigned int jvar,
4295  const DofMap & dof_map,
4296  const std::vector<dof_id_type> & idof_indices,
4297  const std::vector<dof_id_type> & jdof_indices,
4298  GlobalDataKey,
4299  const TagID tag)
4300 {
4301  if (idof_indices.size() == 0 || jdof_indices.size() == 0)
4302  return;
4303  if (jacobian.n() == 0 || jacobian.m() == 0)
4304  return;
4305  if (!(*_cm)(ivar, jvar))
4306  return;
4307 
4308  auto & iv = _sys.getVariable(_tid, ivar);
4309  auto & jv = _sys.getVariable(_tid, jvar);
4310  auto & scaling_factor = iv.arrayScalingFactor();
4311 
4312  const unsigned int ivn = iv.number();
4313  const unsigned int jvn = jv.number();
4314  auto & keg = jacobianBlockNonlocal(ivn, jvn, LocalDataKey{}, tag);
4315 
4316  // It is guaranteed by design iv.number <= ivar since iv is obtained
4317  // through SystemBase::getVariable with ivar.
4318  // Most of times ivar will just be equal to iv.number except for array variables,
4319  // where ivar could be a number for a component of an array variable but calling
4320  // getVariable will return the array variable that has the number of the 0th component.
4321  // It is the same for jvar.
4322  const unsigned int i = ivar - ivn;
4323  const unsigned int j = jvar - jvn;
4324 
4325  // DoF indices are independently given
4326  auto di = idof_indices;
4327  auto dj = jdof_indices;
4328 
4329  auto indof = di.size();
4330  auto jndof = dj.size();
4331 
4332  unsigned int jj = j;
4333  if (ivar == jvar && _component_block_diagonal[ivn])
4334  jj = 0;
4335 
4336  auto sub = keg.sub_matrix(i * indof, indof, jj * jndof, jndof);
4337  // If we're computing the jacobian for automatically scaling variables we do not want to
4338  // constrain the element matrix because it introduces 1s on the diagonal for the constrained
4339  // dofs
4341  dof_map.constrain_element_matrix(sub, di, dj, false);
4342 
4343  if (scaling_factor[i] != 1.0)
4344  sub *= scaling_factor[i];
4345 
4346  jacobian.add_matrix(sub, di, dj);
4347 }
4348 
4349 void
4351  const unsigned int ivar,
4352  const unsigned int jvar,
4353  const DofMap & dof_map,
4354  const std::vector<dof_id_type> & idof_indices,
4355  const std::vector<dof_id_type> & jdof_indices,
4356  GlobalDataKey,
4357  const std::set<TagID> & tags)
4358 {
4359  for (auto tag : tags)
4361  jacobian, ivar, jvar, dof_map, idof_indices, jdof_indices, GlobalDataKey{}, tag);
4362 }
4363 
4364 void
4366  const unsigned int ivar,
4367  const unsigned int jvar,
4368  const DofMap & dof_map,
4369  std::vector<dof_id_type> & dof_indices,
4370  std::vector<dof_id_type> & neighbor_dof_indices,
4371  GlobalDataKey,
4372  const TagID tag)
4373 {
4374  if (dof_indices.size() == 0 && neighbor_dof_indices.size() == 0)
4375  return;
4376  if (!(*_cm)(ivar, jvar))
4377  return;
4378 
4379  auto & iv = _sys.getVariable(_tid, ivar);
4380  auto & jv = _sys.getVariable(_tid, jvar);
4381  auto & scaling_factor = iv.arrayScalingFactor();
4382 
4383  const unsigned int ivn = iv.number();
4384  const unsigned int jvn = jv.number();
4385  auto & ken = jacobianBlockNeighbor(Moose::ElementNeighbor, ivn, jvn, LocalDataKey{}, tag);
4386  auto & kne = jacobianBlockNeighbor(Moose::NeighborElement, ivn, jvn, LocalDataKey{}, tag);
4387  auto & knn = jacobianBlockNeighbor(Moose::NeighborNeighbor, ivn, jvn, LocalDataKey{}, tag);
4388 
4389  // It is guaranteed by design iv.number <= ivar since iv is obtained
4390  // through SystemBase::getVariable with ivar.
4391  // Most of times ivar will just be equal to iv.number except for array variables,
4392  // where ivar could be a number for a component of an array variable but calling
4393  // getVariable will return the array variable that has the number of the 0th component.
4394  // It is the same for jvar.
4395  const unsigned int i = ivar - ivn;
4396  const unsigned int j = jvar - jvn;
4397  // DoF indices are independently given
4398  auto dc = dof_indices;
4399  auto dn = neighbor_dof_indices;
4400  auto cndof = dc.size();
4401  auto nndof = dn.size();
4402 
4403  unsigned int jj = j;
4404  if (ivar == jvar && _component_block_diagonal[ivn])
4405  jj = 0;
4406 
4407  auto suben = ken.sub_matrix(i * cndof, cndof, jj * nndof, nndof);
4408  auto subne = kne.sub_matrix(i * nndof, nndof, jj * cndof, cndof);
4409  auto subnn = knn.sub_matrix(i * nndof, nndof, jj * nndof, nndof);
4410 
4411  // If we're computing the jacobian for automatically scaling variables we do not want to
4412  // constrain the element matrix because it introduces 1s on the diagonal for the constrained
4413  // dofs
4415  {
4416  dof_map.constrain_element_matrix(suben, dc, dn, false);
4417  dof_map.constrain_element_matrix(subne, dn, dc, false);
4418  dof_map.constrain_element_matrix(subnn, dn, dn, false);
4419  }
4420 
4421  if (scaling_factor[i] != 1.0)
4422  {
4423  suben *= scaling_factor[i];
4424  subne *= scaling_factor[i];
4425  subnn *= scaling_factor[i];
4426  }
4427 
4428  jacobian.add_matrix(suben, dc, dn);
4429  jacobian.add_matrix(subne, dn, dc);
4430  jacobian.add_matrix(subnn, dn, dn);
4431 }
4432 
4433 void
4435  const unsigned int ivar,
4436  const unsigned int jvar,
4437  const DofMap & dof_map,
4438  std::vector<dof_id_type> & dof_indices,
4439  std::vector<dof_id_type> & neighbor_dof_indices,
4440  GlobalDataKey,
4441  const std::set<TagID> & tags)
4442 {
4443  for (const auto tag : tags)
4445  jacobian, ivar, jvar, dof_map, dof_indices, neighbor_dof_indices, GlobalDataKey{}, tag);
4446 }
4447 
4448 void
4450 {
4451  for (const auto & it : _cm_ss_entry)
4452  addJacobianCoupledVarPair(*it.first, *it.second);
4453 }
4454 
4455 void
4457 {
4458  const std::vector<MooseVariableFEBase *> & vars = _sys.getVariables(_tid);
4460  for (const auto & var_j : vars)
4461  addJacobianCoupledVarPair(var_i, *var_j);
4462 }
4463 
4464 void
4467 {
4468  _cached_jacobian_rows[tag].push_back(i);
4469  _cached_jacobian_cols[tag].push_back(j);
4470  _cached_jacobian_values[tag].push_back(value);
4471 }
4472 
4473 void
4476  Real value,
4477  LocalDataKey,
4478  const std::set<TagID> & tags)
4479 {
4480  for (auto tag : tags)
4481  if (_sys.hasMatrix(tag))
4482  cacheJacobian(i, j, value, LocalDataKey{}, tag);
4483 }
4484 
4485 void
4487 {
4488  for (MooseIndex(_cached_jacobian_rows) tag = 0; tag < _cached_jacobian_rows.size(); tag++)
4489  if (_sys.hasMatrix(tag))
4490  {
4491  // First zero the rows (including the diagonals) to prepare for
4492  // setting the cached values.
4494 
4495  // TODO: Use SparseMatrix::set_values() for efficiency
4496  for (MooseIndex(_cached_jacobian_values) i = 0; i < _cached_jacobian_values[tag].size(); ++i)
4497  _sys.getMatrix(tag).set(_cached_jacobian_rows[tag][i],
4498  _cached_jacobian_cols[tag][i],
4499  _cached_jacobian_values[tag][i]);
4500  }
4501 
4503 }
4504 
4505 void
4507 {
4508  for (MooseIndex(_cached_jacobian_rows) tag = 0; tag < _cached_jacobian_rows.size(); tag++)
4509  if (_sys.hasMatrix(tag))
4511 
4513 }
4514 
4515 void
4517 {
4518  for (MooseIndex(_cached_jacobian_rows) tag = 0; tag < _cached_jacobian_rows.size(); tag++)
4519  {
4520  _cached_jacobian_rows[tag].clear();
4521  _cached_jacobian_cols[tag].clear();
4522  _cached_jacobian_values[tag].clear();
4523  }
4524 }
4525 
4526 void
4528 {
4529  mooseAssert(_xfem != nullptr, "This function should not be called if xfem is inactive");
4530 
4532  return;
4533 
4534  MooseArray<Real> xfem_weight_multipliers;
4535  if (_xfem->getXFEMWeights(xfem_weight_multipliers, elem, _current_qrule, _current_q_points))
4536  {
4537  mooseAssert(xfem_weight_multipliers.size() == _current_JxW.size(),
4538  "Size of weight multipliers in xfem doesn't match number of quadrature points");
4539  for (unsigned i = 0; i < xfem_weight_multipliers.size(); i++)
4540  _current_JxW[i] = _current_JxW[i] * xfem_weight_multipliers[i];
4541 
4542  xfem_weight_multipliers.release();
4543  }
4544 }
4545 
4546 void
4547 Assembly::modifyFaceWeightsDueToXFEM(const Elem * elem, unsigned int side)
4548 {
4549  mooseAssert(_xfem != nullptr, "This function should not be called if xfem is inactive");
4550 
4552  return;
4553 
4554  MooseArray<Real> xfem_face_weight_multipliers;
4555  if (_xfem->getXFEMFaceWeights(
4556  xfem_face_weight_multipliers, elem, _current_qrule_face, _current_q_points_face, side))
4557  {
4558  mooseAssert(xfem_face_weight_multipliers.size() == _current_JxW_face.size(),
4559  "Size of weight multipliers in xfem doesn't match number of quadrature points");
4560  for (unsigned i = 0; i < xfem_face_weight_multipliers.size(); i++)
4561  _current_JxW_face[i] = _current_JxW_face[i] * xfem_face_weight_multipliers[i];
4562 
4563  xfem_face_weight_multipliers.release();
4564  }
4565 }
4566 
4567 void
4569 {
4570  _scaling_vector = &_sys.getVector("scaling_factors");
4571 }
4572 
4573 void
4574 Assembly::modifyArbitraryWeights(const std::vector<Real> & weights)
4575 {
4576  mooseAssert(_current_qrule == _current_qrule_arbitrary, "Rule should be arbitrary");
4577  mooseAssert(weights.size() == _current_physical_points.size(), "Size mismatch");
4578 
4579  for (MooseIndex(weights.size()) i = 0; i < weights.size(); ++i)
4580  _current_JxW[i] = weights[i];
4581 }
4582 
4583 template <>
4585 Assembly::fePhi<VectorValue<Real>>(FEType type) const
4586 {
4587  buildVectorFE(type);
4588  return _vector_fe_shape_data[type]->_phi;
4589 }
4590 
4591 template <>
4593 Assembly::feGradPhi<VectorValue<Real>>(FEType type) const
4594 {
4595  buildVectorFE(type);
4596  return _vector_fe_shape_data[type]->_grad_phi;
4597 }
4598 
4599 template <>
4601 Assembly::feSecondPhi<VectorValue<Real>>(FEType type) const
4602 {
4603  _need_second_derivative[type] = true;
4604  buildVectorFE(type);
4605  return _vector_fe_shape_data[type]->_second_phi;
4606 }
4607 
4608 template <>
4610 Assembly::fePhiLower<VectorValue<Real>>(FEType type) const
4611 {
4612  buildVectorLowerDFE(type);
4613  return _vector_fe_shape_data_lower[type]->_phi;
4614 }
4615 
4616 template <>
4618 Assembly::feDualPhiLower<VectorValue<Real>>(FEType type) const
4619 {
4620  buildVectorDualLowerDFE(type);
4621  return _vector_fe_shape_data_dual_lower[type]->_phi;
4622 }
4623 
4624 template <>
4626 Assembly::feGradPhiLower<VectorValue<Real>>(FEType type) const
4627 {
4628  buildVectorLowerDFE(type);
4629  return _vector_fe_shape_data_lower[type]->_grad_phi;
4630 }
4631 
4632 template <>
4634 Assembly::feGradDualPhiLower<VectorValue<Real>>(FEType type) const
4635 {
4636  buildVectorDualLowerDFE(type);
4637  return _vector_fe_shape_data_dual_lower[type]->_grad_phi;
4638 }
4639 
4640 template <>
4642 Assembly::fePhiFace<VectorValue<Real>>(FEType type) const
4643 {
4644  buildVectorFaceFE(type);
4645  return _vector_fe_shape_data_face[type]->_phi;
4646 }
4647 
4648 template <>
4650 Assembly::feGradPhiFace<VectorValue<Real>>(FEType type) const
4651 {
4652  buildVectorFaceFE(type);
4653  return _vector_fe_shape_data_face[type]->_grad_phi;
4654 }
4655 
4656 template <>
4658 Assembly::feSecondPhiFace<VectorValue<Real>>(FEType type) const
4659 {
4660  _need_second_derivative[type] = true;
4661  buildVectorFaceFE(type);
4662  return _vector_fe_shape_data_face[type]->_second_phi;
4663 }
4664 
4665 template <>
4667 Assembly::fePhiNeighbor<VectorValue<Real>>(FEType type) const
4668 {
4669  buildVectorNeighborFE(type);
4670  return _vector_fe_shape_data_neighbor[type]->_phi;
4671 }
4672 
4673 template <>
4675 Assembly::feGradPhiNeighbor<VectorValue<Real>>(FEType type) const
4676 {
4677  buildVectorNeighborFE(type);
4678  return _vector_fe_shape_data_neighbor[type]->_grad_phi;
4679 }
4680 
4681 template <>
4683 Assembly::feSecondPhiNeighbor<VectorValue<Real>>(FEType type) const
4684 {
4685  _need_second_derivative_neighbor[type] = true;
4686  buildVectorNeighborFE(type);
4687  return _vector_fe_shape_data_neighbor[type]->_second_phi;
4688 }
4689 
4690 template <>
4692 Assembly::fePhiFaceNeighbor<VectorValue<Real>>(FEType type) const
4693 {
4694  buildVectorFaceNeighborFE(type);
4695  return _vector_fe_shape_data_face_neighbor[type]->_phi;
4696 }
4697 
4698 template <>
4700 Assembly::feGradPhiFaceNeighbor<VectorValue<Real>>(FEType type) const
4701 {
4702  buildVectorFaceNeighborFE(type);
4703  return _vector_fe_shape_data_face_neighbor[type]->_grad_phi;
4704 }
4705 
4706 template <>
4708 Assembly::feSecondPhiFaceNeighbor<VectorValue<Real>>(FEType type) const
4709 {
4710  _need_second_derivative_neighbor[type] = true;
4711  buildVectorFaceNeighborFE(type);
4712  return _vector_fe_shape_data_face_neighbor[type]->_second_phi;
4713 }
4714 
4715 template <>
4717 Assembly::feCurlPhi<VectorValue<Real>>(FEType type) const
4718 {
4719  _need_curl[type] = true;
4720  buildVectorFE(type);
4721  return _vector_fe_shape_data[type]->_curl_phi;
4722 }
4723 
4724 template <>
4726 Assembly::feCurlPhiFace<VectorValue<Real>>(FEType type) const
4727 {
4728  _need_curl[type] = true;
4729  buildVectorFaceFE(type);
4730  return _vector_fe_shape_data_face[type]->_curl_phi;
4731 }
4732 
4733 template <>
4735 Assembly::feCurlPhiNeighbor<VectorValue<Real>>(FEType type) const
4736 {
4737  _need_curl[type] = true;
4738  buildVectorNeighborFE(type);
4739  return _vector_fe_shape_data_neighbor[type]->_curl_phi;
4740 }
4741 
4742 template <>
4744 Assembly::feCurlPhiFaceNeighbor<VectorValue<Real>>(FEType type) const
4745 {
4746  _need_curl[type] = true;
4747  buildVectorFaceNeighborFE(type);
4748  return _vector_fe_shape_data_face_neighbor[type]->_curl_phi;
4749 }
4750 
4751 template <>
4753 Assembly::feDivPhi<VectorValue<Real>>(FEType type) const
4754 {
4755  _need_div[type] = true;
4756  buildVectorFE(type);
4757  return _vector_fe_shape_data[type]->_div_phi;
4758 }
4759 
4760 template <>
4762 Assembly::feDivPhiFace<VectorValue<Real>>(FEType type) const
4763 {
4764  _need_div[type] = true;
4765  buildVectorFaceFE(type);
4766  return _vector_fe_shape_data_face[type]->_div_phi;
4767 }
4768 
4769 template <>
4771 Assembly::feDivPhiNeighbor<VectorValue<Real>>(FEType type) const
4772 {
4773  _need_div[type] = true;
4774  buildVectorNeighborFE(type);
4775  return _vector_fe_shape_data_neighbor[type]->_div_phi;
4776 }
4777 
4778 template <>
4780 Assembly::feDivPhiFaceNeighbor<VectorValue<Real>>(FEType type) const
4781 {
4782  _need_div[type] = true;
4783  buildVectorFaceNeighborFE(type);
4784  return _vector_fe_shape_data_face_neighbor[type]->_div_phi;
4785 }
4786 
4787 const MooseArray<ADReal> &
4789 {
4790  _calculate_curvatures = true;
4791  const Order helper_order = _mesh.hasSecondOrderElements() ? SECOND : FIRST;
4792  const FEType helper_type(helper_order, LAGRANGE);
4793  // Must prerequest the second derivatives. Sadly because there is only one
4794  // _need_second_derivative map for both volumetric and face FE objects we must request both here
4795  feSecondPhi<Real>(helper_type);
4796  feSecondPhiFace<Real>(helper_type);
4797  return _ad_curvatures;
4798 }
4799 
4800 void
4802 {
4803  for (unsigned int dim = 0; dim <= _mesh_dimension; dim++)
4804  {
4805  _holder_fe_helper[dim]->get_phi();
4806  _holder_fe_helper[dim]->get_dphi();
4807  _holder_fe_helper[dim]->get_xyz();
4808  _holder_fe_helper[dim]->get_JxW();
4809 
4810  _holder_fe_face_helper[dim]->get_phi();
4811  _holder_fe_face_helper[dim]->get_dphi();
4812  _holder_fe_face_helper[dim]->get_xyz();
4813  _holder_fe_face_helper[dim]->get_JxW();
4814  _holder_fe_face_helper[dim]->get_normals();
4815 
4818  _holder_fe_face_neighbor_helper[dim]->get_normals();
4819 
4820  _holder_fe_neighbor_helper[dim]->get_xyz();
4821  _holder_fe_neighbor_helper[dim]->get_JxW();
4822  }
4823 
4824  for (unsigned int dim = 0; dim < _mesh_dimension; dim++)
4825  {
4826  // We need these computations in order to compute correct lower-d element volumes in
4827  // curvilinear coordinates
4828  _holder_fe_lower_helper[dim]->get_xyz();
4829  _holder_fe_lower_helper[dim]->get_JxW();
4830  }
4831 }
4832 
4833 void
4834 Assembly::havePRefinement(const std::vector<FEFamily> & disable_p_refinement_for_families)
4835 {
4836  if (_have_p_refinement)
4837  // Already performed tasks for p-refinement
4838  return;
4839 
4840  const std::unordered_set<FEFamily> disable_families(disable_p_refinement_for_families.begin(),
4841  disable_p_refinement_for_families.end());
4842 
4843  const Order helper_order = _mesh.hasSecondOrderElements() ? SECOND : FIRST;
4844  const FEType helper_type(helper_order, LAGRANGE);
4845  auto process_fe =
4846  [&disable_families](const unsigned int num_dimensionalities, auto & fe_container)
4847  {
4848  if (!disable_families.empty())
4849  for (const auto dim : make_range(num_dimensionalities))
4850  {
4851  auto fe_container_it = fe_container.find(dim);
4852  if (fe_container_it != fe_container.end())
4853  for (auto & [fe_type, fe_ptr] : fe_container_it->second)
4854  if (disable_families.count(fe_type.family))
4855  fe_ptr->add_p_level_in_reinit(false);
4856  }
4857  };
4858  auto process_fe_and_helpers = [process_fe, &helper_type](auto & unique_helper_container,
4859  auto & helper_container,
4860  const unsigned int num_dimensionalities,
4861  const bool user_added_helper_type,
4862  auto & fe_container)
4863  {
4864  unique_helper_container.resize(num_dimensionalities);
4865  for (const auto dim : make_range(num_dimensionalities))
4866  {
4867  auto & unique_helper = unique_helper_container[dim];
4868  unique_helper = FEGenericBase<Real>::build(dim, helper_type);
4869  // don't participate in p-refinement
4870  unique_helper->add_p_level_in_reinit(false);
4871  helper_container[dim] = unique_helper.get();
4872 
4873  // If the user did not request the helper type then we should erase it from our FE container
4874  // so that they're not penalized (in the "we should be able to do p-refinement sense") for
4875  // our perhaps silly helpers
4876  if (!user_added_helper_type)
4877  {
4878  auto & fe_container_dim = libmesh_map_find(fe_container, dim);
4879  auto fe_it = fe_container_dim.find(helper_type);
4880  mooseAssert(fe_it != fe_container_dim.end(), "We should have the helper type");
4881  delete fe_it->second;
4882  fe_container_dim.erase(fe_it);
4883  }
4884  }
4885 
4886  process_fe(num_dimensionalities, fe_container);
4887  };
4888 
4889  // Handle scalar field families
4890  process_fe_and_helpers(_unique_fe_helper,
4892  _mesh_dimension + 1,
4894  _fe);
4895  process_fe_and_helpers(_unique_fe_face_helper,
4897  _mesh_dimension + 1,
4899  _fe_face);
4900  process_fe_and_helpers(_unique_fe_face_neighbor_helper,
4902  _mesh_dimension + 1,
4905  process_fe_and_helpers(_unique_fe_neighbor_helper,
4907  _mesh_dimension + 1,
4909  _fe_neighbor);
4910  process_fe_and_helpers(_unique_fe_lower_helper,
4914  _fe_lower);
4915  // Handle vector field families
4916  process_fe(_mesh_dimension + 1, _vector_fe);
4917  process_fe(_mesh_dimension + 1, _vector_fe_face);
4918  process_fe(_mesh_dimension + 1, _vector_fe_neighbor);
4919  process_fe(_mesh_dimension + 1, _vector_fe_face_neighbor);
4920  process_fe(_mesh_dimension, _vector_fe_lower);
4921 
4923 
4924  _have_p_refinement = true;
4925 }
4926 
4927 template void coordTransformFactor<Point, Real>(const SubProblem & s,
4928  SubdomainID sub_id,
4929  const Point & point,
4930  Real & factor,
4931  SubdomainID neighbor_sub_id);
4932 template void coordTransformFactor<ADPoint, ADReal>(const SubProblem & s,
4933  SubdomainID sub_id,
4934  const ADPoint & point,
4935  ADReal & factor,
4936  SubdomainID neighbor_sub_id);
4937 template void coordTransformFactor<Point, Real>(const MooseMesh & mesh,
4938  SubdomainID sub_id,
4939  const Point & point,
4940  Real & factor,
4941  SubdomainID neighbor_sub_id);
4943  SubdomainID sub_id,
4944  const ADPoint & point,
4945  ADReal & factor,
4946  SubdomainID neighbor_sub_id);
4947 
4948 template <>
4950 Assembly::genericQPoints<false>() const
4951 {
4952  return qPoints();
4953 }
4954 
4955 template <>
4957 Assembly::genericQPoints<true>() const
4958 {
4959  return adQPoints();
4960 }
const Elem *const & elem() const
Return the current element.
Definition: Assembly.h:367
virtual MooseMesh & mesh()=0
MooseArray< DualReal > _ad_JxW
Definition: Assembly.h:2787
LAGRANGE
void copyShapes(MooseVariableField< T > &v)
Definition: Assembly.C:2991
void setWeights(const std::vector< Real > &weights)
Set the quadrature weights.
std::map< unsigned int, std::map< FEType, FEBase * > > _fe_face
types of finite elements
Definition: Assembly.h:2467
bool _need_neighbor_elem_volume
true is apps need to compute neighbor element volume
Definition: Assembly.h:2571
void cacheResidualNeighbor(GlobalDataKey, const std::vector< VectorTag > &tags)
Takes the values that are currently in _sub_Rn of all field variables and appends them to the cached ...
Definition: Assembly.C:3451
virtual void insert(const Number *v, const std::vector< numeric_index_type > &dof_indices)
ArbitraryQuadrature * _current_qrule_arbitrary
The current arbitrary quadrature rule used within the element interior.
Definition: Assembly.h:2367
std::map< FEType, FEBase * > _current_fe
The "volume" fe object that matches the current elem.
Definition: Assembly.h:2335
MooseArray< Real > _curvatures
Definition: Assembly.h:2802
const std::vector< MooseVariableFieldBase * > & getVariables(THREAD_ID tid)
Definition: SystemBase.h:742
VectorVariablePhiValue _phi
Definition: Assembly.h:2710
SystemBase & _sys
Definition: Assembly.h:2265
std::vector< std::vector< dof_id_type > > _cached_residual_rows
Where the cached values should go (the first vector is for TIME vs NONTIME)
Definition: Assembly.h:2754
std::vector< std::vector< dof_id_type > > _cached_jacobian_rows
Row where the corresponding cached value should go.
Definition: Assembly.h:2761
void computeGradPhiAD(const Elem *elem, unsigned int n_qp, ADTemplateVariablePhiGradient< OutputType > &grad_phi, FEGenericBase< OutputType > *fe)
compute gradient of phi possibly with derivative information with respect to nonlinear displacement v...
Definition: Assembly.C:887
unsigned int _max_cached_residuals
Definition: Assembly.h:2756
std::map< FEType, ADTemplateVariablePhiGradient< Real > > _ad_grad_phi_data_face
Definition: Assembly.h:2735
std::vector< dof_id_type > componentDofIndices(const std::vector< dof_id_type > &dof_indices, unsigned int component) const
Obtain DoF indices of a component with the indices of the 0th component.
MooseArray< VectorValue< DualReal > > _ad_q_points_face
Definition: Assembly.h:2801
std::vector< DualReal > _ad_detadz_map
Definition: Assembly.h:2794
QBase * _current_qrule_lower
quadrature rule used on lower dimensional elements.
Definition: Assembly.h:2545
bool _user_added_fe_lower_of_helper_type
Definition: Assembly.h:2318
MooseArray< Point > _current_physical_points
This will be filled up with the physical points passed into reinitAtPhysical() if it is called...
Definition: Assembly.h:2599
std::vector< DualReal > _ad_dxidy_map
Definition: Assembly.h:2790
const VariablePhiGradient & gradPhiFaceNeighbor(const MooseVariableField< Real > &) const
Definition: Assembly.h:1313
std::vector< std::unique_ptr< FEBase > > _unique_fe_lower_helper
Definition: Assembly.h:2326
Order
MooseArray< VectorValue< DualReal > > _ad_normals
Definition: Assembly.h:2800
virtual const FieldVariablePhiValue & phi() const =0
Return the variable&#39;s elemental shape functions.
void setResidualBlock(NumericVector< Number > &residual, DenseVector< Number > &res_block, const std::vector< dof_id_type > &dof_indices, const std::vector< Real > &scaling_factor, bool is_nodal)
Set a local residual block to a global residual vector with proper scaling.
Definition: Assembly.C:3285
void buildNeighborFE(FEType type) const
Build FEs for a neighbor with a type.
Definition: Assembly.C:312
const VariablePhiSecond & secondPhi() const
Definition: Assembly.h:1278
void setMortarQRule(Order order)
Specifies a custom qrule for integration on mortar segment mesh.
Definition: Assembly.C:732
std::map< unsigned int, std::map< FEType, FEVectorBase * > > _vector_fe
Each dimension&#39;s actual vector fe objects indexed on type.
Definition: Assembly.h:2357
typename OutputTools< typename Moose::ADType< T >::type >::VariablePhiGradient ADTemplateVariablePhiGradient
Definition: MooseTypes.h:548
void buildVectorLowerDFE(FEType type) const
Build Vector FEs for a lower dimensional element with a type.
Definition: Assembly.C:401
std::vector< VectorValue< DualReal > > _ad_d2xyzdxi2_map
Definition: Assembly.h:2783
MooseArray< Real > _coord_neighbor
The current coordinate transformation coefficients.
Definition: Assembly.h:2524
virtual void haveADObjects(bool have_ad_objects)
Method for setting whether we have any ad objects.
Definition: SubProblem.h:737
void buildFE(FEType type) const
Build FEs with a type.
Definition: Assembly.C:264
QBase * _qrule_msm
A qrule object for working on mortar segement elements.
Definition: Assembly.h:2539
const std::vector< MooseVariableScalar * > & getScalarVariables(THREAD_ID tid)
Definition: SystemBase.h:747
QBase * _current_qrule
The current current quadrature rule being used (could be either volumetric or arbitrary - for dirac k...
Definition: Assembly.h:2363
std::vector< std::vector< std::vector< DenseMatrix< Number > > > > _sub_Kle
dlower/dsecondary (or dlower/delement)
Definition: Assembly.h:2644
virtual void zero() override final
void cacheResidualLower(GlobalDataKey, const std::vector< VectorTag > &tags)
Takes the values that are currently in _sub_Rl and appends them to the cached values.
Definition: Assembly.C:3466
const unsigned int invalid_uint
bool hasVector(const std::string &tag_name) const
Check if the named vector exists in the system.
Definition: SystemBase.C:880
LAGRANGE_VEC
MooseArray< DualReal > _ad_JxW_face
Definition: Assembly.h:2799
Assembly(SystemBase &sys, THREAD_ID tid)
Definition: Assembly.C:77
std::map< FEType, std::unique_ptr< FEShapeData > > _fe_shape_data
Shape function values, gradients, second derivatives for each FE type.
Definition: Assembly.h:2718
void buildLowerDDualFE(FEType type) const
Definition: Assembly.C:380
unsigned int TagID
Definition: MooseTypes.h:199
void addJacobianBlockNonlocal(SparseMatrix< Number > &jacobian, unsigned int ivar, unsigned int jvar, const DofMap &dof_map, const std::vector< dof_id_type > &idof_indices, const std::vector< dof_id_type > &jdof_indices, GlobalDataKey, TagID tag)
Adds non-local element matrix for ivar rows and jvar columns to the global Jacobian matrix...
Definition: Assembly.C:4292
MooseArray< Real > _current_JxW_neighbor
The current transformed jacobian weights on a neighbor&#39;s face.
Definition: Assembly.h:2522
std::shared_ptr< XFEMInterface > _xfem
The XFEM controller.
Definition: Assembly.h:2332
void reinitNeighborLowerDElem(const Elem *elem)
reinitialize a neighboring lower dimensional element
Definition: Assembly.C:2375
virtual ~Assembly()
Definition: Assembly.C:184
void prepareJacobianBlock()
Sizes and zeroes the Jacobian blocks used for the current element.
Definition: Assembly.C:2678
DenseMatrix< Number > & jacobianBlockNonlocal(unsigned int ivar, unsigned int jvar, LocalDataKey, TagID tag)
Get local Jacobian block from non-local contribution for a pair of variables and a tag...
Definition: Assembly.h:1103
void mooseError(Args &&... args)
Emit an error message with the given stringified, concatenated args and terminate the application...
Definition: MooseError.h:299
virtual void zero() override final
std::vector< DualReal > _ad_dzetady_map
Definition: Assembly.h:2796
std::vector< std::vector< std::vector< DenseMatrix< Number > > > > _sub_Kel
dsecondary/dlower (or delement/dlower)
Definition: Assembly.h:2648
const std::vector< Real > & arrayScalingFactor() const
MooseArray< Real > _coord
The current coordinate transformation coefficients.
Definition: Assembly.h:2377
unsigned int number() const
Get variable number coming from libMesh.
MooseArray< VectorValue< DualReal > > _ad_q_points
Definition: Assembly.h:2788
std::unique_ptr< QBase > vol
volume/elem (meshdim) quadrature rule
Definition: Assembly.h:2395
DenseMatrix< Number > & jacobianBlockNeighbor(Moose::DGJacobianType type, unsigned int ivar, unsigned int jvar, LocalDataKey, TagID tag)
Get local Jacobian block of a DG Jacobian type for a pair of variables and a tag. ...
Definition: Assembly.C:3108
void reinitFE(const Elem *elem)
Just an internal helper function to reinit the volume FE objects.
Definition: Assembly.C:757
TagID _id
The id associated with the vector tag.
Definition: VectorTag.h:28
virtual unsigned int currentNlSysNum() const =0
void jacobianBlockUsed(TagID tag, unsigned int ivar, unsigned int jvar, bool used)
Sets whether or not Jacobian coupling between ivar and jvar is used to the value used.
Definition: Assembly.h:2192
void coordTransformFactor(const P &point, C &factor, const Moose::CoordinateSystemType coord_type, const unsigned int rz_radial_coord=libMesh::invalid_uint)
compute a coordinate transformation factor
void init(const CouplingMatrix *cm)
Initialize the Assembly object and set the CouplingMatrix for use throughout.
Definition: Assembly.C:2461
void prepareNonlocal()
Definition: Assembly.C:2716
std::map< unsigned int, FEBase * > _holder_fe_neighbor_helper
Each dimension&#39;s helper objects.
Definition: Assembly.h:2505
std::unique_ptr< FEBase > _fe_msm
A FE object for working on mortar segement elements.
Definition: Assembly.h:2534
std::map< FEType, std::unique_ptr< FEShapeData > > _fe_shape_data_face_neighbor
Definition: Assembly.h:2721
void createQRules(QuadratureType type, Order order, Order volume_order, Order face_order, SubdomainID block, bool allow_negative_qweights=true)
Creates block-specific volume, face and arbitrary qrules based on the orders and the flag of whether ...
Definition: Assembly.C:614
std::vector< DualReal > _ad_dzetadz_map
Definition: Assembly.h:2797
const Elem & elem() const
Definition: FaceInfo.h:80
void reinitAtPhysical(const Elem *elem, const std::vector< Point > &physical_points)
Reinitialize the assembly data at specific physical point in the given element.
Definition: Assembly.C:1780
void addCachedResidualDirectly(NumericVector< Number > &residual, GlobalDataKey, const VectorTag &vector_tag)
Adds the values that have been cached by calling cacheResidual(), cacheResidualNeighbor(), and/or cacheResidualLower() to a user-defined residual (that is, not necessarily the vector that vector_tag points to)
Definition: Assembly.C:3526
bool _current_elem_volume_computed
Boolean to indicate whether current element volumes has been computed.
Definition: Assembly.h:2579
void jacobianBlockLowerUsed(TagID tag, unsigned int ivar, unsigned int jvar, bool used)
Sets whether or not lower Jacobian coupling between ivar and jvar is used to the value used...
Definition: Assembly.h:2228
const VectorVariablePhiDivergence & divPhi(const MooseVariableField< RealVectorValue > &) const
Definition: Assembly.h:1338
std::map< FEType, bool > _need_div
Definition: Assembly.h:2821
std::vector< std::unique_ptr< FEBase > > _unique_fe_neighbor_helper
Definition: Assembly.h:2325
std::vector< std::vector< std::vector< DenseMatrix< Number > > > > _sub_Kll
dlower/dlower
Definition: Assembly.h:2642
bool _user_added_fe_face_neighbor_of_helper_type
Definition: Assembly.h:2316
void setResidualNeighbor(NumericVector< Number > &residual, GlobalDataKey, const VectorTag &vector_tag)
Sets local neighbor residuals of all field variables to the global residual vector for a tag...
Definition: Assembly.C:3557
bool _have_p_refinement
Whether we have ever conducted p-refinement.
Definition: Assembly.h:2851
FIRST
VariablePhiValue _phi
Definition: Assembly.h:2700
Real _current_neighbor_volume
Volume of the current neighbor.
Definition: Assembly.h:2573
void jacobianBlockNonlocalUsed(TagID tag, unsigned int ivar, unsigned int jvar, bool used)
Sets whether or not nonlocal Jacobian coupling between ivar and jvar is used to the value used...
Definition: Assembly.h:2246
virtual void add_vector(const Number *v, const std::vector< numeric_index_type > &dof_indices)
ArbitraryQuadrature * qruleArbitraryFace(const Elem *elem, unsigned int side)
Definition: Assembly.C:1916
std::map< FEType, FEBase * > _current_fe_face
The "face" fe object that matches the current elem.
Definition: Assembly.h:2337
const VectorVariablePhiCurl & curlPhi(const MooseVariableField< RealVectorValue > &) const
Definition: Assembly.h:1334
std::vector< Point > _current_neighbor_ref_points
The current reference points on the neighbor element.
Definition: Assembly.h:2854
std::vector< std::vector< std::vector< DenseMatrix< Number > > > > _sub_Kln
dlower/dprimary (or dlower/dneighbor)
Definition: Assembly.h:2646
const Elem * _current_neighbor_elem
The current neighbor "element".
Definition: Assembly.h:2563
void addJacobianNonlocal(GlobalDataKey)
Adds non-local Jacobian to the global Jacobian matrices.
Definition: Assembly.C:3879
std::vector< std::vector< DenseVector< Number > > > _sub_Rn
Definition: Assembly.h:2614
unsigned int count() const
Get the number of components Note: For standard and vector variables, the number is one...
virtual const FieldVariablePhiGradient & gradPhiNeighbor() const =0
Return the gradients of the variable&#39;s shape functions on a neighboring element.
const VariablePhiValue & phi() const
Definition: Assembly.h:1269
MooseMesh & _mesh
Definition: Assembly.h:2305
TagTypeID _type_id
The index for this tag into a vector that contains tags of only its type ordered by ID...
Definition: VectorTag.h:45
std::map< FEType, std::unique_ptr< FEShapeData > > _fe_shape_data_neighbor
Definition: Assembly.h:2720
std::map< unsigned int, FEBase * > _holder_fe_face_neighbor_helper
Definition: Assembly.h:2506
void setPoints(const std::vector< Point > &points)
Set the quadrature points.
MeshBase & mesh
const VariablePhiGradient & gradPhi() const
Definition: Assembly.h:1276
MooseArray< Real > _current_JxW_face
The current transformed jacobian weights on a face.
Definition: Assembly.h:2481
void modifyWeightsDueToXFEM(const Elem *elem)
Update the integration weights for XFEM partial elements.
Definition: Assembly.C:4527
void coordTransformFactorRZGeneral(const P &point, const std::pair< Point, RealVectorValue > &axis, C &factor)
Computes a coordinate transformation factor for a general axisymmetric axis.
const Elem * _current_elem
The current "element" we are currently on.
Definition: Assembly.h:2549
const VariablePhiSecond & secondPhiNeighbor(const MooseVariableField< Real > &) const
Definition: Assembly.h:1304
bool computingScalingJacobian() const
Whether we are computing an initial Jacobian for automatic variable scaling.
Definition: SystemBase.C:1477
THREAD_ID _tid
Thread number (id)
Definition: Assembly.h:2303
void reinitFEFaceNeighbor(const Elem *neighbor, const std::vector< Point > &reference_points)
Definition: Assembly.C:1561
static constexpr std::size_t dim
This is the dimension of all vector and tensor datastructures used in MOOSE.
Definition: Moose.h:148
virtual const FieldVariablePhiSecond & secondPhi() const =0
Return the rank-2 tensor of second derivatives of the variable&#39;s elemental shape functions.
void reinitNeighborAtPhysical(const Elem *neighbor, unsigned int neighbor_side, const std::vector< Point > &physical_points)
Reinitializes the neighbor at the physical coordinates on neighbor side given.
Definition: Assembly.C:2410
std::vector< std::unique_ptr< FEBase > > _unique_fe_face_helper
Definition: Assembly.h:2323
QuadratureType
std::vector< std::vector< std::vector< unsigned char > > > _jacobian_block_nonlocal_used
Definition: Assembly.h:2295
std::vector< std::pair< MooseVariableScalar *, MooseVariableFieldBase * > > _cm_sf_entry
Entries in the coupling matrix for scalar variables vs field variables.
Definition: Assembly.h:2288
void prepareNeighbor()
Definition: Assembly.C:2795
void resizeADMappingObjects(unsigned int n_qp, unsigned int dim)
resize any objects that contribute to automatic differentiation-related mapping calculations ...
Definition: Assembly.C:967
OutputTools< Real >::VariablePhiValue VariablePhiValue
Definition: MooseTypes.h:307
unsigned int m() const
virtual bool hasMatrix(TagID tag) const
Check if the tagged matrix exists in the system.
Definition: SystemBase.h:338
ElemSideBuilder _current_neighbor_side_elem_builder
In place side element builder for _current_neighbor_side_elem.
Definition: Assembly.h:2829
std::map< unsigned int, std::map< FEType, FEVectorBase * > > _vector_fe_face_neighbor
Definition: Assembly.h:2502
std::map< FEType, bool > _need_second_derivative
Definition: Assembly.h:2818
const VariablePhiValue & phiFaceNeighbor(const MooseVariableField< Real > &) const
Definition: Assembly.h:1309
unsigned int elemSideID() const
Definition: FaceInfo.h:108
std::vector< bool > _component_block_diagonal
An flag array Indiced by variable index to show if there is no component-wise coupling for the variab...
Definition: Assembly.h:2771
Real _current_elem_volume
Volume of the current element.
Definition: Assembly.h:2555
std::map< FEType, FEBase * > _current_fe_face_neighbor
The "neighbor face" fe object that matches the current elem.
Definition: Assembly.h:2341
const MooseArray< ADReal > & adCurvatures() const
Definition: Assembly.C:4788
This class provides an interface for common operations on field variables of both FE and FV types wit...
std::map< FEType, FEVectorBase * > _current_vector_fe_face
The "face" vector fe object that matches the current elem.
Definition: Assembly.h:2346
void shallowCopy(const MooseArray &rhs)
Doesn&#39;t actually make a copy of the data.
Definition: MooseArray.h:293
std::vector< std::unique_ptr< FEBase > > _unique_fe_helper
Containers for holding unique FE helper types if we are doing p-refinement.
Definition: Assembly.h:2322
std::vector< DualReal > _ad_dzetadx_map
Definition: Assembly.h:2795
ADRealEigenVector< T, D, asd > sqrt(const ADRealEigenVector< T, D, asd > &)
void processLocalResidual(DenseVector< Number > &res_block, std::vector< dof_id_type > &dof_indices, const std::vector< Real > &scaling_factor, bool is_nodal)
Appling scaling, constraints to the local residual block and populate the full DoF indices for array ...
Definition: Assembly.C:3209
const FEType _helper_type
The finite element type of the FE helper classes.
Definition: Assembly.h:2311
void addResidualLower(GlobalDataKey, const std::vector< VectorTag > &vector_tags)
Add local neighbor residuals of all field variables for a set of tags onto the global residual vector...
Definition: Assembly.C:3368
DenseMatrix< Number > & jacobianBlock(unsigned int ivar, unsigned int jvar, LocalDataKey, TagID tag)
Get local Jacobian block for a pair of variables and a tag.
Definition: Assembly.h:1092
void addJacobianScalar(GlobalDataKey)
Add Jacobians for pairs of scalar variables into the global Jacobian matrices.
Definition: Assembly.C:4449
std::vector< std::vector< std::vector< DenseMatrix< Number > > > > _sub_Knn
jacobian contributions from the neighbor <Tag, ivar, jvar>
Definition: Assembly.h:2640
Base class for a system (of equations)
Definition: SystemBase.h:85
const VariablePhiValue & phiNeighbor(const MooseVariableField< Real > &) const
Definition: Assembly.h:1296
void setVolumeQRule(QBase *qrule, unsigned int dim)
Set the qrule to be used for volume integration.
Definition: Assembly.C:652
FEGenericBase< RealGradient > FEVectorBase
unsigned int numExtraElemIntegers() const
Number of extra element integers Assembly tracked.
Definition: Assembly.h:326
SECOND
std::vector< std::vector< Real > > _cached_jacobian_values
Values cached by calling cacheJacobian()
Definition: Assembly.h:2759
std::vector< std::pair< MooseVariableFieldBase *, MooseVariableFieldBase * > > _cm_ff_entry
Entries in the coupling matrix for field variables.
Definition: Assembly.h:2284
void addJacobianNeighborLowerD(GlobalDataKey)
Add all portions of the Jacobian except PrimaryPrimary, e.g.
Definition: Assembly.C:3939
std::map< FEType, FEVectorBase * > _current_vector_fe
The "volume" vector fe object that matches the current elem.
Definition: Assembly.h:2344
VariablePhiGradient _grad_phi
Definition: Assembly.h:2701
template void coordTransformFactor< ADPoint, ADReal >(const SubProblem &s, SubdomainID sub_id, const ADPoint &point, ADReal &factor, SubdomainID neighbor_sub_id)
void prepareScalar()
Definition: Assembly.C:2941
virtual const FieldVariablePhiValue & phiNeighbor() const =0
Return the variable&#39;s shape functions on a neighboring element.
ElemSideBuilder _compute_face_map_side_elem_builder
In place side element builder for computeFaceMap()
Definition: Assembly.h:2831
void modifyFaceWeightsDueToXFEM(const Elem *elem, unsigned int side=0)
Update the face integration weights for XFEM partial elements.
Definition: Assembly.C:4547
const CouplingMatrix * _cm
Coupling matrices.
Definition: Assembly.h:2271
std::map< FEType, bool > _need_second_derivative_neighbor
Definition: Assembly.h:2819
void reinitElemAndNeighbor(const Elem *elem, unsigned int side, const Elem *neighbor, unsigned int neighbor_side, const std::vector< Point > *neighbor_reference_points=nullptr)
Reinitialize an element and its neighbor along a particular side.
Definition: Assembly.C:1987
OutputTools< Real >::VariablePhiSecond VariablePhiSecond
Definition: MooseTypes.h:309
unsigned int neighborSideID() const
Definition: FaceInfo.h:109
DenseVector< Number > _tmp_Re
auxiliary vector for scaling residuals (optimization to avoid expensive construction/destruction) ...
Definition: Assembly.h:2619
unsigned int _mesh_dimension
Definition: Assembly.h:2307
std::vector< Eigen::Map< RealDIMValue > > _mapped_normals
Mapped normals.
Definition: Assembly.h:2485
VectorVariablePhiDivergence _vector_div_phi_face
Definition: Assembly.h:2683
void cacheJacobian(GlobalDataKey)
Takes the values that are currently in _sub_Kee and appends them to the cached values.
Definition: Assembly.C:4054
void reinit(const Elem *elem)
Reinitialize objects (JxW, q_points, ...) for an elements.
Definition: Assembly.C:1811
const NumericVector< Real > * _scaling_vector
The map from global index to variable scaling factor.
Definition: Assembly.h:2824
auto max(const L &left, const R &right)
QBase * _current_qrule_volume
The current volumetric quadrature for the element.
Definition: Assembly.h:2365
virtual void set(const numeric_index_type i, const numeric_index_type j, const Number value)=0
void addCachedResiduals(GlobalDataKey, const std::vector< VectorTag > &tags)
Pushes all cached residuals to the global residual vectors associated with each tag.
Definition: Assembly.C:3481
const DofMap & _dof_map
DOF map.
Definition: Assembly.h:2301
Data structure for tracking/grouping a set of quadrature rules for a particular dimensionality of mes...
Definition: Assembly.h:2383
MONOMIAL_VEC
std::vector< DualReal > _ad_dxidx_map
Definition: Assembly.h:2789
unsigned int _max_cached_jacobians
Definition: Assembly.h:2765
virtual void add(const numeric_index_type i, const numeric_index_type j, const Number value)=0
DenseMatrix< Number > & jacobianBlockMortar(Moose::ConstraintJacobianType type, unsigned int ivar, unsigned int jvar, LocalDataKey, TagID tag)
Returns the jacobian block for the given mortar Jacobian type.
Definition: Assembly.C:3149
QUAD4
std::vector< std::vector< std::vector< DenseMatrix< Number > > > > _sub_Ken
jacobian contributions from the element and neighbor <Tag, ivar, jvar>
Definition: Assembly.h:2636
std::map< FEType, std::unique_ptr< VectorFEShapeData > > _vector_fe_shape_data_dual_lower
Definition: Assembly.h:2731
virtual unsigned int nVariables() const
Get the number of variables in this system.
Definition: SystemBase.C:847
const CouplingMatrix & _nonlocal_cm
Definition: Assembly.h:2272
virtual const FieldVariablePhiValue & phiFaceNeighbor() const =0
Return the variable&#39;s shape functions on a neighboring element face.
std::vector< Point > _temp_reference_points
Temporary work data for reinitAtPhysical()
Definition: Assembly.h:2777
std::vector< std::pair< MooseVariableScalar *, MooseVariableScalar * > > _cm_ss_entry
Entries in the coupling matrix for scalar variables.
Definition: Assembly.h:2290
std::vector< std::vector< std::vector< DenseMatrix< Number > > > > _sub_Kne
jacobian contributions from the neighbor and element <Tag, ivar, jvar>
Definition: Assembly.h:2638
const Elem * _current_neighbor_lower_d_elem
The current neighboring lower dimensional element.
Definition: Assembly.h:2586
unsigned int _current_neighbor_side
The current side of the selected neighboring element (valid only when working with sides) ...
Definition: Assembly.h:2567
void cacheResidualNodes(const DenseVector< Number > &res, const std::vector< dof_id_type > &dof_index, LocalDataKey, TagID tag)
Lets an external class cache residual at a set of nodes.
Definition: Assembly.C:3433
void prepareLowerD()
Prepare the Jacobians and residuals for a lower dimensional element.
Definition: Assembly.C:2834
bool _user_added_fe_neighbor_of_helper_type
Definition: Assembly.h:2317
void buildFaceNeighborFE(FEType type) const
Build FEs for a neighbor face with a type.
Definition: Assembly.C:334
std::map< FEType, std::unique_ptr< VectorFEShapeData > > _vector_fe_shape_data_face
Definition: Assembly.h:2727
void reinitLowerDElem(const Elem *elem, const std::vector< Point > *const pts=nullptr, const std::vector< Real > *const weights=nullptr)
Reinitialize FE data for a lower dimenesional element with a given set of reference points...
Definition: Assembly.C:2282
void computeCurrentFaceVolume()
Definition: Assembly.C:1761
std::vector< std::vector< DenseVector< Number > > > _sub_Rl
residual contributions for each variable from the lower dimensional element
Definition: Assembly.h:2616
This data structure is used to store geometric and variable related metadata about each cell face in ...
Definition: FaceInfo.h:35
QRules & qrules(unsigned int dim)
Definition: Assembly.h:2443
virtual const FieldVariablePhiSecond & secondPhiFaceNeighbor() const =0
Return the rank-2 tensor of second derivatives of the variable&#39;s shape functions on a neighboring ele...
virtual const std::vector< dof_id_type > & dofIndicesNeighbor() const =0
Get neighbor DOF indices for currently selected element.
static const subdomain_id_type invalid_subdomain_id
CONSTANT
virtual void add_matrix(const DenseMatrix< Number > &dm, const std::vector< numeric_index_type > &rows, const std::vector< numeric_index_type > &cols)=0
void prepareOffDiagScalar()
Definition: Assembly.C:2965
VectorVariablePhiSecond _second_phi
Definition: Assembly.h:2712
unsigned int size() const
The number of elements that can currently be stored in the array.
Definition: MooseArray.h:256
Implements a fake quadrature rule where you can specify the locations (in the reference domain) of th...
void addJacobianCoupledVarPair(const MooseVariableBase &ivar, const MooseVariableBase &jvar)
Adds element matrices for ivar rows and jvar columns to the global Jacobian matrices.
Definition: Assembly.C:3851
void addJacobianLowerD(GlobalDataKey)
Add portions of the Jacobian of LowerLower, LowerSecondary, and SecondaryLower for boundary condition...
Definition: Assembly.C:4017
virtual const FieldVariablePhiSecond & secondPhiFace() const =0
Return the rank-2 tensor of second derivatives of the variable&#39;s shape functions on an element face...
QBase * _current_qrule_neighbor
quadrature rule used on neighbors
Definition: Assembly.h:2516
std::vector< DualReal > _ad_dxidz_map
Definition: Assembly.h:2791
const Elem * neighborPtr() const
Definition: FaceInfo.h:83
VectorVariablePhiGradient _grad_phi
Definition: Assembly.h:2711
ArbitraryQuadrature * _current_qrule_arbitrary_face
The current arbitrary quadrature rule used on the element face.
Definition: Assembly.h:2369
void modifyArbitraryWeights(const std::vector< Real > &weights)
Modify the weights when using the arbitrary quadrature rule.
Definition: Assembly.C:4574
std::vector< std::pair< MooseVariableFieldBase *, MooseVariableScalar * > > _cm_fs_entry
Entries in the coupling matrix for field variables vs scalar variables.
Definition: Assembly.h:2286
const std::vector< Real > * _JxW_msm
A JxW for working on mortar segement elements.
Definition: Assembly.h:2532
Real value(unsigned n, unsigned alpha, unsigned beta, Real x)
MeshBase & getMesh()
Accessor for the underlying libMesh Mesh object.
Definition: MooseMesh.C:3199
void coordTransformFactor(const SubProblem &s, const SubdomainID sub_id, const P &point, C &factor, const SubdomainID neighbor_sub_id)
Computes a conversion multiplier for use when computing integraals for the current coordinate system ...
Definition: Assembly.C:39
std::unique_ptr< QBase > face
area/face (meshdim-1) quadrature rule
Definition: Assembly.h:2397
dof_id_type numeric_index_type
std::map< FEType, ADTemplateVariablePhiGradient< Real > > _ad_grad_phi_data
Definition: Assembly.h:2733
template void coordTransformFactor< Point, Real >(const SubProblem &s, SubdomainID sub_id, const Point &point, Real &factor, SubdomainID neighbor_sub_id)
std::unordered_map< SubdomainID, std::vector< QRules > > _qrules
Holds quadrature rules for each dimension.
Definition: Assembly.h:2412
unsigned int n_vars
void prepareResidual()
Sizes and zeroes the residual for the current element.
Definition: Assembly.C:2700
VectorVariablePhiCurl _curl_phi
Definition: Assembly.h:2713
std::map< FEType, FEBase * > _current_fe_neighbor
The "neighbor" fe object that matches the current elem.
Definition: Assembly.h:2339
Real elementVolume(const Elem *elem) const
On-demand computation of volume element accounting for RZ/RSpherical.
Definition: Assembly.C:3778
void cacheJacobianNeighbor(GlobalDataKey)
Takes the values that are currently in the neighbor Dense Matrices and appends them to the cached val...
Definition: Assembly.C:4106
SubdomainID _current_neighbor_subdomain_id
The current neighbor subdomain ID.
Definition: Assembly.h:2565
std::vector< std::vector< DenseVector< Number > > > _sub_Re
Definition: Assembly.h:2613
void reinitNeighbor(const Elem *neighbor, const std::vector< Point > &reference_points)
Reinitializes the neighbor side using reference coordinates.
Definition: Assembly.C:1675
std::vector< std::vector< std::vector< unsigned char > > > _jacobian_block_used
Flag that indicates if the jacobian block was used.
Definition: Assembly.h:2294
void prepare()
Definition: Assembly.C:2709
virtual numeric_index_type m() const =0
void setFaceQRule(QBase *qrule, unsigned int dim)
Set the qrule to be used for face integration.
Definition: Assembly.C:671
std::vector< DualReal > _ad_jac
Definition: Assembly.h:2786
MooseMesh wraps a libMesh::Mesh object and enhances its capabilities by caching additional data and s...
Definition: MooseMesh.h:88
SubProblem & _subproblem
Definition: Assembly.h:2266
libmesh_assert(ctx)
void buildFaceFE(FEType type) const
Build FEs for a face with a type.
Definition: Assembly.C:290
std::map< unsigned int, std::map< FEType, FEBase * > > _fe_neighbor
types of finite elements
Definition: Assembly.h:2499
void cacheResidual(GlobalDataKey, const std::vector< VectorTag > &tags)
Takes the values that are currently in _sub_Re of all field variables and appends them to the cached ...
Definition: Assembly.C:3400
bool _calculate_xyz
Definition: Assembly.h:2810
MooseArray< std::vector< Point > > _current_tangents
The current tangent vectors at the quadrature points.
Definition: Assembly.h:2487
virtual const std::vector< dof_id_type > & dofIndices() const
Get local DoF indices.
bool _calculate_curvatures
Definition: Assembly.h:2812
const std::vector< VectorTag > & _residual_vector_tags
The residual vector tags that Assembly could possibly contribute to.
Definition: Assembly.h:2748
std::map< FEType, FEVectorBase * > _current_vector_fe_face_neighbor
The "neighbor face" vector fe object that matches the current elem.
Definition: Assembly.h:2350
std::vector< dof_id_type > _neighbor_extra_elem_ids
Extra element IDs of neighbor.
Definition: Assembly.h:2492
MooseArray< Real > _current_JxW
The current list of transformed jacobian weights.
Definition: Assembly.h:2373
virtual void zero_rows(std::vector< numeric_index_type > &rows, Number diag_value=0.0)
void havePRefinement(const std::vector< FEFamily > &disable_p_refinement_for_families)
Indicate that we have p-refinement.
Definition: Assembly.C:4834
virtual bool checkNonlocalCouplingRequirement()
Definition: SubProblem.h:88
std::vector< std::pair< unsigned int, unsigned short > > _disp_numbers_and_directions
Container of displacement numbers and directions.
Definition: Assembly.h:2808
std::vector< dof_id_type > _temp_dof_indices
Temporary work vector to keep from reallocating it.
Definition: Assembly.h:2774
OutputTools< Real >::VariablePhiCurl VariablePhiCurl
Definition: MooseTypes.h:310
std::vector< std::vector< std::vector< DenseMatrix< Number > > > > _sub_Kee
Definition: Assembly.h:2632
std::map< FEType, std::unique_ptr< VectorFEShapeData > > _vector_fe_shape_data_lower
Definition: Assembly.h:2730
OStreamProxy err(std::cerr)
DualReal ADReal
Definition: ADRealForward.h:14
const VariablePhiSecond & secondPhiFace(const MooseVariableField< Real > &) const
Definition: Assembly.h:1291
std::map< FEType, ADTemplateVariablePhiGradient< RealVectorValue > > _ad_vector_grad_phi_data
Definition: Assembly.h:2734
bool usesPhiNeighbor() const
Whether or not this variable is actually using the shape function value.
std::map< unsigned int, std::map< FEType, FEVectorBase * > > _vector_fe_face
types of vector finite elements
Definition: Assembly.h:2469
subdomain_id_type SubdomainID
virtual bool computingSecond() const =0
Whether or not this variable is computing any second derivatives.
unsigned int number() const
Gets the number of this system.
Definition: SystemBase.C:1132
const Elem * _msm_elem
Definition: Assembly.h:2833
std::vector< T > stdVector() const
Extremely inefficient way to produce a std::vector from a MooseArray!
Definition: MooseArray.h:341
QBase * qruleFace(const Elem *elem, unsigned int side)
This is an abstraction over the internal qrules function.
Definition: Assembly.C:1910
bool _calculate_ad_coord
Whether to calculate coord with AD.
Definition: Assembly.h:2816
std::map< FEType, std::unique_ptr< FEShapeData > > _fe_shape_data_lower
Definition: Assembly.h:2722
const Elem * _current_lower_d_elem
The current lower dimensional element.
Definition: Assembly.h:2584
void addResidualBlock(NumericVector< Number > &residual, DenseVector< Number > &res_block, const std::vector< dof_id_type > &dof_indices, const std::vector< Real > &scaling_factor, bool is_nodal)
Add a local residual block to a global residual vector with proper scaling.
Definition: Assembly.C:3245
void addResidual(GlobalDataKey, const std::vector< VectorTag > &vector_tags)
Add local residuals of all field variables for a set of tags onto the global residual vectors associa...
Definition: Assembly.C:3318
void addJacobianNeighborTags(SparseMatrix< Number > &jacobian, unsigned int ivar, unsigned int jvar, const DofMap &dof_map, std::vector< dof_id_type > &dof_indices, std::vector< dof_id_type > &neighbor_dof_indices, GlobalDataKey, const std::set< TagID > &tags)
Adds three neighboring element matrices for ivar rows and jvar columns to the global Jacobian matrix...
Definition: Assembly.C:4434
std::vector< VectorValue< DualReal > > _ad_dxyzdeta_map
Definition: Assembly.h:2781
const VariablePhiValue & phiFace() const
Definition: Assembly.h:1284
std::map< unsigned int, std::map< FEType, FEBase * > > _fe_lower
FE objects for lower dimensional elements.
Definition: Assembly.h:2509
bool hasSecondOrderElements()
check if the mesh has SECOND order elements
Definition: MooseMesh.C:3458
FEGenericBase< Real > FEBase
void addJacobianBlockNonlocalTags(SparseMatrix< Number > &jacobian, unsigned int ivar, unsigned int jvar, const DofMap &dof_map, const std::vector< dof_id_type > &idof_indices, const std::vector< dof_id_type > &jdof_indices, GlobalDataKey, const std::set< TagID > &tags)
Adds non-local element matrix for ivar rows and jvar columns to the global Jacobian matrix...
Definition: Assembly.C:4350
OutputTools< Real >::VariablePhiDivergence VariablePhiDivergence
Definition: MooseTypes.h:311
Real _current_lower_d_elem_volume
The current lower dimensional element volume.
Definition: Assembly.h:2590
std::map< unsigned int, std::map< FEType, FEBase * > > _fe
Each dimension&#39;s actual fe objects indexed on type.
Definition: Assembly.h:2355
const MooseArray< Real > & JxW() const
Returns the reference to the transformed jacobian weights.
Definition: Assembly.h:240
void reinitMortarElem(const Elem *elem)
reinitialize a mortar segment mesh element in order to get a proper JxW
Definition: Assembly.C:2396
Real _current_side_volume
Volume of the current side element.
Definition: Assembly.h:2561
std::vector< std::vector< Real > > _cached_residual_values
Values cached by calling cacheResidual() (the first vector is for TIME vs NONTIME) ...
Definition: Assembly.h:2751
const bool _displaced
Definition: Assembly.h:2268
virtual bool usesSecondPhiNeighbor() const =0
Whether or not this variable is actually using the shape function second derivatives.
virtual const FieldVariablePhiSecond & secondPhiNeighbor() const =0
Return the rank-2 tensor of second derivatives of the variable&#39;s shape functions on a neighboring ele...
void buildVectorFE(FEType type) const
Build Vector FEs with a type.
Definition: Assembly.C:451
virtual const FieldVariablePhiGradient & gradPhiFaceNeighbor() const =0
Return the gradients of the variable&#39;s shape functions on a neighboring element face.
MooseArray< DualReal > _ad_curvatures
Definition: Assembly.h:2803
void reinitFVFace(const FaceInfo &fi)
Definition: Assembly.C:1850
std::map< unsigned int, std::map< FEType, FEVectorBase * > > _vector_fe_lower
Vector FE objects for lower dimensional elements.
Definition: Assembly.h:2511
const MooseArray< Real > & JxWNeighbor() const
Returns the reference to the transformed jacobian weights on a current face.
Definition: Assembly.C:257
std::vector< VectorValue< DualReal > > _ad_d2xyzdxideta_map
Definition: Assembly.h:2784
const Node * _current_node
The current node we are working with.
Definition: Assembly.h:2575
bool _building_helpers
Whether we are currently building the FE classes for the helpers.
Definition: Assembly.h:2329
bool _calculate_face_xyz
Definition: Assembly.h:2811
virtual unsigned int numMatrixTags() const
The total number of tags.
Definition: SubProblem.h:220
DGJacobianType
Definition: MooseTypes.h:662
OutputTools< Real >::VariablePhiGradient VariablePhiGradient
Definition: MooseTypes.h:308
virtual MooseVariableScalar & getScalarVariable(THREAD_ID tid, const std::string &var_name) const
Gets a reference to a scalar variable with specified number.
Definition: SystemBase.C:141
std::map< FEType, std::unique_ptr< VectorFEShapeData > > _vector_fe_shape_data_face_neighbor
Definition: Assembly.h:2729
void addJacobian(GlobalDataKey)
Adds all local Jacobian to the global Jacobian matrices.
Definition: Assembly.C:3866
MooseArray< Point > _current_normals
The current Normal vectors at the quadrature points.
Definition: Assembly.h:2483
virtual const FieldVariablePhiValue & phiFace() const =0
Return the variable&#39;s shape functions on an element face.
void buildVectorFaceFE(FEType type) const
Build Vector FEs for a face with a type.
Definition: Assembly.C:484
const SubdomainID ANY_BLOCK_ID
Definition: MooseTypes.C:19
const VariablePhiGradient & gradPhiNeighbor(const MooseVariableField< Real > &) const
Definition: Assembly.h:1300
virtual const FieldVariablePhiGradient & gradPhi() const =0
Return the gradients of the variable&#39;s elemental shape functions.
RAVIART_THOMAS
DIE A HORRIBLE DEATH HERE typedef LIBMESH_DEFAULT_SCALAR_TYPE Real
void hasScalingVector()
signals this object that a vector containing variable scaling factors should be used when doing resid...
Definition: Assembly.C:4568
Generic class for solving transient nonlinear problems.
Definition: SubProblem.h:75
EDGE2
void setNeighborQRule(QBase *qrule, unsigned int dim)
Set the qrule to be used for neighbor integration.
Definition: Assembly.C:706
std::map< FEType, std::unique_ptr< FEShapeData > > _fe_shape_data_dual_lower
Definition: Assembly.h:2723
void zeroCachedJacobian(GlobalDataKey)
Zero out previously-cached Jacobian rows.
Definition: Assembly.C:4506
std::vector< VectorValue< DualReal > > _ad_dxyzdzeta_map
Definition: Assembly.h:2782
void setCoordinateTransformation(const QBase *qrule, const Points &q_points, Coords &coord, SubdomainID sub_id)
Definition: Assembly.C:1719
void reinitNeighborFaceRef(const Elem *neighbor_elem, unsigned int neighbor_side, Real tolerance, const std::vector< Point > *const pts, const std::vector< Real > *const weights=nullptr)
Reinitialize FE data for the given neighbor_element on the given side with a given set of reference p...
Definition: Assembly.C:2186
bool usesGradPhiNeighbor() const
Whether or not this variable is actually using the shape function gradient.
void prepareVariableNonlocal(MooseVariableFieldBase *var)
Definition: Assembly.C:2768
void release()
Manually deallocates the data pointer.
Definition: MooseArray.h:66
std::map< FEType, std::unique_ptr< FEShapeData > > _fe_shape_data_face
Definition: Assembly.h:2719
virtual SparseMatrix< Number > & getMatrix(TagID tag)
Get a raw SparseMatrix.
Definition: SystemBase.C:980
std::map< FEType, std::unique_ptr< VectorFEShapeData > > _vector_fe_shape_data
Shape function values, gradients, second derivatives for each vector FE type.
Definition: Assembly.h:2726
void addResidualScalar(GlobalDataKey, const std::vector< VectorTag > &vector_tags)
Add residuals of all scalar variables for a set of tags onto the global residual vectors associated w...
Definition: Assembly.C:3392
MooseArray< Real > _coord_msm
The coordinate transformation coefficients evaluated on the quadrature points of the mortar segment m...
Definition: Assembly.h:2527
std::vector< std::vector< std::vector< DenseMatrix< Number > > > > _sub_Keg
Definition: Assembly.h:2633
bool _need_lower_d_elem_volume
Whether we need to compute the lower dimensional element volume.
Definition: Assembly.h:2588
bool _user_added_fe_face_of_helper_type
Definition: Assembly.h:2315
const std::vector< dof_id_type > & allDofIndices() const
Get all global dofindices for the variable.
void buildVectorNeighborFE(FEType type) const
Build Vector FEs for a neighbor with a type.
Definition: Assembly.C:513
std::unique_ptr< ArbitraryQuadrature > arbitrary_vol
volume/elem (meshdim) custom points quadrature rule
Definition: Assembly.h:2401
void reinitFENeighbor(const Elem *neighbor, const std::vector< Point > &reference_points)
Definition: Assembly.C:1620
void initNonlocalCoupling()
Create pair of variables requiring nonlocal jacobian contributions.
Definition: Assembly.C:2643
ConstraintJacobianType
Definition: MooseTypes.h:709
std::map< unsigned int, FEBase * > _holder_fe_face_helper
Each dimension&#39;s helper objects.
Definition: Assembly.h:2471
void setLowerQRule(QBase *qrule, unsigned int dim)
Set the qrule to be used for lower dimensional integration.
Definition: Assembly.C:687
const Elem *const & neighbor() const
Return the neighbor element.
Definition: Assembly.h:423
std::map< unsigned int, std::map< FEType, FEVectorBase * > > _vector_fe_neighbor
Definition: Assembly.h:2501
void cacheJacobianNonlocal(GlobalDataKey)
Takes the values that are currently in _sub_Keg and appends them to the cached values.
Definition: Assembly.C:4084
Class for scalar variables (they are different).
IntRange< T > make_range(T beg, T end)
std::vector< std::unique_ptr< FEBase > > _unique_fe_face_neighbor_helper
Definition: Assembly.h:2324
void resize(unsigned int size)
Change the number of elements the array can store.
Definition: MooseArray.h:213
void computeSinglePointMapAD(const Elem *elem, const std::vector< Real > &qw, unsigned p, FEBase *fe)
compute the finite element reference-physical mapping quantities (such as JxW) with possible dependen...
Definition: Assembly.C:997
void helpersRequestData()
request phi, dphi, xyz, JxW, etc.
Definition: Assembly.C:4801
std::vector< std::pair< MooseVariableFieldBase *, MooseVariableFieldBase * > > _cm_nonlocal_entry
Entries in the coupling matrix for field variables for nonlocal calculations.
Definition: Assembly.h:2292
void addJacobianOffDiagScalar(unsigned int ivar, GlobalDataKey)
Add Jacobians for a scalar variables with all other field variables into the global Jacobian matrices...
Definition: Assembly.C:4456
std::vector< DualReal > _ad_detadx_map
Definition: Assembly.h:2792
void buildLowerDFE(FEType type) const
Build FEs for a lower dimensional element with a type.
Definition: Assembly.C:356
virtual unsigned int size() const override final
unsigned int _current_side
The current side of the selected element (valid only when working with sides)
Definition: Assembly.h:2557
void setCachedJacobian(GlobalDataKey)
Sets previously-cached Jacobian values via SparseMatrix::set() calls.
Definition: Assembly.C:4486
VariablePhiSecond _second_phi
Definition: Assembly.h:2702
std::map< unsigned int, FEBase * > _holder_fe_helper
Each dimension&#39;s helper objects.
Definition: Assembly.h:2359
void prepareVariable(MooseVariableFieldBase *var)
Used for preparing the dense residual and jacobian blocks for one particular variable.
Definition: Assembly.C:2740
const Elem * _current_neighbor_side_elem
The current side element of the ncurrent neighbor element.
Definition: Assembly.h:2569
void reinitElemFaceRef(const Elem *elem, unsigned int elem_side, Real tolerance, const std::vector< Point > *const pts=nullptr, const std::vector< Real > *const weights=nullptr)
Reinitialize FE data for the given element on the given side, optionally with a given set of referenc...
Definition: Assembly.C:2015
void copyFaceShapes(MooseVariableField< T > &v)
Definition: Assembly.C:3028
std::vector< dof_id_type > _extra_elem_ids
Extra element IDs.
Definition: Assembly.h:2490
void derivInsert(NumberArray< N, Real > &derivs, dof_id_type index, Real value)
Moose::CoordinateSystemType getCoordSystem(SubdomainID sid) const
Definition: SubProblem.C:1235
void clearCachedQRules()
Set the cached quadrature rules to nullptr.
Definition: Assembly.C:723
void addResidualNeighbor(GlobalDataKey, const std::vector< VectorTag > &vector_tags)
Add local neighbor residuals of all field variables for a set of tags onto the global residual vector...
Definition: Assembly.C:3343
bool _current_side_volume_computed
Boolean to indicate whether current element side volumes has been computed.
Definition: Assembly.h:2581
virtual bool isScalarVariable(unsigned int var_name) const
Definition: SystemBase.C:841
std::map< FEType, ADTemplateVariablePhiGradient< RealVectorValue > > _ad_vector_grad_phi_data_face
Definition: Assembly.h:2737
std::vector< VectorValue< DualReal > > _ad_d2xyzdeta2_map
Definition: Assembly.h:2785
Moose::VectorTagType _type
The type of the vector tag.
Definition: VectorTag.h:51
void jacobianBlockNeighborUsed(TagID tag, unsigned int ivar, unsigned int jvar, bool used)
Sets whether or not neighbor Jacobian coupling between ivar and jvar is used to the value used...
Definition: Assembly.h:2210
std::unique_ptr< ArbitraryQuadrature > arbitrary_face
area/face (meshdim-1) custom points quadrature rule
Definition: Assembly.h:2403
Eigen::Matrix< Real, Eigen::Dynamic, 1 > RealEigenVector
Definition: MooseTypes.h:138
virtual const std::vector< dof_id_type > & dofIndicesLower() const =0
Get dof indices for the current lower dimensional element (this is meaningful when performing mortar ...
void prepareBlock(unsigned int ivar, unsigned jvar, const std::vector< dof_id_type > &dof_indices)
Definition: Assembly.C:2890
std::map< unsigned int, std::map< FEType, FEBase * > > _fe_face_neighbor
Definition: Assembly.h:2500
void addJacobianNeighbor(GlobalDataKey)
Add ElementNeighbor, NeighborElement, and NeighborNeighbor portions of the Jacobian for compute objec...
Definition: Assembly.C:3901
std::vector< std::vector< std::vector< unsigned char > > > _jacobian_block_lower_used
Flag that indicates if the jacobian block for the lower dimensional element was used.
Definition: Assembly.h:2299
MOOSE now contains C++17 code, so give a reasonable error message stating what the user can do to add...
VectorVariablePhiDivergence _div_phi
Definition: Assembly.h:2714
void cacheJacobianBlock(DenseMatrix< Number > &jac_block, const std::vector< dof_id_type > &idof_indices, const std::vector< dof_id_type > &jdof_indices, Real scaling_factor, LocalDataKey, TagID tag)
Cache a local Jacobian block with the provided rows (idof_indices) and columns (jdof_indices) for eve...
Definition: Assembly.C:3743
MooseVariableFieldBase & getVariable(THREAD_ID tid, const std::string &var_name) const
Gets a reference to a variable of with specified name.
Definition: SystemBase.C:86
NEDELEC_ONE
bool _custom_mortar_qrule
Flag specifying whether a custom quadrature rule has been specified for mortar segment mesh...
Definition: Assembly.h:2541
const unsigned int & side() const
Returns the current side.
Definition: Assembly.h:399
void computeCurrentElemVolume()
Definition: Assembly.C:1742
void cacheJacobianBlockNonzero(DenseMatrix< Number > &jac_block, const MooseVariableBase &ivar, const MooseVariableBase &jvar, const std::vector< dof_id_type > &idof_indices, const std::vector< dof_id_type > &jdof_indices, TagID tag)
Push non-zeros of a local Jacobian block with proper scaling into cache for a certain tag...
Definition: Assembly.C:3685
Real _current_neighbor_lower_d_elem_volume
The current neighboring lower dimensional element volume.
Definition: Assembly.h:2594
bool _need_neighbor_lower_d_elem_volume
Whether we need to compute the neighboring lower dimensional element volume.
Definition: Assembly.h:2592
MooseArray< Point > _current_q_points
The current list of quadrature points.
Definition: Assembly.h:2371
bool _user_added_fe_of_helper_type
Whether user code requested a FEType the same as our _helper_type.
Definition: Assembly.h:2314
Moose::CoordinateSystemType _coord_type
The coordinate system.
Definition: Assembly.h:2375
void cacheJacobianMortar(GlobalDataKey)
Cache all portions of the Jacobian, e.g.
Definition: Assembly.C:4144
std::unique_ptr< ArbitraryQuadrature > neighbor
area/face (meshdim-1) custom points quadrature rule for DG
Definition: Assembly.h:2405
void addJacobianBlock(SparseMatrix< Number > &jacobian, unsigned int ivar, unsigned int jvar, const DofMap &dof_map, std::vector< dof_id_type > &dof_indices, GlobalDataKey, TagID tag)
Adds element matrix for ivar rows and jvar columns to the global Jacobian matrix. ...
Definition: Assembly.C:4237
unsigned int n() const
void buildVectorFaceNeighborFE(FEType type) const
Build Vector FEs for a neighbor face with a type.
Definition: Assembly.C:542
void buildVectorDualLowerDFE(FEType type) const
Definition: Assembly.C:426
void bumpVolumeQRuleOrder(Order volume_order, SubdomainID block)
Increases the element/volume quadrature order for the specified mesh block if and only if the current...
Definition: Assembly.C:572
Storage for all of the information pretaining to a vector tag.
Definition: VectorTag.h:15
const Node *const & node() const
Returns the reference to the node.
Definition: Assembly.h:495
std::vector< std::vector< std::vector< unsigned char > > > _jacobian_block_neighbor_used
Flag that indicates if the jacobian block for neighbor was used.
Definition: Assembly.h:2297
std::map< unsigned int, FEBase * > _holder_fe_lower_helper
helper object for transforming coordinates for lower dimensional element quadrature points ...
Definition: Assembly.h:2513
void computeADFace(const Elem &elem, const unsigned int side)
compute AD things on an element face
Definition: Assembly.C:2107
std::map< FEType, std::unique_ptr< VectorFEShapeData > > _vector_fe_shape_data_neighbor
Definition: Assembly.h:2728
std::vector< DualReal > _ad_detady_map
Definition: Assembly.h:2793
void setResidual(NumericVector< Number > &residual, GlobalDataKey, const VectorTag &vector_tag)
Sets local residuals of all field variables to the global residual vector for a tag.
Definition: Assembly.C:3544
std::vector< std::vector< dof_id_type > > _cached_jacobian_cols
Column where the corresponding cached value should go.
Definition: Assembly.h:2763
void addCachedJacobian(GlobalDataKey)
Adds the values that have been cached by calling cacheJacobian() and or cacheJacobianNeighbor() to th...
Definition: Assembly.C:3811
void addJacobianBlockTags(SparseMatrix< Number > &jacobian, unsigned int ivar, unsigned int jvar, const DofMap &dof_map, std::vector< dof_id_type > &dof_indices, GlobalDataKey, const std::set< TagID > &tags)
Add element matrix for ivar rows and jvar columns to the global Jacobian matrix for given tags...
Definition: Assembly.C:4224
DenseMatrix sub_matrix(unsigned int row_id, unsigned int row_size, unsigned int col_id, unsigned int col_size) const
MooseArray< Point > _current_q_points_face
The current quadrature points on a face.
Definition: Assembly.h:2479
void cacheResidualBlock(std::vector< Real > &cached_residual_values, std::vector< dof_id_type > &cached_residual_rows, DenseVector< Number > &res_block, const std::vector< dof_id_type > &dof_indices, const std::vector< Real > &scaling_factor, bool is_nodal)
Push a local residual block with proper scaling into cache.
Definition: Assembly.C:3261
void prepareBlockNonlocal(unsigned int ivar, unsigned jvar, const std::vector< dof_id_type > &idof_indices, const std::vector< dof_id_type > &jdof_indices)
Definition: Assembly.C:2915
virtual NumericVector< Number > & getVector(const std::string &name)
Get a raw NumericVector by name.
Definition: SystemBase.C:889
void bumpAllQRuleOrder(Order order, SubdomainID block)
Increases the element/volume and face/area quadrature orders for the specified mesh block if and only...
Definition: Assembly.C:595
const VariablePhiSecond & secondPhiFaceNeighbor(const MooseVariableField< Real > &) const
Definition: Assembly.h:1317
const Elem * _current_side_elem
The current "element" making up the side we are currently on.
Definition: Assembly.h:2559
bool _block_diagonal_matrix
Will be true if our preconditioning matrix is a block-diagonal matrix. Which means that we can take s...
Definition: Assembly.h:2768
MooseArray< DualReal > _ad_coord
The AD version of the current coordinate transformation coefficients.
Definition: Assembly.h:2379
bool _need_JxW_neighbor
Flag to indicate that JxW_neighbor is needed.
Definition: Assembly.h:2520
std::map< FEType, bool > _need_curl
Definition: Assembly.h:2820
virtual const VectorTag & getVectorTag(const TagID tag_id) const
Get a VectorTag from a TagID.
Definition: SubProblem.C:139
void copyNeighborShapes(MooseVariableField< T > &v)
Definition: Assembly.C:3065
void cacheJacobianCoupledVarPair(const MooseVariableBase &ivar, const MooseVariableBase &jvar)
Caches element matrix for ivar rows and jvar columns.
Definition: Assembly.C:4068
QMONOMIAL
MooseArray< Point > _current_q_points_face_neighbor
The current quadrature points on the neighbor face.
Definition: Assembly.h:2518
VectorVariablePhiCurl _vector_curl_phi_face
Definition: Assembly.h:2682
Key structure for APIs adding/caching local element residuals/Jacobians.
Definition: Assembly.h:812
SubdomainID _current_subdomain_id
The current subdomain ID.
Definition: Assembly.h:2551
virtual numeric_index_type n() const =0
ElemSideBuilder _current_side_elem_builder
In place side element builder for _current_side_elem.
Definition: Assembly.h:2827
QBase * _current_qrule_face
quadrature rule used on faces
Definition: Assembly.h:2475
std::map< FEType, FEVectorBase * > _current_vector_fe_neighbor
The "neighbor" vector fe object that matches the current elem.
Definition: Assembly.h:2348
void clearCachedResiduals(GlobalDataKey)
Clears all of the residuals in _cached_residual_rows and _cached_residual_values. ...
Definition: Assembly.C:3496
virtual const FieldVariablePhiGradient & gradPhiFace() const =0
Return the gradients of the variable&#39;s shape functions on an element face.
unsigned int THREAD_ID
Definition: MooseTypes.h:198
const Node * _current_neighbor_node
The current neighboring node we are working with.
Definition: Assembly.h:2577
void clearCachedJacobian()
Clear any currently cached jacobians.
Definition: Assembly.C:4516
uint8_t dof_id_type
const VariablePhiGradient & gradPhiFace() const
Definition: Assembly.h:1286
std::vector< std::vector< std::vector< DenseMatrix< Number > > > > _sub_Knl
dprimary/dlower (or dneighbor/dlower)
Definition: Assembly.h:2650
std::vector< VectorValue< DualReal > > _ad_dxyzdxi_map
AD quantities.
Definition: Assembly.h:2780
MooseVariableField< T > & getActualFieldVariable(THREAD_ID tid, const std::string &var_name)
Returns a field variable pointer - this includes finite volume variables.
Definition: SystemBase.C:114
void reinitFEFace(const Elem *elem, unsigned int side)
Just an internal helper function to reinit the face FE objects.
Definition: Assembly.C:1261
void computeFaceMap(const Elem &elem, const unsigned int side, const std::vector< Real > &qw)
Definition: Assembly.C:1341
void reinitDual(const Elem *elem, const std::vector< Point > &pts, const std::vector< Real > &JxW)
Reintialize dual basis coefficients based on a customized quadrature rule.
Definition: Assembly.C:2264
Key structure for APIs manipulating global vectors/matrices.
Definition: Assembly.h:794