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)
 
void insert_ids (const std::vector< dof_id_type > &ids, const std::vector< FValue > &vals, processor_id_type pid)
 
void find_dofs_to_send (const Node &node, const Elem &elem, unsigned short node_num, const var_set &vars)
 
void insert_id (dof_id_type id, const FValue &val, processor_id_type pid)
 
void insert_ids (const std::vector< dof_id_type > &ids, const std::vector< FValue > &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< FValue, processor_id_type > > new_ids_to_push
 
std::unordered_map< dof_id_type, FValue > new_ids_to_save
 

Protected Attributes

std::vector< FEContinuityconts
 

Detailed Description

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

Definition at line 235 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 255 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)

Definition at line 236 of file generic_projector.h.

236 : 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   
)

Definition at line 238 of file generic_projector.h.

238 : 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 2322 of file generic_projector.h.

References libMesh::Elem::active(), libMesh::Variable::active_on_subdomain(), libMesh::DofMap::dof_indices(), libMesh::MeshBase::elem_ref(), libMesh::DofObject::id(), libMesh::DofObject::invalid_processor_id, libMesh::Parallel::Utils::is_sorted(), libMesh::Elem::node_ptr(), libMesh::DofObject::processor_id(), and libMesh::Elem::subdomain_id().

2323 {
2324  libmesh_assert (&node == elem.node_ptr(node_num));
2325 
2326  // Any ghosted node in our range might have an owner who needs our
2327  // data
2328  const processor_id_type owner = node.processor_id();
2329  if (owner != system.processor_id())
2330  {
2331  const MeshBase & mesh = system.get_mesh();
2332  const DofMap & dof_map = system.get_dof_map();
2333 
2334  // But let's check and see if we can be certain the owner can
2335  // compute any or all of its own dof coefficients on that node.
2336  std::vector<dof_id_type> node_dof_ids, patch_dof_ids;
2337  for (const auto & var : vars)
2338  {
2339  const Variable & variable = system.variable(var);
2340 
2341  if (!variable.active_on_subdomain(elem.subdomain_id()))
2342  continue;
2343 
2344  dof_map.dof_indices(elem, node_num, node_dof_ids, var);
2345  }
2346  libmesh_assert(std::is_sorted(node_dof_ids.begin(),
2347  node_dof_ids.end()));
2348  const std::vector<dof_id_type> & patch =
2349  (*this->projector.nodes_to_elem)[node.id()];
2350  for (const auto & elem_id : patch)
2351  {
2352  const Elem & patch_elem = mesh.elem_ref(elem_id);
2353  if (!patch_elem.active() || owner != patch_elem.processor_id())
2354  continue;
2355  dof_map.dof_indices(&patch_elem, patch_dof_ids);
2356  std::sort(patch_dof_ids.begin(), patch_dof_ids.end());
2357 
2358  // Remove any node_dof_ids that we see can be calculated on
2359  // this element
2360  std::vector<dof_id_type> diff_ids(node_dof_ids.size());
2361  auto it = std::set_difference(node_dof_ids.begin(), node_dof_ids.end(),
2362  patch_dof_ids.begin(), patch_dof_ids.end(), diff_ids.begin());
2363  diff_ids.resize(it-diff_ids.begin());
2364  node_dof_ids.swap(diff_ids);
2365  if (node_dof_ids.empty())
2366  break;
2367  }
2368 
2369  // Give ids_to_push default invalid pid: not yet computed
2370  for (auto id : node_dof_ids)
2372  }
2373 }
const Variable & variable(unsigned int var) const
Return a constant reference to Variable var.
Definition: system.h:2167
const MeshBase & get_mesh() const
Definition: system.h:2067
uint8_t processor_id_type
Definition: id_types.h:104
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:404
std::unordered_map< dof_id_type, std::vector< dof_id_type > > * nodes_to_elem
std::unordered_map< dof_id_type, std::pair< FValue, processor_id_type > > new_ids_to_push
processor_id_type processor_id() const
const DofMap & get_dof_map() const
Definition: system.h:2083

