1 #ifndef VERTEXCFD_INTEGRATOR_BOUNDARYGRADBASISDOTVECTOR_IMPL_HPP
2 #define VERTEXCFD_INTEGRATOR_BOUNDARYGRADBASISDOTVECTOR_IMPL_HPP
4 #include <Panzer_BasisIRLayout.hpp>
5 #include <Panzer_HierarchicParallelism.hpp>
6 #include <Panzer_IntegrationRule.hpp>
7 #include <Panzer_Workset_Utilities.hpp>
14 template<
typename EvalType,
typename Traits>
15 BoundaryGradBasisDotVector<EvalType, Traits>::BoundaryGradBasisDotVector(
16 const panzer::EvaluatorStyle& eval_style,
17 const std::string& res_name,
18 const std::string& flux_name,
19 const panzer::BasisIRLayout& basis,
20 const panzer::IntegrationRule& ir,
21 const double& multiplier,
22 const std::vector<std::string>& fm_names)
23 : _eval_style(eval_style)
24 , _multiplier(multiplier)
25 , _basis_name(basis.name())
26 , _field(res_name, basis.functional)
27 , _boundary_grad_basis(
"boundary_grad_basis", basis.basis_grad)
28 , _vector(flux_name, ir.dl_vector)
29 , _normals(
"Side Normal", ir.dl_vector)
33 throw std::invalid_argument(
34 "Error: BoundaryGradBasisDotVector called with an empty residual "
39 throw std::invalid_argument(
40 "Error: BoundaryGradBasisDotVector called with an empty flux "
44 if (!basis.getBasis()->supportsGrad())
47 =
"Error: BoundaryGradBasisDotVector: Basis of type "
48 + basis.getBasis()->name()
49 +
" does not support the gradient operator.";
50 throw std::logic_error(msg);
53 if (_eval_style == panzer::EvaluatorStyle::CONTRIBUTES)
55 this->addContributedField(_field);
59 this->addEvaluatedField(_field);
62 this->addEvaluatedField(_boundary_grad_basis);
64 this->addDependentField(_vector);
65 this->addDependentField(_normals);
69 const int num_name = fm_names.size();
70 _field_mults.resize(num_name);
72 = Kokkos::View<Kokkos::View<
const ScalarT**,
73 typename PHX::DevLayout<ScalarT>::type,
75 "GradBasisDotVector::KokkosFieldMultipliers", num_name);
76 for (
int i = 0; i < num_name; ++i)
79 = PHX::MDField<const ScalarT, panzer::Cell, panzer::Point>(
80 fm_names[i], ir.dl_scalar);
81 this->addDependentField(_field_mults[i]);
84 std::string n(
"BoundaryGradBasisDotVector (");
85 if (_eval_style == panzer::EvaluatorStyle::CONTRIBUTES)
93 n +=
"): " + _field.fieldTag().name();
98 template<
typename EvalType,
typename Traits>
99 void BoundaryGradBasisDotVector<EvalType, Traits>::postRegistrationSetup(
100 typename Traits::SetupData sd, PHX::FieldManager<Traits>& )
102 for (std::size_t i = 0; i < _field_mults.size(); ++i)
104 _kokkos_field_mults(i) = _field_mults[i].get_static_view();
106 PHX::Device().fence();
109 = panzer::getBasisIndex(_basis_name, (*sd.worksets_)[0], this->wda);
113 template<
typename EvalType,
typename Traits>
114 template<
int NUM_FIELD_MULT>
115 KOKKOS_INLINE_FUNCTION
void
116 BoundaryGradBasisDotVector<EvalType, Traits>::operator()(
117 const FieldMultTag<NUM_FIELD_MULT>& ,
118 const Kokkos::TeamPolicy<PHX::exec_space>::member_type& team)
const
120 const int cell = team.league_rank();
123 const int num_qp(_vector.extent(1));
124 const int num_dim(_vector.extent(2));
125 const int num_bases(_grad_basis.extent(1));
127 for (
int qp = 0; qp < num_qp; ++qp)
129 for (
int basis = 0; basis < num_bases; ++basis)
132 for (
int dim = 0; dim < num_dim; ++dim)
134 n_dot_grad += _normals(cell, qp, dim)
135 * _grad_basis(cell, basis, qp, dim);
137 for (
int dim = 0; dim < num_dim; ++dim)
139 _boundary_grad_basis(cell, basis, qp, dim)
140 = _grad_basis(cell, basis, qp, dim)
141 - _normals(cell, qp, dim) * n_dot_grad;
147 if (_eval_style == panzer::EvaluatorStyle::EVALUATES)
149 Kokkos::parallel_for(
150 Kokkos::TeamThreadRange(team, 0, num_bases),
151 [&](
const int& basis) { _field(cell, basis) = 0.0; });
156 if (NUM_FIELD_MULT == 0)
158 for (
int qp = 0; qp < num_qp; ++qp)
160 for (
int dim = 0; dim < num_dim; ++dim)
162 tmp = _multiplier * _vector(cell, qp, dim);
163 Kokkos::parallel_for(
164 Kokkos::TeamThreadRange(team, 0, num_bases),
165 [&](
const int& basis) {
167 += _boundary_grad_basis(cell, basis, qp, dim) * tmp;
172 else if (NUM_FIELD_MULT == 1)
174 for (
int qp = 0; qp < num_qp; ++qp)
176 for (
int dim = 0; dim < num_dim; ++dim)
178 tmp = _multiplier * _vector(cell, qp, dim)
179 * _kokkos_field_mults(0)(cell, qp);
180 Kokkos::parallel_for(
181 Kokkos::TeamThreadRange(team, 0, num_bases),
182 [&](
const int& basis) {
184 += _boundary_grad_basis(cell, basis, qp, dim) * tmp;
191 const int num_field_mults(_kokkos_field_mults.extent(0));
192 for (
int qp = 0; qp < num_qp; ++qp)
194 ScalarT field_mults_total(1);
195 for (
int fm = 0; fm < num_field_mults; ++fm)
196 field_mults_total *= _kokkos_field_mults(fm)(cell, qp);
197 for (
int dim = 0; dim < num_dim; ++dim)
199 tmp = _multiplier * _vector(cell, qp, dim) * field_mults_total;
200 Kokkos::parallel_for(
201 Kokkos::TeamThreadRange(team, 0, num_bases),
202 [&](
const int& basis) {
204 += _boundary_grad_basis(cell, basis, qp, dim) * tmp;
212 template<
typename EvalType,
typename Traits>
213 template<
int NUM_FIELD_MULT>
214 KOKKOS_INLINE_FUNCTION
void
215 BoundaryGradBasisDotVector<EvalType, Traits>::operator()(
216 const SharedFieldMultTag<NUM_FIELD_MULT>& ,
217 const Kokkos::TeamPolicy<PHX::exec_space>::member_type& team)
const
219 const int cell = team.league_rank();
220 const int num_qp = _vector.extent(1);
221 const int num_dim = _vector.extent(2);
222 const int num_bases = _grad_basis.extent(1);
223 const int fad_size = Kokkos::dimension_scalar(_field.get_view());
226 scratch_view tmp_field;
227 if (Sacado::IsADType<ScalarT>::value)
229 tmp = scratch_view(team.team_shmem(), 1, fad_size);
230 tmp_field = scratch_view(team.team_shmem(), num_bases, fad_size);
234 tmp = scratch_view(team.team_shmem(), 1);
235 tmp_field = scratch_view(team.team_shmem(), num_bases);
240 for (
int qp = 0; qp < num_qp; ++qp)
242 for (
int basis = 0; basis < num_bases; ++basis)
245 for (
int dim = 0; dim < num_dim; ++dim)
247 n_dot_grad += _normals(cell, qp, dim)
248 * _grad_basis(cell, basis, qp, dim);
250 for (
int dim = 0; dim < num_dim; ++dim)
252 _boundary_grad_basis(cell, basis, qp, dim)
253 = _grad_basis(cell, basis, qp, dim)
254 - _normals(cell, qp, dim) * n_dot_grad;
260 Kokkos::parallel_for(Kokkos::TeamThreadRange(team, 0, num_bases),
261 [&](
const int& basis) { tmp_field(basis) = 0.0; });
264 if (NUM_FIELD_MULT == 0)
266 for (
int qp = 0; qp < num_qp; ++qp)
268 for (
int dim = 0; dim < num_dim; ++dim)
271 tmp(0) = _multiplier * _vector(cell, qp, dim);
272 Kokkos::parallel_for(
273 Kokkos::TeamThreadRange(team, 0, num_bases),
274 [&](
const int& basis) {
276 += _boundary_grad_basis(cell, basis, qp, dim)
282 else if (NUM_FIELD_MULT == 1)
284 for (
int qp = 0; qp < num_qp; ++qp)
286 for (
int dim = 0; dim < num_dim; ++dim)
289 tmp(0) = _multiplier * _vector(cell, qp, dim)
290 * _kokkos_field_mults(0)(cell, qp);
291 Kokkos::parallel_for(
292 Kokkos::TeamThreadRange(team, 0, num_bases),
293 [&](
const int& basis) {
295 += _boundary_grad_basis(cell, basis, qp, dim)
303 const int num_field_mults(_kokkos_field_mults.extent(0));
304 for (
int qp = 0; qp < num_qp; ++qp)
306 ScalarT field_mults_total(1);
307 for (
int fm = 0; fm < num_field_mults; ++fm)
308 field_mults_total *= _kokkos_field_mults(fm)(cell, qp);
309 for (
int dim = 0; dim < num_dim; ++dim)
312 tmp(0) = _multiplier * _vector(cell, qp, dim)
314 Kokkos::parallel_for(
315 Kokkos::TeamThreadRange(team, 0, num_bases),
316 [&](
const int& basis) {
318 += _boundary_grad_basis(cell, basis, qp, dim)
326 if (_eval_style == panzer::EvaluatorStyle::EVALUATES)
328 Kokkos::parallel_for(
329 Kokkos::TeamThreadRange(team, 0, num_bases),
330 [&](
const int& basis) { _field(cell, basis) = tmp_field(basis); });
332 else if (_eval_style == panzer::EvaluatorStyle::CONTRIBUTES)
334 Kokkos::parallel_for(Kokkos::TeamThreadRange(team, 0, num_bases),
335 [&](
const int& basis) {
336 _field(cell, basis) += tmp_field(basis);
342 template<
typename EvalType,
typename Traits>
343 void BoundaryGradBasisDotVector<EvalType, Traits>::evaluateFields(
344 typename Traits::EvalData workset)
346 _grad_basis = this->wda(workset).bases[_basis_index]->weighted_grad_basis;
348 const bool use_shared_memory
349 = panzer::HP::inst().useSharedMemory<ScalarT>();
350 if (use_shared_memory)
353 if (Sacado::IsADType<ScalarT>::value)
355 const int fad_size = Kokkos::dimension_scalar(_field.get_view());
356 bytes = scratch_view::shmem_size(1, fad_size)
357 + scratch_view::shmem_size(_grad_basis.extent(1), fad_size);
360 bytes = scratch_view::shmem_size(1)
361 + scratch_view::shmem_size(_grad_basis.extent(1));
366 if (_field_mults.size() == 0)
370 .teamPolicy<ScalarT, SharedFieldMultTag<0>, PHX::Device>(
372 .set_scratch_size(0, Kokkos::PerTeam(bytes));
373 Kokkos::parallel_for(this->getName(), policy, *
this);
375 else if (_field_mults.size() == 1)
379 .teamPolicy<ScalarT, SharedFieldMultTag<1>, PHX::Device>(
381 .set_scratch_size(0, Kokkos::PerTeam(bytes));
382 Kokkos::parallel_for(this->getName(), policy, *
this);
388 .teamPolicy<ScalarT, SharedFieldMultTag<-1>, PHX::Device>(
390 .set_scratch_size(0, Kokkos::PerTeam(bytes));
391 Kokkos::parallel_for(this->getName(), policy, *
this);
399 if (_field_mults.size() == 0)
403 .teamPolicy<ScalarT, FieldMultTag<0>, PHX::Device>(
405 Kokkos::parallel_for(this->getName(), policy, *
this);
407 else if (_field_mults.size() == 1)
411 .teamPolicy<ScalarT, FieldMultTag<1>, PHX::Device>(
413 Kokkos::parallel_for(this->getName(), policy, *
this);
419 .teamPolicy<ScalarT, FieldMultTag<-1>, PHX::Device>(
421 Kokkos::parallel_for(this->getName(), policy, *
this);
431 #endif // VERTEXCFD_INTEGRATOR_BOUNDARYGRADBASISDOTVECTOR_IMPL_HPP