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