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 2839 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::Parallel::Utils::is_sorted(), 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().

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

◆ 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 1932 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.

1933 {
1934  auto merge_multimaps = [](ves_multimap & self, const ves_multimap & other_mm)
1935  {
1936  for (const auto & pair : other_mm)
1937  {
1938  const Node * node = pair.first;
1939  auto remaining_vars = std::get<2>(pair.second);
1940 
1941  auto my_range = self.equal_range(node);
1942  for (const auto & v_ent : as_range(my_range))
1943  for (const unsigned int var_covered :
1944  std::get<2>(v_ent.second))
1945  remaining_vars.erase(var_covered);
1946 
1947  if (!remaining_vars.empty())
1948  self.emplace
1949  (node, std::make_tuple(std::get<0>(pair.second),
1950  std::get<1>(pair.second),
1951  std::move(remaining_vars)));
1952  }
1953  };
1954 
1955  merge_multimaps(vertices, other.vertices);
1956  merge_multimaps(edges, other.edges);
1957  merge_multimaps(sides, other.sides);
1958 
1959  std::sort(interiors.begin(), interiors.end());
1960  std::vector<const Elem *> other_interiors = other.interiors;
1961  std::sort(other_interiors.begin(), other_interiors.end());
1962  std::vector<const Elem *> merged_interiors;
1963  std::set_union(interiors.begin(), interiors.end(),
1964  other_interiors.begin(), other_interiors.end(),
1965  std::back_inserter(merged_interiors));
1966  interiors.swap(merged_interiors);
1967 
1968  SubFunctor::join(other);
1969 }
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::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::MONOMIAL, libMesh::FEInterface::n_dofs_at_node(), libMesh::FEInterface::n_dofs_per_elem(), n_nodes, libMesh::NODEELEM, libMesh::System::number(), libMesh::FEType::order, libMesh::DofObject::processor_id(), libMesh::RATIONAL_BERNSTEIN, libMesh::GenericProjector< FFunctor, GFunctor, FValue, ProjectionAction >::system, libMesh::Variable::system(), libMesh::Variable::type(), and libMesh::System::variable().

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_edge_nodes = (n_nodes > n_vertices && dim > 2);
1615 
1616  // If we have even more nodes, the next is a side node.
1617  const bool has_side_nodes =
1618  (n_nodes > n_vertices + ((dim > 2) * n_edges));
1619 
1620  // We may be out of nodes at this point or we have interior
1621  // nodes which may have DoFs to project too
1622  const bool has_interior_nodes =
1623  (n_nodes > n_vertices + ((dim > 2) * n_edges) + n_sides);
1624 
1625  for (auto v_num : this->projector.variables)
1626  {
1627  const Variable & var = this->projector.system.variable(v_num);
1628  if (!var.active_on_subdomain(elem->subdomain_id()))
1629  continue;
1630  const FEType fe_type = var.type();
1631  const auto & dof_map = this->projector.system.get_dof_map();
1632  const auto vg = dof_map.var_group_from_var_number(v_num);
1633  const bool add_p_level = dof_map.should_p_refine(vg);
1634 
1635  // If we're trying to do projections on an isogeometric
1636  // analysis mesh, only the finite element nodes constrained
1637  // by those spline nodes truly have delta function degrees
1638  // of freedom. We'll have to back out the spline degrees of
1639  // freedom indirectly later.
1640  if (fe_type.family == RATIONAL_BERNSTEIN &&
1641  elem->type() == NODEELEM)
1642  continue;
1643 
1644  if (FEInterface::n_dofs_at_node(fe_type, elem, 0, add_p_level))
1645  vertex_vars.insert(vertex_vars.end(), v_num);
1646 
1647  // The first non-vertex node is always an edge node if those
1648  // exist. All edge nodes have the same number of DoFs
1649  if (has_edge_nodes)
1650  if (FEInterface::n_dofs_at_node(fe_type, elem, n_vertices, add_p_level))
1651  edge_vars.insert(edge_vars.end(), v_num);
1652 
1653  if (has_side_nodes)
1654  {
1655  if (dim != 3)
1656  {
1657  if (FEInterface::n_dofs_at_node(fe_type, elem, n_vertices, add_p_level))
1658  side_vars.insert(side_vars.end(), v_num);
1659  }
1660  else
1661  // In 3D, not all face nodes always have the same number of
1662  // DoFs! We'll loop over all sides to be safe.
1663  for (unsigned int n = 0; n != n_nodes; ++n)
1664  if (elem->is_face(n))
1665  if (FEInterface::n_dofs_at_node(fe_type, elem, n, add_p_level))
1666  {
1667  side_vars.insert(side_vars.end(), v_num);
1668  break;
1669  }
1670  }
1671 
1672  if (FEInterface::n_dofs_per_elem(fe_type, elem, add_p_level) ||
1673  (has_interior_nodes &&
1674  FEInterface::n_dofs_at_node(fe_type, elem, n_nodes-1, add_p_level)))
1675  {
1676 #ifdef LIBMESH_ENABLE_AMR
1677  // We may have already just copied constant monomials,
1678  // or we may be about to copy the whole element
1679  if ((f.is_grid_projection() &&
1680  fe_type.family == MONOMIAL &&
1681  fe_type.order == CONSTANT &&
1682  elem->p_level() == 0 &&
1683  elem->refinement_flag() != Elem::JUST_COARSENED &&
1684  elem->p_refinement_flag() != Elem::JUST_COARSENED)
1685  || copy_this_elem
1686  )
1687  continue;
1688 #endif // LIBMESH_ENABLE_AMR
1689 
1690  // We need to project any other variables
1691  if (interiors.empty() || interiors.back() != elem)
1692  interiors.push_back(elem);
1693  }
1694  }
1695 
1696  // We'll use a greedy algorithm in most cases: if another
1697  // element has already claimed some of our DoFs, we'll let it do
1698  // the work.
1699  auto erase_covered_vars = []
1700  (const Node * node, var_set & remaining, const ves_multimap & covered)
1701  {
1702  auto covered_range = covered.equal_range(node);
1703  for (const auto & v_ent : as_range(covered_range))
1704  for (const unsigned int var_covered :
1705  std::get<2>(v_ent.second))
1706  remaining.erase(var_covered);
1707  };
1708 
1709  auto erase_nonhanging_vars = [&extra_hanging_dofs]
1710  (const Node * node, var_set & remaining, const ves_multimap & covered)
1711  {
1712  auto covered_range = covered.equal_range(node);
1713  for (const auto & v_ent : as_range(covered_range))
1714  for (const unsigned int var_covered :
1715  std::get<2>(v_ent.second))
1716  if (!extra_hanging_dofs[var_covered])
1717  remaining.erase(var_covered);
1718  };
1719 
1720  auto erase_copied_vars = [&copied_nodes, &extra_hanging_dofs]
1721  (const Node * node, bool is_vertex, var_set & remaining)
1722  {
1723  auto copying_range = copied_nodes.equal_range(node);
1724  for (const auto & v_ent : as_range(copying_range))
1725  {
1726  for (const unsigned int var_covered :
1727  v_ent.second.first)
1728  if (is_vertex || !extra_hanging_dofs[var_covered])
1729  remaining.erase(var_covered);
1730 
1731  for (const unsigned int var_covered :
1732  v_ent.second.second)
1733  if (!is_vertex || !extra_hanging_dofs[var_covered])
1734  remaining.erase(var_covered);
1735  }
1736  };
1737 
1738  for (unsigned int v=0; v != n_vertices; ++v)
1739  {
1740  const Node * node = elem->node_ptr(v);
1741 
1742  auto remaining_vars = vertex_vars;
1743 
1744  erase_covered_vars(node, remaining_vars, vertices);
1745 
1746  if (remaining_vars.empty())
1747  continue;
1748 
1749  if (!all_extra_hanging_dofs)
1750  {
1751  erase_nonhanging_vars(node, remaining_vars, edges);
1752  if (remaining_vars.empty())
1753  continue;
1754 
1755  erase_nonhanging_vars(node, remaining_vars, sides);
1756  if (remaining_vars.empty())
1757  continue;
1758  }
1759 
1760  erase_copied_vars(node, true, remaining_vars);
1761  if (remaining_vars.empty())
1762  continue;
1763 
1764  if (copy_this_elem)
1765  {
1766  std::vector<dof_id_type> node_dof_ids;
1767  std::vector<typename FFunctor::ValuePushType> values;
1768 
1769  for (auto var : remaining_vars)
1770  {
1771  f.eval_old_dofs(*elem, v, var, node_dof_ids, values);
1772  insert_ids(node_dof_ids, values, node->processor_id());
1773  }
1774  copied_nodes[node].first.insert(remaining_vars.begin(),
1775  remaining_vars.end());
1776  this->find_dofs_to_send(*node, *elem, v, remaining_vars);
1777  }
1778  else
1779  vertices.emplace
1780  (node, std::make_tuple(elem, v, std::move(remaining_vars)));
1781  }
1782 
1783  if (has_edge_nodes)
1784  {
1785  for (unsigned int e=0; e != n_edges; ++e)
1786  {
1787  const Node * node = elem->node_ptr(n_vertices+e);
1788 
1789  auto remaining_vars = edge_vars;
1790 
1791  erase_covered_vars(node, remaining_vars, edges);
1792  if (remaining_vars.empty())
1793  continue;
1794 
1795  erase_covered_vars(node, remaining_vars, sides);
1796  if (remaining_vars.empty())
1797  continue;
1798 
1799  if (!all_extra_hanging_dofs)
1800  {
1801  erase_nonhanging_vars(node, remaining_vars, vertices);
1802  if (remaining_vars.empty())
1803  continue;
1804  }
1805 
1806  erase_copied_vars(node, false, remaining_vars);
1807  if (remaining_vars.empty())
1808  continue;
1809 
1810  if (copy_this_elem)
1811  {
1812  std::vector<dof_id_type> edge_dof_ids;
1813  std::vector<typename FFunctor::ValuePushType> values;
1814 
1815  for (auto var : remaining_vars)
1816  {
1817  f.eval_old_dofs(*elem, n_vertices+e, var, edge_dof_ids, values);
1818  insert_ids(edge_dof_ids, values, node->processor_id());
1819  }
1820 
1821  copied_nodes[node].second.insert(remaining_vars.begin(),
1822  remaining_vars.end());
1823  this->find_dofs_to_send(*node, *elem, n_vertices+e, remaining_vars);
1824  }
1825  else
1826  edges.emplace
1827  (node, std::make_tuple(elem, e, std::move(remaining_vars)));
1828  }
1829  }
1830 
1831  if (has_side_nodes)
1832  {
1833  for (unsigned int side=0; side != n_sides; ++side)
1834  {
1835  const Node * node = nullptr;
1836  unsigned short node_num = n_vertices+(dim>2)*n_edges+side;
1837  if (dim != 3)
1838  node = elem->node_ptr(node_num);
1839  else
1840  {
1841  // In 3D only some sides may have nodes
1842  for (unsigned int n = 0; n != n_nodes; ++n)
1843  {
1844  if (!elem->is_face(n))
1845  continue;
1846 
1847  if (elem->is_node_on_side(n, side))
1848  {
1849  node_num = n;
1850  node = elem->node_ptr(node_num);
1851  break;
1852  }
1853  }
1854  }
1855 
1856  if (!node)
1857  continue;
1858 
1859  auto remaining_vars = side_vars;
1860 
1861  erase_covered_vars(node, remaining_vars, edges);
1862  if (remaining_vars.empty())
1863  continue;
1864 
1865  erase_covered_vars(node, remaining_vars, sides);
1866  if (remaining_vars.empty())
1867  continue;
1868 
1869  if (!all_extra_hanging_dofs)
1870  {
1871  erase_nonhanging_vars(node, remaining_vars, vertices);
1872  if (remaining_vars.empty())
1873  continue;
1874  }
1875 
1876  erase_copied_vars(node, false, remaining_vars);
1877  if (remaining_vars.empty())
1878  continue;
1879 
1880  if (copy_this_elem)
1881  {
1882  std::vector<dof_id_type> side_dof_ids;
1883  std::vector<typename FFunctor::ValuePushType> values;
1884 
1885  for (auto var : remaining_vars)
1886  {
1887  f.eval_old_dofs(*elem, node_num, var, side_dof_ids, values);
1888  insert_ids(side_dof_ids, values, node->processor_id());
1889  }
1890 
1891  copied_nodes[node].second.insert(remaining_vars.begin(),
1892  remaining_vars.end());
1893  this->find_dofs_to_send(*node, *elem, node_num, remaining_vars);
1894  }
1895  else
1896  sides.emplace
1897  (node, std::make_tuple(elem, side, std::move(remaining_vars)));
1898  }
1899  }
1900 
1901  // Elements with elemental dofs might need those copied too.
1902  if (copy_this_elem)
1903  {
1904  std::vector<typename FFunctor::ValuePushType> U;
1905  std::vector<dof_id_type> dof_ids;
1906 
1907  for (auto v_num : this->projector.variables)
1908  {
1909  const Variable & var = system.variable(v_num);
1910  if (!var.active_on_subdomain(elem->subdomain_id()))
1911  continue;
1912  FEType fe_type = var.type();
1913 
1914  f.eval_old_dofs(*elem, fe_type, sys_num, v_num,
1915  dof_ids, U);
1916  action.insert(dof_ids, U);
1917 
1918  if (has_interior_nodes)
1919  {
1920  f.eval_old_dofs(*elem, n_nodes-1, v_num, dof_ids, U);
1921  action.insert(dof_ids, U);
1922  }
1923  }
1924  }
1925  }
1926 }
static unsigned int n_dofs_per_elem(const unsigned int dim, const FEType &fe_t, const ElemType t)
Definition: fe_interface.C:530
const Variable & variable(unsigned int var) const
Return a constant reference to Variable var.
Definition: system.h:2458
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:1452
unsigned int var_group_from_var_number(unsigned int var_num) const
Definition: dof_map.h:2430
std::vector< const Elem * > interiors
const dof_id_type n_nodes
Definition: tecplot_io.C:67
unsigned int number() const
Definition: system.h:2350
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
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:436
void find_dofs_to_send(const Node &node, const Elem &elem, unsigned short node_num, const var_set &vars)
std::set< unsigned int > var_set
const DofMap & get_dof_map() const
Definition: system.h:2374
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: