libMesh
Public Types | Public Member Functions | Public Attributes | Protected Attributes | List of all members
libMesh::GenericProjector< FFunctor, GFunctor, FValue, ProjectionAction >::SortAndCopy Struct Reference

#include <generic_projector.h>

Inheritance diagram for libMesh::GenericProjector< FFunctor, GFunctor, FValue, ProjectionAction >::SortAndCopy:
[legend]

Public Types

typedef std::unordered_multimap< const Node *, std::tuple< const Elem *, unsigned short, var_set > > ves_multimap
 

Public Member Functions

 SortAndCopy (GenericProjector &p)
 
 SortAndCopy (SortAndCopy &other, Threads::split)
 
void operator() (const ConstElemRange &range)
 
void join (const SortAndCopy &other)
 
template<typename InsertInput , typename std::enable_if< std::is_same< typename ProjectionAction::InsertInput, InsertInput >::value, int >::type = 0>
void insert_ids (const std::vector< dof_id_type > &ids, const std::vector< InsertInput > &vals, processor_id_type pid)
 
template<typename InsertInput , typename std::enable_if< !std::is_same< typename ProjectionAction::InsertInput, InsertInput >::value, int >::type = 0>
void insert_ids (const std::vector< dof_id_type > &ids, const std::vector< InsertInput > &vals, processor_id_type pid)
 
void find_dofs_to_send (const Node &node, const Elem &elem, unsigned short node_num, const var_set &vars)
 
template<typename InsertInput , typename std::enable_if< std::is_same< typename ProjectionAction::InsertInput, InsertInput >::value, int >::type = 0>
void insert_id (dof_id_type id, const InsertInput &val, processor_id_type pid)
 
template<typename InsertInput , typename std::enable_if< !std::is_same< typename ProjectionAction::InsertInput, InsertInput >::value, int >::type = 0>
void insert_id (dof_id_type id, const InsertInput &val, processor_id_type pid)
 
template<typename InsertInput , typename std::enable_if< std::is_same< typename ProjectionAction::InsertInput, InsertInput >::value, int >::type = 0>
void insert_ids (const std::vector< dof_id_type > &ids, const std::vector< InsertInput > &vals, processor_id_type pid)
 
void join (const SubFunctor &other)
 

Public Attributes

ves_multimap vertices
 
ves_multimap edges
 
ves_multimap sides
 
std::vector< const Elem * > interiors
 
ProjectionAction action
 
FFunctor f
 
const Systemsystem
 
FEMContext context
 
GenericProjectorprojector
 
std::unordered_map< dof_id_type, std::pair< typename FFunctor::ValuePushType, processor_id_type > > new_ids_to_push
 
std::unordered_map< dof_id_type, typename FFunctor::ValuePushType > new_ids_to_save
 

Protected Attributes

std::vector< FEContinuityconts
 
std::vector< FEFieldTypefield_types
 

Detailed Description

template<typename FFunctor, typename GFunctor, typename FValue, typename ProjectionAction>
struct libMesh::GenericProjector< FFunctor, GFunctor, FValue, ProjectionAction >::SortAndCopy

Definition at line 280 of file generic_projector.h.

Member Typedef Documentation

◆ ves_multimap

template<typename FFunctor , typename GFunctor , typename FValue , typename ProjectionAction >
typedef std::unordered_multimap<const Node *, std::tuple<const Elem *, unsigned short, var_set> > libMesh::GenericProjector< FFunctor, GFunctor, FValue, ProjectionAction >::SortAndCopy::ves_multimap

Definition at line 300 of file generic_projector.h.

Constructor & Destructor Documentation

◆ SortAndCopy() [1/2]

template<typename FFunctor , typename GFunctor , typename FValue , typename ProjectionAction >
libMesh::GenericProjector< FFunctor, GFunctor, FValue, ProjectionAction >::SortAndCopy::SortAndCopy ( GenericProjector p)
inline

Definition at line 281 of file generic_projector.h.

281 : SubFunctor(p) {}

◆ SortAndCopy() [2/2]

template<typename FFunctor , typename GFunctor , typename FValue , typename ProjectionAction >
libMesh::GenericProjector< FFunctor, GFunctor, FValue, ProjectionAction >::SortAndCopy::SortAndCopy ( SortAndCopy other,
Threads::split   
)
inline

Definition at line 283 of file generic_projector.h.

283 : SubFunctor(other.projector) {}

Member Function Documentation

◆ find_dofs_to_send()

template<typename FFunctor , typename GFunctor , typename FValue , typename ProjectionAction >
void libMesh::GenericProjector< FFunctor, GFunctor, FValue, ProjectionAction >::SubFunctor::find_dofs_to_send ( const Node node,
const Elem elem,
unsigned short  node_num,
const var_set vars 
)
inherited

Definition at line 2845 of file generic_projector.h.

