71 const bool two_term_expansion,
72 const bool correct_skewness,
73 const Elem * elem_to_extrapolate_from,
77 bool elem_to_extrapolate_from_is_fi_elem;
78 std::tie(elem_to_extrapolate_from, elem_to_extrapolate_from_is_fi_elem) =
79 [
this, &fi, elem_to_extrapolate_from]() -> std::pair<const Elem *, bool>
81 if (elem_to_extrapolate_from)
82 return {elem_to_extrapolate_from, elem_to_extrapolate_from == &fi.
elem()};
85 const auto [elem_guaranteed_to_have_dofs,
87 elem_guaranteed_to_have_dofs_is_fi_elem] =
89 libmesh_ignore(other_elem);
90 return {elem_guaranteed_to_have_dofs, elem_guaranteed_to_have_dofs_is_fi_elem};
96 const Point vector_to_face = elem_to_extrapolate_from_is_fi_elem
104 fi, two_term_expansion, correct_skewness, elem_to_extrapolate_from, time);
106 return boundary_value;
130 bool correct_skewness)
const
149 std::vector<std::pair<const FaceInfo *, bool>> ebf_faces;
153 VectorValue<ADReal> & grad = *value_pointer;
155 bool volume_set =
false;
191 std::vector<VectorValue<Real>> ebf_grad_coeffs;
194 std::vector<const ADReal *> ebf_b;
197 std::vector<VectorValue<Real>> grad_ebf_coeffs;
199 VectorValue<ADReal> grad_b = 0;
203 std::vector<TensorValue<Real>> fdf_grad_centroid_coeffs;
205 const unsigned int lm_dim = LIBMESH_DIM;
207 auto action_functor = [&volume_set,
218 &fdf_grad_centroid_coeffs,
221 this](
const Elem & functor_elem,
222 const Elem *
const neighbor,
224 const Point & surface_vector,
226 const bool elem_has_info)
228 mooseAssert(fi,
"We need a FaceInfo for this action_functor");
229 mooseAssert(elem == &functor_elem,
230 "Just a sanity check that the element being passed in is the one we passed out.");
237 ebf_faces.push_back(std::make_pair(fi, fdf_face));
240 ebf_grad_coeffs.push_back(-1. * (elem_has_info
241 ? (fi->faceCentroid() - fi->elemCentroid())
242 : (fi->faceCentroid() - fi->neighborCentroid())));
243 ebf_b.push_back(&elem_value);
246 grad_ebf_coeffs.push_back(-surface_vector);
252 fdf_grad_centroid_coeffs.emplace_back();
253 auto & current_coeffs = fdf_grad_centroid_coeffs.back();
254 const auto normal = fi->normal();
255 for (
const auto i : make_range(lm_dim))
256 for (
const auto j : make_range(lm_dim))
258 auto & current_coeff = current_coeffs(i, j);
259 current_coeff = normal(i) * normal(j);
270 grad_b += surface_vector * elem_value;
275 Moose::FV::LimiterType::CentralDifference,
284 "We've run out of face types");
295 this->
_subproblem, functor_elem.subdomain_id(), fi->elemCentroid(), coord);
296 volume = fi->elemVolume() * coord;
301 this->
_subproblem, neighbor->subdomain_id(), fi->neighborCentroid(), coord);
302 volume = fi->neighborVolume() * coord;
311 mooseAssert(volume_set && volume > 0,
"We should have set the volume");
315 if (coord_system == Moose::CoordinateSystemType::COORD_RZ)
318 grad_b(r_coord) -= elem_value / elem->vertex_average()(r_coord);
322 coord_system != Moose::CoordinateSystemType::COORD_RSPHERICAL,
323 "We have not yet implemented the correct translation from gradient to divergence for "
324 "spherical coordinates yet.");
327 ebf_faces.size() < UINT_MAX,
328 "You've created a mystical element that has more faces than can be held by unsigned "
329 "int. I applaud you.");
330 const auto num_ebfs =
static_cast<unsigned int>(ebf_faces.size());
338 const unsigned int sys_dim =
339 lm_dim + num_ebfs + lm_dim *
static_cast<unsigned int>(fdf_grad_centroid_coeffs.size());
340 DenseVector<ADReal>
x(sys_dim),
b(sys_dim);
341 DenseMatrix<ADReal>
A(sys_dim, sys_dim);
344 for (
const auto lm_dim_index : make_range(lm_dim))
347 A(lm_dim_index, lm_dim_index) = 1;
350 for (
const auto ebf_index : make_range(num_ebfs))
351 A(lm_dim_index, lm_dim + ebf_index) = grad_ebf_coeffs[ebf_index](lm_dim_index) / volume;
354 b(lm_dim_index) = grad_b(lm_dim_index);
357 unsigned int num_fdf_faces = 0;
360 for (
const auto ebf_index : make_range(num_ebfs))
363 A(lm_dim + ebf_index, lm_dim + ebf_index) = 1;
365 const bool fdf_face = ebf_faces[ebf_index].second;
366 const unsigned int starting_j_index =
367 fdf_face ? lm_dim + num_ebfs + num_fdf_faces * lm_dim : 0;
369 num_fdf_faces += fdf_face;
372 for (
const auto lm_dim_index : make_range(lm_dim))
373 A(lm_dim + ebf_index, starting_j_index + lm_dim_index) =
374 ebf_grad_coeffs[ebf_index](lm_dim_index);
377 b(lm_dim + ebf_index) = *ebf_b[ebf_index];
380 mooseAssert(num_fdf_faces == fdf_grad_centroid_coeffs.size(),
381 "Bad math in INSFVVelocityVariable::adGradlnSln(const Elem *). Please contact a "
385 for (
const auto fdf_face_index : make_range(num_fdf_faces))
387 const auto starting_i_index = lm_dim + num_ebfs + fdf_face_index * lm_dim;
389 for (
const auto lm_dim_i_index : make_range(lm_dim))
391 auto i_index = starting_i_index + lm_dim_i_index;
392 A(i_index, i_index) = 1;
394 for (
const auto lm_dim_j_index : make_range(lm_dim))
396 A(i_index, lm_dim_j_index) =
397 fdf_grad_centroid_coeffs[fdf_face_index](lm_dim_i_index, lm_dim_j_index);
402 for (
const auto lm_dim_index : make_range(lm_dim))
403 grad(lm_dim_index) =
x(lm_dim_index);
409 mooseAssert(pr.second,
"Insertion should have just happened.");
410 return pr.first->second;
415 catch (std::exception & e)
419 if (!strstr(e.what(),
"singular"))
424 "I believe we should only get singular systems when two-term boundary expansion is "
427 const auto & grad =
adGradSln(elem, time, correct_skewness);