2026{
2027 LOG_SCOPE ("project_vertices","GenericProjector");
2028
2030
2031
2032
2033 std::vector<unsigned short> extra_hanging_dofs;
2035 {
2036 if (extra_hanging_dofs.size() <= v_num)
2037 extra_hanging_dofs.resize(v_num+1, false);
2038 extra_hanging_dofs[v_num] =
2040 }
2041
2042 for (const auto & v_pair : range)
2043 {
2044 const Node & vertex = *v_pair.first;
2045 const Elem & elem = *std::get<0>(v_pair.second);
2046 const unsigned int n = std::get<1>(v_pair.second);
2047 const var_set & vertex_vars = std::get<2>(v_pair.second);
2048
2050
2052
2053
2054
2055 for (const auto & var : vertex_vars)
2056 {
2058 const FEType & base_fe_type = variable.
type();
2059 const unsigned int var_component =
2061
2062 if (base_fe_type.family ==
SCALAR)
2063 continue;
2064
2067
2069 {
2070 libmesh_assert_equal_to(vertex.n_comp(sys_num, var), 0);
2071 }
2072 else if (cont ==
C_ZERO ||
2074 {
2076 elem.dim() != 1)
2077 {
2078 libmesh_assert_equal_to(vertex.n_comp(sys_num, var), 0);
2079 continue;
2080 }
2081
2082 const FValue val =
f.eval_at_node
2084 vertex, extra_hanging_dofs[var],
system.
time);
2085
2087 {
2088 libmesh_assert_equal_to(vertex.n_comp(sys_num, var), elem.dim());
2089
2090
2092 {
2093 const dof_id_type id = vertex.dof_number(sys_num, var, i);
2094
2095
2096
2097 const auto insert_val =
2098 raw_value<typename ProjectionAction::InsertInput>(val, i);
2099
2100 insert_id(
id, insert_val, vertex.processor_id());
2101 }
2102 }
2103 else
2104 {
2105
2106
2107
2108
2109
2110
2111 const dof_id_type id = vertex.dof_number(sys_num, var, 0);
2112 insert_id(
id, val, vertex.processor_id());
2113 }
2114 }
2115 else if (cont ==
C_ONE)
2116 {
2118 const dof_id_type first_id = vertex.dof_number(sys_num, var, 0);
2119
2120
2121
2122
2123
2124
2125 const int dim = elem.dim();
2126#ifndef NDEBUG
2127
2128
2129
2130
2131
2133 {
2135 libmesh_assert_equal_to(
dim, e.dim());
2136 }
2137#endif
2138#ifdef LIBMESH_ENABLE_AMR
2139 bool is_old_vertex = true;
2141 {
2142 const int i_am_child =
2143 elem.parent()->which_child_am_i(&elem);
2144 is_old_vertex =
2145 elem.parent()->is_vertex_on_parent(i_am_child, n);
2146 }
2147#else
2148 const bool is_old_vertex = false;
2149#endif
2150
2151
2152 if (base_fe_type.family ==
HERMITE)
2153 {
2154 const FValue val =
2156 var_component,
2158 vertex,
2159 extra_hanging_dofs[var],
2161 insert_id(first_id, val, vertex.processor_id());
2162
2163 typename GFunctor::FunctorValue grad =
2164 is_old_vertex ?
2166 var_component,
2168 vertex,
2169 extra_hanging_dofs[var],
2172 var_component,
2173 vertex,
2175 false);
2176
2178 vertex.processor_id());
2179#if LIBMESH_DIM > 1
2180 if (
dim > 1 && is_old_vertex &&
f.is_grid_projection())
2181 {
2182 for (
int i = 1; i <
dim; ++i)
2184 vertex.processor_id());
2185
2186
2187 std::vector<FValue> derivs;
2188 f.eval_mixed_derivatives
2189 (
context, var_component,
dim, vertex, derivs);
2192 vertex.processor_id());
2193 }
2195 {
2196
2197
2198
2199
2201
2202 Point nxminus = elem.point(n),
2203 nxplus = elem.point(n);
2204 nxminus(0) -= delta_x;
2205 nxplus(0) += delta_x;
2206 typename GFunctor::FunctorValue gxminus =
2208 var_component,
2209 nxminus,
2211 true);
2212 typename GFunctor::FunctorValue gxplus =
2214 var_component,
2215 nxplus,
2217 true);
2218
2220 vertex.processor_id());
2221
2223 (grad_component(gxplus, 1) - grad_component(gxminus, 1)) / 2. / delta_x,
2224 vertex.processor_id());
2225
2226#if LIBMESH_DIM > 2
2228 {
2229
2231 vertex.processor_id());
2232
2234 (grad_component(gxplus, 2) - grad_component(gxminus, 2)) / 2. / delta_x,
2235 vertex.processor_id());
2236
2237
2238 Point nyminus = elem.point(n),
2239 nyplus = elem.point(n);
2240 nyminus(1) -= delta_x;
2241 nyplus(1) += delta_x;
2242 typename GFunctor::FunctorValue gyminus =
2244 var_component,
2245 nyminus,
2247 true);
2248 typename GFunctor::FunctorValue gyplus =
2250 var_component,
2251 nyplus,
2253 true);
2254
2256 (grad_component(gyplus, 2) - grad_component(gyminus, 2)) / 2. / delta_x,
2257 vertex.processor_id());
2258
2259 Point nxmym = elem.point(n),
2260 nxmyp = elem.point(n),
2261 nxpym = elem.point(n),
2262 nxpyp = elem.point(n);
2263 nxmym(0) -= delta_x;
2264 nxmym(1) -= delta_x;
2265 nxmyp(0) -= delta_x;
2266 nxmyp(1) += delta_x;
2267 nxpym(0) += delta_x;
2268 nxpym(1) -= delta_x;
2269 nxpyp(0) += delta_x;
2270 nxpyp(1) += delta_x;
2271 typename GFunctor::FunctorValue gxmym =
2273 var_component,
2274 nxmym,
2276 true);
2277 typename GFunctor::FunctorValue gxmyp =
2279 var_component,
2280 nxmyp,
2282 true);
2283 typename GFunctor::FunctorValue gxpym =
2285 var_component,
2286 nxpym,
2288 true);
2289 typename GFunctor::FunctorValue gxpyp =
2291 var_component,
2292 nxpyp,
2294 true);
2295 FValue gxzplus = (grad_component(gxpyp, 2) - grad_component(gxmyp, 2))
2296 / 2. / delta_x;
2297 FValue gxzminus = (grad_component(gxpym, 2) - grad_component(gxmym, 2))
2298 / 2. / delta_x;
2299
2301 (gxzplus - gxzminus) / 2. / delta_x,
2302 vertex.processor_id());
2303 }
2304#endif
2305 }
2306#endif
2307 }
2308 else
2309 {
2310
2311
2312
2313 libmesh_assert_equal_to(
2315 base_fe_type,
2316 &elem,
2317 elem.get_node_index(&vertex),
2318 base_fe_type.p_refinement),
2319 (
unsigned int)(1 +
dim));
2320
2321 const FValue val =
2323 vertex, extra_hanging_dofs[var],
2325 insert_id(first_id, val, vertex.processor_id());
2326 typename GFunctor::FunctorValue grad =
2327 is_old_vertex ?
2329 vertex, extra_hanging_dofs[var],
2331 g->eval_at_point(
context, var_component, vertex,
2333 for (
int i=0; i!=
dim; ++i)
2334 insert_id(first_id + i + 1, grad.slice(i),
2335 vertex.processor_id());
2336 }
2337 }
2338 else
2339 libmesh_error_msg("Unknown continuity " << cont);
2340 }
2341 }
2342}
static unsigned int n_dofs_at_node(const unsigned int dim, const FEType &fe_t, const ElemType t, const unsigned int n)
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.
const std::vector< unsigned int > & variables
std::set< unsigned int > var_set
virtual const Elem & elem_ref(const dof_id_type i) const
unsigned int variable_scalar_number(std::string_view var, unsigned int component) const
unsigned int number() const
const FEType & type() const
auto index_range(const T &sizable)
Helper function that returns an IntRange<std::size_t> representing all the indices of the passed-in v...
static constexpr Real TOLERANCE
DIE A HORRIBLE DEATH HERE typedef LIBMESH_DEFAULT_SCALAR_TYPE Real
std::vector< FEFieldType > field_types
void insert_id(dof_id_type id, const InsertInput &val, processor_id_type pid)
std::unique_ptr< GFunctor > g
std::vector< FEContinuity > conts
void find_dofs_to_send(const Node &node, const Elem &elem, unsigned short node_num, const var_set &vars)