References libMesh::Elem::active(), libMesh::Variable::active_on_subdomain(), libMesh::DofMap::dof_indices(), libMesh::System::get_dof_map(), libMesh::System::get_mesh(), libMesh::DofObject::id(), libMesh::DofObject::invalid_processor_id, libMesh::libmesh_assert(), mesh, libMesh::Elem::node_ptr(), libMesh::ParallelObject::processor_id(), libMesh::DofObject::processor_id(), libMesh::Elem::subdomain_id(), libMesh::GenericProjector< FFunctor, GFunctor, FValue, ProjectionAction >::system, and libMesh::System::variable().

2846 {
2847  libmesh_assert (&node == elem.node_ptr(node_num));
2848 
2849  // Any ghosted node in our range might have an owner who needs our
2850  // data
2851  const processor_id_type owner = node.processor_id();
2852  if (owner != system.processor_id())
2853  {
2854  const MeshBase & mesh = system.get_mesh();
2855  const DofMap & dof_map = system.get_dof_map();
2856 
2857  // But let's check and see if we can be certain the owner can
2858  // compute any or all of its own dof coefficients on that node.
2859  std::vector<dof_id_type> node_dof_ids, patch_dof_ids;
2860  for (const auto & var : vars)
2861  {
2862  const Variable & variable = system.variable(var);
2863 
2864  if (!variable.active_on_subdomain(elem.subdomain_id()))
2865  continue;
2866 
2867  dof_map.dof_indices(elem, node_num, node_dof_ids, var);
2868  }
2869  libmesh_assert(std::is_sorted(node_dof_ids.begin(),
2870  node_dof_ids.end()));
2871  const std::vector<dof_id_type> & patch =
2872  (*this->projector.nodes_to_elem)[node.id()];
2873  for (const auto & elem_id : patch)
2874  {
2875  const Elem & patch_elem = mesh.elem_ref(elem_id);
2876  if (!patch_elem.active() || owner != patch_elem.processor_id())
2877  continue;
2878  dof_map.dof_indices(&patch_elem, patch_dof_ids);
2879  std::sort(patch_dof_ids.begin(), patch_dof_ids.end());
2880 
2881  // Remove any node_dof_ids that we see can be calculated on
2882  // this element
2883  std::vector<dof_id_type> diff_ids(node_dof_ids.size());
2884  auto it = std::set_difference(node_dof_ids.begin(), node_dof_ids.end(),
2885  patch_dof_ids.begin(), patch_dof_ids.end(), diff_ids.begin());
2886  diff_ids.resize(it-diff_ids.begin());
2887  node_dof_ids.swap(diff_ids);
2888  if (node_dof_ids.empty())
2889  break;
2890  }
2891 
2892  // Give ids_to_push default invalid pid: not yet computed
2893  for (auto id : node_dof_ids)
2895  }
2896 }
std::unordered_map< dof_id_type, std::pair< typename FFunctor::ValuePushType, processor_id_type > > new_ids_to_push
static constexpr processor_id_type invalid_processor_id
An invalid processor_id to distinguish DoFs that have not been assigned to a processor.
Definition: dof_object.h:484
const Variable & variable(unsigned int var) const
Return a constant reference to Variable var.
Definition: system.C:2704
NodesToElemMap * nodes_to_elem
MeshBase & mesh
const MeshBase & get_mesh() const
Definition: system.h:2401
uint8_t processor_id_type
libmesh_assert(ctx)
processor_id_type processor_id() const
const DofMap & get_dof_map() const
Definition: system.h:2417

◆ insert_id() [1/2]

template<typename FFunctor , typename GFunctor , typename FValue , typename ProjectionAction >
template<typename InsertInput , typename std::enable_if< std::is_same< typename ProjectionAction::InsertInput, InsertInput >::value, int >::type >
void libMesh::GenericProjector< FFunctor, GFunctor, FValue, ProjectionAction >::SubFunctor::insert_id ( dof_id_type  id,
const InsertInput &  val,
processor_id_type  pid 
)
inherited

Definition at line 1378 of file generic_projector.h.

1380 {
1381  libmesh_error_msg("ID insertion should only occur when the provided input matches that "
1382  "expected by the ProjectionAction");
1383 }

◆ insert_id() [2/2]

template<typename FFunctor , typename GFunctor , typename FValue , typename ProjectionAction >
template<typename InsertInput , typename std::enable_if< !std::is_same< typename ProjectionAction::InsertInput, InsertInput >::value, int >::type = 0>
void libMesh::GenericProjector< FFunctor, GFunctor, FValue, ProjectionAction >::SubFunctor::insert_id ( dof_id_type  id,
const InsertInput &  val,
processor_id_type  pid 
)
inherited

◆ insert_ids() [1/3]

template<typename FFunctor , typename GFunctor , typename FValue , typename ProjectionAction >
template<typename InsertInput , typename std::enable_if< std::is_same< typename ProjectionAction::InsertInput, InsertInput >::value, int >::type >
void libMesh::GenericProjector< FFunctor, GFunctor, FValue, ProjectionAction >::SubFunctor::insert_ids ( const std::vector< dof_id_type > &  ids,
const std::vector< InsertInput > &  vals,
processor_id_type  pid 
)
inherited

