20 #ifndef GENERIC_PROJECTOR_H 21 #define GENERIC_PROJECTOR_H 52 template <
typename FFunctor,
typename GFunctor,
53 typename FValue,
typename ProjectionAction>
69 const FFunctor & f_in,
70 const GFunctor * g_in,
71 const ProjectionAction & act_in,
72 const std::vector<unsigned int> & variables_in) :
109 template <
typename Val>
120 unsigned int var_num,
127 const std::vector<dof_id_type> & dof_indices =
130 unsigned int size = Ue.
size();
132 libmesh_assert_equal_to(size, dof_indices.size());
138 for (
unsigned int i = 0; i != size; ++i)
139 if ((dof_indices[i] >= first) && (dof_indices[i] < last))
154 template <
typename Output>
161 _f(fw.
_f->clone()) {}
170 {
return _f->component(c, i, n, time); }
176 {
return _f->component(c, i, n, time); }
182 std::vector<Output> )
186 std::unique_ptr<FEMFunctionBase<Output>>
_f;
200 #ifdef LIBMESH_ENABLE_AMR 201 template <
typename Output,
202 void (
FEMContext::*point_output) (
unsigned int,
218 const unsigned int vcomp = sys.variable_scalar_number(v,0);
219 if (vcomp >= component_to_var.size())
220 component_to_var.resize(vcomp+1, static_cast<unsigned int>(-1));
221 component_to_var[vcomp] = v;
229 component_to_var(in.component_to_var)
233 static void get_shape_outputs(
FEBase & fe);
242 for (
unsigned int var=0; var!=sys.n_vars(); ++var)
245 const std::set<unsigned char> & elem_dims =
246 old_context.elem_dimensions();
248 for (
const auto & dim : elem_dims)
250 old_context.get_element_fe(var, fe, dim);
251 get_shape_outputs(*fe);
261 LOG_SCOPE (
"check_old_context(c)",
"OldSolutionBase");
263 if (last_elem != &elem)
267 old_context.pre_fe_reinit(sys, elem.
parent());
280 old_context.pre_fe_reinit(sys, &elem);
287 libmesh_assert(old_context.has_elem());
294 LOG_SCOPE (
"check_old_context(c,p)",
"OldSolutionBase");
296 if (last_elem != &elem)
300 old_context.pre_fe_reinit(sys, elem.
parent());
311 const Real master_tol = out_of_elem_tol / elem.
hmax() * 2;
314 if (child.close_to_point(p, master_tol))
316 old_context.pre_fe_reinit(sys, &child);
321 (old_context.get_elem().close_to_point(p, master_tol));
328 old_context.pre_fe_reinit(sys, &elem);
335 libmesh_assert(old_context.has_elem());
337 const Real master_tol = out_of_elem_tol / elem.
hmax() * 2;
339 if (!old_context.get_elem().close_to_point(p, master_tol))
341 libmesh_assert_equal_to
345 if (child.close_to_point(p, master_tol))
347 old_context.pre_fe_reinit(sys, &child);
352 (old_context.get_elem().close_to_point(p, master_tol));
377 template <
typename Output,
378 void (
FEMContext::*point_output) (
unsigned int,
388 old_solution(old_sol)
391 this->old_context.set_custom_solution(&old_solution);
396 old_solution(in.old_solution)
399 this->old_context.set_custom_solution(&old_solution);
405 unsigned int elem_dim,
414 LOG_SCOPE (
"eval_at_point()",
"OldSolutionValue");
416 if (!this->check_old_context(c, p))
420 libmesh_assert_less(i, this->component_to_var.size());
421 unsigned int var = this->component_to_var[i];
424 (this->old_context.*point_output)(var, p, n, this->out_of_elem_tol);
430 std::vector<Output> & values)
432 LOG_SCOPE (
"eval_old_dofs()",
"OldSolutionValue");
434 this->check_old_context(c);
436 const std::vector<dof_id_type> & old_dof_indices =
437 this->old_context.get_dof_indices(var);
439 libmesh_assert_equal_to (old_dof_indices.size(), values.size());
441 old_solution.get(old_dof_indices, values);
465 #ifdef LIBMESH_USE_COMPLEX_NUMBERS 480 #endif // LIBMESH_USE_COMPLEX_NUMBERS 493 LOG_SCOPE (
"Number eval_at_node()",
"OldSolutionValue");
496 libmesh_assert_less(i, this->component_to_var.size());
497 unsigned int var = this->component_to_var[i];
512 return old_solution(old_id);
515 return this->eval_at_point(c, i, n, 0);
526 unsigned int elem_dim,
530 LOG_SCOPE (
"Gradient eval_at_node()",
"OldSolutionValue");
533 libmesh_assert_less(i, this->component_to_var.size());
534 unsigned int var = this->component_to_var[i];
548 for (
unsigned int d = 0; d != elem_dim; ++d)
552 g(d) = old_solution(old_id);
557 return this->eval_at_point(c, i, n, 0);
570 #ifdef LIBMESH_USE_COMPLEX_NUMBERS 576 #endif // LIBMESH_USE_COMPLEX_NUMBERS 578 #endif // LIBMESH_ENABLE_AMR 585 template <
typename FFunctor,
typename GFunctor,
586 typename FValue,
typename ProjectionAction>
590 LOG_SCOPE (
"operator()",
"GenericProjector");
592 ProjectionAction action(master_action);
593 FFunctor f(master_f);
594 std::unique_ptr<GFunctor> g;
596 g.reset(
new GFunctor(*master_g));
599 const DofMap & dof_map = system.get_dof_map();
615 for (
const auto & var : variables)
619 FEBase * side_fe =
nullptr;
620 FEBase * edge_fe =
nullptr;
622 const std::set<unsigned char> & elem_dims =
625 for (
const auto & dim : elem_dims)
659 f.init_context(context);
661 g->init_context(context);
666 for (
const auto & elem : range)
668 unsigned char dim = cast_int<unsigned char>(elem->dim());
674 #ifdef LIBMESH_ENABLE_AMR 679 if (!elem->old_dof_object &&
682 f.is_grid_projection())
684 #endif // LIBMESH_ENABLE_AMR 688 for (
const auto & var : variables)
692 const FEType & base_fe_type = variable.
type();
694 FEType fe_type = base_fe_type;
708 const std::vector<dof_id_type> & dof_indices =
712 const unsigned int n_dofs =
713 cast_int<unsigned int>(dof_indices.size());
715 const unsigned int var_component =
716 system.variable_scalar_number(var, 0);
722 #ifdef LIBMESH_ENABLE_AMR 723 if (f.is_grid_projection() &&
733 elem->p_level() == 0 &&
740 LOG_SCOPE (
"copy_dofs",
"GenericProjector");
742 f.eval_old_dofs(context, var, Ue.
get_values());
744 action.insert(context, var, Ue);
748 #endif // LIBMESH_ENABLE_AMR 751 FEBase * side_fe =
nullptr;
752 FEBase * edge_fe =
nullptr;
764 std::vector<unsigned int> side_dofs;
767 std::vector<char> dof_is_fixed(n_dofs,
false);
768 std::vector<int> free_dof(n_dofs, 0);
771 const ElemType elem_type = elem->type();
774 const unsigned int n_nodes = elem->n_nodes();
776 START_LOG (
"project_nodes",
"GenericProjector");
782 #ifdef LIBMESH_ENABLE_AMR 784 i_am_child = elem->parent()->which_child_am_i(elem);
798 unsigned int current_dof = 0;
799 for (
unsigned int n=0; n!=
n_nodes; ++n)
803 const unsigned int nc =
806 if (!elem->is_vertex(n) &&
815 libmesh_assert_equal_to (nc, 0);
821 libmesh_assert (!elem->is_vertex(n));
828 Ue(current_dof) = f.eval_at_node(context,
833 dof_is_fixed[current_dof] =
true;
836 else if (cont ==
C_ONE)
838 const bool is_parent_vertex = (i_am_child == -1) ||
839 elem->parent()->is_vertex_on_parent(i_am_child, n);
845 f.eval_at_node(context,
850 dof_is_fixed[current_dof] =
true;
854 g->eval_at_node(context,
859 g->eval_at_point(context,
864 Ue(current_dof) = grad(0);
865 dof_is_fixed[current_dof] =
true;
872 Point nxminus = elem->point(n),
873 nxplus = elem->point(n);
874 nxminus(0) -= delta_x;
875 nxplus(0) += delta_x;
877 g->eval_at_point(context,
882 g->eval_at_point(context,
887 Ue(current_dof) = grad(1);
888 dof_is_fixed[current_dof] =
true;
891 Ue(current_dof) = (gxplus(1) - gxminus(1))
893 dof_is_fixed[current_dof] =
true;
899 Ue(current_dof) = grad(2);
900 dof_is_fixed[current_dof] =
true;
903 Ue(current_dof) = (gxplus(2) - gxminus(2))
905 dof_is_fixed[current_dof] =
true;
908 Point nyminus = elem->point(n),
909 nyplus = elem->point(n);
910 nyminus(1) -= delta_x;
911 nyplus(1) += delta_x;
913 g->eval_at_point(context,
918 g->eval_at_point(context,
923 Ue(current_dof) = (gyplus(2) - gyminus(2))
925 dof_is_fixed[current_dof] =
true;
928 Point nxmym = elem->point(n),
929 nxmyp = elem->point(n),
930 nxpym = elem->point(n),
931 nxpyp = elem->point(n);
941 g->eval_at_point(context,
946 g->eval_at_point(context,
951 g->eval_at_point(context,
956 g->eval_at_point(context,
960 FValue gxzplus = (gxpyp(2) - gxmyp(2))
962 FValue gxzminus = (gxpym(2) - gxmym(2))
965 Ue(current_dof) = (gxzplus - gxzminus)
967 dof_is_fixed[current_dof] =
true;
977 libmesh_assert_equal_to (nc, (
unsigned int)(1 + dim));
978 Ue(current_dof) = f.eval_at_node(context,
983 dof_is_fixed[current_dof] =
true;
987 g->eval_at_node(context,
992 g->eval_at_point(context,
996 for (
unsigned int i=0; i!= dim; ++i)
998 Ue(current_dof) = grad(i);
999 dof_is_fixed[current_dof] =
true;
1005 libmesh_error_msg(
"Unknown continuity " << cont);
1008 STOP_LOG (
"project_nodes",
"GenericProjector");
1010 START_LOG (
"project_edges",
"GenericProjector");
1016 #ifdef LIBMESH_ENABLE_INFINITE_ELEMENTS
1023 const std::vector<Point> & xyz_values =
1024 #ifdef LIBMESH_ENABLE_AMR 1029 const std::vector<Real> & JxW =
1030 #ifdef LIBMESH_ENABLE_AMR 1036 const std::vector<std::vector<Real>> & phi =
1037 #ifdef LIBMESH_ENABLE_AMR 1042 const std::vector<std::vector<RealGradient>> * dphi =
nullptr;
1045 #ifdef LIBMESH_ENABLE_AMR 1051 for (
auto e : elem->edge_index_range())
1053 context.
edge = cast_int<unsigned char>(e);
1055 #ifdef LIBMESH_ENABLE_AMR 1058 std::vector<Point> fine_points;
1060 std::unique_ptr<FEBase> fine_fe
1063 std::unique_ptr<QBase> qrule
1065 fine_fe->attach_quadrature_rule(qrule.get());
1067 const std::vector<Point> & child_xyz =
1070 for (
unsigned int c = 0, nc = elem->n_children();
1073 if (!elem->is_child_on_edge(c, e))
1076 fine_fe->edge_reinit(elem->child_ptr(c), e);
1077 fine_points.insert(fine_points.end(),
1082 std::vector<Point> fine_qp;
1084 fine_points, fine_qp);
1089 #endif // LIBMESH_ENABLE_AMR 1092 const unsigned int n_qp =
1093 cast_int<unsigned int>(xyz_values.size());
1098 const unsigned int n_side_dofs =
1099 cast_int<unsigned int>(side_dofs.size());
1103 unsigned int free_dofs = 0;
1104 for (
unsigned int i=0; i != n_side_dofs; ++i)
1105 if (!dof_is_fixed[side_dofs[i]])
1106 free_dof[free_dofs++] = i;
1118 for (
unsigned int qp=0; qp<n_qp; qp++)
1121 FValue fineval = f.eval_at_point(context,
1128 finegrad = g->eval_at_point(context,
1134 for (
unsigned int sidei=0, freei=0;
1135 sidei != n_side_dofs; ++sidei)
1137 unsigned int i = side_dofs[sidei];
1139 if (dof_is_fixed[i])
1141 for (
unsigned int sidej=0, freej=0;
1142 sidej != n_side_dofs; ++sidej)
1144 unsigned int j = side_dofs[sidej];
1145 if (dof_is_fixed[j])
1146 Fe(freei) -= phi[i][qp] * phi[j][qp] *
1149 Ke(freei,freej) += phi[i][qp] *
1150 phi[j][qp] * JxW[qp];
1153 if (dof_is_fixed[j])
1154 Fe(freei) -= ( (*dphi)[i][qp] *
1158 Ke(freei,freej) += ( (*dphi)[i][qp] *
1162 if (!dof_is_fixed[j])
1165 Fe(freei) += phi[i][qp] * fineval * JxW[qp];
1167 Fe(freei) += (finegrad * (*dphi)[i][qp] ) *
1176 for (
unsigned int i=0; i != free_dofs; ++i)
1178 FValue & ui = Ue(side_dofs[free_dof[i]]);
1182 dof_is_fixed[side_dofs[free_dof[i]]] =
true;
1187 STOP_LOG (
"project_edges",
"GenericProjector");
1189 START_LOG (
"project_sides",
"GenericProjector");
1196 #ifdef LIBMESH_ENABLE_INFINITE_ELEMENTS
1203 const std::vector<Point> & xyz_values =
1204 #ifdef LIBMESH_ENABLE_AMR 1207 #endif // LIBMESH_ENABLE_AMR 1209 const std::vector<Real> & JxW =
1210 #ifdef LIBMESH_ENABLE_AMR 1213 #endif // LIBMESH_ENABLE_AMR 1215 const std::vector<std::vector<Real>> & phi =
1216 #ifdef LIBMESH_ENABLE_AMR 1219 #endif // LIBMESH_ENABLE_AMR 1221 const std::vector<std::vector<RealGradient>> * dphi =
nullptr;
1224 #ifdef LIBMESH_ENABLE_AMR 1229 for (
auto s : elem->side_index_range())
1234 unsigned int n_side_dofs =
1235 cast_int<unsigned int>(side_dofs.size());
1239 unsigned int free_dofs = 0;
1240 for (
unsigned int i=0; i != n_side_dofs; ++i)
1241 if (!dof_is_fixed[side_dofs[i]])
1242 free_dof[free_dofs++] = i;
1253 context.
side = cast_int<unsigned char>(s);
1255 #ifdef LIBMESH_ENABLE_AMR 1258 std::vector<Point> fine_points;
1260 std::unique_ptr<FEBase> fine_fe
1263 std::unique_ptr<QBase> qrule
1265 fine_fe->attach_quadrature_rule(qrule.get());
1267 const std::vector<Point> & child_xyz =
1270 for (
unsigned int c = 0, nc = elem->n_children();
1273 if (!elem->is_child_on_side(c, s))
1276 fine_fe->reinit(elem->child_ptr(c), s);
1277 fine_points.insert(fine_points.end(),
1282 std::vector<Point> fine_qp;
1284 fine_points, fine_qp);
1289 #endif // LIBMESH_ENABLE_AMR 1292 const unsigned int n_qp =
1293 cast_int<unsigned int>(xyz_values.size());
1296 for (
unsigned int qp=0; qp<n_qp; qp++)
1299 FValue fineval = f.eval_at_point(context,
1306 finegrad = g->eval_at_point(context,
1312 for (
unsigned int sidei=0, freei=0;
1313 sidei != n_side_dofs; ++sidei)
1315 unsigned int i = side_dofs[sidei];
1317 if (dof_is_fixed[i])
1319 for (
unsigned int sidej=0, freej=0;
1320 sidej != n_side_dofs; ++sidej)
1322 unsigned int j = side_dofs[sidej];
1323 if (dof_is_fixed[j])
1324 Fe(freei) -= phi[i][qp] * phi[j][qp] *
1327 Ke(freei,freej) += phi[i][qp] *
1328 phi[j][qp] * JxW[qp];
1331 if (dof_is_fixed[j])
1332 Fe(freei) -= ( (*dphi)[i][qp] *
1336 Ke(freei,freej) += ( (*dphi)[i][qp] *
1340 if (!dof_is_fixed[j])
1343 Fe(freei) += (fineval * phi[i][qp]) * JxW[qp];
1345 Fe(freei) += (finegrad * (*dphi)[i][qp] ) *
1354 for (
unsigned int i=0; i != free_dofs; ++i)
1356 FValue & ui = Ue(side_dofs[free_dof[i]]);
1360 dof_is_fixed[side_dofs[free_dof[i]]] =
true;
1365 STOP_LOG (
"project_sides",
"GenericProjector");
1367 START_LOG (
"project_interior",
"GenericProjector");
1373 unsigned int free_dofs = 0;
1374 for (
unsigned int i=0; i != n_dofs; ++i)
1375 if (!dof_is_fixed[i])
1376 free_dof[free_dofs++] = i;
1382 #ifdef LIBMESH_ENABLE_INFINITE_ELEMENTS
1387 const std::vector<Point> & xyz_values = fe->
get_xyz();
1388 const std::vector<Real> & JxW = fe->
get_JxW();
1390 const std::vector<std::vector<Real>> & phi = fe->
get_phi();
1391 const std::vector<std::vector<RealGradient>> * dphi =
nullptr;
1395 #ifdef LIBMESH_ENABLE_AMR 1398 std::vector<Point> fine_points;
1400 std::unique_ptr<FEBase> fine_fe
1403 std::unique_ptr<QBase> qrule
1405 fine_fe->attach_quadrature_rule(qrule.get());
1407 const std::vector<Point> & child_xyz =
1410 for (
auto & child : elem->child_ref_range())
1412 fine_fe->reinit(&child);
1413 fine_points.insert(fine_points.end(),
1418 std::vector<Point> fine_qp;
1420 fine_points, fine_qp);
1425 #endif // LIBMESH_ENABLE_AMR 1428 const unsigned int n_qp =
1429 cast_int<unsigned int>(xyz_values.size());
1437 for (
unsigned int qp=0; qp<n_qp; qp++)
1440 FValue fineval = f.eval_at_point(context,
1447 finegrad = g->eval_at_point(context,
1453 for (
unsigned int i=0, freei=0; i != n_dofs; ++i)
1456 if (dof_is_fixed[i])
1458 for (
unsigned int j=0, freej=0; j != n_dofs; ++j)
1460 if (dof_is_fixed[j])
1461 Fe(freei) -= phi[i][qp] * phi[j][qp] * JxW[qp]
1464 Ke(freei,freej) += phi[i][qp] * phi[j][qp] *
1468 if (dof_is_fixed[j])
1469 Fe(freei) -= ( (*dphi)[i][qp] *
1470 (*dphi)[j][qp] ) * JxW[qp] *
1473 Ke(freei,freej) += ( (*dphi)[i][qp] *
1477 if (!dof_is_fixed[j])
1480 Fe(freei) += phi[i][qp] * fineval * JxW[qp];
1482 Fe(freei) += (finegrad * (*dphi)[i][qp] ) * JxW[qp];
1489 for (
unsigned int i=0; i != free_dofs; ++i)
1491 FValue & ui = Ue(free_dof[i]);
1495 dof_is_fixed[free_dof[i]] =
true;
1500 STOP_LOG (
"project_interior",
"GenericProjector");
1503 for (
unsigned int i=0; i != n_dofs; ++i)
1504 libmesh_assert(dof_is_fixed[i]);
1506 action.insert(context, var, Ue);
1513 #endif // GENERIC_PROJECTOR_H
static void dofs_on_edge(const Elem *const elem, const unsigned int dim, const FEType &fe_t, unsigned int e, std::vector< unsigned int > &di)
Manages the family, order, etc. parameters for a given FE.
virtual unsigned int size() const override
void check_old_context(const FEMContext &c)
RefinementState refinement_flag() const
dof_id_type dof_number(const unsigned int s, const unsigned int var, const unsigned int comp) const
const Elem * parent() const
void operator()(const ConstElemRange &range) const
OldSolutionValue(const OldSolutionValue &in)
A geometric point in (x,y,z) space associated with a DOF.
const std::vector< Point > & get_xyz() const
bool check_old_context(const FEMContext &c, const Point &p)
void get_side_fe(unsigned int var, FEGenericBase< OutputShape > *&fe) const
virtual void pre_fe_reinit(const System &, const Elem *e)
const NumericVector< Number > & old_solution
unsigned int n_comp(const unsigned int s, const unsigned int var) const
void get_edge_fe(unsigned int var, FEGenericBase< OutputShape > *&fe) const
void eval_old_dofs(const FEMContext &c, unsigned int var, std::vector< Output > &values)
void init_context(FEMContext &c)
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 Elem & get_elem() const
void resize(const unsigned int n)
std::vector< T > & get_values()
FEMFunctionWrapper(const FEMFunctionWrapper< Output > &fw)
The base class for all geometric element types.
FEMFunctionWrapper(const FEMFunctionBase< Output > &f)
void set_algebraic_type(const AlgebraicType atype)
static const Real TOLERANCE
Utility class for defining generic ranges for threading.
const GFunctor * master_g
OldSolutionBase(const libMesh::System &sys_in)
virtual Real hmax() const
NumericVector< Val > & target_vector
VectorSetAction(NumericVector< Val > &target_vec)
Output eval_at_node(const FEMContext &c, unsigned int i, unsigned int elem_dim, const Node &n, Real=0.)
OldSolutionBase(const OldSolutionBase &in)
static void get_shape_outputs(FEBase &fe)
SimpleRange< ChildRefIter > child_ref_range()
virtual void elem_fe_reinit(const std::vector< Point > *const pts=nullptr)
virtual FEContinuity get_continuity() const =0
FEType get_fe_type() const
Manages the degrees of freedom (DOFs) in a simulation.
Output eval_at_node(const FEMContext &c, unsigned int i, unsigned int, const Node &n, const Real time)
std::unique_ptr< QBase > default_quadrature_rule(const unsigned int dim, const int extraorder=0) const
const std::vector< std::vector< OutputGradient > > & get_dphi() const
bool is_grid_projection()
const dof_id_type n_nodes
A variable which is solved for in a System of equations.
const Variable & variable(const unsigned int c) const
const FFunctor & master_f
virtual void side_fe_reinit()
dof_id_type numeric_index_type
void eval_old_dofs(const FEMContext &, unsigned int, std::vector< Output >)
unsigned int n_vars(const unsigned int s, const unsigned int vg) const
Manages consistently variables, degrees of freedom, and coefficient vectors.
const std::vector< Real > & get_JxW() const
static std::unique_ptr< FEGenericBase > build(const unsigned int dim, const FEType &type)
void init_context(FEMContext &c)
static Point inverse_map(const unsigned int dim, const FEType &fe_t, const Elem *elem, const Point &p, const Real tolerance=TOLERANCE, const bool secure=true)
const std::vector< dof_id_type > & get_dof_indices() const
std::unique_ptr< FEMFunctionBase< Output > > _f
bool active_on_subdomain(subdomain_id_type sid) const
const ProjectionAction & master_action
void insert(const FEMContext &c, unsigned int var_num, const DenseVector< Val > &Ue)
const std::vector< unsigned int > & variables
virtual void edge_fe_reinit()
static unsigned int n_dofs_at_node(const unsigned int dim, const FEType &fe_t, const ElemType t, const unsigned int n)
virtual numeric_index_type first_local_index() const =0
DIE A HORRIBLE DEATH HERE typedef LIBMESH_DEFAULT_SCALAR_TYPE Real
static const Real out_of_elem_tol
DofObject * old_dof_object
Output eval_at_point(const FEMContext &c, unsigned int i, const Point &p, Real=0.)
GenericProjector(const System &system_in, const FFunctor &f_in, const GFunctor *g_in, const ProjectionAction &act_in, const std::vector< unsigned int > &variables_in)
Output eval_at_point(const FEMContext &c, unsigned int i, const Point &n, const Real time)
virtual void zero() override
void resize(const unsigned int new_m, const unsigned int new_n)
void get_element_fe(unsigned int var, FEGenericBase< OutputShape > *&fe) const
OldSolutionValue(const libMesh::System &sys_in, const NumericVector< Number > &old_sol)
virtual void set(const numeric_index_type i, const T value)=0
std::vector< unsigned int > component_to_var
void cholesky_solve(const DenseVector< T2 > &b, DenseVector< T2 > &x)
A matrix object used for finite element assembly and numerics.
A geometric point in (x,y,z) space.
virtual numeric_index_type last_local_index() const =0
GenericProjector(const GenericProjector &in)
bool is_grid_projection()
const std::set< unsigned char > & elem_dimensions() const
virtual void zero() override
const std::vector< std::vector< OutputShape > > & get_phi() const
const FEType & type() const