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