Definition at line 1420 of file generic_projector.h.

1424 {
1425  libmesh_error_msg("ID insertion should only occur when the provided input matches that "
1426  "expected by the ProjectionAction");
1427 }

◆ insert_ids() [2/3]

template<typename FFunctor , typename GFunctor , typename FValue , typename ProjectionAction >
template<typename InsertInput , typename std::enable_if< std::is_same< typename ProjectionAction::InsertInput, InsertInput >::value, int >::type = 0>
void libMesh::GenericProjector< FFunctor, GFunctor, FValue, ProjectionAction >::SubFunctor::insert_ids ( typename InsertInput  ,
typename std::enable_if< std::is_same< typename ProjectionAction::InsertInput, InsertInput >::value, int >::type  = 0 
)

Definition at line 1420 of file generic_projector.h.

1424 {
1425  libmesh_error_msg("ID insertion should only occur when the provided input matches that "
1426  "expected by the ProjectionAction");
1427 }

◆ insert_ids() [3/3]

template<typename FFunctor , typename GFunctor , typename FValue , typename ProjectionAction >
template<typename InsertInput , typename std::enable_if< !std::is_same< typename ProjectionAction::InsertInput, InsertInput >::value, int >::type = 0>
void libMesh::GenericProjector< FFunctor, GFunctor, FValue, ProjectionAction >::SubFunctor::insert_ids ( typename InsertInput  ,
typename std::enable_if< !std::is_same< typename ProjectionAction::InsertInput, InsertInput >::value, int >::type  = 0 
)

◆ join() [1/2]

template<typename FFunctor , typename GFunctor , typename FValue , typename ProjectionAction >
void libMesh::GenericProjector< FFunctor, GFunctor, FValue, ProjectionAction >::SubFunctor::join ( const SubFunctor other)
inherited

Definition at line 1471 of file generic_projector.h.

References libMesh::GenericProjector< FFunctor, GFunctor, FValue, ProjectionAction >::SubFunctor::new_ids_to_push, and libMesh::GenericProjector< FFunctor, GFunctor, FValue, ProjectionAction >::SubFunctor::new_ids_to_save.

Referenced by libMesh::GenericProjector< FFunctor, GFunctor, FValue, ProjectionAction >::SortAndCopy::join().

1472 {
1473  new_ids_to_push.insert(other.new_ids_to_push.begin(), other.new_ids_to_push.end());
1474  new_ids_to_save.insert(other.new_ids_to_save.begin(), other.new_ids_to_save.end());
1475 }
std::unordered_map< dof_id_type, std::pair< typename FFunctor::ValuePushType, processor_id_type > > new_ids_to_push
std::unordered_map< dof_id_type, typename FFunctor::ValuePushType > new_ids_to_save

◆ join() [2/2]

template<typename FFunctor , typename GFunctor , typename FValue , typename ProjectionAction >
void libMesh::GenericProjector< FFunctor, GFunctor, FValue, ProjectionAction >::SortAndCopy::join ( const SortAndCopy other)

Definition at line 1942 of file generic_projector.h.

References libMesh::as_range(), libMesh::GenericProjector< FFunctor, GFunctor, FValue, ProjectionAction >::SortAndCopy::edges, libMesh::GenericProjector< FFunctor, GFunctor, FValue, ProjectionAction >::SortAndCopy::interiors, libMesh::GenericProjector< FFunctor, GFunctor, FValue, ProjectionAction >::SubFunctor::join(), libMesh::GenericProjector< FFunctor, GFunctor, FValue, ProjectionAction >::SortAndCopy::sides, and libMesh::GenericProjector< FFunctor, GFunctor, FValue, ProjectionAction >::SortAndCopy::vertices.

1943 {
1944  auto merge_multimaps = [](ves_multimap & self, const ves_multimap & other_mm)
1945  {
1946  for (const auto & pair : other_mm)
1947  {
1948  const Node * node = pair.first;
1949  auto remaining_vars = std::get<2>(pair.second);
1950 
1951  auto my_range = self.equal_range(node);
1952  for (const auto & v_ent : as_range(my_range))
1953  for (const unsigned int var_covered :
1954  std::get<2>(v_ent.second))
1955  remaining_vars.erase(var_covered);
1956 
1957  if (!remaining_vars.empty())
1958  self.emplace
1959  (node, std::make_tuple(std::get<0>(pair.second),
1960  std::get<1>(pair.second),
1961  std::move(remaining_vars)));
1962  }
1963  };
1964 
1965  merge_multimaps(vertices, other.vertices);
1966  merge_multimaps(edges, other.edges);
1967  merge_multimaps(sides, other.sides);
1968 
1969  std::sort(interiors.begin(), interiors.end());
1970  std::vector<const Elem *> other_interiors = other.interiors;
1971  std::sort(other_interiors.begin(), other_interiors.end());
1972  std::vector<const Elem *> merged_interiors;
1973  std::set_union(interiors.begin(), interiors.end(),
1974  other_interiors.begin(), other_interiors.end(),
1975  std::back_inserter(merged_interiors));
1976  interiors.swap(merged_interiors);
1977 
1978  SubFunctor::join(other);
1979 }
std::unordered_multimap< const Node *, std::tuple< const Elem *, unsigned short, var_set > > ves_multimap
void join(const SubFunctor &other)
std::vector< const Elem * > interiors
SimpleRange< IndexType > as_range(const std::pair< IndexType, IndexType > &p)
Helper function that allows us to treat a homogenous pair as a range.
Definition: simple_range.h:57

