32 #include "libmesh/string_to_enum.h"    35 #include "libmesh/enum_solver_package.h"    38 #include "libmesh/mesh.h"    39 #include "libmesh/mesh_generation.h"    40 #include "libmesh/mesh_modification.h"    43 #include "libmesh/dense_matrix.h"    44 #include "libmesh/sparse_matrix.h"    45 #include "libmesh/dense_vector.h"    46 #include "libmesh/numeric_vector.h"    49 #include "libmesh/fe.h"    50 #include "libmesh/fe_interface.h"    51 #include "libmesh/elem.h"    54 #include "libmesh/quadrature_gauss.h"    57 #include "libmesh/dof_map.h"    60 #include "libmesh/equation_systems.h"    61 #include "libmesh/linear_implicit_system.h"    64 #include "libmesh/exact_solution.h"    65 #include "libmesh/enum_norm_type.h"    66 #include "solution_function.h"    69 #include "libmesh/getpot.h"    70 #include "libmesh/exodusII_io.h"    72 #ifdef LIBMESH_HAVE_EIGEN_DENSE    74 #include <Eigen/Dense>    77 using namespace Eigen;
    79 #ifdef LIBMESH_USE_COMPLEX_NUMBERS    93 main(
int argc, 
char ** argv)
   100                            "--enable-petsc, --enable-trilinos, or --enable-eigen");
   103   GetPot infile(
"vector_fe_ex8.in");
   106   infile.parse_command_line(argc, argv);
   109   const unsigned int dimension = infile(
"dim", 2);
   110   const unsigned int grid_size = infile(
"grid_size", 15);
   111   const unsigned int order = infile(
"order", 1);
   112   const std::string family_str = infile(
"family", 
"L2_LAGRANGE");
   113   const FEFamily family = Utility::string_to_enum<FEFamily>(family_str);
   114   const std::string vec_family_str = infile(
"vecfamily", 
"L2_LAGRANGE_VEC");
   115   const FEFamily vec_family = Utility::string_to_enum<FEFamily>(vec_family_str);
   118   libmesh_example_requires(dimension <= LIBMESH_DIM, dimension << 
"D support");
   127   const std::string elem_str = infile(
"element_type", std::string(
"TRI6"));
   129   libmesh_error_msg_if((dimension == 2 && elem_str != 
"TRI6" && elem_str != 
"TRI7" &&
   130                         elem_str != 
"QUAD8" && elem_str != 
"QUAD9") ||
   131                            (dimension == 3 && elem_str != 
"TET14" && elem_str != 
"HEX27"),
   134                            << 
" but this example must be run with TRI6, TRI7, QUAD8, or QUAD9 in 2d"   135                            << 
" or with TET14, or HEX27 in 3d.");
   139         mesh, grid_size, grid_size, -1., 1., -1., 1., Utility::string_to_enum<ElemType>(elem_str));
   140   else if (dimension == 3)
   151                                       Utility::string_to_enum<ElemType>(elem_str));
   167   system.
add_variable(
"q", static_cast<Order>(order), vec_family);
   168   system.add_variable(
"u", static_cast<Order>(order), family);
   173   system.add_variable(
"u_enriched", static_cast<Order>(order+1), family);
   183   equation_systems.
init();
   203     std::vector<FunctionBase<Number> *> sols(1, &soln_func);
   204     std::vector<FunctionBase<Gradient> *> grads(1, &soln_grad);
   209   else if (dimension == 3)
   215     std::vector<FunctionBase<Number> *> sols(1, &soln_func);
   216     std::vector<FunctionBase<Gradient> *> grads(1, &soln_grad);
   223   int extra_error_quadrature = infile(
"extra_error_quadrature", 2);
   224   if (extra_error_quadrature)
   238 #ifdef LIBMESH_HAVE_EXODUS_API   243 #endif // #ifdef LIBMESH_HAVE_EXODUS_API   269 template <
typename SolnType, 
typename PhiType, 
typename LocalSolutionVector>
   272                 const unsigned int n_qps,
   273                 const std::vector<std::vector<PhiType>> & phi,
   274                 const LocalSolutionVector & soln)
   277   qp_vec.resize(n_qps);
   278   for (
auto & val : qp_vec)
   282     const auto & qp_phis = phi[i];
   284     const auto sol = soln(i);
   286       qp_vec[qp] += qp_phis[qp] * sol;
   294                       const Elem * 
const elem,
   309   const FEType enriched_scalar_fe_type =
   311   std::unique_ptr<FEBase> enriched_scalar_fe(
FEBase::build(
dim, enriched_scalar_fe_type));
   312   std::unique_ptr<FEBase> enriched_scalar_fe_face(
FEBase::build(
dim, enriched_scalar_fe_type));
   315   enriched_scalar_fe->attach_quadrature_rule(&qrule);
   316   enriched_scalar_fe_face->attach_quadrature_rule(&qface);
   319   const auto & JxW = vector_fe.
