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  using std::sqrt;
1172  _ad_jac[p] = sqrt(det);
1173 
1174  _ad_JxW[p] = _ad_jac[p] * qw[p];
1175 
1176  const auto g11inv = g22 * inv_det;
1177  const auto g12inv = -g12 * inv_det;
1178  const auto g21inv = -g21 * inv_det;
1179  const auto g22inv = g11 * inv_det;
1180 
1181  _ad_dxidx_map[p] = g11inv * dx_dxi + g12inv * dx_deta;
1182  _ad_dxidy_map[p] = g11inv * dy_dxi + g12inv * dy_deta;
1183  _ad_dxidz_map[p] = g11inv * dz_dxi + g12inv * dz_deta;
1184 
1185  _ad_detadx_map[p] = g21inv * dx_dxi + g22inv * dx_deta;
1186  _ad_detady_map[p] = g21inv * dy_dxi + g22inv * dy_deta;
1187  _ad_detadz_map[p] = g21inv * dz_dxi + g22inv * dz_deta;
1188 
1189  break;
1190  }
1191 
1192  case 3:
1193  {
1194  if (_calculate_xyz)
1195  _ad_q_points[p].zero();
1196  _ad_dxyzdxi_map[p].zero();
1197  _ad_dxyzdeta_map[p].zero();
1198  _ad_dxyzdzeta_map[p].zero();
1199 
1200  for (std::size_t i = 0; i < num_shapes; i++)
1201  {
1202  libmesh_assert(elem_nodes[i]);
1203  const Node & node = *elem_nodes[i];
1204  libMesh::VectorValue<ADReal> elem_point = node;
1205  if (do_derivatives)
1206  for (const auto & [disp_num, direction] : _disp_numbers_and_directions)
1207  if (node.n_dofs(sys_num, disp_num))
1209  elem_point(direction).derivatives(), node.dof_number(sys_num, disp_num, 0), 1.);
1210 
1211  _ad_dxyzdxi_map[p].add_scaled(elem_point, dphidxi_map[i][p]);
1212  _ad_dxyzdeta_map[p].add_scaled(elem_point, dphideta_map[i][p]);
1213  _ad_dxyzdzeta_map[p].add_scaled(elem_point, dphidzeta_map[i][p]);
1214 
1215  if (_calculate_xyz)
1216  _ad_q_points[p].add_scaled(elem_point, phi_map[i][p]);
1217  }
1218 
1219  const auto &dx_dxi = _ad_dxyzdxi_map[p](0), &dy_dxi = _ad_dxyzdxi_map[p](1),
1220  &dz_dxi = _ad_dxyzdxi_map[p](2), &dx_deta = _ad_dxyzdeta_map[p](0),
1221  &dy_deta = _ad_dxyzdeta_map[p](1), &dz_deta = _ad_dxyzdeta_map[p](2),
1222  &dx_dzeta = _ad_dxyzdzeta_map[p](0), &dy_dzeta = _ad_dxyzdzeta_map[p](1),
1223  &dz_dzeta = _ad_dxyzdzeta_map[p](2);
1224 
1225  _ad_jac[p] = (dx_dxi * (dy_deta * dz_dzeta - dz_deta * dy_dzeta) +
1226  dy_dxi * (dz_deta * dx_dzeta - dx_deta * dz_dzeta) +
1227  dz_dxi * (dx_deta * dy_dzeta - dy_deta * dx_dzeta));
1228 
1229  if (_ad_jac[p].value() <= -TOLERANCE * TOLERANCE)
1230  {
1231  static bool failing = false;
1232  if (!failing)
1233  {
1234  failing = true;
1236  libmesh_error_msg("ERROR: negative Jacobian " << _ad_jac[p].value() << " at point index "
1237  << p << " in element " << elem->id());
1238  }
1239  else
1240  return;
1241  }
1242 
1243  _ad_JxW[p] = _ad_jac[p] * qw[p];
1244 
1245  const auto inv_jac = 1. / _ad_jac[p];
1246 
1247  _ad_dxidx_map[p] = (dy_deta * dz_dzeta - dz_deta * dy_dzeta) * inv_jac;
1248  _ad_dxidy_map[p] = (dz_deta * dx_dzeta - dx_deta * dz_dzeta) * inv_jac;
1249  _ad_dxidz_map[p] = (dx_deta * dy_dzeta - dy_deta * dx_dzeta) * inv_jac;
1250 
1251  _ad_detadx_map[p] = (dz_dxi * dy_dzeta - dy_dxi * dz_dzeta) * inv_jac;
1252  _ad_detady_map[p] = (dx_dxi * dz_dzeta - dz_dxi * dx_dzeta) * inv_jac;
1253  _ad_detadz_map[p] = (dy_dxi * dx_dzeta - dx_dxi * dy_dzeta) * inv_jac;
1254 
1255  _ad_dzetadx_map[p] = (dy_dxi * dz_deta - dz_dxi * dy_deta) * inv_jac;
1256  _ad_dzetady_map[p] = (dz_dxi * dx_deta - dx_dxi * dz_deta) * inv_jac;
1257  _ad_dzetadz_map[p] = (dx_dxi * dy_deta - dy_dxi * dx_deta) * inv_jac;
1258 
1259  break;
1260  }
1261 
1262  default:
1263  libmesh_error_msg("Invalid dim = " << dim);
1264  }
1265 }
1266 
1267 void
1268 Assembly::reinitFEFace(const Elem * elem, unsigned int side)
1269 {
1270  unsigned int dim = elem->dim();
1271 
1272  for (const auto & it : _fe_face[dim])
1273  {
1274  FEBase & fe_face = *it.second;
1275  const FEType & fe_type = it.first;
1276  FEShapeData & fesd = *_fe_shape_data_face[fe_type];
1277  fe_face.reinit(elem, side);
1278  _current_fe_face[fe_type] = &fe_face;
1279 
1280  fesd._phi.shallowCopy(const_cast<std::vector<std::vector<Real>> &>(fe_face.get_phi()));
1281  fesd._grad_phi.shallowCopy(
1282  const_cast<std::vector<std::vector<VectorValue<Real>>> &>(fe_face.get_dphi()));
1283  if (_need_second_derivative.count(fe_type))
1284  fesd._second_phi.shallowCopy(
1285  const_cast<std::vector<std::vector<TensorValue<Real>>> &>(fe_face.get_d2phi()));
1286  }
1287  for (const auto & it : _vector_fe_face[dim])
1288  {
1289  FEVectorBase & fe_face = *it.second;
1290  const FEType & fe_type = it.first;
1291 
1292  _current_vector_fe_face[fe_type] = &fe_face;
1293 
1294  VectorFEShapeData & fesd = *_vector_fe_shape_data_face[fe_type];
1295 
1296  fe_face.reinit(elem, side);
1297 
1298  fesd._phi.shallowCopy(
1299  const_cast<std::vector<std::vector<VectorValue<Real>>> &>(fe_face.get_phi()));
1300  fesd._grad_phi.shallowCopy(
1301  const_cast<std::vector<std::vector<TensorValue<Real>>> &>(fe_face.get_dphi()));
1302  if (_need_second_derivative.count(fe_type))
1303  fesd._second_phi.shallowCopy(
1304  const_cast<std::vector<std::vector<TypeNTensor<3, Real>>> &>(fe_face.get_d2phi()));
1305  if (_need_curl.count(fe_type))
1306  fesd._curl_phi.shallowCopy(
1307  const_cast<std::vector<std::vector<VectorValue<Real>>> &>(fe_face.get_curl_phi()));
1308  if (_need_face_div.count(fe_type))
1309  fesd._div_phi.shallowCopy(
1310  const_cast<std::vector<std::vector<Real>> &>(fe_face.get_div_phi()));
1311  }
1312  if (!_unique_fe_face_helper.empty())
1313  {
1314  mooseAssert(dim < _unique_fe_face_helper.size(), "We should be in bounds here");
1315  _unique_fe_face_helper[dim]->reinit(elem, side);
1316  }
1317 
1318  // During that last loop the helper objects will have been reinitialized as well
1319  // We need to dig out the q_points and JxW from it.
1321  const_cast<std::vector<Point> &>(_holder_fe_face_helper[dim]->get_xyz()));
1323  const_cast<std::vector<Real> &>(_holder_fe_face_helper[dim]->get_JxW()));
1325  const_cast<std::vector<Point> &>(_holder_fe_face_helper[dim]->get_normals()));
1326 
1327  _mapped_normals.resize(_current_normals.size(), Eigen::Map<RealDIMValue>(nullptr));
1328  for (unsigned int i = 0; i < _current_normals.size(); i++)
1329  // Note: this does NOT do any allocation. It is "reconstructing" the object in place
1330  new (&_mapped_normals[i]) Eigen::Map<RealDIMValue>(const_cast<Real *>(&_current_normals[i](0)));
1331 
1334  const_cast<std::vector<Real> &>(_holder_fe_face_helper[dim]->get_curvatures()));
1335 
1336  computeADFace(*elem, side);
1337 
1338  if (_xfem != nullptr)
1340 
1341  auto n = numExtraElemIntegers();
1342  for (auto i : make_range(n))
1345 }
1346 
1347 void
1348 Assembly::computeFaceMap(const Elem & elem, const unsigned int side, const std::vector<Real> & qw)
1349 {
1350  // Important quantities calculated by this method:
1351  // - _ad_JxW_face
1352  // - _ad_q_points_face
1353  // - _ad_normals
1354  // - _ad_curvatures
1355 
1356  const Elem & side_elem = _compute_face_map_side_elem_builder(elem, side);
1357  const auto dim = elem.dim();
1358  const auto n_qp = qw.size();
1359  const auto & dpsidxi_map = _holder_fe_face_helper[dim]->get_fe_map().get_dpsidxi();
1360  const auto & dpsideta_map = _holder_fe_face_helper[dim]->get_fe_map().get_dpsideta();
1361  const auto & psi_map = _holder_fe_face_helper[dim]->get_fe_map().get_psi();
1362  std::vector<std::vector<Real>> const * d2psidxi2_map = nullptr;
1363  std::vector<std::vector<Real>> const * d2psidxideta_map = nullptr;
1364  std::vector<std::vector<Real>> const * d2psideta2_map = nullptr;
1365  const auto sys_num = _sys.number();
1366  const bool do_derivatives = ADReal::do_derivatives && sys_num == _subproblem.currentNlSysNum();
1367 
1369  {
1370  d2psidxi2_map = &_holder_fe_face_helper[dim]->get_fe_map().get_d2psidxi2();
1371  d2psidxideta_map = &_holder_fe_face_helper[dim]->get_fe_map().get_d2psidxideta();
1372  d2psideta2_map = &_holder_fe_face_helper[dim]->get_fe_map().get_d2psideta2();
1373  }
1374 
1375  switch (dim)
1376  {
1377  case 1:
1378  {
1379  if (!n_qp)
1380  break;
1381 
1382  if (side_elem.node_id(0) == elem.node_id(0))
1383  _ad_normals[0] = Point(-1.);
1384  else
1385  _ad_normals[0] = Point(1.);
1386 
1387  VectorValue<ADReal> side_point;
1388  if (_calculate_face_xyz)
1389  {
1390  const Node & node = side_elem.node_ref(0);
1391  side_point = node;
1392 
1393  if (do_derivatives)
1394  for (const auto & [disp_num, direction] : _disp_numbers_and_directions)
1396  side_point(direction).derivatives(), node.dof_number(sys_num, disp_num, 0), 1.);
1397  }
1398 
1399  for (const auto p : make_range(n_qp))
1400  {
1401  if (_calculate_face_xyz)
1402  {
1403  _ad_q_points_face[p].zero();
1404  _ad_q_points_face[p].add_scaled(side_point, psi_map[0][p]);
1405  }
1406 
1407  _ad_normals[p] = _ad_normals[0];
1408  _ad_JxW_face[p] = 1.0 * qw[p];
1409  }
1410 
1411  break;
1412  }
1413 
1414  case 2:
1415  {
1416  _ad_dxyzdxi_map.resize(n_qp);
1418  _ad_d2xyzdxi2_map.resize(n_qp);
1419 
1420  for (const auto p : make_range(n_qp))
1421  _ad_dxyzdxi_map[p].zero();
1422  if (_calculate_face_xyz)
1423  for (const auto p : make_range(n_qp))
1424  _ad_q_points_face[p].zero();
1426  for (const auto p : make_range(n_qp))
1427  _ad_d2xyzdxi2_map[p].zero();
1428 
1429  const auto n_mapping_shape_functions =
1430  FE<2, LAGRANGE>::n_dofs(&side_elem, side_elem.default_order());
1431 
1432  for (unsigned int i = 0; i < n_mapping_shape_functions; i++)
1433  {
1434  const Node & node = side_elem.node_ref(i);
1435  VectorValue<ADReal> side_point = node;
1436 
1437  if (do_derivatives)
1438  for (const auto & [disp_num, direction] : _disp_numbers_and_directions)
1440  side_point(direction).derivatives(), node.dof_number(sys_num, disp_num, 0), 1.);
1441 
1442  for (const auto p : make_range(n_qp))
1443  _ad_dxyzdxi_map[p].add_scaled(side_point, dpsidxi_map[i][p]);
1444  if (_calculate_face_xyz)
1445  for (const auto p : make_range(n_qp))
1446  _ad_q_points_face[p].add_scaled(side_point, psi_map[i][p]);
1448  for (const auto p : make_range(n_qp))
1449  _ad_d2xyzdxi2_map[p].add_scaled(side_point, (*d2psidxi2_map)[i][p]);
1450  }
1451 
1452  for (const auto p : make_range(n_qp))
1453  {
1454  _ad_normals[p] =
1455  (VectorValue<ADReal>(_ad_dxyzdxi_map[p](1), -_ad_dxyzdxi_map[p](0), 0.)).unit();
1456  const auto the_jac = _ad_dxyzdxi_map[p].norm();
1457  _ad_JxW_face[p] = the_jac * qw[p];
1459  {
1460  const auto numerator = _ad_d2xyzdxi2_map[p] * _ad_normals[p];
1461  const auto denominator = _ad_dxyzdxi_map[p].norm_sq();
1462  libmesh_assert_not_equal_to(denominator, 0);
1463  _ad_curvatures[p] = numerator / denominator;
1464  }
1465  }
1466 
1467  break;
1468  }
1469 
1470  case 3:
1471  {
1472  _ad_dxyzdxi_map.resize(n_qp);
1473  _ad_dxyzdeta_map.resize(n_qp);
1475  {
1476  _ad_d2xyzdxi2_map.resize(n_qp);
1477  _ad_d2xyzdxideta_map.resize(n_qp);
1478  _ad_d2xyzdeta2_map.resize(n_qp);
1479  }
1480 
1481  for (const auto p : make_range(n_qp))
1482  {
1483  _ad_dxyzdxi_map[p].zero();
1484  _ad_dxyzdeta_map[p].zero();
1485  }
1486  if (_calculate_face_xyz)
1487  for (const auto p : make_range(n_qp))
1488  _ad_q_points_face[p].zero();
1490  for (const auto p : make_range(n_qp))
1491  {
1492  _ad_d2xyzdxi2_map[p].zero();
1493  _ad_d2xyzdxideta_map[p].zero();
1494  _ad_d2xyzdeta2_map[p].zero();
1495  }
1496 
1497  const unsigned int n_mapping_shape_functions =
1498  FE<3, LAGRANGE>::n_dofs(&side_elem, side_elem.default_order());
1499 
1500  for (unsigned int i = 0; i < n_mapping_shape_functions; i++)
1501  {
1502  const Node & node = side_elem.node_ref(i);
1503  VectorValue<ADReal> side_point = node;
1504 
1505  if (do_derivatives)
1506  for (const auto & [disp_num, direction] : _disp_numbers_and_directions)
1508  side_point(direction).derivatives(), node.dof_number(sys_num, disp_num, 0), 1.);
1509 
1510  for (const auto p : make_range(n_qp))
1511  {
1512  _ad_dxyzdxi_map[p].add_scaled(side_point, dpsidxi_map[i][p]);
1513  _ad_dxyzdeta_map[p].add_scaled(side_point, dpsideta_map[i][p]);
1514  }
1515  if (_calculate_face_xyz)
1516  for (const auto p : make_range(n_qp))
1517  _ad_q_points_face[p].add_scaled(side_point, psi_map[i][p]);
1519  for (const auto p : make_range(n_qp))
1520  {
1521  _ad_d2xyzdxi2_map[p].add_scaled(side_point, (*d2psidxi2_map)[i][p]);
1522  _ad_d2xyzdxideta_map[p].add_scaled(side_point, (*d2psidxideta_map)[i][p]);
1523  _ad_d2xyzdeta2_map[p].add_scaled(side_point, (*d2psideta2_map)[i][p]);
1524  }
1525  }
1526 
1527  for (const auto p : make_range(n_qp))
1528  {
1529  _ad_normals[p] = _ad_dxyzdxi_map[p].cross(_ad_dxyzdeta_map[p]).unit();
1530 
1531  const auto &dxdxi = _ad_dxyzdxi_map[p](0), &dxdeta = _ad_dxyzdeta_map[p](0),
1532  &dydxi = _ad_dxyzdxi_map[p](1), &dydeta = _ad_dxyzdeta_map[p](1),
1533  &dzdxi = _ad_dxyzdxi_map[p](2), &dzdeta = _ad_dxyzdeta_map[p](2);
1534 
1535  const auto g11 = (dxdxi * dxdxi + dydxi * dydxi + dzdxi * dzdxi);
1536 
1537  const auto g12 = (dxdxi * dxdeta + dydxi * dydeta + dzdxi * dzdeta);
1538 
1539  const auto & g21 = g12;
1540 
1541  const auto g22 = (dxdeta * dxdeta + dydeta * dydeta + dzdeta * dzdeta);
1542 
1543  using std::sqrt;
1544  const auto the_jac = sqrt(g11 * g22 - g12 * g21);
1545 
1546  _ad_JxW_face[p] = the_jac * qw[p];
1547 
1549  {
1550  const auto L = -_ad_d2xyzdxi2_map[p] * _ad_normals[p];
1551  const auto M = -_ad_d2xyzdxideta_map[p] * _ad_normals[p];
1552  const auto N = -_ad_d2xyzdeta2_map[p] * _ad_normals[p];
1553  const auto E = _ad_dxyzdxi_map[p].norm_sq();
1554  const auto F = _ad_dxyzdxi_map[p] * _ad_dxyzdeta_map[p];
1555  const auto G = _ad_dxyzdeta_map[p].norm_sq();
1556 
1557  const auto numerator = E * N - 2. * F * M + G * L;
1558  const auto denominator = E * G - F * F;
1559  libmesh_assert_not_equal_to(denominator, 0.);
1560  _ad_curvatures[p] = 0.5 * numerator / denominator;
1561  }
1562  }
1563 
1564  break;
1565  }
1566 
1567  default:
1568  mooseError("Invalid dimension dim = ", dim);
1569  }
1570 }
1571 
1572 void
1573 Assembly::reinitFEFaceNeighbor(const Elem * neighbor, const std::vector<Point> & reference_points)
1574 {
1575  unsigned int neighbor_dim = neighbor->dim();
1576 
1577  // reinit neighbor face
1578  for (const auto & it : _fe_face_neighbor[neighbor_dim])
1579  {
1580  FEBase & fe_face_neighbor = *it.second;
1581  FEType fe_type = it.first;
1582  FEShapeData & fesd = *_fe_shape_data_face_neighbor[fe_type];
1583 
1584  fe_face_neighbor.reinit(neighbor, &reference_points);
1585 
1586  _current_fe_face_neighbor[fe_type] = &fe_face_neighbor;
1587 
1588  fesd._phi.shallowCopy(const_cast<std::vector<std::vector<Real>> &>(fe_face_neighbor.get_phi()));
1589  fesd._grad_phi.shallowCopy(
1590  const_cast<std::vector<std::vector<RealGradient>> &>(fe_face_neighbor.get_dphi()));
1591  if (_need_second_derivative_neighbor.count(fe_type))
1592  fesd._second_phi.shallowCopy(
1593  const_cast<std::vector<std::vector<TensorValue<Real>>> &>(fe_face_neighbor.get_d2phi()));
1594  }
1595  for (const auto & it : _vector_fe_face_neighbor[neighbor_dim])
1596  {
1597  FEVectorBase & fe_face_neighbor = *it.second;
1598  const FEType & fe_type = it.first;
1599 
1600  _current_vector_fe_face_neighbor[fe_type] = &fe_face_neighbor;
1601 
1603 
1604  fe_face_neighbor.reinit(neighbor, &reference_points);
1605 
1606  fesd._phi.shallowCopy(
1607  const_cast<std::vector<std::vector<VectorValue<Real>>> &>(fe_face_neighbor.get_phi()));
1608  fesd._grad_phi.shallowCopy(
1609  const_cast<std::vector<std::vector<TensorValue<Real>>> &>(fe_face_neighbor.get_dphi()));
1610  if (_need_second_derivative.count(fe_type))
1611  fesd._second_phi.shallowCopy(const_cast<std::vector<std::vector<TypeNTensor<3, Real>>> &>(
1612  fe_face_neighbor.get_d2phi()));
1613  if (_need_curl.count(fe_type))
1614  fesd._curl_phi.shallowCopy(const_cast<std::vector<std::vector<VectorValue<Real>>> &>(
1615  fe_face_neighbor.get_curl_phi()));
1616  if (_need_face_neighbor_div.count(fe_type))
1617  fesd._div_phi.shallowCopy(
1618  const_cast<std::vector<std::vector<Real>> &>(fe_face_neighbor.get_div_phi()));
1619  }
1620  if (!_unique_fe_face_neighbor_helper.empty())
1621  {
1622  mooseAssert(neighbor_dim < _unique_fe_face_neighbor_helper.size(),
1623  "We should be in bounds here");
1624  _unique_fe_face_neighbor_helper[neighbor_dim]->reinit(neighbor, &reference_points);
1625  }
1626 
1628  const_cast<std::vector<Point> &>(_holder_fe_face_neighbor_helper[neighbor_dim]->get_xyz()));
1629 }
1630 
1631 void
1632 Assembly::reinitFENeighbor(const Elem * neighbor, const std::vector<Point> & reference_points)
1633 {
1634  unsigned int neighbor_dim = neighbor->dim();
1635 
1636  // reinit neighbor face
1637  for (const auto & it : _fe_neighbor[neighbor_dim])
1638  {
1639  FEBase & fe_neighbor = *it.second;
1640  FEType fe_type = it.first;
1641  FEShapeData & fesd = *_fe_shape_data_neighbor[fe_type];
1642 
1643  fe_neighbor.reinit(neighbor, &reference_points);
1644 
1645  _current_fe_neighbor[fe_type] = &fe_neighbor;
1646 
1647  fesd._phi.shallowCopy(const_cast<std::vector<std::vector<Real>> &>(fe_neighbor.get_phi()));
1648  fesd._grad_phi.shallowCopy(
1649  const_cast<std::vector<std::vector<RealGradient>> &>(fe_neighbor.get_dphi()));
1650  if (_need_second_derivative_neighbor.count(fe_type))
1651  fesd._second_phi.shallowCopy(
1652  const_cast<std::vector<std::vector<TensorValue<Real>>> &>(fe_neighbor.get_d2phi()));
1653  }
1654  for (const auto & it : _vector_fe_neighbor[neighbor_dim])
1655  {
1656  FEVectorBase & fe_neighbor = *it.second;
1657  const FEType & fe_type = it.first;
1658 
1659  _current_vector_fe_neighbor[fe_type] = &fe_neighbor;
1660 
1662 
1663  fe_neighbor.reinit(neighbor, &reference_points);
1664 
1665  fesd._phi.shallowCopy(
1666  const_cast<std::vector<std::vector<VectorValue<Real>>> &>(fe_neighbor.get_phi()));
1667  fesd._grad_phi.shallowCopy(
1668  const_cast<std::vector<std::vector<TensorValue<Real>>> &>(fe_neighbor.get_dphi()));
1669  if (_need_second_derivative.count(fe_type))
1670  fesd._second_phi.shallowCopy(
1671  const_cast<std::vector<std::vector<TypeNTensor<3, Real>>> &>(fe_neighbor.get_d2phi()));
1672  if (_need_curl.count(fe_type))
1673  fesd._curl_phi.shallowCopy(
1674  const_cast<std::vector<std::vector<VectorValue<Real>>> &>(fe_neighbor.get_curl_phi()));
1675  if (_need_neighbor_div.count(fe_type))
1676  fesd._div_phi.shallowCopy(
1677  const_cast<std::vector<std::vector<Real>> &>(fe_neighbor.get_div_phi()));
1678  }
1679  if (!_unique_fe_neighbor_helper.empty())
1680  {
1681  mooseAssert(neighbor_dim < _unique_fe_neighbor_helper.size(), "We should be in bounds here");
1682  _unique_fe_neighbor_helper[neighbor_dim]->reinit(neighbor, &reference_points);
1683  }
1684 }
1685 
1686 void
1687 Assembly::reinitNeighbor(const Elem * neighbor, const std::vector<Point> & reference_points)
1688 {
1689  unsigned int neighbor_dim = neighbor->dim();
1691  "Neighbor subdomain ID has not been correctly set");
1692 
1693  ArbitraryQuadrature * neighbor_rule =
1694  qrules(neighbor_dim, _current_neighbor_subdomain_id).neighbor.get();
1695  neighbor_rule->setPoints(reference_points);
1696  setNeighborQRule(neighbor_rule, neighbor_dim);
1697 
1700  "current neighbor subdomain has been set incorrectly");
1701 
1702  // Calculate the volume of the neighbor
1704  {
1705  unsigned int dim = neighbor->dim();
1707  QBase * qrule = qrules(dim).vol.get();
1708 
1709  fe.attach_quadrature_rule(qrule);
1710  fe.reinit(neighbor);
1711 
1712  const std::vector<Real> & JxW = fe.get_JxW();
1713  MooseArray<Point> q_points;
1714  q_points.shallowCopy(const_cast<std::vector<Point> &>(fe.get_xyz()));
1715 
1717 
1719  for (unsigned int qp = 0; qp < qrule->n_points(); qp++)
1721  }
1722 
1723  auto n = numExtraElemIntegers();
1724  for (auto i : make_range(n))
1727 }
1728 
1729 template <typename Points, typename Coords>
1730 void
1732  const Points & q_points,
1733  Coords & coord,
1734  SubdomainID sub_id)
1735 {
1736 
1737  mooseAssert(qrule, "The quadrature rule is null in Assembly::setCoordinateTransformation");
1738  auto n_points = qrule->n_points();
1739  mooseAssert(n_points == q_points.size(),
1740  "The number of points in the quadrature rule doesn't match the number of passed-in "
1741  "points in Assembly::setCoordinateTransformation");
1742 
1743  // Make sure to honor the name of this method and set the _coord_type member because users may
1744  // make use of the const Moose::CoordinateSystem & coordTransformation() { return _coord_type; }
1745  // API. MaterialBase for example uses it
1747 
1748  coord.resize(n_points);
1749  for (unsigned int qp = 0; qp < n_points; qp++)
1750  coordTransformFactor(_subproblem, sub_id, q_points[qp], coord[qp]);
1751 }
1752 
1753 void
1755 {
1757  return;
1758 
1761  if (_calculate_ad_coord)
1764 
1765  _current_elem_volume = 0.;
1766  for (unsigned int qp = 0; qp < _current_qrule->n_points(); qp++)
1768 
1770 }
1771 
1772 void
1774 {
1776  return;
1777 
1780  if (_calculate_ad_coord)
1783 
1784  _current_side_volume = 0.;
1785  for (unsigned int qp = 0; qp < _current_qrule_face->n_points(); qp++)
1787 
1789 }
1790 
1791 void
1792 Assembly::reinitAtPhysical(const Elem * elem, const std::vector<Point> & physical_points)
1793 {
1794  _current_elem = elem;
1795  _current_neighbor_elem = nullptr;
1797  "current subdomain has been set incorrectly");
1799 
1800  FEMap::inverse_map(elem->dim(), elem, physical_points, _temp_reference_points);
1801 
1803 
1804  // Save off the physical points
1805  _current_physical_points = physical_points;
1806 }
1807 
1808 void
1809 Assembly::setVolumeQRule(const Elem * const elem)
1810 {
1811  unsigned int elem_dimension = elem->dim();
1812  _current_qrule_volume = qrules(elem_dimension).vol.get();
1813  // Make sure the qrule is the right one
1815  setVolumeQRule(_current_qrule_volume, elem_dimension);
1816 }
1817 
1818 void
1819 Assembly::reinit(const Elem * elem)
1820 {
1821  _current_elem = elem;
1822  _current_neighbor_elem = nullptr;
1824  "current subdomain has been set incorrectly");
1827  reinitFE(elem);
1828 
1830 }
1831 
1832 void
1833 Assembly::reinit(const Elem * elem, const std::vector<Point> & reference_points)
1834 {
1835  _current_elem = elem;
1836  _current_neighbor_elem = nullptr;
1838  "current subdomain has been set incorrectly");
1840 
1841  unsigned int elem_dimension = _current_elem->dim();
1842 
1843  _current_qrule_arbitrary = qrules(elem_dimension).arbitrary_vol.get();
1844 
1845  // Make sure the qrule is the right one
1847  setVolumeQRule(_current_qrule_arbitrary, elem_dimension);
1848 
1849  _current_qrule_arbitrary->setPoints(reference_points);
1850 
1851  reinitFE(elem);
1852 
1854 }
1855 
1856 void
1858 {
1859  _current_elem = &fi.elem();
1861  _current_side = fi.elemSideID();
1864  "current subdomain has been set incorrectly");
1865 
1868 
1869  prepareResidual();
1870  prepareNeighbor();
1872 
1873  unsigned int dim = _current_elem->dim();
1874  if (_current_qrule_face != qrules(dim).fv_face.get())
1875  {
1876  setFaceQRule(qrules(dim).fv_face.get(), dim);
1877  // The order of the element that is used for initing here doesn't matter since this will just
1878  // be used for constant monomials (which only need a single integration point)
1879  if (dim == 3)
1880  _current_qrule_face->init(QUAD4, /* p_level = */ 0, /* simple_type_only = */ true);
1881  else
1882  _current_qrule_face->init(EDGE2, /* p_level = */ 0, /* simple_type_only = */ true);
1883  }
1884 
1886 
1887  mooseAssert(_current_qrule_face->n_points() == 1,
1888  "Our finite volume quadrature rule should always yield a single point");
1889 
1890  // We've initialized the reference points. Now we need to compute the physical location of the
1891  // quadrature points. We do not do any FE initialization so we cannot simply copy over FE
1892  // results like we do in reinitFEFace. Instead we handle the computation of the physical
1893  // locations manually
1895  const auto & ref_points = _current_qrule_face->get_points();
1896  const auto & ref_point = ref_points[0];
1897  auto physical_point = FEMap::map(_current_side_elem->dim(), _current_side_elem, ref_point);
1898  _current_q_points_face[0] = physical_point;
1899 
1901  {
1903  "current neighbor subdomain has been set incorrectly");
1904  // Now handle the neighbor qrule/qpoints
1905  ArbitraryQuadrature * const neighbor_rule =
1907  // Here we are setting a reference point that is correct for the neighbor *side* element. It
1908  // would be wrong if this reference point is used for a volumetric FE reinit with the neighbor
1909  neighbor_rule->setPoints(ref_points);
1910  setNeighborQRule(neighbor_rule, _current_neighbor_elem->dim());
1912  _current_q_points_face_neighbor[0] = std::move(physical_point);
1913  }
1914 }
1915 
1916 QBase *
1917 Assembly::qruleFace(const Elem * elem, unsigned int side)
1918 {
1919  return qruleFaceHelper<QBase>(elem, side, [](QRules & q) { return q.face.get(); });
1920 }
1921 
1923 Assembly::qruleArbitraryFace(const Elem * elem, unsigned int side)
1924 {
1925  return qruleFaceHelper<ArbitraryQuadrature>(
1926  elem, side, [](QRules & q) { return q.arbitrary_face.get(); });
1927 }
1928 
1929 void
1930 Assembly::setFaceQRule(const Elem * const elem, const unsigned int side)
1931 {
1932  const auto elem_dimension = elem->dim();
1934  auto rule = qruleFace(elem, side);
1935  if (_current_qrule_face != rule)
1936  setFaceQRule(rule, elem_dimension);
1937 }
1938 
1939 void
1940 Assembly::reinit(const Elem * const elem, const unsigned int side)
1941 {
1942  _current_elem = elem;
1943  _current_neighbor_elem = nullptr;
1945  "current subdomain has been set incorrectly");
1946  _current_side = side;
1949 
1951 
1954 
1956 }
1957 
1958 void
1959 Assembly::reinit(const Elem * elem, unsigned int side, const std::vector<Point> & reference_points)
1960 {
1961  _current_elem = elem;
1962  _current_neighbor_elem = nullptr;
1964  "current subdomain has been set incorrectly");
1965  _current_side = side;
1968 
1969  unsigned int elem_dimension = _current_elem->dim();
1970 
1972 
1973  // Make sure the qrule is the right one
1976 
1977  _current_qrule_arbitrary->setPoints(reference_points);
1978 
1980 
1982 
1984 }
1985 
1986 void
1987 Assembly::reinit(const Node * node)
1988 {
1989  _current_node = node;
1990  _current_neighbor_node = NULL;
1991 }
1992 
1993 void
1995  unsigned int side,
1996  const Elem * neighbor,
1997  unsigned int neighbor_side,
1998  const std::vector<Point> * neighbor_reference_points)
1999 {
2000  _current_neighbor_side = neighbor_side;
2001 
2002  reinit(elem, side);
2003 
2004  unsigned int neighbor_dim = neighbor->dim();
2005 
2006  if (neighbor_reference_points)
2007  _current_neighbor_ref_points = *neighbor_reference_points;
2008  else
2009  FEMap::inverse_map(
2011 
2013 
2016 }
2017 
2018 void
2020  unsigned int elem_side,
2021  Real tolerance,
2022  const std::vector<Point> * const pts,
2023  const std::vector<Real> * const weights)
2024 {
2025  _current_elem = elem;
2026 
2027  unsigned int elem_dim = elem->dim();
2028 
2029  // Attach the quadrature rules
2030  if (pts)
2031  {
2032  auto face_rule = qruleArbitraryFace(elem, elem_side);
2033  face_rule->setPoints(*pts);
2034  setFaceQRule(face_rule, elem_dim);
2035  }
2036  else
2037  {
2038  auto rule = qruleFace(elem, elem_side);
2039  if (_current_qrule_face != rule)
2040  setFaceQRule(rule, elem_dim);
2041  }
2042 
2043  // reinit face
2044  for (const auto & it : _fe_face[elem_dim])
2045  {
2046  FEBase & fe_face = *it.second;
2047  FEType fe_type = it.first;
2048  FEShapeData & fesd = *_fe_shape_data_face[fe_type];
2049 
2050  fe_face.reinit(elem, elem_side, tolerance, pts, weights);
2051 
2052  _current_fe_face[fe_type] = &fe_face;
2053 
2054  fesd._phi.shallowCopy(const_cast<std::vector<std::vector<Real>> &>(fe_face.get_phi()));
2055  fesd._grad_phi.shallowCopy(
2056  const_cast<std::vector<std::vector<RealGradient>> &>(fe_face.get_dphi()));
2057  if (_need_second_derivative_neighbor.count(fe_type))
2058  fesd._second_phi.shallowCopy(
2059  const_cast<std::vector<std::vector<TensorValue<Real>>> &>(fe_face.get_d2phi()));
2060  }
2061  for (const auto & it : _vector_fe_face[elem_dim])
2062  {
2063  FEVectorBase & fe_face = *it.second;
2064  const FEType & fe_type = it.first;
2065 
2066  _current_vector_fe_face[fe_type] = &fe_face;
2067 
2068  VectorFEShapeData & fesd = *_vector_fe_shape_data_face[fe_type];
2069 
2070  fe_face.reinit(elem, elem_side, tolerance, pts, weights);
2071 
2072  fesd._phi.shallowCopy(
2073  const_cast<std::vector<std::vector<VectorValue<Real>>> &>(fe_face.get_phi()));
2074  fesd._grad_phi.shallowCopy(
2075  const_cast<std::vector<std::vector<TensorValue<Real>>> &>(fe_face.get_dphi()));
2076  if (_need_second_derivative.count(fe_type))
2077  fesd._second_phi.shallowCopy(
2078  const_cast<std::vector<std::vector<TypeNTensor<3, Real>>> &>(fe_face.get_d2phi()));
2079  if (_need_curl.count(fe_type))
2080  fesd._curl_phi.shallowCopy(
2081  const_cast<std::vector<std::vector<VectorValue<Real>>> &>(fe_face.get_curl_phi()));
2082  if (_need_face_div.count(fe_type))
2083  fesd._div_phi.shallowCopy(
2084  const_cast<std::vector<std::vector<Real>> &>(fe_face.get_div_phi()));
2085  }
2086  if (!_unique_fe_face_helper.empty())
2087  {
2088  mooseAssert(elem_dim < _unique_fe_face_helper.size(), "We should be in bounds here");
2089  _unique_fe_face_helper[elem_dim]->reinit(elem, elem_side, tolerance, pts, weights);
2090  }
2091 
2092  // During that last loop the helper objects will have been reinitialized
2094  const_cast<std::vector<Point> &>(_holder_fe_face_helper[elem_dim]->get_xyz()));
2096  const_cast<std::vector<Point> &>(_holder_fe_face_helper[elem_dim]->get_normals()));
2097  _current_tangents.shallowCopy(const_cast<std::vector<std::vector<Point>> &>(
2098  _holder_fe_face_helper[elem_dim]->get_tangents()));
2099  // Note that if the user did pass in points and not weights to this method, JxW will be garbage
2100  // and should not be used
2102  const_cast<std::vector<Real> &>(_holder_fe_face_helper[elem_dim]->get_JxW()));
2105  const_cast<std::vector<Real> &>(_holder_fe_face_helper[elem_dim]->get_curvatures()));
2106 
2107  computeADFace(*elem, elem_side);
2108 }
2109 
2110 void
2111 Assembly::computeADFace(const Elem & elem, const unsigned int side)
2112 {
2113  const auto dim = elem.dim();
2114 
2115  if (_subproblem.haveADObjects())
2116  {
2117  auto n_qp = _current_qrule_face->n_points();
2118  resizeADMappingObjects(n_qp, dim);
2119  _ad_normals.resize(n_qp);
2120  _ad_JxW_face.resize(n_qp);
2121  if (_calculate_face_xyz)
2122  _ad_q_points_face.resize(n_qp);
2124  _ad_curvatures.resize(n_qp);
2125 
2126  if (_displaced)
2127  {
2128  const auto & qw = _current_qrule_face->get_weights();
2129  computeFaceMap(elem, side, qw);
2130  const std::vector<Real> dummy_qw(n_qp, 1.);
2131 
2132  for (unsigned int qp = 0; qp != n_qp; qp++)
2134  }
2135  else
2136  {
2137  for (unsigned qp = 0; qp < n_qp; ++qp)
2138  {
2139  _ad_JxW_face[qp] = _current_JxW_face[qp];
2140  _ad_normals[qp] = _current_normals[qp];
2141  }
2142  if (_calculate_face_xyz)
2143  for (unsigned qp = 0; qp < n_qp; ++qp)
2146  for (unsigned qp = 0; qp < n_qp; ++qp)
2147  _ad_curvatures[qp] = _curvatures[qp];
2148  }
2149 
2150  for (const auto & it : _fe_face[dim])
2151  {
2152  FEBase & fe = *it.second;
2153  auto fe_type = it.first;
2154  auto num_shapes = FEInterface::n_shape_functions(fe_type, &elem);
2155  auto & grad_phi = _ad_grad_phi_data_face[fe_type];
2156 
2157  grad_phi.resize(num_shapes);
2158  for (decltype(num_shapes) i = 0; i < num_shapes; ++i)
2159  grad_phi[i].resize(n_qp);
2160 
2161  const auto & regular_grad_phi = _fe_shape_data_face[fe_type]->_grad_phi;
2162 
2163  if (_displaced)
2164  computeGradPhiAD(&elem, n_qp, grad_phi, &fe);
2165  else
2166  for (decltype(num_shapes) i = 0; i < num_shapes; ++i)
2167  for (unsigned qp = 0; qp < n_qp; ++qp)
2168  grad_phi[i][qp] = regular_grad_phi[i][qp];
2169  }
2170  for (const auto & it : _vector_fe_face[dim])
2171  {
2172  FEVectorBase & fe = *it.second;
2173  auto fe_type = it.first;
2174  auto num_shapes = FEInterface::n_shape_functions(fe_type, &elem);
2175  auto & grad_phi = _ad_vector_grad_phi_data_face[fe_type];
2176 
2177  grad_phi.resize(num_shapes);
2178  for (decltype(num_shapes) i = 0; i < num_shapes; ++i)
2179  grad_phi[i].resize(n_qp);
2180 
2181  const auto & regular_grad_phi = _vector_fe_shape_data_face[fe_type]->_grad_phi;
2182 
2183  if (_displaced)
2184  computeGradPhiAD(&elem, n_qp, grad_phi, &fe);
2185  else
2186  for (decltype(num_shapes) i = 0; i < num_shapes; ++i)
2187  for (unsigned qp = 0; qp < n_qp; ++qp)
2188  grad_phi[i][qp] = regular_grad_phi[i][qp];
2189  }
2190  }
2191 }
2192 
2193 void
2195  unsigned int neighbor_side,
2196  Real tolerance,
2197  const std::vector<Point> * const pts,
2198  const std::vector<Real> * const weights)
2199 {
2201 
2202  unsigned int neighbor_dim = neighbor->dim();
2203 
2204  ArbitraryQuadrature * neighbor_rule =
2205  qrules(neighbor_dim, neighbor->subdomain_id()).neighbor.get();
2206  neighbor_rule->setPoints(*pts);
2207 
2208  // Attach this quadrature rule to all the _fe_face_neighbor FE objects. This
2209  // has to have garbage quadrature weights but that's ok because we never
2210  // actually use the JxW coming from these FE reinit'd objects, e.g. we use the
2211  // JxW coming from the element face reinit for DGKernels or we use the JxW
2212  // coming from reinit of the mortar segment element in the case of mortar
2213  setNeighborQRule(neighbor_rule, neighbor_dim);
2214 
2215  // reinit neighbor face
2216  for (const auto & it : _fe_face_neighbor[neighbor_dim])
2217  {
2218  FEBase & fe_face_neighbor = *it.second;
2219  FEType fe_type = it.first;
2220  FEShapeData & fesd = *_fe_shape_data_face_neighbor[fe_type];
2221 
2222  fe_face_neighbor.reinit(neighbor, neighbor_side, tolerance, pts, weights);
2223 
2224  _current_fe_face_neighbor[fe_type] = &fe_face_neighbor;
2225 
2226  fesd._phi.shallowCopy(const_cast<std::vector<std::vector<Real>> &>(fe_face_neighbor.get_phi()));
2227  fesd._grad_phi.shallowCopy(
2228  const_cast<std::vector<std::vector<RealGradient>> &>(fe_face_neighbor.get_dphi()));
2229  if (_need_second_derivative_neighbor.count(fe_type))
2230  fesd._second_phi.shallowCopy(
2231  const_cast<std::vector<std::vector<TensorValue<Real>>> &>(fe_face_neighbor.get_d2phi()));
2232  }
2233  for (const auto & it : _vector_fe_face_neighbor[neighbor_dim])
2234  {
2235  FEVectorBase & fe_face_neighbor = *it.second;
2236  const FEType & fe_type = it.first;
2237 
2238  _current_vector_fe_face_neighbor[fe_type] = &fe_face_neighbor;
2239 
2241 
2242  fe_face_neighbor.reinit(neighbor, neighbor_side, tolerance, pts, weights);
2243 
2244  fesd._phi.shallowCopy(
2245  const_cast<std::vector<std::vector<VectorValue<Real>>> &>(fe_face_neighbor.get_phi()));
2246  fesd._grad_phi.shallowCopy(
2247  const_cast<std::vector<std::vector<TensorValue<Real>>> &>(fe_face_neighbor.get_dphi()));
2248  if (_need_second_derivative.count(fe_type))
2249  fesd._second_phi.shallowCopy(const_cast<std::vector<std::vector<TypeNTensor<3, Real>>> &>(
2250  fe_face_neighbor.get_d2phi()));
2251  if (_need_curl.count(fe_type))
2252  fesd._curl_phi.shallowCopy(const_cast<std::vector<std::vector<VectorValue<Real>>> &>(
2253  fe_face_neighbor.get_curl_phi()));
2254  if (_need_face_neighbor_div.count(fe_type))
2255  fesd._div_phi.shallowCopy(
2256  const_cast<std::vector<std::vector<Real>> &>(fe_face_neighbor.get_div_phi()));
2257  }
2258  if (!_unique_fe_face_neighbor_helper.empty())
2259  {
2260  mooseAssert(neighbor_dim < _unique_fe_face_neighbor_helper.size(),
2261  "We should be in bounds here");
2262  _unique_fe_face_neighbor_helper[neighbor_dim]->reinit(
2263  neighbor, neighbor_side, tolerance, pts, weights);
2264  }
2265  // During that last loop the helper objects will have been reinitialized as well
2266  // We need to dig out the q_points from it
2268  const_cast<std::vector<Point> &>(_holder_fe_face_neighbor_helper[neighbor_dim]->get_xyz()));
2269 }
2270 
2271 void
2273  const std::vector<Point> & pts,
2274  const std::vector<Real> & JxW)
2275 {
2276  const unsigned int elem_dim = elem->dim();
2277  mooseAssert(elem_dim == _mesh_dimension - 1,
2278  "Dual shape functions should only be computed on lower dimensional face elements");
2279 
2280  for (const auto & it : _fe_lower[elem_dim])
2281  {
2282  FEBase & fe_lower = *it.second;
2283  // We use customized quadrature rule for integration along the mortar segment elements
2284  fe_lower.set_calculate_default_dual_coeff(false);
2285  fe_lower.reinit_dual_shape_coeffs(elem, pts, JxW);
2286  }
2287 }
2288 
2289 void
2291  const std::vector<Point> * const pts,
2292  const std::vector<Real> * const weights)
2293 {
2295 
2296  const unsigned int elem_dim = elem->dim();
2297  mooseAssert(elem_dim < _mesh_dimension,
2298  "The lower dimensional element should truly be a lower dimensional element");
2299 
2300  if (pts)
2301  {
2302  // Lower rule matches the face rule for the higher dimensional element
2303  ArbitraryQuadrature * lower_rule = qrules(elem_dim + 1).arbitrary_face.get();
2304 
2305  // This also sets the quadrature weights to unity
2306  lower_rule->setPoints(*pts);
2307 
2308  if (weights)
2309  lower_rule->setWeights(*weights);
2310 
2311  setLowerQRule(lower_rule, elem_dim);
2312  }
2313  else if (_current_qrule_lower != qrules(elem_dim + 1).face.get())
2314  setLowerQRule(qrules(elem_dim + 1).face.get(), elem_dim);
2315 
2316  for (const auto & it : _fe_lower[elem_dim])
2317  {
2318  FEBase & fe_lower = *it.second;
2319  FEType fe_type = it.first;
2320 
2321  fe_lower.reinit(elem);
2322 
2323  if (FEShapeData * fesd = _fe_shape_data_lower[fe_type].get())
2324  {
2325  fesd->_phi.shallowCopy(const_cast<std::vector<std::vector<Real>> &>(fe_lower.get_phi()));
2326  fesd->_grad_phi.shallowCopy(
2327  const_cast<std::vector<std::vector<RealGradient>> &>(fe_lower.get_dphi()));
2328  if (_need_second_derivative_neighbor.count(fe_type))
2329  fesd->_second_phi.shallowCopy(
2330  const_cast<std::vector<std::vector<TensorValue<Real>>> &>(fe_lower.get_d2phi()));
2331  }
2332 
2333  // Dual shape functions need to be computed after primal basis being initialized
2334  if (FEShapeData * fesd = _fe_shape_data_dual_lower[fe_type].get())
2335  {
2336  fesd->_phi.shallowCopy(const_cast<std::vector<std::vector<Real>> &>(fe_lower.get_dual_phi()));
2337  fesd->_grad_phi.shallowCopy(
2338  const_cast<std::vector<std::vector<RealGradient>> &>(fe_lower.get_dual_dphi()));
2339  if (_need_second_derivative_neighbor.count(fe_type))
2340  fesd->_second_phi.shallowCopy(
2341  const_cast<std::vector<std::vector<TensorValue<Real>>> &>(fe_lower.get_dual_d2phi()));
2342  }
2343  }
2344  if (!_unique_fe_lower_helper.empty())
2345  {
2346  mooseAssert(elem_dim < _unique_fe_lower_helper.size(), "We should be in bounds here");
2347  _unique_fe_lower_helper[elem_dim]->reinit(elem);
2348  }
2349 
2351  return;
2352 
2353  if (pts && !weights)
2354  {
2355  // We only have dummy weights so the JxWs computed during our FE reinits are meaningless and
2356  // we cannot use them
2357 
2359  // We are in a Cartesian coordinate system and we can just use the element volume method
2360  // which has fast computation for certain element types
2362  else
2363  // We manually compute the volume taking the curvilinear coordinate transformations into
2364  // account
2366  }
2367  else
2368  {
2369  // During that last loop the helper objects will have been reinitialized as well
2370  FEBase & helper_fe = *_holder_fe_lower_helper[elem_dim];
2371  const auto & physical_q_points = helper_fe.get_xyz();
2372  const auto & JxW = helper_fe.get_JxW();
2373  MooseArray<Real> coord;
2375  _current_qrule_lower, physical_q_points, coord, elem->subdomain_id());
2377  for (const auto qp : make_range(_current_qrule_lower->n_points()))
2378  _current_lower_d_elem_volume += JxW[qp] * coord[qp];
2379  }
2380 }
2381 
2382 void
2384 {
2385  mooseAssert(elem->dim() < _mesh_dimension,
2386  "You should be calling reinitNeighborLowerDElem on a lower dimensional element");
2387 
2389 
2391  return;
2392 
2394  // We are in a Cartesian coordinate system and we can just use the element volume method which
2395  // has fast computation for certain element types
2397  else
2398  // We manually compute the volume taking the curvilinear coordinate transformations into
2399  // account
2401 }
2402 
2403 void
2405 {
2406  mooseAssert(elem->dim() == _mesh_dimension - 1,
2407  "You should be calling reinitMortarElem on a lower dimensional element");
2408 
2409  _fe_msm->reinit(elem);
2410  _msm_elem = elem;
2411 
2412  MooseArray<Point> array_q_points;
2413  array_q_points.shallowCopy(const_cast<std::vector<Point> &>(_fe_msm->get_xyz()));
2415 }
2416 
2417 void
2418 Assembly::reinitNeighborAtPhysical(const Elem * neighbor,
2419  unsigned int neighbor_side,
2420  const std::vector<Point> & physical_points)
2421 {
2422  unsigned int neighbor_dim = neighbor->dim();
2423  FEMap::inverse_map(neighbor_dim, neighbor, physical_points, _current_neighbor_ref_points);
2424 
2425  if (_need_JxW_neighbor)
2426  {
2427  mooseAssert(
2428  physical_points.size() == 1,
2429  "If reinitializing with more than one point, then I am dubious of your use case. Perhaps "
2430  "you are performing a DG type method and you are reinitializing using points from the "
2431  "element face. In such a case your neighbor JxW must have its index order 'match' the "
2432  "element JxW index order, e.g. imagining a vertical 1D face with two quadrature points, "
2433  "if "
2434  "index 0 for elem JxW corresponds to the 'top' quadrature point, then index 0 for "
2435  "neighbor "
2436  "JxW must also correspond to the 'top' quadrature point. And libMesh/MOOSE has no way to "
2437  "guarantee that with multiple quadrature points.");
2438 
2440 
2441  // With a single point our size-1 JxW should just be the element volume
2444  }
2445 
2448 
2449  // Save off the physical points
2450  _current_physical_points = physical_points;
2451 }
2452 
2453 void
2454 Assembly::reinitNeighborAtPhysical(const Elem * neighbor,
2455  const std::vector<Point> & physical_points)
2456 {
2457  unsigned int neighbor_dim = neighbor->dim();
2458  FEMap::inverse_map(neighbor_dim, neighbor, physical_points, _current_neighbor_ref_points);
2459 
2462  // Save off the physical points
2463  _current_physical_points = physical_points;
2464 }
2465 
2466 void
2468 {
2469  _cm = cm;
2470 
2471  unsigned int n_vars = _sys.nVariables();
2472 
2473  _cm_ss_entry.clear();
2474  _cm_sf_entry.clear();
2475  _cm_fs_entry.clear();
2476  _cm_ff_entry.clear();
2477 
2478  auto & vars = _sys.getVariables(_tid);
2479 
2480  _block_diagonal_matrix = true;
2481  for (auto & ivar : vars)
2482  {
2483  auto i = ivar->number();
2484  if (i >= _component_block_diagonal.size())
2485  _component_block_diagonal.resize(i + 1, true);
2486 
2487  auto ivar_start = _cm_ff_entry.size();
2488  for (unsigned int k = 0; k < ivar->count(); ++k)
2489  {
2490  unsigned int iv = i + k;
2491  for (const auto & j : ConstCouplingRow(iv, *_cm))
2492  {
2493  if (_sys.isScalarVariable(j))
2494  {
2495  auto & jvar = _sys.getScalarVariable(_tid, j);
2496  _cm_fs_entry.push_back(std::make_pair(ivar, &jvar));
2497  _block_diagonal_matrix = false;
2498  }
2499  else
2500  {
2501  auto & jvar = _sys.getVariable(_tid, j);
2502  auto pair = std::make_pair(ivar, &jvar);
2503  auto c = ivar_start;
2504  // check if the pair has been pushed or not
2505  bool has_pair = false;
2506  for (; c < _cm_ff_entry.size(); ++c)
2507  if (_cm_ff_entry[c] == pair)
2508  {
2509  has_pair = true;
2510  break;
2511  }
2512  if (!has_pair)
2513  _cm_ff_entry.push_back(pair);
2514  // only set having diagonal matrix to false when ivar and jvar numbers are different
2515  // Note: for array variables, since we save the entire local Jacobian of all components,
2516  // even there are couplings among components of the same array variable, we still
2517  // do not set the flag to false.
2518  if (i != jvar.number())
2519  _block_diagonal_matrix = false;
2520  else if (iv != j)
2521  _component_block_diagonal[i] = false;
2522  }
2523  }
2524  }
2525  }
2526 
2527  auto & scalar_vars = _sys.getScalarVariables(_tid);
2528 
2529  for (auto & ivar : scalar_vars)
2530  {
2531  auto i = ivar->number();
2532  if (i >= _component_block_diagonal.size())
2533  _component_block_diagonal.resize(i + 1, true);
2534 
2535  for (const auto & j : ConstCouplingRow(i, *_cm))
2536  if (_sys.isScalarVariable(j))
2537  {
2538  auto & jvar = _sys.getScalarVariable(_tid, j);
2539  _cm_ss_entry.push_back(std::make_pair(ivar, &jvar));
2540  }
2541  else
2542  {
2543  auto & jvar = _sys.getVariable(_tid, j);
2544  _cm_sf_entry.push_back(std::make_pair(ivar, &jvar));
2545  }
2546  }
2547 
2548  if (_block_diagonal_matrix && scalar_vars.size() != 0)
2549  _block_diagonal_matrix = false;
2550 
2551  auto num_vector_tags = _residual_vector_tags.size();
2552 
2553  _sub_Re.resize(num_vector_tags);
2554  _sub_Rn.resize(num_vector_tags);
2555  _sub_Rl.resize(num_vector_tags);
2556  for (MooseIndex(_sub_Re) i = 0; i < _sub_Re.size(); i++)
2557  {
2558  _sub_Re[i].resize(n_vars);
2559  _sub_Rn[i].resize(n_vars);
2560  _sub_Rl[i].resize(n_vars);
2561  }
2562 
2563  _cached_residual_values.resize(num_vector_tags);
2564  _cached_residual_rows.resize(num_vector_tags);
2565 
2566  auto num_matrix_tags = _subproblem.numMatrixTags();
2567 
2568  _cached_jacobian_values.resize(num_matrix_tags);
2569  _cached_jacobian_rows.resize(num_matrix_tags);
2570  _cached_jacobian_cols.resize(num_matrix_tags);
2571 
2572  // Element matrices
2573  _sub_Kee.resize(num_matrix_tags);
2574  _sub_Keg.resize(num_matrix_tags);
2575  _sub_Ken.resize(num_matrix_tags);
2576  _sub_Kne.resize(num_matrix_tags);
2577  _sub_Knn.resize(num_matrix_tags);
2578  _sub_Kll.resize(num_matrix_tags);
2579  _sub_Kle.resize(num_matrix_tags);
2580  _sub_Kln.resize(num_matrix_tags);
2581  _sub_Kel.resize(num_matrix_tags);
2582  _sub_Knl.resize(num_matrix_tags);
2583 
2584  _jacobian_block_used.resize(num_matrix_tags);
2585  _jacobian_block_neighbor_used.resize(num_matrix_tags);
2586  _jacobian_block_lower_used.resize(num_matrix_tags);
2587  _jacobian_block_nonlocal_used.resize(num_matrix_tags);
2588 
2589  for (MooseIndex(num_matrix_tags) tag = 0; tag < num_matrix_tags; tag++)
2590  {
2591  _sub_Keg[tag].resize(n_vars);
2592  _sub_Ken[tag].resize(n_vars);
2593  _sub_Kne[tag].resize(n_vars);
2594  _sub_Knn[tag].resize(n_vars);
2595  _sub_Kee[tag].resize(n_vars);
2596  _sub_Kll[tag].resize(n_vars);
2597  _sub_Kle[tag].resize(n_vars);
2598  _sub_Kln[tag].resize(n_vars);
2599  _sub_Kel[tag].resize(n_vars);
2600  _sub_Knl[tag].resize(n_vars);
2601 
2602  _jacobian_block_used[tag].resize(n_vars);
2604  _jacobian_block_lower_used[tag].resize(n_vars);
2606  for (MooseIndex(n_vars) i = 0; i < n_vars; ++i)
2607  {
2609  {
2610  _sub_Kee[tag][i].resize(n_vars);
2611  _sub_Keg[tag][i].resize(n_vars);
2612  _sub_Ken[tag][i].resize(n_vars);
2613  _sub_Kne[tag][i].resize(n_vars);
2614  _sub_Knn[tag][i].resize(n_vars);
2615  _sub_Kll[tag][i].resize(n_vars);
2616  _sub_Kle[tag][i].resize(n_vars);
2617  _sub_Kln[tag][i].resize(n_vars);
2618  _sub_Kel[tag][i].resize(n_vars);
2619  _sub_Knl[tag][i].resize(n_vars);
2620 
2621  _jacobian_block_used[tag][i].resize(n_vars);
2622  _jacobian_block_neighbor_used[tag][i].resize(n_vars);
2623  _jacobian_block_lower_used[tag][i].resize(n_vars);
2624  _jacobian_block_nonlocal_used[tag][i].resize(n_vars);
2625  }
2626  else
2627  {
2628  _sub_Kee[tag][i].resize(1);
2629  _sub_Keg[tag][i].resize(1);
2630  _sub_Ken[tag][i].resize(1);
2631  _sub_Kne[tag][i].resize(1);
2632  _sub_Knn[tag][i].resize(1);
2633  _sub_Kll[tag][i].resize(1);
2634  _sub_Kle[tag][i].resize(1);
2635  _sub_Kln[tag][i].resize(1);
2636  _sub_Kel[tag][i].resize(1);
2637  _sub_Knl[tag][i].resize(1);
2638 
2639  _jacobian_block_used[tag][i].resize(1);
2640  _jacobian_block_neighbor_used[tag][i].resize(1);
2641  _jacobian_block_lower_used[tag][i].resize(1);
2642  _jacobian_block_nonlocal_used[tag][i].resize(1);
2643  }
2644  }
2645  }
2646 }
2647 
2648 void
2650 {
2651  _cm_nonlocal_entry.clear();
2652 
2653  auto & vars = _sys.getVariables(_tid);
2654 
2655  for (auto & ivar : vars)
2656  {
2657  auto i = ivar->number();
2658  auto ivar_start = _cm_nonlocal_entry.size();
2659  for (unsigned int k = 0; k < ivar->count(); ++k)
2660  {
2661  unsigned int iv = i + k;
2662  for (const auto & j : ConstCouplingRow(iv, _nonlocal_cm))
2663  if (!_sys.isScalarVariable(j))
2664  {
2665  auto & jvar = _sys.getVariable(_tid, j);
2666  auto pair = std::make_pair(ivar, &jvar);
2667  auto c = ivar_start;
2668  // check if the pair has been pushed or not
2669  bool has_pair = false;
2670  for (; c < _cm_nonlocal_entry.size(); ++c)
2671  if (_cm_nonlocal_entry[c] == pair)
2672  {
2673  has_pair = true;
2674  break;
2675  }
2676  if (!has_pair)
2677  _cm_nonlocal_entry.push_back(pair);
2678  }
2679  }
2680  }
2681 }
2682 
2683 void
2685 {
2686  for (const auto & it : _cm_ff_entry)
2687  {
2688  MooseVariableFEBase & ivar = *(it.first);
2689  MooseVariableFEBase & jvar = *(it.second);
2690 
2691  unsigned int vi = ivar.number();
2692  unsigned int vj = jvar.number();
2693 
2694  const bool array_block_diagonal_purely_diagonal = vi == vj && _component_block_diagonal[vi];
2695  auto num_cols = jvar.dofIndices().size();
2696  if (array_block_diagonal_purely_diagonal)
2697  num_cols /= jvar.count();
2698 
2699  for (MooseIndex(_jacobian_block_used) tag = 0; tag < _jacobian_block_used.size(); tag++)
2700  {
2701  jacobianBlock(vi, vj, LocalDataKey{}, tag).resize(ivar.dofIndices().size(), num_cols);
2702  jacobianBlockUsed(tag, vi, vj, false);
2703  }
2704  }
2705 }
2706 
2707 void
2709 {
2710  const std::vector<MooseVariableFEBase *> & vars = _sys.getVariables(_tid);
2711  for (const auto & var : vars)
2712  for (auto & tag_Re : _sub_Re)
2713  tag_Re[var->number()].resize(var->dofIndices().size());
2714 }
2715 
2716 void
2718 {
2720  prepareResidual();
2721 }
2722 
2723 void
2725 {
2726  for (const auto & it : _cm_nonlocal_entry)
2727  {
2728  MooseVariableFEBase & ivar = *(it.first);
2729  MooseVariableFEBase & jvar = *(it.second);
2730 
2731  unsigned int vi = ivar.number();
2732  unsigned int vj = jvar.number();
2733 
2734  const bool array_block_diagonal_purely_diagonal = vi == vj && _component_block_diagonal[vi];
2735  auto num_cols = jvar.allDofIndices().size();
2736  if (array_block_diagonal_purely_diagonal)
2737  num_cols /= jvar.count();
2738 
2739  for (MooseIndex(_jacobian_block_nonlocal_used) tag = 0;
2740  tag < _jacobian_block_nonlocal_used.size();
2741  tag++)
2742  {
2743  jacobianBlockNonlocal(vi, vj, LocalDataKey{}, tag).resize(ivar.dofIndices().size(), num_cols);
2744  jacobianBlockNonlocalUsed(tag, vi, vj, false);
2745  }
2746  }
2747 }
2748 
2749 void
2751 {
2752  for (const auto & it : _cm_ff_entry)
2753  {
2754  MooseVariableFEBase & ivar = *(it.first);
2755  MooseVariableFEBase & jvar = *(it.second);
2756 
2757  unsigned int vi = ivar.number();
2758  unsigned int vj = jvar.number();
2759 
2760  const bool array_block_diagonal_purely_diagonal = vi == vj && _component_block_diagonal[vi];
2761  auto num_cols = jvar.dofIndices().size();
2762  if (array_block_diagonal_purely_diagonal)
2763  num_cols /= jvar.count();
2764 
2765  if (vi == var->number() || vj == var->number())
2766  {
2767  for (MooseIndex(_jacobian_block_used) tag = 0; tag < _jacobian_block_used.size(); tag++)
2768  {
2769  jacobianBlock(vi, vj, LocalDataKey{}, tag).resize(ivar.dofIndices().size(), num_cols);
2770  jacobianBlockUsed(tag, vi, vj, false);
2771  }
2772  }
2773  }
2774 
2775  for (auto & tag_Re : _sub_Re)
2776  tag_Re[var->number()].resize(var->dofIndices().size());
2777 }
2778 
2779 void
2781 {
2782  for (const auto & it : _cm_nonlocal_entry)
2783  {
2784  MooseVariableFEBase & ivar = *(it.first);
2785  MooseVariableFEBase & jvar = *(it.second);
2786 
2787  unsigned int vi = ivar.number();
2788  unsigned int vj = jvar.number();
2789 
2790  const bool array_block_diagonal_purely_diagonal = vi == vj && _component_block_diagonal[vi];
2791  auto num_cols = jvar.dofIndices().size();
2792  if (array_block_diagonal_purely_diagonal)
2793  num_cols /= jvar.count();
2794 
2795  if (vi == var->number() || vj == var->number())
2796  {
2797  for (MooseIndex(_jacobian_block_nonlocal_used) tag = 0;
2798  tag < _jacobian_block_nonlocal_used.size();
2799  tag++)
2800  {
2801  jacobianBlockNonlocal(vi, vj, LocalDataKey{}, tag)
2802  .resize(ivar.dofIndices().size(), num_cols);
2803  jacobianBlockNonlocalUsed(tag, vi, vj);
2804  }
2805  }
2806  }
2807 }
2808 
2809 void
2811 {
2812  for (const auto & it : _cm_ff_entry)
2813  {
2814  MooseVariableFEBase & ivar = *(it.first);
2815  MooseVariableFEBase & jvar = *(it.second);
2816 
2817  unsigned int vi = ivar.number();
2818  unsigned int vj = jvar.number();
2819 
2820  const bool array_block_diagonal_purely_diagonal = vi == vj && _component_block_diagonal[vi];
2821  const auto dofs_divisor = array_block_diagonal_purely_diagonal ? jvar.count() : 1;
2822 
2823  for (MooseIndex(_jacobian_block_neighbor_used) tag = 0;
2824  tag < _jacobian_block_neighbor_used.size();
2825  tag++)
2826  {
2828  .resize(ivar.dofIndices().size(), jvar.dofIndicesNeighbor().size() / dofs_divisor);
2829 
2831  .resize(ivar.dofIndicesNeighbor().size(), jvar.dofIndices().size() / dofs_divisor);
2832 
2834  .resize(ivar.dofIndicesNeighbor().size(),
2835  jvar.dofIndicesNeighbor().size() / dofs_divisor);
2836 
2837  jacobianBlockNeighborUsed(tag, vi, vj, false);
2838  }
2839  }
2840 
2841  const std::vector<MooseVariableFEBase *> & vars = _sys.getVariables(_tid);
2842  for (const auto & var : vars)
2843  for (auto & tag_Rn : _sub_Rn)
2844  tag_Rn[var->number()].resize(var->dofIndicesNeighbor().size());
2845 }
2846 
2847 void
2849 {
2850  for (const auto & it : _cm_ff_entry)
2851  {
2852  MooseVariableFEBase & ivar = *(it.first);
2853  MooseVariableFEBase & jvar = *(it.second);
2854 
2855  unsigned int vi = ivar.number();
2856  unsigned int vj = jvar.number();
2857 
2858  const bool array_block_diagonal_purely_diagonal = vi == vj && _component_block_diagonal[vi];
2859  const auto dofs_divisor = array_block_diagonal_purely_diagonal ? jvar.count() : 1;
2860 
2861  for (MooseIndex(_jacobian_block_lower_used) tag = 0; tag < _jacobian_block_lower_used.size();
2862  tag++)
2863  {
2864  // To cover all possible cases we should have 9 combinations below for every 2-permutation
2865  // of Lower,Secondary,Primary. However, 4 cases will in general be covered by calls to
2866  // prepare() and prepareNeighbor(). These calls will cover SecondarySecondary
2867  // (ElementElement), SecondaryPrimary (ElementNeighbor), PrimarySecondary (NeighborElement),
2868  // and PrimaryPrimary (NeighborNeighbor). With these covered we only need to prepare the 5
2869  // remaining below
2870 
2871  // derivatives w.r.t. lower dimensional residuals
2873  .resize(ivar.dofIndicesLower().size(), jvar.dofIndicesLower().size() / dofs_divisor);
2874 
2876  .resize(ivar.dofIndicesLower().size(), jvar.dofIndices().size() / dofs_divisor);
2877 
2879  .resize(ivar.dofIndicesLower().size(), jvar.dofIndicesNeighbor().size() / dofs_divisor);
2880 
2881  // derivatives w.r.t. interior secondary residuals
2883  .resize(ivar.dofIndices().size(), jvar.dofIndicesLower().size() / dofs_divisor);
2884 
2885  // derivatives w.r.t. interior primary residuals
2887  .resize(ivar.dofIndicesNeighbor().size(), jvar.dofIndicesLower().size() / dofs_divisor);
2888 
2889  jacobianBlockLowerUsed(tag, vi, vj, false);
2890  }
2891  }
2892 
2893  const std::vector<MooseVariableFEBase *> & vars = _sys.getVariables(_tid);
2894  for (const auto & var : vars)
2895  for (auto & tag_Rl : _sub_Rl)
2896  tag_Rl[var->number()].resize(var->dofIndicesLower().size());
2897 }
2898 
2899 void
2900 Assembly::prepareBlock(unsigned int ivar,
2901  unsigned int jvar,
2902  const std::vector<dof_id_type> & dof_indices)
2903 {
2904  const auto & iv = _sys.getVariable(_tid, ivar);
2905  const auto & jv = _sys.getVariable(_tid, jvar);
2906  const unsigned int ivn = iv.number();
2907  const unsigned int jvn = jv.number();
2908  const unsigned int icount = iv.count();
2909  unsigned int jcount = jv.count();
2910  if (ivn == jvn && _component_block_diagonal[ivn])
2911  jcount = 1;
2912 
2913  for (MooseIndex(_jacobian_block_used) tag = 0; tag < _jacobian_block_used.size(); tag++)
2914  {
2915  jacobianBlock(ivn, jvn, LocalDataKey{}, tag)
2916  .resize(dof_indices.size() * icount, dof_indices.size() * jcount);
2917  jacobianBlockUsed(tag, ivn, jvn, false);
2918  }
2919 
2920  for (auto & tag_Re : _sub_Re)
2921  tag_Re[ivn].resize(dof_indices.size() * icount);
2922 }
2923 
2924 void
2926  unsigned int jvar,
2927  const std::vector<dof_id_type> & idof_indices,
2928  const std::vector<dof_id_type> & jdof_indices)
2929 {
2930  const auto & iv = _sys.getVariable(_tid, ivar);
2931  const auto & jv = _sys.getVariable(_tid, jvar);
2932  const unsigned int ivn = iv.number();
2933  const unsigned int jvn = jv.number();
2934  const unsigned int icount = iv.count();
2935  unsigned int jcount = jv.count();
2936  if (ivn == jvn && _component_block_diagonal[ivn])
2937  jcount = 1;
2938 
2939  for (MooseIndex(_jacobian_block_nonlocal_used) tag = 0;
2940  tag < _jacobian_block_nonlocal_used.size();
2941  tag++)
2942  {
2943  jacobianBlockNonlocal(ivn, jvn, LocalDataKey{}, tag)
2944  .resize(idof_indices.size() * icount, jdof_indices.size() * jcount);
2945 
2946  jacobianBlockNonlocalUsed(tag, ivn, jvn, false);
2947  }
2948 }
2949 
2950 void
2952 {
2953  const std::vector<MooseVariableScalar *> & vars = _sys.getScalarVariables(_tid);
2954  for (const auto & ivar : vars)
2955  {
2956  auto idofs = ivar->dofIndices().size();
2957 
2958  for (auto & tag_Re : _sub_Re)
2959  tag_Re[ivar->number()].resize(idofs);
2960 
2961  for (const auto & jvar : vars)
2962  {
2963  auto jdofs = jvar->dofIndices().size();
2964 
2965  for (MooseIndex(_jacobian_block_used) tag = 0; tag < _jacobian_block_used.size(); tag++)
2966  {
2967  jacobianBlock(ivar->number(), jvar->number(), LocalDataKey{}, tag).resize(idofs, jdofs);
2968  jacobianBlockUsed(tag, ivar->number(), jvar->number(), false);
2969  }
2970  }
2971  }
2972 }
2973 
2974 void
2976 {
2977  const std::vector<MooseVariableFEBase *> & vars = _sys.getVariables(_tid);
2978  const std::vector<MooseVariableScalar *> & scalar_vars = _sys.getScalarVariables(_tid);
2979 
2980  for (const auto & ivar : scalar_vars)
2981  {
2982  auto idofs = ivar->dofIndices().size();
2983 
2984  for (const auto & jvar : vars)
2985  {
2986  auto jdofs = jvar->dofIndices().size() * jvar->count();
2987  for (MooseIndex(_jacobian_block_used) tag = 0; tag < _jacobian_block_used.size(); tag++)
2988  {
2989  jacobianBlock(ivar->number(), jvar->number(), LocalDataKey{}, tag).resize(idofs, jdofs);
2990  jacobianBlockUsed(tag, ivar->number(), jvar->number(), false);
2991 
2992  jacobianBlock(jvar->number(), ivar->number(), LocalDataKey{}, tag).resize(jdofs, idofs);
2993  jacobianBlockUsed(tag, jvar->number(), ivar->number(), false);
2994  }
2995  }
2996  }
2997 }
2998 
2999 template <typename T>
3000 void
3002 {
3003  phi(v).shallowCopy(v.phi());
3004  gradPhi(v).shallowCopy(v.gradPhi());
3005  if (v.computingSecond())
3006  secondPhi(v).shallowCopy(v.secondPhi());
3007 }
3008 
3009 void
3010 Assembly::copyShapes(unsigned int var)
3011 {
3012  auto & v = _sys.getVariable(_tid, var);
3013  if (v.fieldType() == Moose::VarFieldType::VAR_FIELD_STANDARD)
3014  {
3015  auto & v = _sys.getActualFieldVariable<Real>(_tid, var);
3016  copyShapes(v);
3017  }
3018  else if (v.fieldType() == Moose::VarFieldType::VAR_FIELD_ARRAY)
3019  {
3020  auto & v = _sys.getActualFieldVariable<RealEigenVector>(_tid, var);
3021  copyShapes(v);
3022  }
3023  else if (v.fieldType() == Moose::VarFieldType::VAR_FIELD_VECTOR)
3024  {
3025  auto & v = _sys.getActualFieldVariable<RealVectorValue>(_tid, var);
3026  copyShapes(v);
3027  if (v.computingCurl())
3028  curlPhi(v).shallowCopy(v.curlPhi());
3029  if (v.computingDiv())
3030  divPhi(v).shallowCopy(v.divPhi());
3031  }
3032  else
3033  mooseError("Unsupported variable field type!");
3034 }
3035 
3036 template <typename T>
3037 void
3039 {
3040  phiFace(v).shallowCopy(v.phiFace());
3041  gradPhiFace(v).shallowCopy(v.gradPhiFace());
3042  if (v.computingSecond())
3043  secondPhiFace(v).shallowCopy(v.secondPhiFace());
3044 }
3045 
3046 void
3047 Assembly::copyFaceShapes(unsigned int var)
3048 {
3049  auto & v = _sys.getVariable(_tid, var);
3050  if (v.fieldType() == Moose::VarFieldType::VAR_FIELD_STANDARD)
3051  {
3052  auto & v = _sys.getActualFieldVariable<Real>(_tid, var);
3053  copyFaceShapes(v);
3054  }
3055  else if (v.fieldType() == Moose::VarFieldType::VAR_FIELD_ARRAY)
3056  {
3057  auto & v = _sys.getActualFieldVariable<RealEigenVector>(_tid, var);
3058  copyFaceShapes(v);
3059  }
3060  else if (v.fieldType() == Moose::VarFieldType::VAR_FIELD_VECTOR)
3061  {
3062  auto & v = _sys.getActualFieldVariable<RealVectorValue>(_tid, var);
3063  copyFaceShapes(v);
3064  if (v.computingCurl())
3065  _vector_curl_phi_face.shallowCopy(v.curlPhi());
3066  if (v.computingDiv())
3067  _vector_div_phi_face.shallowCopy(v.divPhi());
3068  }
3069  else
3070  mooseError("Unsupported variable field type!");
3071 }
3072 
3073 template <typename T>
3074 void
3076 {
3077  if (v.usesPhiNeighbor())
3078  {
3079  phiFaceNeighbor(v).shallowCopy(v.phiFaceNeighbor());
3080  phiNeighbor(v).shallowCopy(v.phiNeighbor());
3081  }
3082  if (v.usesGradPhiNeighbor())
3083  {
3084  gradPhiFaceNeighbor(v).shallowCopy(v.gradPhiFaceNeighbor());
3085  gradPhiNeighbor(v).shallowCopy(v.gradPhiNeighbor());
3086  }
3087  if (v.usesSecondPhiNeighbor())
3088  {
3089  secondPhiFaceNeighbor(v).shallowCopy(v.secondPhiFaceNeighbor());
3090  secondPhiNeighbor(v).shallowCopy(v.secondPhiNeighbor());
3091  }
3092 }
3093 
3094 void
3096 {
3097  auto & v = _sys.getVariable(_tid, var);
3098  if (v.fieldType() == Moose::VarFieldType::VAR_FIELD_STANDARD)
3099  {
3100  auto & v = _sys.getActualFieldVariable<Real>(_tid, var);
3101  copyNeighborShapes(v);
3102  }
3103  else if (v.fieldType() == Moose::VarFieldType::VAR_FIELD_ARRAY)
3104  {
3105  auto & v = _sys.getActualFieldVariable<RealEigenVector>(_tid, var);
3106  copyNeighborShapes(v);
3107  }
3108  else if (v.fieldType() == Moose::VarFieldType::VAR_FIELD_VECTOR)
3109  {
3110  auto & v = _sys.getActualFieldVariable<RealVectorValue>(_tid, var);
3111  copyNeighborShapes(v);
3112  }
3113  else
3114  mooseError("Unsupported variable field type!");
3115 }
3116 
3119  Moose::DGJacobianType type, unsigned int ivar, unsigned int jvar, LocalDataKey, TagID tag)
3120 {
3121  if (type == Moose::ElementElement)
3122  jacobianBlockUsed(tag, ivar, jvar, true);
3123  else
3124  jacobianBlockNeighborUsed(tag, ivar, jvar, true);
3125 
3127  {
3128  switch (type)
3129  {
3130  default:
3131  case Moose::ElementElement:
3132  return _sub_Kee[tag][ivar][0];
3134  return _sub_Ken[tag][ivar][0];
3136  return _sub_Kne[tag][ivar][0];
3138  return _sub_Knn[tag][ivar][0];
3139  }
3140  }
3141  else
3142  {
3143  switch (type)
3144  {
3145  default:
3146  case Moose::ElementElement:
3147  return _sub_Kee[tag][ivar][jvar];
3149  return _sub_Ken[tag][ivar][jvar];
3151  return _sub_Kne[tag][ivar][jvar];
3153  return _sub_Knn[tag][ivar][jvar];
3154  }
3155  }
3156 }
3157 
3160  unsigned int ivar,
3161  unsigned int jvar,
3162  LocalDataKey,
3163  TagID tag)
3164 {
3165  jacobianBlockLowerUsed(tag, ivar, jvar, true);
3167  {
3168  switch (type)
3169  {
3170  default:
3171  case Moose::LowerLower:
3172  return _sub_Kll[tag][ivar][0];
3173  case Moose::LowerSecondary:
3174  return _sub_Kle[tag][ivar][0];
3175  case Moose::LowerPrimary:
3176  return _sub_Kln[tag][ivar][0];
3177  case Moose::SecondaryLower:
3178  return _sub_Kel[tag][ivar][0];
3180  return _sub_Kee[tag][ivar][0];
3182  return _sub_Ken[tag][ivar][0];
3183  case Moose::PrimaryLower:
3184  return _sub_Knl[tag][ivar][0];
3186  return _sub_Kne[tag][ivar][0];
3187  case Moose::PrimaryPrimary:
3188  return _sub_Knn[tag][ivar][0];
3189  }
3190  }
3191  else
3192  {
3193  switch (type)
3194  {
3195  default:
3196  case Moose::LowerLower:
3197  return _sub_Kll[tag][ivar][jvar];
3198  case Moose::LowerSecondary:
3199  return _sub_Kle[tag][ivar][jvar];
3200  case Moose::LowerPrimary:
3201  return _sub_Kln[tag][ivar][jvar];
3202  case Moose::SecondaryLower:
3203  return _sub_Kel[tag][ivar][jvar];
3205  return _sub_Kee[tag][ivar][jvar];
3207  return _sub_Ken[tag][ivar][jvar];
3208  case Moose::PrimaryLower:
3209  return _sub_Knl[tag][ivar][jvar];
3211  return _sub_Kne[tag][ivar][jvar];
3212  case Moose::PrimaryPrimary:
3213  return _sub_Knn[tag][ivar][jvar];
3214  }
3215  }
3216 }
3217 
3218 void
3220  std::vector<dof_id_type> & dof_indices,
3221  const std::vector<Real> & scaling_factor)
3222 {
3223  mooseAssert(res_block.size() == dof_indices.size(),
3224  "The size of residual and degree of freedom container must be the same");
3225 
3226  // For an array variable, ndof is the number of dofs of the zero-th component and
3227  // ntdof is the number of dofs of all components.
3228  // For standard or vector variables, ndof will be the same as ntdof.
3229  const auto ntdof = res_block.size();
3230  const auto count = scaling_factor.size();
3231  const auto ndof = ntdof / count;
3232  if (count > 1)
3233  {
3234  unsigned int p = 0;
3235  for (MooseIndex(count) j = 0; j < count; ++j)
3236  for (MooseIndex(ndof) i = 0; i < ndof; ++i)
3237  res_block(p++) *= scaling_factor[j];
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 {
3254  if (dof_indices.size() > 0 && res_block.size())
3255  {
3256  _temp_dof_indices = dof_indices;
3257  _tmp_Re = res_block;
3260  }
3261 }
3262 
3263 void
3264 Assembly::cacheResidualBlock(std::vector<Real> & cached_residual_values,
3265  std::vector<dof_id_type> & cached_residual_rows,
3266  DenseVector<Number> & res_block,
3267  const std::vector<dof_id_type> & dof_indices,
3268  const std::vector<Real> & scaling_factor)
3269 {
3270  if (dof_indices.size() > 0 && res_block.size())
3271  {
3272  _temp_dof_indices = dof_indices;
3273  _tmp_Re = res_block;
3275 
3276  for (MooseIndex(_tmp_Re) i = 0; i < _tmp_Re.size(); i++)
3277  {
3278  cached_residual_values.push_back(_tmp_Re(i));
3279  cached_residual_rows.push_back(_temp_dof_indices[i]);
3280  }
3281  }
3282 
3283  res_block.zero();
3284 }
3285 
3286 void
3288  DenseVector<Number> & res_block,
3289  const std::vector<dof_id_type> & dof_indices,
3290  const std::vector<Real> & scaling_factor)
3291 {
3292  if (dof_indices.size() > 0)
3293  {
3294  std::vector<dof_id_type> di(dof_indices);
3295  _tmp_Re = res_block;
3296  processLocalResidual(_tmp_Re, di, scaling_factor);
3297  residual.insert(_tmp_Re, di);
3298  }
3299 }
3300 
3301 void
3303 {
3304  mooseAssert(vector_tag._type == Moose::VECTOR_TAG_RESIDUAL,
3305  "Non-residual tag in Assembly::addResidual");
3306 
3307  auto & tag_Re = _sub_Re[vector_tag._type_id];
3308  NumericVector<Number> & residual = _sys.getVector(vector_tag._id);
3309  const std::vector<MooseVariableFEBase *> & vars = _sys.getVariables(_tid);
3310  for (const auto & var : vars)
3311  addResidualBlock(residual, tag_Re[var->number()], var->dofIndices(), var->arrayScalingFactor());
3312 }
3313 
3314 void
3315 Assembly::addResidual(GlobalDataKey, const std::vector<VectorTag> & vector_tags)
3316 {
3317  for (const auto & vector_tag : vector_tags)
3318  if (_sys.hasVector(vector_tag._id))
3319  addResidual(vector_tag);
3320 }
3321 
3322 void
3324 {
3325  mooseAssert(vector_tag._type == Moose::VECTOR_TAG_RESIDUAL,
3326  "Non-residual tag in Assembly::addResidualNeighbor");
3327 
3328  auto & tag_Rn = _sub_Rn[vector_tag._type_id];
3329  NumericVector<Number> & residual = _sys.getVector(vector_tag._id);
3330  const std::vector<MooseVariableFEBase *> & vars = _sys.getVariables(_tid);
3331  for (const auto & var : vars)
3333  residual, tag_Rn[var->number()], var->dofIndicesNeighbor(), var->arrayScalingFactor());
3334 }
3335 
3336 void
3337 Assembly::addResidualNeighbor(GlobalDataKey, const std::vector<VectorTag> & vector_tags)
3338 {
3339  for (const auto & vector_tag : vector_tags)
3340  if (_sys.hasVector(vector_tag._id))
3341  addResidualNeighbor(vector_tag);
3342 }
3343 
3344 void
3346 {
3347  mooseAssert(vector_tag._type == Moose::VECTOR_TAG_RESIDUAL,
3348  "Non-residual tag in Assembly::addResidualLower");
3349 
3350  auto & tag_Rl = _sub_Rl[vector_tag._type_id];
3351  NumericVector<Number> & residual = _sys.getVector(vector_tag._id);
3352  const std::vector<MooseVariableFEBase *> & vars = _sys.getVariables(_tid);
3353  for (const auto & var : vars)
3355  residual, tag_Rl[var->number()], var->dofIndicesLower(), var->arrayScalingFactor());
3356 }
3357 
3358 void
3359 Assembly::addResidualLower(GlobalDataKey, const std::vector<VectorTag> & vector_tags)
3360 {
3361  for (const auto & vector_tag : vector_tags)
3362  if (_sys.hasVector(vector_tag._id))
3363  addResidualLower(vector_tag);
3364 }
3365 
3366 // private method, so no key required
3367 void
3369 {
3370  mooseAssert(vector_tag._type == Moose::VECTOR_TAG_RESIDUAL,
3371  "Non-residual tag in Assembly::addResidualScalar");
3372 
3373  // add the scalar variables residuals
3374  auto & tag_Re = _sub_Re[vector_tag._type_id];
3375  NumericVector<Number> & residual = _sys.getVector(vector_tag._id);
3376  const std::vector<MooseVariableScalar *> & vars = _sys.getScalarVariables(_tid);
3377  for (const auto & var : vars)
3378  addResidualBlock(residual, tag_Re[var->number()], var->dofIndices(), var->arrayScalingFactor());
3379 }
3380 
3381 void
3382 Assembly::addResidualScalar(GlobalDataKey, const std::vector<VectorTag> & vector_tags)
3383 {
3384  for (const auto & vector_tag : vector_tags)
3385  if (_sys.hasVector(vector_tag._id))
3386  addResidualScalar(vector_tag);
3387 }
3388 
3389 void
3390 Assembly::cacheResidual(GlobalDataKey, const std::vector<VectorTag> & tags)
3391 {
3392  const std::vector<MooseVariableFEBase *> & vars = _sys.getVariables(_tid);
3393  for (const auto & var : vars)
3394  for (const auto & vector_tag : tags)
3395  if (_sys.hasVector(vector_tag._id))
3396  cacheResidualBlock(_cached_residual_values[vector_tag._type_id],
3397  _cached_residual_rows[vector_tag._type_id],
3398  _sub_Re[vector_tag._type_id][var->number()],
3399  var->dofIndices(),
3400  var->arrayScalingFactor());
3401 }
3402 
3403 // private method, so no key required
3404 void
3406 {
3407  const VectorTag & tag = _subproblem.getVectorTag(tag_id);
3408 
3409  _cached_residual_values[tag._type_id].push_back(value);
3410  _cached_residual_rows[tag._type_id].push_back(dof);
3411 }
3412 
3413 // private method, so no key required
3414 void
3415 Assembly::cacheResidual(dof_id_type dof, Real value, const std::set<TagID> & tags)
3416 {
3417  for (auto & tag : tags)
3418  cacheResidual(dof, value, tag);
3419 }
3420 
3421 void
3423  const std::vector<dof_id_type> & dof_index,
3424  LocalDataKey,
3425  TagID tag)
3426 {
3427  // Add the residual value and dof_index to cached_residual_values and cached_residual_rows
3428  // respectively.
3429  // This is used by NodalConstraint.C to cache the residual calculated for primary and secondary
3430  // node.
3431  const VectorTag & vector_tag = _subproblem.getVectorTag(tag);
3432  for (MooseIndex(dof_index) i = 0; i < dof_index.size(); ++i)
3433  {
3434  _cached_residual_values[vector_tag._type_id].push_back(res(i));
3435  _cached_residual_rows[vector_tag._type_id].push_back(dof_index[i]);
3436  }
3437 }
3438 
3439 void
3440 Assembly::cacheResidualNeighbor(GlobalDataKey, const std::vector<VectorTag> & tags)
3441 {
3442  const std::vector<MooseVariableFEBase *> & vars = _sys.getVariables(_tid);
3443  for (const auto & var : vars)
3444  for (const auto & vector_tag : tags)
3445  if (_sys.hasVector(vector_tag._id))
3446  cacheResidualBlock(_cached_residual_values[vector_tag._type_id],
3447  _cached_residual_rows[vector_tag._type_id],
3448  _sub_Rn[vector_tag._type_id][var->number()],
3449  var->dofIndicesNeighbor(),
3450  var->arrayScalingFactor());
3451 }
3452 
3453 void
3454 Assembly::cacheResidualLower(GlobalDataKey, const std::vector<VectorTag> & tags)
3455 {
3456  const std::vector<MooseVariableFEBase *> & vars = _sys.getVariables(_tid);
3457  for (const auto & var : vars)
3458  for (const auto & vector_tag : tags)
3459  if (_sys.hasVector(vector_tag._id))
3460  cacheResidualBlock(_cached_residual_values[vector_tag._type_id],
3461  _cached_residual_rows[vector_tag._type_id],
3462  _sub_Rl[vector_tag._type_id][var->number()],
3463  var->dofIndicesLower(),
3464  var->arrayScalingFactor());
3465 }
3466 
3467 void
3468 Assembly::addCachedResiduals(GlobalDataKey, const std::vector<VectorTag> & tags)
3469 {
3470  for (const auto & vector_tag : tags)
3471  {
3472  if (!_sys.hasVector(vector_tag._id))
3473  {
3474  _cached_residual_values[vector_tag._type_id].clear();
3475  _cached_residual_rows[vector_tag._type_id].clear();
3476  continue;
3477  }
3478  addCachedResidualDirectly(_sys.getVector(vector_tag._id), GlobalDataKey{}, vector_tag);
3479  }
3480 }
3481 
3482 void
3484 {
3485  for (const auto & vector_tag : _residual_vector_tags)
3486  clearCachedResiduals(vector_tag);
3487 }
3488 
3489 // private method, so no key required
3490 void
3492 {
3493  auto & values = _cached_residual_values[vector_tag._type_id];
3494  auto & rows = _cached_residual_rows[vector_tag._type_id];
3495 
3496  mooseAssert(values.size() == rows.size(),
3497  "Number of cached residuals and number of rows must match!");
3498 
3499  // Keep track of the largest size so we can use it to reserve and avoid
3500  // as much dynamic allocation as possible
3501  if (_max_cached_residuals < values.size())
3502  _max_cached_residuals = values.size();
3503 
3504  // Clear both vectors (keeps the capacity the same)
3505  values.clear();
3506  rows.clear();
3507  // And then reserve: use 2 as a fudge factor to *really* avoid dynamic allocation!
3508  values.reserve(_max_cached_residuals * 2);
3509  rows.reserve(_max_cached_residuals * 2);
3510 }
3511 
3512 void
3514  GlobalDataKey,
3515  const VectorTag & vector_tag)
3516 {
3517  const auto & values = _cached_residual_values[vector_tag._type_id];
3518  const auto & rows = _cached_residual_rows[vector_tag._type_id];
3519 
3520  mooseAssert(values.size() == rows.size(),
3521  "Number of cached residuals and number of rows must match!");
3522 
3523  if (!values.empty())
3524  {
3525  residual.add_vector(values, rows);
3526  clearCachedResiduals(vector_tag);
3527  }
3528 }
3529 
3530 void
3532 {
3533  auto & tag_Re = _sub_Re[vector_tag._type_id];
3534  const std::vector<MooseVariableFEBase *> & vars = _sys.getVariables(_tid);
3535  for (const auto & var : vars)
3536  setResidualBlock(residual, tag_Re[var->number()], var->dofIndices(), var->arrayScalingFactor());
3537 }
3538 
3539 void
3541  GlobalDataKey,
3542  const VectorTag & vector_tag)
3543 {
3544  auto & tag_Rn = _sub_Rn[vector_tag._type_id];
3545  const std::vector<MooseVariableFEBase *> & vars = _sys.getVariables(_tid);
3546  for (const auto & var : vars)
3548  residual, tag_Rn[var->number()], var->dofIndicesNeighbor(), var->arrayScalingFactor());
3549 }
3550 
3551 // private method, so no key required
3552 void
3554  DenseMatrix<Number> & jac_block,
3555  const MooseVariableBase & ivar,
3556  const MooseVariableBase & jvar,
3557  const std::vector<dof_id_type> & idof_indices,
3558  const std::vector<dof_id_type> & jdof_indices)
3559 {
3560  if (idof_indices.size() == 0 || jdof_indices.size() == 0)
3561  return;
3562  if (jac_block.n() == 0 || jac_block.m() == 0)
3563  return;
3564 
3565  const auto & scaling_factors = ivar.arrayScalingFactor();
3566  const unsigned int iv = ivar.number();
3567  const unsigned int jv = jvar.number();
3568 
3569  for (unsigned int i = 0; i < ivar.count(); ++i)
3570  {
3571  for (const auto & jt : ConstCouplingRow(iv + i, *_cm))
3572  {
3573  if (jt < jv || jt >= jv + jvar.count())
3574  continue;
3575  unsigned int j = jt - jv;
3576 
3577  auto di = ivar.componentDofIndices(idof_indices, i);
3578  auto dj = jvar.componentDofIndices(jdof_indices, j);
3579  auto indof = di.size();
3580  auto jndof = dj.size();
3581 
3582  unsigned int jj = j;
3583  if (iv == jv && _component_block_diagonal[iv])
3584  // here i must be equal to j
3585  jj = 0;
3586 
3587  auto sub = jac_block.sub_matrix(i * indof, indof, jj * jndof, jndof);
3588  if (scaling_factors[i] != 1.0)
3589  sub *= scaling_factors[i];
3590 
3591  // If we're computing the jacobian for automatically scaling variables we do not want
3592  // to constrain the element matrix because it introduces 1s on the diagonal for the
3593  // constrained dofs
3595  _dof_map.constrain_element_matrix(sub, di, dj, false);
3596 
3597  jacobian.add_matrix(sub, di, dj);
3598  }
3599  }
3600 }
3601 
3602 // private method, so no key required
3603 void
3605  const MooseVariableBase & ivar,
3606  const MooseVariableBase & jvar,
3607  const std::vector<dof_id_type> & idof_indices,
3608  const std::vector<dof_id_type> & jdof_indices,
3609  TagID tag)
3610 {
3611  if (idof_indices.size() == 0 || jdof_indices.size() == 0)
3612  return;
3613  if (jac_block.n() == 0 || jac_block.m() == 0)
3614  return;
3615  if (!_sys.hasMatrix(tag))
3616  return;
3617 
3618  auto & scaling_factors = ivar.arrayScalingFactor();
3619  const unsigned int iv = ivar.number();
3620  const unsigned int jv = jvar.number();
3621 
3622  for (unsigned int i = 0; i < ivar.count(); ++i)
3623  {
3624  for (const auto & jt : ConstCouplingRow(iv + i, *_cm))
3625  {
3626  if (jt < jv || jt >= jv + jvar.count())
3627  continue;
3628  unsigned int j = jt - jv;
3629 
3630  auto di = ivar.componentDofIndices(idof_indices, i);
3631  auto dj = jvar.componentDofIndices(jdof_indices, j);
3632  auto indof = di.size();
3633  auto jndof = dj.size();
3634 
3635  unsigned int jj = j;
3636  if (iv == jv && _component_block_diagonal[iv])
3637  // here i must be equal to j
3638  jj = 0;
3639 
3640  auto sub = jac_block.sub_matrix(i * indof, indof, jj * jndof, jndof);
3641  if (scaling_factors[i] != 1.0)
3642  sub *= scaling_factors[i];
3643 
3644  // If we're computing the jacobian for automatically scaling variables we do not want
3645  // to constrain the element matrix because it introduces 1s on the diagonal for the
3646  // constrained dofs
3648  _dof_map.constrain_element_matrix(sub, di, dj, false);
3649 
3650  for (MooseIndex(di) i = 0; i < di.size(); i++)
3651  for (MooseIndex(dj) j = 0; j < dj.size(); j++)
3652  {
3653  _cached_jacobian_values[tag].push_back(sub(i, j));
3654  _cached_jacobian_rows[tag].push_back(di[i]);
3655  _cached_jacobian_cols[tag].push_back(dj[j]);
3656  }
3657  }
3658  }
3659 
3660  jac_block.zero();
3661 }
3662 
3663 // private method, so no key required
3664 void
3666  const MooseVariableBase & ivar,
3667  const MooseVariableBase & jvar,
3668  const std::vector<dof_id_type> & idof_indices,
3669  const std::vector<dof_id_type> & jdof_indices,
3670  TagID tag)
3671 {
3672  if (idof_indices.size() == 0 || jdof_indices.size() == 0)
3673  return;
3674  if (jac_block.n() == 0 || jac_block.m() == 0)
3675  return;
3676  if (!_sys.hasMatrix(tag))
3677  return;
3678 
3679  auto & scaling_factor = ivar.arrayScalingFactor();
3680 
3681  for (unsigned int i = 0; i < ivar.count(); ++i)
3682  {
3683  unsigned int iv = ivar.number();
3684  for (const auto & jt : ConstCouplingRow(iv + i, *_cm))
3685  {
3686  unsigned int jv = jvar.number();
3687  if (jt < jv || jt >= jv + jvar.count())
3688  continue;
3689  unsigned int j = jt - jv;
3690 
3691  auto di = ivar.componentDofIndices(idof_indices, i);
3692  auto dj = jvar.componentDofIndices(jdof_indices, j);
3693  auto indof = di.size();
3694  auto jndof = dj.size();
3695 
3696  unsigned int jj = j;
3697  if (iv == jv && _component_block_diagonal[iv])
3698  // here i must be equal to j
3699  jj = 0;
3700 
3701  auto sub = jac_block.sub_matrix(i * indof, indof, jj * jndof, jndof);
3702  if (scaling_factor[i] != 1.0)
3703  sub *= scaling_factor[i];
3704 
3705  _dof_map.constrain_element_matrix(sub, di, dj, false);
3706 
3707  for (MooseIndex(di) i = 0; i < di.size(); i++)
3708  for (MooseIndex(dj) j = 0; j < dj.size(); j++)
3709  if (sub(i, j) != 0.0) // no storage allocated for unimplemented jacobian terms,
3710  // maintaining maximum sparsity possible
3711  {
3712  _cached_jacobian_values[tag].push_back(sub(i, j));
3713  _cached_jacobian_rows[tag].push_back(di[i]);
3714  _cached_jacobian_cols[tag].push_back(dj[j]);
3715  }
3716  }
3717  }
3718 
3719  jac_block.zero();
3720 }
3721 
3722 void
3724  const std::vector<dof_id_type> & idof_indices,
3725  const std::vector<dof_id_type> & jdof_indices,
3726  Real scaling_factor,
3727  LocalDataKey,
3728  TagID tag)
3729 {
3730  // Only cache data when the matrix exists
3731  if ((idof_indices.size() > 0) && (jdof_indices.size() > 0) && jac_block.n() && jac_block.m() &&
3732  _sys.hasMatrix(tag))
3733  {
3734  std::vector<dof_id_type> di(idof_indices);
3735  std::vector<dof_id_type> dj(jdof_indices);
3736 
3737  // If we're computing the jacobian for automatically scaling variables we do not want to
3738  // constrain the element matrix because it introduces 1s on the diagonal for the constrained
3739  // dofs
3741  _dof_map.constrain_element_matrix(jac_block, di, dj, false);
3742 
3743  if (scaling_factor != 1.0)
3744  jac_block *= scaling_factor;
3745 
3746  for (MooseIndex(di) i = 0; i < di.size(); i++)
3747  for (MooseIndex(dj) j = 0; j < dj.size(); j++)
3748  {
3749  _cached_jacobian_values[tag].push_back(jac_block(i, j));
3750  _cached_jacobian_rows[tag].push_back(di[i]);
3751  _cached_jacobian_cols[tag].push_back(dj[j]);
3752  }
3753  }
3754  jac_block.zero();
3755 }
3756 
3757 Real
3758 Assembly::elementVolume(const Elem * elem) const
3759 {
3760  FEType fe_type(elem->default_order(), LAGRANGE);
3761  std::unique_ptr<FEBase> fe(FEBase::build(elem->dim(), fe_type));
3762 
3763  // references to the quadrature points and weights
3764  const std::vector<Real> & JxW = fe->get_JxW();
3765  const std::vector<Point> & q_points = fe->get_xyz();
3766 
3767  // The default quadrature rule should integrate the mass matrix,
3768  // thus it should be plenty to compute the volume
3769  QGauss qrule(elem->dim(), fe_type.default_quadrature_order());
3770  fe->attach_quadrature_rule(&qrule);
3771  fe->reinit(elem);
3772 
3773  // perform a sanity check to ensure that size of quad rule and size of q_points is
3774  // identical
3775  mooseAssert(qrule.n_points() == q_points.size(),
3776  "The number of points in the quadrature rule doesn't match the number of passed-in "
3777  "points in Assembly::setCoordinateTransformation");
3778 
3779  // compute the coordinate transformation
3780  Real vol = 0;
3781  for (unsigned int qp = 0; qp < qrule.n_points(); ++qp)
3782  {
3783  Real coord;
3784  coordTransformFactor(_subproblem, elem->subdomain_id(), q_points[qp], coord);
3785  vol += JxW[qp] * coord;
3786  }
3787  return vol;
3788 }
3789 
3790 void
3792 {
3793 #ifndef NDEBUG
3795  {
3796  mooseAssert(_cached_jacobian_rows.size() == _cached_jacobian_cols.size(),
3797  "Error: Cached data sizes MUST be the same!");
3798  for (MooseIndex(_cached_jacobian_rows) i = 0; i < _cached_jacobian_rows.size(); i++)
3799  mooseAssert(_cached_jacobian_rows[i].size() == _cached_jacobian_cols[i].size(),
3800  "Error: Cached data sizes MUST be the same for a given tag!");
3801  }
3802 #endif
3803 
3804  for (MooseIndex(_cached_jacobian_rows) i = 0; i < _cached_jacobian_rows.size(); i++)
3805  if (_sys.hasMatrix(i))
3806  for (MooseIndex(_cached_jacobian_rows[i]) j = 0; j < _cached_jacobian_rows[i].size(); j++)
3808  _cached_jacobian_cols[i][j],
3809  _cached_jacobian_values[i][j]);
3810 
3811  for (MooseIndex(_cached_jacobian_rows) i = 0; i < _cached_jacobian_rows.size(); i++)
3812  {
3813  if (!_sys.hasMatrix(i))
3814  continue;
3815 
3818 
3819  // Try to be more efficient from now on
3820  // The 2 is just a fudge factor to keep us from having to grow the vector during assembly
3821  _cached_jacobian_values[i].clear();
3823 
3824  _cached_jacobian_rows[i].clear();
3826 
3827  _cached_jacobian_cols[i].clear();
3829  }
3830 }
3831 
3832 inline void
3834 {
3835  auto i = ivar.number();
3836  auto j = jvar.number();
3837  for (MooseIndex(_jacobian_block_used) tag = 0; tag < _jacobian_block_used.size(); tag++)
3838  if (jacobianBlockUsed(tag, i, j) && _sys.hasMatrix(tag))
3840  jacobianBlock(i, j, LocalDataKey{}, tag),
3841  ivar,
3842  jvar,
3843  ivar.dofIndices(),
3844  jvar.dofIndices());
3845 }
3846 
3847 void
3849 {
3850  for (const auto & it : _cm_ff_entry)
3851  addJacobianCoupledVarPair(*it.first, *it.second);
3852 
3853  for (const auto & it : _cm_sf_entry)
3854  addJacobianCoupledVarPair(*it.first, *it.second);
3855 
3856  for (const auto & it : _cm_fs_entry)
3857  addJacobianCoupledVarPair(*it.first, *it.second);
3858 }
3859 
3860 void
3862 {
3863  for (const auto & it : _cm_nonlocal_entry)
3864  {
3865  auto ivar = it.first;
3866  auto jvar = it.second;
3867  auto i = ivar->number();
3868  auto j = jvar->number();
3869  for (MooseIndex(_jacobian_block_nonlocal_used) tag = 0;
3870  tag < _jacobian_block_nonlocal_used.size();
3871  tag++)
3872  if (jacobianBlockNonlocalUsed(tag, i, j) && _sys.hasMatrix(tag))
3874  jacobianBlockNonlocal(i, j, LocalDataKey{}, tag),
3875  *ivar,
3876  *jvar,
3877  ivar->dofIndices(),
3878  jvar->allDofIndices());
3879  }
3880 }
3881 
3882 void
3884 {
3885  for (const auto & it : _cm_ff_entry)
3886  {
3887  auto ivar = it.first;
3888  auto jvar = it.second;
3889  auto i = ivar->number();
3890  auto j = jvar->number();
3891  for (MooseIndex(_jacobian_block_neighbor_used) tag = 0;
3892  tag < _jacobian_block_neighbor_used.size();
3893  tag++)
3894  if (jacobianBlockNeighborUsed(tag, i, j) && _sys.hasMatrix(tag))
3895  {
3898  *ivar,
3899  *jvar,
3900  ivar->dofIndices(),
3901  jvar->dofIndicesNeighbor());
3902 
3905  *ivar,
3906  *jvar,
3907  ivar->dofIndicesNeighbor(),
3908  jvar->dofIndices());
3909 
3912  *ivar,
3913  *jvar,
3914  ivar->dofIndicesNeighbor(),
3915  jvar->dofIndicesNeighbor());
3916  }
3917  }
3918 }
3919 
3920 void
3922 {
3923  for (const auto & it : _cm_ff_entry)
3924  {
3925  auto ivar = it.first;
3926  auto jvar = it.second;
3927  auto i = ivar->number();
3928  auto j = jvar->number();
3929  for (MooseIndex(_jacobian_block_lower_used) tag = 0; tag < _jacobian_block_lower_used.size();
3930  tag++)
3931  if (jacobianBlockLowerUsed(tag, i, j) && _sys.hasMatrix(tag))
3932  {
3935  *ivar,
3936  *jvar,
3937  ivar->dofIndicesLower(),
3938  jvar->dofIndicesLower());
3939 
3942  *ivar,
3943  *jvar,
3944  ivar->dofIndicesLower(),
3945  jvar->dofIndicesNeighbor());
3946 
3949  *ivar,
3950  *jvar,
3951  ivar->dofIndicesLower(),
3952  jvar->dofIndices());
3953 
3956  *ivar,
3957  *jvar,
3958  ivar->dofIndicesNeighbor(),
3959  jvar->dofIndicesLower());
3960 
3963  *ivar,
3964  *jvar,
3965  ivar->dofIndices(),
3966  jvar->dofIndicesLower());
3967  }
3968 
3969  for (MooseIndex(_jacobian_block_neighbor_used) tag = 0;
3970  tag < _jacobian_block_neighbor_used.size();
3971  tag++)
3972  if (jacobianBlockNeighborUsed(tag, i, j) && _sys.hasMatrix(tag))
3973  {
3976  *ivar,
3977  *jvar,
3978  ivar->dofIndices(),
3979  jvar->dofIndicesNeighbor());
3980 
3983  *ivar,
3984  *jvar,
3985  ivar->dofIndicesNeighbor(),
3986  jvar->dofIndices());
3987 
3990  *ivar,
3991  *jvar,
3992  ivar->dofIndicesNeighbor(),
3993  jvar->dofIndicesNeighbor());
3994  }
3995  }
3996 }
3997 
3998 void
4000 {
4001  for (const auto & it : _cm_ff_entry)
4002  {
4003  auto ivar = it.first;
4004  auto jvar = it.second;
4005  auto i = ivar->number();
4006  auto j = jvar->number();
4007  for (MooseIndex(_jacobian_block_lower_used) tag = 0; tag < _jacobian_block_lower_used.size();
4008  tag++)
4009  if (jacobianBlockLowerUsed(tag, i, j) && _sys.hasMatrix(tag))
4010  {
4013  *ivar,
4014  *jvar,
4015  ivar->dofIndicesLower(),
4016  jvar->dofIndicesLower());
4017 
4020  *ivar,
4021  *jvar,
4022  ivar->dofIndicesLower(),
4023  jvar->dofIndices());
4024 
4027  *ivar,
4028  *jvar,
4029  ivar->dofIndices(),
4030  jvar->dofIndicesLower());
4031  }
4032  }
4033 }
4034 
4035 void
4037 {
4038  for (const auto & it : _cm_ff_entry)
4039  cacheJacobianCoupledVarPair(*it.first, *it.second);
4040 
4041  for (const auto & it : _cm_fs_entry)
4042  cacheJacobianCoupledVarPair(*it.first, *it.second);
4043 
4044  for (const auto & it : _cm_sf_entry)
4045  cacheJacobianCoupledVarPair(*it.first, *it.second);
4046 }
4047 
4048 // private method, so no key required
4049 void
4051  const MooseVariableBase & jvar)
4052 {
4053  auto i = ivar.number();
4054  auto j = jvar.number();
4055  for (MooseIndex(_jacobian_block_used) tag = 0; tag < _jacobian_block_used.size(); tag++)
4056  if (jacobianBlockUsed(tag, i, j) && _sys.hasMatrix(tag))
4058  ivar,
4059  jvar,
4060  ivar.dofIndices(),
4061  jvar.dofIndices(),
4062  tag);
4063 }
4064 
4065 void
4067 {
4068  for (const auto & it : _cm_nonlocal_entry)
4069  {
4070  auto ivar = it.first;
4071  auto jvar = it.second;
4072  auto i = ivar->number();
4073  auto j = jvar->number();
4074  for (MooseIndex(_jacobian_block_nonlocal_used) tag = 0;
4075  tag < _jacobian_block_nonlocal_used.size();
4076  tag++)
4077  if (jacobianBlockNonlocalUsed(tag, i, j) && _sys.hasMatrix(tag))
4079  *ivar,
4080  *jvar,
4081  ivar->dofIndices(),
4082  jvar->allDofIndices(),
4083  tag);
4084  }
4085 }
4086 
4087 void
4089 {
4090  for (const auto & it : _cm_ff_entry)
4091  {
4092  auto ivar = it.first;
4093  auto jvar = it.second;
4094  auto i = ivar->number();
4095  auto j = jvar->number();
4096 
4097  for (MooseIndex(_jacobian_block_neighbor_used) tag = 0;
4098  tag < _jacobian_block_neighbor_used.size();
4099  tag++)
4100  if (jacobianBlockNeighborUsed(tag, i, j) && _sys.hasMatrix(tag))
4101  {
4103  *ivar,
4104  *jvar,
4105  ivar->dofIndices(),
4106  jvar->dofIndicesNeighbor(),
4107  tag);
4109  *ivar,
4110  *jvar,
4111  ivar->dofIndicesNeighbor(),
4112  jvar->dofIndices(),
4113  tag);
4116  *ivar,
4117  *jvar,
4118  ivar->dofIndicesNeighbor(),
4119  jvar->dofIndicesNeighbor(),
4120  tag);
4121  }
4122  }
4123 }
4124 
4125 void
4127 {
4128  for (const auto & it : _cm_ff_entry)
4129  {
4130  auto ivar = it.first;
4131  auto jvar = it.second;
4132  auto i = ivar->number();
4133  auto j = jvar->number();
4134  for (MooseIndex(_jacobian_block_lower_used) tag = 0; tag < _jacobian_block_lower_used.size();
4135  tag++)
4136  if (jacobianBlockLowerUsed(tag, i, j) && _sys.hasMatrix(tag))
4137  {
4139  *ivar,
4140  *jvar,
4141  ivar->dofIndicesLower(),
4142  jvar->dofIndicesLower(),
4143  tag);
4144 
4146  *ivar,
4147  *jvar,
4148  ivar->dofIndicesLower(),
4149  jvar->dofIndices(),
4150  tag);
4151 
4153  *ivar,
4154  *jvar,
4155  ivar->dofIndicesLower(),
4156  jvar->dofIndicesNeighbor(),
4157  tag);
4158 
4160  *ivar,
4161  *jvar,
4162  ivar->dofIndices(),
4163  jvar->dofIndicesLower(),
4164  tag);
4165 
4168  *ivar,
4169  *jvar,
4170  ivar->dofIndices(),
4171  jvar->dofIndices(),
4172  tag);
4173 
4175  *ivar,
4176  *jvar,
4177  ivar->dofIndices(),
4178  jvar->dofIndicesNeighbor(),
4179  tag);
4180 
4182  *ivar,
4183  *jvar,
4184  ivar->dofIndicesNeighbor(),
4185  jvar->dofIndicesLower(),
4186  tag);
4187 
4189  *ivar,
4190  *jvar,
4191  ivar->dofIndicesNeighbor(),
4192  jvar->dofIndices(),
4193  tag);
4194 
4196  *ivar,
4197  *jvar,
4198  ivar->dofIndicesNeighbor(),
4199  jvar->dofIndicesNeighbor(),
4200  tag);
4201  }
4202  }
4203 }
4204 
4205 void
4207  unsigned int ivar,
4208  unsigned int jvar,
4209  const DofMap & dof_map,
4210  std::vector<dof_id_type> & dof_indices,
4211  GlobalDataKey,
4212  const std::set<TagID> & tags)
4213 {
4214  for (auto tag : tags)
4215  addJacobianBlock(jacobian, ivar, jvar, dof_map, dof_indices, GlobalDataKey{}, tag);
4216 }
4217 
4218 void
4220  unsigned int ivar,
4221  unsigned int jvar,
4222  const DofMap & dof_map,
4223  std::vector<dof_id_type> & dof_indices,
4224  GlobalDataKey,
4225  TagID tag)
4226 {
4227  if (dof_indices.size() == 0)
4228  return;
4229  if (!(*_cm)(ivar, jvar))
4230  return;
4231 
4232  auto & iv = _sys.getVariable(_tid, ivar);
4233  auto & jv = _sys.getVariable(_tid, jvar);
4234  auto & scaling_factor = iv.arrayScalingFactor();
4235 
4236  const unsigned int ivn = iv.number();
4237  const unsigned int jvn = jv.number();
4238  auto & ke = jacobianBlock(ivn, jvn, LocalDataKey{}, tag);
4239 
4240  // It is guaranteed by design iv.number <= ivar since iv is obtained
4241  // through SystemBase::getVariable with ivar.
4242  // Most of times ivar will just be equal to iv.number except for array variables,
4243  // where ivar could be a number for a component of an array variable but calling
4244  // getVariable will return the array variable that has the number of the 0th component.
4245  // It is the same for jvar.
4246  const unsigned int i = ivar - ivn;
4247  const unsigned int j = jvar - jvn;
4248 
4249  // DoF indices are independently given
4250  auto di = dof_indices;
4251  auto dj = dof_indices;
4252 
4253  auto indof = di.size();
4254  auto jndof = dj.size();
4255 
4256  unsigned int jj = j;
4257  if (ivar == jvar && _component_block_diagonal[ivn])
4258  jj = 0;
4259 
4260  auto sub = ke.sub_matrix(i * indof, indof, jj * jndof, jndof);
4261  // If we're computing the jacobian for automatically scaling variables we do not want to
4262  // constrain the element matrix because it introduces 1s on the diagonal for the constrained
4263  // dofs
4265  dof_map.constrain_element_matrix(sub, di, dj, false);
4266 
4267  if (scaling_factor[i] != 1.0)
4268  sub *= scaling_factor[i];
4269 
4270  jacobian.add_matrix(sub, di, dj);
4271 }
4272 
4273 void
4275  const unsigned int ivar,
4276  const unsigned int jvar,
4277  const DofMap & dof_map,
4278  const std::vector<dof_id_type> & idof_indices,
4279  const std::vector<dof_id_type> & jdof_indices,
4280  GlobalDataKey,
4281  const TagID tag)
4282 {
4283  if (idof_indices.size() == 0 || jdof_indices.size() == 0)
4284  return;
4285  if (jacobian.n() == 0 || jacobian.m() == 0)
4286  return;
4287  if (!(*_cm)(ivar, jvar))
4288  return;
4289 
4290  auto & iv = _sys.getVariable(_tid, ivar);
4291  auto & jv = _sys.getVariable(_tid, jvar);
4292  auto & scaling_factor = iv.arrayScalingFactor();
4293 
4294  const unsigned int ivn = iv.number();
4295  const unsigned int jvn = jv.number();
4296  auto & keg = jacobianBlockNonlocal(ivn, jvn, LocalDataKey{}, tag);
4297 
4298  // It is guaranteed by design iv.number <= ivar since iv is obtained
4299  // through SystemBase::getVariable with ivar.
4300  // Most of times ivar will just be equal to iv.number except for array variables,
4301  // where ivar could be a number for a component of an array variable but calling
4302  // getVariable will return the array variable that has the number of the 0th component.
4303  // It is the same for jvar.
4304  const unsigned int i = ivar - ivn;
4305  const unsigned int j = jvar - jvn;
4306 
4307  // DoF indices are independently given
4308  auto di = idof_indices;
4309  auto dj = jdof_indices;
4310 
4311  auto indof = di.size();
4312  auto jndof = dj.size();
4313 
4314  unsigned int jj = j;
4315  if (ivar == jvar && _component_block_diagonal[ivn])
4316  jj = 0;
4317 
4318  auto sub = keg.sub_matrix(i * indof, indof, jj * jndof, jndof);
4319  // If we're computing the jacobian for automatically scaling variables we do not want to
4320  // constrain the element matrix because it introduces 1s on the diagonal for the constrained
4321  // dofs
4323  dof_map.constrain_element_matrix(sub, di, dj, false);
4324 
4325  if (scaling_factor[i] != 1.0)
4326  sub *= scaling_factor[i];
4327 
4328  jacobian.add_matrix(sub, di, dj);
4329 }
4330 
4331 void
4333  const unsigned int ivar,
4334  const unsigned int jvar,
4335  const DofMap & dof_map,
4336  const std::vector<dof_id_type> & idof_indices,
4337  const std::vector<dof_id_type> & jdof_indices,
4338  GlobalDataKey,
4339  const std::set<TagID> & tags)
4340 {
4341  for (auto tag : tags)
4343  jacobian, ivar, jvar, dof_map, idof_indices, jdof_indices, GlobalDataKey{}, tag);
4344 }
4345 
4346 void
4348  const unsigned int ivar,
4349  const unsigned int jvar,
4350  const DofMap & dof_map,
4351  std::vector<dof_id_type> & dof_indices,
4352  std::vector<dof_id_type> & neighbor_dof_indices,
4353  GlobalDataKey,
4354  const TagID tag)
4355 {
4356  if (dof_indices.size() == 0 && neighbor_dof_indices.size() == 0)
4357  return;
4358  if (!(*_cm)(ivar, jvar))
4359  return;
4360 
4361  auto & iv = _sys.getVariable(_tid, ivar);
4362  auto & jv = _sys.getVariable(_tid, jvar);
4363  auto & scaling_factor = iv.arrayScalingFactor();
4364 
4365  const unsigned int ivn = iv.number();
4366  const unsigned int jvn = jv.number();
4367  auto & ken = jacobianBlockNeighbor(Moose::ElementNeighbor, ivn, jvn, LocalDataKey{}, tag);
4368  auto & kne = jacobianBlockNeighbor(Moose::NeighborElement, ivn, jvn, LocalDataKey{}, tag);
4369  auto & knn = jacobianBlockNeighbor(Moose::NeighborNeighbor, ivn, jvn, LocalDataKey{}, tag);
4370 
4371  // It is guaranteed by design iv.number <= ivar since iv is obtained
4372  // through SystemBase::getVariable with ivar.
4373  // Most of times ivar will just be equal to iv.number except for array variables,
4374  // where ivar could be a number for a component of an array variable but calling
4375  // getVariable will return the array variable that has the number of the 0th component.
4376  // It is the same for jvar.
4377  const unsigned int i = ivar - ivn;
4378  const unsigned int j = jvar - jvn;
4379  // DoF indices are independently given
4380  auto dc = dof_indices;
4381  auto dn = neighbor_dof_indices;
4382  auto cndof = dc.size();
4383  auto nndof = dn.size();
4384 
4385  unsigned int jj = j;
4386  if (ivar == jvar && _component_block_diagonal[ivn])
4387  jj = 0;
4388 
4389  auto suben = ken.sub_matrix(i * cndof, cndof, jj * nndof, nndof);
4390  auto subne = kne.sub_matrix(i * nndof, nndof, jj * cndof, cndof);
4391  auto subnn = knn.sub_matrix(i * nndof, nndof, jj * nndof, nndof);
4392 
4393  // If we're computing the jacobian for automatically scaling variables we do not want to
4394  // constrain the element matrix because it introduces 1s on the diagonal for the constrained
4395  // dofs
4397  {
4398  dof_map.constrain_element_matrix(suben, dc, dn, false);
4399  dof_map.constrain_element_matrix(subne, dn, dc, false);
4400  dof_map.constrain_element_matrix(subnn, dn, dn, false);
4401  }
4402 
4403  if (scaling_factor[i] != 1.0)
4404  {
4405  suben *= scaling_factor[i];
4406  subne *= scaling_factor[i];
4407  subnn *= scaling_factor[i];
4408  }
4409 
4410  jacobian.add_matrix(suben, dc, dn);
4411  jacobian.add_matrix(subne, dn, dc);
4412  jacobian.add_matrix(subnn, dn, dn);
4413 }
4414 
4415 void
4417  const unsigned int ivar,
4418  const unsigned int jvar,
4419  const DofMap & dof_map,
4420  std::vector<dof_id_type> & dof_indices,
4421  std::vector<dof_id_type> & neighbor_dof_indices,
4422  GlobalDataKey,
4423  const std::set<TagID> & tags)
4424 {
4425  for (const auto tag : tags)
4427  jacobian, ivar, jvar, dof_map, dof_indices, neighbor_dof_indices, GlobalDataKey{}, tag);
4428 }
4429 
4430 void
4432 {
4433  for (const auto & it : _cm_ss_entry)
4434  addJacobianCoupledVarPair(*it.first, *it.second);
4435 }
4436 
4437 void
4439 {
4440  const std::vector<MooseVariableFEBase *> & vars = _sys.getVariables(_tid);
4442  for (const auto & var_j : vars)
4443  addJacobianCoupledVarPair(var_i, *var_j);
4444 }
4445 
4446 void
4449 {
4450  _cached_jacobian_rows[tag].push_back(i);
4451  _cached_jacobian_cols[tag].push_back(j);
4452  _cached_jacobian_values[tag].push_back(value);
4453 }
4454 
4455 void
4458  Real value,
4459  LocalDataKey,
4460  const std::set<TagID> & tags)
4461 {
4462  for (auto tag : tags)
4463  if (_sys.hasMatrix(tag))
4464  cacheJacobian(i, j, value, LocalDataKey{}, tag);
4465 }
4466 
4467 void
4469 {
4470  for (MooseIndex(_cached_jacobian_rows) tag = 0; tag < _cached_jacobian_rows.size(); tag++)
4471  if (_sys.hasMatrix(tag))
4472  {
4473  // First zero the rows (including the diagonals) to prepare for
4474  // setting the cached values.
4476 
4477  // TODO: Use SparseMatrix::set_values() for efficiency
4478  for (MooseIndex(_cached_jacobian_values) i = 0; i < _cached_jacobian_values[tag].size(); ++i)
4479  _sys.getMatrix(tag).set(_cached_jacobian_rows[tag][i],
4480  _cached_jacobian_cols[tag][i],
4481  _cached_jacobian_values[tag][i]);
4482  }
4483 
4485 }
4486 
4487 void
4489 {
4490  for (MooseIndex(_cached_jacobian_rows) tag = 0; tag < _cached_jacobian_rows.size(); tag++)
4491  if (_sys.hasMatrix(tag))
4493 
4495 }
4496 
4497 void
4499 {
4500  for (MooseIndex(_cached_jacobian_rows) tag = 0; tag < _cached_jacobian_rows.size(); tag++)
4501  {
4502  _cached_jacobian_rows[tag].clear();
4503  _cached_jacobian_cols[tag].clear();
4504  _cached_jacobian_values[tag].clear();
4505  }
4506 }
4507 
4508 void
4510 {
4511  mooseAssert(_xfem != nullptr, "This function should not be called if xfem is inactive");
4512 
4514  return;
4515 
4516  MooseArray<Real> xfem_weight_multipliers;
4517  if (_xfem->getXFEMWeights(xfem_weight_multipliers, elem, _current_qrule, _current_q_points))
4518  {
4519  mooseAssert(xfem_weight_multipliers.size() == _current_JxW.size(),
4520  "Size of weight multipliers in xfem doesn't match number of quadrature points");
4521  for (unsigned i = 0; i < xfem_weight_multipliers.size(); i++)
4522  _current_JxW[i] = _current_JxW[i] * xfem_weight_multipliers[i];
4523 
4524  xfem_weight_multipliers.release();
4525  }
4526 }
4527 
4528 void
4529 Assembly::modifyFaceWeightsDueToXFEM(const Elem * elem, unsigned int side)
4530 {
4531  mooseAssert(_xfem != nullptr, "This function should not be called if xfem is inactive");
4532 
4534  return;
4535 
4536  MooseArray<Real> xfem_face_weight_multipliers;
4537  if (_xfem->getXFEMFaceWeights(
4538  xfem_face_weight_multipliers, elem, _current_qrule_face, _current_q_points_face, side))
4539  {
4540  mooseAssert(xfem_face_weight_multipliers.size() == _current_JxW_face.size(),
4541  "Size of weight multipliers in xfem doesn't match number of quadrature points");
4542  for (unsigned i = 0; i < xfem_face_weight_multipliers.size(); i++)
4543  _current_JxW_face[i] = _current_JxW_face[i] * xfem_face_weight_multipliers[i];
4544 
4545  xfem_face_weight_multipliers.release();
4546  }
4547 }
4548 
4549 void
4551 {
4552  _scaling_vector = &_sys.getVector("scaling_factors");
4553 }
4554 
4555 void
4556 Assembly::modifyArbitraryWeights(const std::vector<Real> & weights)
4557 {
4558  mooseAssert(_current_qrule == _current_qrule_arbitrary, "Rule should be arbitrary");
4559  mooseAssert(weights.size() == _current_physical_points.size(), "Size mismatch");
4560 
4561  for (MooseIndex(weights.size()) i = 0; i < weights.size(); ++i)
4562  _current_JxW[i] = weights[i];
4563 }
4564 
4565 template <>
4567 Assembly::fePhi<VectorValue<Real>>(FEType type) const
4568 {
4569  buildVectorFE(type);
4570  return _vector_fe_shape_data[type]->_phi;
4571 }
4572 
4573 template <>
4575 Assembly::feGradPhi<VectorValue<Real>>(FEType type) const
4576 {
4577  buildVectorFE(type);
4578  return _vector_fe_shape_data[type]->_grad_phi;
4579 }
4580 
4581 template <>
4583 Assembly::feSecondPhi<VectorValue<Real>>(FEType type) const
4584 {
4585  _need_second_derivative.insert(type);
4586  buildVectorFE(type);
4587  return _vector_fe_shape_data[type]->_second_phi;
4588 }
4589 
4590 template <>
4592 Assembly::fePhiLower<VectorValue<Real>>(FEType type) const
4593 {
4594  buildVectorLowerDFE(type);
4595  return _vector_fe_shape_data_lower[type]->_phi;
4596 }
4597 
4598 template <>
4600 Assembly::feDualPhiLower<VectorValue<Real>>(FEType type) const
4601 {
4602  buildVectorDualLowerDFE(type);
4603  return _vector_fe_shape_data_dual_lower[type]->_phi;
4604 }
4605 
4606 template <>
4608 Assembly::feGradPhiLower<VectorValue<Real>>(FEType type) const
4609 {
4610  buildVectorLowerDFE(type);
4611  return _vector_fe_shape_data_lower[type]->_grad_phi;
4612 }
4613 
4614 template <>
4616 Assembly::feGradDualPhiLower<VectorValue<Real>>(FEType type) const
4617 {
4618  buildVectorDualLowerDFE(type);
4619  return _vector_fe_shape_data_dual_lower[type]->_grad_phi;
4620 }
4621 
4622 template <>
4624 Assembly::fePhiFace<VectorValue<Real>>(FEType type) const
4625 {
4626  buildVectorFaceFE(type);
4627  return _vector_fe_shape_data_face[type]->_phi;
4628 }
4629 
4630 template <>
4632 Assembly::feGradPhiFace<VectorValue<Real>>(FEType type) const
4633 {
4634  buildVectorFaceFE(type);
4635  return _vector_fe_shape_data_face[type]->_grad_phi;
4636 }
4637 
4638 template <>
4640 Assembly::feSecondPhiFace<VectorValue<Real>>(FEType type) const
4641 {
4642  _need_second_derivative.insert(type);
4643  buildVectorFaceFE(type);
4644 
4645  // If we're building for a face we probably need to build for a
4646  // neighbor while _need_second_derivative is set;
4647  // onInterface/reinitNeighbor/etc don't distinguish
4648  buildVectorFaceNeighborFE(type);
4649 
4650  return _vector_fe_shape_data_face[type]->_second_phi;
4651 }
4652 
4653 template <>
4655 Assembly::fePhiNeighbor<VectorValue<Real>>(FEType type) const
4656 {
4657  buildVectorNeighborFE(type);
4658  return _vector_fe_shape_data_neighbor[type]->_phi;
4659 }
4660 
4661 template <>
4663 Assembly::feGradPhiNeighbor<VectorValue<Real>>(FEType type) const
4664 {
4665  buildVectorNeighborFE(type);
4666  return _vector_fe_shape_data_neighbor[type]->_grad_phi;
4667 }
4668 
4669 template <>
4671 Assembly::feSecondPhiNeighbor<VectorValue<Real>>(FEType type) const
4672 {
4673  _need_second_derivative_neighbor.insert(type);
4674  buildVectorNeighborFE(type);
4675  return _vector_fe_shape_data_neighbor[type]->_second_phi;
4676 }
4677 
4678 template <>
4680 Assembly::fePhiFaceNeighbor<VectorValue<Real>>(FEType type) const
4681 {
4682  buildVectorFaceNeighborFE(type);
4683  return _vector_fe_shape_data_face_neighbor[type]->_phi;
4684 }
4685 
4686 template <>
4688 Assembly::feGradPhiFaceNeighbor<VectorValue<Real>>(FEType type) const
4689 {
4690  buildVectorFaceNeighborFE(type);
4691  return _vector_fe_shape_data_face_neighbor[type]->_grad_phi;
4692 }
4693 
4694 template <>
4696 Assembly::feSecondPhiFaceNeighbor<VectorValue<Real>>(FEType type) const
4697 {
4698  _need_second_derivative_neighbor.insert(type);
4699  buildVectorFaceNeighborFE(type);
4700  return _vector_fe_shape_data_face_neighbor[type]->_second_phi;
4701 }
4702 
4703 template <>
4705 Assembly::feCurlPhi<VectorValue<Real>>(FEType type) const
4706 {
4707  _need_curl.insert(type);
4708  buildVectorFE(type);
4709  return _vector_fe_shape_data[type]->_curl_phi;
4710 }
4711 
4712 template <>
4714 Assembly::feCurlPhiFace<VectorValue<Real>>(FEType type) const
4715 {
4716  _need_curl.insert(type);
4717  buildVectorFaceFE(type);
4718 
4719  // If we're building for a face we probably need to build for a
4720  // neighbor while _need_curl is set;
4721  // onInterface/reinitNeighbor/etc don't distinguish
4722  buildVectorFaceNeighborFE(type);
4723 
4724  return _vector_fe_shape_data_face[type]->_curl_phi;
4725 }
4726 
4727 template <>
4729 Assembly::feCurlPhiNeighbor<VectorValue<Real>>(FEType type) const
4730 {
4731  _need_curl.insert(type);
4732  buildVectorNeighborFE(type);
4733  return _vector_fe_shape_data_neighbor[type]->_curl_phi;
4734 }
4735 
4736 template <>
4738 Assembly::feCurlPhiFaceNeighbor<VectorValue<Real>>(FEType type) const
4739 {
4740  _need_curl.insert(type);
4741  buildVectorFaceNeighborFE(type);
4742 
4743  return _vector_fe_shape_data_face_neighbor[type]->_curl_phi;
4744 }
4745 
4746 template <>
4748 Assembly::feDivPhi<VectorValue<Real>>(FEType type) const
4749 {
4750  _need_div.insert(type);
4751  buildVectorFE(type);
4752  return _vector_fe_shape_data[type]->_div_phi;
4753 }
4754 
4755 template <>
4757 Assembly::feDivPhiFace<VectorValue<Real>>(FEType type) const
4758 {
4759  _need_face_div.insert(type);
4760  buildVectorFaceFE(type);
4761 
4762  // If we're building for a face we probably need to build for a
4763  // neighbor while _need_face_div is set;
4764  // onInterface/reinitNeighbor/etc don't distinguish
4765  buildVectorFaceNeighborFE(type);
4766 
4767  return _vector_fe_shape_data_face[type]->_div_phi;
4768 }
4769 
4770 template <>
4772 Assembly::feDivPhiNeighbor<VectorValue<Real>>(FEType type) const
4773 {
4774  _need_neighbor_div.insert(type);
4775  buildVectorNeighborFE(type);
4776  return _vector_fe_shape_data_neighbor[type]->_div_phi;
4777 }
4778 
4779 template <>
4781 Assembly::feDivPhiFaceNeighbor<VectorValue<Real>>(FEType type) const
4782 {
4783  _need_face_neighbor_div.insert(type);
4784  buildVectorFaceNeighborFE(type);
4785  return _vector_fe_shape_data_face_neighbor[type]->_div_phi;
4786 }
4787 
4788 const MooseArray<ADReal> &
4790 {
4791  _calculate_curvatures = true;
4792  const Order helper_order = _mesh.hasSecondOrderElements() ? SECOND : FIRST;
4793  const FEType helper_type(helper_order, LAGRANGE);
4794  // Must prerequest the second derivatives. Sadly because there is only one
4795  // _need_second_derivative map for both volumetric and face FE objects we must request both here
4796  feSecondPhi<Real>(helper_type);
4797  feSecondPhiFace<Real>(helper_type);
4798  return _ad_curvatures;
4799 }
4800 
4801 void
4803 {
4804  for (unsigned int dim = 0; dim <= _mesh_dimension; dim++)
4805  {
4806  _holder_fe_helper[dim]->get_phi();
4807  _holder_fe_helper[dim]->get_dphi();
4808  _holder_fe_helper[dim]->get_xyz();
4809  _holder_fe_helper[dim]->get_JxW();
4810 
4811  _holder_fe_face_helper[dim]->get_phi();
4812  _holder_fe_face_helper[dim]->get_dphi();
4813  _holder_fe_face_helper[dim]->get_xyz();
4814  _holder_fe_face_helper[dim]->get_JxW();
4815  _holder_fe_face_helper[dim]->get_normals();
4816 
4819  _holder_fe_face_neighbor_helper[dim]->get_normals();
4820 
4821  _holder_fe_neighbor_helper[dim]->get_xyz();
4822  _holder_fe_neighbor_helper[dim]->get_JxW();
4823  }
4824 
4825  for (unsigned int dim = 0; dim < _mesh_dimension; dim++)
4826  {
4827  // We need these computations in order to compute correct lower-d element volumes in
4828  // curvilinear coordinates
4829  _holder_fe_lower_helper[dim]->get_xyz();
4830  _holder_fe_lower_helper[dim]->get_JxW();
4831  }
4832 }
4833 
4834 void
4835 Assembly::havePRefinement(const std::unordered_set<FEFamily> & disable_families)
4836 {
4837  if (_have_p_refinement)
4838  // Already performed tasks for p-refinement
4839  return;
4840 
4841  const Order helper_order = _mesh.hasSecondOrderElements() ? SECOND : FIRST;
4842  const FEType helper_type(helper_order, LAGRANGE);
4843  auto process_fe =
4844  [&disable_families](const unsigned int num_dimensionalities, auto & fe_container)
4845  {
4846  if (!disable_families.empty())
4847  for (const auto dim : make_range(num_dimensionalities))
4848  {
4849  auto fe_container_it = fe_container.find(dim);
4850  if (fe_container_it != fe_container.end())
4851  for (auto & [fe_type, fe_ptr] : fe_container_it->second)
4852  if (disable_families.count(fe_type.family))
4853  fe_ptr->add_p_level_in_reinit(false);
4854  }
4855  };
4856  auto process_fe_and_helpers = [process_fe, &helper_type](auto & unique_helper_container,
4857  auto & helper_container,
4858  const unsigned int num_dimensionalities,
4859  const bool user_added_helper_type,
4860  auto & fe_container)
4861  {
4862  unique_helper_container.resize(num_dimensionalities);
4863  for (const auto dim : make_range(num_dimensionalities))
4864  {
4865  auto & unique_helper = unique_helper_container[dim];
4866  unique_helper = FEGenericBase<Real>::build(dim, helper_type);
4867  // don't participate in p-refinement
4868  unique_helper->add_p_level_in_reinit(false);
4869  helper_container[dim] = unique_helper.get();
4870 
4871  // If the user did not request the helper type then we should erase it from our FE container
4872  // so that they're not penalized (in the "we should be able to do p-refinement sense") for
4873  // our perhaps silly helpers
4874  if (!user_added_helper_type)
4875  {
4876  auto & fe_container_dim = libmesh_map_find(fe_container, dim);
4877  auto fe_it = fe_container_dim.find(helper_type);
4878  mooseAssert(fe_it != fe_container_dim.end(), "We should have the helper type");
4879  delete fe_it->second;
4880  fe_container_dim.erase(fe_it);
4881  }
4882  }
4883 
4884  process_fe(num_dimensionalities, fe_container);
4885  };
4886 
4887  // Handle scalar field families
4888  process_fe_and_helpers(_unique_fe_helper,
4890  _mesh_dimension + 1,
4892  _fe);
4893  process_fe_and_helpers(_unique_fe_face_helper,
4895  _mesh_dimension + 1,
4897  _fe_face);
4898  process_fe_and_helpers(_unique_fe_face_neighbor_helper,
4900  _mesh_dimension + 1,
4903  process_fe_and_helpers(_unique_fe_neighbor_helper,
4905  _mesh_dimension + 1,
4907  _fe_neighbor);
4908  process_fe_and_helpers(_unique_fe_lower_helper,
4912  _fe_lower);
4913  // Handle vector field families
4914  process_fe(_mesh_dimension + 1, _vector_fe);
4915  process_fe(_mesh_dimension + 1, _vector_fe_face);
4916  process_fe(_mesh_dimension + 1, _vector_fe_neighbor);
4917  process_fe(_mesh_dimension + 1, _vector_fe_face_neighbor);
4918  process_fe(_mesh_dimension, _vector_fe_lower);
4919 
4921 
4922  _have_p_refinement = true;
4923 }
4924 
4925 template void coordTransformFactor<Point, Real>(const SubProblem & s,
4926  SubdomainID sub_id,
4927  const Point & point,
4928  Real & factor,
4929  SubdomainID neighbor_sub_id);
4930 template void coordTransformFactor<ADPoint, ADReal>(const SubProblem & s,
4931  SubdomainID sub_id,
4932  const ADPoint & point,
4933  ADReal & factor,
4934  SubdomainID neighbor_sub_id);
4935 template void coordTransformFactor<Point, Real>(const MooseMesh & mesh,
4936  SubdomainID sub_id,
4937  const Point & point,
4938  Real & factor,
4939  SubdomainID neighbor_sub_id);
4941  SubdomainID sub_id,
4942  const ADPoint & point,
4943  ADReal & factor,
4944  SubdomainID neighbor_sub_id);
4945 
4946 template <>
4948 Assembly::genericQPoints<false>() const
4949 {
4950  return qPoints();
4951 }
4952 
4953 template <>
4955 Assembly::genericQPoints<true>() const
4956 {
4957  return adQPoints();
4958 }
const Elem *const & elem() const
Return the current element.
Definition: Assembly.h:414
virtual MooseMesh & mesh()=0
MooseArray< VectorValue< ADReal > > _ad_normals
Definition: Assembly.h:2851
void copyShapes(MooseVariableField< T > &v)
Definition: Assembly.C:3001
libMesh::ElemSideBuilder _compute_face_map_side_elem_builder
In place side element builder for computeFaceMap()
Definition: Assembly.h:2885
std::map< unsigned int, std::map< FEType, FEBase * > > _fe_face
types of finite elements
Definition: Assembly.h:2518
bool _need_neighbor_elem_volume
true is apps need to compute neighbor element volume
Definition: Assembly.h:2622
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:3440
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:2418
std::map< FEType, FEBase * > _current_fe
The "volume" fe object that matches the current elem.
Definition: Assembly.h:2386
MooseArray< Real > _curvatures
Definition: Assembly.h:2853
const std::vector< MooseVariableFieldBase * > & getVariables(THREAD_ID tid)
Definition: SystemBase.h:751
std::vector< ADReal > _ad_detadz_map
Definition: Assembly.h:2845
VectorVariablePhiValue _phi
Definition: Assembly.h:2761
std::unique_ptr< FEGenericBase< Real > > build(const unsigned int dim, const FEType &fet)
SystemBase & _sys
Definition: Assembly.h:2316
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:2805
std::vector< std::vector< dof_id_type > > _cached_jacobian_rows
Row where the corresponding cached value should go.
Definition: Assembly.h:2812
unsigned int _max_cached_residuals
Definition: Assembly.h:2807
std::map< FEType, ADTemplateVariablePhiGradient< Real > > _ad_grad_phi_data_face
Definition: Assembly.h:2786
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:2369
MooseArray< Point > _current_physical_points
This will be filled up with the physical points passed into reinitAtPhysical() if it is called...
Definition: Assembly.h:2650
const VariablePhiGradient & gradPhiFaceNeighbor(const MooseVariableField< Real > &) const
Definition: Assembly.h:1363
std::vector< std::unique_ptr< FEBase > > _unique_fe_lower_helper
Definition: Assembly.h:2377
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:2430
virtual const FieldVariablePhiValue & phi() const =0
Return the variable&#39;s elemental shape functions.
void buildNeighborFE(FEType type) const
Build FEs for a neighbor with a type.
Definition: Assembly.C:314
const VariablePhiSecond & secondPhi() const
Definition: Assembly.h:1328
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:2408
typename OutputTools< typename Moose::ADType< T >::type >::VariablePhiGradient ADTemplateVariablePhiGradient
Definition: MooseTypes.h:682
const std::vector< std::vector< OutputShape > > & get_dual_phi() const
void buildVectorLowerDFE(FEType type) const
Build Vector FEs for a lower dimensional element with a type.
Definition: Assembly.C:403
MooseArray< Real > _coord_neighbor
The current coordinate transformation coefficients.
Definition: Assembly.h:2575
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:2695
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:3454
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:2769
void buildLowerDDualFE(FEType type) const
Definition: Assembly.C:382
unsigned int TagID
Definition: MooseTypes.h:238
virtual bool checkNonlocalCouplingRequirement() const =0
MooseArray< Real > _current_JxW_neighbor
The current transformed jacobian weights on a neighbor&#39;s face.
Definition: Assembly.h:2573
std::shared_ptr< XFEMInterface > _xfem
The XFEM controller.
Definition: Assembly.h:2383
void reinitNeighborLowerDElem(const Elem *elem)
reinitialize a neighboring lower dimensional element
Definition: Assembly.C:2383
virtual ~Assembly()
Definition: Assembly.C:186
void prepareJacobianBlock()
Sizes and zeroes the Jacobian blocks used for the current element.
Definition: Assembly.C:2684
DenseMatrix< Number > & jacobianBlockNonlocal(unsigned int ivar, unsigned int jvar, LocalDataKey, TagID tag)
Get local Jacobian block from non-local contribution for a pair of variables and a tag...
Definition: Assembly.h:1153
void mooseError(Args &&... args)
Emit an error message with the given stringified, concatenated args and terminate the application...
Definition: MooseError.h:323
virtual void zero() override final
std::vector< std::vector< std::vector< DenseMatrix< Number > > > > _sub_Kel
dsecondary/dlower (or delement/dlower)
Definition: Assembly.h:2699
const std::vector< Real > & arrayScalingFactor() const
MooseArray< Real > _coord
The current coordinate transformation coefficients.
Definition: Assembly.h:2428
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:3118
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:2567
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:2243
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:2724
std::map< unsigned int, FEBase * > _holder_fe_neighbor_helper
Each dimension&#39;s helper objects.
Definition: Assembly.h:2556
std::unique_ptr< FEBase > _fe_msm
A FE object for working on mortar segement elements.
Definition: Assembly.h:2585
std::map< FEType, std::unique_ptr< FEShapeData > > _fe_shape_data_face_neighbor
Definition: Assembly.h:2772
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:1792
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:3513
bool _current_elem_volume_computed
Boolean to indicate whether current element volumes has been computed.
Definition: Assembly.h:2630
std::vector< ADReal > _ad_detady_map
Definition: Assembly.h:2844
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:2279
const VectorVariablePhiDivergence & divPhi(const MooseVariableField< RealVectorValue > &) const
Definition: Assembly.h:1388
std::vector< ADReal > _ad_dzetadz_map
Definition: Assembly.h:2848
std::vector< std::unique_ptr< FEBase > > _unique_fe_neighbor_helper
Definition: Assembly.h:2376
std::vector< std::vector< std::vector< DenseMatrix< Number > > > > _sub_Kll
dlower/dlower
Definition: Assembly.h:2693
bool _user_added_fe_face_neighbor_of_helper_type
Definition: Assembly.h:2367
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:3540
bool _have_p_refinement
Whether we have ever conducted p-refinement.
Definition: Assembly.h:2905
VariablePhiValue _phi
Definition: Assembly.h:2751
char ** vars
Real _current_neighbor_volume
Volume of the current neighbor.
Definition: Assembly.h:2624
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:2297
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:1923
std::map< FEType, FEBase * > _current_fe_face
The "face" fe object that matches the current elem.
Definition: Assembly.h:2388
const VectorVariablePhiCurl & curlPhi(const MooseVariableField< RealVectorValue > &) const
Definition: Assembly.h:1384
std::vector< Point > _current_neighbor_ref_points
The current reference points on the neighbor element.
Definition: Assembly.h:2908
std::vector< std::vector< std::vector< DenseMatrix< Number > > > > _sub_Kln
dlower/dprimary (or dlower/dneighbor)
Definition: Assembly.h:2697
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:2614
void addJacobianNonlocal(GlobalDataKey)
Adds non-local Jacobian to the global Jacobian matrices.
Definition: Assembly.C:3861
std::vector< std::vector< DenseVector< Number > > > _sub_Rn
Definition: Assembly.h:2665
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:1319
MooseMesh & _mesh
Definition: Assembly.h:2356
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:2771
std::map< unsigned int, FEBase * > _holder_fe_face_neighbor_helper
Definition: Assembly.h:2557
unsigned int n_elem_integers() const
MeshBase & mesh
const VariablePhiGradient & gradPhi() const
Definition: Assembly.h:1326
MooseArray< Real > _current_JxW_face
The current transformed jacobian weights on a face.
Definition: Assembly.h:2532
void modifyWeightsDueToXFEM(const Elem *elem)
Update the integration weights for XFEM partial elements.
Definition: Assembly.C:4509
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:2600
const VariablePhiSecond & secondPhiNeighbor(const MooseVariableField< Real > &) const
Definition: Assembly.h:1354
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:2354
void reinitFEFaceNeighbor(const Elem *neighbor, const std::vector< Point > &reference_points)
Definition: Assembly.C:1573
static constexpr std::size_t dim
This is the dimension of all vector and tensor datastructures used in MOOSE.
Definition: Moose.h:162
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:2374
QuadratureType
std::vector< std::vector< std::vector< unsigned char > > > _jacobian_block_nonlocal_used
Definition: Assembly.h:2346
std::vector< std::pair< MooseVariableScalar *, MooseVariableFieldBase * > > _cm_sf_entry
Entries in the coupling matrix for scalar variables vs field variables.
Definition: Assembly.h:2339
void prepareNeighbor()
Definition: Assembly.C:2810
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:348
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:1731
std::map< unsigned int, std::map< FEType, FEVectorBase * > > _vector_fe_face_neighbor
Definition: Assembly.h:2553
const VariablePhiValue & phiFaceNeighbor(const MooseVariableField< Real > &) const
Definition: Assembly.h:1359
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:2822
Real _current_elem_volume
Volume of the current element.
Definition: Assembly.h:2606
std::map< FEType, FEBase * > _current_fe_face_neighbor
The "neighbor face" fe object that matches the current elem.
Definition: Assembly.h:2392
const MooseArray< ADReal > & adCurvatures() const
Definition: Assembly.C:4789
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:2397
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:2373
const FEType _helper_type
The finite element type of the FE helper classes.
Definition: Assembly.h:2362
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:3359
DenseMatrix< Number > & jacobianBlock(unsigned int ivar, unsigned int jvar, LocalDataKey, TagID tag)
Get local Jacobian block for a pair of variables and a tag.
Definition: Assembly.h:1142
The following methods are specializations for using the libMesh::Parallel::packed_range_* routines fo...
void addJacobianScalar(GlobalDataKey)
Add Jacobians for pairs of scalar variables into the global Jacobian matrices.
Definition: Assembly.C:4431
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:2691
Base class for a system (of equations)
Definition: SystemBase.h:84
libMesh::QBase * _current_qrule_face
quadrature rule used on faces
Definition: Assembly.h:2526
const VariablePhiValue & phiNeighbor(const MooseVariableField< Real > &) const
Definition: Assembly.h:1346
unsigned int numExtraElemIntegers() const
Number of extra element integers Assembly tracked.
Definition: Assembly.h:373
std::set< FEType > _need_second_derivative_neighbor
Definition: Assembly.h:2870
void setWeights(const std::vector< libMesh::Real > &weights)
Set the quadrature weights.
DualNumber< Real, DNDerivativeType, true > ADReal
Definition: ADRealForward.h:42
std::vector< std::vector< Real > > _cached_jacobian_values
Values cached by calling cacheJacobian()
Definition: Assembly.h:2810
std::vector< std::pair< MooseVariableFieldBase *, MooseVariableFieldBase * > > _cm_ff_entry
Entries in the coupling matrix for field variables.
Definition: Assembly.h:2335
void addJacobianNeighborLowerD(GlobalDataKey)
Add all portions of the Jacobian except PrimaryPrimary, e.g.
Definition: Assembly.C:3921
std::map< FEType, FEVectorBase * > _current_vector_fe
The "volume" vector fe object that matches the current elem.
Definition: Assembly.h:2395
VariablePhiGradient _grad_phi
Definition: Assembly.h:2752
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:2832
void prepareScalar()
Definition: Assembly.C:2951
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:4529
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:1994
OutputTools< Real >::VariablePhiSecond VariablePhiSecond
Definition: MooseTypes.h:350
std::unique_ptr< libMesh::QBase > face
area/face (meshdim-1) quadrature rule
Definition: Assembly.h:2448
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:2670
unsigned int _mesh_dimension
Definition: Assembly.h:2358
virtual QuadratureType type() const=0
std::vector< Eigen::Map< RealDIMValue > > _mapped_normals
Mapped normals.
Definition: Assembly.h:2536
VectorVariablePhiDivergence _vector_div_phi_face
Definition: Assembly.h:2734
void cacheJacobian(GlobalDataKey)
Takes the values that are currently in _sub_Kee and appends them to the cached values.
Definition: Assembly.C:4036
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:2878
auto max(const L &left, const R &right)
void processLocalResidual(DenseVector< Number > &res_block, std::vector< dof_id_type > &dof_indices, const std::vector< Real > &scaling_factor)
Appling scaling, constraints to the local residual block and populate the full DoF indices for array ...
Definition: Assembly.C:3219
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:3468
Data structure for tracking/grouping a set of quadrature rules for a particular dimensionality of mes...
Definition: Assembly.h:2434
MONOMIAL_VEC
const std::vector< std::vector< Real > > & get_dphideta_map() const
unsigned int _max_cached_jacobians
Definition: Assembly.h:2816
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:3159
QUAD4
std::vector< std::vector< std::vector< DenseMatrix< Number > > > > _sub_Ken
jacobian contributions from the element and neighbor <Tag, ivar, jvar>
Definition: Assembly.h:2687
FEType get_fe_type() const
std::map< FEType, std::unique_ptr< VectorFEShapeData > > _vector_fe_shape_data_dual_lower
Definition: Assembly.h:2782
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:2833
std::vector< Point > _temp_reference_points
Temporary work data for reinitAtPhysical()
Definition: Assembly.h:2828
std::vector< std::pair< MooseVariableScalar *, MooseVariableScalar * > > _cm_ss_entry
Entries in the coupling matrix for scalar variables.
Definition: Assembly.h:2341
std::vector< std::vector< std::vector< DenseMatrix< Number > > > > _sub_Kne
jacobian contributions from the neighbor and element <Tag, ivar, jvar>
Definition: Assembly.h:2689
const Elem * _current_neighbor_lower_d_elem
The current neighboring lower dimensional element.
Definition: Assembly.h:2637
unsigned int _current_neighbor_side
The current side of the selected neighboring element (valid only when working with sides) ...
Definition: Assembly.h:2618
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:3422
void init(const libMesh::CouplingMatrix *cm)
Initialize the Assembly object and set the CouplingMatrix for use throughout.
Definition: Assembly.C:2467
void prepareLowerD()
Prepare the Jacobians and residuals for a lower dimensional element.
Definition: Assembly.C:2848
bool _user_added_fe_neighbor_of_helper_type
Definition: Assembly.h:2368
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:2778
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:2290
void computeCurrentFaceVolume()
Definition: Assembly.C:1773
std::vector< std::vector< DenseVector< Number > > > _sub_Rl
residual contributions for each variable from the lower dimensional element
Definition: Assembly.h:2667
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:2494
virtual const FieldVariablePhiSecond & secondPhiFaceNeighbor() const =0
Return the rank-2 tensor of second derivatives of the variable&#39;s shape functions on a neighboring ele...
virtual const std::vector< dof_id_type > & dofIndicesNeighbor() const =0
Get neighbor DOF indices for currently selected element.
CONSTANT
std::unique_ptr< libMesh::QBase > vol
volume/elem (meshdim) quadrature rule
Definition: Assembly.h:2446
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:2975
VectorVariablePhiSecond _second_phi
Definition: Assembly.h:2763
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:3833
std::vector< ADReal > _ad_dzetadx_map
Definition: Assembly.h:2846
void addJacobianLowerD(GlobalDataKey)
Add portions of the Jacobian of LowerLower, LowerSecondary, and SecondaryLower for boundary condition...
Definition: Assembly.C:3999
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:2762
MooseArray< ADReal > _ad_curvatures
Definition: Assembly.h:2854
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:2420
void modifyArbitraryWeights(const std::vector< Real > &weights)
Modify the weights when using the arbitrary quadrature rule.
Definition: Assembly.C:4556
std::vector< std::pair< MooseVariableFieldBase *, MooseVariableScalar * > > _cm_fs_entry
Entries in the coupling matrix for field variables vs scalar variables.
Definition: Assembly.h:2337
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:2583
dof_id_type id() const
std::vector< ADReal > _ad_dzetady_map
Definition: Assembly.h:2847
Real value(unsigned n, unsigned alpha, unsigned beta, Real x)
MeshBase & getMesh()
Accessor for the underlying libMesh Mesh object.
Definition: MooseMesh.C:3528
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:2784
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:2463
unsigned int n_vars
void prepareResidual()
Sizes and zeroes the residual for the current element.
Definition: Assembly.C:2708
VectorVariablePhiCurl _curl_phi
Definition: Assembly.h:2764
std::map< FEType, FEBase * > _current_fe_neighbor
The "neighbor" fe object that matches the current elem.
Definition: Assembly.h:2390
Real elementVolume(const Elem *elem) const
On-demand computation of volume element accounting for RZ/RSpherical.
Definition: Assembly.C:3758
void cacheJacobianNeighbor(GlobalDataKey)
Takes the values that are currently in the neighbor Dense Matrices and appends them to the cached val...
Definition: Assembly.C:4088
SubdomainID _current_neighbor_subdomain_id
The current neighbor subdomain ID.
Definition: Assembly.h:2616
const std::vector< std::vector< OutputGradient > > & get_dual_dphi() const
std::vector< std::vector< DenseVector< Number > > > _sub_Re
Definition: Assembly.h:2664
void reinitNeighbor(const Elem *neighbor, const std::vector< Point > &reference_points)
Reinitializes the neighbor side using reference coordinates.
Definition: Assembly.C:1687
std::vector< ADReal > _ad_dxidz_map
Definition: Assembly.h:2842
std::vector< std::vector< std::vector< unsigned char > > > _jacobian_block_used
Flag that indicates if the jacobian block was used.
Definition: Assembly.h:2345
void prepare()
Definition: Assembly.C:2717
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:92
libMesh::QBase * _current_qrule_lower
quadrature rule used on lower dimensional elements.
Definition: Assembly.h:2596
SubProblem & _subproblem
Definition: Assembly.h:2317
libmesh_assert(ctx)
std::vector< ADReal > _ad_detadx_map
Definition: Assembly.h:2843
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:2550
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:3390
bool _calculate_xyz
Definition: Assembly.h:2861
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:4332
MooseArray< std::vector< Point > > _current_tangents
The current tangent vectors at the quadrature points.
Definition: Assembly.h:2538
virtual const std::vector< dof_id_type > & dofIndices() const
Get local DoF indices.
bool _calculate_curvatures
Definition: Assembly.h:2863
const std::vector< VectorTag > & _residual_vector_tags
The residual vector tags that Assembly could possibly contribute to.
Definition: Assembly.h:2799
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:2401
std::vector< dof_id_type > _neighbor_extra_elem_ids
Extra element IDs of neighbor.
Definition: Assembly.h:2543
MooseArray< Real > _current_JxW
The current list of transformed jacobian weights.
Definition: Assembly.h:2424
Order get_order() const
std::vector< VectorValue< ADReal > > _ad_dxyzdxi_map
AD quantities.
Definition: Assembly.h:2831
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:2859
std::vector< dof_id_type > _temp_dof_indices
Temporary work vector to keep from reallocating it.
Definition: Assembly.h:2825
std::set< FEType > _need_neighbor_div
Definition: Assembly.h:2874
L2_RAVIART_THOMAS
OutputTools< Real >::VariablePhiCurl VariablePhiCurl
Definition: MooseTypes.h:351
std::vector< std::vector< std::vector< DenseMatrix< Number > > > > _sub_Kee
Definition: Assembly.h:2683
std::vector< VectorValue< ADReal > > _ad_d2xyzdxi2_map
Definition: Assembly.h:2834
unsigned int get_dim() const
std::vector< ADReal > _ad_jac
Definition: Assembly.h:2837
std::set< FEType > _need_curl
Definition: Assembly.h:2871
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:4274
unsigned int n_points() const
std::map< FEType, std::unique_ptr< VectorFEShapeData > > _vector_fe_shape_data_lower
Definition: Assembly.h:2781
OStreamProxy err(std::cerr)
const VariablePhiSecond & secondPhiFace(const MooseVariableField< Real > &) const
Definition: Assembly.h:1341
std::map< FEType, ADTemplateVariablePhiGradient< RealVectorValue > > _ad_vector_grad_phi_data
Definition: Assembly.h:2785
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:2520
libMesh::QBase * _current_qrule_volume
The current volumetric quadrature for the element.
Definition: Assembly.h:2416
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:2887
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:1917
bool _calculate_ad_coord
Whether to calculate coord with AD.
Definition: Assembly.h:2867
std::map< FEType, std::unique_ptr< FEShapeData > > _fe_shape_data_lower
Definition: Assembly.h:2773
const Elem * _current_lower_d_elem
The current lower dimensional element.
Definition: Assembly.h:2635
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:3315
const VariablePhiValue & phiFace() const
Definition: Assembly.h:1334
std::set< FEType > _need_second_derivative
Definition: Assembly.h:2869
std::map< unsigned int, std::map< FEType, FEBase * > > _fe_lower
FE objects for lower dimensional elements.
Definition: Assembly.h:2560
bool hasSecondOrderElements()
check if the mesh has SECOND order elements
Definition: MooseMesh.C:3791
std::set< FEType > _need_face_neighbor_div
Definition: Assembly.h:2875
libMesh::QBase * _qrule_msm
A qrule object for working on mortar segement elements.
Definition: Assembly.h:2590
libMesh::ElemSideBuilder _current_neighbor_side_elem_builder
In place side element builder for _current_neighbor_side_elem.
Definition: Assembly.h:2883
OutputTools< Real >::VariablePhiDivergence VariablePhiDivergence
Definition: MooseTypes.h:352
Real _current_lower_d_elem_volume
The current lower dimensional element volume.
Definition: Assembly.h:2641
libMesh::QBase * _current_qrule
The current current quadrature rule being used (could be either volumetric or arbitrary - for dirac k...
Definition: Assembly.h:2414
std::map< unsigned int, std::map< FEType, FEBase * > > _fe
Each dimension&#39;s actual fe objects indexed on type.
Definition: Assembly.h:2406
const MooseArray< Real > & JxW() const
Returns the reference to the transformed jacobian weights.
Definition: Assembly.h:276
void reinitMortarElem(const Elem *elem)
reinitialize a mortar segment mesh element in order to get a proper JxW
Definition: Assembly.C:2404
Real _current_side_volume
Volume of the current side element.
Definition: Assembly.h:2612
std::set< FEType > _need_div
Definition: Assembly.h:2872
std::vector< std::vector< Real > > _cached_residual_values
Values cached by calling cacheResidual() (the first vector is for TIME vs NONTIME) ...
Definition: Assembly.h:2802
const bool _displaced
Definition: Assembly.h:2319
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:4416
void reinitFVFace(const FaceInfo &fi)
Definition: Assembly.C:1857
std::map< unsigned int, std::map< FEType, FEVectorBase * > > _vector_fe_lower
Vector FE objects for lower dimensional elements.
Definition: Assembly.h:2562
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:2626
bool _building_helpers
Whether we are currently building the FE classes for the helpers.
Definition: Assembly.h:2380
bool _calculate_face_xyz
Definition: Assembly.h:2862
virtual unsigned int numMatrixTags() const
The total number of tags.
Definition: SubProblem.h:248
DGJacobianType
Definition: MooseTypes.h:798
OutputTools< Real >::VariablePhiGradient VariablePhiGradient
Definition: MooseTypes.h:349
std::vector< ADReal > _ad_dxidx_map
Definition: Assembly.h:2840
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:2841
std::vector< VectorValue< ADReal > > _ad_d2xyzdxideta_map
Definition: Assembly.h:2835
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:2780
void addJacobian(GlobalDataKey)
Adds all local Jacobian to the global Jacobian matrices.
Definition: Assembly.C:3848
MooseArray< Point > _current_normals
The current Normal vectors at the quadrature points.
Definition: Assembly.h:2534
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:4835
const SubdomainID ANY_BLOCK_ID
Definition: MooseTypes.C:19
MooseArray< VectorValue< ADReal > > _ad_q_points
Definition: Assembly.h:2839
const VariablePhiGradient & gradPhiNeighbor(const MooseVariableField< Real > &) const
Definition: Assembly.h:1350
MooseArray< VectorValue< ADReal > > _ad_q_points_face
Definition: Assembly.h:2852
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:2322
void hasScalingVector()
signals this object that a vector containing variable scaling factors should be used when doing resid...
Definition: Assembly.C:4550
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:2774
void zeroCachedJacobian(GlobalDataKey)
Zero out previously-cached Jacobian rows.
Definition: Assembly.C:4488
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:2194
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:2780
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:2770
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:2777
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:3382
MooseArray< Real > _coord_msm
The coordinate transformation coefficients evaluated on the quadrature points of the mortar segment m...
Definition: Assembly.h:2578
std::vector< std::vector< std::vector< DenseMatrix< Number > > > > _sub_Keg
Definition: Assembly.h:2684
bool _need_lower_d_elem_volume
Whether we need to compute the lower dimensional element volume.
Definition: Assembly.h:2639
bool _user_added_fe_face_of_helper_type
Definition: Assembly.h:2366
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:2452
void reinitFENeighbor(const Elem *neighbor, const std::vector< Point > &reference_points)
Definition: Assembly.C:1632
void initNonlocalCoupling()
Create pair of variables requiring nonlocal jacobian contributions.
Definition: Assembly.C:2649
ConstraintJacobianType
Definition: MooseTypes.h:845
std::map< unsigned int, FEBase * > _holder_fe_face_helper
Each dimension&#39;s helper objects.
Definition: Assembly.h:2522
const std::vector< std::vector< Real > > & get_dphidxi_map() const
const Elem *const & neighbor() const
Return the neighbor element.
Definition: Assembly.h:470
std::map< unsigned int, std::map< FEType, FEVectorBase * > > _vector_fe_neighbor
Definition: Assembly.h:2552
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:4066
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:2375
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:4802
std::vector< std::pair< MooseVariableFieldBase *, MooseVariableFieldBase * > > _cm_nonlocal_entry
Entries in the coupling matrix for field variables for nonlocal calculations.
Definition: Assembly.h:2343
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:4438
virtual void init(const Elem &e, unsigned int p_level=invalid_uint)
void cacheResidualBlock(std::vector< Real > &cached_residual_values, std::vector< dof_id_type > &cached_residual_rows, DenseVector< Number > &res_block, const std::vector< dof_id_type > &dof_indices, const std::vector< Real > &scaling_factor)
Push a local residual block with proper scaling into cache.
Definition: Assembly.C:3264
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:2608
void setCachedJacobian(GlobalDataKey)
Sets previously-cached Jacobian values via SparseMatrix::set() calls.
Definition: Assembly.C:4468
VariablePhiSecond _second_phi
Definition: Assembly.h:2753
const libMesh::CouplingMatrix & _nonlocal_cm
Definition: Assembly.h:2323
std::map< unsigned int, FEBase * > _holder_fe_helper
Each dimension&#39;s helper objects.
Definition: Assembly.h:2410
void prepareVariable(MooseVariableFieldBase *var)
Used for preparing the dense residual and jacobian blocks for one particular variable.
Definition: Assembly.C:2750
const Elem * _current_neighbor_side_elem
The current side element of the ncurrent neighbor element.
Definition: Assembly.h:2620
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:2019
void copyFaceShapes(MooseVariableField< T > &v)
Definition: Assembly.C:3038
std::vector< dof_id_type > _extra_elem_ids
Extra element IDs.
Definition: Assembly.h:2541
Moose::CoordinateSystemType getCoordSystem(SubdomainID sid) const
Definition: SubProblem.C:1283
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:4206
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:3337
bool _current_side_volume_computed
Boolean to indicate whether current element side volumes has been computed.
Definition: Assembly.h:2632
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:2788
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:2261
std::unique_ptr< ArbitraryQuadrature > arbitrary_face
area/face (meshdim-1) custom points quadrature rule
Definition: Assembly.h:2454
Eigen::Matrix< Real, Eigen::Dynamic, 1 > RealEigenVector
Definition: MooseTypes.h:147
virtual const std::vector< dof_id_type > & dofIndicesLower() const =0
Get dof indices for the current lower dimensional element (this is meaningful when performing mortar ...
void prepareBlock(unsigned int ivar, unsigned jvar, const std::vector< dof_id_type > &dof_indices)
Definition: Assembly.C:2900
std::map< unsigned int, std::map< FEType, FEBase * > > _fe_face_neighbor
Definition: Assembly.h:2551
void addJacobianNeighbor(GlobalDataKey)
Add ElementNeighbor, NeighborElement, and NeighborNeighbor portions of the Jacobian for compute objec...
Definition: Assembly.C:3883
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:2350
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:2765
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
void addResidualBlock(NumericVector< Number > &residual, DenseVector< Number > &res_block, const std::vector< dof_id_type > &dof_indices, const std::vector< Real > &scaling_factor)
Add a local residual block to a global residual vector with proper scaling.
Definition: Assembly.C:3249
bool _custom_mortar_qrule
Flag specifying whether a custom quadrature rule has been specified for mortar segment mesh...
Definition: Assembly.h:2592
const unsigned int & side() const
Returns the current side.
Definition: Assembly.h:446
void computeCurrentElemVolume()
Definition: Assembly.C:1754
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:3665
Real _current_neighbor_lower_d_elem_volume
The current neighboring lower dimensional element volume.
Definition: Assembly.h:2645
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:2643
MooseArray< Point > _current_q_points
The current list of quadrature points.
Definition: Assembly.h:2422
bool _user_added_fe_of_helper_type
Whether user code requested a FEType the same as our _helper_type.
Definition: Assembly.h:2365
void setResidualBlock(NumericVector< Number > &residual, DenseVector< Number > &res_block, const std::vector< dof_id_type > &dof_indices, const std::vector< Real > &scaling_factor)
Set a local residual block to a global residual vector with proper scaling.
Definition: Assembly.C:3287
Moose::CoordinateSystemType _coord_type
The coordinate system.
Definition: Assembly.h:2426
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:4126
std::unique_ptr< ArbitraryQuadrature > neighbor
area/face (meshdim-1) custom points quadrature rule for DG
Definition: Assembly.h:2456
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:545
std::vector< std::vector< std::vector< unsigned char > > > _jacobian_block_neighbor_used
Flag that indicates if the jacobian block for neighbor was used.
Definition: Assembly.h:2348
std::map< unsigned int, FEBase * > _holder_fe_lower_helper
helper object for transforming coordinates for lower dimensional element quadrature points ...
Definition: Assembly.h:2564
static constexpr subdomain_id_type invalid_subdomain_id
const libMesh::DofMap & _dof_map
DOF map.
Definition: Assembly.h:2352
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:2111
std::map< FEType, std::unique_ptr< VectorFEShapeData > > _vector_fe_shape_data_neighbor
Definition: Assembly.h:2779
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:3531
std::vector< std::vector< dof_id_type > > _cached_jacobian_cols
Column where the corresponding cached value should go.
Definition: Assembly.h:2814
void addCachedJacobian(GlobalDataKey)
Adds the values that have been cached by calling cacheJacobian() and or cacheJacobianNeighbor() to th...
Definition: Assembly.C:3791
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:2530
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:2925
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:1367
const Elem * _current_side_elem
The current "element" making up the side we are currently on.
Definition: Assembly.h:2610
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:2819
bool _need_JxW_neighbor
Flag to indicate that JxW_neighbor is needed.
Definition: Assembly.h:2571
virtual const VectorTag & getVectorTag(const TagID tag_id) const
Get a VectorTag from a TagID.
Definition: SubProblem.C:162
void copyNeighborShapes(MooseVariableField< T > &v)
Definition: Assembly.C:3075
void cacheJacobianCoupledVarPair(const MooseVariableBase &ivar, const MooseVariableBase &jvar)
Caches element matrix for ivar rows and jvar columns.
Definition: Assembly.C:4050
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:2569
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:2881
VectorVariablePhiCurl _vector_curl_phi_face
Definition: Assembly.h:2733
Key structure for APIs adding/caching local element residuals/Jacobians.
Definition: Assembly.h:862
std::set< FEType > _need_face_div
Definition: Assembly.h:2873
SubdomainID _current_subdomain_id
The current subdomain ID.
Definition: Assembly.h:2602
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:2399
void clearCachedResiduals(GlobalDataKey)
Clears all of the residuals in _cached_residual_rows and _cached_residual_values. ...
Definition: Assembly.C:3483
virtual const FieldVariablePhiGradient & gradPhiFace() const =0
Return the gradients of the variable&#39;s shape functions on an element face.
unsigned int THREAD_ID
Definition: MooseTypes.h:237
const Node * _current_neighbor_node
The current neighboring node we are working with.
Definition: Assembly.h:2628
std::vector< VectorValue< ADReal > > _ad_d2xyzdeta2_map
Definition: Assembly.h:2836
void clearCachedJacobian()
Clear any currently cached jacobians.
Definition: Assembly.C:4498
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:1336
std::vector< std::vector< std::vector< DenseMatrix< Number > > > > _sub_Knl
dprimary/dlower (or dneighbor/dlower)
Definition: Assembly.h:2701
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:1268
MooseArray< ADReal > _ad_JxW
Definition: Assembly.h:2838
MooseArray< ADReal > _ad_JxW_face
Definition: Assembly.h:2850
void computeFaceMap(const Elem &elem, const unsigned int side, const std::vector< Real > &qw)
Definition: Assembly.C:1348
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:2272
void constrain_element_matrix(DenseMatrix< Number > &matrix, std::vector< dof_id_type > &elem_dofs, bool asymmetric_constraint_rows=true) const
Key structure for APIs manipulating global vectors/matrices.
Definition: Assembly.h:844