◆ operator()()

template<typename FFunctor , typename GFunctor , typename FValue , typename ProjectionAction >
void libMesh::GenericProjector< FFunctor, GFunctor, FValue, ProjectionAction >::SortAndCopy::operator() ( const ConstElemRange range)

Definition at line 1481 of file generic_projector.h.

References libMesh::Variable::active_on_subdomain(), libMesh::as_range(), libMesh::C0POLYHEDRON, libMesh::CONSTANT, dim, libMesh::FEInterface::extra_hanging_dofs(), libMesh::FEType::family, libMesh::DofObject::get_old_dof_object(), libMesh::Elem::JUST_COARSENED, libMesh::Elem::JUST_REFINED, libMesh::LAGRANGE, libMesh::libmesh_assert(), libMesh::make_range(), libMesh::MONOMIAL, libMesh::FEInterface::n_dofs_at_node(), libMesh::FEInterface::n_dofs_per_elem(), n_nodes, libMesh::NODEELEM, libMesh::System::number(), libMesh::FEType::order, libMesh::FEType::p_refinement, libMesh::DofObject::processor_id(), libMesh::RATIONAL_BERNSTEIN, libMesh::GenericProjector< FFunctor, GFunctor, FValue, ProjectionAction >::system, libMesh::Variable::system(), libMesh::Variable::type(), libMesh::System::variable(), and libMesh::XYZ.