get_JxW();
   320   const auto & q_point = vector_fe.
get_xyz();
   321   const auto & scalar_phi = scalar_fe.
get_phi();
   322   const auto & enriched_scalar_phi = enriched_scalar_fe->get_phi();
   323   const auto & enriched_scalar_dphi = enriched_scalar_fe->get_dphi();
   326   const auto & vector_phi_face = vector_fe_face.
get_phi();
   327   const auto & scalar_phi_face = scalar_fe_face.
get_phi();
   328   const auto & enriched_scalar_phi_face = enriched_scalar_fe_face->get_phi();
   329   const auto & lambda_phi_face = lambda_fe_face.
get_phi();
   330   const auto & JxW_face = scalar_fe_face.
get_JxW();
   331   const auto & normals = vector_fe_face.
get_normals();
   336   std::vector<dof_id_type> enriched_scalar_dof_indices;
   339   std::vector<Number> lambda_qps;
   341   std::vector<Number> scalar_qps;
   343   std::vector<Gradient> vector_qps;
   346   const auto enriched_scalar_n_dofs = enriched_scalar_dof_indices.size();
   348   const auto m = enriched_scalar_n_dofs + 1;
   349   const auto n = enriched_scalar_n_dofs + 1;
   351   K_enriched_scalar.
resize(m, n);
   352   F_enriched_scalar.
resize(m);
   353   U_enriched_scalar.
resize(n);
   355   enriched_scalar_fe->reinit(elem);
   367     for (
const auto i : 
make_range(enriched_scalar_n_dofs))
   368       for (
const auto j : 
make_range(enriched_scalar_n_dofs))
   369         K_enriched_scalar(i, j) +=
   370             JxW[qp] * (enriched_scalar_dphi[i][qp] * enriched_scalar_dphi[j][qp]);
   374       const Real x = q_point[qp](0);
   375       const Real y = q_point[qp](1);
   376       const Real z = q_point[qp](2);
   388       for (
const auto i : 
make_range(enriched_scalar_n_dofs))
   389         F_enriched_scalar(i) += JxW[qp] * enriched_scalar_phi[i][qp] * f;
   395       for (
const auto i : 
make_range(enriched_scalar_n_dofs))
   396         K_enriched_scalar(i, enriched_scalar_n_dofs) += JxW[qp] * enriched_scalar_phi[i][qp];
   399       for (
const auto j : 
make_range(enriched_scalar_n_dofs))
   400         K_enriched_scalar(enriched_scalar_n_dofs, j) += JxW[qp] * enriched_scalar_phi[j][qp];
   403       F_enriched_scalar(enriched_scalar_n_dofs) += JxW[qp] * scalar_qps[qp];
   407   bool tau_found = 
false;
   411     vector_fe_face.
reinit(elem, side);
   414     enriched_scalar_fe_face->reinit(elem, side);
   423         for (
const auto i : 
make_range(enriched_scalar_n_dofs))
   424           F_enriched_scalar(i) -=
   425               JxW_face[qp] * enriched_scalar_phi_face[i][qp] * vector_qps[qp] * normals[qp];
   428       scalar_fe_face.
reinit(elem, side);
   430       lambda_fe_face.
reinit(elem, side);
   435       const Real tau = tau_found ? 0 : 1 / elem->
hmin();
   440         const auto normal = normals[qp];
   441         const auto qhat = vector_qps[qp] + tau * (scalar_qps[qp] - lambda_qps[qp]) * normal;
   444         for (
const auto i : 
make_range(enriched_scalar_n_dofs))
   445           F_enriched_scalar(i) -= JxW_face[qp] * enriched_scalar_phi_face[i][qp] * qhat * normal;
   450   K_enriched_scalar.
lu_solve(F_enriched_scalar, U_enriched_scalar);
   455   for (
const auto i : 
make_range(enriched_scalar_n_dofs))
   456     U_insertion(i) = U_enriched_scalar(i);
   457   system.
solution->insert(U_insertion, enriched_scalar_dof_indices);
   475   const auto & lambda_dof_map = lambda_system.
get_dof_map();
   479   const FEType lambda_fe_type =
   490   vector_fe->attach_quadrature_rule(&qrule);
   491   scalar_fe->attach_quadrature_rule(&qrule);
   503   vector_fe_face->attach_quadrature_rule(&qface);
   504   scalar_fe_face->attach_quadrature_rule(&qface);
   505   lambda_fe_face->attach_quadrature_rule(&qface);
   508   const auto & JxW = vector_fe->get_JxW();
   509   const auto & q_point = vector_fe->get_xyz();
   510   const auto & vector_phi = vector_fe->get_phi();
   511   const auto & scalar_phi = scalar_fe->get_phi();
   512   const auto & grad_scalar_phi = scalar_fe->get_dphi();
   513   const auto & div_vector_phi = vector_fe->get_div_phi();
   516   const auto & vector_phi_face = vector_fe_face->get_phi();
   517   const auto & scalar_phi_face = scalar_fe_face->get_phi();
   518   const auto & lambda_phi_face = lambda_fe_face->get_phi();
   519   const auto & JxW_face = scalar_fe_face->get_JxW();
   520   const auto & qface_point = vector_fe_face->get_xyz();
   521   const auto & normals = vector_fe_face->get_normals();
   538   EigenMatrix A, Ainv, 
