This method projects an arbitrary boundary solution to the current mesh. The input function f
gives the arbitrary solution, while the new_vector
(which should already be correctly sized) gives the solution (to be computed) on the current mesh.
1344 const BoundaryInfo & boundary_info =
1351 DenseMatrix<Real> Ke;
1352 DenseVector<Number> Fe;
1354 DenseVector<Number> Ue;
1358 for (
auto v : IntRange<std::size_t>(0,
variables.size()))
1362 const Variable & variable = dof_map.variable(var);
1364 const FEType & fe_type = variable.type();
1366 if (fe_type.family ==
SCALAR)
1369 const unsigned int var_component =
1376 std::unique_ptr<QBase> qedgerule (fe_type.default_quadrature_rule(1));
1377 std::unique_ptr<QBase> qsiderule (fe_type.default_quadrature_rule(
dim-1));
1381 const std::vector<std::vector<Real>> & phi = fe->get_phi();
1385 const std::vector<std::vector<RealGradient>> * dphi =
nullptr;
1394 const std::vector<std::vector<RealGradient>> &
1395 ref_dphi = fe->get_dphi();
1400 const std::vector<Real> & JxW =
1404 const std::vector<Point> & xyz_values =
1408 std::vector<dof_id_type> dof_indices;
1410 std::vector<unsigned int> side_dofs;
1413 std::vector<boundary_id_type> bc_ids;
1416 for (
const auto & elem : range)
1420 if (!variable.active_on_subdomain(elem->subdomain_id()))
1423 const unsigned short n_nodes = elem->n_nodes();
1424 const unsigned short n_edges = elem->n_edges();
1425 const unsigned short n_sides = elem->n_sides();
1429 std::vector<bool> is_boundary_node(
n_nodes,
false),
1430 is_boundary_edge(n_edges,
false),
1431 is_boundary_side(n_sides,
false);
1434 std::vector<bool> is_boundary_nodeset(
n_nodes,
false);
1436 for (
unsigned char s=0; s != n_sides; ++s)
1439 boundary_info.boundary_ids (elem, s, bc_ids);
1440 bool do_this_side =
false;
1441 for (
const auto & bc_id : bc_ids)
1444 do_this_side =
true;
1450 is_boundary_side[s] =
true;
1453 for (
unsigned int n=0; n !=
n_nodes; ++n)
1454 if (elem->is_node_on_side(n,s))
1455 is_boundary_node[n] =
true;
1456 for (
unsigned int e=0; e != n_edges; ++e)
1457 if (elem->is_edge_on_side(e,s))
1458 is_boundary_edge[e] =
true;
1463 for (
unsigned int n=0; n !=
n_nodes; ++n)
1465 boundary_info.boundary_ids (elem->node_ptr(n), bc_ids);
1467 for (
const auto & bc_id : bc_ids)
1470 is_boundary_node[n] =
true;
1471 is_boundary_nodeset[n] =
true;
1477 for (
unsigned short e=0; e != n_edges; ++e)
1479 boundary_info.edge_boundary_ids (elem, e, bc_ids);
1481 for (
const auto & bc_id : bc_ids)
1483 is_boundary_edge[e] =
true;
1488 dof_map.dof_indices (elem, dof_indices, var);
1491 const unsigned int n_dofs =
1492 cast_int<unsigned int>(dof_indices.size());
1495 std::vector<char> dof_is_fixed(n_dofs,
false);
1496 std::vector<int> free_dof(n_dofs, 0);
1499 const ElemType elem_type = elem->type();
1502 Ue.resize (n_dofs); Ue.zero();
1511 unsigned int current_dof = 0;
1512 for (
unsigned short n = 0; n !=
n_nodes; ++n)
1516 const unsigned int nc =
1519 if ((!elem->is_vertex(n) || !is_boundary_node[n]) &&
1520 !is_boundary_nodeset[n])
1527 libmesh_assert_equal_to (nc, 0);
1533 libmesh_assert_equal_to (nc, 1);
1534 Ue(current_dof) =
f->component(var_component,
1537 dof_is_fixed[current_dof] =
true;
1541 else if (fe_type.family ==
HERMITE)
1543 Ue(current_dof) =
f->component(var_component,
1546 dof_is_fixed[current_dof] =
true;
1548 Gradient grad =
g->component(var_component,
1552 Ue(current_dof) = grad(0);
1553 dof_is_fixed[current_dof] =
true;
1559 Point nxminus = elem->point(n),
1560 nxplus = elem->point(n);
1563 Gradient gxminus =
g->component(var_component,
1566 Gradient gxplus =
g->component(var_component,
1570 Ue(current_dof) = grad(1);
1571 dof_is_fixed[current_dof] =
true;
1574 Ue(current_dof) = (gxplus(1) - gxminus(1))
1576 dof_is_fixed[current_dof] =
true;
1583 Ue(current_dof) = grad(2);
1584 dof_is_fixed[current_dof] =
true;
1587 Ue(current_dof) = (gxplus(2) - gxminus(2))
1589 dof_is_fixed[current_dof] =
true;
1592 Point nyminus = elem->point(n),
1593 nyplus = elem->point(n);
1596 Gradient gyminus =
g->component(var_component,
1599 Gradient gyplus =
g->component(var_component,
1603 Ue(current_dof) = (gyplus(2) - gyminus(2))
1605 dof_is_fixed[current_dof] =
true;
1608 Point nxmym = elem->point(n),
1609 nxmyp = elem->point(n),
1610 nxpym = elem->point(n),
1611 nxpyp = elem->point(n);
1620 Gradient gxmym =
g->component(var_component,
1623 Gradient gxmyp =
g->component(var_component,
1626 Gradient gxpym =
g->component(var_component,
1629 Gradient gxpyp =
g->component(var_component,
1632 Number gxzplus = (gxpyp(2) - gxmyp(2))
1634 Number gxzminus = (gxpym(2) - gxmym(2))
1637 Ue(current_dof) = (gxzplus - gxzminus)
1639 dof_is_fixed[current_dof] =
true;
1642 #endif // LIBMESH_DIM > 2
1644 #endif // LIBMESH_DIM > 1
1649 else if (cont ==
C_ONE)
1651 libmesh_assert_equal_to (nc, 1 +
dim);
1652 Ue(current_dof) =
f->component(var_component,
1655 dof_is_fixed[current_dof] =
true;
1657 Gradient grad =
g->component(var_component,
1660 for (
unsigned int i=0; i!=
dim; ++i)
1662 Ue(current_dof) = grad(i);
1663 dof_is_fixed[current_dof] =
true;
1668 libmesh_error_msg(
"Unknown continuity " << cont);
1673 for (
unsigned short e = 0; e != n_edges; ++e)
1675 if (!is_boundary_edge[e])
1681 const unsigned int n_side_dofs =
1682 cast_int<unsigned int>(side_dofs.size());
1686 unsigned int free_dofs = 0;
1687 for (
auto i : IntRange<unsigned int>(0, n_side_dofs))
1688 if (!dof_is_fixed[side_dofs[i]])
1689 free_dof[free_dofs++] = i;
1695 Ke.resize (free_dofs, free_dofs); Ke.zero();
1696 Fe.resize (free_dofs); Fe.zero();
1698 DenseVector<Number> Uedge(free_dofs);
1701 fe->attach_quadrature_rule (qedgerule.get());
1702 fe->edge_reinit (elem, e);
1703 const unsigned int n_qp = qedgerule->n_points();
1706 for (
unsigned int qp=0; qp<n_qp; qp++)
1709 Number fineval =
f->component(var_component,
1715 finegrad =
g->component(var_component,
1720 for (
unsigned int sidei=0, freei=0;
1721 sidei != n_side_dofs; ++sidei)
1723 unsigned int i = side_dofs[sidei];
1725 if (dof_is_fixed[i])
1727 for (
unsigned int sidej=0, freej=0;
1728 sidej != n_side_dofs; ++sidej)
1730 unsigned int j = side_dofs[sidej];
1731 if (dof_is_fixed[j])
1732 Fe(freei) -= phi[i][qp] * phi[j][qp] *
1735 Ke(freei,freej) += phi[i][qp] *
1736 phi[j][qp] * JxW[qp];
1739 if (dof_is_fixed[j])
1740 Fe(freei) -= ((*dphi)[i][qp] *
1744 Ke(freei,freej) += ((*dphi)[i][qp] *
1748 if (!dof_is_fixed[j])
1751 Fe(freei) += phi[i][qp] * fineval * JxW[qp];
1753 Fe(freei) += (finegrad * (*dphi)[i][qp]) *
1759 Ke.cholesky_solve(Fe, Uedge);
1762 for (
unsigned int i=0; i != free_dofs; ++i)
1764 Number & ui = Ue(side_dofs[free_dof[i]]);
1768 dof_is_fixed[side_dofs[free_dof[i]]] =
true;
1774 for (
unsigned short s = 0; s != n_sides; ++s)
1776 if (!is_boundary_side[s])
1784 unsigned int free_dofs = 0;
1786 if (!dof_is_fixed[side_dofs[i]])
1787 free_dof[free_dofs++] = i;
1793 Ke.resize (free_dofs, free_dofs); Ke.zero();
1794 Fe.resize (free_dofs); Fe.zero();
1796 DenseVector<Number> Uside(free_dofs);
1799 fe->attach_quadrature_rule (qsiderule.get());
1800 fe->reinit (elem, s);
1801 const unsigned int n_qp = qsiderule->n_points();
1803 const unsigned int n_side_dofs =
1804 cast_int<unsigned int>(side_dofs.size());
1807 for (
unsigned int qp=0; qp<n_qp; qp++)
1810 Number fineval =
f->component(var_component,
1816 finegrad =
g->component(var_component,
1821 for (
unsigned int sidei=0, freei=0;
1822 sidei != n_side_dofs; ++sidei)
1824 unsigned int i = side_dofs[sidei];
1826 if (dof_is_fixed[i])
1828 for (
unsigned int sidej=0, freej=0;
1829 sidej != n_side_dofs; ++sidej)
1831 unsigned int j = side_dofs[sidej];
1832 if (dof_is_fixed[j])
1833 Fe(freei) -= phi[i][qp] * phi[j][qp] *
1836 Ke(freei,freej) += phi[i][qp] *
1837 phi[j][qp] * JxW[qp];
1840 if (dof_is_fixed[j])
1841 Fe(freei) -= ((*dphi)[i][qp] *
1845 Ke(freei,freej) += ((*dphi)[i][qp] *
1849 if (!dof_is_fixed[j])
1852 Fe(freei) += (fineval * phi[i][qp]) * JxW[qp];
1854 Fe(freei) += (finegrad * (*dphi)[i][qp]) *
1860 Ke.cholesky_solve(Fe, Uside);
1863 for (
unsigned int i=0; i != free_dofs; ++i)
1865 Number & ui = Ue(side_dofs[free_dof[i]]);
1869 dof_is_fixed[side_dofs[free_dof[i]]] =
true;
1881 for (
unsigned int i = 0; i < n_dofs; i++)
1882 if (dof_is_fixed[i] &&
1883 (dof_indices[i] >= first) &&
1884 (dof_indices[i] < last))