LCOV - code coverage report
Current view: top level - src/systems - fem_context.C (source / functions) Hit Total Coverage
Test: libMesh/libmesh: #4481 (67a8c4) with base cc8438 Lines: 513 810 63.3 %
Date: 2026-06-12 15:24:28 Functions: 81 215 37.7 %
Legend: Lines: hit not hit

          Line data    Source code
       1             : // The libMesh Finite Element Library.
       2             : // Copyright (C) 2002-2026 Benjamin S. Kirk, John W. Peterson, Roy H. Stogner
       3             : 
       4             : // This library is free software; you can redistribute it and/or
       5             : // modify it under the terms of the GNU Lesser General Public
       6             : // License as published by the Free Software Foundation; either
       7             : // version 2.1 of the License, or (at your option) any later version.
       8             : 
       9             : // This library is distributed in the hope that it will be useful,
      10             : // but WITHOUT ANY WARRANTY; without even the implied warranty of
      11             : // MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
      12             : // Lesser General Public License for more details.
      13             : 
      14             : // You should have received a copy of the GNU Lesser General Public
      15             : // License along with this library; if not, write to the Free Software
      16             : // Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA  02111-1307  USA
      17             : 
      18             : 
      19             : 
      20             : #include "libmesh/fem_context.h"
      21             : 
      22             : #include "libmesh/boundary_info.h"
      23             : #include "libmesh/diff_system.h"
      24             : #include "libmesh/dof_map.h"
      25             : #include "libmesh/elem.h"
      26             : #include "libmesh/fe_base.h"
      27             : #include "libmesh/fe_interface.h"
      28             : #include "libmesh/libmesh_logging.h"
      29             : #include "libmesh/mesh_base.h"
      30             : #include "libmesh/numeric_vector.h"
      31             : #include "libmesh/quadrature.h"
      32             : #include "libmesh/system.h"
      33             : #include "libmesh/time_solver.h"
      34             : #include "libmesh/unsteady_solver.h" // For euler_residual
      35             : 
      36             : namespace libMesh
      37             : {
      38             : 
      39      233358 : FEMContext::FEMContext (const System & sys,
      40             :                         const std::vector<unsigned int> * active_vars,
      41      233358 :                         bool allocate_local_matrices)
      42      233358 :   : FEMContext(sys, sys.extra_quadrature_order, active_vars,
      43      233358 :                allocate_local_matrices)
      44             : {
      45      233358 :   init_internal_data(sys);
      46      233358 : }
      47             : 
      48      233358 : FEMContext::FEMContext (const System & sys,
      49             :                         int extra_quadrature_order,
      50             :                         const std::vector<unsigned int> * active_vars,
      51      233358 :                         bool allocate_local_matrices)
      52             :   : DiffContext(sys, allocate_local_matrices),
      53       94044 :     side(0), edge(0),
      54       94044 :     _mesh_sys(nullptr),
      55       94044 :     _mesh_x_var(0),
      56       94044 :     _mesh_y_var(0),
      57       94044 :     _mesh_z_var(0),
      58       94044 :     _atype(CURRENT),
      59       94044 :     _custom_solution(nullptr),
      60      233358 :     _boundary_info(sys.get_mesh().get_boundary_info()),
      61       94044 :     _elem(nullptr),
      62      233358 :     _dim(cast_int<unsigned char>(sys.get_mesh().mesh_dimension())),
      63       94044 :     _elem_dim(0), /* This will be reset in set_elem(). */
      64      208971 :     _elem_dims(sys.get_mesh().elem_dimensions()),
      65       94044 :     _element_qrule(4),
      66       94044 :     _side_qrule(4),
      67      466716 :     _extra_quadrature_order(extra_quadrature_order)
      68             : {
      69      233358 :   if (active_vars)
      70             :     {
      71       51994 :       libmesh_assert(!active_vars->empty());
      72             :       auto vars_copy =
      73      226528 :         std::make_unique<std::vector<unsigned int>>(*active_vars);
      74             : 
      75             :       // We want to do quick binary_search later
      76      174534 :       std::sort(vars_copy->begin(), vars_copy->end());
      77             : 
      78      122540 :       _active_vars = std::move(vars_copy);
      79       70546 :     }
      80             : 
      81      233358 :   init_internal_data(sys);
      82      233358 : }
      83             : 
      84             : 
      85             : 
      86      469337 : FEType FEMContext::find_hardest_fe_type()
      87             : {
      88      280208 :   const System & sys = this->get_system();
      89             :   FEType hardest_fe_type =
      90      189129 :     sys.variable_type(_active_vars ?
      91      469337 :                       (*_active_vars)[0] : 0);
      92             : 
      93     1299366 :   auto check_var = [&hardest_fe_type, &sys](unsigned int v)
      94             :     {
      95      565147 :       FEType fe_type = sys.variable_type(v);
      96             : 
      97             :       // Make sure we find a non-SCALAR FE family, even in the case
      98             :       // where the first variable(s) weren't
      99      565147 :       if (hardest_fe_type.family == SCALAR)
     100             :         {
     101           0 :           hardest_fe_type.family = fe_type.family;
     102           0 :           hardest_fe_type.order = fe_type.order;
     103             :         }
     104             : 
     105             :       // FIXME - we don't yet handle mixed finite elements from
     106             :       // different families which require different quadrature rules
     107             :       // libmesh_assert_equal_to (fe_type.family, hardest_fe_type.family);
     108             : 
     109             :       // We need to detect SCALAR's so we can prepare FE objects for
     110             :       // them, and so we don't mistake high order scalars as a reason
     111             :       // to crank up the quadrature order on other types.
     112      565147 :       if (fe_type.family != SCALAR && fe_type.order > hardest_fe_type.order)
     113         840 :         hardest_fe_type = fe_type;
     114      667121 :     };
     115             : 
     116      469337 :   if (_active_vars)
     117      721102 :     for (auto v : *_active_vars)
     118      372034 :       check_var(v);
     119             :   else
     120      313382 :     for (auto v : make_range(sys.n_vars()))
     121      193113 :       check_var(v);
     122             : 
     123      609441 :   return hardest_fe_type;
     124             : }
     125             : 
     126             : 
     127      469273 : void FEMContext::attach_quadrature_rules()
     128             : {
     129      280176 :   const System & sys = this->get_system();
     130             : 
     131     1496843 :   auto attach_rules = [this, &sys](unsigned int v)
     132             :     {
     133     1135852 :       for (const auto & dim : _elem_dims)
     134             :         {
     135      570769 :           FEType fe_type = sys.variable_type(v);
     136             : 
     137      741353 :           _element_fe[dim][fe_type]->attach_quadrature_rule(_element_qrule[dim].get());
     138      570769 :           if (dim)
     139      729625 :             _side_fe[dim][fe_type]->attach_quadrature_rule(_side_qrule[dim].get());
     140      570769 :           if (dim == 3)
     141      149944 :             _edge_fe[fe_type]->attach_quadrature_rule(_edge_qrule.get());
     142             :         };
     143      667041 :     };
     144             : 
     145      469273 :   if (_active_vars)
     146      721102 :     for (auto v : *_active_vars)
     147      372034 :       attach_rules(v);
     148             :   else
     149      313254 :     for (auto v : make_range(sys.n_vars()))
     150      193049 :       attach_rules(v);
     151      469273 : }
     152             : 
     153             : 
     154             : 
     155      466716 : void FEMContext::use_default_quadrature_rules(int extra_quadrature_order)
     156             : {
     157      466716 :   _extra_quadrature_order = extra_quadrature_order;
     158             : 
     159      466716 :   FEType hardest_fe_type = this->find_hardest_fe_type();
     160             : 
     161      936020 :   for (const auto & dim : _elem_dims)
     162             :     {
     163             :       // Create an adequate quadrature rule
     164      469304 :       _element_qrule[dim] =
     165      798586 :         hardest_fe_type.default_quadrature_rule(dim, _extra_quadrature_order);
     166      469304 :       if (dim)
     167      463814 :         _side_qrule[dim] =
     168      927628 :           hardest_fe_type.default_quadrature_rule(dim-1, _extra_quadrature_order);
     169      469304 :       if (dim == 3)
     170      215804 :         _edge_qrule = hardest_fe_type.default_quadrature_rule(1, _extra_quadrature_order);
     171             :     }
     172             : 
     173      466716 :   this->attach_quadrature_rules();
     174      466716 : }
     175             : 
     176             : 
     177        2557 : void FEMContext::use_unweighted_quadrature_rules(int extra_quadrature_order)
     178             : {
     179        2557 :   _extra_quadrature_order = extra_quadrature_order;
     180             : 
     181        2557 :   FEType hardest_fe_type = this->find_hardest_fe_type();
     182             : 
     183        5114 :   for (const auto & dim : _elem_dims)
     184             :     {
     185             :       // Create an adequate quadrature rule
     186        2557 :       _element_qrule[dim] =
     187        4340 :         hardest_fe_type.unweighted_quadrature_rule(dim, _extra_quadrature_order);
     188        2557 :       _side_qrule[dim] =
     189        4340 :         hardest_fe_type.unweighted_quadrature_rule(dim-1, _extra_quadrature_order);
     190        2557 :       if (dim == 3)
     191         240 :         _edge_qrule = hardest_fe_type.unweighted_quadrature_rule(1, _extra_quadrature_order);
     192             :     }
     193             : 
     194        2557 :   this->attach_quadrature_rules();
     195        2557 : }
     196             : 
     197             : 
     198      466716 : void FEMContext::init_internal_data(const System & sys)
     199             : {
     200             :   // Reserve space for the FEAbstract and QBase objects for each
     201             :   // element dimension possibility (0,1,2,3)
     202             : 
     203             :   // Note: we would simply resize() all four of these vectors, but
     204             :   // some compilers (ICC 19, MSVC) generate a diagnostic about copying
     205             :   // a std::unique_ptr in this case, so the following two lines are a
     206             :   // workaround.
     207      466716 :   _element_fe = std::vector<std::map<FEType, std::unique_ptr<FEAbstract>>>(4);
     208      466716 :   _side_fe = std::vector<std::map<FEType, std::unique_ptr<FEAbstract>>>(4);
     209      466716 :   _element_fe_var.resize(4);
     210      466716 :   _side_fe_var.resize(4);
     211             : 
     212             :   // We need to know which of our variables has the hardest
     213             :   // shape functions to numerically integrate.
     214             : 
     215      466716 :   unsigned int nv = sys.n_vars();
     216      139314 :   libmesh_assert (nv);
     217             : 
     218      139314 :   bool have_scalar = false;
     219             : 
     220      466716 :   if (_active_vars)
     221             :     {
     222      721102 :       for (auto v : *_active_vars)
     223      372034 :         if (sys.variable_type(v).family == SCALAR)
     224             :           {
     225           0 :             have_scalar = true;
     226           0 :             break;
     227             :           }
     228             :     }
     229             :   else
     230             :     {
     231      307760 :       for (auto v : make_range(sys.n_vars()))
     232      190492 :         if (sys.variable_type(v).family == SCALAR)
     233             :           {
     234         112 :             have_scalar = true;
     235         112 :             break;
     236             :           }
     237             :     }
     238             : 
     239      466716 :   if (have_scalar)
     240             :     // SCALAR FEs have dimension 0 by assumption
     241         380 :     _elem_dims.insert(0);
     242             : 
     243      228592 :   auto build_var_fe = [this, &sys](unsigned int dim,
     244     2250134 :                                    unsigned int i)
     245             :     {
     246      568212 :       FEType fe_type = sys.variable_type(i);
     247      568212 :       const bool add_p_level = fe_type.p_refinement;
     248             : 
     249      738022 :       auto & element_fe = _element_fe[dim][fe_type];
     250      738022 :       auto & side_fe = _side_fe[dim][fe_type];
     251      568212 :       if (!element_fe)
     252             :         {
     253      860354 :           element_fe = FEAbstract::build(dim, fe_type);
     254      151030 :           element_fe->add_p_level_in_reinit(add_p_level);
     255      860354 :           side_fe = FEAbstract::build(dim, fe_type);
     256      151030 :           side_fe->add_p_level_in_reinit(add_p_level);
     257             : 
     258      505692 :           if (dim == 3)
     259             :           {
     260      129228 :             auto & edge_fe = _edge_fe[fe_type];
     261      222032 :             edge_fe = FEAbstract::build(dim, fe_type);
     262       36424 :             edge_fe->add_p_level_in_reinit(add_p_level);
     263             :           }
     264             :         }
     265             : 
     266      907832 :       _element_fe_var[dim][i] = element_fe.get();
     267      738022 :       _side_fe_var[dim][i] = side_fe.get();
     268      568212 :       if ((dim) == 3)
     269      149804 :         _edge_fe_var[i] = _edge_fe[fe_type].get();
     270      667022 :     };
     271             : 
     272      936020 :   for (const auto & dim : _elem_dims)
     273             :     {
     274             :       // Create finite element objects
     275      609326 :       _element_fe_var[dim].resize(nv);
     276      609326 :       _side_fe_var[dim].resize(nv);
     277      469304 :       if (dim == 3)
     278      125596 :         _edge_fe_var.resize(nv);
     279             : 
     280      469304 :       if (_active_vars)
     281      722990 :         for (auto v : *_active_vars)
     282      372978 :           build_var_fe(dim, v);
     283             :       else
     284      314526 :         for (auto v : make_range(nv))
     285      195234 :           build_var_fe(dim, v);
     286             :     }
     287             : 
     288      466716 :   this->use_default_quadrature_rules(_extra_quadrature_order);
     289      466716 : }
     290             : 
     291      500405 : FEMContext::~FEMContext()
     292             : {
     293      461828 : }
     294             : 
     295             : 
     296             : 
     297      794383 : bool FEMContext::has_side_boundary_id(boundary_id_type id) const
     298             : {
     299      794383 :   return _boundary_info.has_boundary_id(&(this->get_elem()), side, id);
     300             : }
     301             : 
     302             : 
     303             : 
     304           0 : void FEMContext::side_boundary_ids(std::vector<boundary_id_type> & vec_to_fill) const
     305             : {
     306           0 :   _boundary_info.boundary_ids(&(this->get_elem()), side, vec_to_fill);
     307           0 : }
     308             : 
     309             : 
     310             : 
     311             : template<typename OutputType,
     312             :          typename FEMContext::FENeeded<OutputType>::value_getter fe_getter,
     313             :          FEMContext::diff_subsolution_getter subsolution_getter>
     314    91200942 : void FEMContext::some_value(unsigned int var, unsigned int qp, OutputType & u) const
     315             : {
     316             :   // Get local-to-global dof index lookup
     317    25411254 :   const unsigned int n_dofs = cast_int<unsigned int>
     318    50822508 :     (this->get_dof_indices(var).size());
     319             : 
     320             :   // Get current local coefficients
     321    25411254 :   const DenseSubVector<Number> & coef = (this->*subsolution_getter)(var);
     322    25411254 :   libmesh_assert_equal_to(coef.size(), n_dofs);
     323             : 
     324             :   // Get finite element object
     325    25411254 :   typename FENeeded<OutputType>::value_base * fe = nullptr;
     326    25411254 :   (this->*fe_getter)( var, fe, this->get_elem_dim() );
     327             : 
     328             :   // Get shape function values at quadrature point
     329             :   const std::vector<std::vector
     330    25411254 :                     <typename FENeeded<OutputType>::value_shape>> & phi = fe->get_phi();
     331    25411254 :   libmesh_assert_equal_to(phi.size(), n_dofs);
     332             : 
     333             :   // Accumulate solution value
     334    75867009 :   u = 0.;
     335             : 
     336   753643539 :   for (unsigned int l=0; l != n_dofs; l++)
     337             :     {
     338   179827806 :       libmesh_assert_less(qp, phi[l].size());
     339  1200835711 :       u += phi[l][qp] * coef(l);
     340             :     }
     341    91200942 : }
     342             : 
     343             : 
     344             : 
     345             : template<typename OutputType,
     346             :          typename FEMContext::FENeeded<OutputType>::grad_getter fe_getter,
     347             :          FEMContext::diff_subsolution_getter subsolution_getter>
     348    86963802 : void FEMContext::some_gradient(unsigned int var, unsigned int qp, OutputType & du) const
     349             : {
     350             :   // Get local-to-global dof index lookup
     351             :   const unsigned int n_dofs = cast_int<unsigned int>
     352    48169212 :     (this->get_dof_indices(var).size());
     353             : 
     354             :   // Get current local coefficients
     355    24084606 :   const DenseSubVector<Number> & coef = (this->*subsolution_getter)(var);
     356             : 
     357             :   // Get finite element object
     358    24084606 :   typename FENeeded<OutputType>::grad_base * fe = nullptr;
     359    24084606 :   (this->*fe_getter)( var, fe, this->get_elem_dim() );
     360             : 
     361             :   // Get shape function values at quadrature point
     362             :   const std::vector<std::vector
     363             :                     <typename FENeeded<OutputType>::grad_base::OutputGradient>>
     364    24084606 :     & dphi = fe->get_dphi();
     365             : 
     366             :   // Accumulate solution derivatives
     367    24084606 :   du = 0;
     368             : 
     369   757167572 :   for (unsigned int l=0; l != n_dofs; l++)
     370   850350452 :     du.add_scaled(dphi[l][qp], coef(l));
     371             : 
     372   111048408 :   return;
     373             : }
     374             : 
     375             : 
     376             : 
     377             : #ifdef LIBMESH_ENABLE_SECOND_DERIVATIVES
     378             : template<typename OutputType,
     379             :          typename FEMContext::FENeeded<OutputType>::hess_getter fe_getter,
     380             :          FEMContext::diff_subsolution_getter subsolution_getter>
     381           0 : void FEMContext::some_hessian(unsigned int var, unsigned int qp, OutputType & d2u) const
     382             : {
     383             :   // Get local-to-global dof index lookup
     384             :   const unsigned int n_dofs = cast_int<unsigned int>
     385           0 :     (this->get_dof_indices(var).size());
     386             : 
     387             :   // Get current local coefficients
     388           0 :   const DenseSubVector<Number> & coef = (this->*subsolution_getter)(var);
     389             : 
     390             :   // Get finite element object
     391           0 :   typename FENeeded<OutputType>::hess_base * fe = nullptr;
     392           0 :   (this->*fe_getter)( var, fe, this->get_elem_dim() );
     393             : 
     394             :   // Get shape function values at quadrature point
     395             :   const std::vector<std::vector
     396             :                     <typename FENeeded<OutputType>::hess_base::OutputTensor>>
     397           0 :     & d2phi = fe->get_d2phi();
     398             : 
     399             :   // Accumulate solution second derivatives
     400           0 :   d2u = 0.0;
     401             : 
     402           0 :   for (unsigned int l=0; l != n_dofs; l++)
     403           0 :     d2u.add_scaled(d2phi[l][qp], coef(l));
     404             : 
     405           0 :   return;
     406             : }
     407             : #endif
     408             : 
     409             : 
     410             : 
     411      503590 : Number FEMContext::interior_value(unsigned int var, unsigned int qp) const
     412             : {
     413        8269 :   Number u;
     414             : 
     415      330304 :   this->interior_value( var, qp, u );
     416             : 
     417      503590 :   return u;
     418             : }
     419             : 
     420             : template<typename OutputType>
     421    32459888 : void FEMContext::interior_value(unsigned int var, unsigned int qp,
     422             :                                 OutputType & u) const
     423             : {
     424    17173528 :   this->some_value<OutputType,
     425             :                    &FEMContext::get_element_fe<typename TensorTools::MakeReal<OutputType>::type>,
     426    15459646 :                    &DiffContext::get_elem_solution>(var, qp, u);
     427    32459888 : }
     428             : 
     429             : 
     430             : template<typename OutputType>
     431      592704 : void FEMContext::interior_values (unsigned int var,
     432             :                                   const NumericVector<Number> & _system_vector,
     433             :                                   std::vector<OutputType> & u_vals) const
     434             : {
     435             :   typedef typename TensorTools::MakeReal<OutputType>::type OutputShape;
     436             : 
     437             :   // Get local-to-global dof index lookup
     438             :   const unsigned int n_dofs = cast_int<unsigned int>
     439      395136 :     (this->get_dof_indices(var).size());
     440             : 
     441             :   // Get current local coefficients
     442      592704 :   const DenseSubVector<Number> & coef = get_localized_subvector(_system_vector, var);
     443             : 
     444             :   // Get the finite element object
     445      197568 :   FEGenericBase<OutputShape> * fe = nullptr;
     446      197568 :   this->get_element_fe<OutputShape>( var, fe, this->get_elem_dim() );
     447             : 
     448             :   // Get shape function values at quadrature point
     449      197568 :   const std::vector<std::vector<OutputShape>> & phi = fe->get_phi();
     450             : 
     451             :   // Loop over all the q_points on this element
     452     3366720 :   for (auto qp : index_range(u_vals))
     453             :     {
     454      924672 :       OutputType & u = u_vals[qp];
     455             : 
     456             :       // Compute the value at this q_point
     457     2774016 :       u = 0.;
     458             : 
     459    13870080 :       for (unsigned int l=0; l != n_dofs; l++)
     460    22192128 :         u += phi[l][qp] * coef(l);
     461             :     }
     462             : 
     463      790272 :   return;
     464             : }
     465             : 
     466    35328034 : Gradient FEMContext::interior_gradient(unsigned int var,
     467             :                                        unsigned int qp) const
     468             : {
     469    10669062 :   Gradient du;
     470             : 
     471    21338124 :   this->interior_gradient( var, qp, du );
     472             : 
     473    35328034 :   return du;
     474             : }
     475             : 
     476             : 
     477             : 
     478             : template<typename OutputType>
     479    72973892 : void FEMContext::interior_gradient(unsigned int var,
     480             :                                    unsigned int qp,
     481             :                                    OutputType & du) const
     482             : {
     483    48169212 :   this->some_gradient<OutputType,
     484             :                       &FEMContext::get_element_fe<typename TensorTools::MakeReal
     485             :                                                   <typename TensorTools::DecrementRank
     486             :                                                    <OutputType>::type>::type>,
     487    38794590 :                       &DiffContext::get_elem_solution>(var, qp, du);
     488    72973892 : }
     489             : 
     490             : 
     491             : 
     492             : template<typename OutputType>
     493           0 : void FEMContext::interior_gradients(unsigned int var,
     494             :                                     const NumericVector<Number> & _system_vector,
     495             :                                     std::vector<OutputType> & du_vals) const
     496             : {
     497             :   typedef typename TensorTools::MakeReal
     498             :     <typename TensorTools::DecrementRank<OutputType>::type>::type
     499             :     OutputShape;
     500             : 
     501             :   // Get local-to-global dof index lookup
     502             :   const unsigned int n_dofs = cast_int<unsigned int>
     503           0 :     (this->get_dof_indices(var).size());
     504             : 
     505             :   // Get current local coefficients
     506           0 :   const DenseSubVector<Number> & coef = get_localized_subvector(_system_vector, var);
     507             : 
     508             :   // Get finite element object
     509           0 :   FEGenericBase<OutputShape> * fe = nullptr;
     510           0 :   this->get_element_fe<OutputShape>( var, fe, this->get_elem_dim() );
     511             : 
     512             :   // Get shape function values at quadrature point
     513           0 :   const std::vector<std::vector<typename FEGenericBase<OutputShape>::OutputGradient>> & dphi = fe->get_dphi();
     514             : 
     515             :   // Loop over all the q_points in this finite element
     516           0 :   for (auto qp : index_range(du_vals))
     517             :     {
     518           0 :       OutputType & du = du_vals[qp];
     519             : 
     520             :       // Compute the gradient at this q_point
     521           0 :       du = 0;
     522             : 
     523           0 :       for (unsigned int l=0; l != n_dofs; l++)
     524           0 :         du.add_scaled(dphi[l][qp], coef(l));
     525             :     }
     526             : 
     527           0 :   return;
     528             : }
     529             : 
     530             : #ifdef LIBMESH_ENABLE_SECOND_DERIVATIVES
     531           0 : Tensor FEMContext::interior_hessian(unsigned int var, unsigned int qp) const
     532             : {
     533           0 :   Tensor d2u;
     534             : 
     535           0 :   this->interior_hessian( var, qp, d2u );
     536             : 
     537           0 :   return d2u;
     538             : }
     539             : 
     540             : template<typename OutputType>
     541           0 : void FEMContext::interior_hessian(unsigned int var, unsigned int qp,
     542             :                                   OutputType & d2u) const
     543             : {
     544           0 :   this->some_hessian<OutputType,
     545             :                      &FEMContext::get_element_fe
     546             :                      <typename TensorTools::MakeReal
     547             :                       <typename TensorTools::DecrementRank
     548             :                        <typename TensorTools::DecrementRank
     549             :                         <OutputType>::type>::type>::type>,
     550           0 :                      &DiffContext::get_elem_solution>(var, qp, d2u);
     551           0 : }
     552             : 
     553             : 
     554             : template<typename OutputType>
     555           0 : void FEMContext::interior_hessians(unsigned int var,
     556             :                                    const NumericVector<Number> & _system_vector,
     557             :                                    std::vector<OutputType> & d2u_vals) const
     558             : {
     559             :   typedef typename TensorTools::DecrementRank<OutputType>::type Rank1Decrement;
     560             :   typedef typename TensorTools::DecrementRank<Rank1Decrement>::type Rank2Decrement;
     561             :   typedef typename TensorTools::MakeReal<Rank2Decrement>::type OutputShape;
     562             : 
     563             :   // Get local-to-global dof index lookup
     564             :   const unsigned int n_dofs = cast_int<unsigned int>
     565           0 :     (this->get_dof_indices(var).size());
     566             : 
     567             :   // Get current local coefficients
     568           0 :   const DenseSubVector<Number> & coef = get_localized_subvector(_system_vector, var);
     569             : 
     570             :   // Get finite element object
     571           0 :   FEGenericBase<OutputShape> * fe = nullptr;
     572           0 :   this->get_element_fe<OutputShape>( var, fe, this->get_elem_dim() );
     573             : 
     574             :   // Get shape function values at quadrature point
     575           0 :   const std::vector<std::vector<typename FEGenericBase<OutputShape>::OutputTensor>> & d2phi = fe->get_d2phi();
     576             : 
     577             :   // Loop over all the q_points in this finite element
     578           0 :   for (auto qp : index_range(d2u_vals))
     579             :     {
     580           0 :       OutputType & d2u = d2u_vals[qp];
     581             : 
     582             :       // Compute the gradient at this q_point
     583           0 :       d2u = 0;
     584             : 
     585           0 :       for (unsigned int l=0; l != n_dofs; l++)
     586           0 :         d2u.add_scaled(d2phi[l][qp], coef(l));
     587             :     }
     588             : 
     589           0 :   return;
     590             : }
     591             : 
     592             : 
     593             : #endif // ifdef LIBMESH_ENABLE_SECOND_DERIVATIVES
     594             : 
     595             : 
     596             : template<typename OutputType>
     597      550912 : void FEMContext::interior_curl(unsigned int var, unsigned int qp,
     598             :                                OutputType & curl_u) const
     599             : {
     600             :   typedef typename TensorTools::MakeReal<OutputType>::type OutputShape;
     601             : 
     602             :   // Get local-to-global dof index lookup
     603             :   const unsigned int n_dofs = cast_int<unsigned int>
     604      265856 :     (this->get_dof_indices(var).size());
     605             : 
     606             :   // Get current local coefficients
     607      132928 :   libmesh_assert_greater (this->_elem_subsolutions.size(), var);
     608      132928 :   const DenseSubVector<Number> & coef = this->get_elem_solution(var);
     609             : 
     610             :   // Get finite element object
     611      132928 :   FEGenericBase<OutputShape> * fe = nullptr;
     612      132928 :   this->get_element_fe<OutputShape>( var, fe, this->get_elem_dim() );
     613             : 
     614             :   // Get shape function values at quadrature point
     615      352320 :   const std::vector<std::vector<typename FEGenericBase<OutputShape>::OutputShape>> & curl_phi = fe->get_curl_phi();
     616             : 
     617             :   // Accumulate solution curl
     618      132928 :   curl_u = 0.;
     619             : 
     620     4470272 :   for (unsigned int l=0; l != n_dofs; l++)
     621     4883200 :     curl_u.add_scaled(curl_phi[l][qp], coef(l));
     622             : 
     623      683840 :   return;
     624             : }
     625             : 
     626             : 
     627             : template<typename OutputType>
     628           0 : void FEMContext::interior_div(unsigned int var, unsigned int qp,
     629             :                               OutputType & div_u) const
     630             : {
     631             :   typedef typename
     632             :     TensorTools::IncrementRank
     633             :     <typename TensorTools::MakeReal<OutputType>::type>::type OutputShape;
     634             : 
     635             :   // Get local-to-global dof index lookup
     636             :   const unsigned int n_dofs = cast_int<unsigned int>
     637           0 :     (this->get_dof_indices(var).size());
     638             : 
     639             :   // Get current local coefficients
     640           0 :   libmesh_assert_greater (this->_elem_subsolutions.size(), var);
     641           0 :   const DenseSubVector<Number> & coef = this->get_elem_solution(var);
     642             : 
     643             :   // Get finite element object
     644           0 :   FEGenericBase<OutputShape> * fe = nullptr;
     645           0 :   this->get_element_fe<OutputShape>( var, fe, this->get_elem_dim() );
     646             : 
     647             :   // Get shape function values at quadrature point
     648           0 :   const std::vector<std::vector<typename FEGenericBase<OutputShape>::OutputDivergence>> & div_phi = fe->get_div_phi();
     649             : 
     650             :   // Accumulate solution curl
     651           0 :   div_u = 0.;
     652             : 
     653           0 :   for (unsigned int l=0; l != n_dofs; l++)
     654           0 :     div_u += div_phi[l][qp] * coef(l);
     655             : 
     656           0 :   return;
     657             : }
     658             : 
     659             : 
     660     1274440 : Number FEMContext::side_value(unsigned int var,
     661             :                               unsigned int qp) const
     662             : {
     663     1274440 :   Number u = 0.;
     664             : 
     665      705124 :   this->side_value( var, qp, u );
     666             : 
     667     1274440 :   return u;
     668             : }
     669             : 
     670             : 
     671             : template<typename OutputType>
     672      772196 : void FEMContext::side_value(unsigned int var,
     673             :                             unsigned int qp,
     674             :                             OutputType & u) const
     675             : {
     676      738020 :   this->some_value<OutputType,
     677             :                    &FEMContext::get_side_fe<typename TensorTools::MakeReal<OutputType>::type>,
     678      603492 :                    &DiffContext::get_elem_solution>(var, qp, u);
     679      772196 : }
     680             : 
     681             : 
     682             : template<typename OutputType>
     683           0 : void FEMContext::side_values(unsigned int var,
     684             :                              const NumericVector<Number> & _system_vector,
     685             :                              std::vector<OutputType> & u_vals) const
     686             : {
     687             :   typedef typename TensorTools::MakeReal<OutputType>::type OutputShape;
     688             : 
     689             :   // Get local-to-global dof index lookup
     690             :   const unsigned int n_dofs = cast_int<unsigned int>
     691           0 :     (this->get_dof_indices(var).size());
     692             : 
     693             :   // Get current local coefficients
     694           0 :   const DenseSubVector<Number> & coef = get_localized_subvector(_system_vector, var);
     695             : 
     696             :   // Get the finite element object
     697           0 :   FEGenericBase<OutputShape> * the_side_fe = nullptr;
     698           0 :   this->get_side_fe<OutputShape>( var, the_side_fe, this->get_elem_dim() );
     699             : 
     700             :   // Get shape function values at quadrature point
     701           0 :   const std::vector<std::vector<OutputShape>> & phi = the_side_fe->get_phi();
     702             : 
     703             :   // Loop over all the q_points on this element
     704           0 :   for (auto qp : index_range(u_vals))
     705             :     {
     706           0 :       OutputType & u = u_vals[qp];
     707             : 
     708             :       // Compute the value at this q_point
     709           0 :       u = 0.;
     710             : 
     711           0 :       for (unsigned int l=0; l != n_dofs; l++)
     712           0 :         u += phi[l][qp] * coef(l);
     713             :     }
     714             : 
     715           0 :   return;
     716             : }
     717             : 
     718     1945461 : Gradient FEMContext::side_gradient(unsigned int var, unsigned int qp) const
     719             : {
     720      560627 :   Gradient du;
     721             : 
     722     1945461 :   this->side_gradient( var, qp, du );
     723             : 
     724     1945461 :   return du;
     725             : }
     726             : 
     727             : 
     728             : template<typename OutputType>
     729     1945461 : void FEMContext::side_gradient(unsigned int var, unsigned int qp,
     730             :                                OutputType & du) const
     731             : {
     732             :   typedef typename TensorTools::MakeReal
     733             :     <typename TensorTools::DecrementRank<OutputType>::type>::type
     734             :     OutputShape;
     735             : 
     736             :   // Get local-to-global dof index lookup
     737             :   const unsigned int n_dofs = cast_int<unsigned int>
     738     1121254 :     (this->get_dof_indices(var).size());
     739             : 
     740             :   // Get current local coefficients
     741      560627 :   libmesh_assert_greater (this->_elem_subsolutions.size(), var);
     742      560627 :   const DenseSubVector<Number> & coef = this->get_elem_solution(var);
     743             : 
     744             :   // Get finite element object
     745      560627 :   FEGenericBase<OutputShape> * the_side_fe = nullptr;
     746      560627 :   this->get_side_fe<OutputShape>( var, the_side_fe, this->get_elem_dim() );
     747             : 
     748             :   // Get shape function values at quadrature point
     749      560627 :   const std::vector<std::vector<typename FEGenericBase<OutputShape>::OutputGradient>> & dphi = the_side_fe->get_dphi();
     750             : 
     751             :   // Accumulate solution derivatives
     752      560627 :   du = 0.;
     753             : 
     754    14405404 :   for (unsigned int l=0; l != n_dofs; l++)
     755    16254598 :     du.add_scaled(dphi[l][qp], coef(l));
     756             : 
     757     2506088 :   return;
     758             : }
     759             : 
     760             : 
     761             : 
     762             : template<typename OutputType>
     763           0 : void FEMContext::side_gradients(unsigned int var,
     764             :                                 const NumericVector<Number> & _system_vector,
     765             :                                 std::vector<OutputType> & du_vals) const
     766             : {
     767             :   typedef typename TensorTools::MakeReal
     768             :     <typename TensorTools::DecrementRank<OutputType>::type>::type
     769             :     OutputShape;
     770             : 
     771             :   // Get local-to-global dof index lookup
     772             :   const unsigned int n_dofs = cast_int<unsigned int>
     773           0 :     (this->get_dof_indices(var).size());
     774             : 
     775             :   // Get current local coefficients
     776           0 :   const DenseSubVector<Number> & coef = get_localized_subvector(_system_vector, var);
     777             : 
     778             :   // Get finite element object
     779           0 :   FEGenericBase<OutputShape> * the_side_fe = nullptr;
     780           0 :   this->get_side_fe<OutputShape>( var, the_side_fe, this->get_elem_dim() );
     781             : 
     782             :   // Get shape function values at quadrature point
     783           0 :   const std::vector<std::vector<typename FEGenericBase<OutputShape>::OutputGradient>> & dphi = the_side_fe->get_dphi();
     784             : 
     785             :   // Loop over all the q_points in this finite element
     786           0 :   for (auto qp : index_range(du_vals))
     787             :     {
     788           0 :       OutputType & du = du_vals[qp];
     789             : 
     790           0 :       du = 0;
     791             : 
     792             :       // Compute the gradient at this q_point
     793           0 :       for (unsigned int l=0; l != n_dofs; l++)
     794           0 :         du.add_scaled(dphi[l][qp], coef(l));
     795             :     }
     796             : 
     797           0 :   return;
     798             : }
     799             : 
     800             : #ifdef LIBMESH_ENABLE_SECOND_DERIVATIVES
     801           0 : Tensor FEMContext::side_hessian(unsigned int var,
     802             :                                 unsigned int qp) const
     803             : {
     804           0 :   Tensor d2u;
     805             : 
     806           0 :   this->side_hessian( var, qp, d2u );
     807             : 
     808           0 :   return d2u;
     809             : }
     810             : 
     811             : 
     812             : 
     813             : template<typename OutputType>
     814           0 : void FEMContext::side_hessian(unsigned int var,
     815             :                               unsigned int qp,
     816             :                               OutputType & d2u) const
     817             : {
     818           0 :   this->some_hessian<OutputType,
     819             :                      &FEMContext::get_side_fe
     820             :                      <typename TensorTools::MakeReal
     821             :                       <typename TensorTools::DecrementRank
     822             :                        <typename TensorTools::DecrementRank
     823             :                         <OutputType>::type>::type>::type>,
     824           0 :                      &DiffContext::get_elem_solution>(var, qp, d2u);
     825           0 : }
     826             : 
     827             : 
     828             : 
     829             : template<typename OutputType>
     830           0 : void FEMContext::side_hessians(unsigned int var,
     831             :                                const NumericVector<Number> & _system_vector,
     832             :                                std::vector<OutputType> & d2u_vals) const
     833             : {
     834             :   typedef typename TensorTools::DecrementRank<OutputType>::type Rank1Decrement;
     835             :   typedef typename TensorTools::DecrementRank<Rank1Decrement>::type Rank2Decrement;
     836             :   typedef typename TensorTools::MakeReal<Rank2Decrement>::type OutputShape;
     837             : 
     838             :   // Get local-to-global dof index lookup
     839             :   const unsigned int n_dofs = cast_int<unsigned int>
     840           0 :     (this->get_dof_indices(var).size());
     841             : 
     842             :   // Get current local coefficients
     843           0 :   const DenseSubVector<Number> & coef = get_localized_subvector(_system_vector, var);
     844             : 
     845             :   // Get finite element object
     846           0 :   FEGenericBase<OutputShape> * the_side_fe = nullptr;
     847           0 :   this->get_side_fe<OutputShape>( var, the_side_fe, this->get_elem_dim() );
     848             : 
     849             :   // Get shape function values at quadrature point
     850           0 :   const std::vector<std::vector<typename FEGenericBase<OutputShape>::OutputTensor>> & d2phi = the_side_fe->get_d2phi();
     851             : 
     852             :   // Loop over all the q_points in this finite element
     853           0 :   for (auto qp : index_range(d2u_vals))
     854             :     {
     855           0 :       OutputType & d2u = d2u_vals[qp];
     856             : 
     857             :       // Compute the gradient at this q_point
     858           0 :       d2u = 0;
     859             : 
     860           0 :       for (unsigned int l=0; l != n_dofs; l++)
     861           0 :         d2u.add_scaled(d2phi[l][qp], coef(l));
     862             :     }
     863             : 
     864           0 :   return;
     865             : }
     866             : 
     867             : 
     868             : 
     869             : #endif // ifdef LIBMESH_ENABLE_SECOND_DERIVATIVES
     870             : 
     871             : 
     872             : 
     873       16320 : Number FEMContext::point_value(unsigned int var, const Point & p) const
     874             : {
     875       16320 :   Number u = 0.;
     876             : 
     877       16320 :   this->point_value( var, p, u );
     878             : 
     879       16320 :   return u;
     880             : }
     881             : 
     882             : template<typename OutputType>
     883     2278205 : void FEMContext::point_value(unsigned int var,
     884             :                              const Point & p,
     885             :                              OutputType & u,
     886             :                              const Real tolerance) const
     887             : {
     888             :   typedef typename TensorTools::MakeReal<OutputType>::type OutputShape;
     889             : 
     890             :   // Get local-to-global dof index lookup
     891             :   const unsigned int n_dofs = cast_int<unsigned int>
     892     1325792 :     (this->get_dof_indices(var).size());
     893             : 
     894             :   // Get current local coefficients
     895      662896 :   libmesh_assert_greater (this->_elem_subsolutions.size(), var);
     896      662896 :   const DenseSubVector<Number> & coef = this->get_elem_solution(var);
     897             : 
     898             :   // Get finite element object
     899      662896 :   FEGenericBase<OutputShape> * fe = nullptr;
     900      662896 :   this->get_element_fe<OutputShape>( var, fe, this->get_elem_dim() );
     901             : 
     902             :   // Build a FE for calculating u(p)
     903     1325792 :   FEGenericBase<OutputShape> * fe_new =
     904      952413 :     this->build_new_fe( fe, p, tolerance, 0 );
     905             : 
     906             :   // Get the values of the shape function derivatives
     907      662896 :   const std::vector<std::vector<OutputShape>> &  phi = fe_new->get_phi();
     908             : 
     909     1969381 :   u = 0.;
     910             : 
     911    32390151 :   for (unsigned int l=0; l != n_dofs; l++)
     912    47196564 :     u += phi[l][0] * coef(l);
     913             : 
     914     2941101 :   return;
     915             : }
     916             : 
     917             : 
     918             : 
     919       16320 : Gradient FEMContext::point_gradient(unsigned int var, const Point & p) const
     920             : {
     921        5440 :   Gradient grad_u;
     922             : 
     923       16320 :   this->point_gradient( var, p, grad_u );
     924             : 
     925       16320 :   return grad_u;
     926             : }
     927             : 
     928             : 
     929             : 
     930             : template<typename OutputType>
     931       75843 : void FEMContext::point_gradient(unsigned int var,
     932             :                                 const Point & p,
     933             :                                 OutputType & grad_u,
     934             :                                 const Real tolerance) const
     935             : {
     936             :   typedef typename TensorTools::MakeReal
     937             :     <typename TensorTools::DecrementRank<OutputType>::type>::type
     938             :     OutputShape;
     939             : 
     940             :   // Get local-to-global dof index lookup
     941             :   const unsigned int n_dofs = cast_int<unsigned int>
     942       40592 :     (this->get_dof_indices(var).size());
     943             : 
     944             :   // Get current local coefficients
     945       20296 :   libmesh_assert_greater (this->_elem_subsolutions.size(), var);
     946       20296 :   const DenseSubVector<Number> & coef = this->get_elem_solution(var);
     947             : 
     948             :   // Get finite element object
     949       20296 :   FEGenericBase<OutputShape> * fe = nullptr;
     950       20296 :   this->get_element_fe<OutputShape>( var, fe, this->get_elem_dim() );
     951             : 
     952             :   // Build a FE for calculating u(p)
     953       40592 :   FEGenericBase<OutputShape> * fe_new =
     954       35251 :     this->build_new_fe( fe, p, tolerance, 1 );
     955             : 
     956             :   // Get the values of the shape function derivatives
     957       20296 :   const std::vector<std::vector<typename FEGenericBase<OutputShape>::OutputGradient>> &  dphi = fe_new->get_dphi();
     958             : 
     959       20296 :   grad_u = 0.0;
     960             : 
     961      923257 :   for (unsigned int l=0; l != n_dofs; l++)
     962     1070918 :     grad_u.add_scaled(dphi[l][0], coef(l));
     963             : 
     964       96139 :   return;
     965             : }
     966             : 
     967             : 
     968             : 
     969             : #ifdef LIBMESH_ENABLE_SECOND_DERIVATIVES
     970             : 
     971           0 : Tensor FEMContext::point_hessian(unsigned int var, const Point & p) const
     972             : {
     973           0 :   Tensor hess_u;
     974             : 
     975           0 :   this->point_hessian( var, p, hess_u );
     976             : 
     977           0 :   return hess_u;
     978             : }
     979             : 
     980             : 
     981             : template<typename OutputType>
     982          15 : void FEMContext::point_hessian(unsigned int var,
     983             :                                const Point & p,
     984             :                                OutputType & hess_u,
     985             :                                const Real tolerance) const
     986             : {
     987             :   typedef typename TensorTools::DecrementRank<OutputType>::type Rank1Decrement;
     988             :   typedef typename TensorTools::DecrementRank<Rank1Decrement>::type Rank2Decrement;
     989             :   typedef typename TensorTools::MakeReal<Rank2Decrement>::type OutputShape;
     990             : 
     991             :   // Get local-to-global dof index lookup
     992             :   const unsigned int n_dofs = cast_int<unsigned int>
     993           6 :     (this->get_dof_indices(var).size());
     994             : 
     995             :   // Get current local coefficients
     996           3 :   libmesh_assert_greater (this->_elem_subsolutions.size(), var);
     997           3 :   const DenseSubVector<Number> & coef = this->get_elem_solution(var);
     998             : 
     999             :   // Get finite element object
    1000           3 :   FEGenericBase<OutputShape> * fe = nullptr;
    1001           3 :   this->get_element_fe<OutputShape>( var, fe, this->get_elem_dim() );
    1002             : 
    1003             :   // Build a FE for calculating u(p)
    1004           6 :   FEGenericBase<OutputShape> * fe_new =
    1005           9 :     this->build_new_fe( fe, p, tolerance, 2 );
    1006             : 
    1007             :   // Get the values of the shape function derivatives
    1008           3 :   const std::vector<std::vector<typename FEGenericBase<OutputShape>::OutputTensor>> &  d2phi = fe_new->get_d2phi();
    1009             : 
    1010           3 :   hess_u = 0.0;
    1011             : 
    1012         135 :   for (unsigned int l=0; l != n_dofs; l++)
    1013         144 :     hess_u.add_scaled(d2phi[l][0], coef(l));
    1014             : 
    1015          18 :   return;
    1016             : }
    1017             : 
    1018             : #endif // LIBMESH_ENABLE_SECOND_DERIVATIVES
    1019             : 
    1020             : 
    1021             : template<typename OutputType>
    1022           0 : void FEMContext::point_curl(unsigned int var,
    1023             :                             const Point & p,
    1024             :                             OutputType & curl_u,
    1025             :                             const Real tolerance) const
    1026             : {
    1027             :   typedef typename TensorTools::MakeReal<OutputType>::type OutputShape;
    1028             : 
    1029             :   // Get local-to-global dof index lookup
    1030             :   const unsigned int n_dofs = cast_int<unsigned int>
    1031           0 :     (this->get_dof_indices(var).size());
    1032             : 
    1033             :   // Get current local coefficients
    1034           0 :   libmesh_assert_greater (this->_elem_subsolutions.size(), var);
    1035           0 :   const DenseSubVector<Number> & coef = this->get_elem_solution(var);
    1036             : 
    1037             :   // Get finite element object
    1038           0 :   FEGenericBase<OutputShape> * fe = nullptr;
    1039           0 :   this->get_element_fe<OutputShape>( var, fe, this->get_elem_dim() );
    1040             : 
    1041             :   // Build a FE for calculating u(p)
    1042           0 :   FEGenericBase<OutputShape> * fe_new =
    1043           0 :     this->build_new_fe( fe, p, tolerance, 3 );
    1044             : 
    1045             :   // Get the values of the shape function derivatives
    1046           0 :   const std::vector<std::vector<typename FEGenericBase<OutputShape>::OutputShape>> &  curl_phi = fe_new->get_curl_phi();
    1047             : 
    1048           0 :   curl_u = 0.0;
    1049             : 
    1050           0 :   for (unsigned int l=0; l != n_dofs; l++)
    1051           0 :     curl_u.add_scaled(curl_phi[l][0], coef(l));
    1052             : 
    1053           0 :   return;
    1054             : }
    1055             : 
    1056             : 
    1057             : 
    1058           0 : Number FEMContext::fixed_interior_value(unsigned int var, unsigned int qp) const
    1059             : {
    1060           0 :   Number u = 0.;
    1061             : 
    1062           0 :   this->fixed_interior_value( var, qp, u );
    1063             : 
    1064           0 :   return u;
    1065             : }
    1066             : 
    1067             : 
    1068             : 
    1069             : template<typename OutputType>
    1070           0 : void FEMContext::fixed_interior_value(unsigned int var, unsigned int qp,
    1071             :                                       OutputType & u) const
    1072             : {
    1073           0 :   this->some_value<OutputType,
    1074             :                    &FEMContext::get_element_fe
    1075             :                    <typename TensorTools::MakeReal<OutputType>::type>,
    1076           0 :                    &DiffContext::get_elem_fixed_solution>(var, qp, u);
    1077           0 : }
    1078             : 
    1079             : 
    1080             : 
    1081           0 : Gradient FEMContext::fixed_interior_gradient(unsigned int var, unsigned int qp) const
    1082             : {
    1083           0 :   Gradient du;
    1084             : 
    1085           0 :   this->fixed_interior_gradient( var, qp, du );
    1086             : 
    1087           0 :   return du;
    1088             : }
    1089             : 
    1090             : 
    1091             : template<typename OutputType>
    1092           0 : void FEMContext::fixed_interior_gradient(unsigned int var, unsigned int qp,
    1093             :                                          OutputType & du) const
    1094             : {
    1095           0 :   this->some_gradient
    1096             :     <OutputType,
    1097             :      &FEMContext::get_element_fe
    1098             :      <typename TensorTools::MakeReal
    1099             :       <typename TensorTools::DecrementRank
    1100             :        <OutputType>::type>::type>,
    1101             :      &DiffContext::get_elem_fixed_solution>
    1102           0 :     (var, qp, du);
    1103           0 : }
    1104             : 
    1105             : 
    1106             : 
    1107             : #ifdef LIBMESH_ENABLE_SECOND_DERIVATIVES
    1108           0 : Tensor FEMContext::fixed_interior_hessian(unsigned int var, unsigned int qp) const
    1109             : {
    1110           0 :   Tensor d2u;
    1111             : 
    1112           0 :   this->fixed_interior_hessian( var, qp, d2u );
    1113             : 
    1114           0 :   return d2u;
    1115             : }
    1116             : 
    1117             : 
    1118             : template<typename OutputType>
    1119           0 : void FEMContext::fixed_interior_hessian(unsigned int var, unsigned int qp,
    1120             :                                         OutputType & d2u) const
    1121             : {
    1122           0 :   this->some_hessian<OutputType,
    1123             :                      &FEMContext::get_element_fe
    1124             :                      <typename TensorTools::MakeReal
    1125             :                       <typename TensorTools::DecrementRank
    1126             :                        <typename TensorTools::DecrementRank
    1127             :                         <OutputType>::type>::type>::type>,
    1128           0 :                      &DiffContext::get_elem_fixed_solution>(var, qp, d2u);
    1129           0 : }
    1130             : #endif // ifdef LIBMESH_ENABLE_SECOND_DERIVATIVES
    1131             : 
    1132             : 
    1133             : 
    1134           0 : Number FEMContext::fixed_side_value(unsigned int var, unsigned int qp) const
    1135             : {
    1136           0 :   Number u = 0.;
    1137             : 
    1138           0 :   this->fixed_side_value( var, qp, u );
    1139             : 
    1140           0 :   return u;
    1141             : }
    1142             : 
    1143             : 
    1144             : template<typename OutputType>
    1145           0 : void FEMContext::fixed_side_value(unsigned int var, unsigned int qp,
    1146             :                                   OutputType & u) const
    1147             : {
    1148           0 :   this->some_value
    1149             :     <OutputType,
    1150             :      &FEMContext::get_side_fe
    1151             :      <typename TensorTools::MakeReal<OutputType>::type>,
    1152             :      &DiffContext::get_elem_fixed_solution>
    1153           0 :     (var, qp, u);
    1154           0 : }
    1155             : 
    1156             : 
    1157             : 
    1158           0 : Gradient FEMContext::fixed_side_gradient(unsigned int var, unsigned int qp) const
    1159             : {
    1160           0 :   Gradient du;
    1161             : 
    1162           0 :   this->fixed_side_gradient( var, qp, du );
    1163             : 
    1164           0 :   return du;
    1165             : }
    1166             : 
    1167             : 
    1168             : template<typename OutputType>
    1169           0 : void FEMContext::fixed_side_gradient(unsigned int var, unsigned int qp,
    1170             :                                      OutputType & du) const
    1171             : {
    1172           0 :   this->some_gradient<OutputType,
    1173             :                       &FEMContext::get_side_fe
    1174             :                       <typename TensorTools::MakeReal
    1175             :                        <typename TensorTools::DecrementRank
    1176             :                         <OutputType>::type>::type>,
    1177           0 :                       &DiffContext::get_elem_fixed_solution>(var, qp, du);
    1178           0 : }
    1179             : 
    1180             : 
    1181             : 
    1182             : #ifdef LIBMESH_ENABLE_SECOND_DERIVATIVES
    1183           0 : Tensor FEMContext::fixed_side_hessian(unsigned int var, unsigned int qp) const
    1184             : {
    1185           0 :   Tensor d2u;
    1186             : 
    1187           0 :   this->fixed_side_hessian( var, qp, d2u );
    1188             : 
    1189           0 :   return d2u;
    1190             : }
    1191             : 
    1192             : template<typename OutputType>
    1193           0 : void FEMContext::fixed_side_hessian(unsigned int var, unsigned int qp,
    1194             :                                     OutputType & d2u) const
    1195             : {
    1196           0 :   this->some_hessian<OutputType,
    1197             :                      &FEMContext::get_side_fe
    1198             :                      <typename TensorTools::MakeReal
    1199             :                       <typename TensorTools::DecrementRank
    1200             :                        <typename TensorTools::DecrementRank
    1201             :                         <OutputType>::type>::type>::type>,
    1202           0 :                      &DiffContext::get_elem_fixed_solution>(var, qp, d2u);
    1203           0 : }
    1204             : #endif // ifdef LIBMESH_ENABLE_SECOND_DERIVATIVES
    1205             : 
    1206             : 
    1207             : 
    1208           0 : Number FEMContext::fixed_point_value(unsigned int var, const Point & p) const
    1209             : {
    1210           0 :   Number u = 0.;
    1211             : 
    1212           0 :   this->fixed_point_value( var, p, u );
    1213             : 
    1214           0 :   return u;
    1215             : }
    1216             : 
    1217             : template<typename OutputType>
    1218           0 : void FEMContext::fixed_point_value(unsigned int var,
    1219             :                                    const Point & p,
    1220             :                                    OutputType & u,
    1221             :                                    const Real tolerance) const
    1222             : {
    1223             :   typedef typename TensorTools::MakeReal<OutputType>::type OutputShape;
    1224             : 
    1225             :   // Get local-to-global dof index lookup
    1226             :   const unsigned int n_dofs = cast_int<unsigned int>
    1227           0 :     (this->get_dof_indices(var).size());
    1228             : 
    1229             :   // Get current local coefficients
    1230           0 :   libmesh_assert_greater (_elem_fixed_subsolutions.size(), var);
    1231           0 :   const DenseSubVector<Number> & coef = this->get_elem_fixed_solution(var);
    1232             : 
    1233             :   // Get finite element object
    1234           0 :   FEGenericBase<OutputShape> * fe = nullptr;
    1235           0 :   this->get_element_fe<OutputShape>( var, fe, this->get_elem_dim() );
    1236             : 
    1237             :   // Build a FE for calculating u(p)
    1238           0 :   FEGenericBase<OutputShape> * fe_new =
    1239           0 :     this->build_new_fe( fe, p, tolerance, 0 );
    1240             : 
    1241             :   // Get the values of the shape function derivatives
    1242           0 :   const std::vector<std::vector<OutputShape>> &  phi = fe_new->get_phi();
    1243             : 
    1244           0 :   u = 0.;
    1245             : 
    1246           0 :   for (unsigned int l=0; l != n_dofs; l++)
    1247           0 :     u += phi[l][0] * coef(l);
    1248             : 
    1249           0 :   return;
    1250             : }
    1251             : 
    1252             : 
    1253             : 
    1254           0 : Gradient FEMContext::fixed_point_gradient(unsigned int var, const Point & p) const
    1255             : {
    1256           0 :   Gradient grad_u;
    1257             : 
    1258           0 :   this->fixed_point_gradient( var, p, grad_u );
    1259             : 
    1260           0 :   return grad_u;
    1261             : }
    1262             : 
    1263             : 
    1264             : 
    1265             : template<typename OutputType>
    1266           0 : void FEMContext::fixed_point_gradient(unsigned int var,
    1267             :                                       const Point & p,
    1268             :                                       OutputType & grad_u,
    1269             :                                       const Real tolerance) const
    1270             : {
    1271             :   typedef typename TensorTools::MakeReal
    1272             :     <typename TensorTools::DecrementRank<OutputType>::type>::type
    1273             :     OutputShape;
    1274             : 
    1275             :   // Get local-to-global dof index lookup
    1276             :   const unsigned int n_dofs = cast_int<unsigned int>
    1277           0 :     (this->get_dof_indices(var).size());
    1278             : 
    1279             :   // Get current local coefficients
    1280           0 :   libmesh_assert_greater (_elem_fixed_subsolutions.size(), var);
    1281           0 :   const DenseSubVector<Number> & coef = this->get_elem_fixed_solution(var);
    1282             : 
    1283             :   // Get finite element object
    1284           0 :   FEGenericBase<OutputShape> * fe = nullptr;
    1285           0 :   this->get_element_fe<OutputShape>( var, fe, this->get_elem_dim() );
    1286             : 
    1287             :   // Build a FE for calculating u(p)
    1288           0 :   FEGenericBase<OutputShape> * fe_new =
    1289           0 :     this->build_new_fe( fe, p, tolerance, 1 );
    1290             : 
    1291             :   // Get the values of the shape function derivatives
    1292           0 :   const std::vector<std::vector<typename FEGenericBase<OutputShape>::OutputGradient>> &  dphi = fe_new->get_dphi();
    1293             : 
    1294           0 :   grad_u = 0.0;
    1295             : 
    1296           0 :   for (unsigned int l=0; l != n_dofs; l++)
    1297           0 :     grad_u.add_scaled(dphi[l][0], coef(l));
    1298             : 
    1299           0 :   return;
    1300             : }
    1301             : 
    1302             : 
    1303             : #ifdef LIBMESH_ENABLE_SECOND_DERIVATIVES
    1304             : 
    1305           0 : Tensor FEMContext::fixed_point_hessian(unsigned int var, const Point & p) const
    1306             : {
    1307           0 :   Tensor hess_u;
    1308             : 
    1309           0 :   this->fixed_point_hessian( var, p, hess_u );
    1310             : 
    1311           0 :   return hess_u;
    1312             : }
    1313             : 
    1314             : 
    1315             : 
    1316             : template<typename OutputType>
    1317           0 : void FEMContext::fixed_point_hessian(unsigned int var,
    1318             :                                      const Point & p,
    1319             :                                      OutputType & hess_u,
    1320             :                                      const Real tolerance) const
    1321             : {
    1322             :   typedef typename TensorTools::DecrementRank<OutputType>::type Rank1Decrement;
    1323             :   typedef typename TensorTools::DecrementRank<Rank1Decrement>::type Rank2Decrement;
    1324             :   typedef typename TensorTools::MakeReal<Rank2Decrement>::type OutputShape;
    1325             : 
    1326             :   // Get local-to-global dof index lookup
    1327             :   const unsigned int n_dofs = cast_int<unsigned int>
    1328           0 :     (this->get_dof_indices(var).size());
    1329             : 
    1330             :   // Get current local coefficients
    1331           0 :   libmesh_assert_greater (_elem_fixed_subsolutions.size(), var);
    1332           0 :   const DenseSubVector<Number> & coef = this->get_elem_fixed_solution(var);
    1333             : 
    1334             :   // Get finite element object
    1335           0 :   FEGenericBase<OutputShape> * fe = nullptr;
    1336           0 :   this->get_element_fe<OutputShape>( var, fe, this->get_elem_dim() );
    1337             : 
    1338             :   // Build a FE for calculating u(p)
    1339           0 :   FEGenericBase<OutputShape> * fe_new =
    1340           0 :     this->build_new_fe( fe, p, tolerance, 2 );
    1341             : 
    1342             :   // Get the values of the shape function derivatives
    1343           0 :   const std::vector<std::vector<typename FEGenericBase<OutputShape>::OutputTensor>> &  d2phi = fe_new->get_d2phi();
    1344             : 
    1345           0 :   hess_u = 0.0;
    1346             : 
    1347           0 :   for (unsigned int l=0; l != n_dofs; l++)
    1348           0 :     hess_u.add_scaled(d2phi[l][0], coef(l));
    1349             : 
    1350           0 :   return;
    1351             : }
    1352             : 
    1353             : #endif // LIBMESH_ENABLE_SECOND_DERIVATIVES
    1354             : 
    1355             : 
    1356             : 
    1357             : template<typename OutputType>
    1358    44515696 : void FEMContext::interior_rate(unsigned int var, unsigned int qp,
    1359             :                                OutputType & u) const
    1360             : {
    1361    26171416 :   this->some_value<OutputType,
    1362             :                    &FEMContext::get_element_fe
    1363             :                    <typename TensorTools::MakeReal<OutputType>::type>,
    1364    18344280 :                    &DiffContext::get_elem_solution_rate>(var, qp, u);
    1365    44515696 : }
    1366             : 
    1367             : template<typename OutputType>
    1368           0 : void FEMContext::interior_rate_gradient(unsigned int var, unsigned int qp,
    1369             :                                         OutputType & dudot) const
    1370             : {
    1371           0 :   this->some_gradient<OutputType,
    1372             :                       &FEMContext::get_element_fe<typename TensorTools::MakeReal
    1373             :                                                   <typename TensorTools::DecrementRank
    1374             :                                                    <OutputType>::type>::type>,
    1375           0 :                       &DiffContext::get_elem_solution_rate>(var, qp, dudot);
    1376           0 : }
    1377             : 
    1378             : template<typename OutputType>
    1379           0 : void FEMContext::side_rate(unsigned int var, unsigned int qp,
    1380             :                            OutputType & u) const
    1381             : {
    1382           0 :   this->some_value<OutputType,
    1383             :                    &FEMContext::get_side_fe
    1384             :                    <typename TensorTools::MakeReal<OutputType>::type>,
    1385           0 :                    &DiffContext::get_elem_solution_rate>(var, qp, u);
    1386           0 : }
    1387             : 
    1388             : template<typename OutputType>
    1389    12710560 : void FEMContext::interior_accel(unsigned int var, unsigned int qp,
    1390             :                                 OutputType & u) const
    1391             : {
    1392     6739544 :   this->some_value<OutputType,
    1393             :                    &FEMContext::get_element_fe
    1394             :                    <typename TensorTools::MakeReal<OutputType>::type>,
    1395     5971016 :                    &DiffContext::get_elem_solution_accel>(var, qp, u);
    1396    12710560 : }
    1397             : 
    1398             : 
    1399             : 
    1400             : template<typename OutputType>
    1401           0 : void FEMContext::side_accel(unsigned int var, unsigned int qp,
    1402             :                             OutputType & u) const
    1403             : {
    1404           0 :   this->some_value<OutputType,
    1405             :                    &FEMContext::get_side_fe
    1406             :                    <typename TensorTools::MakeReal<OutputType>::type>,
    1407           0 :                    &DiffContext::get_elem_solution_accel>(var, qp, u);
    1408           0 : }
    1409             : 
    1410             : 
    1411             : 
    1412    10967848 : void FEMContext::elem_reinit(Real theta)
    1413             : {
    1414             :   // Update the "time" variable of this context object
    1415    10967848 :   this->_update_time_from_system(theta);
    1416             : 
    1417             :   // Handle a moving element if necessary.
    1418    10967848 :   if (_mesh_sys)
    1419             :     {
    1420             :       // We assume that the ``default'' state
    1421             :       // of the mesh is its final, theta=1.0
    1422             :       // position, so we don't bother with
    1423             :       // mesh motion in that case.
    1424           0 :       if (theta != 1.0)
    1425             :         {
    1426             :           // FIXME - ALE is not threadsafe yet!
    1427           0 :           libmesh_assert_equal_to (libMesh::n_threads(), 1);
    1428             : 
    1429           0 :           elem_position_set(theta);
    1430             :         }
    1431           0 :       elem_fe_reinit();
    1432             :     }
    1433    10967848 : }
    1434             : 
    1435             : 
    1436     1234400 : void FEMContext::elem_side_reinit(Real theta)
    1437             : {
    1438             :   // Update the "time" variable of this context object
    1439     1234400 :   this->_update_time_from_system(theta);
    1440             : 
    1441             :   // Handle a moving element if necessary
    1442     1234400 :   if (_mesh_sys)
    1443             :     {
    1444             :       // FIXME - not threadsafe yet!
    1445           0 :       elem_position_set(theta);
    1446           0 :       side_fe_reinit();
    1447             :     }
    1448     1234400 : }
    1449             : 
    1450             : 
    1451           0 : void FEMContext::elem_edge_reinit(Real theta)
    1452             : {
    1453             :   // Update the "time" variable of this context object
    1454           0 :   this->_update_time_from_system(theta);
    1455             : 
    1456             :   // Handle a moving element if necessary
    1457           0 :   if (_mesh_sys)
    1458             :     {
    1459             :       // FIXME - not threadsafe yet!
    1460           0 :       elem_position_set(theta);
    1461           0 :       edge_fe_reinit();
    1462             :     }
    1463           0 : }
    1464             : 
    1465             : 
    1466           0 : void FEMContext::nonlocal_reinit(Real theta)
    1467             : {
    1468             :   // Update the "time" variable of this context object
    1469           0 :   this->_update_time_from_system(theta);
    1470             : 
    1471             :   // We can reuse the Elem FE safely here.
    1472           0 :   elem_fe_reinit();
    1473           0 : }
    1474             : 
    1475             : 
    1476    11337493 : void FEMContext::elem_fe_reinit(const std::vector<Point> * const pts)
    1477             : {
    1478             :   // Initialize all the interior FE objects on elem.
    1479             :   // Logging of FE::reinit is done in the FE functions
    1480             :   // We only reinit the FE objects for the current element
    1481             :   // dimension
    1482     3569233 :   const unsigned char dim = this->get_elem_dim();
    1483             : 
    1484     3569233 :   libmesh_assert( !_element_fe[dim].empty() );
    1485             : 
    1486    24112026 :   for (const auto & pr : _element_fe[dim])
    1487             :     {
    1488    12774533 :       if (this->has_elem())
    1489    12774533 :         pr.second->reinit(&(this->get_elem()), pts);
    1490             :         // If !this->has_elem(), then still might need to reinit for a
    1491             :         // SCALAR variable; everything else will depend on an elem
    1492           0 :       else if (pr.first.family == SCALAR)
    1493           0 :         pr.second->reinit(nullptr);
    1494             :     }
    1495    11337493 : }
    1496             : 
    1497             : 
    1498     3476476 : void FEMContext::side_fe_reinit ()
    1499             : {
    1500             :   // Initialize all the side FE objects on elem/side.
    1501             :   // Logging of FE::reinit is done in the FE functions
    1502             :   // We only reinit the FE objects for the current element
    1503             :   // dimension
    1504      983776 :   const unsigned char dim = this->get_elem_dim();
    1505             : 
    1506      983776 :   libmesh_assert( !_side_fe[dim].empty() );
    1507             : 
    1508     7120307 :   for (auto & pr : _side_fe[dim])
    1509     3643831 :     pr.second->reinit(&(this->get_elem()), this->get_side());
    1510     3476476 : }
    1511             : 
    1512             : 
    1513             : 
    1514       31584 : void FEMContext::edge_fe_reinit ()
    1515             : {
    1516        8130 :   libmesh_assert_equal_to (this->get_elem_dim(), 3);
    1517             : 
    1518             :   // Initialize all the interior FE objects on elem/edge.
    1519             :   // Logging of FE::reinit is done in the FE functions
    1520       74538 :   for (auto & pr : _edge_fe)
    1521       42954 :     pr.second->edge_reinit(&(this->get_elem()), this->get_edge());
    1522       31584 : }
    1523             : 
    1524             : 
    1525             : 
    1526          64 : void FEMContext::elem_position_get()
    1527             : {
    1528             :   // This is too expensive to call unless we've been asked to move the mesh
    1529           0 :   libmesh_assert (_mesh_sys);
    1530             : 
    1531             :   // This will probably break with threading when two contexts are
    1532             :   // operating on elements which share a node
    1533           0 :   libmesh_assert_equal_to (libMesh::n_threads(), 1);
    1534             : 
    1535             :   // If the coordinate data is in our own system, it's already
    1536             :   // been set up for us
    1537             :   //  if (_mesh_sys == this->number())
    1538             :   //    {
    1539          64 :   unsigned int n_nodes = this->get_elem().n_nodes();
    1540             : 
    1541             : #ifndef NDEBUG
    1542           0 :   const unsigned char dim = this->get_elem_dim();
    1543             : 
    1544             :   // For simplicity we demand that mesh coordinates be stored
    1545             :   // in a format that allows a direct copy
    1546           0 :   libmesh_assert(this->get_mesh_x_var() == libMesh::invalid_uint ||
    1547             :                  (this->get_element_fe(this->get_mesh_x_var(), dim)->get_fe_type().family
    1548             :                   == FEMap::map_fe_type(this->get_elem()) &&
    1549             :                   this->get_element_fe(this->get_mesh_x_var(), dim)->get_fe_type().order.get_order()
    1550             :                   == this->get_elem().default_order()));
    1551           0 :   libmesh_assert(this->get_mesh_y_var() == libMesh::invalid_uint ||
    1552             :                  (this->get_element_fe(this->get_mesh_y_var(), dim)->get_fe_type().family
    1553             :                   == FEMap::map_fe_type(this->get_elem()) &&
    1554             :                   this->get_element_fe(this->get_mesh_y_var(), dim)->get_fe_type().order.get_order()
    1555             :                   == this->get_elem().default_order()));
    1556           0 :   libmesh_assert(this->get_mesh_z_var() == libMesh::invalid_uint ||
    1557             :                  (this->get_element_fe(this->get_mesh_z_var(), dim)->get_fe_type().family
    1558             :                   == FEMap::map_fe_type(this->get_elem()) &&
    1559             :                   this->get_element_fe(this->get_mesh_z_var(), dim)->get_fe_type().order.get_order()
    1560             :                   == this->get_elem().default_order()));
    1561             : #endif
    1562             : 
    1563             :   // Get degree of freedom coefficients from point coordinates
    1564          64 :   if (this->get_mesh_x_var() != libMesh::invalid_uint)
    1565         576 :     for (unsigned int i=0; i != n_nodes; ++i)
    1566         512 :       (this->get_elem_solution(this->get_mesh_x_var()))(i) = this->get_elem().point(i)(0);
    1567             : 
    1568          64 :   if (this->get_mesh_y_var() != libMesh::invalid_uint)
    1569         576 :     for (unsigned int i=0; i != n_nodes; ++i)
    1570         512 :       (this->get_elem_solution(this->get_mesh_y_var()))(i) = this->get_elem().point(i)(1);
    1571             : 
    1572          64 :   if (this->get_mesh_z_var() != libMesh::invalid_uint)
    1573         576 :     for (unsigned int i=0; i != n_nodes; ++i)
    1574         512 :       (this->get_elem_solution(this->get_mesh_z_var()))(i) = this->get_elem().point(i)(2);
    1575             :   //    }
    1576             :   // FIXME - If the coordinate data is not in our own system, someone
    1577             :   // had better get around to implementing that... - RHS
    1578             :   //  else
    1579             :   //    {
    1580             :   //      libmesh_not_implemented();
    1581             :   //    }
    1582          64 : }
    1583             : 
    1584             : 
    1585             : 
    1586           0 : void FEMContext::set_jacobian_tolerance(Real tol)
    1587             : {
    1588           0 :   for (auto & m : _element_fe)
    1589           0 :     for (auto & pr : m)
    1590           0 :       pr.second->get_fe_map().set_jacobian_tolerance(tol);
    1591             : 
    1592           0 :   for (auto & m : _side_fe)
    1593           0 :     for (auto & pr : m)
    1594           0 :       pr.second->get_fe_map().set_jacobian_tolerance(tol);
    1595             : 
    1596           0 :   for (auto & pr : _edge_fe)
    1597           0 :     pr.second->get_fe_map().set_jacobian_tolerance(tol);
    1598           0 : }
    1599             : 
    1600             : 
    1601             : 
    1602             : // We can ignore the theta argument in the current use of this
    1603             : // function, because elem_subsolutions will already have been set to
    1604             : // the theta value.
    1605             : //
    1606             : // To enable loose mesh movement coupling things will need to change.
    1607        2560 : void FEMContext::_do_elem_position_set(Real)
    1608             : {
    1609             :   // This is too expensive to call unless we've been asked to move the mesh
    1610           0 :   libmesh_assert (_mesh_sys);
    1611             : 
    1612             :   // This will probably break with threading when two contexts are
    1613             :   // operating on elements which share a node
    1614           0 :   libmesh_assert_equal_to (libMesh::n_threads(), 1);
    1615             : 
    1616             :   // If the coordinate data is in our own system, it's already
    1617             :   // been set up for us, and we can ignore our input parameter theta
    1618             :   //  if (_mesh_sys == this->number())
    1619             :   //    {
    1620        2560 :   unsigned int n_nodes = this->get_elem().n_nodes();
    1621             : 
    1622             : #ifndef NDEBUG
    1623           0 :   const unsigned char dim = this->get_elem_dim();
    1624             : 
    1625             :   // For simplicity we demand that mesh coordinates be stored
    1626             :   // in a format that allows a direct copy
    1627           0 :   libmesh_assert(this->get_mesh_x_var() == libMesh::invalid_uint ||
    1628             :                  (this->get_element_fe(this->get_mesh_x_var(), dim)->get_fe_type().family
    1629             :                   == FEMap::map_fe_type(this->get_elem()) &&
    1630             :                   this->get_elem_solution(this->get_mesh_x_var()).size() == n_nodes));
    1631           0 :   libmesh_assert(this->get_mesh_y_var() == libMesh::invalid_uint ||
    1632             :                  (this->get_element_fe(this->get_mesh_y_var(), dim)->get_fe_type().family
    1633             :                   == FEMap::map_fe_type(this->get_elem()) &&
    1634             :                   this->get_elem_solution(this->get_mesh_y_var()).size() == n_nodes));
    1635           0 :   libmesh_assert(this->get_mesh_z_var() == libMesh::invalid_uint ||
    1636             :                  (this->get_element_fe(this->get_mesh_z_var(), dim)->get_fe_type().family
    1637             :                   == FEMap::map_fe_type(this->get_elem()) &&
    1638             :                   this->get_elem_solution(this->get_mesh_z_var()).size() == n_nodes));
    1639             : #endif
    1640             : 
    1641             :   // Set the new point coordinates
    1642        2560 :   if (this->get_mesh_x_var() != libMesh::invalid_uint)
    1643       23040 :     for (unsigned int i=0; i != n_nodes; ++i)
    1644       20480 :       const_cast<Elem &>(this->get_elem()).point(i)(0) =
    1645           0 :         libmesh_real(this->get_elem_solution(this->get_mesh_x_var())(i));
    1646             : 
    1647        2560 :   if (this->get_mesh_y_var() != libMesh::invalid_uint)
    1648       23040 :     for (unsigned int i=0; i != n_nodes; ++i)
    1649       20480 :       const_cast<Elem &>(this->get_elem()).point(i)(1) =
    1650           0 :         libmesh_real(this->get_elem_solution(this->get_mesh_y_var())(i));
    1651             : 
    1652        2560 :   if (this->get_mesh_z_var() != libMesh::invalid_uint)
    1653       23040 :     for (unsigned int i=0; i != n_nodes; ++i)
    1654       20480 :       const_cast<Elem &>(this->get_elem()).point(i)(2) =
    1655           0 :         libmesh_real(this->get_elem_solution(this->get_mesh_z_var())(i));
    1656             :   //    }
    1657             :   // FIXME - If the coordinate data is not in our own system, someone
    1658             :   // had better get around to implementing that... - RHS
    1659             :   //  else
    1660             :   //    {
    1661             :   //      libmesh_not_implemented();
    1662             :   //    }
    1663        2560 : }
    1664             : 
    1665             : 
    1666             : 
    1667             : 
    1668             : 
    1669             : /*
    1670             :   void FEMContext::reinit(const FEMSystem & sys, Elem * e)
    1671             :   {
    1672             :   // Initialize our elem pointer, algebraic objects
    1673             :   this->pre_fe_reinit(e);
    1674             : 
    1675             :   // Moving the mesh may be necessary
    1676             :   // Reinitializing the FE objects is definitely necessary
    1677             :   this->elem_reinit(1.);
    1678             :   }
    1679             : */
    1680             : 
    1681             : 
    1682             : 
    1683    15497217 : void FEMContext::pre_fe_reinit(const System & sys, const Elem * e)
    1684             : {
    1685    15497217 :   this->set_elem(e);
    1686             : 
    1687    16175332 :   if (algebraic_type() == CURRENT ||
    1688      678115 :       algebraic_type() == DOFS_ONLY)
    1689             :     {
    1690             :       // Initialize the per-element data for elem.
    1691    14445151 :       if (this->has_elem())
    1692    14445151 :         sys.get_dof_map().dof_indices (&(this->get_elem()), this->get_dof_indices());
    1693             :       else
    1694             :         // If !this->has_elem(), then we assume we are dealing with a SCALAR variable
    1695           0 :         sys.get_dof_map().dof_indices
    1696           0 :           (static_cast<Elem*>(nullptr), this->get_dof_indices());
    1697             :     }
    1698             : #ifdef LIBMESH_ENABLE_AMR
    1699     1057524 :   else if (algebraic_type() == OLD ||
    1700        5458 :            algebraic_type() == OLD_DOFS_ONLY)
    1701             :     {
    1702             :       // Initialize the per-element data for elem.
    1703     1052066 :       if (this->has_elem())
    1704     1052066 :         sys.get_dof_map().old_dof_indices (&(this->get_elem()), this->get_dof_indices());
    1705             :       else
    1706             :         // If !this->has_elem(), then we assume we are dealing with a SCALAR variable
    1707           0 :         sys.get_dof_map().old_dof_indices
    1708           0 :           (static_cast<Elem*>(nullptr), this->get_dof_indices());
    1709             :     }
    1710             : #endif // LIBMESH_ENABLE_AMR
    1711             : 
    1712             :   const unsigned int n_dofs = cast_int<unsigned int>
    1713     9426823 :     (this->get_dof_indices().size());
    1714     4713501 :   const unsigned int n_qoi = sys.n_qois();
    1715             : 
    1716    20210718 :   if (this->algebraic_type() != NONE &&
    1717    29946304 :       this->algebraic_type() != DOFS_ONLY &&
    1718     4323240 :       this->algebraic_type() != OLD_DOFS_ONLY)
    1719             :     {
    1720             :       // This also resizes elem_solution
    1721    14042421 :       if (_custom_solution == nullptr)
    1722    13006760 :         sys.current_local_solution->get(this->get_dof_indices(), this->get_elem_solution().get_values());
    1723             :       else
    1724     1035661 :         _custom_solution->get(this->get_dof_indices(), this->get_elem_solution().get_values());
    1725             : 
    1726    14042421 :       if (sys.use_fixed_solution)
    1727           0 :         this->get_elem_fixed_solution().resize(n_dofs);
    1728             : 
    1729             :       // Only make space for these if we're using DiffSystem
    1730             :       // This is assuming *only* DiffSystem is using elem_solution_rate/accel
    1731    14042421 :       const DifferentiableSystem * diff_system = dynamic_cast<const DifferentiableSystem *>(&sys);
    1732    14042421 :       if (diff_system)
    1733             :         {
    1734             :           // Now, we only need these if the solver is unsteady
    1735    11445055 :           if (!diff_system->get_time_solver().is_steady())
    1736             :             {
    1737     6617176 :               this->get_elem_solution_rate().resize(n_dofs);
    1738             : 
    1739             :               // We only need accel space if the TimeSolver is second order
    1740     3202000 :               const UnsteadySolver & time_solver = cast_ref<const UnsteadySolver &>(diff_system->get_time_solver());
    1741             : 
    1742     9819158 :               if (time_solver.time_order() >= 2 || !diff_system->get_second_order_vars().empty())
    1743      215000 :                 this->get_elem_solution_accel().resize(n_dofs);
    1744             :             }
    1745             :         }
    1746             : 
    1747    14042421 :       if (algebraic_type() != OLD)
    1748             :         {
    1749             :           // These resize calls also zero out the residual and jacobian
    1750     8971374 :           this->get_elem_residual().resize(n_dofs);
    1751    13006760 :           if (this->_have_local_matrices)
    1752     7700447 :             this->get_elem_jacobian().resize(n_dofs, n_dofs);
    1753             : 
    1754    13006760 :           this->get_qoi_derivatives().resize(n_qoi);
    1755    13006760 :           this->_elem_qoi_subderivatives.resize(n_qoi);
    1756    22462760 :           for (std::size_t q=0; q != n_qoi; ++q)
    1757     9456000 :             (this->get_qoi_derivatives())[q].resize(n_dofs);
    1758             :         }
    1759             :     }
    1760             : 
    1761             :   // Initialize the per-variable data for elem.
    1762             :   {
    1763     4713501 :     unsigned int sub_dofs = 0;
    1764    34997724 :     for (auto i : make_range(sys.n_vars()))
    1765             :       {
    1766    20234859 :         if (algebraic_type() == CURRENT ||
    1767      734352 :             algebraic_type() == DOFS_ONLY)
    1768             :           {
    1769    18387564 :             if (this->has_elem())
    1770    23845437 :               sys.get_dof_map().dof_indices (&(this->get_elem()), this->get_dof_indices(i), i);
    1771             :             else
    1772             :               // If !this->has_elem(), then we assume we are dealing with a SCALAR variable
    1773           0 :               sys.get_dof_map().dof_indices
    1774           0 :                 (static_cast<Elem*>(nullptr), this->get_dof_indices(i), i);
    1775             :           }
    1776             : #ifdef LIBMESH_ENABLE_AMR
    1777     1129215 :         else if (algebraic_type() == OLD ||
    1778       16272 :                  algebraic_type() == OLD_DOFS_ONLY)
    1779             :           {
    1780     1112943 :             if (this->has_elem())
    1781     1112943 :               sys.get_dof_map().old_dof_indices (&(this->get_elem()), this->get_dof_indices(i), i);
    1782             :             else
    1783             :               // If !this->has_elem(), then we assume we are dealing with a SCALAR variable
    1784           0 :               sys.get_dof_map().old_dof_indices
    1785           0 :                 (static_cast<Elem*>(nullptr), this->get_dof_indices(i), i);
    1786             :           }
    1787             : #endif // LIBMESH_ENABLE_AMR
    1788             : 
    1789    25264807 :         if (this->algebraic_type() != NONE &&
    1790    37860257 :             this->algebraic_type() != DOFS_ONLY &&
    1791     5336375 :             this->algebraic_type() != OLD_DOFS_ONLY)
    1792             :           {
    1793             :             const unsigned int n_dofs_var = cast_int<unsigned int>
    1794    15959567 :               (this->get_dof_indices(i).size());
    1795             : 
    1796             : 
    1797    18719021 :             if (!_active_vars ||
    1798     1524818 :                 std::binary_search(_active_vars->begin(),
    1799             :                                    _active_vars->end(), i))
    1800             :               {
    1801    15960294 :                 this->get_elem_solution(i).reposition
    1802     5320098 :                   (sub_dofs, n_dofs_var);
    1803             : 
    1804             :                 // Only make space for these if we're using DiffSystem
    1805             :                 // This is assuming *only* DiffSystem is using elem_solution_rate/accel
    1806    17882874 :                 const DifferentiableSystem * diff_system = dynamic_cast<const DifferentiableSystem *>(&sys);
    1807    17882874 :                 if (diff_system)
    1808             :                   {
    1809             :                     // Now, we only need these if the solver is unsteady
    1810    14484523 :                     if (!diff_system->get_time_solver().is_steady())
    1811             :                       {
    1812    11536488 :                         this->get_elem_solution_rate(i).reposition
    1813     3845496 :                           (sub_dofs, n_dofs_var);
    1814             : 
    1815             :                         // We only need accel space if the TimeSolver is second order
    1816     3845496 :                         const UnsteadySolver & time_solver = cast_ref<const UnsteadySolver &>(diff_system->get_time_solver());
    1817             : 
    1818    12241622 :                         if (time_solver.time_order() >= 2 || !diff_system->get_second_order_vars().empty())
    1819     1108752 :                           this->get_elem_solution_accel(i).reposition
    1820      369584 :                             (sub_dofs, n_dofs_var);
    1821             :                       }
    1822             :                   }
    1823             : 
    1824    17882874 :                 if (sys.use_fixed_solution)
    1825           0 :                   this->get_elem_fixed_solution(i).reposition
    1826           0 :                     (sub_dofs, n_dofs_var);
    1827             : 
    1828    17882874 :                 if (algebraic_type() != OLD)
    1829             :                   {
    1830    15089829 :                     this->get_elem_residual(i).reposition
    1831     5029943 :                       (sub_dofs, n_dofs_var);
    1832             : 
    1833    26299306 :                     for (std::size_t q=0; q != n_qoi; ++q)
    1834     9318924 :                       this->get_qoi_derivatives(q,i).reposition
    1835     3106308 :                         (sub_dofs, n_dofs_var);
    1836             : 
    1837    16818862 :                     if (this->_have_local_matrices)
    1838             :                       {
    1839    21742520 :                         for (unsigned int j=0; j != i; ++j)
    1840             :                           {
    1841             :                             const unsigned int n_dofs_var_j =
    1842             :                               cast_int<unsigned int>
    1843     3550756 :                               (this->get_dof_indices(j).size());
    1844             : 
    1845     5326134 :                             this->get_elem_jacobian(i,j).reposition
    1846     3550756 :                               (sub_dofs, this->get_elem_residual(j).i_off(),
    1847             :                                n_dofs_var, n_dofs_var_j);
    1848     5326134 :                             this->get_elem_jacobian(j,i).reposition
    1849     3550756 :                               (this->get_elem_residual(j).i_off(), sub_dofs,
    1850             :                                n_dofs_var_j, n_dofs_var);
    1851             :                           }
    1852    13582713 :                         this->get_elem_jacobian(i,i).reposition
    1853     4527571 :                           (sub_dofs, sub_dofs,
    1854             :                            n_dofs_var,
    1855             :                            n_dofs_var);
    1856             :                       }
    1857             :                   }
    1858             :               }
    1859             : 
    1860    17882894 :             sub_dofs += n_dofs_var;
    1861             :           }
    1862             :       }
    1863             : 
    1864    14140324 :     if (this->algebraic_type() != NONE &&
    1865     9036741 :         this->algebraic_type() != DOFS_ONLY &&
    1866    13750242 :         this->algebraic_type() != OLD &&
    1867     4040844 :         this->algebraic_type() != OLD_DOFS_ONLY)
    1868     4035386 :       libmesh_assert_equal_to (sub_dofs, n_dofs);
    1869             :   }
    1870             : 
    1871             :   // Now do the localization for the user requested vectors
    1872    20210718 :   if (this->algebraic_type() != NONE &&
    1873    29946304 :       this->algebraic_type() != DOFS_ONLY &&
    1874     4323240 :       this->algebraic_type() != OLD_DOFS_ONLY)
    1875             :     {
    1876     4317782 :       DiffContext::localized_vectors_iterator localized_vec_it = this->_localized_vectors.begin();
    1877     4317782 :       const DiffContext::localized_vectors_iterator localized_vec_end = this->_localized_vectors.end();
    1878             : 
    1879    21142773 :       for (; localized_vec_it != localized_vec_end; ++localized_vec_it)
    1880             :         {
    1881     7100352 :           const NumericVector<Number> & current_localized_vector = *localized_vec_it->first;
    1882     2366784 :           DenseVector<Number> & target_vector = localized_vec_it->second.first;
    1883             : 
    1884     7100352 :           current_localized_vector.get(this->get_dof_indices(), target_vector.get_values());
    1885             : 
    1886             :           // Initialize the per-variable data for elem.
    1887     7100352 :           unsigned int sub_dofs = 0;
    1888    11833920 :           auto init_localized_var_data = [this, localized_vec_it, &sub_dofs](unsigned int i)
    1889             :             {
    1890             :               const unsigned int n_dofs_var = cast_int<unsigned int>
    1891     4733568 :                 (this->get_dof_indices(i).size());
    1892             : 
    1893             :               // This is redundant with earlier initialization, isn't it? - RHS
    1894             :               // sys.get_dof_map().dof_indices (&(this->get_elem()), this->get_dof_indices(i), i);
    1895             : 
    1896     4733568 :               localized_vec_it->second.second[i].reposition
    1897     7100352 :                 (sub_dofs, n_dofs_var);
    1898             : 
    1899     9467136 :               sub_dofs += n_dofs_var;
    1900     7100352 :             };
    1901             : 
    1902     7100352 :           if (_active_vars)
    1903           0 :             for (auto v : *_active_vars)
    1904           0 :               init_localized_var_data(v);
    1905             :           else
    1906    14200704 :             for (auto v : make_range(sys.n_vars()))
    1907     4733568 :               init_localized_var_data(v);
    1908             : 
    1909     2366784 :           libmesh_assert_equal_to (sub_dofs, n_dofs);
    1910             :         }
    1911             :     }
    1912    15497217 : }
    1913             : 
    1914    15497217 : void FEMContext::set_elem( const Elem * e )
    1915             : {
    1916    15497217 :   this->_elem = e;
    1917             : 
    1918             :   // If e is nullptr, we assume it's SCALAR and set _elem_dim to 0.
    1919    15497217 :   this->_elem_dim =
    1920    15497217 :     cast_int<unsigned char>(this->_elem ? this->_elem->dim() : 0);
    1921    15497217 : }
    1922             : 
    1923    12202248 : void FEMContext::_update_time_from_system(Real theta)
    1924             : {
    1925             :   // Update the "time" variable based on the value of theta.  For this
    1926             :   // to work, we need to know the value of deltat, a pointer to which is now
    1927             :   // stored by our parent DiffContext class.  Note: get_deltat_value() will
    1928             :   // assert in debug mode if the requested pointer is nullptr.
    1929    12202248 :   const Real deltat = this->get_deltat_value();
    1930             : 
    1931    12202248 :   this->set_time(theta*(this->get_system_time() + deltat) + (1.-theta)*this->get_system_time());
    1932    12202248 : }
    1933             : 
    1934             : 
    1935             : 
    1936             : template<>
    1937             : FEGenericBase<Real> *
    1938     2367299 : FEMContext::cached_fe( const unsigned int elem_dim,
    1939             :                        const FEType fe_type,
    1940             :                        const int get_derivative_level ) const
    1941             : {
    1942             : #ifdef LIBMESH_ENABLE_INFINITE_ELEMENTS
    1943             :   const bool fe_needs_inf =
    1944     1688468 :     this->has_elem() && this->get_elem().infinite();
    1945             : #endif
    1946             : 
    1947     3043527 :   if (!_real_fe ||
    1948     2364308 :       elem_dim != _real_fe->get_dim() ||
    1949     4422380 :       fe_type != _real_fe->get_fe_type() ||
    1950     2349615 :       get_derivative_level != _real_fe_derivative_level)
    1951             :     {
    1952       17694 :       _real_fe_derivative_level = get_derivative_level;
    1953             : 
    1954             :       _real_fe =
    1955             : #ifdef LIBMESH_ENABLE_INFINITE_ELEMENTS
    1956       25828 :         fe_needs_inf ?
    1957             :         FEGenericBase<Real>::build_InfFE(elem_dim, fe_type) :
    1958             : #endif
    1959       14747 :         FEGenericBase<Real>::build(elem_dim, fe_type);
    1960             :     }
    1961             : 
    1962             : #ifdef LIBMESH_ENABLE_INFINITE_ELEMENTS
    1963     1675554 :   else if (fe_needs_inf && !_real_fe_is_inf)
    1964         352 :     _real_fe =
    1965         582 :       FEGenericBase<Real>::build_InfFE(elem_dim, fe_type);
    1966     1675018 :   else if (!fe_needs_inf && _real_fe_is_inf)
    1967             :     _real_fe =
    1968         590 :       FEGenericBase<Real>::build(elem_dim, fe_type);
    1969             : 
    1970     1688468 :   _real_fe_is_inf =
    1971     1688468 :     (this->has_elem() && this->get_elem().infinite());
    1972             : #endif
    1973             : 
    1974     2367299 :   return _real_fe.get();
    1975             : }
    1976             : 
    1977             : 
    1978             : template<>
    1979             : FEGenericBase<RealGradient> *
    1980       17820 : FEMContext::cached_fe( const unsigned int elem_dim,
    1981             :                        const FEType fe_type,
    1982             :                        const int get_derivative_level ) const
    1983             : {
    1984             : #ifdef LIBMESH_ENABLE_INFINITE_ELEMENTS
    1985             :   const bool fe_needs_inf =
    1986       13227 :     this->has_elem() && this->get_elem().infinite();
    1987             : #endif
    1988             : 
    1989       22014 :   if (!_real_grad_fe ||
    1990       17421 :       elem_dim != _real_grad_fe->get_dim() ||
    1991       31257 :       fe_type != _real_grad_fe->get_fe_type() ||
    1992       17421 :       get_derivative_level != _real_grad_fe_derivative_level)
    1993             :     {
    1994         399 :       _real_grad_fe_derivative_level = get_derivative_level;
    1995             : 
    1996             :       _real_grad_fe =
    1997             : #ifdef LIBMESH_ENABLE_INFINITE_ELEMENTS
    1998         570 :         fe_needs_inf ?
    1999             :         FEGenericBase<RealGradient>::build_InfFE(elem_dim, fe_type) :
    2000             : #endif
    2001         342 :         FEGenericBase<RealGradient>::build(elem_dim, fe_type);
    2002             :     }
    2003             : 
    2004             : #ifdef LIBMESH_ENABLE_INFINITE_ELEMENTS
    2005       12942 :   else if (fe_needs_inf && !_real_grad_fe_is_inf)
    2006           0 :     _real_grad_fe =
    2007           0 :       FEGenericBase<RealGradient>::build_InfFE(elem_dim, fe_type);
    2008       12942 :   else if (!fe_needs_inf && _real_grad_fe_is_inf)
    2009             :     _real_grad_fe =
    2010           0 :       FEGenericBase<RealGradient>::build(elem_dim, fe_type);
    2011             : 
    2012       13227 :   _real_grad_fe_is_inf =
    2013       13227 :     (this->has_elem() && this->get_elem().infinite());
    2014             : #endif
    2015             : 
    2016       17820 :   return _real_grad_fe.get();
    2017             : }
    2018             : 
    2019             : 
    2020             : 
    2021             : template<typename OutputShape>
    2022             : FEGenericBase<OutputShape> *
    2023     2385119 : FEMContext::build_new_fe( const FEGenericBase<OutputShape>* fe,
    2024             :                           const Point & p,
    2025             :                           const Real tolerance,
    2026             :                           const int get_derivative_level) const
    2027             : {
    2028     1376971 :   FEType fe_type = fe->get_fe_type();
    2029             : 
    2030             :   // If we don't have an Elem to evaluate on, then the only functions
    2031             :   // we can sensibly evaluate are the scalar dofs which are the same
    2032             :   // everywhere.
    2033      693547 :   libmesh_assert(this->has_elem() || fe_type.family == SCALAR);
    2034             : 
    2035             : #ifdef LIBMESH_ENABLE_AMR
    2036     2385119 :   const int add_p_level = fe->add_p_level_in_reinit();
    2037     3056324 :   if ((algebraic_type() == OLD) &&
    2038     1342410 :       this->has_elem())
    2039             :     {
    2040     2988454 :       if (this->get_elem().p_refinement_flag() == Elem::JUST_REFINED)
    2041       25465 :         fe_type.order -= add_p_level;
    2042     2215209 :       else if (this->get_elem().p_refinement_flag() == Elem::JUST_COARSENED)
    2043         152 :         fe_type.order += add_p_level;
    2044             :     }
    2045             : #endif // LIBMESH_ENABLE_AMR
    2046             : 
    2047     2385119 :   const unsigned int elem_dim = this->has_elem() ? this->get_elem().dim() : 0;
    2048             : 
    2049     1387094 :   FEGenericBase<OutputShape>* fe_new =
    2050      998025 :     cached_fe<OutputShape>(elem_dim, fe_type, get_derivative_level);
    2051             : #ifdef LIBMESH_ENABLE_AMR
    2052      693547 :   fe_new->add_p_level_in_reinit(add_p_level);
    2053             : #endif // LIBMESH_ENABLE_AMR
    2054             : 
    2055             :   // Map the physical co-ordinates to the master co-ordinates using the inverse_map from fe_interface.h
    2056             :   // Build a vector of point co-ordinates to send to reinit
    2057     2385119 :   Point master_point = this->has_elem() ?
    2058     2385119 :     FEMap::inverse_map (elem_dim, &this->get_elem(), p, tolerance) :
    2059             :     Point(0);
    2060             : 
    2061     2385119 :   std::vector<Point> coor(1, master_point);
    2062             : 
    2063     2385119 :   switch (get_derivative_level)
    2064             :     {
    2065       10352 :     case -1:
    2066       10352 :       fe_new->get_phi();
    2067       10352 :       fe_new->get_dphi();
    2068             : #ifdef LIBMESH_ENABLE_SECOND_DERIVATIVES
    2069       10352 :       fe_new->get_d2phi();
    2070             : #endif
    2071       20704 :       fe_new->get_curl_phi();
    2072       10352 :       break;
    2073      662896 :     case 0:
    2074      662896 :       fe_new->get_phi();
    2075      662896 :       break;
    2076       20296 :     case 1:
    2077       20296 :       fe_new->get_dphi();
    2078       20296 :       break;
    2079           3 :     case 2:
    2080             : #ifdef LIBMESH_ENABLE_SECOND_DERIVATIVES
    2081           3 :       fe_new->get_d2phi();
    2082             : #else
    2083             :       // here a different configuration is required.
    2084             :       libmesh_not_implemented();
    2085             : #endif
    2086           3 :       break;
    2087           0 :     case 3:
    2088           0 :       fe_new->get_curl_phi();
    2089           0 :       break;
    2090           0 :     default:
    2091           0 :       libmesh_error();
    2092             :     }
    2093             : 
    2094             :   // Reinitialize the element and compute the shape function values at coor
    2095     2385119 :   if (this->has_elem())
    2096     2385119 :     fe_new->reinit (&this->get_elem(), &coor);
    2097             :   else
    2098             :     // If !this->has_elem(), then we assume we are dealing with a SCALAR variable
    2099           0 :     fe_new->reinit (nullptr, &coor);
    2100             : 
    2101     3078666 :   return fe_new;
    2102             : }
    2103             : 
    2104             : 
    2105             : 
    2106             : 
    2107             : 
    2108             : // Instantiate member function templates
    2109             : template LIBMESH_EXPORT void FEMContext::interior_value<Number>(unsigned int, unsigned int, Number &) const;
    2110             : template LIBMESH_EXPORT void FEMContext::interior_values<Number>(unsigned int, const NumericVector<Number> &,
    2111             :                                                   std::vector<Number> &) const;
    2112             : template LIBMESH_EXPORT void FEMContext::interior_value<Gradient>(unsigned int, unsigned int, Gradient &) const;
    2113             : template LIBMESH_EXPORT void FEMContext::interior_values<Gradient>(unsigned int, const NumericVector<Number> &,
    2114             :                                                     std::vector<Gradient> &) const;
    2115             : 
    2116             : template LIBMESH_EXPORT void FEMContext::interior_gradient<Gradient>(unsigned int, unsigned int, Gradient &) const;
    2117             : template LIBMESH_EXPORT void FEMContext::interior_gradients<Gradient>(unsigned int, const NumericVector<Number> &,
    2118             :                                                        std::vector<Gradient> &) const;
    2119             : template LIBMESH_EXPORT void FEMContext::interior_gradient<Tensor>(unsigned int, unsigned int, Tensor &) const;
    2120             : template LIBMESH_EXPORT void FEMContext::interior_gradients<Tensor>(unsigned int, const NumericVector<Number> &,
    2121             :                                                      std::vector<Tensor> &) const;
    2122             : 
    2123             : #ifdef LIBMESH_ENABLE_SECOND_DERIVATIVES
    2124             : template LIBMESH_EXPORT void FEMContext::interior_hessian<Tensor>(unsigned int, unsigned int, Tensor &) const;
    2125             : template LIBMESH_EXPORT void FEMContext::interior_hessians<Tensor>(unsigned int, const NumericVector<Number> &,
    2126             :                                                     std::vector<Tensor> &) const;
    2127             : //FIXME: Not everything is implemented yet for second derivatives of RealGradients
    2128             : //template LIBMESH_EXPORT void FEMContext::interior_hessian<??>(unsigned int, unsigned int, ??&) const;
    2129             : //template LIBMESH_EXPORT void FEMContext::interior_hessians<??>(unsigned int, const NumericVector<Number> &,
    2130             : //                                                std::vector<??> &) const;
    2131             : #endif
    2132             : 
    2133             : template LIBMESH_EXPORT void FEMContext::interior_curl<Gradient>(unsigned int, unsigned int, Gradient &) const;
    2134             : 
    2135             : template LIBMESH_EXPORT void FEMContext::interior_div<Number>(unsigned int, unsigned int, Number &) const;
    2136             : 
    2137             : template LIBMESH_EXPORT void FEMContext::side_value<Number>(unsigned int, unsigned int, Number &) const;
    2138             : template LIBMESH_EXPORT void FEMContext::side_value<Gradient>(unsigned int, unsigned int, Gradient &) const;
    2139             : template LIBMESH_EXPORT void FEMContext::side_values<Number>(unsigned int, const NumericVector<Number> &,
    2140             :                                               std::vector<Number> &) const;
    2141             : template LIBMESH_EXPORT void FEMContext::side_values<Gradient>(unsigned int, const NumericVector<Number> &,
    2142             :                                                 std::vector<Gradient> &) const;
    2143             : 
    2144             : template LIBMESH_EXPORT void FEMContext::side_gradient<Gradient>(unsigned int, unsigned int, Gradient &) const;
    2145             : template LIBMESH_EXPORT void FEMContext::side_gradients<Gradient>(unsigned int, const NumericVector<Number> &,
    2146             :                                                    std::vector<Gradient> &) const;
    2147             : template LIBMESH_EXPORT void FEMContext::side_gradient<Tensor>(unsigned int, unsigned int, Tensor &) const;
    2148             : template LIBMESH_EXPORT void FEMContext::side_gradients<Tensor>(unsigned int, const NumericVector<Number> &,
    2149             :                                                  std::vector<Tensor> &) const;
    2150             : 
    2151             : 
    2152             : #ifdef LIBMESH_ENABLE_SECOND_DERIVATIVES
    2153             : template LIBMESH_EXPORT void FEMContext::side_hessian<Tensor>(unsigned int, unsigned int, Tensor &) const;
    2154             : template LIBMESH_EXPORT void FEMContext::side_hessians<Tensor>(unsigned int, const NumericVector<Number> &,
    2155             :                                                 std::vector<Tensor> &) const;
    2156             : //FIXME: Not everything is implemented yet for second derivatives of RealGradients
    2157             : //template LIBMESH_EXPORT void FEMContext::side_hessian<??>(unsigned int, unsigned int,
    2158             : //                                           ??&) const;
    2159             : //template LIBMESH_EXPORT void FEMContext::side_hessians<??>(unsigned int, const NumericVector<Number> &,
    2160             : //                                            std::vector<??> &) const;
    2161             : #endif
    2162             : 
    2163             : template LIBMESH_EXPORT void FEMContext::point_value<Number>(unsigned int, const Point &, Number &, const Real) const;
    2164             : template LIBMESH_EXPORT void FEMContext::point_value<Gradient>(unsigned int, const Point &, Gradient &, const Real) const;
    2165             : 
    2166             : template LIBMESH_EXPORT void FEMContext::point_gradient<Gradient>(unsigned int, const Point &, Gradient &, const Real) const;
    2167             : template LIBMESH_EXPORT void FEMContext::point_gradient<Tensor>(unsigned int, const Point &, Tensor &, const Real) const;
    2168             : 
    2169             : #ifdef LIBMESH_ENABLE_SECOND_DERIVATIVES
    2170             : template LIBMESH_EXPORT void FEMContext::point_hessian<Tensor>(unsigned int, const Point &, Tensor &, const Real) const;
    2171             : //FIXME: Not everything is implemented yet for second derivatives of RealGradients
    2172             : //template LIBMESH_EXPORT void FEMContext::point_hessian<??>(unsigned int, const Point &, ??&) const;
    2173             : #endif
    2174             : 
    2175             : template LIBMESH_EXPORT void FEMContext::point_curl<Gradient>(unsigned int, const Point &, Gradient &, const Real) const;
    2176             : 
    2177             : template LIBMESH_EXPORT void FEMContext::fixed_interior_value<Number>(unsigned int, unsigned int, Number &) const;
    2178             : template LIBMESH_EXPORT void FEMContext::fixed_interior_value<Gradient>(unsigned int, unsigned int, Gradient &) const;
    2179             : 
    2180             : template LIBMESH_EXPORT void FEMContext::fixed_interior_gradient<Gradient>(unsigned int, unsigned int, Gradient &) const;
    2181             : template LIBMESH_EXPORT void FEMContext::fixed_interior_gradient<Tensor>(unsigned int, unsigned int, Tensor &) const;
    2182             : 
    2183             : #ifdef LIBMESH_ENABLE_SECOND_DERIVATIVES
    2184             : template LIBMESH_EXPORT void FEMContext::fixed_interior_hessian<Tensor>(unsigned int, unsigned int, Tensor &) const;
    2185             : //FIXME: Not everything is implemented yet for second derivatives of RealGradients
    2186             : //template LIBMESH_EXPORT void FEMContext::fixed_interior_hessian<??>(unsigned int, unsigned int, ??&) const;
    2187             : #endif
    2188             : 
    2189             : template LIBMESH_EXPORT void FEMContext::fixed_side_value<Number>(unsigned int, unsigned int, Number &) const;
    2190             : template LIBMESH_EXPORT void FEMContext::fixed_side_value<Gradient>(unsigned int, unsigned int, Gradient &) const;
    2191             : 
    2192             : template LIBMESH_EXPORT void FEMContext::fixed_side_gradient<Gradient>(unsigned int, unsigned int, Gradient &) const;
    2193             : template LIBMESH_EXPORT void FEMContext::fixed_side_gradient<Tensor>(unsigned int, unsigned int, Tensor &) const;
    2194             : 
    2195             : #ifdef LIBMESH_ENABLE_SECOND_DERIVATIVES
    2196             : template LIBMESH_EXPORT void FEMContext::fixed_side_hessian<Tensor>(unsigned int, unsigned int, Tensor &) const;
    2197             : //FIXME: Not everything is implemented yet for second derivatives of RealGradients
    2198             : //template LIBMESH_EXPORT void FEMContext::fixed_side_hessian<??>(unsigned int, unsigned int, ??&) const;
    2199             : #endif
    2200             : 
    2201             : template LIBMESH_EXPORT void FEMContext::fixed_point_value<Number>(unsigned int, const Point &, Number &, const Real) const;
    2202             : template LIBMESH_EXPORT void FEMContext::fixed_point_value<Gradient>(unsigned int, const Point &, Gradient &, const Real) const;
    2203             : 
    2204             : template LIBMESH_EXPORT void FEMContext::fixed_point_gradient<Gradient>(unsigned int, const Point &, Gradient &, const Real) const;
    2205             : template LIBMESH_EXPORT void FEMContext::fixed_point_gradient<Tensor>(unsigned int, const Point &, Tensor &, const Real) const;
    2206             : 
    2207             : #ifdef LIBMESH_ENABLE_SECOND_DERIVATIVES
    2208             : template LIBMESH_EXPORT void FEMContext::fixed_point_hessian<Tensor>(unsigned int, const Point &, Tensor &, const Real) const;
    2209             : //FIXME: Not everything is implemented yet for second derivatives of RealGradients
    2210             : //template LIBMESH_EXPORT void FEMContext::fixed_point_hessian<??>(unsigned int, const Point &, ??&) const;
    2211             : #endif
    2212             : 
    2213             : template LIBMESH_EXPORT void FEMContext::interior_rate<Number>(unsigned int, unsigned int, Number &) const;
    2214             : template LIBMESH_EXPORT void FEMContext::interior_rate<Gradient>(unsigned int, unsigned int, Gradient &) const;
    2215             : 
    2216             : template LIBMESH_EXPORT void FEMContext::interior_rate_gradient<Gradient>(unsigned int, unsigned int, Gradient &) const;
    2217             : template LIBMESH_EXPORT void FEMContext::interior_rate_gradient<Tensor>(unsigned int, unsigned int, Tensor &) const;
    2218             : 
    2219             : template LIBMESH_EXPORT void FEMContext::side_rate<Number>(unsigned int, unsigned int, Number &) const;
    2220             : template LIBMESH_EXPORT void FEMContext::side_rate<Gradient>(unsigned int, unsigned int, Gradient &) const;
    2221             : 
    2222             : template LIBMESH_EXPORT void FEMContext::interior_accel<Number>(unsigned int, unsigned int, Number &) const;
    2223             : template LIBMESH_EXPORT void FEMContext::interior_accel<Gradient>(unsigned int, unsigned int, Gradient &) const;
    2224             : 
    2225             : template LIBMESH_EXPORT void FEMContext::side_accel<Number>(unsigned int, unsigned int, Number &) const;
    2226             : template LIBMESH_EXPORT void FEMContext::side_accel<Gradient>(unsigned int, unsigned int, Gradient &) const;
    2227             : 
    2228             : template LIBMESH_EXPORT FEGenericBase<Real> *
    2229             : FEMContext::build_new_fe(const FEGenericBase<Real>*,
    2230             :                          const Point &,
    2231             :                          const Real,
    2232             :                          const int) const;
    2233             : 
    2234             : template LIBMESH_EXPORT FEGenericBase<RealGradient> *
    2235             : FEMContext::build_new_fe(const FEGenericBase<RealGradient>*,
    2236             :                          const Point &,
    2237             :                          const Real,
    2238             :                          const int) const;
    2239             : 
    2240             : } // namespace libMesh

Generated by: LCOV version 1.14