B, Bt, C, Ct, Sinv, D, E, Et, H;
   545   std::vector<dof_id_type> vector_dof_indices;
   546   std::vector<dof_id_type> scalar_dof_indices;
   547   std::vector<dof_id_type> lambda_dof_indices;
   548   std::vector<Number> lambda_solution_std_vec;
   553   for (
const auto & elem : 
mesh.active_local_element_ptr_range())
   556     dof_map.dof_indices(elem, vector_dof_indices, system.variable_number(
"q"));
   557     dof_map.dof_indices(elem, scalar_dof_indices, system.variable_number(
"u"));
   558     lambda_dof_map.dof_indices(elem, lambda_dof_indices, lambda_system.
variable_number(
"lambda"));
   560     const auto vector_n_dofs = vector_dof_indices.size();
   561     const auto scalar_n_dofs = scalar_dof_indices.size();
   562     const auto lambda_n_dofs = lambda_dof_indices.size();
   566     scalar_fe->reinit(elem);
   568     libmesh_assert_equal_to(vector_n_dofs, vector_phi.size());
   569     libmesh_assert_equal_to(scalar_n_dofs, scalar_phi.size());
   572     A.setZero(vector_n_dofs, vector_n_dofs);
   573     B.setZero(vector_n_dofs, scalar_n_dofs);
   574     C.setZero(vector_n_dofs, lambda_n_dofs);
   575     G.setZero(vector_n_dofs);
   577     Bt.setZero(scalar_n_dofs, vector_n_dofs);
   578     D.setZero(scalar_n_dofs, scalar_n_dofs);
   579     E.setZero(scalar_n_dofs, lambda_n_dofs);
   580     F.setZero(scalar_n_dofs);
   582     Ct.setZero(lambda_n_dofs, vector_n_dofs);
   583     Et.setZero(lambda_n_dofs, scalar_n_dofs);
   584     H.setZero(lambda_n_dofs, lambda_n_dofs);
   586     for (
const auto qp : 
make_range(qrule.n_points()))
   589       for (
const auto i : 
make_range(vector_n_dofs))
   590         for (
const auto j : 
make_range(vector_n_dofs))
   591           A(i, j) -= JxW[qp] * (vector_phi[i][qp] * vector_phi[j][qp]);
   594       for (
const auto i : 
make_range(vector_n_dofs))
   595         for (
const auto j : 
make_range(scalar_n_dofs))
   596           B(i, j) += JxW[qp] * (div_vector_phi[i][qp] * scalar_phi[j][qp]);
   599       for (
const auto i : 
make_range(scalar_n_dofs))
   600         for (
const auto j : 
make_range(vector_n_dofs))
   601           Bt(i, j) += JxW[qp] * (grad_scalar_phi[i][qp] * vector_phi[j][qp]);
   608         const Real x = q_point[qp](0);
   609         const Real y = q_point[qp](1);
   610         const Real z = q_point[qp](2);
   622         for (
const auto i : 
make_range(scalar_n_dofs))
   623           F(i) -= JxW[qp] * scalar_phi[i][qp] * f;
   628     bool tau_found = 
