Panzer Version of the Day
Loading...
Searching...
No Matches
Panzer_Integrator_DivBasisTimesScalar_impl.hpp
Go to the documentation of this file.
1// @HEADER
2// *****************************************************************************
3// Panzer: A partial differential equation assembly
4// engine for strongly coupled complex multiphysics systems
5//
6// Copyright 2011 NTESS and the Panzer contributors.
7// SPDX-License-Identifier: BSD-3-Clause
8// *****************************************************************************
9// @HEADER
10
11#ifndef __Panzer_Integrator_DivBasisTimesScalar_impl_hpp__
12#define __Panzer_Integrator_DivBasisTimesScalar_impl_hpp__
13
15//
16// Include Files
17//
19
20// Intrepid2
21#include "Intrepid2_FunctionSpaceTools.hpp"
22
23// Kokkos
24#include "Kokkos_ViewFactory.hpp"
25
26// Panzer
31
32namespace panzer
33{
35 //
36 // Main Constructor
37 //
39 template<typename EvalT, typename Traits>
43 const std::string& resName,
44 const std::string& valName,
45 const panzer::BasisIRLayout& basis,
47 const double& multiplier, /* = 1 */
48 const std::vector<std::string>& fmNames /* =
49 std::vector<std::string>() */)
50 :
51 evalStyle_(evalStyle),
52 multiplier_(multiplier),
53 basisName_(basis.name())
54 {
55 using PHX::View;
56 using panzer::BASIS;
57 using panzer::Cell;
59 using panzer::IP;
61 using PHX::MDField;
62 using std::invalid_argument;
63 using std::logic_error;
64 using std::string;
65 using Teuchos::RCP;
66
67 // Ensure the input makes sense.
68 TEUCHOS_TEST_FOR_EXCEPTION(resName == "", invalid_argument, "Error: " \
69 "Integrator_DivBasisTimesScalar called with an empty residual name.")
70 TEUCHOS_TEST_FOR_EXCEPTION(valName == "", invalid_argument, "Error: " \
71 "Integrator_DivBasisTimesScalar called with an empty value name.")
72 RCP<const PureBasis> tmpBasis = basis.getBasis();
73 TEUCHOS_TEST_FOR_EXCEPTION(not tmpBasis->supportsDiv(), logic_error,
74 "Error: Integrator_DivBasisTimesScalar: Basis of type \""
75 << tmpBasis->name() << "\" does not support DIV.")
76 TEUCHOS_TEST_FOR_EXCEPTION(not tmpBasis->requiresOrientations(), logic_error,
77 "Error: Integration_DivBasisTimesScalar: Basis of type \""
78 << tmpBasis->name() << "\" should require orientations.")
79
80 // Create the field for the scalar quantity we're integrating.
81 scalar_ = MDField<const ScalarT, Cell, IP>(valName, ir.dl_scalar);
82 this->addDependentField(scalar_);
83
84 // Create the field that we're either contributing to or evaluating
85 // (storing).
86 field_ = MDField<ScalarT, Cell, BASIS>(resName, basis.functional);
88 this->addContributedField(field_);
89 else // if (evalStyle_ == EvaluatorStyle::EVALUATES)
90 this->addEvaluatedField(field_);
91
92 // Add the dependent field multipliers, if there are any.
93 int i(0);
94 fieldMults_.resize(fmNames.size());
96 View<PHX::UnmanagedView<const ScalarT**>*>("DivBasisTimesScalar::KokkosFieldMultipliers",
97 fmNames.size());
98 for (const auto& name : fmNames)
99 {
100 fieldMults_[i++] = MDField<const ScalarT, Cell, IP>(name, ir.dl_scalar);
101 this->addDependentField(fieldMults_[i - 1]);
102 } // end loop over the field multipliers
103
104 // Set the name of this object.
105 string n("Integrator_DivBasisTimesScalar (");
107 n += "CONTRIBUTES";
108 else // if (evalStyle_ == EvaluatorStyle::EVALUATES)
109 n += "EVALUATES";
110 n += "): " + field_.fieldTag().name();
111 this->setName(n);
112 } // end of Main Constructor
113
115 //
116 // ParameterList Constructor
117 //
119 template<typename EvalT, typename Traits>
122 const Teuchos::ParameterList& p)
123 :
126 p.get<std::string>("Residual Name"),
127 p.get<std::string>("Value Name"),
128 (*p.get<Teuchos::RCP<panzer::BasisIRLayout>>("Basis")),
129 (*p.get<Teuchos::RCP<panzer::IntegrationRule>>("IR")),
130 p.get<double>("Multiplier"),
131 p.isType<Teuchos::RCP<const std::vector<std::string>>>
132 ("Field Multipliers") ?
133 (*p.get<Teuchos::RCP<const std::vector<std::string>>>
134 ("Field Multipliers")) : std::vector<std::string>())
135 {
136 using Teuchos::ParameterList;
137 using Teuchos::RCP;
138
139 // Ensure that the input ParameterList didn't contain any bogus entries.
140 RCP<ParameterList> validParams = this->getValidParameters();
141 p.validateParameters(*validParams);
142 } // end of ParameterList Constructor
143
145 //
146 // postRegistrationSetup()
147 //
149 template<typename EvalT, typename Traits>
150 void
153 typename Traits::SetupData sd,
155 {
156 using Kokkos::createDynRankView;
158
159 auto kokkosFieldMults_h = Kokkos::create_mirror_view(kokkosFieldMults_);
160
161 // Get the PHX::Views of the field multipliers.
162 for (size_t i(0); i < fieldMults_.size(); ++i)
163 kokkosFieldMults_h(i) = fieldMults_[i].get_static_view();
164
165 Kokkos::deep_copy(kokkosFieldMults_, kokkosFieldMults_h);
166
167 // Allocate temporary if not using shared memory
168 bool use_shared_memory = panzer::HP::inst().useSharedMemory<ScalarT>();
169 if (!use_shared_memory) {
170 if (Sacado::IsADType<ScalarT>::value) {
171 const auto fadSize = Kokkos::dimension_scalar(field_.get_view());
172 tmp_ = PHX::View<ScalarT*>("panzer::Integrator::DivBasisTimesScalar::tmp_",field_.extent(0),fadSize);
173 } else {
174 tmp_ = PHX::View<ScalarT*>("panzer::Integrator::DivBasisTimesScalar::tmp_",field_.extent(0));
175 }
176 }
177
178 // Determine the index in the Workset bases for our particular basis name.
179 basisIndex_ = getBasisIndex(basisName_, (*sd.worksets_)[0], this->wda);
180 } // end of postRegistrationSetup()
181
183 //
184 // No shared memory operator()()
185 //
187 template<typename EvalT, typename Traits>
188 template<int NUM_FIELD_MULT>
189 KOKKOS_INLINE_FUNCTION
190 void
193 const FieldMultTag<NUM_FIELD_MULT>& /* tag */,
194 const Kokkos::TeamPolicy<PHX::exec_space>::member_type& team) const
195 {
197 const int cell = team.league_rank();
198
199 // Initialize the evaluated field.
200 const int numQP(scalar_.extent(1)), numBases(basis_.extent(1));
201 if (evalStyle_ == EvaluatorStyle::EVALUATES) {
202 Kokkos::parallel_for(Kokkos::TeamThreadRange(team,0,numBases), [&] (const int basis) {
203 field_(cell, basis) = 0.0;
204 });
205 }
206
207 // The following if-block is for the sake of optimization depending on the
208 // number of field multipliers.
209 if (NUM_FIELD_MULT == 0)
210 {
211 // Loop over the quadrature points, scale the integrand by the
212 // multiplier, and then perform the actual integration, looping over the
213 // bases.
214 for (int qp(0); qp < numQP; ++qp)
215 {
216 Kokkos::parallel_for(Kokkos::TeamThreadRange(team,0,numBases), [&] (const int basis) {
217 field_(cell, basis) += basis_(cell, basis, qp) * multiplier_ * scalar_(cell, qp);
218 });
219 } // end loop over the quadrature points
220 }
221 else if (NUM_FIELD_MULT == 1)
222 {
223 // Loop over the quadrature points, scale the integrand by the multiplier
224 // and the single field multiplier, and then perform the actual
225 // integration, looping over the bases.
226 for (int qp(0); qp < numQP; ++qp)
227 {
228 Kokkos::parallel_for(Kokkos::TeamThreadRange(team,0,numBases), [&] (const int basis) {
229 field_(cell, basis) += basis_(cell, basis, qp) * multiplier_ * scalar_(cell, qp) * kokkosFieldMults_(0)(cell, qp);
230 });
231 } // end loop over the quadrature points
232 }
233 else
234 {
235 // Loop over the quadrature points and pre-multiply all the field
236 // multipliers together, scale the integrand by the multiplier and the
237 // combination of field multipliers, and then perform the actual
238 // integration, looping over the bases.
239 const int numFieldMults(kokkosFieldMults_.extent(0));
240 for (int qp(0); qp < numQP; ++qp)
241 {
242 team.team_barrier();
243 tmp_(cell) = 1.0;
244 for (int fm(0); fm < numFieldMults; ++fm)
245 tmp_(cell) *= kokkosFieldMults_(fm)(cell, qp);
246 Kokkos::parallel_for(Kokkos::TeamThreadRange(team,0,numBases),[&] (const int& basis) {
247 field_(cell, basis) += basis_(cell, basis, qp) * multiplier_ * scalar_(cell, qp) * tmp_(cell);
248 });
249 } // end loop over the quadrature points
250 } // end if (NUM_FIELD_MULT == something)
251 } // end of operator()
252
254 //
255 // Shared memory operator()()
256 //
258 template<typename EvalT, typename Traits>
259 template<int NUM_FIELD_MULT>
260 KOKKOS_INLINE_FUNCTION
261 void
264 const SharedFieldMultTag<NUM_FIELD_MULT>& /* tag */,
265 const Kokkos::TeamPolicy<PHX::exec_space>::member_type& team) const
266 {
268 const int cell = team.league_rank();
269 const int numQP = scalar_.extent(1);
270 const int numBases = basis_.extent(1);
271 const int fadSize = Kokkos::dimension_scalar(field_.get_view());
272
273 scratch_view tmp;
274 scratch_view tmp_field;
275 if (Sacado::IsADType<ScalarT>::value) {
276 tmp = scratch_view(team.team_shmem(),1,fadSize);
277 tmp_field = scratch_view(team.team_shmem(),numBases,fadSize);
278 }
279 else {
280 tmp = scratch_view(team.team_shmem(),1);
281 tmp_field = scratch_view(team.team_shmem(),numBases);
282 }
283
284 // Initialize the evaluated field.
285 Kokkos::parallel_for(Kokkos::TeamThreadRange(team,0,numBases),[&] (const int& basis) {
286 tmp_field(basis) = 0.0;
287 });
288
289 // The following if-block is for the sake of optimization depending on the
290 // number of field multipliers.
291 if (NUM_FIELD_MULT == 0)
292 {
293 // Loop over the quadrature points, scale the integrand by the
294 // multiplier, and then perform the actual integration, looping over the
295 // bases.
296 for (int qp(0); qp < numQP; ++qp)
297 {
298 team.team_barrier();
299 tmp(0) = multiplier_ * scalar_(cell, qp);
300 Kokkos::parallel_for(Kokkos::TeamThreadRange(team,0,numBases),[&] (const int& basis) {
301 tmp_field(basis) += basis_(cell, basis, qp) * tmp(0);
302 });
303 } // end loop over the quadrature points
304 }
305 else if (NUM_FIELD_MULT == 1)
306 {
307 // Loop over the quadrature points, scale the integrand by the multiplier
308 // and the single field multiplier, and then perform the actual
309 // integration, looping over the bases.
310 for (int qp(0); qp < numQP; ++qp)
311 {
312 team.team_barrier();
313 tmp(0) = multiplier_ * scalar_(cell, qp) * kokkosFieldMults_(0)(cell, qp);
314 Kokkos::parallel_for(Kokkos::TeamThreadRange(team,0,numBases),[&] (const int& basis) {
315 tmp_field(basis) += basis_(cell, basis, qp) * tmp(0);
316 });
317 } // end loop over the quadrature points
318 }
319 else
320 {
321 // Loop over the quadrature points and pre-multiply all the field
322 // multipliers together, scale the integrand by the multiplier and the
323 // combination of field multipliers, and then perform the actual
324 // integration, looping over the bases.
325 const int numFieldMults = kokkosFieldMults_.extent(0);
326 for (int qp(0); qp < numQP; ++qp)
327 {
328 team.team_barrier();
329 ScalarT fieldMultsTotal(1); // need shared mem here
330 for (int fm(0); fm < numFieldMults; ++fm)
331 fieldMultsTotal *= kokkosFieldMults_(fm)(cell, qp);
332 tmp(0) = multiplier_ * scalar_(cell, qp) * fieldMultsTotal;
333 Kokkos::parallel_for(Kokkos::TeamThreadRange(team,0,numBases),[&] (const int& basis) {
334 tmp_field(basis) += basis_(cell, basis, qp) * tmp(0);
335 });
336 } // end loop over the quadrature points
337 } // end if (NUM_FIELD_MULT == something)
338
339 // Put final values into target field
340 if (evalStyle_ == EvaluatorStyle::EVALUATES) {
341 Kokkos::parallel_for(Kokkos::TeamThreadRange(team,0,numBases),[&] (const int& basis) {
342 field_(cell,basis) = tmp_field(basis);
343 });
344 }
345 else { // Contributed
346 Kokkos::parallel_for(Kokkos::TeamThreadRange(team,0,numBases),[&] (const int& basis) {
347 field_(cell,basis) += tmp_field(basis);
348 });
349 }
350
351 } // end of operator()
352
354 //
355 // evaluateFields()
356 //
358 template<typename EvalT, typename Traits>
359 void
362 typename Traits::EvalData workset)
363 {
364 using Kokkos::parallel_for;
365 using Kokkos::TeamPolicy;
366
367 // Grab the basis information.
368 basis_ = this->wda(workset).bases[basisIndex_]->weighted_div_basis;
369
370 bool use_shared_memory = panzer::HP::inst().useSharedMemory<ScalarT>();
371
372 if (use_shared_memory) {
373 int bytes;
374 if (Sacado::IsADType<ScalarT>::value) {
375 const int fadSize = Kokkos::dimension_scalar(field_.get_view());
376 bytes = scratch_view::shmem_size(1,fadSize) + scratch_view::shmem_size(basis_.extent(1),fadSize);
377 }
378 else
379 bytes = scratch_view::shmem_size(1) + scratch_view::shmem_size(basis_.extent(1));
380
381 // The following if-block is for the sake of optimization depending on the
382 // number of field multipliers. The parallel_fors will loop over the cells
383 // in the Workset and execute operator()() above.
384 if (fieldMults_.size() == 0) {
385 auto policy = panzer::HP::inst().teamPolicy<ScalarT,SharedFieldMultTag<0>,PHX::Device>(workset.num_cells).set_scratch_size(0,Kokkos::PerTeam(bytes));
386 parallel_for(this->getName(), policy, *this);
387 } else if (fieldMults_.size() == 1) {
388 auto policy = panzer::HP::inst().teamPolicy<ScalarT,SharedFieldMultTag<1>,PHX::Device>(workset.num_cells).set_scratch_size(0,Kokkos::PerTeam(bytes));
389 parallel_for(this->getName(), policy, *this);
390 } else {
391 auto policy = panzer::HP::inst().teamPolicy<ScalarT,SharedFieldMultTag<-1>,PHX::Device>(workset.num_cells).set_scratch_size(0,Kokkos::PerTeam(bytes));
392 parallel_for(this->getName(), policy, *this);
393 }
394 }
395 else {
396 // The following if-block is for the sake of optimization depending on the
397 // number of field multipliers. The parallel_fors will loop over the cells
398 // in the Workset and execute operator()() above.
399 if (fieldMults_.size() == 0) {
400 auto policy = panzer::HP::inst().teamPolicy<ScalarT,FieldMultTag<0>,PHX::Device>(workset.num_cells);
401 parallel_for(this->getName(), policy, *this);
402 } else if (fieldMults_.size() == 1) {
403 auto policy = panzer::HP::inst().teamPolicy<ScalarT,FieldMultTag<1>,PHX::Device>(workset.num_cells);
404 parallel_for(this->getName(), policy, *this);
405 } else {
406 auto policy = panzer::HP::inst().teamPolicy<ScalarT,FieldMultTag<-1>,PHX::Device>(workset.num_cells);
407 parallel_for(this->getName(), policy, *this);
408 }
409 }
410 } // end of evaluateFields()
411
413 //
414 // getValidParameters()
415 //
417 template<typename EvalT, typename TRAITS>
418 Teuchos::RCP<Teuchos::ParameterList>
420 {
423 using std::string;
424 using std::vector;
425 using Teuchos::ParameterList;
426 using Teuchos::RCP;
427 using Teuchos::rcp;
428
429 // Create a ParameterList with all the valid keys we support.
430 RCP<ParameterList> p = rcp(new ParameterList);
431 p->set<string>("Residual Name", "?");
432 p->set<string>("Value Name", "?");
433 p->set<string>("Test Field Name", "?");
434 RCP<BasisIRLayout> basis;
435 p->set("Basis", basis);
436 RCP<IntegrationRule> ir;
437 p->set("IR", ir);
438 p->set<double>("Multiplier", 1.0);
439 RCP<const vector<string>> fms;
440 p->set("Field Multipliers", fms);
441 return p;
442 } // end of getValidParameters()
443
444} // end of namespace panzer
445
446#endif // __Panzer_Integrator_DivBasisTimesScalar_impl_hpp__
panzer::EvaluatorStyle evalStyle
The EvaluatorStyle of the parent Integrator_CurlBasisDotVector object.
double multiplier
The scalar multiplier out in front of the integral ( ).
Teuchos::RCP< PHX::DataLayout > functional
<Cell,Basis>
Teuchos::RCP< const PureBasis > getBasis() const
static HP & inst()
Private ctor.
Kokkos::TeamPolicy< TeamPolicyProperties... > teamPolicy(const int &league_size)
Returns a TeamPolicy for hierarchic parallelism.
PHX::MDField< const ScalarT, Cell, IP > scalar_
A field representing the scalar function we're integrating ( ).
Teuchos::RCP< Teuchos::ParameterList > getValidParameters() const
Get Valid Parameters.
KOKKOS_INLINE_FUNCTION void operator()(const FieldMultTag< NUM_FIELD_MULT > &tag, const Kokkos::TeamPolicy< PHX::exec_space >::member_type &team) const
Perform the integration. Main memory version.
Integrator_DivBasisTimesScalar(const panzer::EvaluatorStyle &evalStyle, const std::string &resName, const std::string &valName, const panzer::BasisIRLayout &basis, const panzer::IntegrationRule &ir, const double &multiplier=1, const std::vector< std::string > &fmNames=std::vector< std::string >())
Main Constructor.
void postRegistrationSetup(typename Traits::SetupData d, PHX::FieldManager< Traits > &fm)
Post-Registration Setup.
Kokkos::View< ScalarT *,typename PHX::DevLayout< ScalarT >::type, typename PHX::exec_space::scratch_memory_space, Kokkos::MemoryUnmanaged > scratch_view
Type for shared memory.
void evaluateFields(typename Traits::EvalData d)
Evaluate Fields.
const panzer::EvaluatorStyle evalStyle_
An enum determining the behavior of this Evaluator.
PHX::MDField< ScalarT, Cell, BASIS > field_
A field to which we'll contribute, or in which we'll store, the result of computing this integral.
PHX::View< PHX::UnmanagedView< const ScalarT ** > * > kokkosFieldMults_
The PHX::View representation of the (possibly empty) list of fields that are multipliers out in front...
std::vector< PHX::MDField< const ScalarT, Cell, IP > > fieldMults_
The (possibly empty) list of fields that are multipliers out in front of the integral ( ,...
Teuchos::RCP< PHX::DataLayout > dl_scalar
Data layout for scalar fields.
Description and data layouts associated with a particular basis.
int num_cells
DEPRECATED - use: numCells()
std::vector< std::string >::size_type getBasisIndex(std::string basis_name, const panzer::Workset &workset, WorksetDetailsAccessor &wda)
Returns the index in the workset bases for a particular BasisIRLayout name.
EvaluatorStyle
An indication of how an Evaluator will behave.
This empty struct allows us to optimize operator()() depending on the number of field multipliers.
This empty struct allows us to optimize operator()() depending on the number of field multipliers.
Teuchos::RCP< const std::vector< panzer::Workset > > worksets_