Panzer Version of the Day
Loading...
Searching...
No Matches
Panzer_Integrator_GradBasisDotVector_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_GradBasisDotVector_impl_hpp__
12#define __Panzer_Integrator_GradBasisDotVector_impl_hpp__
13
15//
16// Include Files
17//
19
20// Panzer
25
26namespace panzer
27{
29 //
30 // Main Constructor
31 //
33 template<typename EvalT, typename Traits>
36 const panzer::EvaluatorStyle& evalStyle,
37 const std::string& resName,
38 const std::string& fluxName,
39 const panzer::BasisIRLayout& basis,
41 const double& multiplier, /* = 1 */
42 const std::vector<std::string>& fmNames, /* =
43 std::vector<std::string>() */
44 const Teuchos::RCP<PHX::DataLayout>& vecDL /* = Teuchos::null */)
45 :
46 evalStyle_(evalStyle),
47 multiplier_(multiplier),
48 basisName_(basis.name())
49 {
50 using PHX::View;
51 using panzer::BASIS;
52 using panzer::Cell;
54 using panzer::IP;
55 using PHX::DataLayout;
56 using PHX::MDField;
57 using std::invalid_argument;
58 using std::logic_error;
59 using std::string;
60 using Teuchos::RCP;
61
62 // Ensure the input makes sense.
63 TEUCHOS_TEST_FOR_EXCEPTION(resName == "", invalid_argument, "Error: " \
64 "Integrator_GradBasisDotVector called with an empty residual name.")
65 TEUCHOS_TEST_FOR_EXCEPTION(fluxName == "", invalid_argument, "Error: " \
66 "Integrator_GradBasisDotVector called with an empty flux name.")
67 RCP<const PureBasis> tmpBasis = basis.getBasis();
68 TEUCHOS_TEST_FOR_EXCEPTION(not tmpBasis->supportsGrad(), logic_error,
69 "Error: Integrator_GradBasisDotVector: Basis of type \""
70 << tmpBasis->name() << "\" does not support the gradient operator.")
71 RCP<DataLayout> tmpVecDL = ir.dl_vector;
72 if (not vecDL.is_null())
73 {
74 tmpVecDL = vecDL;
75 TEUCHOS_TEST_FOR_EXCEPTION(
76 tmpVecDL->extent(2) < ir.dl_vector->extent(2), logic_error,
77 "Integrator_GradBasisDotVector: Dimension of space exceeds " \
78 "dimension of Vector Data Layout.");
79 } // end if (not vecDL.is_null())
80
81 // Create the field for the vector-valued function we're integrating.
82 vector_ = MDField<const ScalarT, Cell, IP, Dim>(fluxName, tmpVecDL);
83 this->addDependentField(vector_);
84
85 // Create the field that we're either contributing to or evaluating
86 // (storing).
87 field_ = MDField<ScalarT, Cell, BASIS>(resName, basis.functional);
89 this->addContributedField(field_);
90 else // if (evalStyle_ == EvaluatorStyle::EVALUATES)
91 this->addEvaluatedField(field_);
92
93 // Add the dependent field multipliers, if there are any.
94 int i(0);
95 fieldMults_.resize(fmNames.size());
96 kokkosFieldMults_ = PHX::View<PHX::UnmanagedView<const ScalarT**>*>("GradBasisDotVector::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_GradBasisDotVector (");
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>
121 Integrator_GradBasisDotVector(const Teuchos::ParameterList& p,
122 const panzer::EvaluatorStyle es)
123 :
125 p.get<std::string>("Residual Name"),
126 p.get<std::string>("Flux Name"),
127 (*p.get<Teuchos::RCP<panzer::BasisIRLayout>>("Basis")),
128 (*p.get<Teuchos::RCP<panzer::IntegrationRule>>("IR")),
129 p.get<double>("Multiplier"),
130 p.isType<Teuchos::RCP<const std::vector<std::string>>>
131 ("Field Multipliers") ?
132 (*p.get<Teuchos::RCP<const std::vector<std::string>>>
133 ("Field Multipliers")) : std::vector<std::string>(),
134 p.isType<Teuchos::RCP<PHX::DataLayout>>("Vector Data Layout") ?
135 p.get<Teuchos::RCP<PHX::DataLayout>>("Vector Data Layout") :
136 Teuchos::null)
137 {
138 using Teuchos::ParameterList;
139 using Teuchos::RCP;
140
141 // Ensure that the input ParameterList didn't contain any bogus entries.
142 RCP<ParameterList> validParams = this->getValidParameters();
143 p.validateParameters(*validParams);
144 } // end of ParameterList Constructor
145
147 //
148 // postRegistrationSetup()
149 //
151 template<typename EvalT, typename Traits>
152 void
155 typename Traits::SetupData sd,
157 {
159 using std::size_t;
160
161 // Get the PHX::Views of the field multipliers.
162 auto field_mults_host_mirror = Kokkos::create_mirror_view(kokkosFieldMults_);
163 for (size_t i(0); i < fieldMults_.size(); ++i)
164 field_mults_host_mirror(i) = fieldMults_[i].get_static_view();
165 Kokkos::deep_copy(kokkosFieldMults_,field_mults_host_mirror);
166
167 // Determine the index in the Workset bases for our particular basis name.
168 basisIndex_ = getBasisIndex(basisName_, (*sd.worksets_)[0], this->wda);
169
170 // Allocate temporary if not using shared memory
171 bool use_shared_memory = panzer::HP::inst().useSharedMemory<ScalarT>();
172 if (!use_shared_memory) {
173 if (Sacado::IsADType<ScalarT>::value) {
174 const auto fadSize = Sacado::dimension_scalar(field_.get_view());
175 tmp_ = PHX::View<ScalarT*>("GradBasisDotVector::tmp_",field_.extent(0),fadSize);
176 } else {
177 tmp_ = PHX::View<ScalarT*>("GradBasisDotVector::tmp_",field_.extent(0));
178 }
179 }
180 } // end of postRegistrationSetup()
181
183 //
184 // operator()() NO shared memory
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::ExecutionSpace>::member_type& team) const
195 {
197 const int cell = team.league_rank();
198
199 // The vector may have more components than the spatial dimension (see
200 // the Vector Data Layout); the gradient of the basis is zero in those
201 // directions, so only loop over the spatial dimension.
202 const int numQP(vector_.extent(1)), numSpatialDim(basis_.extent(3)),
203 numBases(basis_.extent(1));
204
205 // Initialize the evaluated field.
207 Kokkos::parallel_for(Kokkos::TeamThreadRange(team,0,numBases), [&] (const int basis) {
208 field_(cell, basis) = 0.0;
209 });
210
211 for (int qp(0); qp < numQP; ++qp) {
212 for (int dim(0); dim < numSpatialDim; ++dim) {
213 if constexpr (NUM_FIELD_MULT == 0) {
214 Kokkos::parallel_for(Kokkos::TeamThreadRange(team,0,numBases), [&] (const int basis) {
215 field_(cell, basis) += basis_(cell, basis, qp, dim) * multiplier_ * vector_(cell, qp, dim);
216 });
217 }
218 else if constexpr (NUM_FIELD_MULT == 1) {
219 Kokkos::parallel_for(Kokkos::TeamThreadRange(team,0,numBases), [&] (const int basis) {
220 field_(cell, basis) += basis_(cell, basis, qp, dim) * multiplier_ * vector_(cell, qp, dim)
221 * kokkosFieldMults_(0)(cell, qp);
222 });
223 }
224 else if constexpr (NUM_FIELD_MULT == 2) {
225 Kokkos::parallel_for(Kokkos::TeamThreadRange(team,0,numBases), [&] (const int basis) {
226 field_(cell, basis) += basis_(cell, basis, qp, dim) * multiplier_ * vector_(cell, qp, dim)
227 * kokkosFieldMults_(0)(cell, qp) * kokkosFieldMults_(1)(cell, qp);
228 });
229 }
230 else if constexpr (NUM_FIELD_MULT == 3) {
231 Kokkos::parallel_for(Kokkos::TeamThreadRange(team,0,numBases), [&] (const int basis) {
232 field_(cell, basis) += basis_(cell, basis, qp, dim) * multiplier_ * vector_(cell, qp, dim)
233 * kokkosFieldMults_(0)(cell, qp) * kokkosFieldMults_(1)(cell, qp) * kokkosFieldMults_(2)(cell, qp);
234 });
235 }
236 else {
237 Kokkos::abort("Panzer_Integrator_GradBasisDotVector: NUM_FIELD_MULT out of range!");
238 }
239 } // end dim loop
240 } // end qp loop
241 } // end of operator()()
242
244 //
245 // operator()() With shared memory
246 //
248 template<typename EvalT, typename Traits>
249 template<int NUM_FIELD_MULT>
250 KOKKOS_INLINE_FUNCTION
251 void
254 const SharedFieldMultTag<NUM_FIELD_MULT>& /* tag */,
255 const Kokkos::TeamPolicy<PHX::ExecutionSpace>::member_type& team) const
256 {
258 const int cell = team.league_rank();
259 const int numQP = vector_.extent(1);
260 // Only loop over the spatial dimension; see the non-shared operator.
261 const int numSpatialDim = basis_.extent(3);
262 const int numBases = basis_.extent(1);
263 const int fadSize = Sacado::dimension_scalar(field_.get_view());
264
265 scratch_view tmp_field;
266 if (Sacado::IsADType<ScalarT>::value) {
267 tmp_field = scratch_view(team.team_shmem(),numBases,fadSize);
268 }
269 else {
270 tmp_field = scratch_view(team.team_shmem(),numBases);
271 }
272
273 // Initialize the evaluated field.
274 Kokkos::parallel_for(Kokkos::TeamThreadRange(team,0,numBases), [&] (const int basis) {
275 tmp_field(basis) = 0.0;
276 });
277
278 // The following if-block is for the sake of optimization depending on the
279 // number of field multipliers.
280 for (int qp(0); qp < numQP; ++qp) {
281 for (int dim(0); dim < numSpatialDim; ++dim) {
282 if constexpr (NUM_FIELD_MULT == 0) {
283 Kokkos::parallel_for(Kokkos::TeamThreadRange(team,0,numBases), [&] (const int basis) {
284 tmp_field(basis) += basis_(cell, basis, qp, dim) * multiplier_ * vector_(cell, qp, dim);
285 });
286 }
287 else if constexpr (NUM_FIELD_MULT == 1) {
288 Kokkos::parallel_for(Kokkos::TeamThreadRange(team,0,numBases), [&] (const int basis) {
289 tmp_field(basis) += basis_(cell, basis, qp, dim) * multiplier_ * vector_(cell, qp, dim)
290 * kokkosFieldMults_(0)(cell, qp);
291 });
292 }
293 else if constexpr (NUM_FIELD_MULT == 2) {
294 Kokkos::parallel_for(Kokkos::TeamThreadRange(team,0,numBases), [&] (const int basis) {
295 tmp_field(basis) += basis_(cell, basis, qp, dim) * multiplier_ * vector_(cell, qp, dim)
296 * kokkosFieldMults_(0)(cell, qp) * kokkosFieldMults_(1)(cell, qp);
297 });
298 }
299 else if constexpr (NUM_FIELD_MULT == 3) {
300 Kokkos::parallel_for(Kokkos::TeamThreadRange(team,0,numBases), [&] (const int basis) {
301 tmp_field(basis) += basis_(cell, basis, qp, dim) * multiplier_ * vector_(cell, qp, dim)
302 * kokkosFieldMults_(0)(cell, qp) * kokkosFieldMults_(1)(cell, qp) * kokkosFieldMults_(2)(cell, qp);
303 });
304 }
305 else {
306 Kokkos::abort("Panzer_Integrator_GradBasisDotVector: NUM_FIELD_MULT out of range!");
307 }
308 } // end loop over the dimensions of the vector field
309 } // end loop over the quadrature points
310
311 // Put final values into target field
313 Kokkos::parallel_for(Kokkos::TeamThreadRange(team,0,numBases),[&] (const int basis) {
314 field_(cell,basis) = tmp_field(basis);
315 });
316 }
317 else { // Contributed
318 Kokkos::parallel_for(Kokkos::TeamThreadRange(team,0,numBases),[&] (const int basis) {
319 field_(cell,basis) += tmp_field(basis);
320 });
321 }
322
323 } // end of operator()()
324
326 //
327 // evaluateFields()
328 //
330 template<typename EvalT, typename Traits>
331 void
334 typename Traits::EvalData workset)
335 {
336 using Kokkos::parallel_for;
337 using Kokkos::TeamPolicy;
338
339 // Grab the basis information.
340 basis_ = this->wda(workset).bases[basisIndex_]->weighted_grad_basis;
341
342 bool use_shared_memory = panzer::HP::inst().useSharedMemory<ScalarT>();
343 if (use_shared_memory) {
344 int bytes;
345 if (Sacado::IsADType<ScalarT>::value) {
346 const int fadSize = Sacado::dimension_scalar(field_.get_view());
347 bytes = scratch_view::shmem_size(basis_.extent(1),fadSize);
348 }
349 else
350 bytes = scratch_view::shmem_size(basis_.extent(1));
351
352 // The following if-block is for the sake of optimization depending on the
353 // number of field multipliers. The parallel_fors will loop over the cells
354 // in the Workset and execute operator()() above.
355 if (fieldMults_.size() == 0) {
356 auto policy = panzer::HP::inst().teamPolicy<ScalarT,SharedFieldMultTag<0>,PHX::ExecutionSpace>(workset.num_cells).set_scratch_size(0,Kokkos::PerTeam(bytes));
357 parallel_for(this->getName(), policy, *this);
358 } else if (fieldMults_.size() == 1) {
359 auto policy = panzer::HP::inst().teamPolicy<ScalarT,SharedFieldMultTag<1>,PHX::ExecutionSpace>(workset.num_cells).set_scratch_size(0,Kokkos::PerTeam(bytes));
360 parallel_for(this->getName(), policy, *this);
361 } else if (fieldMults_.size() == 2) {
362 auto policy = panzer::HP::inst().teamPolicy<ScalarT,SharedFieldMultTag<2>,PHX::ExecutionSpace>(workset.num_cells).set_scratch_size(0,Kokkos::PerTeam(bytes));
363 parallel_for(this->getName(), policy, *this);
364 } else if (fieldMults_.size() == 3) {
365 auto policy = panzer::HP::inst().teamPolicy<ScalarT,SharedFieldMultTag<3>,PHX::ExecutionSpace>(workset.num_cells).set_scratch_size(0,Kokkos::PerTeam(bytes));
366 parallel_for(this->getName(), policy, *this);
367 } else {
368 TEUCHOS_TEST_FOR_EXCEPTION(fieldMults_.size() > 3,std::runtime_error,
369 "ERROR: Panzer_Integrator_GradBasisDotVector supports up to three field multipliers! User requested "
370 << fieldMults_.size() << "!");
371 }
372 }
373 else {
374 // The following if-block is for the sake of optimization depending on the
375 // number of field multipliers. The parallel_fors will loop over the cells
376 // in the Workset and execute operator()() above.
377 if (fieldMults_.size() == 0) {
378 auto policy = panzer::HP::inst().teamPolicy<ScalarT,FieldMultTag<0>,PHX::ExecutionSpace>(workset.num_cells);
379 parallel_for(this->getName(), policy, *this);
380 } else if (fieldMults_.size() == 1) {
381 auto policy = panzer::HP::inst().teamPolicy<ScalarT,FieldMultTag<1>,PHX::ExecutionSpace>(workset.num_cells);
382 parallel_for(this->getName(), policy, *this);
383 } else if (fieldMults_.size() == 2) {
384 auto policy = panzer::HP::inst().teamPolicy<ScalarT,FieldMultTag<2>,PHX::ExecutionSpace>(workset.num_cells);
385 parallel_for(this->getName(), policy, *this);
386 } else if (fieldMults_.size() == 3) {
387 auto policy = panzer::HP::inst().teamPolicy<ScalarT,FieldMultTag<3>,PHX::ExecutionSpace>(workset.num_cells);
388 parallel_for(this->getName(), policy, *this);
389 } else {
390 TEUCHOS_TEST_FOR_EXCEPTION(fieldMults_.size() > 3,std::runtime_error,
391 "ERROR: Panzer_Integrator_GradBasisDotVector supports up to three field multipliers! User requested "
392 << fieldMults_.size() << "!");
393 }
394 }
395 } // end of evaluateFields()
396
398 //
399 // getValidParameters()
400 //
402 template<typename EvalT, typename TRAITS>
403 Teuchos::RCP<Teuchos::ParameterList>
406 {
409 using PHX::DataLayout;
410 using std::string;
411 using std::vector;
412 using Teuchos::ParameterList;
413 using Teuchos::RCP;
414 using Teuchos::rcp;
415
416 // Create a ParameterList with all the valid keys we support.
417 RCP<ParameterList> p = rcp(new ParameterList);
418 p->set<string>("Residual Name", "?");
419 p->set<string>("Flux Name", "?");
420 RCP<BasisIRLayout> basis;
421 p->set("Basis", basis);
422 RCP<IntegrationRule> ir;
423 p->set("IR", ir);
424 p->set<double>("Multiplier", 1.0);
425 RCP<const vector<string>> fms;
426 p->set("Field Multipliers", fms);
427 RCP<DataLayout> vecDL;
428 p->set("Vector Data Layout", vecDL);
429 return p;
430 } // end of getValidParameters()
431
432} // end of namespace panzer
433
434#endif // __Panzer_Integrator_GradBasisDotVector_impl_hpp__
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::View< ScalarT * > tmp_
Temporary used when shared memory is disabled.
PHX::MDField< ScalarT, panzer::Cell, panzer::BASIS > field_
A field to which we'll contribute, or in which we'll store, the result of computing this integral.
double multiplier_
The scalar multiplier out in front of the integral ( ).
Teuchos::RCP< Teuchos::ParameterList > getValidParameters() const
Get Valid Parameters.
std::vector< PHX::MDField< const ScalarT, panzer::Cell, panzer::IP > > fieldMults_
The (possibly empty) list of fields that are multipliers out in front of the integral ( ,...
Integrator_GradBasisDotVector(const panzer::EvaluatorStyle &evalStyle, const std::string &resName, const std::string &fluxName, const panzer::BasisIRLayout &basis, const panzer::IntegrationRule &ir, const double &multiplier=1, const std::vector< std::string > &fmNames=std::vector< std::string >(), const Teuchos::RCP< PHX::DataLayout > &vecDL=Teuchos::null)
Main Constructor.
Kokkos::View< ScalarT *,typename PHX::DevLayout< ScalarT >::type, typename PHX::ExecutionSpace::scratch_memory_space, Kokkos::MemoryUnmanaged > scratch_view
Type for shared memory.
void postRegistrationSetup(typename Traits::SetupData d, PHX::FieldManager< Traits > &fm)
Post-Registration Setup.
PHX::MDField< const ScalarT, panzer::Cell, panzer::IP, panzer::Dim > vector_
A field representing the vector-valued function we're integrating ( ).
const panzer::EvaluatorStyle evalStyle_
An enum determining the behavior of this Evaluator.
std::string basisName_
The name of the basis we're using.
PHX::View< PHX::UnmanagedView< const ScalarT ** > * > kokkosFieldMults_
The PHX::View representation of the (possibly empty) list of fields that are multipliers out in front...
PHX::MDField< double, panzer::Cell, panzer::BASIS, panzer::IP, panzer::Dim > basis_
The gradient vector basis information necessary for integration.
KOKKOS_INLINE_FUNCTION void operator()(const FieldMultTag< NUM_FIELD_MULT > &tag, const Kokkos::TeamPolicy< PHX::ExecutionSpace >::member_type &team) const
Perform the integration.
void evaluateFields(typename Traits::EvalData d)
Evaluate Fields.
std::size_t basisIndex_
The index in the Workset bases for our particular BasisIRLayout name.
Teuchos::RCP< PHX::DataLayout > dl_vector
Data layout for vector fields.
Teuchos::RCP< PHX::DataLayout > dl_scalar
Data layout for scalar fields.
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_
All worksets that will be evaluated over the lifetime of this evaluator.
const panzer::Workset & EvalData
Data type passed to PHX::Evaluator::evaluateFields(): a single workset holding the cell data for one ...
const SD & SetupData
Data type passed to PHX::Evaluator::postRegistrationSetup().