1482 {
1483  LOG_SCOPE ("SortAndCopy::operator()","GenericProjector");
1484 
1485  // Look at all the elements in the range. Directly copy values from
1486  // unchanged elements. For other elements, determine sets of
1487  // vertices, edge nodes, and side nodes to project.
1488  //
1489  // As per our other weird nomenclature, "sides" means faces in 3D
1490  // and edges in 2D, and "edges" gets skipped in 2D
1491  //
1492  // This gets tricky in the case of subdomain-restricted
1493  // variables, for which we might need to do the same projection
1494  // from different elements when evaluating different variables.
1495  // We'll keep track of which variables can be projected from which
1496  // elements.
1497 
1498  // If we copy DoFs on a node, keep track of it so we don't bother
1499  // with any redundant interpolations or projections later.
1500  //
1501  // We still need to keep track of *which* variables get copied,
1502  // since we may be able to copy elements which lack some
1503  // subdomain-restricted variables.
1504  //
1505  // For extra_hanging_dofs FE types, we'll keep track of which
1506  // variables were copied from vertices, and which from edges/sides,
1507  // because those types need copies made from *both* on hanging
1508  // nodes.
1509  std::unordered_map<const Node *, std::pair<var_set, var_set>> copied_nodes;
1510 
1511  const unsigned int sys_num = system.number();
1512 
1513  // At hanging nodes for variables with extra hanging dofs we'll need
1514  // to do projections *separately* from vertex elements and side/edge
1515  // elements.
1516  std::vector<unsigned short> extra_hanging_dofs;
1517  bool all_extra_hanging_dofs = true;
1518  for (auto v_num : this->projector.variables)
1519  {
1520  if (extra_hanging_dofs.size() <= v_num)
1521  extra_hanging_dofs.resize(v_num+1, false);
1522  extra_hanging_dofs[v_num] =
1524 
1525  if (!extra_hanging_dofs[v_num])
1526  all_extra_hanging_dofs = false;
1527  }
1528 
1529  for (const auto & elem : range)
1530  {
1531  // If we're doing AMR, we might be able to copy more DoFs than
1532  // we interpolate or project.
1533  bool copy_this_elem = false;
1534 
1535 #ifdef LIBMESH_ENABLE_AMR
1536  // If we're projecting from an old grid
1537  if (f.is_grid_projection())
1538  {
1539  // If this element doesn't have an old_dof_object, but it
1540  // wasn't just refined or just coarsened into activity, then
1541  // it must be newly added, so the user is responsible for
1542  // setting the new dofs on it during a grid projection.
1543  const DofObject * old_dof_object = elem->get_old_dof_object();
1544  const Elem::RefinementState h_flag = elem->refinement_flag();
1545  const Elem::RefinementState p_flag = elem->p_refinement_flag();
1546  if (!old_dof_object &&
1547  h_flag != Elem::JUST_REFINED &&
1548  h_flag != Elem::JUST_COARSENED)
1549  continue;
1550 
1551  // If this is an unchanged element, just copy everything
1552  if (h_flag != Elem::JUST_REFINED &&
1553  h_flag != Elem::JUST_COARSENED &&
1554  p_flag != Elem::JUST_REFINED &&
1555  p_flag != Elem::JUST_COARSENED)
1556  copy_this_elem = true;
1557  else
1558  {
1559  bool reinitted = false;
1560 
1561  const unsigned int p_level = elem->p_level();
1562 
1563  // If this element has a low order monomial which has
1564  // merely been h refined, copy it.
1565  const bool copy_possible =
1566  p_level == 0 &&
1567  h_flag != Elem::JUST_COARSENED &&
1568  p_flag != Elem::JUST_COARSENED;
1569 
1570  std::vector<typename FFunctor::ValuePushType> Ue(1);
1571  std::vector<dof_id_type> elem_dof_ids(1);
1572 
1573  for (auto v_num : this->projector.variables)
1574  {
1575  const Variable & var = system.variable(v_num);
1576  if (!var.active_on_subdomain(elem->subdomain_id()))
1577  continue;
1578  const FEType fe_type = var.type();
1579 
1580  if (fe_type.family == MONOMIAL &&
1581  fe_type.order == CONSTANT &&
1582  copy_possible)
1583  {
1584  if (!reinitted)
1585  {
1586  reinitted = true;
1587  context.pre_fe_reinit(system, elem);
1588  }
1589 
1590  f.eval_old_dofs(*elem, fe_type, sys_num, v_num,
1591  elem_dof_ids, Ue);
1592 
1593  action.insert(elem_dof_ids[0], Ue[0]);
1594  }
1595  }
1596  }
1597  }
1598 #endif // LIBMESH_ENABLE_AMR
1599 
1600  const int dim = elem->dim();
1601 
1602  const unsigned int n_vertices = elem->n_vertices();
1603  const unsigned int n_edges = elem->n_edges();
1604  const unsigned int n_nodes = elem->n_nodes();
1605 
1606  // In 1-D we already handle our sides as vertices
1607  const unsigned int n_sides = (dim > 1) * elem->n_sides();
1608 
1609  // What variables are supported on each kind of node on this elem?
1610  var_set vertex_vars, edge_vars, side_vars;
1611 
1612  // If we have non-vertex nodes, the first is an edge node, but
1613  // if we're in 2D we'll call that a side node
1614  const bool has_poly_midnode = (elem->type() == C0POLYHEDRON) && (n_nodes == n_vertices + 1);
1615  const bool has_edge_nodes = (n_nodes > n_vertices + has_poly_midnode && dim > 2);
1616 
1617  // If we have even more nodes, the next is a side node.
1618  const bool has_side_nodes =
1619  (n_nodes > n_vertices + ((dim > 2) * n_edges));
1620 
1621  // We may be out of nodes at this point or we have interior
1622  // nodes which may have DoFs to project too
1623  const bool has_interior_nodes =
1624  (n_nodes > n_vertices + ((dim > 2) * n_edges) + n_sides);
1625 
1626  for (auto v_num : this->projector.variables)
1627  {
1628  const Variable & var = this->projector.system.variable(v_num);
1629  if (!var.active_on_subdomain(elem->subdomain_id()))
1630  continue;
1631  const FEType fe_type = var.type();
1632  const bool add_p_level = fe_type.p_refinement;
1633 
1634  // If we're trying to do projections on an isogeometric
1635  // analysis mesh, only the finite element nodes constrained
1636  // by those spline nodes truly have delta function degrees
1637  // of freedom. We'll have to back out the spline degrees of
1638  // freedom indirectly later.
1639  if (fe_type.family == RATIONAL_BERNSTEIN &&
1640  elem->type() == NODEELEM)
1641  continue;
1642 
1643  if (FEInterface::n_dofs_at_node(fe_type, elem, 0, add_p_level))
1644  vertex_vars.insert(vertex_vars.end(), v_num);
1645 
1646  // The first non-vertex node is always an edge node if those
1647  // exist. All edge nodes have the same number of DoFs
1648  if (has_edge_nodes)
1649  if (FEInterface::n_dofs_at_node(fe_type, elem, n_vertices, add_p_level))
1650  edge_vars.insert(edge_vars.end(), v_num);
1651 
1652  if (has_side_nodes)
1653  {
1654  if (dim != 3)
1655  {
1656  if (FEInterface::n_dofs_at_node(fe_type, elem, n_vertices, add_p_level))
1657  side_vars.insert(side_vars.end(), v_num);
1658  }
1659  else
1660  // In 3D, not all face nodes always have the same number of
1661  // DoFs! We'll loop over all sides to be safe.
1662  for (unsigned int n = 0; n != n_nodes; ++n)
1663  if (elem->is_face(n))
1664  if (FEInterface::n_dofs_at_node(fe_type, elem, n, add_p_level))
1665  {
1666  side_vars.insert(side_vars.end(), v_num);
1667  break;
1668  }
1669  }
1670 
1671  if (FEInterface::n_dofs_per_elem(fe_type, elem, add_p_level) ||
1672  (has_interior_nodes &&
1673  FEInterface::n_dofs_at_node(fe_type, elem, n_nodes-1, add_p_level)))
1674  {
1675 #ifdef LIBMESH_ENABLE_AMR
1676  // We may have already just copied constant monomials,
1677  // or we may be about to copy the whole element
1678  if ((f.is_grid_projection() &&
1679  fe_type.family == MONOMIAL &&
1680  fe_type.order == CONSTANT &&
1681  elem->p_level() == 0 &&
1682  elem->refinement_flag() != Elem::JUST_COARSENED &&
1683  elem->p_refinement_flag() != Elem::JUST_COARSENED)
1684  || copy_this_elem
1685  )
1686  continue;
1687 #endif // LIBMESH_ENABLE_AMR
1688 
1689  // We need to project any other variables
1690  if (interiors.empty() || interiors.back() != elem)
1691  interiors.push_back(elem);
1692  }
1693  }
1694 
1695  // We'll use a greedy algorithm in most cases: if another
1696  // element has already claimed some of our DoFs, we'll let it do
1697  // the work.
1698  auto erase_covered_vars = []
1699  (const Node * node, var_set & remaining, const ves_multimap & covered)
1700  {
1701  auto covered_range = covered.equal_range(node);
1702  for (const auto & v_ent : as_range(covered_range))
1703  for (const unsigned int var_covered :
1704  std::get<2>(v_ent.second))
1705  remaining.erase(var_covered);
1706  };
1707 
1708  auto erase_nonhanging_vars = [&extra_hanging_dofs]
1709  (const Node * node, var_set & remaining, const ves_multimap & covered)
1710  {
1711  auto covered_range = covered.equal_range(node);
1712  for (const auto & v_ent : as_range(covered_range))
1713  for (const unsigned int var_covered :
1714  std::get<2>(v_ent.second))
1715  if (!extra_hanging_dofs[var_covered])
1716  remaining.erase(var_covered);
1717  };
1718 
1719  auto erase_copied_vars = [&copied_nodes, &extra_hanging_dofs]
1720  (const Node * node, bool is_vertex, var_set & remaining)
1721  {
1722  auto copying_range = copied_nodes.equal_range(node);
1723  for (const auto & v_ent : as_range(copying_range))
1724  {
1725  for (const unsigned int var_covered :
1726  v_ent.second.first)
1727  if (is_vertex || !extra_hanging_dofs[var_covered])
1728  remaining.erase(var_covered);
1729 
1730  for (const unsigned int var_covered :
1731  v_ent.second.second)
1732  if (!is_vertex || !extra_hanging_dofs[var_covered])
1733  remaining.erase(var_covered);
1734  }
1735  };
1736 
1737  // Treat polyhedron midnode as a vertex
1738  // NOTE: if we start having edge or side nodes on polyhedra, we need to use that +1 offset
1739  // in the edge and side nodes code as well!
1740 #ifndef NDEBUG
1741  for (auto v_num : this->projector.variables)
1742  {
1743  const auto & family = this->projector.system.variable(v_num).type().family;
1744  // Add to the list once known to be correctly functioning with the midnode
1745  libmesh_assert(!has_poly_midnode || (family == LAGRANGE || family == MONOMIAL || family == XYZ));
1746  }
1747 #endif
1748  for (const auto v : make_range(n_vertices + has_poly_midnode))
1749  {
1750  const Node * node = elem->node_ptr(v);
1751 
1752  auto remaining_vars = vertex_vars;
1753 
1754  erase_covered_vars(node, remaining_vars, vertices);
1755 
1756  if (remaining_vars.empty())
1757  continue;
1758 
1759  if (!all_extra_hanging_dofs)
1760  {
1761  erase_nonhanging_vars(node, remaining_vars, edges);
1762  if (remaining_vars.empty())
1763  continue;
1764 
1765  erase_nonhanging_vars(node, remaining_vars, sides);
1766  if (remaining_vars.empty())
1767  continue;
1768  }
1769 
1770  erase_copied_vars(node, true, remaining_vars);
1771  if (remaining_vars.empty())
1772  continue;
1773 
1774  if (copy_this_elem)
1775  {
1776  std::vector<dof_id_type> node_dof_ids;
1777  std::vector<typename FFunctor::ValuePushType> values;
1778 
1779  for (auto var : remaining_vars)
1780  {
1781  f.eval_old_dofs(*elem, v, var, node_dof_ids, values);
1782  insert_ids(node_dof_ids, values, node->processor_id());
1783  }
1784  copied_nodes[node].first.insert(remaining_vars.begin(),
1785  remaining_vars.end());
1786  this->find_dofs_to_send(*node, *elem, v, remaining_vars);
1787  }
1788  else
1789  vertices.emplace
1790  (node, std::make_tuple(elem, v, std::move(remaining_vars)));
1791  }
1792 
1793  if (has_edge_nodes)
1794  {
1795  for (unsigned int e=0; e != n_edges; ++e)
1796  {
1797  const Node * node = elem->node_ptr(n_vertices+e);
1798 
1799  auto remaining_vars = edge_vars;
1800 
1801  erase_covered_vars(node, remaining_vars, edges);
1802  if (remaining_vars.empty())
1803  continue;
1804 
1805  erase_covered_vars(node, remaining_vars, sides);
1806  if (remaining_vars.empty())
1807  continue;
1808 
1809  if (!all_extra_hanging_dofs)
1810  {
1811  erase_nonhanging_vars(node, remaining_vars, vertices);
1812  if (remaining_vars.empty())
1813  continue;
1814  }
1815 
1816  erase_copied_vars(node, false, remaining_vars);
1817  if (remaining_vars.empty())
1818  continue;
1819 
1820  if (copy_this_elem)
1821  {
1822  std::vector<dof_id_type> edge_dof_ids;
1823  std::vector<typename FFunctor::ValuePushType> values;
1824 
1825  for (auto var : remaining_vars)
1826  {
1827  f.eval_old_dofs(*elem, n_vertices+e, var, edge_dof_ids, values);
1828  insert_ids(edge_dof_ids, values, node->processor_id());
1829  }
1830 
1831  copied_nodes[node].second.insert(remaining_vars.begin(),
1832  remaining_vars.end());
1833  this->find_dofs_to_send(*node, *elem, n_vertices+e, remaining_vars);
1834  }
1835  else
1836  edges.emplace
1837  (node, std::make_tuple(elem, e, std::move(remaining_vars)));
1838  }
1839  }
1840 
1841  if (has_side_nodes)
1842  {
1843  for (unsigned int side=0; side != n_sides; ++side)
1844  {
1845  const Node * node = nullptr;
1846  unsigned short node_num = n_vertices+(dim>2)*n_edges+side;
1847  if (dim != 3)
1848  node = elem->node_ptr(node_num);
1849  else
1850  {
1851  // In 3D only some sides may have nodes
1852  for (unsigned int n = 0; n != n_nodes; ++n)
1853  {
1854  if (!elem->is_face(n))
1855  continue;
1856 
1857  if (elem->is_node_on_side(n, side))
1858  {
1859  node_num = n;
1860  node = elem->node_ptr(node_num);
1861  break;
1862  }
1863  }
1864  }
1865 
1866  if (!node)
1867  continue;
1868 
1869  auto remaining_vars = side_vars;
1870 
1871  erase_covered_vars(node, remaining_vars, edges);
1872  if (remaining_vars.empty())
1873  continue;
1874 
1875  erase_covered_vars(node, remaining_vars, sides);
1876  if (remaining_vars.empty())
1877  continue;
1878 
1879  if (!all_extra_hanging_dofs)
1880  {
1881  erase_nonhanging_vars(node, remaining_vars, vertices);
1882  if (remaining_vars.empty())
1883  continue;
1884  }
1885 
1886  erase_copied_vars(node, false, remaining_vars);
1887  if (remaining_vars.empty())
1888  continue;
1889 
1890  if (copy_this_elem)
1891  {
1892  std::vector<dof_id_type> side_dof_ids;
1893  std::vector<typename FFunctor::ValuePushType> values;
1894 
1895  for (auto var : remaining_vars)
1896  {
1897  f.eval_old_dofs(*elem, node_num, var, side_dof_ids, values);
1898  insert_ids(side_dof_ids, values, node->processor_id());
1899  }
1900 
1901  copied_nodes[node].second.insert(remaining_vars.begin(),
1902  remaining_vars.end());
1903  this->find_dofs_to_send(*node, *elem, node_num, remaining_vars);
1904  }
1905  else
1906  sides.emplace
1907  (node, std::make_tuple(elem, side, std::move(remaining_vars)));
1908  }
1909  }
1910 
1911  // Elements with elemental dofs might need those copied too.
1912  if (copy_this_elem)
1913  {
1914  std::vector<typename FFunctor::ValuePushType> U;
1915  std::vector<dof_id_type> dof_ids;
1916 
1917  for (auto v_num : this->projector.variables)
1918  {
1919  const Variable & var = system.variable(v_num);
1920  if (!var.active_on_subdomain(elem->subdomain_id()))
1921  continue;
1922  FEType fe_type = var.type();
1923 
1924  f.eval_old_dofs(*elem, fe_type, sys_num, v_num,
1925  dof_ids, U);
1926  action.insert(dof_ids, U);
1927 
1928  if (has_interior_nodes)
1929  {
1930  f.eval_old_dofs(*elem, n_nodes-1, v_num, dof_ids, U);
1931  action.insert(dof_ids, U);
1932  }
1933  }
1934  }
1935  }
1936 }
static unsigned int n_dofs_per_elem(const unsigned int dim, const FEType &fe_t, const ElemType t)
Definition: fe_interface.C:531
FEFamily family
The type of finite element.
Definition: fe_type.h:228
bool p_refinement
Whether or not the finite elements for this type increase their p refinement level on geometric eleme...
Definition: fe_type.h:292
const Variable & variable(unsigned int var) const
Return a constant reference to Variable var.
Definition: system.C:2704
virtual void pre_fe_reinit(const System &, const Elem *e)
Reinitializes local data vectors/matrices on the current geometric element.
Definition: fem_context.C:1683
unsigned int dim
std::unordered_multimap< const Node *, std::tuple< const Elem *, unsigned short, var_set > > ves_multimap
RefinementState
Enumeration of possible element refinement states.
Definition: elem.h:1443
std::vector< const Elem * > interiors
const dof_id_type n_nodes
Definition: tecplot_io.C:67
unsigned int number() const
Definition: system.h:2393
static bool extra_hanging_dofs(const FEType &fe_t)
void insert_ids(const std::vector< dof_id_type > &ids, const std::vector< InsertInput > &vals, processor_id_type pid)
SimpleRange< IndexType > as_range(const std::pair< IndexType, IndexType > &p)
Helper function that allows us to treat a homogenous pair as a range.
Definition: simple_range.h:57
libmesh_assert(ctx)
const std::vector< unsigned int > & variables
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:437
void find_dofs_to_send(const Node &node, const Elem &elem, unsigned short node_num, const var_set &vars)
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...
Definition: int_range.h:176
std::set< unsigned int > var_set
const FEType & type() const
Definition: variable.h:144

