Panzer Version of the Day
Loading...
Searching...
No Matches
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
28
29// Phalanx
30#include "Phalanx_KokkosDeviceTypes.hpp"
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 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;
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);
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 (");
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 :
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 {
157 using Teuchos::ParameterList;
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;
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 (");
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 {
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.
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
373 PHX::MDField<ScalarT, panzer::Cell, panzer::IP> result;
374
380
385 PHX::MDField<const ScalarT, panzer::Cell, panzer::IP> vectorField;
386
391 PHX::MDField<const ScalarT, panzer::Cell, panzer::IP> fieldMult;
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
477 PHX::MDField<ScalarT, panzer::Cell, panzer::IP, panzer::Dim> result;
478
483 double multiplier;
484
489 PHX::MDField<const ScalarT, panzer::Cell, panzer::IP, panzer::Dim>
491
496 PHX::MDField<const ScalarT, panzer::Cell, panzer::IP> fieldMult;
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 {
535 if (evalStyle == EvaluatorStyle::EVALUATES)
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
553 PHX::MDField<ScalarT, panzer::Cell, panzer::IP, panzer::Dim> result;
554
559 PHX::MDField<ScalarT, panzer::Cell, panzer::BASIS> field;
560
564 PHX::MDField<const double, panzer::Cell, panzer::BASIS, panzer::IP,
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
626 PHX::MDField<ScalarT, panzer::Cell, panzer::IP> result;
627
632 PHX::MDField<ScalarT, panzer::Cell, panzer::BASIS> field;
633
637 PHX::MDField<const double, panzer::Cell, panzer::BASIS, panzer::IP>
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;
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>
751 Teuchos::RCP<Teuchos::ParameterList>
754 {
757 using std::string;
758 using std::vector;
759 using Teuchos::ParameterList;
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);
768 RCP<IntegrationRule> ir;
769 p->set("IR", ir);
770 p->set<double>("Multiplier", 1.0);
771 RCP<const vector<string>> fms;
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
PHX::MDField< const double, panzer::Cell, panzer::BASIS, panzer::IP, panzer::Dim > weightedCurlBasis
The vector basis information necessary for integration.
PHX::MDField< const ScalarT, panzer::Cell, panzer::IP > vectorField
A field representing the vector-valued function we're integrating ( ).
PHX::MDField< ScalarT, panzer::Cell, panzer::IP > result
A field that will be used to build up the result of the integral we're performing.
panzer::EvaluatorStyle evalStyle
The EvaluatorStyle of the parent Integrator_CurlBasisDotVector object.
double multiplier
The scalar multiplier out in front of the integral ( ).
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.
PHX::MDField< const ScalarT, panzer::Cell, panzer::IP > fieldMult
One of the field multipliers ( , , etc.) out in front of the integral.
const std::string & getType() const
Get type of basis.
Teuchos::RCP< PHX::DataLayout > functional
<Cell,Basis>
Teuchos::RCP< const PureBasis > getBasis() const
PHX::MDField< const Scalar, Cell, BASIS, IP > ConstArray_CellBasisIP
Array_CellBasisIPDim weighted_curl_basis_vector
Array_CellBasisIP weighted_curl_basis_scalar
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.
ConstArray_CellBasisIP getBasisValues(const bool weighted, const bool cache=true, const bool force=false) const
Get the basis values evaluated at mesh points.
PHX::MDField< const Scalar, Cell, BASIS, IP, Dim > ConstArray_CellBasisIPDim
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.
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...
PHX::MDField< const ScalarT, panzer::Cell, panzer::IP, panzer::Dim > vector3D_
A field representing the vector-valued function we're integrating ( ) in a three-dimensional problem.
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 ScalarT, panzer::Cell, panzer::IP > vector2D_
A field representing the vector-valued function we're integrating ( ) in a two-dimensional problem.
Teuchos::RCP< Teuchos::ParameterList > getValidParameters() const
Get Valid Parameters.
void postRegistrationSetup(typename Traits::SetupData sd, PHX::FieldManager< Traits > &fm)
Post-Registration Setup.
panzer::BasisDescriptor bd_
The BasisDescriptor for the basis to use.
int spaceDim_
The spatial dimension of the vector-valued function we're integrating, either 2 or 3.
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.
void evaluateFields(typename Traits::EvalData d)
Evaluate Fields.
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.
PHX::MDField< Scalar, T0 > buildStaticArray(const std::string &str, int d0) const
Teuchos::RCP< PHX::DataLayout > dl_vector
Data layout for vector fields.
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.
Teuchos::RCP< const std::vector< panzer::Workset > > worksets_