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.
1185 libmesh_assert(
f.get());
1201 const BoundaryInfo & boundary_info =
1208 DenseMatrix<Real> Ke;
1209 DenseVector<Number> Fe;
1211 DenseVector<Number> Ue;
1215 for (std::size_t v=0; v!=
variables.size(); v++)
1219 const Variable & variable = dof_map.variable(var);
1221 const FEType & fe_type = variable.type();
1223 if (fe_type.family ==
SCALAR)
1226 const unsigned int var_component =
1233 std::unique_ptr<QBase> qedgerule (fe_type.default_quadrature_rule(1));
1234 std::unique_ptr<QBase> qsiderule (fe_type.default_quadrature_rule(dim-1));
1238 const std::vector<std::vector<Real>> & phi = fe->get_phi();
1242 const std::vector<std::vector<RealGradient>> * dphi =
nullptr;
1249 libmesh_assert(
g.get());
1251 const std::vector<std::vector<RealGradient>> &
1252 ref_dphi = fe->get_dphi();
1257 const std::vector<Real> & JxW =
1261 const std::vector<Point> & xyz_values =
1265 std::vector<dof_id_type> dof_indices;
1267 std::vector<unsigned int> side_dofs;
1270 std::vector<boundary_id_type> bc_ids;
1273 for (
const auto & elem : range)
1277 if (!variable.active_on_subdomain(elem->subdomain_id()))
1280 const unsigned short n_nodes = elem->n_nodes();
1281 const unsigned short n_edges = elem->n_edges();
1282 const unsigned short n_sides = elem->n_sides();
1286 std::vector<bool> is_boundary_node(
n_nodes,
false),
1287 is_boundary_edge(n_edges,
false),
1288 is_boundary_side(n_sides,
false);
1291 std::vector<bool> is_boundary_nodeset(
n_nodes,
false);
1293 for (
unsigned char s=0; s != n_sides; ++s)
1296 boundary_info.boundary_ids (elem, s, bc_ids);
1297 bool do_this_side =
false;
1298 for (
const auto &
bc_id : bc_ids)
1301 do_this_side =
true;
1307 is_boundary_side[s] =
true;
1310 for (
unsigned int n=0; n !=
n_nodes; ++n)
1311 if (elem->is_node_on_side(n,s))
1312 is_boundary_node[n] =
true;
1313 for (
unsigned int e=0; e != n_edges; ++e)
1314 if (elem->is_edge_on_side(e,s))
1315 is_boundary_edge[e] =
true;
1320 for (
unsigned int n=0; n !=
n_nodes; ++n)
1322 boundary_info.boundary_ids (elem->node_ptr(n), bc_ids);
1324 for (
const auto &
bc_id : bc_ids)
1327 is_boundary_node[n] =
true;
1328 is_boundary_nodeset[n] =
true;
1334 for (
unsigned short e=0; e != n_edges; ++e)
1336 boundary_info.edge_boundary_ids (elem, e, bc_ids);
1338 for (
const auto &
bc_id : bc_ids)
1340 is_boundary_edge[e] =
true;
1345 dof_map.dof_indices (elem, dof_indices, var);
1348 const unsigned int n_dofs =
1349 cast_int<unsigned int>(dof_indices.size());
1352 std::vector<char> dof_is_fixed(n_dofs,
false);
1353 std::vector<int> free_dof(n_dofs, 0);
1356 const ElemType elem_type = elem->type();
1359 Ue.resize (n_dofs); Ue.zero();
1368 unsigned int current_dof = 0;
1369 for (
unsigned short n = 0; n !=
n_nodes; ++n)
1373 const unsigned int nc =
1376 if ((!elem->is_vertex(n) || !is_boundary_node[n]) &&
1377 !is_boundary_nodeset[n])
1384 libmesh_assert_equal_to (nc, 0);
1390 libmesh_assert_equal_to (nc, 1);
1391 Ue(current_dof) =
f->component(var_component,
1394 dof_is_fixed[current_dof] =
true;
1398 else if (fe_type.family ==
HERMITE)
1400 Ue(current_dof) =
f->component(var_component,
1403 dof_is_fixed[current_dof] =
true;
1405 Gradient grad =
g->component(var_component,
1409 Ue(current_dof) = grad(0);
1410 dof_is_fixed[current_dof] =
true;
1415 Point nxminus = elem->point(n),
1416 nxplus = elem->point(n);
1419 Gradient gxminus =
g->component(var_component,
1422 Gradient gxplus =
g->component(var_component,
1426 Ue(current_dof) = grad(1);
1427 dof_is_fixed[current_dof] =
true;
1430 Ue(current_dof) = (gxplus(1) - gxminus(1))
1432 dof_is_fixed[current_dof] =
true;
1438 Ue(current_dof) = grad(2);
1439 dof_is_fixed[current_dof] =
true;
1442 Ue(current_dof) = (gxplus(2) - gxminus(2))
1444 dof_is_fixed[current_dof] =
true;
1447 Point nyminus = elem->point(n),
1448 nyplus = elem->point(n);
1451 Gradient gyminus =
g->component(var_component,
1454 Gradient gyplus =
g->component(var_component,
1458 Ue(current_dof) = (gyplus(2) - gyminus(2))
1460 dof_is_fixed[current_dof] =
true;
1463 Point nxmym = elem->point(n),
1464 nxmyp = elem->point(n),
1465 nxpym = elem->point(n),
1466 nxpyp = elem->point(n);
1475 Gradient gxmym =
g->component(var_component,
1478 Gradient gxmyp =
g->component(var_component,
1481 Gradient gxpym =
g->component(var_component,
1484 Gradient gxpyp =
g->component(var_component,
1487 Number gxzplus = (gxpyp(2) - gxmyp(2))
1489 Number gxzminus = (gxpym(2) - gxmym(2))
1492 Ue(current_dof) = (gxzplus - gxzminus)
1494 dof_is_fixed[current_dof] =
true;
1502 else if (cont ==
C_ONE)
1504 libmesh_assert_equal_to (nc, 1 + dim);
1505 Ue(current_dof) =
f->component(var_component,
1508 dof_is_fixed[current_dof] =
true;
1510 Gradient grad =
g->component(var_component,
1513 for (
unsigned int i=0; i!= dim; ++i)
1515 Ue(current_dof) = grad(i);
1516 dof_is_fixed[current_dof] =
true;
1521 libmesh_error_msg(
"Unknown continuity " << cont);
1526 for (
unsigned short e = 0; e != n_edges; ++e)
1528 if (!is_boundary_edge[e])
1534 const unsigned int n_side_dofs =
1535 cast_int<unsigned int>(side_dofs.size());
1539 unsigned int free_dofs = 0;
1540 for (
auto i : IntRange<unsigned int>(0, n_side_dofs))
1541 if (!dof_is_fixed[side_dofs[i]])
1542 free_dof[free_dofs++] = i;
1548 Ke.resize (free_dofs, free_dofs); Ke.zero();
1549 Fe.resize (free_dofs); Fe.zero();
1551 DenseVector<Number> Uedge(free_dofs);
1554 fe->attach_quadrature_rule (qedgerule.get());
1555 fe->edge_reinit (elem, e);
1556 const unsigned int n_qp = qedgerule->n_points();
1559 for (
unsigned int qp=0; qp<n_qp; qp++)
1562 Number fineval =
f->component(var_component,
1568 finegrad =
g->component(var_component,
1573 for (
unsigned int sidei=0, freei=0;
1574 sidei != n_side_dofs; ++sidei)
1576 unsigned int i = side_dofs[sidei];
1578 if (dof_is_fixed[i])
1580 for (
unsigned int sidej=0, freej=0;
1581 sidej != n_side_dofs; ++sidej)
1583 unsigned int j = side_dofs[sidej];
1584 if (dof_is_fixed[j])
1585 Fe(freei) -= phi[i][qp] * phi[j][qp] *
1588 Ke(freei,freej) += phi[i][qp] *
1589 phi[j][qp] * JxW[qp];
1592 if (dof_is_fixed[j])
1593 Fe(freei) -= ((*dphi)[i][qp] *
1597 Ke(freei,freej) += ((*dphi)[i][qp] *
1601 if (!dof_is_fixed[j])
1604 Fe(freei) += phi[i][qp] * fineval * JxW[qp];
1606 Fe(freei) += (finegrad * (*dphi)[i][qp]) *
1612 Ke.cholesky_solve(Fe, Uedge);
1615 for (
unsigned int i=0; i != free_dofs; ++i)
1617 Number & ui = Ue(side_dofs[free_dof[i]]);
1621 dof_is_fixed[side_dofs[free_dof[i]]] =
true;
1627 for (
unsigned short s = 0; s != n_sides; ++s)
1629 if (!is_boundary_side[s])
1637 unsigned int free_dofs = 0;
1639 if (!dof_is_fixed[side_dofs[i]])
1640 free_dof[free_dofs++] = i;
1646 Ke.resize (free_dofs, free_dofs); Ke.zero();
1647 Fe.resize (free_dofs); Fe.zero();
1649 DenseVector<Number> Uside(free_dofs);
1652 fe->attach_quadrature_rule (qsiderule.get());
1653 fe->reinit (elem, s);
1654 const unsigned int n_qp = qsiderule->n_points();
1656 const unsigned int n_side_dofs =
1657 cast_int<unsigned int>(side_dofs.size());
1660 for (
unsigned int qp=0; qp<n_qp; qp++)
1663 Number fineval =
f->component(var_component,
1669 finegrad =
g->component(var_component,
1674 for (
unsigned int sidei=0, freei=0;
1675 sidei != n_side_dofs; ++sidei)
1677 unsigned int i = side_dofs[sidei];
1679 if (dof_is_fixed[i])
1681 for (
unsigned int sidej=0, freej=0;
1682 sidej != n_side_dofs; ++sidej)
1684 unsigned int j = side_dofs[sidej];
1685 if (dof_is_fixed[j])
1686 Fe(freei) -= phi[i][qp] * phi[j][qp] *
1689 Ke(freei,freej) += phi[i][qp] *
1690 phi[j][qp] * JxW[qp];
1693 if (dof_is_fixed[j])
1694 Fe(freei) -= ((*dphi)[i][qp] *
1698 Ke(freei,freej) += ((*dphi)[i][qp] *
1702 if (!dof_is_fixed[j])
1705 Fe(freei) += (fineval * phi[i][qp]) * JxW[qp];
1707 Fe(freei) += (finegrad * (*dphi)[i][qp]) *
1713 Ke.cholesky_solve(Fe, Uside);
1716 for (
unsigned int i=0; i != free_dofs; ++i)
1718 Number & ui = Ue(side_dofs[free_dof[i]]);
1722 dof_is_fixed[side_dofs[free_dof[i]]] =
true;
1734 for (
unsigned int i = 0; i < n_dofs; i++)
1735 if (dof_is_fixed[i] &&
1736 (dof_indices[i] >= first) &&
1737 (dof_indices[i] < last))
static void dofs_on_edge(const Elem *const elem, const unsigned int dim, const FEType &fe_t, unsigned int e, std::vector< unsigned int > &di)
unsigned int variable_scalar_number(const std::string &var, unsigned int component) const
static void dofs_on_side(const Elem *const elem, const unsigned int dim, const FEType &fe_t, unsigned int s, std::vector< unsigned int > &di)
std::unique_ptr< FunctionBase< Number > > f
IntRange< std::size_t > index_range(const std::vector< T > &vec)
static const Real TOLERANCE
const std::vector< unsigned int > & variables
const BoundaryInfo & get_boundary_info() const
const MeshBase & get_mesh() const
const dof_id_type n_nodes
NumericVector< Number > & new_vector
NumberVectorValue Gradient
static std::unique_ptr< FEGenericBase > build(const unsigned int dim, const FEType &type)
static unsigned int n_dofs_at_node(const unsigned int dim, const FEType &fe_t, const ElemType t, const unsigned int n)
virtual numeric_index_type first_local_index() const =0
unsigned int mesh_dimension() const
virtual void set(const numeric_index_type i, const T value)=0
const std::set< boundary_id_type > & b
std::unique_ptr< FunctionBase< Gradient > > g
const DofMap & get_dof_map() const
virtual numeric_index_type last_local_index() const =0