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
3791 Assembly::saveLocalADArray(std::vector<ADReal> & re,
3792  unsigned int i,
3793  unsigned int ntest,
3794  const ADRealEigenVector & v) const
3795 {
3796  for (unsigned int j = 0; j < v.size(); ++j, i += ntest)
3797  re[i] += v(j);
3798 }
3799 
3800 void
3802 {
3803 #ifndef NDEBUG
3805  {
3806  mooseAssert(_cached_jacobian_rows.size() == _cached_jacobian_cols.size(),
3807  "Error: Cached data sizes MUST be the same!");
3808  for (MooseIndex(_cached_jacobian_rows) i = 0; i < _cached_jacobian_rows.size(); i++)
3809  mooseAssert(_cached_jacobian_rows[i].size() == _cached_jacobian_cols[i].size(),
3810  "Error: Cached data sizes MUST be the same for a given tag!");
3811  }
3812 #endif
3813 
3814  for (MooseIndex(_cached_jacobian_rows) i = 0; i < _cached_jacobian_rows.size(); i++)
3815  if (_sys.hasMatrix(i))
3816  for (MooseIndex(_cached_jacobian_rows[i]) j = 0; j < _cached_jacobian_rows[i].size(); j++)
3818  _cached_jacobian_cols[i][j],
3819  _cached_jacobian_values[i][j]);
3820 
3821  for (MooseIndex(_cached_jacobian_rows) i = 0; i < _cached_jacobian_rows.size(); i++)
3822  {
3823  if (!_sys.hasMatrix(i))
3824  continue;
3825 
3828 
3829  // Try to be more efficient from now on
3830  // The 2 is just a fudge factor to keep us from having to grow the vector during assembly
3831  _cached_jacobian_values[i].clear();
3833 
3834  _cached_jacobian_rows[i].clear();
3836 
3837  _cached_jacobian_cols[i].clear();
3839  }
3840 }
3841 
3842 inline void
3844 {
3845  auto i = ivar.number();
3846  auto j = jvar.number();
3847  for (MooseIndex(_jacobian_block_used) tag = 0; tag < _jacobian_block_used.size(); tag++)
3848  if (jacobianBlockUsed(tag, i, j) && _sys.hasMatrix(tag))
3850  jacobianBlock(i, j, LocalDataKey{}, tag),
3851  ivar,
3852  jvar,
3853  ivar.dofIndices(),
3854  jvar.dofIndices());
3855 }
3856 
3857 void
3859 {
3860  for (const auto & it : _cm_ff_entry)
3861  addJacobianCoupledVarPair(*it.first, *it.second);
3862 
3863  for (const auto & it : _cm_sf_entry)
3864  addJacobianCoupledVarPair(*it.first, *it.second);
3865 
3866  for (const auto & it : _cm_fs_entry)
3867  addJacobianCoupledVarPair(*it.first, *it.second);
3868 }
3869 
3870 void
3872 {
3873  for (const auto & it : _cm_nonlocal_entry)
3874  {
3875  auto ivar = it.first;
3876  auto jvar = it.second;
3877  auto i = ivar->number();
3878  auto j = jvar->number();
3879  for (MooseIndex(_jacobian_block_nonlocal_used) tag = 0;
3880  tag < _jacobian_block_nonlocal_used.size();
3881  tag++)
3882  if (jacobianBlockNonlocalUsed(tag, i, j) && _sys.hasMatrix(tag))
3884  jacobianBlockNonlocal(i, j, LocalDataKey{}, tag),
3885  *ivar,
3886  *jvar,
3887  ivar->dofIndices(),
3888  jvar->allDofIndices());
3889  }
3890 }
3891 
3892 void
3894 {
3895  for (const auto & it : _cm_ff_entry)
3896  {
3897  auto ivar = it.first;
3898  auto jvar = it.second;
3899  auto i = ivar->number();
3900  auto j = jvar->number();
3901  for (MooseIndex(_jacobian_block_neighbor_used) tag = 0;
3902  tag < _jacobian_block_neighbor_used.size();
3903  tag++)
3904  if (jacobianBlockNeighborUsed(tag, i, j) && _sys.hasMatrix(tag))
3905  {
3908  *ivar,
3909  *jvar,
3910  ivar->dofIndices(),
3911  jvar->dofIndicesNeighbor());
3912 
3915  *ivar,
3916  *jvar,
3917  ivar->dofIndicesNeighbor(),
3918  jvar->dofIndices());
3919 
3922  *ivar,
3923  *jvar,
3924  ivar->dofIndicesNeighbor(),
3925  jvar->dofIndicesNeighbor());
3926  }
3927  }
3928 }
3929 
3930 void
3932 {
3933  for (const auto & it : _cm_ff_entry)
3934  {
3935  auto ivar = it.first;
3936  auto jvar = it.second;
3937  auto i = ivar->number();
3938  auto j = jvar->number();
3939  for (MooseIndex(_jacobian_block_lower_used) tag = 0; tag < _jacobian_block_lower_used.size();
3940  tag++)
3941  if (jacobianBlockLowerUsed(tag, i, j) && _sys.hasMatrix(tag))
3942  {
3945  *ivar,
3946  *jvar,
3947  ivar->dofIndicesLower(),
3948  jvar->dofIndicesLower());
3949 
3952  *ivar,
3953  *jvar,
3954  ivar->dofIndicesLower(),
3955  jvar->dofIndicesNeighbor());
3956 
3959  *ivar,
3960  *jvar,
3961  ivar->dofIndicesLower(),
3962  jvar->dofIndices());
3963 
3966  *ivar,
3967  *jvar,
3968  ivar->dofIndicesNeighbor(),
3969  jvar->dofIndicesLower());
3970 
3973  *ivar,
3974  *jvar,
3975  ivar->dofIndices(),
3976  jvar->dofIndicesLower());
3977  }
3978 
3979  for (MooseIndex(_jacobian_block_neighbor_used) tag = 0;
3980  tag < _jacobian_block_neighbor_used.size();
3981  tag++)
3982  if (jacobianBlockNeighborUsed(tag, i, j) && _sys.hasMatrix(tag))
3983  {
3986  *ivar,
3987  *jvar,
3988  ivar->dofIndices(),
3989  jvar->dofIndicesNeighbor());
3990 
3993  *ivar,
3994  *jvar,
3995  ivar->dofIndicesNeighbor(),
3996  jvar->dofIndices());
3997 
4000  *ivar,
4001  *jvar,
4002  ivar->dofIndicesNeighbor(),
4003  jvar->dofIndicesNeighbor());
4004  }
4005  }
4006 }
4007 
4008 void
4010 {
4011  for (const auto & it : _cm_ff_entry)
4012  {
4013  auto ivar = it.first;
4014  auto jvar = it.second;
4015  auto i = ivar->number();
4016  auto j = jvar->number();
4017  for (MooseIndex(_jacobian_block_lower_used) tag = 0; tag < _jacobian_block_lower_used.size();
4018  tag++)
4019  if (jacobianBlockLowerUsed(tag, i, j) && _sys.hasMatrix(tag))
4020  {
4023  *ivar,
4024  *jvar,
4025  ivar->dofIndicesLower(),
4026  jvar->dofIndicesLower());
4027 
4030  *ivar,
4031  *jvar,
4032  ivar->dofIndicesLower(),
4033  jvar->dofIndices());
4034 
4037  *ivar,
4038  *jvar,
4039  ivar->dofIndices(),
4040  jvar->dofIndicesLower());
4041  }
4042  }
4043 }
4044 
4045 void
4047 {
4048  for (const auto & it : _cm_ff_entry)
4049  cacheJacobianCoupledVarPair(*it.first, *it.second);
4050 
4051  for (const auto & it : _cm_fs_entry)
4052  cacheJacobianCoupledVarPair(*it.first, *it.second);
4053 
4054  for (const auto & it : _cm_sf_entry)
4055  cacheJacobianCoupledVarPair(*it.first, *it.second);
4056 }
4057 
4058 // private method, so no key required
4059 void
4061  const MooseVariableBase & jvar)
4062 {
4063  auto i = ivar.number();
4064  auto j = jvar.number();
4065  for (MooseIndex(_jacobian_block_used) tag = 0; tag < _jacobian_block_used.size(); tag++)
4066  if (jacobianBlockUsed(tag, i, j) && _sys.hasMatrix(tag))
4068  ivar,
4069  jvar,
4070  ivar.dofIndices(),
4071  jvar.dofIndices(),
4072  tag);
4073 }
4074 
4075 void
4077 {
4078  for (const auto & it : _cm_nonlocal_entry)
4079  {
4080  auto ivar = it.first;
4081  auto jvar = it.second;
4082  auto i = ivar->number();
4083  auto j = jvar->number();
4084  for (MooseIndex(_jacobian_block_nonlocal_used) tag = 0;
4085  tag < _jacobian_block_nonlocal_used.size();
4086  tag++)
4087  if (jacobianBlockNonlocalUsed(tag, i, j) && _sys.hasMatrix(tag))
4089  *ivar,
4090  *jvar,
4091  ivar->dofIndices(),
4092  jvar->allDofIndices(),
4093  tag);
4094  }
4095 }
4096 
4097 void
4099 {
4100  for (const auto & it : _cm_ff_entry)
4101  {
4102  auto ivar = it.first;
4103  auto jvar = it.second;
4104  auto i = ivar->number();
4105  auto j = jvar->number();
4106 
4107  for (MooseIndex(_jacobian_block_neighbor_used) tag = 0;
4108  tag < _jacobian_block_neighbor_used.size();
4109  tag++)
4110  if (jacobianBlockNeighborUsed(tag, i, j) && _sys.hasMatrix(tag))
4111  {
4113  *ivar,
4114  *jvar,
4115  ivar->dofIndices(),
4116  jvar->dofIndicesNeighbor(),
4117  tag);
4119  *ivar,
4120  *jvar,
4121  ivar->dofIndicesNeighbor(),
4122  jvar->dofIndices(),
4123  tag);
4126  *ivar,
4127  *jvar,
4128  ivar->dofIndicesNeighbor(),
4129  jvar->dofIndicesNeighbor(),
4130  tag);
4131  }
4132  }
4133 }
4134 
4135 void
4137 {
4138  for (const auto & it : _cm_ff_entry)
4139  {
4140  auto ivar = it.first;
4141  auto jvar = it.second;
4142  auto i = ivar->number();
4143  auto j = jvar->number();
4144  for (MooseIndex(_jacobian_block_lower_used) tag = 0; tag < _jacobian_block_lower_used.size();
4145  tag++)
4146  if (jacobianBlockLowerUsed(tag, i, j) && _sys.hasMatrix(tag))
4147  {
4149  *ivar,
4150  *jvar,
4151  ivar->dofIndicesLower(),
4152  jvar->dofIndicesLower(),
4153  tag);
4154 
4156  *ivar,
4157  *jvar,
4158  ivar->dofIndicesLower(),
4159  jvar->dofIndices(),
4160  tag);
4161 
4163  *ivar,
4164  *jvar,
4165  ivar->dofIndicesLower(),
4166  jvar->dofIndicesNeighbor(),
4167  tag);
4168 
4170  *ivar,
4171  *jvar,
4172  ivar->dofIndices(),
4173  jvar->dofIndicesLower(),
4174  tag);
4175 
4178  *ivar,
4179  *jvar,
4180  ivar->dofIndices(),
4181  jvar->dofIndices(),
4182  tag);
4183 
4185  *ivar,
4186  *jvar,
4187  ivar->dofIndices(),
4188  jvar->dofIndicesNeighbor(),
4189  tag);
4190 
4192  *ivar,
4193  *jvar,
4194  ivar->dofIndicesNeighbor(),
4195  jvar->dofIndicesLower(),
4196  tag);
4197 
4199  *ivar,
4200  *jvar,
4201  ivar->dofIndicesNeighbor(),
4202  jvar->dofIndices(),
4203  tag);
4204 
4206  *ivar,
4207  *jvar,
4208  ivar->dofIndicesNeighbor(),
4209  jvar->dofIndicesNeighbor(),
4210  tag);
4211  }
4212  }
4213 }
4214 
4215 void
4217  unsigned int ivar,
4218  unsigned int jvar,
4219  const DofMap & dof_map,
4220  std::vector<dof_id_type> & dof_indices,
4221  GlobalDataKey,
4222  const std::set<TagID> & tags)
4223 {
4224  for (auto tag : tags)
4225  addJacobianBlock(jacobian, ivar, jvar, dof_map, dof_indices, GlobalDataKey{}, tag);
4226 }
4227 
4228 void
4230  unsigned int ivar,
4231  unsigned int jvar,
4232  const DofMap & dof_map,
4233  std::vector<dof_id_type> & dof_indices,
4234  GlobalDataKey,
4235  TagID tag)
4236 {
4237  if (dof_indices.size() == 0)
4238  return;
4239  if (!(*_cm)(ivar, jvar))
4240  return;
4241 
4242  auto & iv = _sys.getVariable(_tid, ivar);
4243  auto & jv = _sys.getVariable(_tid, jvar);
4244  auto & scaling_factor = iv.arrayScalingFactor();
4245 
4246  const unsigned int ivn = iv.number();
4247  const unsigned int jvn = jv.number();
4248  auto & ke = jacobianBlock(ivn, jvn, LocalDataKey{}, tag);
4249 
4250  // It is guaranteed by design iv.number <= ivar since iv is obtained
4251  // through SystemBase::getVariable with ivar.
4252  // Most of times ivar will just be equal to iv.number except for array variables,
4253  // where ivar could be a number for a component of an array variable but calling
4254  // getVariable will return the array variable that has the number of the 0th component.
4255  // It is the same for jvar.
4256  const unsigned int i = ivar - ivn;
4257  const unsigned int j = jvar - jvn;
4258 
4259  // DoF indices are independently given
4260  auto di = dof_indices;
4261  auto dj = dof_indices;
4262 
4263  auto indof = di.size();
4264  auto jndof = dj.size();
4265 
4266  unsigned int jj = j;
4267  if (ivar == jvar && _component_block_diagonal[ivn])
4268  jj = 0;
4269 
4270  auto sub = ke.sub_matrix(i * indof, indof, jj * jndof, jndof);
4271  // If we're computing the jacobian for automatically scaling variables we do not want to
4272  // constrain the element matrix because it introduces 1s on the diagonal for the constrained
4273  // dofs
4275  dof_map.constrain_element_matrix(sub, di, dj, false);
4276 
4277  if (scaling_factor[i] != 1.0)
4278  sub *= scaling_factor[i];
4279 
4280  jacobian.add_matrix(sub, di, dj);
4281 }
4282 
4283 void
4285  const unsigned int ivar,
4286  const unsigned int jvar,
4287  const DofMap & dof_map,
4288  const std::vector<dof_id_type> & idof_indices,
4289  const std::vector<dof_id_type> & jdof_indices,
4290  GlobalDataKey,
4291  const TagID tag)
4292 {
4293  if (idof_indices.size() == 0 || jdof_indices.size() == 0)
4294  return;
4295  if (jacobian.n() == 0 || jacobian.m() == 0)
4296  return;
4297  if (!(*_cm)(ivar, jvar))
4298  return;
4299 
4300  auto & iv = _sys.getVariable(_tid, ivar);
4301  auto & jv = _sys.getVariable(_tid, jvar);
4302  auto & scaling_factor = iv.arrayScalingFactor();
4303 
4304  const unsigned int ivn = iv.number();
4305  const unsigned int jvn = jv.number();
4306  auto & keg = jacobianBlockNonlocal(ivn, jvn, LocalDataKey{}, tag);
4307 
4308  // It is guaranteed by design iv.number <= ivar since iv is obtained
4309  // through SystemBase::getVariable with ivar.
4310  // Most of times ivar will just be equal to iv.number except for array variables,
4311  // where ivar could be a number for a component of an array variable but calling
4312  // getVariable will return the array variable that has the number of the 0th component.
4313  // It is the same for jvar.
4314  const unsigned int i = ivar - ivn;
4315  const unsigned int j = jvar - jvn;
4316 
4317  // DoF indices are independently given
4318  auto di = idof_indices;
4319  auto dj = jdof_indices;
4320 
4321  auto indof = di.size();
4322  auto jndof = dj.size();
4323 
4324  unsigned int jj = j;
4325  if (ivar == jvar && _component_block_diagonal[ivn])
4326  jj = 0;
4327 
4328  auto sub = keg.sub_matrix(i * indof, indof, jj * jndof, jndof);
4329  // If we're computing the jacobian for automatically scaling variables we do not want to
4330  // constrain the element matrix because it introduces 1s on the diagonal for the constrained
4331  // dofs
4333  dof_map.constrain_element_matrix(sub, di, dj, false);
4334 
4335  if (scaling_factor[i] != 1.0)
4336  sub *= scaling_factor[i];
4337 
4338  jacobian.add_matrix(sub, di, dj);
4339 }
4340 
4341 void
4343  const unsigned int ivar,
4344  const unsigned int jvar,
4345  const DofMap & dof_map,
4346  const std::vector<dof_id_type> & idof_indices,
4347  const std::vector<dof_id_type> & jdof_indices,
4348  GlobalDataKey,
4349  const std::set<TagID> & tags)
4350 {
4351  for (auto tag : tags)
4353  jacobian, ivar, jvar, dof_map, idof_indices, jdof_indices, GlobalDataKey{}, tag);
4354 }
4355 
4356 void
4358  const unsigned int ivar,
4359  const unsigned int jvar,
4360  const DofMap & dof_map,
4361  std::vector<dof_id_type> & dof_indices,
4362  std::vector<dof_id_type> & neighbor_dof_indices,
4363  GlobalDataKey,
4364  const TagID tag)
4365 {
4366  if (dof_indices.size() == 0 && neighbor_dof_indices.size() == 0)
4367  return;
4368  if (!(*_cm)(ivar, jvar))
4369  return;
4370 
4371  auto & iv = _sys.getVariable(_tid, ivar);
4372  auto & jv = _sys.getVariable(_tid, jvar);
4373  auto & scaling_factor = iv.arrayScalingFactor();
4374 
4375  const unsigned int ivn = iv.number();
4376  const unsigned int jvn = jv.number();
4377  auto & ken = jacobianBlockNeighbor(Moose::ElementNeighbor, ivn, jvn, LocalDataKey{}, tag);
4378  auto & kne = jacobianBlockNeighbor(Moose::NeighborElement, ivn, jvn, LocalDataKey{}, tag);
4379  auto & knn = jacobianBlockNeighbor(Moose::NeighborNeighbor, ivn, jvn, LocalDataKey{}, tag);
4380 
4381  // It is guaranteed by design iv.number <= ivar since iv is obtained
4382  // through SystemBase::getVariable with ivar.
4383  // Most of times ivar will just be equal to iv.number except for array variables,
4384  // where ivar could be a number for a component of an array variable but calling
4385  // getVariable will return the array variable that has the number of the 0th component.
4386  // It is the same for jvar.
4387  const unsigned int i = ivar - ivn;
4388  const unsigned int j = jvar - jvn;
4389  // DoF indices are independently given
4390  auto dc = dof_indices;
4391  auto dn = neighbor_dof_indices;
4392  auto cndof = dc.size();
4393  auto nndof = dn.size();
4394 
4395  unsigned int jj = j;
4396  if (ivar == jvar && _component_block_diagonal[ivn])
4397  jj = 0;
4398 
4399  auto suben = ken.sub_matrix(i * cndof, cndof, jj * nndof, nndof);
4400  auto subne = kne.sub_matrix(i * nndof, nndof, jj * cndof, cndof);
4401  auto subnn = knn.sub_matrix(i * nndof, nndof, jj * nndof, nndof);
4402 
4403  // If we're computing the jacobian for automatically scaling variables we do not want to
4404  // constrain the element matrix because it introduces 1s on the diagonal for the constrained
4405  // dofs
4407  {
4408  dof_map.constrain_element_matrix(suben, dc, dn, false);
4409  dof_map.constrain_element_matrix(subne, dn, dc, false);
4410  dof_map.constrain_element_matrix(subnn, dn, dn, false);
4411  }
4412 
4413  if (scaling_factor[i] != 1.0)
4414  {
4415  suben *= scaling_factor[i];
4416  subne *= scaling_factor[i];
4417  subnn *= scaling_factor[i];
4418  }
4419 
4420  jacobian.add_matrix(suben, dc, dn);
4421  jacobian.add_matrix(subne, dn, dc);
4422  jacobian.add_matrix(subnn, dn, dn);
4423 }
4424 
4425 void
4427  const unsigned int ivar,
4428  const unsigned int jvar,
4429  const DofMap & dof_map,
4430  std::vector<dof_id_type> & dof_indices,
4431  std::vector<dof_id_type> & neighbor_dof_indices,
4432  GlobalDataKey,
4433  const std::set<TagID> & tags)
4434 {
4435  for (const auto tag : tags)
4437  jacobian, ivar, jvar, dof_map, dof_indices, neighbor_dof_indices, GlobalDataKey{}, tag);
4438 }
4439 
4440 void
4442 {
4443  for (const auto & it : _cm_ss_entry)
4444  addJacobianCoupledVarPair(*it.first, *it.second);
4445 }
4446 
4447 void
4449 {
4450  const std::vector<MooseVariableFEBase *> & vars = _sys.getVariables(_tid);
4452  for (const auto & var_j : vars)
4453  addJacobianCoupledVarPair(var_i, *var_j);
4454 }
4455 
4456 void
4459 {
4460  _cached_jacobian_rows[tag].push_back(i);
4461  _cached_jacobian_cols[tag].push_back(j);
4462  _cached_jacobian_values[tag].push_back(value);
4463 }
4464 
4465 void
4468  Real value,
4469  LocalDataKey,
4470  const std::set<TagID> & tags)
4471 {
4472  for (auto tag : tags)
4473  if (_sys.hasMatrix(tag))
4474  cacheJacobian(i, j, value, LocalDataKey{}, tag);
4475 }
4476 
4477 void
4479 {
4480  for (MooseIndex(_cached_jacobian_rows) tag = 0; tag < _cached_jacobian_rows.size(); tag++)
4481  if (_sys.hasMatrix(tag))
4482  {
4483  // First zero the rows (including the diagonals) to prepare for
4484  // setting the cached values.
4486 
4487  // TODO: Use SparseMatrix::set_values() for efficiency
4488  for (MooseIndex(_cached_jacobian_values) i = 0; i < _cached_jacobian_values[tag].size(); ++i)
4489  _sys.getMatrix(tag).set(_cached_jacobian_rows[tag][i],
4490  _cached_jacobian_cols[tag][i],
4491  _cached_jacobian_values[tag][i]);
4492  }
4493 
4495 }
4496 
4497 void
4499 {
4500  for (MooseIndex(_cached_jacobian_rows) tag = 0; tag < _cached_jacobian_rows.size(); tag++)
4501  if (_sys.hasMatrix(tag))
4503 
4505 }
4506 
4507 void
4509 {
4510  for (MooseIndex(_cached_jacobian_rows) tag = 0; tag < _cached_jacobian_rows.size(); tag++)
4511  {
4512  _cached_jacobian_rows[tag].clear();
4513  _cached_jacobian_cols[tag].clear();
4514  _cached_jacobian_values[tag].clear();
4515  }
4516 }
4517 
4518 void
4520 {
4521  mooseAssert(_xfem != nullptr, "This function should not be called if xfem is inactive");
4522 
4524  return;
4525 
4526  MooseArray<Real> xfem_weight_multipliers;
4527  if (_xfem->getXFEMWeights(xfem_weight_multipliers, elem, _current_qrule, _current_q_points))
4528  {
4529  mooseAssert(xfem_weight_multipliers.size() == _current_JxW.size(),
4530  "Size of weight multipliers in xfem doesn't match number of quadrature points");
4531  for (unsigned i = 0; i < xfem_weight_multipliers.size(); i++)
4532  _current_JxW[i] = _current_JxW[i] * xfem_weight_multipliers[i];
4533 
4534  xfem_weight_multipliers.release();
4535  }
4536 }
4537 
4538 void
4539 Assembly::modifyFaceWeightsDueToXFEM(const Elem * elem, unsigned int side)
4540 {
4541  mooseAssert(_xfem != nullptr, "This function should not be called if xfem is inactive");
4542 
4544  return;
4545 
4546  MooseArray<Real> xfem_face_weight_multipliers;
4547  if (_xfem->getXFEMFaceWeights(
4548  xfem_face_weight_multipliers, elem, _current_qrule_face, _current_q_points_face, side))
4549  {
4550  mooseAssert(xfem_face_weight_multipliers.size() == _current_JxW_face.size(),
4551  "Size of weight multipliers in xfem doesn't match number of quadrature points");
4552  for (unsigned i = 0; i < xfem_face_weight_multipliers.size(); i++)
4553  _current_JxW_face[i] = _current_JxW_face[i] * xfem_face_weight_multipliers[i];
4554 
4555  xfem_face_weight_multipliers.release();
4556  }
4557 }
4558 
4559 void
4561 {
4562  _scaling_vector = &_sys.getVector("scaling_factors");
4563 }
4564 
4565 void
4566 Assembly::modifyArbitraryWeights(const std::vector<Real> & weights)
4567 {
4568  mooseAssert(_current_qrule == _current_qrule_arbitrary, "Rule should be arbitrary");
4569  mooseAssert(weights.size() == _current_physical_points.size(), "Size mismatch");
4570 
4571  for (MooseIndex(weights.size()) i = 0; i < weights.size(); ++i)
4572  _current_JxW[i] = weights[i];
4573 }
4574 
4575 template <>
4577 Assembly::fePhi<VectorValue<Real>>(FEType type) const
4578 {
4579  buildVectorFE(type);
4580  return _vector_fe_shape_data[type]->_phi;
4581 }
4582 
4583 template <>
4585 Assembly::feGradPhi<VectorValue<Real>>(FEType type) const
4586 {
4587  buildVectorFE(type);
4588  return _vector_fe_shape_data[type]->_grad_phi;
4589 }
4590 
4591 template <>
4593 Assembly::feSecondPhi<VectorValue<Real>>(FEType type) const
4594 {
4595  _need_second_derivative.insert(type);
4596  buildVectorFE(type);
4597  return _vector_fe_shape_data[type]->_second_phi;
4598 }
4599 
4600 template <>
4602 Assembly::fePhiLower<VectorValue<Real>>(FEType type) const
4603 {
4604  buildVectorLowerDFE(type);
4605  return _vector_fe_shape_data_lower[type]->_phi;
4606 }
4607 
4608 template <>
4610 Assembly::feDualPhiLower<VectorValue<Real>>(FEType type) const
4611 {
4612  buildVectorDualLowerDFE(type);
4613  return _vector_fe_shape_data_dual_lower[type]->_phi;
4614 }
4615 
4616 template <>
4618 Assembly::feGradPhiLower<VectorValue<Real>>(FEType type) const
4619 {
4620  buildVectorLowerDFE(type);
4621  return _vector_fe_shape_data_lower[type]->_grad_phi;
4622 }
4623 
4624 template <>
4626 Assembly::feGradDualPhiLower<VectorValue<Real>>(FEType type) const
4627 {
4628  buildVectorDualLowerDFE(type);
4629  return _vector_fe_shape_data_dual_lower[type]->_grad_phi;
4630 }
4631 
4632 template <>
4634 Assembly::fePhiFace<VectorValue<Real>>(FEType type) const
4635 {
4636  buildVectorFaceFE(type);
4637  return _vector_fe_shape_data_face[type]->_phi;
4638 }
4639 
4640 template <>
4642 Assembly::feGradPhiFace<VectorValue<Real>>(FEType type) const
4643 {
4644  buildVectorFaceFE(type);
4645  return _vector_fe_shape_data_face[type]->_grad_phi;
4646 }
4647 
4648 template <>
4650 Assembly::feSecondPhiFace<VectorValue<Real>>(FEType type) const
4651 {
4652  _need_second_derivative.insert(type);
4653  buildVectorFaceFE(type);
4654 
4655  // If we're building for a face we probably need to build for a
4656  // neighbor while _need_second_derivative is set;
4657  // onInterface/reinitNeighbor/etc don't distinguish
4658  buildVectorFaceNeighborFE(type);
4659 
4660  return _vector_fe_shape_data_face[type]->_second_phi;
4661 }
4662 
4663 template <>
4665 Assembly::fePhiNeighbor<VectorValue<Real>>(FEType type) const
4666 {
4667  buildVectorNeighborFE(type);
4668  return _vector_fe_shape_data_neighbor[type]->_phi;
4669 }
4670 
4671 template <>
4673 Assembly::feGradPhiNeighbor<VectorValue<Real>>(FEType type) const
4674 {
4675  buildVectorNeighborFE(type);
4676  return _vector_fe_shape_data_neighbor[type]->_grad_phi;
4677 }
4678 
4679 template <>
4681 Assembly::feSecondPhiNeighbor<VectorValue<Real>>(FEType type) const
4682 {
4683  _need_second_derivative_neighbor.insert(type);
4684  buildVectorNeighborFE(type);
4685  return _vector_fe_shape_data_neighbor[type]->_second_phi;
4686 }
4687 
4688 template <>
4690 Assembly::fePhiFaceNeighbor<VectorValue<Real>>(FEType type) const
4691 {
4692  buildVectorFaceNeighborFE(type);
4693  return _vector_fe_shape_data_face_neighbor[type]->_phi;
4694 }
4695 
4696 template <>
4698 Assembly::feGradPhiFaceNeighbor<VectorValue<Real>>(FEType type) const
4699 {
4700  buildVectorFaceNeighborFE(type);
4701  return _vector_fe_shape_data_face_neighbor[type]->_grad_phi;
4702 }
4703 
4704 template <>
4706 Assembly::feSecondPhiFaceNeighbor<VectorValue<Real>>(FEType type) const
4707 {
4708  _need_second_derivative_neighbor.insert(type);
4709  buildVectorFaceNeighborFE(type);
4710  return _vector_fe_shape_data_face_neighbor[type]->_second_phi;
4711 }
4712 
4713 template <>
4715 Assembly::feCurlPhi<VectorValue<Real>>(FEType type) const
4716 {
4717  _need_curl.insert(type);
4718  buildVectorFE(type);
4719  return _vector_fe_shape_data[type]->_curl_phi;
4720 }
4721 
4722 template <>
4724 Assembly::feCurlPhiFace<VectorValue<Real>>(FEType type) const
4725 {
4726  _need_curl.insert(type);
4727  buildVectorFaceFE(type);
4728 
4729  // If we're building for a face we probably need to build for a
4730  // neighbor while _need_curl is set;
4731  // onInterface/reinitNeighbor/etc don't distinguish
4732  buildVectorFaceNeighborFE(type);
4733 
4734  return _vector_fe_shape_data_face[type]->_curl_phi;
4735 }
4736 
4737 template <>
4739 Assembly::feCurlPhiNeighbor<VectorValue<Real>>(FEType type) const
4740 {
4741  _need_curl.insert(type);
4742  buildVectorNeighborFE(type);
4743  return _vector_fe_shape_data_neighbor[type]->_curl_phi;
4744 }
4745 
4746 template <>
4748 Assembly::feCurlPhiFaceNeighbor<VectorValue<Real>>(FEType type) const
4749 {
4750  _need_curl.insert(type);
4751  buildVectorFaceNeighborFE(type);
4752 
4753  return _vector_fe_shape_data_face_neighbor[type]->_curl_phi;
4754 }
4755 
4756 template <>
4758 Assembly::feDivPhi<VectorValue<Real>>(FEType type) const
4759 {
4760  _need_div.insert(type);
4761  buildVectorFE(type);
4762  return _vector_fe_shape_data[type]->_div_phi;
4763 }
4764 
4765 template <>
4767 Assembly::feDivPhiFace<VectorValue<Real>>(FEType type) const
4768 {
4769  _need_face_div.insert(type);
4770  buildVectorFaceFE(type);
4771 
4772  // If we're building for a face we probably need to build for a
4773  // neighbor while _need_face_div is set;
4774  // onInterface/reinitNeighbor/etc don't distinguish
4775  buildVectorFaceNeighborFE(type);
4776 
4777  return _vector_fe_shape_data_face[type]->_div_phi;
4778 }
4779 
4780 template <>
4782 Assembly::feDivPhiNeighbor<VectorValue<Real>>(FEType type) const
4783 {
4784  _need_neighbor_div.insert(type);
4785  buildVectorNeighborFE(type);
4786  return _vector_fe_shape_data_neighbor[type]->_div_phi;
4787 }
4788 
4789 template <>
4791 Assembly::feDivPhiFaceNeighbor<VectorValue<Real>>(FEType type) const
4792 {
4793  _need_face_neighbor_div.insert(type);
4794  buildVectorFaceNeighborFE(type);
4795  return _vector_fe_shape_data_face_neighbor[type]->_div_phi;
4796 }
4797 
4798 const MooseArray<ADReal> &
4800 {
4801  _calculate_curvatures = true;
4802  const Order helper_order = _mesh.hasSecondOrderElements() ? SECOND : FIRST;
4803  const FEType helper_type(helper_order, LAGRANGE);
4804  // Must prerequest the second derivatives. Sadly because there is only one
4805  // _need_second_derivative map for both volumetric and face FE objects we must request both here
4806  feSecondPhi<Real>(helper_type);
4807  feSecondPhiFace<Real>(helper_type);
4808  return _ad_curvatures;
4809 }
4810 
4811 void
4813 {
4814  for (unsigned int dim = 0; dim <= _mesh_dimension; dim++)
4815  {
4816  _holder_fe_helper[dim]->get_phi();
4817  _holder_fe_helper[dim]->get_dphi();
4818  _holder_fe_helper[dim]->get_xyz();
4819  _holder_fe_helper[dim]->get_JxW();
4820 
4821  _holder_fe_face_helper[dim]->get_phi();
4822  _holder_fe_face_helper[dim]->get_dphi();
4823  _holder_fe_face_helper[dim]->get_xyz();
4824  _holder_fe_face_helper[dim]->get_JxW();
4825  _holder_fe_face_helper[dim]->get_normals();
4826 
4829  _holder_fe_face_neighbor_helper[dim]->get_normals();
4830 
4831  _holder_fe_neighbor_helper[dim]->get_xyz();
4832  _holder_fe_neighbor_helper[dim]->get_JxW();
4833  }
4834 
4835  for (unsigned int dim = 0; dim < _mesh_dimension; dim++)
4836  {
4837  // We need these computations in order to compute correct lower-d element volumes in
4838  // curvilinear coordinates
4839  _holder_fe_lower_helper[dim]->get_xyz();
4840  _holder_fe_lower_helper[dim]->get_JxW();
4841  }
4842 }
4843 
4844 void
4845 Assembly::havePRefinement(const std::unordered_set<FEFamily> & disable_families)
4846 {
4847  if (_have_p_refinement)
4848  // Already performed tasks for p-refinement
4849  return;
4850 
4851  const Order helper_order = _mesh.hasSecondOrderElements() ? SECOND : FIRST;
4852  const FEType helper_type(helper_order, LAGRANGE);
4853  auto process_fe =
4854  [&disable_families](const unsigned int num_dimensionalities, auto & fe_container)
4855  {
4856  if (!disable_families.empty())
4857  for (const auto dim : make_range(num_dimensionalities))
4858  {
4859  auto fe_container_it = fe_container.find(dim);
4860  if (fe_container_it != fe_container.end())
4861  for (auto & [fe_type, fe_ptr] : fe_container_it->second)
4862  if (disable_families.count(fe_type.family))
4863  fe_ptr->add_p_level_in_reinit(false);
4864  }
4865  };
4866  auto process_fe_and_helpers = [process_fe, &helper_type](auto & unique_helper_container,
4867  auto & helper_container,
4868  const unsigned int num_dimensionalities,
4869  const bool user_added_helper_type,
4870  auto & fe_container)
4871  {
4872  unique_helper_container.resize(num_dimensionalities);
4873  for (const auto dim : make_range(num_dimensionalities))
4874  {
4875  auto & unique_helper = unique_helper_container[dim];
4876  unique_helper = FEGenericBase<Real>::build(dim, helper_type);
4877  // don't participate in p-refinement
4878  unique_helper->add_p_level_in_reinit(false);
4879  helper_container[dim] = unique_helper.get();
4880 
4881  // If the user did not request the helper type then we should erase it from our FE container
4882  // so that they're not penalized (in the "we should be able to do p-refinement sense") for
4883  // our perhaps silly helpers
4884  if (!user_added_helper_type)
4885  {
4886  auto & fe_container_dim = libmesh_map_find(fe_container, dim);
4887  auto fe_it = fe_container_dim.find(helper_type);
4888  mooseAssert(fe_it != fe_container_dim.end(), "We should have the helper type");
4889  delete fe_it->second;
4890  fe_container_dim.erase(fe_it);
4891  }
4892  }
4893 
4894  process_fe(num_dimensionalities, fe_container);
4895  };
4896 
4897  // Handle scalar field families
4898  process_fe_and_helpers(_unique_fe_helper,
4900  _mesh_dimension + 1,
4902  _fe);
4903  process_fe_and_helpers(_unique_fe_face_helper,
4905  _mesh_dimension + 1,
4907  _fe_face);
4908  process_fe_and_helpers(_unique_fe_face_neighbor_helper,
4910  _mesh_dimension + 1,
4913  process_fe_and_helpers(_unique_fe_neighbor_helper,
4915  _mesh_dimension + 1,
4917  _fe_neighbor);
4918  process_fe_and_helpers(_unique_fe_lower_helper,
4922  _fe_lower);
4923  // Handle vector field families
4924  process_fe(_mesh_dimension + 1, _vector_fe);
4925  process_fe(_mesh_dimension + 1, _vector_fe_face);
4926  process_fe(_mesh_dimension + 1, _vector_fe_neighbor);
4927  process_fe(_mesh_dimension + 1, _vector_fe_face_neighbor);
4928  process_fe(_mesh_dimension, _vector_fe_lower);
4929 
4931 
4932  _have_p_refinement = true;
4933 }
4934 
4935 template void coordTransformFactor<Point, Real>(const SubProblem & s,
4936  SubdomainID sub_id,
4937  const Point & point,
4938  Real & factor,
4939  SubdomainID neighbor_sub_id);
4940 template void coordTransformFactor<ADPoint, ADReal>(const SubProblem & s,
4941  SubdomainID sub_id,
4942  const ADPoint & point,
4943  ADReal & factor,
4944  SubdomainID neighbor_sub_id);
4945 template void coordTransformFactor<Point, Real>(const MooseMesh & mesh,
4946  SubdomainID sub_id,
4947  const Point & point,
4948  Real & factor,
4949  SubdomainID neighbor_sub_id);
4951  SubdomainID sub_id,
4952  const ADPoint & point,
4953  ADReal & factor,
4954  SubdomainID neighbor_sub_id);
4955 
4956 template <>
4958 Assembly::genericQPoints<false>() const
4959 {
4960  return qPoints();
4961 }
4962 
4963 template <>
4965 Assembly::genericQPoints<true>() const
4966 {
4967  return adQPoints();
4968 }
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:2847
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:2881
std::map< unsigned int, std::map< FEType, FEBase * > > _fe_face
types of finite elements
Definition: Assembly.h:2514
bool _need_neighbor_elem_volume
true is apps need to compute neighbor element volume
Definition: Assembly.h:2618
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:2414
std::map< FEType, FEBase * > _current_fe
The "volume" fe object that matches the current elem.
Definition: Assembly.h:2382
MooseArray< Real > _curvatures
Definition: Assembly.h:2849
const std::vector< MooseVariableFieldBase * > & getVariables(THREAD_ID tid)
Definition: SystemBase.h:752
std::vector< ADReal > _ad_detadz_map
Definition: Assembly.h:2841
VectorVariablePhiValue _phi
Definition: Assembly.h:2757
std::unique_ptr< FEGenericBase< Real > > build(const unsigned int dim, const FEType &fet)
SystemBase & _sys
Definition: Assembly.h:2312
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:2801
std::vector< std::vector< dof_id_type > > _cached_jacobian_rows
Row where the corresponding cached value should go.
Definition: Assembly.h:2808
Eigen::Matrix< ADReal, Eigen::Dynamic, 1 > ADRealEigenVector
Definition: MooseTypes.h:148
unsigned int _max_cached_residuals
Definition: Assembly.h:2803
std::map< FEType, ADTemplateVariablePhiGradient< Real > > _ad_grad_phi_data_face
Definition: Assembly.h:2782
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:2365
MooseArray< Point > _current_physical_points
This will be filled up with the physical points passed into reinitAtPhysical() if it is called...
Definition: Assembly.h:2646
const VariablePhiGradient & gradPhiFaceNeighbor(const MooseVariableField< Real > &) const
Definition: Assembly.h:1363
std::vector< std::unique_ptr< FEBase > > _unique_fe_lower_helper
Definition: Assembly.h:2373
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:2426
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:2404
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:2571
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:759
std::vector< std::vector< std::vector< DenseMatrix< Number > > > > _sub_Kle
dlower/dsecondary (or dlower/delement)
Definition: Assembly.h:2691
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:925
void saveLocalADArray(std::vector< ADReal > &re, unsigned int i, unsigned int ntest, const ADRealEigenVector &v) const
Definition: Assembly.C:3791
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:2765
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:2569
std::shared_ptr< XFEMInterface > _xfem
The XFEM controller.
Definition: Assembly.h:2379
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:311
virtual void zero() override final
std::vector< std::vector< std::vector< DenseMatrix< Number > > > > _sub_Kel
dsecondary/dlower (or delement/dlower)
Definition: Assembly.h:2695
const std::vector< Real > & arrayScalingFactor() const
MooseArray< Real > _coord
The current coordinate transformation coefficients.
Definition: Assembly.h:2424
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:2563
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:2239
void coordTransformFactor(const P &point, C &factor, const Moose::CoordinateSystemType coord_type, const unsigned int rz_radial_coord=libMesh::invalid_uint)
Compute a coordinate transformation volume integration factor.
void prepareNonlocal()
Definition: Assembly.C:2724
std::map< unsigned int, FEBase * > _holder_fe_neighbor_helper
Each dimension&#39;s helper objects.
Definition: Assembly.h:2552
std::unique_ptr< FEBase > _fe_msm
A FE object for working on mortar segement elements.
Definition: Assembly.h:2581
std::map< FEType, std::unique_ptr< FEShapeData > > _fe_shape_data_face_neighbor
Definition: Assembly.h:2768
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:85
void reinitAtPhysical(const Elem *elem, const std::vector< Point > &physical_points)
Reinitialize the assembly data at specific physical point in the given element.
Definition: Assembly.C: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:2626
std::vector< ADReal > _ad_detady_map
Definition: Assembly.h:2840
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:2275
const VectorVariablePhiDivergence & divPhi(const MooseVariableField< RealVectorValue > &) const
Definition: Assembly.h:1388
std::vector< ADReal > _ad_dzetadz_map
Definition: Assembly.h:2844
std::vector< std::unique_ptr< FEBase > > _unique_fe_neighbor_helper
Definition: Assembly.h:2372
std::vector< std::vector< std::vector< DenseMatrix< Number > > > > _sub_Kll
dlower/dlower
Definition: Assembly.h:2689
bool _user_added_fe_face_neighbor_of_helper_type
Definition: Assembly.h:2363
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:2901
VariablePhiValue _phi
Definition: Assembly.h:2747
char ** vars
Real _current_neighbor_volume
Volume of the current neighbor.
Definition: Assembly.h:2620
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:2293
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:2384
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:2904
std::vector< std::vector< std::vector< DenseMatrix< Number > > > > _sub_Kln
dlower/dprimary (or dlower/dneighbor)
Definition: Assembly.h:2693
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:2610
void addJacobianNonlocal(GlobalDataKey)
Adds non-local Jacobian to the global Jacobian matrices.
Definition: Assembly.C:3871
std::vector< std::vector< DenseVector< Number > > > _sub_Rn
Definition: Assembly.h:2661
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:2352
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:2767
std::map< unsigned int, FEBase * > _holder_fe_face_neighbor_helper
Definition: Assembly.h:2553
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:2528
void modifyWeightsDueToXFEM(const Elem *elem)
Update the integration weights for XFEM partial elements.
Definition: Assembly.C:4519
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:2596
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:1554
THREAD_ID _tid
Thread number (id)
Definition: Assembly.h:2350
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:163
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:2370
QuadratureType
std::vector< std::vector< std::vector< unsigned char > > > _jacobian_block_nonlocal_used
Definition: Assembly.h:2342
std::vector< std::pair< MooseVariableScalar *, MooseVariableFieldBase * > > _cm_sf_entry
Entries in the coupling matrix for scalar variables vs field variables.
Definition: Assembly.h:2335
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:361
const std::vector< std::vector< Real > > & get_phi_map() const
void setCoordinateTransformation(const libMesh::QBase *qrule, const Points &q_points, Coords &coord, SubdomainID sub_id)
Definition: Assembly.C:1731
std::map< unsigned int, std::map< FEType, FEVectorBase * > > _vector_fe_face_neighbor
Definition: Assembly.h:2549
const VariablePhiValue & phiFaceNeighbor(const MooseVariableField< Real > &) const
Definition: Assembly.h:1359
unsigned int elemSideID() const
Definition: FaceInfo.h:113
std::vector< bool > _component_block_diagonal
An flag array Indiced by variable index to show if there is no component-wise coupling for the variab...
Definition: Assembly.h:2818
Real _current_elem_volume
Volume of the current element.
Definition: Assembly.h:2602
std::map< FEType, FEBase * > _current_fe_face_neighbor
The "neighbor face" fe object that matches the current elem.
Definition: Assembly.h:2388
const MooseArray< ADReal > & adCurvatures() const
Definition: Assembly.C:4799
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:2393
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:2369
const FEType _helper_type
The finite element type of the FE helper classes.
Definition: Assembly.h:2358
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:4441
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:2687
Base class for a system (of equations)
Definition: SystemBase.h:85
libMesh::QBase * _current_qrule_face
quadrature rule used on faces
Definition: Assembly.h:2522
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:2866
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:2806
std::vector< std::pair< MooseVariableFieldBase *, MooseVariableFieldBase * > > _cm_ff_entry
Entries in the coupling matrix for field variables.
Definition: Assembly.h:2331
void addJacobianNeighborLowerD(GlobalDataKey)
Add all portions of the Jacobian except PrimaryPrimary, e.g.
Definition: Assembly.C:3931
std::map< FEType, FEVectorBase * > _current_vector_fe
The "volume" vector fe object that matches the current elem.
Definition: Assembly.h:2391
VariablePhiGradient _grad_phi
Definition: Assembly.h:2748
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:2828
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:4539
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:2444
unsigned int neighborSideID() const
Definition: FaceInfo.h:114
DenseVector< Number > _tmp_Re
auxiliary vector for scaling residuals (optimization to avoid expensive construction/destruction) ...
Definition: Assembly.h:2666
unsigned int _mesh_dimension
Definition: Assembly.h:2354
virtual QuadratureType type() const=0
std::vector< Eigen::Map< RealDIMValue > > _mapped_normals
Mapped normals.
Definition: Assembly.h:2532
VectorVariablePhiDivergence _vector_div_phi_face
Definition: Assembly.h:2730
void cacheJacobian(GlobalDataKey)
Takes the values that are currently in _sub_Kee and appends them to the cached values.
Definition: Assembly.C:4046
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:2874
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:2430
MONOMIAL_VEC
const std::vector< std::vector< Real > > & get_dphideta_map() const
unsigned int _max_cached_jacobians
Definition: Assembly.h:2812
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:2683
FEType get_fe_type() const
std::map< FEType, std::unique_ptr< VectorFEShapeData > > _vector_fe_shape_data_dual_lower
Definition: Assembly.h:2778
virtual unsigned int nVariables() const
Get the number of variables in this system.
Definition: SystemBase.C:892
virtual const FieldVariablePhiValue & phiFaceNeighbor() const =0
Return the variable&#39;s shape functions on a neighboring element face.
unsigned int n_dofs(const unsigned int s, const unsigned int var=libMesh::invalid_uint) const
std::vector< VectorValue< ADReal > > _ad_dxyzdzeta_map
Definition: Assembly.h:2829
std::vector< Point > _temp_reference_points
Temporary work data for reinitAtPhysical()
Definition: Assembly.h:2824
std::vector< std::pair< MooseVariableScalar *, MooseVariableScalar * > > _cm_ss_entry
Entries in the coupling matrix for scalar variables.
Definition: Assembly.h:2337
std::vector< std::vector< std::vector< DenseMatrix< Number > > > > _sub_Kne
jacobian contributions from the neighbor and element <Tag, ivar, jvar>
Definition: Assembly.h:2685
const Elem * _current_neighbor_lower_d_elem
The current neighboring lower dimensional element.
Definition: Assembly.h:2633
unsigned int _current_neighbor_side
The current side of the selected neighboring element (valid only when working with sides) ...
Definition: Assembly.h:2614
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:2364
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:2774
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:2663
This data structure is used to store geometric and variable related metadata about each cell face in ...
Definition: FaceInfo.h:37
QRules & qrules(unsigned int dim)
Definition: Assembly.h:2490
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:2442
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:2759
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:3843
std::vector< ADReal > _ad_dzetadx_map
Definition: Assembly.h:2842
void addJacobianLowerD(GlobalDataKey)
Add portions of the Jacobian of LowerLower, LowerSecondary, and SecondaryLower for boundary condition...
Definition: Assembly.C:4009
virtual const FieldVariablePhiSecond & secondPhiFace() const =0
Return the rank-2 tensor of second derivatives of the variable&#39;s shape functions on an element face...
void setPoints(const std::vector< libMesh::Point > &points)
Set the quadrature points.
const Elem * neighborPtr() const
Definition: FaceInfo.h:88
VectorVariablePhiGradient _grad_phi
Definition: Assembly.h:2758
MooseArray< ADReal > _ad_curvatures
Definition: Assembly.h:2850
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:2416
void modifyArbitraryWeights(const std::vector< Real > &weights)
Modify the weights when using the arbitrary quadrature rule.
Definition: Assembly.C:4566
std::vector< std::pair< MooseVariableFieldBase *, MooseVariableScalar * > > _cm_fs_entry
Entries in the coupling matrix for field variables vs scalar variables.
Definition: Assembly.h:2333
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:2579
dof_id_type id() const
std::vector< ADReal > _ad_dzetady_map
Definition: Assembly.h:2843
Real value(unsigned n, unsigned alpha, unsigned beta, Real x)
MeshBase & getMesh()
Accessor for the underlying libMesh Mesh object.
Definition: MooseMesh.C:3575
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:2780
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:2459
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:2760
std::map< FEType, FEBase * > _current_fe_neighbor
The "neighbor" fe object that matches the current elem.
Definition: Assembly.h:2386
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:4098
SubdomainID _current_neighbor_subdomain_id
The current neighbor subdomain ID.
Definition: Assembly.h:2612
const std::vector< std::vector< OutputGradient > > & get_dual_dphi() const
std::vector< std::vector< DenseVector< Number > > > _sub_Re
Definition: Assembly.h:2660
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:2838
std::vector< std::vector< std::vector< unsigned char > > > _jacobian_block_used
Flag that indicates if the jacobian block was used.
Definition: Assembly.h:2341
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:93
libMesh::QBase * _current_qrule_lower
quadrature rule used on lower dimensional elements.
Definition: Assembly.h:2592
SubProblem & _subproblem
Definition: Assembly.h:2313
libmesh_assert(ctx)
std::vector< ADReal > _ad_detadx_map
Definition: Assembly.h:2839
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:2546
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:2857
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:4342
MooseArray< std::vector< Point > > _current_tangents
The current tangent vectors at the quadrature points.
Definition: Assembly.h:2534
virtual const std::vector< dof_id_type > & dofIndices() const
Get local DoF indices.
bool _calculate_curvatures
Definition: Assembly.h:2859
const std::vector< VectorTag > & _residual_vector_tags
The residual vector tags that Assembly could possibly contribute to.
Definition: Assembly.h:2795
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:2397
std::vector< dof_id_type > _neighbor_extra_elem_ids
Extra element IDs of neighbor.
Definition: Assembly.h:2539
MooseArray< Real > _current_JxW
The current list of transformed jacobian weights.
Definition: Assembly.h:2420
Order get_order() const
std::vector< VectorValue< ADReal > > _ad_dxyzdxi_map
AD quantities.
Definition: Assembly.h:2827
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:2855
std::vector< dof_id_type > _temp_dof_indices
Temporary work vector to keep from reallocating it.
Definition: Assembly.h:2821
std::set< FEType > _need_neighbor_div
Definition: Assembly.h:2870
L2_RAVIART_THOMAS
OutputTools< Real >::VariablePhiCurl VariablePhiCurl
Definition: MooseTypes.h:351
std::vector< std::vector< std::vector< DenseMatrix< Number > > > > _sub_Kee
Definition: Assembly.h:2679
std::vector< VectorValue< ADReal > > _ad_d2xyzdxi2_map
Definition: Assembly.h:2830
unsigned int get_dim() const
std::vector< ADReal > _ad_jac
Definition: Assembly.h:2833
std::set< FEType > _need_curl
Definition: Assembly.h:2867
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:4284
unsigned int n_points() const
std::map< FEType, std::unique_ptr< VectorFEShapeData > > _vector_fe_shape_data_lower
Definition: Assembly.h:2777
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:2781
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:2516
libMesh::QBase * _current_qrule_volume
The current volumetric quadrature for the element.
Definition: Assembly.h:2412
const std::vector< std::vector< OutputTensor > > & get_d2phi() const
virtual bool computingSecond() const =0
Whether or not this variable is computing any second derivatives.
unsigned int number() const
Gets the number of this system.
Definition: SystemBase.C:1158
const Elem * _msm_elem
Definition: Assembly.h:2883
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:2863
std::map< FEType, std::unique_ptr< FEShapeData > > _fe_shape_data_lower
Definition: Assembly.h:2769
const Elem * _current_lower_d_elem
The current lower dimensional element.
Definition: Assembly.h:2631
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:2865
std::map< unsigned int, std::map< FEType, FEBase * > > _fe_lower
FE objects for lower dimensional elements.
Definition: Assembly.h:2556
bool hasSecondOrderElements()
check if the mesh has SECOND order elements
Definition: MooseMesh.C:3842
std::set< FEType > _need_face_neighbor_div
Definition: Assembly.h:2871
libMesh::QBase * _qrule_msm
A qrule object for working on mortar segement elements.
Definition: Assembly.h:2586
libMesh::ElemSideBuilder _current_neighbor_side_elem_builder
In place side element builder for _current_neighbor_side_elem.
Definition: Assembly.h:2879
OutputTools< Real >::VariablePhiDivergence VariablePhiDivergence
Definition: MooseTypes.h:352
Real _current_lower_d_elem_volume
The current lower dimensional element volume.
Definition: Assembly.h:2637
libMesh::QBase * _current_qrule
The current current quadrature rule being used (could be either volumetric or arbitrary - for dirac k...
Definition: Assembly.h:2410
std::map< unsigned int, std::map< FEType, FEBase * > > _fe
Each dimension&#39;s actual fe objects indexed on type.
Definition: Assembly.h:2402
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:2608
std::set< FEType > _need_div
Definition: Assembly.h:2868
std::vector< std::vector< Real > > _cached_residual_values
Values cached by calling cacheResidual() (the first vector is for TIME vs NONTIME) ...
Definition: Assembly.h:2798
const bool _displaced
Definition: Assembly.h:2315
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:4426
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:2558
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:2622
bool _building_helpers
Whether we are currently building the FE classes for the helpers.
Definition: Assembly.h:2376
bool _calculate_face_xyz
Definition: Assembly.h:2858
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:2836
virtual MooseVariableScalar & getScalarVariable(THREAD_ID tid, const std::string &var_name) const
Gets a reference to a scalar variable with specified number.
Definition: SystemBase.C:146
std::vector< ADReal > _ad_dxidy_map
Definition: Assembly.h:2837
std::vector< VectorValue< ADReal > > _ad_d2xyzdxideta_map
Definition: Assembly.h:2831
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:2776
void addJacobian(GlobalDataKey)
Adds all local Jacobian to the global Jacobian matrices.
Definition: Assembly.C:3858
MooseArray< Point > _current_normals
The current Normal vectors at the quadrature points.
Definition: Assembly.h:2530
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:4845
const SubdomainID ANY_BLOCK_ID
Definition: MooseTypes.C:19
MooseArray< VectorValue< ADReal > > _ad_q_points
Definition: Assembly.h:2835
const VariablePhiGradient & gradPhiNeighbor(const MooseVariableField< Real > &) const
Definition: Assembly.h:1350
MooseArray< VectorValue< ADReal > > _ad_q_points_face
Definition: Assembly.h:2848
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:2318
void hasScalingVector()
signals this object that a vector containing variable scaling factors should be used when doing resid...
Definition: Assembly.C:4560
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:2770
void zeroCachedJacobian(GlobalDataKey)
Zero out previously-cached Jacobian rows.
Definition: Assembly.C:4498
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:2766
virtual libMesh::SparseMatrix< Number > & getMatrix(TagID tag)
Get a raw SparseMatrix.
Definition: SystemBase.C:1025
std::map< FEType, std::unique_ptr< VectorFEShapeData > > _vector_fe_shape_data
Shape function values, gradients, second derivatives for each vector FE type.
Definition: Assembly.h:2773
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:2574
std::vector< std::vector< std::vector< DenseMatrix< Number > > > > _sub_Keg
Definition: Assembly.h:2680
bool _need_lower_d_elem_volume
Whether we need to compute the lower dimensional element volume.
Definition: Assembly.h:2635
bool _user_added_fe_face_of_helper_type
Definition: Assembly.h:2362
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:2448
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:2518
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:2548
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:4076
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:2371
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:4812
std::vector< std::pair< MooseVariableFieldBase *, MooseVariableFieldBase * > > _cm_nonlocal_entry
Entries in the coupling matrix for field variables for nonlocal calculations.
Definition: Assembly.h:2339
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:4448
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:2604
void setCachedJacobian(GlobalDataKey)
Sets previously-cached Jacobian values via SparseMatrix::set() calls.
Definition: Assembly.C:4478
VariablePhiSecond _second_phi
Definition: Assembly.h:2749
const libMesh::CouplingMatrix & _nonlocal_cm
Definition: Assembly.h:2319
std::map< unsigned int, FEBase * > _holder_fe_helper
Each dimension&#39;s helper objects.
Definition: Assembly.h:2406
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:2616
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:2537
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:4216
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:2628
virtual bool isScalarVariable(unsigned int var_name) const
Definition: SystemBase.C:886
virtual void reinit_dual_shape_coeffs(const Elem *, const std::vector< Point > &, const std::vector< Real > &)
std::map< FEType, ADTemplateVariablePhiGradient< RealVectorValue > > _ad_vector_grad_phi_data_face
Definition: Assembly.h:2784
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:2257
std::unique_ptr< ArbitraryQuadrature > arbitrary_face
area/face (meshdim-1) custom points quadrature rule
Definition: Assembly.h:2450
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:2547
void addJacobianNeighbor(GlobalDataKey)
Add ElementNeighbor, NeighborElement, and NeighborNeighbor portions of the Jacobian for compute objec...
Definition: Assembly.C:3893
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:2346
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:2761
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:91
NEDELEC_ONE
void addResidualBlock(NumericVector< Number > &residual, DenseVector< Number > &res_block, const std::vector< dof_id_type > &dof_indices, const std::vector< Real > &scaling_factor)
Add a local residual block to a global residual vector with proper scaling.
Definition: Assembly.C:3249
bool _custom_mortar_qrule
Flag specifying whether a custom quadrature rule has been specified for mortar segment mesh...
Definition: Assembly.h:2588
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:2641
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:2639
MooseArray< Point > _current_q_points
The current list of quadrature points.
Definition: Assembly.h:2418
bool _user_added_fe_of_helper_type
Whether user code requested a FEType the same as our _helper_type.
Definition: Assembly.h:2361
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:2422
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:4136
std::unique_ptr< ArbitraryQuadrature > neighbor
area/face (meshdim-1) custom points quadrature rule for DG
Definition: Assembly.h:2452
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:2344
std::map< unsigned int, FEBase * > _holder_fe_lower_helper
helper object for transforming coordinates for lower dimensional element quadrature points ...
Definition: Assembly.h:2560
static constexpr subdomain_id_type invalid_subdomain_id
const libMesh::DofMap & _dof_map
DOF map.
Definition: Assembly.h:2348
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:2775
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:2810
void addCachedJacobian(GlobalDataKey)
Adds the values that have been cached by calling cacheJacobian() and or cacheJacobianNeighbor() to th...
Definition: Assembly.C:3801
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:2526
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:934
void bumpAllQRuleOrder(Order order, SubdomainID block)
Increases the element/volume and face/area quadrature orders for the specified mesh block if and only...
Definition: Assembly.C: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:2606
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:2815
bool _need_JxW_neighbor
Flag to indicate that JxW_neighbor is needed.
Definition: Assembly.h:2567
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:4060
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:2565
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:2877
VectorVariablePhiCurl _vector_curl_phi_face
Definition: Assembly.h:2729
Key structure for APIs adding/caching local element residuals/Jacobians.
Definition: Assembly.h:862
std::set< FEType > _need_face_div
Definition: Assembly.h:2869
SubdomainID _current_subdomain_id
The current subdomain ID.
Definition: Assembly.h:2598
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:2395
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:2624
std::vector< VectorValue< ADReal > > _ad_d2xyzdeta2_map
Definition: Assembly.h:2832
void clearCachedJacobian()
Clear any currently cached jacobians.
Definition: Assembly.C:4508
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:2697
const std::vector< std::vector< OutputTensor > > & get_dual_d2phi() const
MooseVariableField< T > & getActualFieldVariable(THREAD_ID tid, const std::string &var_name)
Returns a field variable pointer - this includes finite volume variables.
Definition: SystemBase.C:119
void reinitFEFace(const Elem *elem, unsigned int side)
Just an internal helper function to reinit the face FE objects.
Definition: Assembly.C:1268
MooseArray< ADReal > _ad_JxW
Definition: Assembly.h:2834
MooseArray< ADReal > _ad_JxW_face
Definition: Assembly.h:2846
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