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.
1553 const BoundaryInfo & boundary_info =
1561 DenseVector<Number> Fe;
1563 DenseVector<Number> Ue;
1571 const Variable & variable = dof_map.variable(var);
1573 const FEType & fe_type = variable.type();
1575 if (fe_type.family ==
SCALAR)
1578 const unsigned int var_component =
1585 std::unique_ptr<QBase> qedgerule (fe_type.default_quadrature_rule(1));
1586 std::unique_ptr<QBase> qsiderule (fe_type.default_quadrature_rule(
dim-1));
1590 const std::vector<std::vector<Real>> & phi = fe->get_phi();
1594 const std::vector<std::vector<RealGradient>> * dphi =
nullptr;
1603 const std::vector<std::vector<RealGradient>> &
1604 ref_dphi = fe->get_dphi();
1609 const std::vector<Real> & JxW =
1613 const std::vector<Point> & xyz_values =
1617 std::vector<dof_id_type> dof_indices;
1619 std::vector<unsigned int> side_dofs;
1622 std::vector<boundary_id_type> bc_ids;
1625 for (
const auto & elem : range)
1629 if (!variable.active_on_subdomain(elem->subdomain_id()))
1632 const unsigned short n_nodes = elem->n_nodes();
1633 const unsigned short n_edges = elem->n_edges();
1634 const unsigned short n_sides = elem->n_sides();
1638 std::vector<bool> is_boundary_node(
n_nodes,
false),
1639 is_boundary_edge(n_edges,
false),
1640 is_boundary_side(n_sides,
false);
1643 std::vector<bool> is_boundary_nodeset(
n_nodes,
false);
1645 for (
unsigned char s=0; s != n_sides; ++s)
1648 boundary_info.boundary_ids (elem, s, bc_ids);
1649 bool do_this_side =
false;
1650 for (
const auto & bc_id : bc_ids)
1653 do_this_side =
true;
1659 is_boundary_side[s] =
true;
1662 for (
unsigned int n=0; n !=
n_nodes; ++n)
1663 if (elem->is_node_on_side(n,s))
1664 is_boundary_node[n] =
true;
1665 for (
unsigned int e=0; e != n_edges; ++e)
1666 if (elem->is_edge_on_side(e,s))
1667 is_boundary_edge[e] =
true;
1672 for (
unsigned int n=0; n !=
n_nodes; ++n)
1674 boundary_info.boundary_ids (elem->node_ptr(n), bc_ids);
1676 for (
const auto & bc_id : bc_ids)
1679 is_boundary_node[n] =
true;
1680 is_boundary_nodeset[n] =
true;
1686 for (
unsigned short e=0; e != n_edges; ++e)
1688 boundary_info.edge_boundary_ids (elem, e, bc_ids);
1690 for (
const auto & bc_id : bc_ids)
1692 is_boundary_edge[e] =
true;
1697 dof_map.dof_indices (elem, dof_indices, var);
1700 const unsigned int n_dofs =
1701 cast_int<unsigned int>(dof_indices.size());
1704 std::vector<char> dof_is_fixed(n_dofs,
false);
1705 std::vector<int> free_dof(n_dofs, 0);
1708 Ue.resize (n_dofs); Ue.zero();
1717 unsigned int current_dof = 0;
1718 for (
unsigned short n = 0; n !=
n_nodes; ++n)
1724 const unsigned int nc =
1727 if ((!elem->is_vertex(n) || !is_boundary_node[n]) &&
1728 !is_boundary_nodeset[n])
1735 libmesh_assert_equal_to (nc, 0);
1741 libmesh_assert_equal_to (nc, 1);
1742 Ue(current_dof) =
f->component(var_component,
1745 dof_is_fixed[current_dof] =
true;
1749 else if (fe_type.family ==
HERMITE)
1751 Ue(current_dof) =
f->component(var_component,
1754 dof_is_fixed[current_dof] =
true;
1756 Gradient grad =
g->component(var_component,
1760 Ue(current_dof) = grad(0);
1761 dof_is_fixed[current_dof] =
true;
1767 Point nxminus = elem->point(n),
1768 nxplus = elem->point(n);
1771 Gradient gxminus =
g->component(var_component,
1774 Gradient gxplus =
g->component(var_component,
1778 Ue(current_dof) = grad(1);
1779 dof_is_fixed[current_dof] =
true;
1782 Ue(current_dof) = (gxplus(1) - gxminus(1))
1784 dof_is_fixed[current_dof] =
true;
1791 Ue(current_dof) = grad(2);
1792 dof_is_fixed[current_dof] =
true;
1795 Ue(current_dof) = (gxplus(2) - gxminus(2))
1797 dof_is_fixed[current_dof] =
true;
1800 Point nyminus = elem->point(n),
1801 nyplus = elem->point(n);
1804 Gradient gyminus =
g->component(var_component,
1807 Gradient gyplus =
g->component(var_component,
1811 Ue(current_dof) = (gyplus(2) - gyminus(2))
1813 dof_is_fixed[current_dof] =
true;
1816 Point nxmym = elem->point(n),
1817 nxmyp = elem->point(n),
1818 nxpym = elem->point(n),
1819 nxpyp = elem->point(n);
1828 Gradient gxmym =
g->component(var_component,
1831 Gradient gxmyp =
g->component(var_component,
1834 Gradient gxpym =
g->component(var_component,
1837 Gradient gxpyp =
g->component(var_component,
1840 Number gxzplus = (gxpyp(2) - gxmyp(2))
1842 Number gxzminus = (gxpym(2) - gxmym(2))
1845 Ue(current_dof) = (gxzplus - gxzminus)
1847 dof_is_fixed[current_dof] =
true;
1850 #endif // LIBMESH_DIM > 2 1852 #endif // LIBMESH_DIM > 1 1857 else if (cont ==
C_ONE)
1859 libmesh_assert_equal_to (nc, 1 +
dim);
1860 Ue(current_dof) =
f->component(var_component,
1863 dof_is_fixed[current_dof] =
true;
1865 Gradient grad =
g->component(var_component,
1868 for (
unsigned int i=0; i!=
dim; ++i)
1870 Ue(current_dof) = grad(i);
1871 dof_is_fixed[current_dof] =
true;
1876 libmesh_error_msg(
"Unknown continuity " << cont);
1881 for (
unsigned short e = 0; e != n_edges; ++e)
1883 if (!is_boundary_edge[e])
1889 const unsigned int n_side_dofs =
1890 cast_int<unsigned int>(side_dofs.size());
1894 unsigned int free_dofs = 0;
1896 if (!dof_is_fixed[side_dofs[i]])
1897 free_dof[free_dofs++] = i;
1903 Ke.resize (free_dofs, free_dofs); Ke.zero();
1904 Fe.resize (free_dofs); Fe.zero();
1906 DenseVector<Number> Uedge(free_dofs);
1909 fe->attach_quadrature_rule (qedgerule.get());
1910 fe->edge_reinit (elem, e);
1911 const unsigned int n_qp = qedgerule->n_points();
1914 for (
unsigned int qp=0; qp<n_qp; qp++)
1917 Number fineval =
f->component(var_component,
1923 finegrad =
g->component(var_component,
1928 for (
unsigned int sidei=0, freei=0;
1929 sidei != n_side_dofs; ++sidei)
1931 unsigned int i = side_dofs[sidei];
1933 if (dof_is_fixed[i])
1935 for (
unsigned int sidej=0, freej=0;
1936 sidej != n_side_dofs; ++sidej)
1938 unsigned int j = side_dofs[sidej];
1939 if (dof_is_fixed[j])
1940 Fe(freei) -= phi[i][qp] * phi[j][qp] *
1943 Ke(freei,freej) += phi[i][qp] *
1944 phi[j][qp] * JxW[qp];
1947 if (dof_is_fixed[j])
1948 Fe(freei) -= ((*dphi)[i][qp] *
1952 Ke(freei,freej) += ((*dphi)[i][qp] *
1956 if (!dof_is_fixed[j])
1959 Fe(freei) += phi[i][qp] * fineval * JxW[qp];
1961 Fe(freei) += (finegrad * (*dphi)[i][qp]) *
1967 Ke.cholesky_solve(Fe, Uedge);
1970 for (
unsigned int i=0; i != free_dofs; ++i)
1972 Number & ui = Ue(side_dofs[free_dof[i]]);
1976 dof_is_fixed[side_dofs[free_dof[i]]] =
true;
1982 for (
unsigned short s = 0; s != n_sides; ++s)
1984 if (!is_boundary_side[s])
1992 unsigned int free_dofs = 0;
1994 if (!dof_is_fixed[side_dofs[i]])
1995 free_dof[free_dofs++] = i;
2001 Ke.resize (free_dofs, free_dofs); Ke.zero();
2002 Fe.resize (free_dofs); Fe.zero();
2004 DenseVector<Number> Uside(free_dofs);
2007 fe->attach_quadrature_rule (qsiderule.get());
2008 fe->reinit (elem, s);
2009 const unsigned int n_qp = qsiderule->n_points();
2011 const unsigned int n_side_dofs =
2012 cast_int<unsigned int>(side_dofs.size());
2015 for (
unsigned int qp=0; qp<n_qp; qp++)
2018 Number fineval =
f->component(var_component,
2024 finegrad =
g->component(var_component,
2029 for (
unsigned int sidei=0, freei=0;
2030 sidei != n_side_dofs; ++sidei)
2032 unsigned int i = side_dofs[sidei];
2034 if (dof_is_fixed[i])
2036 for (
unsigned int sidej=0, freej=0;
2037 sidej != n_side_dofs; ++sidej)
2039 unsigned int j = side_dofs[sidej];
2040 if (dof_is_fixed[j])
2041 Fe(freei) -= phi[i][qp] * phi[j][qp] *
2044 Ke(freei,freej) += phi[i][qp] *
2045 phi[j][qp] * JxW[qp];
2048 if (dof_is_fixed[j])
2049 Fe(freei) -= ((*dphi)[i][qp] *
2053 Ke(freei,freej) += ((*dphi)[i][qp] *
2057 if (!dof_is_fixed[j])
2060 Fe(freei) += (fineval * phi[i][qp]) * JxW[qp];
2062 Fe(freei) += (finegrad * (*dphi)[i][qp]) *
2068 Ke.cholesky_solve(Fe, Uside);
2071 for (
unsigned int i=0; i != free_dofs; ++i)
2073 Number & ui = Ue(side_dofs[free_dof[i]]);
2077 dof_is_fixed[side_dofs[free_dof[i]]] =
true;
2089 for (
unsigned int i = 0; i < n_dofs; i++)
2090 if (dof_is_fixed[i] &&
2091 (dof_indices[i] >= first) &&
2092 (dof_indices[i] < last))
Real time
For time-dependent problems, this is the time t at the beginning of the current timestep.
unsigned int variable_scalar_number(std::string_view var, unsigned int component) const
static constexpr Real TOLERANCE
std::unique_ptr< FunctionBase< Number > > f
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, const bool add_p_level=true)
Fills the vector di with the local degree of freedom indices associated with edge e of element elem A...
const std::vector< unsigned int > & variables
const BoundaryInfo & get_boundary_info() const
The information about boundary ids on the mesh.
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)
Builds a specific finite element type.
template class LIBMESH_EXPORT DenseMatrix< Real >
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
FEContinuity
defines an enum for finite element types to libmesh_assert a certain level (or type? Hcurl?) of continuity.
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...
unsigned int mesh_dimension() const
virtual void set(const numeric_index_type i, const T value)=0
Sets v(i) = value.
const std::set< boundary_id_type > & b
std::unique_ptr< FunctionBase< Gradient > > g
const DofMap & get_dof_map() 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, const bool add_p_level=true)
Fills the vector di with the local degree of freedom indices associated with side s of element elem A...
virtual numeric_index_type last_local_index() const =0
auto index_range(const T &sizable)
Helper function that returns an IntRange<std::size_t> representing all the indices of the passed-in v...
spin_mutex spin_mtx
A convenient spin mutex object which can be used for obtaining locks.