Member Data Documentation

◆ action

template<typename FFunctor , typename GFunctor , typename FValue , typename ProjectionAction >
ProjectionAction libMesh::GenericProjector< FFunctor, GFunctor, FValue, ProjectionAction >::SubFunctor::action

Definition at line 231 of file generic_projector.h.

◆ context

template<typename FFunctor , typename GFunctor , typename FValue , typename ProjectionAction >
FEMContext libMesh::GenericProjector< FFunctor, GFunctor, FValue, ProjectionAction >::SubFunctor::context

Definition at line 236 of file generic_projector.h.

◆ conts

template<typename FFunctor , typename GFunctor , typename FValue , typename ProjectionAction >
std::vector<FEContinuity> libMesh::GenericProjector< FFunctor, GFunctor, FValue, ProjectionAction >::SubFunctor::conts
protectedinherited

Definition at line 239 of file generic_projector.h.

◆ edges

template<typename FFunctor , typename GFunctor , typename FValue , typename ProjectionAction >
ves_multimap libMesh::GenericProjector< FFunctor, GFunctor, FValue, ProjectionAction >::SortAndCopy::edges

◆ f

template<typename FFunctor , typename GFunctor , typename FValue , typename ProjectionAction >
FFunctor libMesh::GenericProjector< FFunctor, GFunctor, FValue, ProjectionAction >::SubFunctor::f

Definition at line 232 of file generic_projector.h.

◆ field_types

template<typename FFunctor , typename GFunctor , typename FValue , typename ProjectionAction >
std::vector<FEFieldType> libMesh::GenericProjector< FFunctor, GFunctor, FValue, ProjectionAction >::SubFunctor::field_types
protectedinherited

Definition at line 240 of file generic_projector.h.

◆ interiors

template<typename FFunctor , typename GFunctor , typename FValue , typename ProjectionAction >
std::vector<const Elem *> libMesh::GenericProjector< FFunctor, GFunctor, FValue, ProjectionAction >::SortAndCopy::interiors

◆ new_ids_to_push

template<typename FFunctor , typename GFunctor , typename FValue , typename ProjectionAction >
std::unordered_map<dof_id_type, std::pair<typename FFunctor::ValuePushType, processor_id_type> > libMesh::GenericProjector< FFunctor, GFunctor, FValue, ProjectionAction >::SubFunctor::new_ids_to_push
inherited

◆ new_ids_to_save

template<typename FFunctor , typename GFunctor , typename FValue , typename ProjectionAction >
std::unordered_map<dof_id_type, typename FFunctor::ValuePushType> libMesh::GenericProjector< FFunctor, GFunctor, FValue, ProjectionAction >::SubFunctor::new_ids_to_save
inherited

◆ projector

template<typename FFunctor , typename GFunctor , typename FValue , typename ProjectionAction >
GenericProjector& libMesh::GenericProjector< FFunctor, GFunctor, FValue, ProjectionAction >::SubFunctor::projector
inherited

Definition at line 170 of file generic_projector.h.

◆ sides

template<typename FFunctor , typename GFunctor , typename FValue , typename ProjectionAction >
ves_multimap libMesh::GenericProjector< FFunctor, GFunctor, FValue, ProjectionAction >::SortAndCopy::sides

◆ system

template<typename FFunctor , typename GFunctor , typename FValue , typename ProjectionAction >
const System& libMesh::GenericProjector< FFunctor, GFunctor, FValue, ProjectionAction >::SubFunctor::system

Definition at line 242 of file generic_projector.h.

◆ vertices

template<typename FFunctor , typename GFunctor , typename FValue , typename ProjectionAction >
ves_multimap libMesh::GenericProjector< FFunctor, GFunctor, FValue, ProjectionAction >::SortAndCopy::vertices

The documentation for this struct was generated from the following file: