https://mooseframework.inl.gov
Loading...
Searching...
No Matches
FaceCenteredMapFunctor.C
Go to the documentation of this file.
1//* This file is part of the MOOSE framework
2//* https://mooseframework.inl.gov
3//*
4//* All rights reserved, see COPYRIGHT for full restrictions
5//* https://github.com/idaholab/moose/blob/master/COPYRIGHT
6//*
7//* Licensed under LGPL 2.1, please see LICENSE for details
8//* https://www.gnu.org/licenses/lgpl-2.1.html
9
11#include "FaceInfo.h"
12#include "FVUtils.h"
13#include "libmesh/compare_types.h"
14#include "libmesh/type_tensor.h"
15#include "libmesh/tensor_tools.h"
16#include "libmesh/dense_matrix.h"
17#include "libmesh/elem.h"
18#include "libmesh/point.h"
19
20namespace Moose
21{
22template <typename T, typename T2, typename std::enable_if<ScalarTraits<T>::value, int>::type = 0>
23inline TypeVector<typename libMesh::CompareTypes<T, T2>::supertype>
24outer_product(const T & a, const TypeVector<T2> & b)
25{
26 TypeVector<typename libMesh::CompareTypes<T, T2>::supertype> ret;
27 for (const auto i : make_range(Moose::dim))
28 ret(i) = a * b(i);
29
30 return ret;
31}
32
33template <typename T, typename T2>
34inline TypeTensor<typename libMesh::CompareTypes<T, T2>::supertype>
35outer_product(const TypeVector<T> & a, const TypeVector<T2> & b)
36{
37 return libMesh::outer_product(a, b);
38}
39}
40
41template <typename T, typename Map>
44{
45 // The following reconstruction is based on Weller's method. For more information on this,
46 // we recommend:
47 //
48 // Weller, Hilary. "Non-orthogonal version of the arbitrary polygonal C-grid and a new diamond
49 // grid." Geoscientific Model Development 7.3 (2014): 779-797.
50 //
51 // and
52 //
53 // Aguerre, Horacio J., et al. "An oscillation-free flow solver based on flux reconstruction."
54 // Journal of Computational Physics 365 (2018): 135-148.
55 //
56 // This basically reconstructs the cell value based on flux values as follows:
57 //
58 // $\left( \sum_f n_f \outer S_f \right)^{-1} \sum_f (\phi_f \cdot S_f)n_f$
59 //
60 // where $S_f$ is the surface normal vector, $n_f$ is the unit surface vector and $\phi_f$ is a
61 // vector value on the field. Hence the restriction to vector values.
62
65 // Primitive type one rank below the type of the stored data (T). If we are storing a rank two
66 // tensor, this is a vector, if we are storing a vector this is just a number
67 using PrimitiveType = typename MetaPhysicL::ReplaceAlgebraicType<
68 T,
69 typename TensorTools::DecrementRank<typename MetaPhysicL::ValueType<T>::type>::type>::type;
70
72 {
73 const auto dim = _mesh.dimension();
74 // The reason why these are DenseVector/Matrix is that when the mesh dimension is lower than 3,
75 // we get singular matrixes if we try to invert TensorValues.
76 DenseMatrix<PrimitiveType> n_x_Sf(dim, dim);
77 DenseVector<PrimitiveType> sum_normal_flux(dim);
78
79 const Elem * const elem = elem_arg.elem;
80
81 for (const auto side : make_range(elem->n_sides()))
82 {
83 const Elem * const neighbor = elem->neighbor_ptr(side);
84
85 // We need to check if the faceinfo belongs to the element or the neighbor. Based on that we
86 // query the faceinfo and adjust the normal to point outward of the current cell
87 const bool elem_has_fi = Moose::FV::elemHasFaceInfo(*elem, neighbor);
88 const FaceInfo * const fi = _mesh.faceInfo(
89 elem_has_fi ? elem : neighbor, elem_has_fi ? side : neighbor->which_neighbor_am_i(elem));
90 const Point & normal = elem_has_fi ? fi->normal() : Point(-fi->normal());
91
92 const Point area_vector = normal * fi->faceArea();
93 const ValueType face_value = this->evaluate(fi);
94
95 const auto product = Moose::outer_product(normal, area_vector);
96
97 const auto flux_contrib = normal * (face_value * area_vector);
98 for (const auto i : make_range(dim))
99 {
100 sum_normal_flux(i) += flux_contrib(i);
101 for (const auto j : make_range(dim))
102 n_x_Sf(i, j) += product(i, j);
103 }
104 }
105
106 // We do the inversion of the surface vector matrix here. It is symmetric
107 // and small so we can do it using a Cholesky decomposition.
108 DenseVector<PrimitiveType> dense_result(dim);
109 n_x_Sf.cholesky_solve(sum_normal_flux, dense_result);
110
111 ValueType result;
112 for (const auto i : make_range(dim))
113 result(i) = dense_result(i);
114
115 return result;
116 }
117 else
118 {
119 (void)elem_arg; // WE do this because the GCC min complains that it is not used and
120 // [[maybe_unused]] doesnt work for GCC min
121 mooseError("Cell center reconstruction is not implemented!");
122 }
123}
124
125template <typename T, typename Map>
128{
129 return this->evaluate(face.fi);
130}
131
132template <typename T, typename Map>
135{
136 auto it = this->find(fi->id());
137 if (it == this->end())
138 {
139 if (!_sub_ids.empty() && !_sub_ids.count(fi->elem().subdomain_id()))
140 {
141 if (fi->neighborPtr() && !_sub_ids.count(fi->neighborPtr()->subdomain_id()))
142 mooseError("Attempted to evaluate FaceCenteredMapFunctor '",
143 this->functorName(),
144 "' with an element subdomain id of '",
145 fi->elem().subdomain_id(),
146 fi->neighborPtr() ? " or neighbor subdomain id of '" +
147 std::to_string(fi->neighborPtr()->subdomain_id()) + "'"
148 : "",
149 "' but that subdomain id is not one of the subdomain ids the functor is "
150 "restricted to.");
151 }
152 else
153 mooseError("Attempted access into FaceCenteredMapFunctor '",
154 this->functorName(),
155 "' with a key that does not yet exist in the map. Make sure to fill your "
156 "FaceCenteredMapFunctor for all elements you will attempt to access later.");
157
159 }
160
161 return it->second;
162}
163
165 std::unordered_map<dof_id_type, ADRealVectorValue>>;
166template class FaceCenteredMapFunctor<RealVectorValue,
167 std::unordered_map<dof_id_type, RealVectorValue>>;
const double T
void mooseError(Args &&... args)
T evaluate(Real, const Point &)
unsigned int dim
A functor whose evaluation relies on querying a map where the keys are face info ids and the values c...
ValueType evaluate(const FaceInfo *const fi) const
Evaluate the face functor using a FaceInfo argument.
const Point & normal() const
const Elem & elem() const
const Elem * neighborPtr() const
Real faceArea() const
dof_id_type id() const
const Elem * neighbor_ptr(unsigned int i) const
bool elemHasFaceInfo(const Elem &elem, const Elem *const neighbor)
static constexpr std::size_t dim
TypeVector< typename libMesh::CompareTypes< T, T2 >::supertype > outer_product(const T &a, const TypeVector< T2 > &b)
TypeTensor< typename CompareTypes< T, T2 >::supertype > outer_product(const TypeVector< T > &a, const TypeVector< T2 > &b)
const libMesh::Elem * elem
const FaceInfo * fi