Panzer  Version of the Day
 All Classes Namespaces Files Functions Variables Typedefs Enumerations Enumerator Friends Macros Groups Pages
Panzer_Integrator_CurlBasisDotVector_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_CurlBasisDotVector_impl_hpp
12 #define Panzer_Integrator_CurlBasisDotVector_impl_hpp
13 
15 //
16 // Include Files
17 //
19 
20 // Intrepid2
21 #include "Intrepid2_FunctionSpaceTools.hpp"
22 
23 // Panzer
24 #include "Panzer_BasisIRLayout.hpp"
28 
29 // Phalanx
30 #include "Phalanx_KokkosDeviceTypes.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  useDescriptors_(false),
53  multiplier_(multiplier),
54  basisName_(basis.name())
55  {
56  using PHX::View;
57  using panzer::BASIS;
58  using panzer::Cell;
59  using panzer::Dim;
61  using panzer::IP;
62  using panzer::PureBasis;
63  using PHX::MDField;
64  using std::invalid_argument;
65  using std::logic_error;
66  using std::string;
67  using Teuchos::RCP;
68 
69  // Ensure the input makes sense.
70  TEUCHOS_TEST_FOR_EXCEPTION(resName == "", invalid_argument, "Error: " \
71  "Integrator_CurlBasisDotVector called with an empty residual name.")
72  TEUCHOS_TEST_FOR_EXCEPTION(valName == "", invalid_argument, "Error: " \
73  "Integrator_CurlBasisDotVector called with an empty value name.")
74  RCP<const PureBasis> tmpBasis = basis.getBasis();
75  TEUCHOS_TEST_FOR_EXCEPTION(not tmpBasis->isVectorBasis(), logic_error,
76  "Error: Integrator_CurlBasisDotVector: Basis of type \""
77  << tmpBasis->name() << "\" is not a vector basis.")
78  TEUCHOS_TEST_FOR_EXCEPTION(not tmpBasis->requiresOrientations(),
79  logic_error, "Error: Integrator_CurlBasisDotVector: Basis of type \""
80  << tmpBasis->name() << "\" does not require orientations, though it " \
81  "should for its use in this Evaluator.")
82  TEUCHOS_TEST_FOR_EXCEPTION(not tmpBasis->supportsCurl(), logic_error,
83  "Error: Integrator_CurlBasisDotVector: Basis of type \""
84  << tmpBasis->name() << "\" does not support curl.")
85  TEUCHOS_TEST_FOR_EXCEPTION(not ((tmpBasis->dimension() == 2) or
86  (tmpBasis->dimension() == 3)), logic_error,
87  "Error: Integrator_CurlBasisDotVector requires either a two- or " \
88  "three-dimensional basis. The basis \"" << tmpBasis->name()
89  << "\" is neither.")
90 
91  // Use a scalar field only if we're dealing with a two-dimensional case.
92  spaceDim_ = tmpBasis->dimension();
93 
94  // Create the field for the vector-values quantity we're integrating.
95  if (spaceDim_ == 2)
96  {
97  vector2D_ = MDField<const ScalarT, Cell, IP>(valName, ir.dl_scalar);
98  this->addDependentField(vector2D_);
99  }
100  else // if (spaceDim_ == 3)
101  {
102  vector3D_ = MDField<const ScalarT, Cell, IP, Dim>(valName, ir.dl_vector);
103  this->addDependentField(vector3D_);
104  } // end if spaceDim_ is 2 or 3
105 
106  // Create the field that we're either contributing to or evaluating
107  // (storing).
108  field_ = MDField<ScalarT, Cell, BASIS>(resName, basis.functional);
109  if (evalStyle == EvaluatorStyle::CONTRIBUTES)
110  this->addContributedField(field_);
111  else // if (evalStyle == EvaluatorStyle::EVALUATES)
112  this->addEvaluatedField(field_);
113 
114  // Add the dependent field multipliers, if there are any.
115  int i(0);
116  fieldMults_.resize(fmNames.size());
117  kokkosFieldMults_ = View<Kokkos::View<const ScalarT**, typename PHX::DevLayout<ScalarT>::type, Kokkos::MemoryUnmanaged>*>(
118  "CurlBasisDotVector::KokkosFieldMultipliers", fmNames.size());
119  for (const auto& name : fmNames)
120  {
121  fieldMults_[i++] = MDField<const ScalarT, Cell, IP>(name, ir.dl_scalar);
122  this->addDependentField(fieldMults_[i - 1]);
123  } // end loop over the field multipliers
124 
125  // Set the name of this object.
126  string n("Integrator_CurlBasisDotVector (");
127  if (evalStyle == EvaluatorStyle::CONTRIBUTES)
128  n += "CONTRIBUTES";
129  else // if (evalStyle == EvaluatorStyle::EVALUATES)
130  n += "EVALUATES";
131  n += "): " + field_.fieldTag().name();
132  this->setName(n);
133  } // end of Main Constructor
134 
136  //
137  // ParameterList Constructor
138  //
140  template<typename EvalT, typename Traits>
143  const Teuchos::ParameterList& p)
144  :
146  panzer::EvaluatorStyle::EVALUATES,
147  p.get<std::string>("Residual Name"),
148  p.get<std::string>("Value Name"),
149  (*p.get<Teuchos::RCP<panzer::BasisIRLayout>>("Basis")),
150  (*p.get<Teuchos::RCP<panzer::IntegrationRule>>("IR")),
151  p.get<double>("Multiplier"),
152  p.isType<Teuchos::RCP<const std::vector<std::string>>>
153  ("Field Multipliers") ?
154  (*p.get<Teuchos::RCP<const std::vector<std::string>>>
155  ("Field Multipliers")) : std::vector<std::string>())
156  {
158  using Teuchos::RCP;
159 
160  // Ensure that the input ParameterList didn't contain any bogus entries.
161  RCP<ParameterList> validParams = this->getValidParameters();
162  p.validateParameters(*validParams);
163  } // end of ParameterList Constructor
164 
166  //
167  // FieldTag Constructor
168  //
170  template<typename EvalT, typename TRAITS>
174  const PHX::FieldTag& resTag,
175  const PHX::FieldTag& valTag,
176  const panzer::BasisDescriptor& bd,
178  const int& spaceDim, /* = 3 */
179  const double& multiplier, /* = 1 */
180  const std::vector<PHX::FieldTag>& multipliers /* =
181  std::vector<PHX::FieldTag>() */)
182  :
183  evalStyle_(evalStyle),
184  useDescriptors_(true),
185  bd_(bd),
186  id_(id),
187  multiplier_(multiplier),
188  spaceDim_(spaceDim)
189  {
190  using PHX::View;
192  using std::logic_error;
193  using std::string;
194 
195  // Ensure the input makes sense.
196  TEUCHOS_TEST_FOR_EXCEPTION(bd_.getType() != "HCurl", logic_error,
197  "Error: Integrator_CurlBasisDotVector: Basis of type \""
198  << bd_.getType() << "\" does not support curl.")
199  TEUCHOS_TEST_FOR_EXCEPTION(not ((spaceDim == 2) or (spaceDim == 3)),
200  logic_error, "Error: Integrator_CurlBasisDotVector works on either " \
201  "two- or three-dimensional problems. You've provided spaceDim = "
202  << spaceDim << ".")
203 
204  // Create the field for the vector-valued quantity we're integrating.
205  if (spaceDim_ == 2)
206  {
207  vector2D_ = valTag;
208  this->addDependentField(vector2D_);
209  }
210  else // if (spaceDim_ == 3)
211  {
212  vector3D_ = valTag;
213  this->addDependentField(vector3D_);
214  } // end if spaceDim_ is 2 or 3
215 
216  // Create the field that we're either contributing to or evaluating
217  // (storing).
218  field_ = resTag;
219  if (evalStyle == EvaluatorStyle::CONTRIBUTES)
220  this->addContributedField(field_);
221  else // if (evalStyle == EvaluatorStyle::EVALUATES)
222  this->addEvaluatedField(field_);
223 
224  // Add the dependent field multipliers, if there are any.
225  int i(0);
226  fieldMults_.resize(multipliers.size());
227  kokkosFieldMults_ = View<Kokkos::View<const ScalarT**, typename PHX::DevLayout<ScalarT>::type, Kokkos::MemoryUnmanaged>*>(
228  "CurlBasisDotVector::KokkosFieldMultipliers", multipliers.size());
229  for (const auto& fm : multipliers)
230  {
231  fieldMults_[i++] = fm;
232  this->addDependentField(fieldMults_[i - 1]);
233  } // end loop over the field multipliers
234 
235  // Set the name of this object.
236  string n("Integrator_CurlBasisDotVector (");
237  if (evalStyle == EvaluatorStyle::CONTRIBUTES)
238  n += "CONTRIBUTES";
239  else // if (evalStyle == EvaluatorStyle::EVALUATES)
240  n += "EVALUATES";
241  n += "): " + field_.fieldTag().name();
242  this->setName(n);
243  } // end of Other Constructor
244 
246  //
247  // postRegistrationSetup()
248  //
250  template<typename EvalT, typename Traits>
251  void
254  typename Traits::SetupData sd,
256  {
257  using panzer::getBasisIndex;
258  using PHX::MDField;
259  using std::vector;
260 
261  // Get the PHX::Views of the field multipliers.
262  auto kokkosFieldMults_h = Kokkos::create_mirror_view(kokkosFieldMults_);
263  for (size_t i(0); i < fieldMults_.size(); ++i)
264  kokkosFieldMults_h(i) = fieldMults_[i].get_static_view();
265  Kokkos::deep_copy(kokkosFieldMults_, kokkosFieldMults_h);
266  // Determine the index in the Workset bases for our particular basis
267  // name.
268  if (not useDescriptors_)
269  basisIndex_ = getBasisIndex(basisName_, (*sd.worksets_)[0], this->wda);
270 
271  // Set up the field that will be used to build of the result of this
272  // integration.
273  MDFieldArrayFactory af("",
274  fm.template getKokkosExtendedDataTypeDimensions<EvalT>(), true);
275  if (spaceDim_ == 2)
276  result2D_ = af.buildStaticArray<ScalarT, Cell, IP>(
277  "Integrator_CurlBasisDotVector: 2-D Result", vector2D_.extent(0),
278  vector2D_.extent(1));
279  else // if (spaceDim_ == 3)
280  result3D_ = af.buildStaticArray<ScalarT, Cell, IP, Dim>(
281  "Integrator_CurlBasisDotVector: 3-D Result", vector3D_.extent(0),
282  vector3D_.extent(1), 3);
283  } // end of postRegistrationSetup()
284 
286  //
287  // Anonymous namespace containing classes for performing the integration.
288  //
290  namespace
291  {
303  template<typename ScalarT>
304  class PreMultiply2D
305  {
306  public:
307 
312  struct ScalarMultiplierTag
313  {
314  }; // end of struct ScalarMultiplierTag
315 
320  struct FieldMultiplierTag
321  {
322  }; // end of struct FieldMultiplierTag
323 
335  KOKKOS_INLINE_FUNCTION
336  void operator()(const ScalarMultiplierTag, const unsigned cell) const
337  {
338  int numQP(result.extent(1));
339  for (int qp(0); qp < numQP; ++qp)
340  result(cell, qp) = multiplier * vectorField(cell, qp);
341  } // end of ScalarMultiplierTag operator()()
342 
355  KOKKOS_INLINE_FUNCTION
356  void operator()(const FieldMultiplierTag, const unsigned cell) const
357  {
358  int numQP(result.extent(1));
359  for (int qp(0); qp < numQP; ++qp)
360  result(cell, qp) *= fieldMult(cell, qp);
361  } // end of FieldMultiplierTag operator()()
362 
367  using execution_space = PHX::Device;
368 
374 
379  double multiplier;
380 
386 
392  }; // end of class PreMultiply2D
393 
405  template<typename ScalarT>
406  class PreMultiply3D
407  {
408  public:
409 
414  struct ScalarMultiplierTag
415  {
416  }; // end of struct ScalarMultiplierTag
417 
422  struct FieldMultiplierTag
423  {
424  }; // end of struct FieldMultiplierTag
425 
437  KOKKOS_INLINE_FUNCTION
438  void operator()(const ScalarMultiplierTag, const unsigned cell) const
439  {
440  int numQP(result.extent(1)), numDim(result.extent(2));
441  for (int qp(0); qp < numQP; ++qp)
442  for (int dim(0); dim < numDim; ++dim)
443  result(cell, qp, dim) = multiplier * vectorField(cell, qp, dim);
444  } // end of ScalarMultiplierTag operator()()
445 
458  KOKKOS_INLINE_FUNCTION
459  void operator()(const FieldMultiplierTag, const unsigned cell) const
460  {
461  int numQP(result.extent(1)), numDim(result.extent(2));
462  for (int qp(0); qp < numQP; ++qp)
463  for (int dim(0); dim < numDim; ++dim)
464  result(cell, qp, dim) *= fieldMult(cell, qp);
465  } // end of FieldMultiplierTag operator()()
466 
471  using execution_space = PHX::Device;
472 
478 
483  double multiplier;
484 
490  vectorField;
491 
497  }; // end of class PreMultiply3D
498 
510  template<typename ScalarT, int spaceDim>
511  class Integrate3D
512  {
513  public:
514 
527  KOKKOS_INLINE_FUNCTION
528  void operator()(const unsigned cell) const
529  {
531  int numBases(weightedCurlBasis.extent(1)),
532  numQP(weightedCurlBasis.extent(2));
533  for (int basis(0); basis < numBases; ++basis)
534  {
536  field(cell, basis) = 0.0;
537  for (int qp(0); qp < numQP; ++qp)
538  for (int dim(0); dim < spaceDim; ++dim)
539  field(cell, basis) += result(cell, qp, dim) *
540  weightedCurlBasis(cell, basis, qp, dim);
541  } // end loop over the basis functions
542  } // end of operator()
543 
548  using execution_space = PHX::Device;
549 
554 
560 
566 
572  }; // end of class Integrate3D
573 
585  template<typename ScalarT>
586  class Integrate2D
587  {
588  public:
589 
601  KOKKOS_INLINE_FUNCTION
602  void operator()(const unsigned cell) const
603  {
605  int numBases(weightedCurlBasis.extent(1)),
606  numQP(weightedCurlBasis.extent(2));
607  for (int basis(0); basis < numBases; ++basis)
608  {
610  field(cell, basis) = 0.0;
611  for (int qp(0); qp < numQP; ++qp)
612  field(cell, basis) += result(cell, qp) *
613  weightedCurlBasis(cell, basis, qp);
614  } // end loop over the basis functions
615  } // end of operator()
616 
621  using execution_space = PHX::Device;
622 
627 
633 
639 
645  }; // end of class Integrate2D
646 
647  } // end of anonymous namespace
648 
650  //
651  // evaluateFields()
652  //
654  template<typename EvalT, typename Traits>
655  void
658  typename Traits::EvalData workset)
659  {
660  using Kokkos::parallel_for;
661  using Kokkos::RangePolicy;
662  using panzer::BasisValues2;
663  using PHX::Device;
664  using PHX::MDField;
665  using std::vector;
666 
667  // Grab the basis information.
668  const BasisValues2<double>& bv = useDescriptors_ ?
669  this->wda(workset).getBasisValues(bd_, id_) :
670  *this->wda(workset).bases[basisIndex_];
671 
672  // If we're dealing with a two- or three-dimensional problem...
673  if (spaceDim_ == 2)
674  {
675  // Create an object to multiply the integrand by the scalar multiplier
676  // and any field multipliers out in front of the integral.
677  using PreMultiply = PreMultiply2D<ScalarT>;
678  using ScalarMultiplierTag = typename PreMultiply::ScalarMultiplierTag;
679  using FieldMultiplierTag = typename PreMultiply::FieldMultiplierTag;
680  PreMultiply preMultiply;
681  preMultiply.result = result2D_;
682  preMultiply.multiplier = multiplier_;
683  preMultiply.vectorField = vector2D_;
684 
685  // Multiply the integrand by the scalar multiplier out in front of the
686  // integral.
687  parallel_for(RangePolicy<Device, ScalarMultiplierTag>(0,
688  workset.num_cells), preMultiply);
689 
690  // Multiply the integrand by any field multipliers out in front of the
691  // integral.
692  for (const auto& field : fieldMults_)
693  {
694  preMultiply.fieldMult = field;
695  parallel_for(RangePolicy<Device, FieldMultiplierTag>(0,
696  workset.num_cells), preMultiply);
697  } // end loop over the field multipliers
698 
699  // Create an object to do the actual integration and then do it.
700  Integrate2D<ScalarT> integrate;
701  integrate.result = result2D_;
702  integrate.field = field_;
704  integrate.weightedCurlBasis = useDescriptors_ ? bv.getCurl2DVectorBasis(true) : Array(bv.weighted_curl_basis_scalar);
705  integrate.evalStyle = evalStyle_;
706  parallel_for(workset.num_cells, integrate);
707  }
708  else // if (spaceDim_ == 3)
709  {
710  // Create an object to multiply the integrand by the scalar multiplier
711  // and any field multipliers out in front of the integral.
712  using PreMultiply = PreMultiply3D<ScalarT>;
713  using ScalarMultiplierTag = typename PreMultiply::ScalarMultiplierTag;
714  using FieldMultiplierTag = typename PreMultiply::FieldMultiplierTag;
715  PreMultiply preMultiply;
716  preMultiply.result = result3D_;
717  preMultiply.multiplier = multiplier_;
718  preMultiply.vectorField = vector3D_;
719 
720  // Multiply the integrand by the scalar multiplier out in front of the
721  // integral.
722  parallel_for(RangePolicy<Device, ScalarMultiplierTag>(0,
723  workset.num_cells), preMultiply);
724 
725  // Multiply the integrand by any field multipliers out in front of the
726  // integral.
727  for (const auto& field : fieldMults_)
728  {
729  preMultiply.fieldMult = field;
730  parallel_for(RangePolicy<Device, FieldMultiplierTag>(0,
731  workset.num_cells), preMultiply);
732  } // end loop over the field multipliers
733 
734  // Create an object to do the actual integration and then do it.
735  Integrate3D<ScalarT, 3> integrate;
736  integrate.result = result3D_;
737  integrate.field = field_;
739  integrate.weightedCurlBasis = useDescriptors_ ? bv.getCurlVectorBasis(true) : Array(bv.weighted_curl_basis_vector);
740  integrate.evalStyle = evalStyle_;
741  parallel_for(workset.num_cells, integrate);
742  } // end if spaceDim_ is 2 or 3
743  } // end of evaluateFields()
744 
746  //
747  // getValidParameters()
748  //
750  template<typename EvalT, typename TRAITS>
754  {
755  using panzer::BasisIRLayout;
757  using std::string;
758  using std::vector;
760  using Teuchos::RCP;
761  using Teuchos::rcp;
762 
763  RCP<ParameterList> p = rcp(new ParameterList);
764  p->set<string>("Residual Name", "?");
765  p->set<string>("Value Name", "?");
766  RCP<BasisIRLayout> basis;
767  p->set("Basis", basis);
769  p->set("IR", ir);
770  p->set<double>("Multiplier", 1.0);
772  p->set("Field Multipliers", fms);
773  return p;
774  } // end of getValidParameters()
775 
776 } // end of namespace panzer
777 
778 #endif // Panzer_Integrator_CurlBasisDotVector_impl_hpp
Array_CellBasisIPDim weighted_curl_basis_vector
void evaluateFields(typename Traits::EvalData d)
Evaluate Fields.
int num_cells
DEPRECATED - use: numCells()
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 ( ...
PHX::MDField< const double, panzer::Cell, panzer::BASIS, panzer::IP, panzer::Dim > weightedCurlBasis
The vector basis information necessary for integration.
#define TEUCHOS_TEST_FOR_EXCEPTION(throw_exception_test, Exception, msg)
PHX::MDField< const ScalarT, panzer::Cell, panzer::IP > vectorField
A field representing the vector-valued function we&#39;re integrating ( ).
Teuchos::RCP< Teuchos::ParameterList > getValidParameters() const
Get Valid Parameters.
EvaluatorStyle
An indication of how an Evaluator will behave.
PHX::MDField< Scalar, T0 > buildStaticArray(const std::string &str, int d0) const
ConstArray_CellBasisIPDim getCurlVectorBasis(const bool weighted, const bool cache=true, const bool force=false) const
Get the curl of a 3D vector basis evaluated at mesh points.
Teuchos::RCP< const PureBasis > getBasis() const
panzer::BasisDescriptor bd_
The BasisDescriptor for the basis to use.
PHX::MDField< ScalarT, panzer::Cell, panzer::IP > result
A field that will be used to build up the result of the integral we&#39;re performing.
double multiplier
The scalar multiplier out in front of the integral ( ).
TEUCHOS_DEPRECATED RCP< T > rcp(T *p, Dealloc_T dealloc, bool owns_mem)
const std::string & getType() const
Get type of basis.
Teuchos::RCP< PHX::DataLayout > dl_scalar
Data layout for scalar fields.
ConstArray_CellBasisIP getBasisValues(const bool weighted, const bool cache=true, const bool force=false) const
Get the basis values evaluated at mesh points.
panzer::EvaluatorStyle evalStyle
The EvaluatorStyle of the parent Integrator_CurlBasisDotVector object.
PHX::MDField< const ScalarT, panzer::Cell, panzer::IP, panzer::Dim > vector3D_
A field representing the vector-valued function we&#39;re integrating ( ) in a three-dimensional problem...
int spaceDim_
The spatial dimension of the vector-valued function we&#39;re integrating, either 2 or 3...
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.
Array_CellBasisIP weighted_curl_basis_scalar
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 sd, PHX::FieldManager< Traits > &fm)
Post-Registration Setup.
Teuchos::RCP< PHX::DataLayout > dl_vector
Data layout for vector fields.
PHX::MDField< ScalarT, panzer::Cell, panzer::BASIS > field_
A field to which we&#39;ll contribute, or in which we&#39;ll store, the result of computing this integral...
PHX::MDField< ScalarT, panzer::Cell, panzer::BASIS > field
A field to which we&#39;ll contribute, or in which we&#39;ll store, the result of computing this integral...
PHX::View< Kokkos::View< const ScalarT **, typename PHX::DevLayout< ScalarT >::type, Kokkos::MemoryUnmanaged > * > kokkosFieldMults_
The PHX::View representation of the (possibly empty) list of fields that are multipliers out in front...
Integrator_CurlBasisDotVector(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.
const std::vector< std::pair< int, LocalOrdinal > > &pid_and_lid const
Description and data layouts associated with a particular basis.
PHX::MDField< const ScalarT, panzer::Cell, panzer::IP > fieldMult
One of the field multipliers ( , , etc.) out in front of the integral.
Teuchos::RCP< PHX::DataLayout > functional
&lt;Cell,Basis&gt;
PHX::MDField< const ScalarT, panzer::Cell, panzer::IP > vector2D_
A field representing the vector-valued function we&#39;re integrating ( ) in a two-dimensional problem...
ConstArray_CellBasisIP getCurl2DVectorBasis(const bool weighted, const bool cache=true, const bool force=false) const
Get the curl of a 2D vector basis evaluated at mesh points.
Teuchos::RCP< const std::vector< panzer::Workset > > worksets_
typename EvalT::ScalarT ScalarT
The scalar type.