VertexCFD  0.0-dev
VertexCFD_Closure_MethodManufacturedSolutionSource_impl.hpp
1 #ifndef VERTEXCFD_CLOSURE_METHODMANUFACTUREDSOLUTIONSOURCE_IMPL_HPP
2 #define VERTEXCFD_CLOSURE_METHODMANUFACTUREDSOLUTIONSOURCE_IMPL_HPP
3 
4 #include "utils/VertexCFD_Utils_VectorField.hpp"
5 
6 #include "utils/VertexCFD_Utils_Constants.hpp"
7 
8 #include <Panzer_HierarchicParallelism.hpp>
9 #include <Panzer_Workset_Utilities.hpp>
10 
11 #include <Sacado.hpp>
12 
13 #include <cmath>
14 #include <type_traits>
15 
16 namespace VertexCFD
17 {
18 namespace ClosureModel
19 {
20 //---------------------------------------------------------------------------//
21 template<class EvalType, class Traits, int NumSpaceDim>
22 MethodManufacturedSolutionSource<EvalType, Traits, NumSpaceDim>::
23  MethodManufacturedSolutionSource(const panzer::IntegrationRule& ir,
24  const bool build_viscous_flux,
25  const Teuchos::ParameterList& closure_params)
26  : _continuity_mms_source("MMS_SOURCE_continuity", ir.dl_scalar)
27  , _energy_mms_source("MMS_SOURCE_energy", ir.dl_scalar)
28  , _ir_degree(ir.cubature_degree)
29  , _build_viscous_flux(build_viscous_flux)
30  , _rho(closure_params.get<double>("Density"))
31  , _nu(closure_params.get<double>("Kinematic Viscosity"))
32  , _kappa(0.0)
33 {
34  this->addEvaluatedField(_continuity_mms_source);
35  Utils::addEvaluatedVectorField(
36  *this, ir.dl_scalar, _momentum_mms_source, "MMS_SOURCE_momentum_");
37  this->addEvaluatedField(_energy_mms_source);
38 
39  // MMS function coefficients
40  _phi_coeff[0] = 0.0125;
41  _phi_coeff[1] = 1.0;
42  _phi_coeff[2] = 0.25;
43  _phi_coeff[3] = 0.5;
44  _phi_coeff[4] = 0.125;
45  _phi_coeff[5] = 0.0;
46 
47  _vel_coeff[0][0] = 0.0125;
48  _vel_coeff[0][1] = 0.08;
49  _vel_coeff[0][2] = 0.125;
50  _vel_coeff[0][3] = 0.0;
51  _vel_coeff[0][4] = 0.125;
52  _vel_coeff[0][5] = 0.25;
53 
54  _vel_coeff[1][0] = 0.0375;
55  _vel_coeff[1][1] = 1.125;
56  _vel_coeff[1][2] = 0.25;
57  _vel_coeff[1][3] = 0.0;
58  _vel_coeff[1][4] = 0.375;
59  _vel_coeff[1][5] = 0.5;
60 
61  _T_coeff[0] = 0.0625;
62  _T_coeff[1] = 1.0;
63  _T_coeff[2] = 0.375;
64  _T_coeff[3] = 0.25;
65  _T_coeff[4] = 0.25;
66  _T_coeff[5] = 0.5;
67 
68  if (num_space_dim == 3)
69  {
70  _phi_coeff[6] = 0.375;
71  _phi_coeff[7] = 1.0;
72 
73  _vel_coeff[0][6] = 0.25;
74  _vel_coeff[0][7] = 0.0;
75 
76  _vel_coeff[1][6] = 0.25;
77  _vel_coeff[1][7] = 0.5;
78 
79  _vel_coeff[2][0] = 0.025;
80  _vel_coeff[2][1] = 0.0;
81  _vel_coeff[2][2] = 0.125;
82  _vel_coeff[2][3] = 1.0;
83  _vel_coeff[2][4] = 0.25;
84  _vel_coeff[2][5] = 0.25;
85  _vel_coeff[2][6] = 0.25;
86  _vel_coeff[2][7] = 0.25;
87 
88  _T_coeff[6] = 0.125;
89  _T_coeff[7] = 0.5;
90  }
91 
92  this->setName("Method of Manufactured Solution Source "
93  + std::to_string(num_space_dim) + "D");
94 }
95 
96 //---------------------------------------------------------------------------//
97 template<class EvalType, class Traits, int NumSpaceDim>
98 void MethodManufacturedSolutionSource<EvalType, Traits, NumSpaceDim>::
99  postRegistrationSetup(typename Traits::SetupData sd,
100  PHX::FieldManager<Traits>&)
101 {
102  _ir_index = panzer::getIntegrationRuleIndex(_ir_degree, (*sd.worksets_)[0]);
103 }
104 
105 //---------------------------------------------------------------------------//
106 template<class EvalType, class Traits, int NumSpaceDim>
107 void MethodManufacturedSolutionSource<EvalType, Traits, NumSpaceDim>::evaluateFields(
108  typename Traits::EvalData workset)
109 {
110  _ip_coords = workset.int_rules[_ir_index]->ip_coordinates;
111  const Kokkos::RangePolicy<PHX::Device> policy(0, workset.num_cells);
112  Kokkos::parallel_for(this->getName(), policy, *this);
113 }
114 
115 //---------------------------------------------------------------------------//
116 template<class EvalType, class Traits, int NumSpaceDim>
117 template<typename T>
118 KOKKOS_INLINE_FUNCTION T
119 MethodManufacturedSolutionSource<EvalType, Traits, NumSpaceDim>::set_function(
120  const Kokkos::Array<double, num_coeff>& coeff,
121  const Kokkos::Array<T, num_space_dim>& x) const
122 {
123  using Constants::pi;
124 
125  // Function = B+ A * sin(2*pi*f_x*(x-phi_x)) * sin(2*pi*f_y*(y-phi_y))
126  // * sin(2*pi*f_z*(z-phi_z)) for 3D
127  T val = coeff[0];
128  for (int i = 0; i < num_space_dim; ++i)
129  val *= sin(2.0 * pi * coeff[2 * (i + 1)]
130  * (x[i] - coeff[2 * (i + 1) + 1]));
131  val += coeff[1];
132  return val;
133 }
134 
135 //---------------------------------------------------------------------------//
136 template<class EvalType, class Traits, int NumSpaceDim>
137 KOKKOS_INLINE_FUNCTION void
138 MethodManufacturedSolutionSource<EvalType, Traits, NumSpaceDim>::operator()(
139  const int cell) const
140 {
141  const int num_point = _continuity_mms_source.extent(1);
142  using Constants::pi;
143  const double third = 1.0 / 3.0;
144 
145  for (int point = 0; point < num_point; ++point)
146  {
147  using diff1_type = Sacado::Fad::SFad<scalar_type, num_space_dim>;
148  using diff2_type = Sacado::Fad::SFad<diff1_type, num_space_dim>;
149 
150  // Create independent variables.
151  Kokkos::Array<diff1_type, num_space_dim> diff1_x;
152  Kokkos::Array<diff2_type, num_space_dim> diff2_x;
153 
154  // Assign values
155  for (int i = 0; i < num_space_dim; ++i)
156  diff1_x[i] = _ip_coords(cell, point, i);
157 
158  // Initialize derivative
159  for (int i = 0; i < num_space_dim; ++i)
160  {
161  diff1_x[i].diff(i, num_space_dim);
162  diff2_x[i] = diff1_x[i];
163  }
164 
165  for (int i = 0; i < num_space_dim; ++i)
166  diff2_x[i].diff(i, num_space_dim);
167 
168  // Variables with second derivatives
169  Kokkos::Array<diff2_type, num_space_dim> diff2_vel;
170  for (int i = 0; i < num_space_dim; ++i)
171  diff2_vel[i] = set_function(_vel_coeff[i], diff2_x);
172  const diff2_type diff2_T = set_function(_T_coeff, diff2_x);
173 
174  // diff1 gradients
175  Kokkos::Array<Kokkos::Array<diff1_type, num_space_dim>, num_space_dim>
176  diff1_grad_u;
177  Kokkos::Array<diff1_type, num_space_dim> diff1_grad_T;
178  for (int i = 0; i < num_space_dim; ++i)
179  {
180  for (int j = 0; j < num_space_dim; ++j)
181  diff1_grad_u[i][j] = diff2_vel[i].fastAccessDx(j);
182 
183  diff1_grad_T[i] = diff2_T.fastAccessDx(i);
184  }
185 
186  diff1_type diff1_tr_grad_u = 0.0;
187  for (int i = 0; i < num_space_dim; ++i)
188  diff1_tr_grad_u += diff1_grad_u[i][i];
189  diff1_tr_grad_u *= third;
190 
191  // diff1 primitives
192  const diff1_type diff1_phi = set_function(_phi_coeff, diff1_x);
193 
194  Kokkos::Array<diff1_type, num_space_dim> diff1_vel;
195  for (int i = 0; i < num_space_dim; ++i)
196  diff1_vel[i] = diff2_vel[i].val();
197  const diff1_type diff1_T = diff2_T.val();
198 
200  // Convective flux
202  Kokkos::Array<Kokkos::Array<diff1_type, num_space_dim>, num_conserve>
203  conv_flux;
204 
205  // Convective continuity
206  for (int i = 0; i < num_space_dim; ++i)
207  conv_flux[0][i] = diff1_vel[i];
208 
209  // Convective momentum
210  for (int i = 0; i < num_space_dim; ++i)
211  for (int j = 0; j < num_space_dim; ++j)
212  {
213  conv_flux[i + 1][j] = diff1_vel[i] * diff1_vel[j];
214  if (i == j)
215  conv_flux[i + 1][j] += diff1_phi;
216  }
217 
218  // Convective energy
219  for (int i = 0; i < num_space_dim; ++i)
220  {
221  conv_flux[num_conserve - 1][i] = diff1_T * diff1_vel[i];
222  }
223 
224  // Total flux
225  Kokkos::Array<Kokkos::Array<diff1_type, num_space_dim>, num_conserve> flux;
226  for (int i = 0; i < num_conserve; ++i)
227  for (int j = 0; j < num_space_dim; ++j)
228  flux[i][j] = conv_flux[i][j];
229 
231  // Vicous flux
233  if (_build_viscous_flux)
234  {
235  // Compute viscous stress tensor
236  Kokkos::Array<Kokkos::Array<diff1_type, num_space_dim>, num_space_dim>
237  diff1_tau;
238  for (int i = 0; i < num_space_dim; ++i)
239  for (int j = 0; j < num_space_dim; ++j)
240  {
241  if (i == j)
242  diff1_tau[i][j]
243  = 2.0 * _nu
244  * (diff1_grad_u[i][j] - diff1_tr_grad_u);
245  else
246  diff1_tau[i][j]
247  = _nu * (diff1_grad_u[i][j] + diff1_grad_u[j][i]);
248  }
249 
250  // Vicous flux
251  Kokkos::Array<Kokkos::Array<diff1_type, num_space_dim>, num_conserve>
252  visc_flux;
253 
254  // Viscous continuity
255  for (int i = 0; i < num_space_dim; ++i)
256  visc_flux[0][i] = 0.0;
257 
258  // Viscous momentum
259  for (int i = 0; i < num_space_dim; ++i)
260  for (int j = 0; j < num_space_dim; ++j)
261  visc_flux[i + 1][j] = diff1_tau[i][j];
262 
263  // Viscous energy
264  for (int i = 0; i < num_space_dim; ++i)
265  {
266  diff1_type viscous_work = 0.0;
267  for (int j = 0; j < num_space_dim; ++j)
268  viscous_work += diff1_vel[j] * diff1_tau[i][j];
269 
270  visc_flux[num_conserve - 1][i] = viscous_work
271  + _kappa * diff1_grad_T[i];
272  }
273 
274  // Total flux
275  for (int i = 0; i < num_conserve; ++i)
276  for (int j = 0; j < num_space_dim; ++j)
277  flux[i][j] -= visc_flux[i][j];
278  }
279 
280  // Sum up flux in each direction
281  scalar_type continuity_sum = 0.0;
282  Kokkos::Array<scalar_type, num_space_dim> mom_sum;
283  for (int i = 0; i < num_space_dim; ++i)
284  mom_sum[i] = 0.0;
285  scalar_type energy_sum = 0.0;
286  for (int i = 0; i < num_space_dim; ++i)
287  {
288  continuity_sum += flux[0][i].fastAccessDx(i);
289  for (int j = 0; j < num_space_dim; ++j)
290  mom_sum[i] += flux[i + 1][j].fastAccessDx(j);
291  // FIXME: warning: iteration 2 invokes undefined behavior
292  // [-Waggressive-loop-optimizations]
293  energy_sum += flux[num_conserve - 1][i].fastAccessDx(i);
294  }
295 
296  _continuity_mms_source(cell, point) = continuity_sum;
297  for (int i = 0; i < num_space_dim; ++i)
298  _momentum_mms_source[i](cell, point) = mom_sum[i];
299  _energy_mms_source(cell, point) = energy_sum;
300  }
301 }
302 
303 //---------------------------------------------------------------------------//
304 
305 } // end namespace ClosureModel
306 } // end namespace VertexCFD
307 
308 #endif // end VERTEXCFD_CLOSURE_METHODMANUFACTUREDSOLUTIONSOURCE_IMPL_HPP
VertexCFD
Definition: tstMethodManufacturedSolutionBC.cpp:23