false;
   629     for (
auto side : elem->side_index_range())
   632       vector_fe_face->reinit(elem, side);
   633       scalar_fe_face->reinit(elem, side);
   634       lambda_fe_face->reinit(elem, side);
   636       if (elem->neighbor_ptr(side) == 
nullptr)
   637         for (
const auto qp : 
make_range(qface.n_points()))
   639           const Real xf = qface_point[qp](0);
   640           const Real yf = qface_point[qp](1);
   641           const Real zf = qface_point[qp](2);
   644           Real scalar_value = 0;
   651           for (
const auto i : 
make_range(vector_n_dofs))
   652             G(i) += JxW_face[qp] * (vector_phi_face[i][qp] * normals[qp]) * scalar_value;
   659           for (
const auto i : 
make_range(scalar_n_dofs))
   660             for (
const auto j : 
make_range(vector_n_dofs))
   662                   JxW_face[qp] * scalar_phi_face[i][qp] * (vector_phi_face[j][qp] * normals[qp]);
   667           for (
const auto i : 
make_range(lambda_n_dofs))
   668             for (
const auto j : 
make_range(lambda_n_dofs))
   669               H(i, j) += JxW_face[qp] * lambda_phi_face[i][qp] * lambda_phi_face[j][qp];
   676         const Real tau = tau_found ? 0 : 1 / elem->hmin();
   679         for (
const auto qp : 
make_range(qface.n_points()))
   681           const auto normal = normals[qp];
   682           const auto normal_sq = normal * normal;
   685           for (
const auto i : 
make_range(vector_n_dofs))
   686             for (
const auto j : 
make_range(lambda_n_dofs))
   688                   JxW_face[qp] * (vector_phi_face[i][qp] * normals[qp]) * lambda_phi_face[j][qp];
   693           for (
const auto i : 
make_range(scalar_n_dofs))
   695             for (
const auto j : 
make_range(vector_n_dofs))
   696               Bt(i, j) -= JxW_face[qp] * scalar_phi_face[i][qp] * (vector_phi_face[j][qp] * normal);
   698             for (
const auto j : 
make_range(scalar_n_dofs))
   700                   JxW_face[qp] * scalar_phi_face[i][qp] * tau * scalar_phi_face[j][qp] * normal_sq;
   702             for (
const auto j : 
make_range(lambda_n_dofs))
   704                   JxW_face[qp] * scalar_phi_face[i][qp] * tau * lambda_phi_face[j][qp] * normal_sq;
   710           for (
const auto i : 
make_range(lambda_n_dofs))
   712             for (
const auto j : 
make_range(vector_n_dofs))
   713               Ct(i, j) -= JxW_face[qp] * lambda_phi_face[i][qp] * (vector_phi_face[j][qp] * normal);
   715             for (
const auto j : 
make_range(scalar_n_dofs))
   717                   JxW_face[qp] * lambda_phi_face[i][qp] * tau * scalar_phi_face[j][qp] * normal_sq;
   719             for (
const auto j : 
make_range(lambda_n_dofs))
   721                   JxW_face[qp] * lambda_phi_face[i][qp] * tau * lambda_phi_face[j][qp] * normal_sq;
   729     Sinv = (D - Bt * Ainv * 
B).inverse();
   730     const auto BtAinvCMinusE = Bt * Ainv * C - E;
   731     const auto BtAinvGMinusF = Bt * Ainv * G - F;
   732     const auto CtAinv = Ct * Ainv;
   733     const auto BSinv = 
B * Sinv;
   734     const auto EtSinv = Et * Sinv;
   735     K = -CtAinv * (BSinv * BtAinvCMinusE + C) + EtSinv * BtAinvCMinusE + H;
   736     P = -CtAinv * (BSinv * BtAinvGMinusF + G) + EtSinv * BtAinvGMinusF;
   739     K_libmesh.
resize(K.rows(), K.cols());
   740     P_libmesh.
resize(P.size());
   746         K_libmesh(i, j) = K(i, j);
   753       dof_map.constrain_element_matrix_and_vector(K_libmesh, P_libmesh, lambda_dof_indices);
   754       matrix.
add_matrix(K_libmesh, lambda_dof_indices);
   755       lambda_system.rhs->
add_vector(P_libmesh, lambda_dof_indices);
   765       Lambda.resize(lambda_n_dofs);
   767       for (
const auto i : 
make_range(lambda_n_dofs))
   768         Lambda(i) = lambda_solution_std_vec[i];
   769       const auto scalar_soln = Sinv * (BtAinvCMinusE * Lambda - BtAinvGMinusF);
   770       const auto vector_soln = Ainv * (G - 
B * scalar_soln - C * Lambda);
   771       for (
const auto i : 
make_range(vector_n_dofs))
   772         system.solution->set(vector_dof_indices[i], vector_soln(i));
   773       for (
const auto i : 
make_range(scalar_n_dofs))
   774         system.solution->set(scalar_dof_indices[i], scalar_soln(i));
   797     system.solution->close();
   807   libmesh_assert_equal_to(system_name, 
"Lambda");
   825     return 1 / elem->
hmin();
   844   const auto & lambda_dof_map = lambda_system.
