Panzer  Version of the Day
 All Classes Namespaces Files Functions Variables Typedefs Enumerations Enumerator Friends Macros Groups Pages
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
27 #include "Panzer_BasisIRLayout.hpp"
31 
32 namespace 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,
46  const panzer::IntegrationRule& ir,
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;
60  using panzer::PureBasis;
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  :
125  panzer::EvaluatorStyle::EVALUATES,
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  {
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,
154  PHX::FieldManager<Traits>& /* fm */)
155  {
157  using panzer::getBasisIndex;
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>
420  {
421  using panzer::BasisIRLayout;
423  using std::string;
424  using std::vector;
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);
437  p->set("IR", ir);
438  p->set<double>("Multiplier", 1.0);
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__
Kokkos::DynRankView< typename InputArray::value_type, PHX::Device > createDynRankView(const InputArray &a, const std::string &name, const DimensionPack...dims)
Wrapper to simplify Panzer use of Sacado ViewFactory.
int num_cells
DEPRECATED - use: numCells()
void evaluateFields(typename Traits::EvalData d)
Evaluate Fields.
Kokkos::TeamPolicy< TeamPolicyProperties...> teamPolicy(const int &league_size)
Returns a TeamPolicy for hierarchic parallelism.
#define TEUCHOS_TEST_FOR_EXCEPTION(throw_exception_test, Exception, msg)
EvaluatorStyle
An indication of how an Evaluator will behave.
Teuchos::RCP< const PureBasis > getBasis() const
const panzer::EvaluatorStyle evalStyle_
An enum determining the behavior of this Evaluator.
double multiplier
The scalar multiplier out in front of the integral ( ).
PHX::MDField< const ScalarT, Cell, IP > scalar_
A field representing the scalar function we&#39;re integrating ( ).
TEUCHOS_DEPRECATED RCP< T > rcp(T *p, Dealloc_T dealloc, bool owns_mem)
Teuchos::RCP< PHX::DataLayout > dl_scalar
Data layout for scalar fields.
panzer::EvaluatorStyle evalStyle
The EvaluatorStyle of the parent Integrator_CurlBasisDotVector object.
This empty struct allows us to optimize operator()() depending on the number of field multipliers...
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.
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.
PHX::MDField< ScalarT, Cell, BASIS > field_
A field to which we&#39;ll contribute, or in which we&#39;ll store, the result of computing this integral...
Teuchos::RCP< Teuchos::ParameterList > getValidParameters() const
Get Valid Parameters.
void validateParameters(ParameterList const &validParamList, int const depth=1000, EValidateUsed const validateUsed=VALIDATE_USED_ENABLED, EValidateDefaults const validateDefaults=VALIDATE_DEFAULTS_ENABLED) const
void postRegistrationSetup(typename Traits::SetupData d, PHX::FieldManager< Traits > &fm)
Post-Registration Setup.
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.
static HP & inst()
Private ctor.
const std::vector< std::pair< int, LocalOrdinal > > &pid_and_lid const
Description and data layouts associated with a particular basis.
PHX::View< PHX::UnmanagedView< const ScalarT ** > * > kokkosFieldMults_
The PHX::View representation of the (possibly empty) list of fields that are multipliers out in front...
This empty struct allows us to optimize operator()() depending on the number of field multipliers...
Teuchos::RCP< PHX::DataLayout > functional
&lt;Cell,Basis&gt;
Teuchos::RCP< const std::vector< panzer::Workset > > worksets_
std::vector< PHX::MDField< const ScalarT, Cell, IP > > fieldMults_
The (possibly empty) list of fields that are multipliers out in front of the integral ( ...