generic_projector.h
Go to the documentation of this file.
1 // The libMesh Finite Element Library.
2 // Copyright (C) 2002-2018 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 #ifndef GENERIC_PROJECTOR_H
21 #define GENERIC_PROJECTOR_H
22 
23 // C++ includes
24 #include <vector>
25 
26 // Local includes
27 #include "libmesh/dense_matrix.h"
28 #include "libmesh/dense_vector.h"
29 #include "libmesh/dof_map.h"
30 #include "libmesh/elem.h"
31 #include "libmesh/fe_base.h"
32 #include "libmesh/fe_interface.h"
34 #include "libmesh/numeric_vector.h"
35 #include "libmesh/quadrature.h"
36 #include "libmesh/system.h"
37 #include "libmesh/threads.h"
38 
39 namespace libMesh
40 {
41 
52 template <typename FFunctor, typename GFunctor,
53  typename FValue, typename ProjectionAction>
55 {
56 private:
57  const System & system;
58 
59  // For TBB compatibility and thread safety we'll copy these in
60  // operator()
61  const FFunctor & master_f;
62  const GFunctor * master_g; // Needed for C1 type elements only
64  const ProjectionAction & master_action;
65  const std::vector<unsigned int> & variables;
66 
67 public:
68  GenericProjector (const System & system_in,
69  const FFunctor & f_in,
70  const GFunctor * g_in,
71  const ProjectionAction & act_in,
72  const std::vector<unsigned int> & variables_in) :
73  system(system_in),
74  master_f(f_in),
75  master_g(g_in),
76  g_was_copied(false),
77  master_action(act_in),
78  variables(variables_in)
79  {}
80 
82  system(in.system),
83  master_f(in.master_f),
84  master_g(in.master_g ? new GFunctor(*in.master_g) : nullptr),
88  {}
89 
91  {
92  if (g_was_copied)
93  delete master_g;
94  }
95 
96  void operator() (const ConstElemRange & range) const;
97 };
98 
99 
109 template <typename Val>
111 {
112 private:
114 
115 public:
117  target_vector(target_vec) {}
118 
119  void insert(const FEMContext & c,
120  unsigned int var_num,
121  const DenseVector<Val> & Ue)
122  {
123  const numeric_index_type
126 
127  const std::vector<dof_id_type> & dof_indices =
128  c.get_dof_indices(var_num);
129 
130  unsigned int size = Ue.size();
131 
132  libmesh_assert_equal_to(size, dof_indices.size());
133 
134  // Lock the new vector since it is shared among threads.
135  {
136  Threads::spin_mutex::scoped_lock lock(Threads::spin_mtx);
137 
138  for (unsigned int i = 0; i != size; ++i)
139  if ((dof_indices[i] >= first) && (dof_indices[i] < last))
140  target_vector.set(dof_indices[i], Ue(i));
141  }
142  }
143 };
144 
145 
154 template <typename Output>
156 {
157 public:
158  FEMFunctionWrapper(const FEMFunctionBase<Output> & f) : _f(f.clone()) {}
159 
161  _f(fw._f->clone()) {}
162 
163  void init_context (FEMContext & c) { _f->init_context(c); }
164 
165  Output eval_at_node (const FEMContext & c,
166  unsigned int i,
167  unsigned int /*elem_dim*/,
168  const Node & n,
169  const Real time)
170  { return _f->component(c, i, n, time); }
171 
172  Output eval_at_point (const FEMContext & c,
173  unsigned int i,
174  const Point & n,
175  const Real time)
176  { return _f->component(c, i, n, time); }
177 
178  bool is_grid_projection() { return false; }
179 
180  void eval_old_dofs (const FEMContext & /* c */,
181  unsigned int /* var_component */,
182  std::vector<Output> /* values */)
183  { libmesh_error(); }
184 
185 private:
186  std::unique_ptr<FEMFunctionBase<Output>> _f;
187 };
188 
189 
200 #ifdef LIBMESH_ENABLE_AMR
201 template <typename Output,
202  void (FEMContext::*point_output) (unsigned int,
203  const Point &,
204  Output &,
205  const Real) const>
207 {
208 public:
210  last_elem(nullptr),
211  sys(sys_in),
212  old_context(sys_in)
213  {
214  // We'll be queried for components but we'll typically be looking
215  // up data by variables, and those indices don't always match
216  for (auto v : IntRange<unsigned int>(0, sys.n_vars()))
217  {
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;
222  }
223  }
224 
226  last_elem(nullptr),
227  sys(in.sys),
228  old_context(sys),
229  component_to_var(in.component_to_var)
230  {
231  }
232 
233  static void get_shape_outputs(FEBase & fe);
234 
235  // Integrating on new mesh elements, we won't yet have an up to date
236  // current_local_solution.
238  {
240 
241  // Loop over variables, to prerequest
242  for (unsigned int var=0; var!=sys.n_vars(); ++var)
243  {
244  FEBase * fe = nullptr;
245  const std::set<unsigned char> & elem_dims =
246  old_context.elem_dimensions();
247 
248  for (const auto & dim : elem_dims)
249  {
250  old_context.get_element_fe(var, fe, dim);
251  get_shape_outputs(*fe);
252  }
253  }
254  }
255 
256  bool is_grid_projection() { return true; }
257 
258 protected:
259  void check_old_context (const FEMContext & c)
260  {
261  LOG_SCOPE ("check_old_context(c)", "OldSolutionBase");
262  const Elem & elem = c.get_elem();
263  if (last_elem != &elem)
264  {
265  if (elem.refinement_flag() == Elem::JUST_REFINED)
266  {
267  old_context.pre_fe_reinit(sys, elem.parent());
268  }
269  else if (elem.refinement_flag() == Elem::JUST_COARSENED)
270  {
271  libmesh_error();
272  }
273  else
274  {
275  if (!elem.old_dof_object)
276  {
277  libmesh_error();
278  }
279 
280  old_context.pre_fe_reinit(sys, &elem);
281  }
282 
283  last_elem = &elem;
284  }
285  else
286  {
287  libmesh_assert(old_context.has_elem());
288  }
289  }
290 
291 
292  bool check_old_context (const FEMContext & c, const Point & p)
293  {
294  LOG_SCOPE ("check_old_context(c,p)", "OldSolutionBase");
295  const Elem & elem = c.get_elem();
296  if (last_elem != &elem)
297  {
298  if (elem.refinement_flag() == Elem::JUST_REFINED)
299  {
300  old_context.pre_fe_reinit(sys, elem.parent());
301  }
302  else if (elem.refinement_flag() == Elem::JUST_COARSENED)
303  {
304  // Find the child with this point. Use out_of_elem_tol
305  // (in physical space, which may correspond to a large
306  // tolerance in master space!) to allow for out-of-element
307  // finite differencing of mixed gradient terms. Pray we
308  // have no quadrature locations which are within 1e-5 of
309  // the element subdivision boundary but are not exactly on
310  // that boundary.
311  const Real master_tol = out_of_elem_tol / elem.hmax() * 2;
312 
313  for (auto & child : elem.child_ref_range())
314  if (child.close_to_point(p, master_tol))
315  {
316  old_context.pre_fe_reinit(sys, &child);
317  break;
318  }
319 
320  libmesh_assert
321  (old_context.get_elem().close_to_point(p, master_tol));
322  }
323  else
324  {
325  if (!elem.old_dof_object)
326  return false;
327 
328  old_context.pre_fe_reinit(sys, &elem);
329  }
330 
331  last_elem = &elem;
332  }
333  else
334  {
335  libmesh_assert(old_context.has_elem());
336 
337  const Real master_tol = out_of_elem_tol / elem.hmax() * 2;
338 
339  if (!old_context.get_elem().close_to_point(p, master_tol))
340  {
341  libmesh_assert_equal_to
343 
344  for (auto & child : elem.child_ref_range())
345  if (child.close_to_point(p, master_tol))
346  {
347  old_context.pre_fe_reinit(sys, &child);
348  break;
349  }
350 
351  libmesh_assert
352  (old_context.get_elem().close_to_point(p, master_tol));
353  }
354  }
355 
356  return true;
357  }
358 
359 protected:
360  const Elem * last_elem;
361  const System & sys;
363  std::vector<unsigned int> component_to_var;
364 
365  static const Real out_of_elem_tol;
366 };
367 
368 
377 template <typename Output,
378  void (FEMContext::*point_output) (unsigned int,
379  const Point &,
380  Output &,
381  const Real) const>
383 {
384 public:
386  const NumericVector<Number> & old_sol) :
387  OldSolutionBase<Output, point_output>(sys_in),
388  old_solution(old_sol)
389  {
390  this->old_context.set_algebraic_type(FEMContext::OLD);
391  this->old_context.set_custom_solution(&old_solution);
392  }
393 
395  OldSolutionBase<Output, point_output>(in.sys),
396  old_solution(in.old_solution)
397  {
398  this->old_context.set_algebraic_type(FEMContext::OLD);
399  this->old_context.set_custom_solution(&old_solution);
400  }
401 
402 
403  Output eval_at_node (const FEMContext & c,
404  unsigned int i,
405  unsigned int elem_dim,
406  const Node & n,
407  Real /* time */ =0.);
408 
409  Output eval_at_point(const FEMContext & c,
410  unsigned int i,
411  const Point & p,
412  Real /* time */ =0.)
413  {
414  LOG_SCOPE ("eval_at_point()", "OldSolutionValue");
415 
416  if (!this->check_old_context(c, p))
417  return 0;
418 
419  // Handle offset from non-scalar components in previous variables
420  libmesh_assert_less(i, this->component_to_var.size());
421  unsigned int var = this->component_to_var[i];
422 
423  Output n;
424  (this->old_context.*point_output)(var, p, n, this->out_of_elem_tol);
425  return n;
426  }
427 
428  void eval_old_dofs (const FEMContext & c,
429  unsigned int var,
430  std::vector<Output> & values)
431  {
432  LOG_SCOPE ("eval_old_dofs()", "OldSolutionValue");
433 
434  this->check_old_context(c);
435 
436  const std::vector<dof_id_type> & old_dof_indices =
437  this->old_context.get_dof_indices(var);
438 
439  libmesh_assert_equal_to (old_dof_indices.size(), values.size());
440 
441  old_solution.get(old_dof_indices, values);
442  }
443 
444 private:
446 };
447 
448 
449 template<>
450 inline void
452 {
453  fe.get_phi();
454 }
455 
456 
457 template<>
458 inline void
460 {
461  fe.get_dphi();
462 }
463 
464 
465 #ifdef LIBMESH_USE_COMPLEX_NUMBERS
466 template<>
467 inline void
469 {
470  fe.get_phi();
471 }
472 
473 
474 template<>
475 inline void
477 {
478  fe.get_dphi();
479 }
480 #endif // LIBMESH_USE_COMPLEX_NUMBERS
481 
482 
483 template<>
484 inline
485 Number
488  unsigned int i,
489  unsigned int /* elem_dim */,
490  const Node & n,
491  Real /* time */)
492 {
493  LOG_SCOPE ("Number eval_at_node()", "OldSolutionValue");
494 
495  // Handle offset from non-scalar components in previous variables
496  libmesh_assert_less(i, this->component_to_var.size());
497  unsigned int var = this->component_to_var[i];
498 
499  // Optimize for the common case, where this node was part of the
500  // old solution.
501  //
502  // Be sure to handle cases where the variable wasn't defined on
503  // this node (due to changing subdomain support) or where the
504  // variable has no components on this node (due to Elem order
505  // exceeding FE order)
506  if (n.old_dof_object &&
507  n.old_dof_object->n_vars(sys.number()) &&
508  n.old_dof_object->n_comp(sys.number(), var))
509  {
510  const dof_id_type old_id =
511  n.old_dof_object->dof_number(sys.number(), var, 0);
512  return old_solution(old_id);
513  }
514 
515  return this->eval_at_point(c, i, n, 0);
516 }
517 
518 
519 
520 template<>
521 inline
522 Gradient
525  unsigned int i,
526  unsigned int elem_dim,
527  const Node & n,
528  Real /* time */)
529 {
530  LOG_SCOPE ("Gradient eval_at_node()", "OldSolutionValue");
531 
532  // Handle offset from non-scalar components in previous variables
533  libmesh_assert_less(i, this->component_to_var.size());
534  unsigned int var = this->component_to_var[i];
535 
536  // Optimize for the common case, where this node was part of the
537  // old solution.
538  //
539  // Be sure to handle cases where the variable wasn't defined on
540  // this node (due to changing subdomain support) or where the
541  // variable has no components on this node (due to Elem order
542  // exceeding FE order)
543  if (n.old_dof_object &&
544  n.old_dof_object->n_vars(sys.number()) &&
545  n.old_dof_object->n_comp(sys.number(), var))
546  {
547  Gradient g;
548  for (unsigned int d = 0; d != elem_dim; ++d)
549  {
550  const dof_id_type old_id =
551  n.old_dof_object->dof_number(sys.number(), var, d+1);
552  g(d) = old_solution(old_id);
553  }
554  return g;
555  }
556 
557  return this->eval_at_point(c, i, n, 0);
558 }
559 
560 
561 
562 
563 
564 template <>
566 
567 template <>
569 
570 #ifdef LIBMESH_USE_COMPLEX_NUMBERS
571 template <>
573 
574 template <>
576 #endif // LIBMESH_USE_COMPLEX_NUMBERS
577 
578 #endif // LIBMESH_ENABLE_AMR
579 
585 template <typename FFunctor, typename GFunctor,
586  typename FValue, typename ProjectionAction>
588  (const ConstElemRange & range) const
589 {
590  LOG_SCOPE ("operator()", "GenericProjector");
591 
592  ProjectionAction action(master_action);
593  FFunctor f(master_f);
594  std::unique_ptr<GFunctor> g;
595  if (master_g)
596  g.reset(new GFunctor(*master_g));
597 
598  // The DofMap for this system
599  const DofMap & dof_map = system.get_dof_map();
600 
601  // The element matrix and RHS for projections.
602  // Note that Ke is always real-valued, whereas
603  // Fe may be complex valued if complex number
604  // support is enabled
607  // The new element degree of freedom coefficients
609 
610  // Context objects to contain all our required FE objects
611  FEMContext context( system );
612 
613  // Loop over all the variables we've been requested to project, to
614  // pre-request
615  for (const auto & var : variables)
616  {
617  // FIXME: Need to generalize this to vector-valued elements. [PB]
618  FEBase * fe = nullptr;
619  FEBase * side_fe = nullptr;
620  FEBase * edge_fe = nullptr;
621 
622  const std::set<unsigned char> & elem_dims =
623  context.elem_dimensions();
624 
625  for (const auto & dim : elem_dims)
626  {
627  context.get_element_fe( var, fe, dim );
628  if (fe->get_fe_type().family == SCALAR)
629  continue;
630  if (dim > 1)
631  context.get_side_fe( var, side_fe, dim );
632  if (dim > 2)
633  context.get_edge_fe( var, edge_fe );
634 
635  fe->get_xyz();
636 
637  fe->get_phi();
638  if (dim > 1)
639  side_fe->get_phi();
640  if (dim > 2)
641  edge_fe->get_phi();
642 
643  const FEContinuity cont = fe->get_continuity();
644  if (cont == C_ONE)
645  {
646  // Our C1 elements need gradient information
647  libmesh_assert(g);
648 
649  fe->get_dphi();
650  if (dim > 1)
651  side_fe->get_dphi();
652  if (dim > 2)
653  edge_fe->get_dphi();
654  }
655  }
656  }
657 
658  // Now initialize any user requested shape functions, xyz vals, etc
659  f.init_context(context);
660  if (g.get())
661  g->init_context(context);
662 
663  // this->init_context(context);
664 
665  // Iterate over all the elements in the range
666  for (const auto & elem : range)
667  {
668  unsigned char dim = cast_int<unsigned char>(elem->dim());
669 
670  context.pre_fe_reinit(system, elem);
671 
672  // If we're doing AMR, this might be a grid projection with a cheap
673  // early exit.
674 #ifdef LIBMESH_ENABLE_AMR
675  // If this element doesn't have an old_dof_object, but it
676  // wasn't just refined or just coarsened into activity, then
677  // it must be newly added, so the user is responsible for
678  // setting the new dofs on it during a grid projection.
679  if (!elem->old_dof_object &&
680  elem->refinement_flag() != Elem::JUST_REFINED &&
681  elem->refinement_flag() != Elem::JUST_COARSENED &&
682  f.is_grid_projection())
683  continue;
684 #endif // LIBMESH_ENABLE_AMR
685 
686  // Loop over all the variables we've been requested to project, to
687  // do the projection
688  for (const auto & var : variables)
689  {
690  const Variable & variable = dof_map.variable(var);
691 
692  const FEType & base_fe_type = variable.type();
693 
694  FEType fe_type = base_fe_type;
695 
696  // This may be a p refined element
697  fe_type.order =
698  libMesh::Order (fe_type.order + elem->p_level());
699 
700  if (fe_type.family == SCALAR)
701  continue;
702 
703  // Per-subdomain variables don't need to be projected on
704  // elements where they're not active
705  if (!variable.active_on_subdomain(elem->subdomain_id()))
706  continue;
707 
708  const std::vector<dof_id_type> & dof_indices =
709  context.get_dof_indices(var);
710 
711  // The number of DOFs on the element
712  const unsigned int n_dofs =
713  cast_int<unsigned int>(dof_indices.size());
714 
715  const unsigned int var_component =
716  system.variable_scalar_number(var, 0);
717 
718  // Zero the interpolated values
719  Ue.resize (n_dofs); Ue.zero();
720 
721  // If we're projecting from an old grid
722 #ifdef LIBMESH_ENABLE_AMR
723  if (f.is_grid_projection() &&
724  // And either this is an unchanged element
725  ((elem->refinement_flag() != Elem::JUST_REFINED &&
726  elem->refinement_flag() != Elem::JUST_COARSENED &&
727  elem->p_refinement_flag() != Elem::JUST_REFINED &&
728  elem->p_refinement_flag() != Elem::JUST_COARSENED) ||
729  // Or this is a low order monomial element which has merely
730  // been h refined
731  (fe_type.family == MONOMIAL &&
732  fe_type.order == CONSTANT &&
733  elem->p_level() == 0 &&
734  elem->refinement_flag() != Elem::JUST_COARSENED &&
735  elem->p_refinement_flag() != Elem::JUST_COARSENED))
736  )
737  // then we can simply copy its old dof
738  // values to new indices.
739  {
740  LOG_SCOPE ("copy_dofs", "GenericProjector");
741 
742  f.eval_old_dofs(context, var, Ue.get_values());
743 
744  action.insert(context, var, Ue);
745 
746  continue;
747  }
748 #endif // LIBMESH_ENABLE_AMR
749 
750  FEBase * fe = nullptr;
751  FEBase * side_fe = nullptr;
752  FEBase * edge_fe = nullptr;
753 
754  context.get_element_fe( var, fe, dim );
755  if (fe->get_fe_type().family == SCALAR)
756  continue;
757  if (dim > 1)
758  context.get_side_fe( var, side_fe, dim );
759  if (dim > 2)
760  context.get_edge_fe( var, edge_fe );
761 
762  const FEContinuity cont = fe->get_continuity();
763 
764  std::vector<unsigned int> side_dofs;
765 
766  // Fixed vs. free DoFs on edge/face projections
767  std::vector<char> dof_is_fixed(n_dofs, false); // bools
768  std::vector<int> free_dof(n_dofs, 0);
769 
770  // The element type
771  const ElemType elem_type = elem->type();
772 
773  // The number of nodes on the new element
774  const unsigned int n_nodes = elem->n_nodes();
775 
776  START_LOG ("project_nodes","GenericProjector");
777 
778  // When interpolating C1 elements we need to know which
779  // vertices were also parent vertices; we'll cache an
780  // intermediate fact outside the nodes loop.
781  int i_am_child = -1;
782 #ifdef LIBMESH_ENABLE_AMR
783  if (elem->parent())
784  i_am_child = elem->parent()->which_child_am_i(elem);
785 #endif
786  // In general, we need a series of
787  // projections to ensure a unique and continuous
788  // solution. We start by interpolating nodes, then
789  // hold those fixed and project edges, then
790  // hold those fixed and project faces, then
791  // hold those fixed and project interiors
792  //
793  // In the LAGRANGE case, we will save a lot of solution
794  // evaluations (at a slight cost in accuracy) by simply
795  // interpolating all nodes rather than projecting.
796 
797  // Interpolate vertex (or for LAGRANGE, all node) values first.
798  unsigned int current_dof = 0;
799  for (unsigned int n=0; n!= n_nodes; ++n)
800  {
801  // FIXME: this should go through the DofMap,
802  // not duplicate dof_indices code badly!
803  const unsigned int nc =
804  FEInterface::n_dofs_at_node (dim, fe_type, elem_type, n);
805 
806  if (!elem->is_vertex(n) &&
807  fe_type.family != LAGRANGE)
808  {
809  current_dof += nc;
810  continue;
811  }
812 
813  if (cont == DISCONTINUOUS)
814  {
815  libmesh_assert_equal_to (nc, 0);
816  }
817  else if (!nc)
818  {
819  // This should only occur for first-order LAGRANGE
820  // FE on non-vertices of higher-order elements
821  libmesh_assert (!elem->is_vertex(n));
822  libmesh_assert_equal_to(fe_type.family, LAGRANGE);
823  }
824  // Assume that C_ZERO elements have a single nodal
825  // value shape function at vertices
826  else if (cont == C_ZERO)
827  {
828  Ue(current_dof) = f.eval_at_node(context,
829  var_component,
830  dim,
831  elem->node_ref(n),
832  system.time);
833  dof_is_fixed[current_dof] = true;
834  current_dof++;
835  }
836  else if (cont == C_ONE)
837  {
838  const bool is_parent_vertex = (i_am_child == -1) ||
839  elem->parent()->is_vertex_on_parent(i_am_child, n);
840 
841  // The hermite element vertex shape functions are weird
842  if (fe_type.family == HERMITE)
843  {
844  Ue(current_dof) =
845  f.eval_at_node(context,
846  var_component,
847  dim,
848  elem->node_ref(n),
849  system.time);
850  dof_is_fixed[current_dof] = true;
851  current_dof++;
852  VectorValue<FValue> grad =
853  is_parent_vertex ?
854  g->eval_at_node(context,
855  var_component,
856  dim,
857  elem->node_ref(n),
858  system.time) :
859  g->eval_at_point(context,
860  var_component,
861  elem->node_ref(n),
862  system.time);
863  // x derivative
864  Ue(current_dof) = grad(0);
865  dof_is_fixed[current_dof] = true;
866  current_dof++;
867  if (dim > 1)
868  {
869  // We'll finite difference mixed derivatives
870  Real delta_x = TOLERANCE * elem->hmin();
871 
872  Point nxminus = elem->point(n),
873  nxplus = elem->point(n);
874  nxminus(0) -= delta_x;
875  nxplus(0) += delta_x;
876  VectorValue<FValue> gxminus =
877  g->eval_at_point(context,
878  var_component,
879  nxminus,
880  system.time);
881  VectorValue<FValue> gxplus =
882  g->eval_at_point(context,
883  var_component,
884  nxplus,
885  system.time);
886  // y derivative
887  Ue(current_dof) = grad(1);
888  dof_is_fixed[current_dof] = true;
889  current_dof++;
890  // xy derivative
891  Ue(current_dof) = (gxplus(1) - gxminus(1))
892  / 2. / delta_x;
893  dof_is_fixed[current_dof] = true;
894  current_dof++;
895 
896  if (dim > 2)
897  {
898  // z derivative
899  Ue(current_dof) = grad(2);
900  dof_is_fixed[current_dof] = true;
901  current_dof++;
902  // xz derivative
903  Ue(current_dof) = (gxplus(2) - gxminus(2))
904  / 2. / delta_x;
905  dof_is_fixed[current_dof] = true;
906  current_dof++;
907  // We need new points for yz
908  Point nyminus = elem->point(n),
909  nyplus = elem->point(n);
910  nyminus(1) -= delta_x;
911  nyplus(1) += delta_x;
912  VectorValue<FValue> gyminus =
913  g->eval_at_point(context,
914  var_component,
915  nyminus,
916  system.time);
917  VectorValue<FValue> gyplus =
918  g->eval_at_point(context,
919  var_component,
920  nyplus,
921  system.time);
922  // xz derivative
923  Ue(current_dof) = (gyplus(2) - gyminus(2))
924  / 2. / delta_x;
925  dof_is_fixed[current_dof] = true;
926  current_dof++;
927  // Getting a 2nd order xyz is more tedious
928  Point nxmym = elem->point(n),
929  nxmyp = elem->point(n),
930  nxpym = elem->point(n),
931  nxpyp = elem->point(n);
932  nxmym(0) -= delta_x;
933  nxmym(1) -= delta_x;
934  nxmyp(0) -= delta_x;
935  nxmyp(1) += delta_x;
936  nxpym(0) += delta_x;
937  nxpym(1) -= delta_x;
938  nxpyp(0) += delta_x;
939  nxpyp(1) += delta_x;
940  VectorValue<FValue> gxmym =
941  g->eval_at_point(context,
942  var_component,
943  nxmym,
944  system.time);
945  VectorValue<FValue> gxmyp =
946  g->eval_at_point(context,
947  var_component,
948  nxmyp,
949  system.time);
950  VectorValue<FValue> gxpym =
951  g->eval_at_point(context,
952  var_component,
953  nxpym,
954  system.time);
955  VectorValue<FValue> gxpyp =
956  g->eval_at_point(context,
957  var_component,
958  nxpyp,
959  system.time);
960  FValue gxzplus = (gxpyp(2) - gxmyp(2))
961  / 2. / delta_x;
962  FValue gxzminus = (gxpym(2) - gxmym(2))
963  / 2. / delta_x;
964  // xyz derivative
965  Ue(current_dof) = (gxzplus - gxzminus)
966  / 2. / delta_x;
967  dof_is_fixed[current_dof] = true;
968  current_dof++;
969  }
970  }
971  }
972  else
973  {
974  // Assume that other C_ONE elements have a single nodal
975  // value shape function and nodal gradient component
976  // shape functions
977  libmesh_assert_equal_to (nc, (unsigned int)(1 + dim));
978  Ue(current_dof) = f.eval_at_node(context,
979  var_component,
980  dim,
981  elem->node_ref(n),
982  system.time);
983  dof_is_fixed[current_dof] = true;
984  current_dof++;
985  VectorValue<FValue> grad =
986  is_parent_vertex ?
987  g->eval_at_node(context,
988  var_component,
989  dim,
990  elem->node_ref(n),
991  system.time) :
992  g->eval_at_point(context,
993  var_component,
994  elem->node_ref(n),
995  system.time);
996  for (unsigned int i=0; i!= dim; ++i)
997  {
998  Ue(current_dof) = grad(i);
999  dof_is_fixed[current_dof] = true;
1000  current_dof++;
1001  }
1002  }
1003  }
1004  else
1005  libmesh_error_msg("Unknown continuity " << cont);
1006  }
1007 
1008  STOP_LOG ("project_nodes","GenericProjector");
1009 
1010  START_LOG ("project_edges","GenericProjector");
1011 
1012  // In 3D with non-LAGRANGE, project any edge values next
1013  if (dim > 2 &&
1014  cont != DISCONTINUOUS &&
1015  (fe_type.family != LAGRANGE
1016 #ifdef LIBMESH_ENABLE_INFINITE_ELEMENTS
1017  || elem->infinite()
1018 #endif
1019  ))
1020  {
1021  // If we're JUST_COARSENED we'll need a custom
1022  // evaluation, not just the standard edge FE
1023  const std::vector<Point> & xyz_values =
1024 #ifdef LIBMESH_ENABLE_AMR
1025  (elem->refinement_flag() == Elem::JUST_COARSENED) ?
1026  fe->get_xyz() :
1027 #endif
1028  edge_fe->get_xyz();
1029  const std::vector<Real> & JxW =
1030 #ifdef LIBMESH_ENABLE_AMR
1031  (elem->refinement_flag() == Elem::JUST_COARSENED) ?
1032  fe->get_JxW() :
1033 #endif
1034  edge_fe->get_JxW();
1035 
1036  const std::vector<std::vector<Real>> & phi =
1037 #ifdef LIBMESH_ENABLE_AMR
1038  (elem->refinement_flag() == Elem::JUST_COARSENED) ?
1039  fe->get_phi() :
1040 #endif
1041  edge_fe->get_phi();
1042  const std::vector<std::vector<RealGradient>> * dphi = nullptr;
1043  if (cont == C_ONE)
1044  dphi =
1045 #ifdef LIBMESH_ENABLE_AMR
1046  (elem->refinement_flag() == Elem::JUST_COARSENED) ?
1047  &(fe->get_dphi()) :
1048 #endif
1049  &(edge_fe->get_dphi());
1050 
1051  for (auto e : elem->edge_index_range())
1052  {
1053  context.edge = cast_int<unsigned char>(e);
1054 
1055 #ifdef LIBMESH_ENABLE_AMR
1056  if (elem->refinement_flag() == Elem::JUST_COARSENED)
1057  {
1058  std::vector<Point> fine_points;
1059 
1060  std::unique_ptr<FEBase> fine_fe
1061  (FEBase::build (dim, base_fe_type));
1062 
1063  std::unique_ptr<QBase> qrule
1064  (base_fe_type.default_quadrature_rule(1));
1065  fine_fe->attach_quadrature_rule(qrule.get());
1066 
1067  const std::vector<Point> & child_xyz =
1068  fine_fe->get_xyz();
1069 
1070  for (unsigned int c = 0, nc = elem->n_children();
1071  c != nc; ++c)
1072  {
1073  if (!elem->is_child_on_edge(c, e))
1074  continue;
1075 
1076  fine_fe->edge_reinit(elem->child_ptr(c), e);
1077  fine_points.insert(fine_points.end(),
1078  child_xyz.begin(),
1079  child_xyz.end());
1080  }
1081 
1082  std::vector<Point> fine_qp;
1083  FEInterface::inverse_map (dim, base_fe_type, elem,
1084  fine_points, fine_qp);
1085 
1086  context.elem_fe_reinit(&fine_qp);
1087  }
1088  else
1089 #endif // LIBMESH_ENABLE_AMR
1090  context.edge_fe_reinit();
1091 
1092  const unsigned int n_qp =
1093  cast_int<unsigned int>(xyz_values.size());
1094 
1095  FEInterface::dofs_on_edge(elem, dim, base_fe_type,
1096  e, side_dofs);
1097 
1098  const unsigned int n_side_dofs =
1099  cast_int<unsigned int>(side_dofs.size());
1100 
1101  // Some edge dofs are on nodes and already
1102  // fixed, others are free to calculate
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;
1107 
1108  // There may be nothing to project
1109  if (!free_dofs)
1110  continue;
1111 
1112  Ke.resize (free_dofs, free_dofs); Ke.zero();
1113  Fe.resize (free_dofs); Fe.zero();
1114  // The new edge coefficients
1115  DenseVector<FValue> Uedge(free_dofs);
1116 
1117  // Loop over the quadrature points
1118  for (unsigned int qp=0; qp<n_qp; qp++)
1119  {
1120  // solution at the quadrature point
1121  FValue fineval = f.eval_at_point(context,
1122  var_component,
1123  xyz_values[qp],
1124  system.time);
1125  // solution grad at the quadrature point
1126  VectorValue<FValue> finegrad;
1127  if (cont == C_ONE)
1128  finegrad = g->eval_at_point(context,
1129  var_component,
1130  xyz_values[qp],
1131  system.time);
1132 
1133  // Form edge projection matrix
1134  for (unsigned int sidei=0, freei=0;
1135  sidei != n_side_dofs; ++sidei)
1136  {
1137  unsigned int i = side_dofs[sidei];
1138  // fixed DoFs aren't test functions
1139  if (dof_is_fixed[i])
1140  continue;
1141  for (unsigned int sidej=0, freej=0;
1142  sidej != n_side_dofs; ++sidej)
1143  {
1144  unsigned int j = side_dofs[sidej];
1145  if (dof_is_fixed[j])
1146  Fe(freei) -= phi[i][qp] * phi[j][qp] *
1147  JxW[qp] * Ue(j);
1148  else
1149  Ke(freei,freej) += phi[i][qp] *
1150  phi[j][qp] * JxW[qp];
1151  if (cont == C_ONE)
1152  {
1153  if (dof_is_fixed[j])
1154  Fe(freei) -= ( (*dphi)[i][qp] *
1155  (*dphi)[j][qp] ) *
1156  JxW[qp] * Ue(j);
1157  else
1158  Ke(freei,freej) += ( (*dphi)[i][qp] *
1159  (*dphi)[j][qp] )
1160  * JxW[qp];
1161  }
1162  if (!dof_is_fixed[j])
1163  freej++;
1164  }
1165  Fe(freei) += phi[i][qp] * fineval * JxW[qp];
1166  if (cont == C_ONE)
1167  Fe(freei) += (finegrad * (*dphi)[i][qp] ) *
1168  JxW[qp];
1169  freei++;
1170  }
1171  }
1172 
1173  Ke.cholesky_solve(Fe, Uedge);
1174 
1175  // Transfer new edge solutions to element
1176  for (unsigned int i=0; i != free_dofs; ++i)
1177  {
1178  FValue & ui = Ue(side_dofs[free_dof[i]]);
1179  libmesh_assert(bool(std::abs(ui) < TOLERANCE) ||
1180  bool(std::abs(ui - Uedge(i)) < TOLERANCE));
1181  ui = Uedge(i);
1182  dof_is_fixed[side_dofs[free_dof[i]]] = true;
1183  }
1184  }
1185  } // end if (dim > 2, !DISCONTINUOUS, !LAGRANGE)
1186 
1187  STOP_LOG ("project_edges","GenericProjector");
1188 
1189  START_LOG ("project_sides","GenericProjector");
1190 
1191  // With non-LAGRANGE, project any side values (edges in 2D,
1192  // faces in 3D) next.
1193  if (dim > 1 &&
1194  cont != DISCONTINUOUS &&
1195  (fe_type.family != LAGRANGE
1196 #ifdef LIBMESH_ENABLE_INFINITE_ELEMENTS
1197  || elem->infinite()
1198 #endif
1199  ))
1200  {
1201  // If we're JUST_COARSENED we'll need a custom
1202  // evaluation, not just the standard side FE
1203  const std::vector<Point> & xyz_values =
1204 #ifdef LIBMESH_ENABLE_AMR
1205  (elem->refinement_flag() == Elem::JUST_COARSENED) ?
1206  fe->get_xyz() :
1207 #endif // LIBMESH_ENABLE_AMR
1208  side_fe->get_xyz();
1209  const std::vector<Real> & JxW =
1210 #ifdef LIBMESH_ENABLE_AMR
1211  (elem->refinement_flag() == Elem::JUST_COARSENED) ?
1212  fe->get_JxW() :
1213 #endif // LIBMESH_ENABLE_AMR
1214  side_fe->get_JxW();
1215  const std::vector<std::vector<Real>> & phi =
1216 #ifdef LIBMESH_ENABLE_AMR
1217  (elem->refinement_flag() == Elem::JUST_COARSENED) ?
1218  fe->get_phi() :
1219 #endif // LIBMESH_ENABLE_AMR
1220  side_fe->get_phi();
1221  const std::vector<std::vector<RealGradient>> * dphi = nullptr;
1222  if (cont == C_ONE)
1223  dphi =
1224 #ifdef LIBMESH_ENABLE_AMR
1225  (elem->refinement_flag() == Elem::JUST_COARSENED) ? &(fe->get_dphi()) :
1226 #endif // LIBMESH_ENABLE_AMR
1227  &(side_fe->get_dphi());
1228 
1229  for (auto s : elem->side_index_range())
1230  {
1231  FEInterface::dofs_on_side(elem, dim, base_fe_type,
1232  s, side_dofs);
1233 
1234  unsigned int n_side_dofs =
1235  cast_int<unsigned int>(side_dofs.size());
1236 
1237  // Some side dofs are on nodes/edges and already
1238  // fixed, others are free to calculate
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;
1243 
1244  // There may be nothing to project
1245  if (!free_dofs)
1246  continue;
1247 
1248  Ke.resize (free_dofs, free_dofs); Ke.zero();
1249  Fe.resize (free_dofs); Fe.zero();
1250  // The new side coefficients
1251  DenseVector<FValue> Uside(free_dofs);
1252 
1253  context.side = cast_int<unsigned char>(s);
1254 
1255 #ifdef LIBMESH_ENABLE_AMR
1256  if (elem->refinement_flag() == Elem::JUST_COARSENED)
1257  {
1258  std::vector<Point> fine_points;
1259 
1260  std::unique_ptr<FEBase> fine_fe
1261  (FEBase::build (dim, base_fe_type));
1262 
1263  std::unique_ptr<QBase> qrule
1264  (base_fe_type.default_quadrature_rule(dim-1));
1265  fine_fe->attach_quadrature_rule(qrule.get());
1266 
1267  const std::vector<Point> & child_xyz =
1268  fine_fe->get_xyz();
1269 
1270  for (unsigned int c = 0, nc = elem->n_children();
1271  c != nc; ++c)
1272  {
1273  if (!elem->is_child_on_side(c, s))
1274  continue;
1275 
1276  fine_fe->reinit(elem->child_ptr(c), s);
1277  fine_points.insert(fine_points.end(),
1278  child_xyz.begin(),
1279  child_xyz.end());
1280  }
1281 
1282  std::vector<Point> fine_qp;
1283  FEInterface::inverse_map (dim, base_fe_type, elem,
1284  fine_points, fine_qp);
1285 
1286  context.elem_fe_reinit(&fine_qp);
1287  }
1288  else
1289 #endif // LIBMESH_ENABLE_AMR
1290  context.side_fe_reinit();
1291 
1292  const unsigned int n_qp =
1293  cast_int<unsigned int>(xyz_values.size());
1294 
1295  // Loop over the quadrature points
1296  for (unsigned int qp=0; qp<n_qp; qp++)
1297  {
1298  // solution at the quadrature point
1299  FValue fineval = f.eval_at_point(context,
1300  var_component,
1301  xyz_values[qp],
1302  system.time);
1303  // solution grad at the quadrature point
1304  VectorValue<FValue> finegrad;
1305  if (cont == C_ONE)
1306  finegrad = g->eval_at_point(context,
1307  var_component,
1308  xyz_values[qp],
1309  system.time);
1310 
1311  // Form side projection matrix
1312  for (unsigned int sidei=0, freei=0;
1313  sidei != n_side_dofs; ++sidei)
1314  {
1315  unsigned int i = side_dofs[sidei];
1316  // fixed DoFs aren't test functions
1317  if (dof_is_fixed[i])
1318  continue;
1319  for (unsigned int sidej=0, freej=0;
1320  sidej != n_side_dofs; ++sidej)
1321  {
1322  unsigned int j = side_dofs[sidej];
1323  if (dof_is_fixed[j])
1324  Fe(freei) -= phi[i][qp] * phi[j][qp] *
1325  JxW[qp] * Ue(j);
1326  else
1327  Ke(freei,freej) += phi[i][qp] *
1328  phi[j][qp] * JxW[qp];
1329  if (cont == C_ONE)
1330  {
1331  if (dof_is_fixed[j])
1332  Fe(freei) -= ( (*dphi)[i][qp] *
1333  (*dphi)[j][qp] ) *
1334  JxW[qp] * Ue(j);
1335  else
1336  Ke(freei,freej) += ( (*dphi)[i][qp] *
1337  (*dphi)[j][qp] )
1338  * JxW[qp];
1339  }
1340  if (!dof_is_fixed[j])
1341  freej++;
1342  }
1343  Fe(freei) += (fineval * phi[i][qp]) * JxW[qp];
1344  if (cont == C_ONE)
1345  Fe(freei) += (finegrad * (*dphi)[i][qp] ) *
1346  JxW[qp];
1347  freei++;
1348  }
1349  }
1350 
1351  Ke.cholesky_solve(Fe, Uside);
1352 
1353  // Transfer new side solutions to element
1354  for (unsigned int i=0; i != free_dofs; ++i)
1355  {
1356  FValue & ui = Ue(side_dofs[free_dof[i]]);
1357  libmesh_assert(bool(std::abs(ui) < TOLERANCE) ||
1358  bool(std::abs(ui - Uside(i)) < TOLERANCE));
1359  ui = Uside(i);
1360  dof_is_fixed[side_dofs[free_dof[i]]] = true;
1361  }
1362  }
1363  } // end if (dim > 1, !DISCONTINUOUS, !LAGRANGE)
1364 
1365  STOP_LOG ("project_sides","GenericProjector");
1366 
1367  START_LOG ("project_interior","GenericProjector");
1368 
1369  // Project the interior values, finally
1370 
1371  // Some interior dofs are on nodes/edges/sides and
1372  // already fixed, others are free to calculate
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;
1377 
1378  // Project any remaining (interior) dofs in the non-LAGRANGE
1379  // case.
1380  if (free_dofs &&
1381  (fe_type.family != LAGRANGE
1382 #ifdef LIBMESH_ENABLE_INFINITE_ELEMENTS
1383  || elem->infinite()
1384 #endif
1385  ))
1386  {
1387  const std::vector<Point> & xyz_values = fe->get_xyz();
1388  const std::vector<Real> & JxW = fe->get_JxW();
1389 
1390  const std::vector<std::vector<Real>> & phi = fe->get_phi();
1391  const std::vector<std::vector<RealGradient>> * dphi = nullptr;
1392  if (cont == C_ONE)
1393  dphi = &(fe->get_dphi());
1394 
1395 #ifdef LIBMESH_ENABLE_AMR
1396  if (elem->refinement_flag() == Elem::JUST_COARSENED)
1397  {
1398  std::vector<Point> fine_points;
1399 
1400  std::unique_ptr<FEBase> fine_fe
1401  (FEBase::build (dim, base_fe_type));
1402 
1403  std::unique_ptr<QBase> qrule
1404  (base_fe_type.default_quadrature_rule(dim));
1405  fine_fe->attach_quadrature_rule(qrule.get());
1406 
1407  const std::vector<Point> & child_xyz =
1408  fine_fe->get_xyz();
1409 
1410  for (auto & child : elem->child_ref_range())
1411  {
1412  fine_fe->reinit(&child);
1413  fine_points.insert(fine_points.end(),
1414  child_xyz.begin(),
1415  child_xyz.end());
1416  }
1417 
1418  std::vector<Point> fine_qp;
1419  FEInterface::inverse_map (dim, base_fe_type, elem,
1420  fine_points, fine_qp);
1421 
1422  context.elem_fe_reinit(&fine_qp);
1423  }
1424  else
1425 #endif // LIBMESH_ENABLE_AMR
1426  context.elem_fe_reinit();
1427 
1428  const unsigned int n_qp =
1429  cast_int<unsigned int>(xyz_values.size());
1430 
1431  Ke.resize (free_dofs, free_dofs); Ke.zero();
1432  Fe.resize (free_dofs); Fe.zero();
1433  // The new interior coefficients
1434  DenseVector<FValue> Uint(free_dofs);
1435 
1436  // Loop over the quadrature points
1437  for (unsigned int qp=0; qp<n_qp; qp++)
1438  {
1439  // solution at the quadrature point
1440  FValue fineval = f.eval_at_point(context,
1441  var_component,
1442  xyz_values[qp],
1443  system.time);
1444  // solution grad at the quadrature point
1445  VectorValue<FValue> finegrad;
1446  if (cont == C_ONE)
1447  finegrad = g->eval_at_point(context,
1448  var_component,
1449  xyz_values[qp],
1450  system.time);
1451 
1452  // Form interior projection matrix
1453  for (unsigned int i=0, freei=0; i != n_dofs; ++i)
1454  {
1455  // fixed DoFs aren't test functions
1456  if (dof_is_fixed[i])
1457  continue;
1458  for (unsigned int j=0, freej=0; j != n_dofs; ++j)
1459  {
1460  if (dof_is_fixed[j])
1461  Fe(freei) -= phi[i][qp] * phi[j][qp] * JxW[qp]
1462  * Ue(j);
1463  else
1464  Ke(freei,freej) += phi[i][qp] * phi[j][qp] *
1465  JxW[qp];
1466  if (cont == C_ONE)
1467  {
1468  if (dof_is_fixed[j])
1469  Fe(freei) -= ( (*dphi)[i][qp] *
1470  (*dphi)[j][qp] ) * JxW[qp] *
1471  Ue(j);
1472  else
1473  Ke(freei,freej) += ( (*dphi)[i][qp] *
1474  (*dphi)[j][qp] ) *
1475  JxW[qp];
1476  }
1477  if (!dof_is_fixed[j])
1478  freej++;
1479  }
1480  Fe(freei) += phi[i][qp] * fineval * JxW[qp];
1481  if (cont == C_ONE)
1482  Fe(freei) += (finegrad * (*dphi)[i][qp] ) * JxW[qp];
1483  freei++;
1484  }
1485  }
1486  Ke.cholesky_solve(Fe, Uint);
1487 
1488  // Transfer new interior solutions to element
1489  for (unsigned int i=0; i != free_dofs; ++i)
1490  {
1491  FValue & ui = Ue(free_dof[i]);
1492  libmesh_assert(bool(std::abs(ui) < TOLERANCE) ||
1493  bool(std::abs(ui - Uint(i)) < TOLERANCE));
1494  ui = Uint(i);
1495  dof_is_fixed[free_dof[i]] = true;
1496  }
1497 
1498  } // if there are free interior dofs
1499 
1500  STOP_LOG ("project_interior","GenericProjector");
1501 
1502  // Make sure every DoF got reached!
1503  for (unsigned int i=0; i != n_dofs; ++i)
1504  libmesh_assert(dof_is_fixed[i]);
1505 
1506  action.insert(context, var, Ue);
1507  } // end variables loop
1508  } // end elements loop
1509 }
1510 
1511 } // namespace libMesh
1512 
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)
Definition: fe_interface.C:536
Manages the family, order, etc. parameters for a given FE.
Definition: fe_type.h:179
virtual unsigned int size() const override
Definition: dense_vector.h:92
FEFamily family
Definition: fe_type.h:204
void check_old_context(const FEMContext &c)
RefinementState refinement_flag() const
Definition: elem.h:2638
double abs(double a)
dof_id_type dof_number(const unsigned int s, const unsigned int var, const unsigned int comp) const
Definition: dof_object.h:833
const Elem * parent() const
Definition: elem.h:2479
void operator()(const ConstElemRange &range) const
OldSolutionValue(const OldSolutionValue &in)
A geometric point in (x,y,z) space associated with a DOF.
Definition: node.h:52
const std::vector< Point > & get_xyz() const
Definition: fe_abstract.h:238
bool check_old_context(const FEMContext &c, const Point &p)
void get_side_fe(unsigned int var, FEGenericBase< OutputShape > *&fe) const
Definition: fem_context.h:299
virtual void pre_fe_reinit(const System &, const Elem *e)
Definition: fem_context.C:1552
const NumericVector< Number > & old_solution
unsigned int n_comp(const unsigned int s, const unsigned int var) const
Definition: dof_object.h:803
void get_edge_fe(unsigned int var, FEGenericBase< OutputShape > *&fe) const
Definition: fem_context.h:1241
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)
Definition: fe_interface.C:523
const Elem & get_elem() const
Definition: fem_context.h:871
void resize(const unsigned int n)
Definition: dense_vector.h:355
std::vector< T > & get_values()
Definition: dense_vector.h:256
FEMFunctionWrapper(const FEMFunctionWrapper< Output > &fw)
The base class for all geometric element types.
Definition: elem.h:100
FEMFunctionWrapper(const FEMFunctionBase< Output > &f)
OrderWrapper order
Definition: fe_type.h:198
void set_algebraic_type(const AlgebraicType atype)
Definition: fem_context.h:948
static const Real TOLERANCE
Utility class for defining generic ranges for threading.
Definition: stored_range.h:52
OldSolutionBase(const libMesh::System &sys_in)
virtual Real hmax() const
Definition: elem.C:373
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()
Definition: elem.h:1779
virtual void elem_fe_reinit(const std::vector< Point > *const pts=nullptr)
Definition: fem_context.C:1362
virtual FEContinuity get_continuity() const =0
FEType get_fe_type() const
Definition: fe_abstract.h:429
Manages the degrees of freedom (DOFs) in a simulation.
Definition: dof_map.h:176
unsigned char edge
Definition: fem_context.h:984
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
Definition: fe_type.C:31
const std::vector< std::vector< OutputGradient > > & get_dphi() const
Definition: fe_base.h:215
const dof_id_type n_nodes
Definition: tecplot_io.C:68
spin_mutex spin_mtx
Definition: threads.C:29
A variable which is solved for in a System of equations.
Definition: variable.h:49
const Variable & variable(const unsigned int c) const
Definition: dof_map.h:1762
virtual void side_fe_reinit()
Definition: fem_context.C:1383
dof_id_type numeric_index_type
Definition: id_types.h:92
void eval_old_dofs(const FEMContext &, unsigned int, std::vector< Output >)
unsigned int n_vars(const unsigned int s, const unsigned int vg) const
Definition: dof_object.h:768
Manages consistently variables, degrees of freedom, and coefficient vectors.
Definition: system.h:92
const std::vector< Real > & get_JxW() const
Definition: fe_abstract.h:245
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)
Definition: fe_interface.C:590
const std::vector< dof_id_type > & get_dof_indices() const
Definition: diff_context.h:367
std::unique_ptr< FEMFunctionBase< Output > > _f
bool active_on_subdomain(subdomain_id_type sid) const
Definition: variable.h:136
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()
Definition: fem_context.C:1399
static unsigned int n_dofs_at_node(const unsigned int dim, const FEType &fe_t, const ElemType t, const unsigned int n)
Definition: fe_interface.C:473
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
Definition: dof_object.h:79
unsigned char side
Definition: fem_context.h:979
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
Definition: dense_matrix.h:808
void resize(const unsigned int new_m, const unsigned int new_n)
Definition: dense_matrix.h:792
void get_element_fe(unsigned int var, FEGenericBase< OutputShape > *&fe) const
Definition: fem_context.h:262
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.
Definition: dense_matrix.h:54
A geometric point in (x,y,z) space.
Definition: point.h:38
virtual numeric_index_type last_local_index() const =0
GenericProjector(const GenericProjector &in)
const std::set< unsigned char > & elem_dimensions() const
Definition: fem_context.h:913
virtual void zero() override
Definition: dense_vector.h:379
uint8_t dof_id_type
Definition: id_types.h:64
const std::vector< std::vector< OutputShape > > & get_phi() const
Definition: fe_base.h:207
const FEType & type() const
Definition: variable.h:119