◆ insert_id()

template<typename FFunctor , typename GFunctor , typename FValue , typename ProjectionAction >
void libMesh::GenericProjector< FFunctor, GFunctor, FValue, ProjectionAction >::SubFunctor::insert_id ( dof_id_type  id,
const FValue &  val,
processor_id_type  pid 
)
inherited

Definition at line 1112 of file generic_projector.h.

References libMesh::DofObject::invalid_processor_id.

1113 {
1114  auto iter = new_ids_to_push.find(id);
1115  if (iter == new_ids_to_push.end())
1116  action.insert(id, val);
1117  else
1118  {
1119  libmesh_assert(pid != DofObject::invalid_processor_id);
1120  iter->second = std::make_pair(val, pid);
1121  }
1122  if (!this->projector.done_saving_ids)
1123  {
1124  libmesh_assert(!new_ids_to_save.count(id));
1125  new_ids_to_save[id] = val;
1126  }
1127 }
std::unordered_map< dof_id_type, FValue > new_ids_to_save
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:404
std::unordered_map< dof_id_type, std::pair< FValue, processor_id_type > > new_ids_to_push

◆ insert_ids() [1/2]

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

Definition at line 1133 of file generic_projector.h.

References libMesh::index_range(), and libMesh::DofObject::invalid_processor_id.

1134 {
1135  libmesh_assert_equal_to(ids.size(), vals.size());
1136  for (auto i : index_range(ids))
1137  {
1138  const dof_id_type id = ids[i];
1139  const FValue & val = vals[i];
1140 
1141  auto iter = new_ids_to_push.find(id);
1142  if (iter == new_ids_to_push.end())
1143  action.insert(id, val);
1144  else
1145  {
1146  libmesh_assert(pid != DofObject::invalid_processor_id);
1147  iter->second = std::make_pair(val, pid);
1148  }
1149  if (!this->projector.done_saving_ids)
1150  {
1151  libmesh_assert(!new_ids_to_save.count(id));
1152  new_ids_to_save[id] = val;
1153  }
1154  }
1155 }
IntRange< std::size_t > index_range(const std::vector< T > &vec)
Helper function that returns an IntRange<std::size_t> representing all the indices of the passed-in v...
Definition: int_range.h:104
std::unordered_map< dof_id_type, FValue > new_ids_to_save
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:404
std::unordered_map< dof_id_type, std::pair< FValue, processor_id_type > > new_ids_to_push
uint8_t dof_id_type
Definition: id_types.h:67

◆ insert_ids() [2/2]

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

Definition at line 1133 of file generic_projector.h.

1134 {
1135  libmesh_assert_equal_to(ids.size(), vals.size());
1136  for (auto i : index_range(ids))
1137  {
1138  const dof_id_type id = ids[i];
1139  const FValue & val = vals[i];
1140 
1141  auto iter = new_ids_to_push.find(id);
1142  if (iter == new_ids_to_push.end())
1143  action.insert(id, val);
1144  else
1145  {
1146  libmesh_assert(pid != DofObject::invalid_processor_id);
1147  iter->second = std::make_pair(val, pid);
1148  }
1149  if (!this->projector.done_saving_ids)
1150  {
1151  libmesh_assert(!new_ids_to_save.count(id));
1152  new_ids_to_save[id] = val;
1153  }
1154  }
1155 }
IntRange< std::size_t > index_range(const std::vector< T > &vec)
Helper function that returns an IntRange<std::size_t> representing all the indices of the passed-in v...
Definition: int_range.h:104
std::unordered_map< dof_id_type, FValue > new_ids_to_save
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:404
std::unordered_map< dof_id_type, std::pair< FValue, processor_id_type > > new_ids_to_push
uint8_t dof_id_type
Definition: id_types.h:67

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

