1482{
1483 LOG_SCOPE ("SortAndCopy::operator()","GenericProjector");
1484
1485
1486
1487
1488
1489
1490
1491
1492
1493
1494
1495
1496
1497
1498
1499
1500
1501
1502
1503
1504
1505
1506
1507
1508
1509 std::unordered_map<const Node *, std::pair<var_set, var_set>> copied_nodes;
1510
1512
1513
1514
1515
1516 std::vector<unsigned short> extra_hanging_dofs;
1517 bool all_extra_hanging_dofs = true;
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
1532
1533 bool copy_this_elem = false;
1534
1535#ifdef LIBMESH_ENABLE_AMR
1536
1537 if (
f.is_grid_projection())
1538 {
1539
1540
1541
1542
1543 const DofObject * old_dof_object = elem->get_old_dof_object();
1546 if (!old_dof_object &&
1549 continue;
1550
1551
1556 copy_this_elem = true;
1557 else
1558 {
1559 bool reinitted = false;
1560
1561 const unsigned int p_level = elem->p_level();
1562
1563
1564
1565 const bool copy_possible =
1566 p_level == 0 &&
1569
1570 std::vector<typename FFunctor::ValuePushType> Ue(1);
1571 std::vector<dof_id_type> elem_dof_ids(1);
1572
1574 {
1576 if (!var.active_on_subdomain(elem->subdomain_id()))
1577 continue;
1578 const FEType fe_type = var.
type();
1579
1582 copy_possible)
1583 {
1584 if (!reinitted)
1585 {
1586 reinitted = true;
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
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
1607 const unsigned int n_sides = (
dim > 1) * elem->n_sides();
1608
1609
1610 var_set vertex_vars, edge_vars, side_vars;
1611
1612
1613
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
1618 const bool has_side_nodes =
1619 (
n_nodes > n_vertices + ((
dim > 2) * n_edges));
1620
1621
1622
1623 const bool has_interior_nodes =
1624 (
n_nodes > n_vertices + ((
dim > 2) * n_edges) + n_sides);
1625
1627 {
1629 if (!var.active_on_subdomain(elem->subdomain_id()))
1630 continue;
1631 const FEType fe_type = var.
type();
1633
1634
1635
1636
1637
1638
1641 continue;
1642
1644 vertex_vars.insert(vertex_vars.end(), v_num);
1645
1646
1647
1648 if (has_edge_nodes)
1650 edge_vars.insert(edge_vars.end(), v_num);
1651
1652 if (has_side_nodes)
1653 {
1655 {
1657 side_vars.insert(side_vars.end(), v_num);
1658 }
1659 else
1660
1661
1662 for (
unsigned int n = 0; n !=
n_nodes; ++n)
1663 if (elem->is_face(n))
1665 {
1666 side_vars.insert(side_vars.end(), v_num);
1667 break;
1668 }
1669 }
1670
1672 (has_interior_nodes &&
1674 {
1675#ifdef LIBMESH_ENABLE_AMR
1676
1677
1678 if ((
f.is_grid_projection() &&
1681 elem->p_level() == 0 &&
1684 || copy_this_elem
1685 )
1686 continue;
1687#endif
1688
1689
1692 }
1693 }
1694
1695
1696
1697
1698 auto erase_covered_vars = []
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]
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
1738
1739
1740#ifndef NDEBUG
1742 {
1744
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());
1787 }
1788 else
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());
1834 }
1835 else
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;
1848 node = elem->node_ptr(node_num);
1849 else
1850 {
1851
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());
1904 }
1905 else
1907 (node, std::make_tuple(elem, side, std::move(remaining_vars)));
1908 }
1909 }
1910
1911
1912 if (copy_this_elem)
1913 {
1914 std::vector<typename FFunctor::ValuePushType> U;
1915 std::vector<dof_id_type> dof_ids;
1916
1918 {
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}
RefinementState
Enumeration of possible element refinement states.
static unsigned int n_dofs_at_node(const unsigned int dim, const FEType &fe_t, const ElemType t, const unsigned int n)
static unsigned int n_dofs_per_elem(const unsigned int dim, const FEType &fe_t, const ElemType t)
static bool extra_hanging_dofs(const FEType &fe_t)
virtual void pre_fe_reinit(const System &, const Elem *e)
Reinitializes local data vectors/matrices on the current geometric element.
bool p_refinement
Whether or not the finite elements for this type increase their p refinement level on geometric eleme...
FEFamily family
The type of finite element.
const std::vector< unsigned int > & variables
std::set< unsigned int > var_set
unsigned int number() const
const FEType & type() const
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...
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)
const dof_id_type n_nodes