get_dof_map();
   848   const FEType lambda_fe_type =
   859   vector_fe->attach_quadrature_rule(&qrule);
   860   scalar_fe->attach_quadrature_rule(&qrule);
   872   vector_fe_face->attach_quadrature_rule(&qface);
   873   scalar_fe_face->attach_quadrature_rule(&qface);
   874   lambda_fe_face->attach_quadrature_rule(&qface);
   877   const auto & JxW = vector_fe->get_JxW();
   878   const auto & q_point = vector_fe->get_xyz();
   879   const auto & vector_phi = vector_fe->get_phi();
   880   const auto & scalar_phi = scalar_fe->get_phi();
   881   const auto & grad_scalar_phi = scalar_fe->get_dphi();
   882   const auto & div_vector_phi = vector_fe->get_div_phi();
   885   const auto & vector_phi_face = vector_fe_face->get_phi();
   886   const auto & scalar_phi_face = scalar_fe_face->get_phi();
   887   const auto & lambda_phi_face = lambda_fe_face->get_phi();
   888   const auto & JxW_face = scalar_fe_face->get_JxW();
   889   const auto & qface_point = vector_fe_face->get_xyz();
   890   const auto & normals = vector_fe_face->get_normals();
   908   std::vector<dof_id_type> vector_dof_indices;
   909   std::vector<dof_id_type> scalar_dof_indices;
   910   std::vector<dof_id_type> lambda_dof_indices;
   911   std::vector<Number> lambda_solution_std_vec;
   915   std::vector<Number> mu;
   918   auto & matrix = lambda_system.get_system_matrix();
   920   auto compute_and_invert_K =
   921       [&](
const auto vector_n_dofs_in, 
const auto scalar_n_dofs_in, 
const Elem * 
const elem_in)
   923     const auto mixed_size = vector_n_dofs_in + scalar_n_dofs_in;
   925     K_mixed.setZero(mixed_size, mixed_size);
   927     for (
const auto qp : 
make_range(qrule.n_points()))
   930       for (
const auto i : 
make_range(vector_n_dofs_in))
   931         for (
const auto j : 
make_range(vector_n_dofs_in))
   932           K_mixed(i, j) += JxW[qp] * (vector_phi[i][qp] * vector_phi[j][qp]);
   935       for (
const auto i : 
make_range(vector_n_dofs_in))
   936         for (
const auto j : 
make_range(scalar_n_dofs_in))
   937           K_mixed(i, j + vector_n_dofs_in) -= JxW[qp] * (div_vector_phi[i][qp] * scalar_phi[j][qp]);
   940       for (
const auto i : 
make_range(scalar_n_dofs_in))
   941         for (
const auto j : 
make_range(vector_n_dofs_in))
   942           K_mixed(i + vector_n_dofs_in, j) -= JxW[qp] * (grad_scalar_phi[i][qp] * vector_phi[j][qp]);
   946     bool tau_found = 
false;
   947     for (
auto side : elem_in->side_index_range())
   950       vector_fe_face->
reinit(elem_in, side);
   951       scalar_fe_face->reinit(elem_in, side);
   952       const bool internal_face = elem_in->neighbor_ptr(side);
   953       const auto tau = 
compute_tau(internal_face, tau_found, elem_in);
   955       for (
const auto qp : 
make_range(qface.n_points()))
   957         const auto normal = normals[qp];
   958         const auto normal_sq = normal * normal;
   963         for (
const auto i : 
make_range(scalar_n_dofs_in))
   965           for (
const auto j : 
make_range(vector_n_dofs_in))
   966             K_mixed(i + vector_n_dofs_in, j) +=
   967                 JxW_face[qp] * scalar_phi_face[i][qp] * (vector_phi_face[j][qp] * normal);
   970             for (
const auto j : 
make_range(scalar_n_dofs_in))
   971               K_mixed(i + vector_n_dofs_in, j + vector_n_dofs_in) +=
   972                   JxW_face[qp] * scalar_phi_face[i][qp] * tau * scalar_phi_face[j][qp] * normal_sq;
   977     Kinv_mixed = K_mixed.inverse();
   980   auto compute_rhs = [&](
const auto vector_n_dofs_in,
   981                          const auto scalar_n_dofs_in,
   982                          const Elem * 
const elem_in,
   983                          const unsigned int shape_function)
   985     const auto mixed_size = vector_n_dofs_in + scalar_n_dofs_in;
   986     F_mixed.setZero(mixed_size);
   992       for (
const auto qp : 
make_range(qrule.n_points()))
   994         const Real x = q_point[qp](0);
   995         const Real y = q_point[qp](1);
   996         const Real z = q_point[qp](2);
  1003         for (
const auto ii : 
make_range(scalar_n_dofs_in))
  1004           F_mixed(ii + vector_n_dofs_in) += JxW[qp] * f * scalar_phi[ii][qp];
  1008     bool tau_found = 
false;
  1009     std::vector<Number> g;
  1011     for (
auto side : elem_in->side_index_range())
  1014       vector_fe_face->reinit(elem_in, side);
  1015       scalar_fe_face->reinit(elem_in, side);
  1016       lambda_fe_face->reinit(elem_in, side);
  1018       const auto & qp_mu = [&]()
  1022           if (elem_in->neighbor_ptr(side))
  1024             compute_qp_soln(lambda_solution_std_vec, qface.n_points(), lambda_phi_face, Lambda);
  1025             return lambda_solution_std_vec;
  1029             g.resize(qface.n_points());
  1030             for (
const auto qp : 
make_range(qface.n_points()))
  1032               auto & g_qp = g[qp];
  1033               const Real xf = qface_point[qp](0);
  1034               const Real yf = qface_point[qp](1);
  1035               const Real zf = qface_point[qp](2);
  1048           auto & real_mu = lambda_phi_face[shape_function];
  1049           mu.resize(qface.n_points());
  1050           for (
const auto qp : 
make_range(qface.n_points()))
  1051             mu[qp] = real_mu[qp];
  1056       const bool internal_face = elem_in->neighbor_ptr(side);
  1057       const auto tau = 