1162 {
1163  new_ids_to_push.insert(other.new_ids_to_push.begin(), other.new_ids_to_push.end());
1164  new_ids_to_save.insert(other.new_ids_to_save.begin(), other.new_ids_to_save.end());
1165 }
std::unordered_map< dof_id_type, FValue > new_ids_to_save
std::unordered_map< dof_id_type, std::pair< FValue, processor_id_type > > new_ids_to_push

◆ 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 1605 of file generic_projector.h.

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

1606 {
1607  auto merge_multimaps = [](ves_multimap & self, const ves_multimap & other_mm)
1608  {
1609  for (const auto & pair : other_mm)
1610  {
1611  const Node * node = pair.first;
1612  auto remaining_vars = std::get<2>(pair.second);
1613 
1614  auto my_range = self.equal_range(node);
1615  for (const auto & v_ent : as_range(my_range))
1616  for (const unsigned int var_covered :
1617  std::get<2>(v_ent.second))
1618  remaining_vars.erase(var_covered);
1619 
1620  if (!remaining_vars.empty())
1621  self.emplace
1622  (node, std::make_tuple(std::get<0>(pair.second),
1623  std::get<1>(pair.second),
1624  std::move(remaining_vars)));
1625  }
1626  };
1627 
1628  merge_multimaps(vertices, other.vertices);
1629  merge_multimaps(edges, other.edges);
1630  merge_multimaps(sides, other.sides);
1631 }
std::unordered_multimap< const Node *, std::tuple< const Elem *, unsigned short, var_set > > ves_multimap
SimpleRange< I > as_range(const std::pair< I, I > &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 1171 of file generic_projector.h.

References libMesh::Variable::active_on_subdomain(), libMesh::as_range(), libMesh::CONSTANT, libMesh::FEInterface::extra_hanging_dofs(), libMesh::FEType::family, libMesh::Elem::JUST_COARSENED, libMesh::Elem::JUST_REFINED, libMesh::MONOMIAL, libMesh::FEInterface::n_dofs_at_node(), libMesh::FEInterface::n_dofs_per_elem(), libMesh::MeshTools::n_nodes(), libMesh::FEType::order, libMesh::DofObject::processor_id(), libMesh::Variable::system(), libMesh::Variable::type(), and libMesh::System::variable().

1172 {
1173  // Look at all the elements in the range. Directly copy values from
1174  // unchanged elements. For other elements, determine sets of
1175  // vertices, edge nodes, and side nodes to project.
1176  //
1177  // As per our other weird nomenclature, "sides" means faces in 3D
1178  // and edges in 2D, and "edges" gets skipped in 2D
1179  //
1180  // This gets tricky in the case of subdomain-restricted
1181  // variables, for which we might need to do the same projection
1182  // from different elements when evaluating different variables.
1183  // We'll keep track of which variables can be projected from which
1184  // elements.
1185 
1186  // If we copy DoFs on a node, keep track of it so we don't bother
1187  // with any redundant interpolations or projections later.
1188  //
1189  // We still need to keep track of *which* variables get copied,
1190  // since we may be able to copy elements which lack some
1191  // subdomain-restricted variables.
1192  //
1193  // For extra_hanging_dofs FE types, we'll keep track of which
1194  // variables were copied from vertices, and which from edges/sides,
1195  // because those types need copies made from *both* on hanging
1196  // nodes.
1197  std::unordered_map<const Node *, std::pair<var_set, var_set>> copied_nodes;
1198 
1199  const unsigned int sys_num = system.number();
1200 
1201  // At hanging nodes for variables with extra hanging dofs we'll need
1202  // to do projections *separately* from vertex elements and side/edge
1203  // elements.
1204  std::vector<unsigned short> extra_hanging_dofs;
1205  bool all_extra_hanging_dofs = true;
1206  for (auto v_num : this->projector.variables)
1207  {
1208  if (extra_hanging_dofs.size() <= v_num)
1209  extra_hanging_dofs.resize(v_num+1, false);
1210  extra_hanging_dofs[v_num] =
1212 
1213  if (!extra_hanging_dofs[v_num])
1214  all_extra_hanging_dofs = false;
1215  }
1216 
1217  for (const auto & elem : range)
1218  {
1219  // If we're doing AMR, we might be able to copy more DoFs than
1220  // we interpolate or project.
1221  bool copy_this_elem = false;
1222 
1223 #ifdef LIBMESH_ENABLE_AMR
1224  // If we're projecting from an old grid
1225  if (f.is_grid_projection())
1226  {
1227  // If this element doesn't have an old_dof_object, but it
1228  // wasn't just refined or just coarsened into activity, then
1229  // it must be newly added, so the user is responsible for
1230  // setting the new dofs on it during a grid projection.
1231  if (!elem->old_dof_object &&
1232  elem->refinement_flag() != Elem::JUST_REFINED &&
1233  elem->refinement_flag() != Elem::JUST_COARSENED)
1234  continue;
1235 
1236  // If this is an unchanged element, just copy everything
1237  if ((elem->refinement_flag() != Elem::JUST_REFINED &&
1238  elem->refinement_flag() != Elem::JUST_COARSENED &&
1239  elem->p_refinement_flag() != Elem::JUST_REFINED &&
1240  elem->p_refinement_flag() != Elem::JUST_COARSENED))
1241  copy_this_elem = true;
1242  else
1243  {
1244  bool reinitted = false;
1245 
1246  // If this element has a low order monomial which has
1247  // merely been h refined, copy it.
1248  for (auto v_num : this->projector.variables)
1249  {
1250  const Variable & var = system.variable(v_num);
1251  if (!var.active_on_subdomain(elem->subdomain_id()))
1252  continue;
1253  FEType fe_type = var.type();
1254 
1255  if (fe_type.family == MONOMIAL &&
1256  fe_type.order == CONSTANT &&
1257  elem->p_level() == 0 &&
1258  elem->refinement_flag() != Elem::JUST_COARSENED &&
1259  elem->p_refinement_flag() != Elem::JUST_COARSENED)
1260  {
1261  if (!reinitted)
1262  {
1263  reinitted = true;
1264  context.pre_fe_reinit(system, elem);
1265  }
1266 
1267  std::vector<FValue> Ue(1);
1268  std::vector<dof_id_type> elem_dof_ids(1);
1269 
1270  f.eval_old_dofs(*elem, fe_type, sys_num, v_num,
1271  elem_dof_ids, Ue);
1272 
1273  action.insert(elem_dof_ids[0], Ue[0]);
1274  }
1275  }
1276  }
1277  }
1278 #endif // LIBMESH_ENABLE_AMR
1279 
1280  const int dim = elem->dim();
1281 
1282  const unsigned int n_vertices = elem->n_vertices();
1283  const unsigned int n_edges = elem->n_edges();
1284  const unsigned int n_nodes = elem->n_nodes();
1285 
1286  // In 1-D we already handle our sides as vertices
1287  const unsigned int n_sides = (dim > 1) * elem->n_sides();
1288 
1289  // What variables are supported on each kind of node on this elem?
1290  var_set vertex_vars, edge_vars, side_vars;
1291 
1292  // If we have non-vertex nodes, the first is an edge node, but
1293  // if we're in 2D we'll call that a side node
1294  const bool has_edge_nodes = (n_nodes > n_vertices && dim > 2);
1295 
1296  // If we have even more nodes, the next is a side node.
1297  const bool has_side_nodes =
1298  (n_nodes > n_vertices + ((dim > 2) * n_edges));
1299 
1300  // We may be out of nodes at this point or we have interior
1301  // nodes which may have DoFs to project too
1302  const bool has_interior_nodes =
1303  (n_nodes > n_vertices + ((dim > 2) * n_edges) + n_sides);
1304 
1305  for (auto v_num : this->projector.variables)
1306  {
1307  const Variable & var = this->projector.system.variable(v_num);
1308  if (!var.active_on_subdomain(elem->subdomain_id()))
1309  continue;
1310  FEType fe_type = var.type();
1311  fe_type.order =
1312  libMesh::Order (fe_type.order + elem->p_level());
1313  const ElemType elem_type = elem->type();
1314 
1315  if (FEInterface::n_dofs_at_node(dim, fe_type, elem_type, 0))
1316  vertex_vars.insert(vertex_vars.end(), v_num);
1317 
1318  // The first non-vertex node is always an edge node if those
1319  // exist. All edge nodes have the same number of DoFs
1320  if (has_edge_nodes)
1321  if (FEInterface::n_dofs_at_node(dim, fe_type, elem_type, n_vertices))
1322  edge_vars.insert(edge_vars.end(), v_num);
1323 
1324  if (has_side_nodes)
1325  {
1326  if (dim != 3)
1327  {
1328  if (FEInterface::n_dofs_at_node(dim, fe_type, elem_type, n_vertices))
1329  side_vars.insert(side_vars.end(), v_num);
1330  }
1331  else
1332  // In 3D, not all face nodes always have the same number of
1333  // DoFs! We'll loop over all sides to be safe.
1334  for (unsigned int n = 0; n != n_nodes; ++n)
1335  if (elem->is_face(n))
1336  if (FEInterface::n_dofs_at_node(dim, fe_type,
1337  elem_type, n))
1338  {
1339  side_vars.insert(side_vars.end(), v_num);
1340  break;
1341  }
1342  }
1343 
1344  if (FEInterface::n_dofs_per_elem(dim, fe_type, elem_type) ||
1345  (has_interior_nodes &&
1346  FEInterface::n_dofs_at_node(dim, fe_type, elem_type, n_nodes-1)))
1347  {
1348  // We may have already just copied constant monomials,
1349  // or we may be about to copy the whole element
1350  if ((f.is_grid_projection() &&
1351  fe_type.family == MONOMIAL &&
1352  fe_type.order == CONSTANT &&
1353  elem->p_level() == 0 &&
1354  elem->refinement_flag() != Elem::JUST_COARSENED &&
1355  elem->p_refinement_flag() != Elem::JUST_COARSENED)
1356  || copy_this_elem
1357  )
1358  continue;
1359 
1360  // We need to project any other variables
1361  if (interiors.empty() || interiors.back() != elem)
1362  interiors.push_back(elem);
1363  }
1364  }
1365 
1366  // We'll use a greedy algorithm in most cases: if another
1367  // element has already claimed some of our DoFs, we'll let it do
1368  // the work.
1369  auto erase_covered_vars = []
1370  (const Node * node, var_set & remaining, const ves_multimap & covered)
1371  {
1372  auto covered_range = covered.equal_range(node);
1373  for (const auto & v_ent : as_range(covered_range))
1374  for (const unsigned int var_covered :
1375  std::get<2>(v_ent.second))
1376  remaining.erase(var_covered);
1377  };
1378 
1379  auto erase_nonhanging_vars = [&extra_hanging_dofs]
1380  (const Node * node, var_set & remaining, const ves_multimap & covered)
1381  {
1382  auto covered_range = covered.equal_range(node);
1383  for (const auto & v_ent : as_range(covered_range))
1384  for (const unsigned int var_covered :
1385  std::get<2>(v_ent.second))
1386  if (!extra_hanging_dofs[var_covered])
1387  remaining.erase(var_covered);
1388  };
1389 
1390  auto erase_copied_vars = [&copied_nodes, &extra_hanging_dofs]
1391  (const Node * node, bool is_vertex, var_set & remaining)
1392  {
1393  auto copying_range = copied_nodes.equal_range(node);
1394  for (const auto & v_ent : as_range(copying_range))
1395  {
1396  for (const unsigned int var_covered :
1397  v_ent.second.first)
1398  if (is_vertex || !extra_hanging_dofs[var_covered])
1399  remaining.erase(var_covered);
1400 
1401  for (const unsigned int var_covered :
1402  v_ent.second.second)
1403  if (!is_vertex || !extra_hanging_dofs[var_covered])
1404  remaining.erase(var_covered);
1405  }
1406  };
1407 
1408  for (unsigned int v=0; v != n_vertices; ++v)
1409  {
1410  const Node * node = elem->node_ptr(v);
1411 
1412  auto remaining_vars = vertex_vars;
1413 
1414  erase_covered_vars(node, remaining_vars, vertices);
1415 
1416  if (remaining_vars.empty())
1417  continue;
1418 
1419  if (!all_extra_hanging_dofs)
1420  {
1421  erase_nonhanging_vars(node, remaining_vars, edges);
1422  if (remaining_vars.empty())
1423  continue;
1424 
1425  erase_nonhanging_vars(node, remaining_vars, sides);
1426  if (remaining_vars.empty())
1427  continue;
1428  }
1429 
1430  erase_copied_vars(node, true, remaining_vars);
1431  if (remaining_vars.empty())
1432  continue;
1433 
1434  if (copy_this_elem)
1435  {
1436  for (auto var : remaining_vars)
1437  {
1438  std::vector<dof_id_type> node_dof_ids;
1439  std::vector<FValue> values;
1440 
1441  f.eval_old_dofs(*elem, v, var, node_dof_ids, values);
1442 
1443  insert_ids(node_dof_ids, values, node->processor_id());
1444  }
1445  copied_nodes[node].first.insert(remaining_vars.begin(),
1446  remaining_vars.end());
1447  this->find_dofs_to_send(*node, *elem, v, remaining_vars);
1448  }
1449  else
1450  vertices.emplace
1451  (node, std::make_tuple(elem, v, std::move(remaining_vars)));
1452  }
1453 
1454  if (has_edge_nodes)
1455  {
1456  for (unsigned int e=0; e != n_edges; ++e)
1457  {
1458  const Node * node = elem->node_ptr(n_vertices+e);
1459 
1460  auto remaining_vars = edge_vars;
1461 
1462  erase_covered_vars(node, remaining_vars, edges);
1463  if (remaining_vars.empty())
1464  continue;
1465 
1466  erase_covered_vars(node, remaining_vars, sides);
1467  if (remaining_vars.empty())
1468  continue;
1469 
1470  if (!all_extra_hanging_dofs)
1471  {
1472  erase_nonhanging_vars(node, remaining_vars, vertices);
1473  if (remaining_vars.empty())
1474  continue;
1475  }
1476 
1477  erase_copied_vars(node, false, remaining_vars);
1478  if (remaining_vars.empty())
1479  continue;
1480 
1481  if (copy_this_elem)
1482  {
1483  for (auto var : remaining_vars)
1484  {
1485  std::vector<dof_id_type> edge_dof_ids;
1486  std::vector<FValue> values;
1487 
1488  f.eval_old_dofs(*elem, n_vertices+e, var, edge_dof_ids, values);
1489 
1490  insert_ids(edge_dof_ids, values, node->processor_id());
1491  }
1492  copied_nodes[node].second.insert(remaining_vars.begin(),
1493  remaining_vars.end());
1494  this->find_dofs_to_send(*node, *elem, n_vertices+e, remaining_vars);
1495  }
1496  else
1497  edges.emplace
1498  (node, std::make_tuple(elem, e, std::move(remaining_vars)));
1499  }
1500  }
1501 
1502  if (has_side_nodes)
1503  {
1504  for (unsigned int side=0; side != n_sides; ++side)
1505  {
1506  const Node * node = nullptr;
1507  unsigned short node_num = n_vertices+(dim>2)*n_edges+side;
1508  if (dim != 3)
1509  node = elem->node_ptr(node_num);
1510  else
1511  {
1512  // In 3D only some sides may have nodes
1513  for (unsigned int n = 0; n != n_nodes; ++n)
1514  {
1515  if (!elem->is_face(n))
1516  continue;
1517 
1518  if (elem->is_node_on_side(n, side))
1519  {
1520  node_num = n;
1521  node = elem->node_ptr(node_num);
1522  break;
1523  }
1524  }
1525  }
1526 
1527  if (!node)
1528  continue;
1529 
1530  auto remaining_vars = side_vars;
1531 
1532  erase_covered_vars(node, remaining_vars, edges);
1533  if (remaining_vars.empty())
1534  continue;
1535 
1536  erase_covered_vars(node, remaining_vars, sides);
1537  if (remaining_vars.empty())
1538  continue;
1539 
1540  if (!all_extra_hanging_dofs)
1541  {
1542  erase_nonhanging_vars(node, remaining_vars, vertices);
1543  if (remaining_vars.empty())
1544  continue;
1545  }
1546 
1547  erase_copied_vars(node, false, remaining_vars);
1548  if (remaining_vars.empty())
1549  continue;
1550 
1551  if (copy_this_elem)
1552  {
1553  for (auto var : remaining_vars)
1554  {
1555  std::vector<dof_id_type> side_dof_ids;
1556  std::vector<FValue> values;
1557 
1558  f.eval_old_dofs(*elem, node_num, var, side_dof_ids, values);
1559 
1560  insert_ids(side_dof_ids, values, node->processor_id());
1561  }
1562  copied_nodes[node].second.insert(remaining_vars.begin(),
1563  remaining_vars.end());
1564  this->find_dofs_to_send(*node, *elem, node_num, remaining_vars);
1565  }
1566  else
1567  sides.emplace
1568  (node, std::make_tuple(elem, side, std::move(remaining_vars)));
1569  }
1570  }
1571 
1572  // Elements with elemental dofs might need those copied too.
1573  if (copy_this_elem)
1574  {
1575  for (auto v_num : this->projector.variables)
1576  {
1577  const Variable & var = system.variable(v_num);
1578  if (!var.active_on_subdomain(elem->subdomain_id()))
1579  continue;
1580  FEType fe_type = var.type();
1581 
1582  std::vector<FValue> Ue;
1583  std::vector<dof_id_type> elem_dof_ids;
1584  f.eval_old_dofs(*elem, fe_type, sys_num, v_num,
1585  elem_dof_ids, Ue);
1586  action.insert(elem_dof_ids, Ue);
1587 
1588  if (has_interior_nodes)
1589  {
1590  std::vector<FValue> Un;
1591  std::vector<dof_id_type> node_dof_ids;
1592 
1593  f.eval_old_dofs(*elem, n_nodes-1, v_num, node_dof_ids, Un);
1594  action.insert(node_dof_ids, Un);
1595  }
1596  }
1597  }
1598  }
1599 }
ElemType
Defines an enum for geometric element types.
dof_id_type n_nodes(const MeshBase::const_node_iterator &begin, const MeshBase::const_node_iterator &end)
Count up the number of nodes of a specific type (as defined by an iterator range).
Order
defines an enum for polynomial orders.
Definition: enum_order.h:40
const Variable & variable(unsigned int var) const
Return a constant reference to Variable var.
Definition: system.h:2167
std::unordered_multimap< const Node *, std::tuple< const Elem *, unsigned short, var_set > > ves_multimap
OrderWrapper order
The approximation order of the element.
Definition: fe_type.h:198
std::vector< const Elem * > interiors
unsigned int number() const
Definition: system.h:2059
SimpleRange< I > as_range(const std::pair< I, I > &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
void find_dofs_to_send(const Node &node, const Elem &elem, unsigned short node_num, const var_set &vars)
static unsigned int n_dofs_per_elem(const unsigned int dim, const FEType &fe_t, const ElemType t)
std::set< unsigned int > var_set
void insert_ids(const std::vector< dof_id_type > &ids, const std::vector< FValue > &vals, processor_id_type pid)
static unsigned int n_dofs_at_node(const unsigned int dim, const FEType &fe_t, const ElemType t, const unsigned int n)
virtual void pre_fe_reinit(const System &, const Elem *e)
Reinitializes local data vectors/matrices on the current geometric element.
static bool extra_hanging_dofs(const FEType &fe_t)
const FEType & type() const
Definition: variable.h:119

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 188 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 193 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 196 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 189 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<FValue, 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, FValue> 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 149 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 198 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: