VertexCFD  0.0-dev
VertexCFD_Closure_SingularValueElementLength_impl.hpp
1 #ifndef VERTEXCFD_CLOSURE_SINGULARVALUEELEMENTLENGTH_IMPL_HPP
2 #define VERTEXCFD_CLOSURE_SINGULARVALUEELEMENTLENGTH_IMPL_HPP
3 
4 #include <Panzer_HierarchicParallelism.hpp>
5 #include <Panzer_Workset_Utilities.hpp>
6 
7 #include <algorithm>
8 #include <cmath>
9 
17 namespace VertexCFD
18 {
19 namespace ClosureModel
20 {
21 //---------------------------------------------------------------------------//
22 template<class EvalType, class Traits>
23 SingularValueElementLength<EvalType, Traits>::SingularValueElementLength(
24  const panzer::IntegrationRule& ir,
25  const std::string& method,
26  const std::string& prefix)
27  : _element_length(prefix + "element_length", ir.dl_vector)
28  , _ir_degree(ir.cubature_degree)
29 {
30  if (method == "singular_value_min")
31  {
32  _method = Method::Min;
33  }
34  else if (method == "singular_value_max")
35  {
36  _method = Method::Max;
37  }
38  else
39  {
40  const std::string msg =
41  "Element Length Method '" + method +
42  "' is not a correct input.\n"
43  "Choose between 'singular_value_min' or 'singular_value_max'";
44  throw std::runtime_error(msg);
45  }
46 
47  this->addEvaluatedField(_element_length);
48  this->setName("Singular Value Element Length");
49 }
50 
51 //---------------------------------------------------------------------------//
52 template<class EvalType, class Traits>
53 void SingularValueElementLength<EvalType, Traits>::postRegistrationSetup(
54  typename Traits::SetupData sd, PHX::FieldManager<Traits>&)
55 {
56  _ir_index = panzer::getIntegrationRuleIndex(_ir_degree, (*sd.worksets_)[0]);
57 }
58 
59 //---------------------------------------------------------------------------//
60 template<class EvalType, class Traits>
61 void SingularValueElementLength<EvalType, Traits>::evaluateFields(
62  typename Traits::EvalData workset)
63 {
64  _cell_jac = workset.int_rules[_ir_index]->jac;
65  auto policy = panzer::HP::inst().teamPolicy<scalar_type, PHX::Device>(
66  workset.num_cells);
67  Kokkos::parallel_for(this->getName(), policy, *this);
68 }
69 
70 //---------------------------------------------------------------------------//
71 template<class EvalType, class Traits>
72 KOKKOS_INLINE_FUNCTION void
73 SingularValueElementLength<EvalType, Traits>::operator()(
74  const Kokkos::TeamPolicy<PHX::exec_space>::member_type& team) const
75 {
76  const int cell = team.league_rank();
77  const int num_point = _element_length.extent(1);
78  const int num_space_dim = _element_length.extent(2);
79 
80  Kokkos::parallel_for(
81  Kokkos::TeamThreadRange(team, 0, num_point), [&](const int point) {
82  using std::sqrt;
83  using std::fmin;
84  using std::fmax;
85 
86  // Calculate the singular values of the jacobian matrix 'J' for
87  // cell 'cell' and point 'point'. The singular values are the
88  // square roots of the eigenvalues of the symmetric matrix 'J \cdot
89  // J^t' that are computed by finding the roots of the quadratic
90  // polynomial 'a \lambda^2 + b \lambda + c'
91  const auto a11 = _cell_jac(cell, point, 0, 0);
92  const auto a12 = _cell_jac(cell, point, 0, 1);
93  const auto a21 = _cell_jac(cell, point, 1, 0);
94  const auto a22 = _cell_jac(cell, point, 1, 1);
95 
96  // Set the coefficients 'a', 'b' and 'c'
97  const double a = 1.0;
98  const double b = -(a11 * a11 + a12 * a12 + a21 * a21 + a22 * a22);
99  const double c = -(a11 * a21 + a12 * a22) * (a11 * a21 + a12 * a22)
100  + (a11 * a11 + a12 * a12)
101  * (a21 * a21 + a22 * a22);
102 
103  // Compute delta value and make it is positive
104  const double delta = fmax(b * b - 4 * a * c, 0.0);
105 
106  // Compute eigenvalues 'lambda1' and 'lambda2'
107  const double lambda1 = 0.5 * (-b - sqrt(delta)) / a;
108  const double lambda2 = 0.5 * (-b + sqrt(delta)) / a;
109 
110  // Set 'h' based on the value of 'method'
111  const double h2 = _method == Method::Min ? fmin(lambda1, lambda2)
112  : fmax(lambda1, lambda2);
113  const double h = sqrt(h2);
114 
115  // Set value of the element length (same value for all
116  // directions)
117  for (int i = 0; i < num_space_dim; i++)
118  {
119  _element_length(cell, point, i) = h;
120  }
121  });
122 }
123 
124 //---------------------------------------------------------------------------//
125 
126 } // end namespace ClosureModel
127 } // end namespace VertexCFD
128 
129 #endif // end VERTEXCFD_CLOSURE_SINGULARVALUEELEMENTLENGTH_IMPL_HPP
VertexCFD
Definition: tstMethodManufacturedSolutionBC.cpp:23