compute_tau(internal_face, tau_found, elem_in);
  1059       for (
const auto qp : 
make_range(qface.n_points()))
  1061         const auto normal = normals[qp];
  1062         const auto normal_sq = normal * normal;
  1065         for (
const auto ii : 
make_range(vector_n_dofs_in))
  1066           F_mixed(ii) -= JxW_face[qp] * (vector_phi_face[ii][qp] * normal) * qp_mu[qp];
  1071         for (
const auto ii : 
make_range(scalar_n_dofs_in))
  1072           F_mixed(ii + vector_n_dofs_in) +=
  1073               JxW_face[qp] * scalar_phi_face[ii][qp] * tau * qp_mu[qp] * normal_sq;
  1078   for (
const auto & elem : 
mesh.active_local_element_ptr_range())
  1080     std::vector<EigenVector> local_solns;
  1081     std::vector<unsigned int> dofs_on_side;
  1082     std::unordered_set<unsigned int> external_boundary_indices;
  1083     std::vector<std::vector<Gradient>> volumetric_q;
  1084     std::vector<std::vector<Number>> volumetric_u;
  1085     std::vector<std::vector<Gradient>> face_q;
  1088     dof_map.dof_indices(elem, vector_dof_indices, system.variable_number(
"q"));
  1089     dof_map.dof_indices(elem, scalar_dof_indices, system.variable_number(
"u"));
  1090     lambda_dof_map.dof_indices(elem, lambda_dof_indices, lambda_system.
variable_number(
"lambda"));
  1092     const auto vector_n_dofs = vector_dof_indices.size();
  1093     const auto scalar_n_dofs = scalar_dof_indices.size();
  1094     const auto lambda_n_dofs = lambda_dof_indices.size();
  1095     const std::size_t n_mu_funcs = global_solve ? lambda_n_dofs : 1;
  1099       K_lm_libmesh.
resize(lambda_n_dofs, lambda_n_dofs);
  1100       F_lm_libmesh.
resize(lambda_n_dofs);
  1102       for (
const auto s : elem->side_index_range())
  1103         if (!elem->neighbor_ptr(s))
  1106           external_boundary_indices.insert(dofs_on_side.begin(), dofs_on_side.end());
  1111     vector_fe->reinit(elem);
  1112     scalar_fe->reinit(elem);
  1114     libmesh_assert_equal_to(vector_n_dofs, vector_phi.size());
  1115     libmesh_assert_equal_to(scalar_n_dofs, scalar_phi.size());
  1117     compute_and_invert_K(vector_n_dofs, scalar_n_dofs, elem);
  1118     local_solns.resize(n_mu_funcs);
  1122       volumetric_q.resize(lambda_n_dofs);
  1123       volumetric_u.resize(lambda_n_dofs);
  1124       face_q.resize(lambda_n_dofs);
  1126       for (
const auto i : 
make_range(lambda_n_dofs))
  1128         if (external_boundary_indices.count(i))
  1131         compute_rhs(vector_n_dofs, scalar_n_dofs, elem, i);
  1132         auto & local_soln = local_solns[i];
  1133         local_soln = Kinv_mixed * F_mixed;
  1134         const auto local_q_soln = local_soln.head(vector_n_dofs);
  1135         const auto local_u_soln = local_soln.tail(scalar_n_dofs);
  1136         compute_qp_soln(volumetric_q[i], qrule.n_points(), vector_phi, local_q_soln);
  1137         compute_qp_soln(volumetric_u[i], qrule.n_points(), scalar_phi, local_u_soln);
  1141       for (
const auto i : 
make_range(lambda_n_dofs))
  1142         if (!external_boundary_indices.count(i))
  1143           for (
const auto j : 
make_range(lambda_n_dofs))
  1144             if (!external_boundary_indices.count(j))
  1145               for (
const auto qp : 
make_range(qrule.n_points()))
  1146                 K_lm_libmesh(i, j) += JxW[qp] * volumetric_q[i][qp] * volumetric_q[j][qp];
  1149       for (
const auto qp : 
make_range(qrule.n_points()))
  1151         const Real x = q_point[qp](0);
  1152         const Real y = q_point[qp](1);
  1153         const Real z = q_point[qp](2);
  1163         for (
const auto i : 
make_range(lambda_n_dofs))
  1164           if (!external_boundary_indices.count(i))
  1165             F_lm_libmesh(i) += JxW[qp] * f * volumetric_u[i][qp];
  1169       for (
const auto s : elem->side_index_range())
  1171         lambda_fe_face->reinit(elem, s);
  1172         for (
const auto i : 
make_range(lambda_n_dofs))
  1173           if (external_boundary_indices.count(i))
  1174             for (
const auto j : 
make_range(lambda_n_dofs))
  1175               if (external_boundary_indices.count(j))
  1176                 for (
const auto qp : 
make_range(qface.n_points()))
  1177                   K_lm_libmesh(i, j) +=
  1178                       JxW_face[qp] * lambda_phi_face[i][qp] * lambda_phi_face[j][qp];
  1180         if (!elem->neighbor_ptr(s))
  1182           vector_fe_face->reinit(elem, s);
  1183           for (
const auto i : 
make_range(lambda_n_dofs))
  1185             if (external_boundary_indices.count(i))
  1188             const auto local_q_soln = local_solns[i].head(vector_n_dofs);
  1189             compute_qp_soln(face_q[i], qface.n_points(), vector_phi_face, local_q_soln);
  1192           for (
const auto qp : 
make_range(qface.n_points()))
  1194             const Real xf = qface_point[qp](0);
  1195             const Real yf = qface_point[qp](1);
  1196             const Real zf = qface_point[qp](2);
  1199             Real scalar_value = 0;
  1204             for (
const auto i : 
make_range(lambda_n_dofs))
  1205               if (!external_boundary_indices.count(i))
  1206                 F_lm_libmesh(i) += JxW_face[qp] * scalar_value * face_q[i][qp] * normals[qp];
  1213       dof_map.constrain_element_matrix_and_vector(K_lm_libmesh, F_lm_libmesh, lambda_dof_indices);
  1214       matrix.
add_matrix(K_lm_libmesh, lambda_dof_indices);
  1215       lambda_system.rhs->
add_vector(F_lm_libmesh, lambda_dof_indices);
  1220       Lambda.resize(lambda_n_dofs);
  1222       for (
const auto i : 
make_range(lambda_n_dofs))
  1223         Lambda(i) = lambda_solution_std_vec[i];
  1226       auto & local_soln = local_solns[0];
  1227       local_soln = Kinv_mixed * F_mixed;
  1228       const auto vector_soln = local_soln.head(vector_n_dofs);
  1229       const auto scalar_soln = local_soln.tail(scalar_n_dofs);
  1230       for (
const auto i : 
make_range(vector_n_dofs))
  1231         system.solution->set(vector_dof_indices[i], vector_soln(i));
  1232       for (
const auto i : 
make_range(scalar_n_dofs))
  1233         system.solution->set(scalar_dof_indices[i], scalar_soln(i));
  1256     system.solution->close();
  1266   libmesh_assert_equal_to(system_name, 
"Lambda");
 class FEType hides (possibly multiple) FEFamily and approximation orders, thereby enabling specialize...
Eigen::Matrix< Number, Eigen::Dynamic, Eigen::Dynamic > EigenMatrix
This class handles the computation of the L2 and/or H1 error for the Systems in the EquationSystems o...
This is the EquationSystems class. 
const unsigned int invalid_uint
A number which is used quite often to represent an invalid or uninitialized value for an unsigned int...
IntRange< unsigned short > side_index_range() const
void dof_indices(const Elem *const elem, std::vector< dof_id_type > &di) const
virtual void reinit()
Reinitializes degrees of freedom and other required data on the current mesh. 
Real compute_tau(const bool internal_face, bool &tau_found, const Elem *const elem)
The ExodusII_IO class implements reading meshes in the ExodusII file format from Sandia National Labs...
void attach_exact_values(const std::vector< FunctionBase< Number > *> &f)
Clone and attach arbitrary functors which compute the exact values of the EquationSystems' solutions ...
Manages consistently variables, degrees of freedom, coefficient vectors, matrices and linear solvers ...
Eigen::Matrix< Number, Eigen::Dynamic, 1 > EigenVector
void resize(const unsigned int n)
Resize the vector. 
void fe_assembly(EquationSystems &es, bool global_solve)
This is the base class from which all geometric element types are derived. 
void extra_quadrature_order(const int extraorder)
Increases or decreases the order of the quadrature rule used for numerical integration. 
Real scalar(Real x, Real y)
Order default_quadrature_order() const
NumericVector< Number > & add_vector(std::string_view vec_name, const bool projections=true, const ParallelType type=PARALLEL)
Adds the additional vector vec_name to this system. 
virtual void reinit() override
Reinitializes the member data fields associated with the system, so that, e.g., assemble() may be use...
The LibMeshInit class, when constructed, initializes the dependent libraries (e.g. 
The libMesh namespace provides an interface to certain functionality in the library. 
void attach_exact_derivs(const std::vector< FunctionBase< Gradient > *> &g)
Clone and attach arbitrary functors which compute the exact gradients of the EquationSystems' solutio...
const T_sys & get_system(std::string_view name) const
This is the MeshBase class. 
unsigned int variable_number(std::string_view var) const
SolverPackage default_solver_package()
This class handles the numbering of degrees of freedom on a mesh. 
virtual void add_matrix(const DenseMatrix< T > &dm, const std::vector< numeric_index_type > &rows, const std::vector< numeric_index_type > &cols)=0
Add the full matrix dm to the SparseMatrix. 
virtual Real hmin() const
virtual void write_equation_systems(const std::string &fname, const EquationSystems &es, const std::set< std::string > *system_names=nullptr) override
Writes out the solution for no specific time or timestep. 
Manages consistently variables, degrees of freedom, and coefficient vectors. 
void compute_error(std::string_view sys_name, std::string_view unknown_name)
Computes and stores the error in the solution value e = u-u_h, the gradient grad(e) = grad(u) - grad(...
std::unique_ptr< NumericVector< Number > > solution
Data structure to hold solution values. 
void init(triangulateio &t)
Initializes the fields of t to nullptr/0 as necessary. 
static std::unique_ptr< FEGenericBase > build(const unsigned int dim, const FEType &type)
Builds a specific finite element type. 
void compute_enriched_soln(const MeshBase &mesh, const DofMap &dof_map, System &system, const Elem *const elem, const EigenVector &vector_soln, const EigenVector &scalar_soln, const EigenVector &Lambda, FEVectorBase &vector_fe, FEVectorBase &vector_fe_face, FEBase &scalar_fe, FEBase &scalar_fe_face, FEBase &lambda_fe_face, QBase &qrule, QBase &qface)
const FEType & variable_type(const unsigned int i) const
virtual_for_inffe const std::vector< Real > & get_JxW() const
virtual void reinit(const Elem *elem, const std::vector< Point > *const pts=nullptr, const std::vector< Real > *const weights=nullptr)=0
This is at the core of this class. 
unsigned int add_variable(std::string_view var, const FEType &type, const std::set< subdomain_id_type > *const active_subdomains=nullptr)
Adds the variable var to the list of variables for this system. 
unsigned int n_points() const
virtual_for_inffe const std::vector< Point > & get_xyz() const
void attach_assemble_function(void fptr(EquationSystems &es, const std::string &name))
Register a user function to use in assembling the system matrix and RHS. 
Real l2_error(std::string_view sys_name, std::string_view unknown_name)
virtual void solve()
Solves the system. 
int main(int argc, char **argv)
const Elem * neighbor_ptr(unsigned int i) const
void lu_solve(const DenseVector< T > &b, DenseVector< T > &x)
Solve the system Ax=b given the input vector b. 
Real forcing(Real x, Real y)
const FEType & variable_type(const unsigned int i) const
DIE A HORRIBLE DEATH HERE typedef LIBMESH_DEFAULT_SCALAR_TYPE Real
void assemble_hdg(EquationSystems &es, const std::string &system_name)
virtual_for_inffe const std::vector< Point > & get_normals() const
void alternative_assemble_hdg(EquationSystems &es, const std::string &system_name)
const MeshBase & get_mesh() const
void resize(const unsigned int new_m, const unsigned int new_n)
Resizes the matrix to the specified size and calls zero(). 
IntRange< T > make_range(T beg, T end)
The 2-parameter make_range() helper function returns an IntRange<T> when both input parameters are of...
This class implements specific orders of Gauss quadrature. 
unsigned int mesh_dimension() const
std::unique_ptr< NumericVector< Number > > current_local_solution
All the values I need to compute my contribution to the simulation at hand. 
void compute_qp_soln(std::vector< SolnType > &qp_vec, const unsigned int n_qps, const std::vector< std::vector< PhiType >> &phi, const std::vector< Number > &dof_values)
virtual void init()
Initialize all the systems. 
FEFamily
defines an enum for finite element families. 
void alternative_fe_assembly(EquationSystems &es, bool global_solve)
virtual System & add_system(std::string_view system_type, std::string_view name)
Add the system of type system_type named name to the systems array. 
The Mesh class is a thin wrapper, around the ReplicatedMesh class by default. 
SparseMatrix< Number > & add_matrix(std::string_view mat_name, ParallelType type=PARALLEL, MatrixBuildType mat_build_type=MatrixBuildType::AUTOMATIC)
Adds the additional matrix mat_name to this system. 
const DofMap & get_dof_map() const
static void dofs_on_side(const Elem *const elem, const unsigned int dim, const FEType &fe_t, unsigned int s, std::vector< unsigned int > &di, const bool add_p_level=true)
Fills the vector di with the local degree of freedom indices associated with side s of element elem A...
The QBase class provides the basic functionality from which various quadrature rules can be derived...
auto index_range(const T &sizable)
Helper function that returns an IntRange<std::size_t> representing all the indices of the passed-in v...
This class forms the foundation from which generic finite elements may be derived. 
const std::vector< std::vector< OutputShape > > & get_phi() const