Panzer  Version of the Day
 All Classes Namespaces Files Functions Variables Typedefs Enumerations Enumerator Friends Macros Groups Pages
Panzer_BasisValues2_impl.hpp
Go to the documentation of this file.
1 // @HEADER
2 // ***********************************************************************
3 //
4 // Panzer: A partial differential equation assembly
5 // engine for strongly coupled complex multiphysics systems
6 // Copyright (2011) Sandia Corporation
7 //
8 // Under the terms of Contract DE-AC04-94AL85000 with Sandia Corporation,
9 // the U.S. Government retains certain rights in this software.
10 //
11 // Redistribution and use in source and binary forms, with or without
12 // modification, are permitted provided that the following conditions are
13 // met:
14 //
15 // 1. Redistributions of source code must retain the above copyright
16 // notice, this list of conditions and the following disclaimer.
17 //
18 // 2. Redistributions in binary form must reproduce the above copyright
19 // notice, this list of conditions and the following disclaimer in the
20 // documentation and/or other materials provided with the distribution.
21 //
22 // 3. Neither the name of the Corporation nor the names of the
23 // contributors may be used to endorse or promote products derived from
24 // this software without specific prior written permission.
25 //
26 // THIS SOFTWARE IS PROVIDED BY SANDIA CORPORATION "AS IS" AND ANY
27 // EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
28 // IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR
29 // PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL SANDIA CORPORATION OR THE
30 // CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL,
31 // EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO,
32 // PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR
33 // PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF
34 // LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING
35 // NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS
36 // SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
37 //
38 // Questions? Contact Roger P. Pawlowski (rppawlo@sandia.gov) and
39 // Eric C. Cyr (eccyr@sandia.gov)
40 // ***********************************************************************
41 // @HEADER
42 
43 #include "PanzerDiscFE_config.hpp"
44 #include "Panzer_Traits.hpp"
45 
47 #include "Kokkos_ViewFactory.hpp"
49 
50 #include "Intrepid2_Utils.hpp"
51 #include "Intrepid2_FunctionSpaceTools.hpp"
52 #include "Intrepid2_Orientation.hpp"
53 #include "Intrepid2_OrientationTools.hpp"
54 
55 // FIXME: There are some calls in Intrepid2 that require non-const arrays when they should be const - search for PHX::getNonConstDynRankViewFromConstMDField
56 #include "Phalanx_GetNonConstDynRankViewFromConstMDField.hpp"
57 
58 namespace panzer {
59 namespace {
60 
61 template<typename Scalar>
62 void
63 applyOrientationsImpl(const int num_cells,
64  Kokkos::DynRankView<Scalar, PHX::Device> view,
65  Kokkos::DynRankView<Intrepid2::Orientation, PHX::Device> orientations,
66  const typename BasisValues2<Scalar>::IntrepidBasis & basis)
67 {
68  using ots=Intrepid2::OrientationTools<PHX::Device>;
69 
70  auto sub_orientations = Kokkos::subview(orientations, std::make_pair(0,num_cells));
71 
72  // There are two options based on rank
73  if(view.rank() == 3){
74  // Grab subview of object to re-orient and create a copy of it
75  auto sub_view = Kokkos::subview(view, std::make_pair(0,num_cells), Kokkos::ALL(), Kokkos::ALL());
76  auto sub_view_clone = Kokkos::createDynRankView(view, "sub_view_clone", sub_view.extent(0), sub_view.extent(1), sub_view.extent(2));
77  Kokkos::deep_copy(sub_view_clone, sub_view);
78 
79  // Apply the orientations to the subview
80  ots::modifyBasisByOrientation(sub_view, sub_view_clone, sub_orientations, &basis);
81  } else if (view.rank() == 4){
82  // Grab subview of object to re-orient and create a copy of it
83  auto sub_view = Kokkos::subview(view, std::make_pair(0,num_cells), Kokkos::ALL(), Kokkos::ALL(), Kokkos::ALL());
84  auto sub_view_clone = Kokkos::createDynRankView(view, "sub_view_clone", sub_view.extent(0), sub_view.extent(1), sub_view.extent(2), sub_view.extent(3));
85  Kokkos::deep_copy(sub_view_clone, sub_view);
86 
87  // Apply the orientations to the subview
88  ots::modifyBasisByOrientation(sub_view, sub_view_clone, sub_orientations, &basis);
89  } else
90  throw std::logic_error("applyOrientationsImpl : Unknown view of rank " + std::to_string(view.rank()));
91 }
92 
93 template<typename Scalar>
94 void
95 applyOrientationsImpl(const int num_cells,
96  Kokkos::DynRankView<Scalar, PHX::Device> view,
97  const std::vector<Intrepid2::Orientation> & orientations,
98  const typename BasisValues2<Scalar>::IntrepidBasis & basis)
99 {
100 
101  // Move orientations vector to device
102  Kokkos::DynRankView<Intrepid2::Orientation,PHX::Device> device_orientations("drv_orts", num_cells);
103  auto host_orientations = Kokkos::create_mirror_view(device_orientations);
104  for(int i=0; i < num_cells; ++i)
105  host_orientations(i) = orientations[i];
106  Kokkos::deep_copy(device_orientations,host_orientations);
107 
108  // Call the device orientations applicator
109  applyOrientationsImpl(num_cells, view, device_orientations, basis);
110 }
111 
112 }
113 
114 
115 template <typename Scalar>
117 BasisValues2(const std::string & pre,
118  const bool allocArrays,
119  const bool buildWeighted)
120  : compute_derivatives(true)
121  , build_weighted(buildWeighted)
122  , alloc_arrays(allocArrays)
123  , prefix(pre)
124  , ddims_(1,0)
125  , references_evaluated(false)
126  , orientations_applied_(false)
127  , num_cells_(0)
128  , num_evaluate_cells_(0)
129  , is_uniform_(false)
130  , num_orientations_cells_(0)
131 
132 {
133  // Default all lazy evaluated components to not-evaluated
135  basis_scalar_evaluated_ = false;
137  basis_vector_evaluated_ = false;
139  grad_basis_evaluated_ = false;
144  div_basis_ref_evaluated_ = false;
145  div_basis_evaluated_ = false;
154 }
155 
156 template <typename Scalar>
160  const PHX::MDField<Scalar,Cell,IP> & jac_det,
161  const PHX::MDField<Scalar,Cell,IP,Dim,Dim> & jac_inv,
162  const int in_num_cells)
163 {
164  PANZER_FUNC_TIME_MONITOR_DIFF("panzer::basisValues2::evaluateValues(5 arg)",bv_ev_5);
165 
166  build_weighted = false;
167 
168  setupUniform(basis_layout, cub_points, jac, jac_det, jac_inv, in_num_cells);
169 
170  const auto elmtspace = getElementSpace();
171  const int num_dims = jac.extent(2);
172 
173  // Evaluate Reference values
174  if(elmtspace == PureBasis::HGRAD or elmtspace == PureBasis::CONST or elmtspace == PureBasis::HVOL)
175  getBasisValuesRef(true,true);
176 
177  if(elmtspace == PureBasis::HDIV or elmtspace == PureBasis::HCURL)
178  getVectorBasisValuesRef(true,true);
179 
180  if(elmtspace == PureBasis::HGRAD and compute_derivatives)
181  getGradBasisValuesRef(true,true);
182 
183  if(elmtspace == PureBasis::HCURL and compute_derivatives){
184  if(num_dims == 2)
185  getCurl2DVectorBasisRef(true,true);
186  else if(num_dims == 3)
187  getCurlVectorBasisRef(true,true);
188  }
189 
190  if(elmtspace == PureBasis::HDIV and compute_derivatives)
191  getDivVectorBasisRef(true, true);
192 
193  references_evaluated = true;
194 
195  // Evaluate real space values
196  if(elmtspace == PureBasis::HGRAD or elmtspace == PureBasis::CONST or elmtspace == PureBasis::HVOL)
197  getBasisValues(false,true,true);
198 
199  if(elmtspace == PureBasis::HDIV or elmtspace == PureBasis::HCURL)
200  getVectorBasisValues(false,true,true);
201 
202  if(elmtspace == PureBasis::HGRAD and compute_derivatives)
203  getGradBasisValues(false,true,true);
204 
205  if(elmtspace == PureBasis::HCURL and compute_derivatives){
206  if(num_dims == 2)
207  getCurl2DVectorBasis(false,true,true);
208  else if(num_dims == 3)
209  getCurlVectorBasis(false,true,true);
210  }
211 
212  if(elmtspace == PureBasis::HDIV and compute_derivatives)
213  getDivVectorBasis(false,true,true);
214 
215  // Orientations have been applied if the number of them is greater than zero
216  orientations_applied_ = (orientations_.size()>0);
217 }
218 
219 template <typename Scalar>
223  const PHX::MDField<Scalar,Cell,IP> & jac_det,
224  const PHX::MDField<Scalar,Cell,IP,Dim,Dim> & jac_inv,
225  const PHX::MDField<Scalar,Cell,IP> & weighted_measure,
226  const PHX::MDField<Scalar,Cell,NODE,Dim> & node_coordinates,
227  bool use_node_coordinates,
228  const int in_num_cells)
229 {
230  PANZER_FUNC_TIME_MONITOR_DIFF("panzer::basisValues2::evaluateValues(8 arg, uniform cub pts)",bv_ev_8u);
231 
232  // This is the base call that will add all the non-weighted versions
233  evaluateValues(cub_points, jac, jac_det, jac_inv, in_num_cells);
234  if(weighted_measure.size() > 0)
235  setWeightedMeasure(weighted_measure);
236 
237  cell_node_coordinates_ = node_coordinates;
238 
239  // Add the weighted versions of all basis components - this will add to the non-weighted versions generated by evaluateValues above
240 
241  const auto elmtspace = getElementSpace();
242  const int num_dims = jac.extent(2);
243 
244  if(elmtspace == PureBasis::HGRAD or elmtspace == PureBasis::CONST or elmtspace == PureBasis::HVOL)
245  getBasisValues(true,true,true);
246 
247  if(elmtspace == PureBasis::HDIV or elmtspace == PureBasis::HCURL)
248  getVectorBasisValues(true,true,true);
249 
250  if(elmtspace == PureBasis::HGRAD and compute_derivatives)
251  getGradBasisValues(true,true,true);
252 
253  if(elmtspace == PureBasis::HCURL and compute_derivatives){
254  if(num_dims == 2)
255  getCurl2DVectorBasis(true,true,true);
256  else if(num_dims == 3)
257  getCurlVectorBasis(true,true,true);
258  }
259 
260  if(elmtspace == PureBasis::HDIV and compute_derivatives)
261  getDivVectorBasis(true,true,true);
262 
263  // Add the node components
264  if(use_node_coordinates){
265  getBasisCoordinatesRef(true,true);
266  getBasisCoordinates(true,true);
267  }
268 
269  // Orientations have been applied if the number of them is greater than zero
270  orientations_applied_ = (orientations_.size()>0);
271 }
272 
273 template <typename Scalar>
277  const PHX::MDField<Scalar,Cell,IP> & jac_det,
278  const PHX::MDField<Scalar,Cell,IP,Dim,Dim> & jac_inv,
279  const PHX::MDField<Scalar,Cell,IP> & weighted_measure,
280  const PHX::MDField<Scalar,Cell,NODE,Dim> & node_coordinates,
281  bool use_node_coordinates,
282  const int in_num_cells)
283 {
284  PANZER_FUNC_TIME_MONITOR_DIFF("panzer::basisValues2::evaluateValues(8 arg,nonuniform cub pts)",bv_ev_8nu);
285 
286  cell_node_coordinates_ = node_coordinates;
287 
288  setup(basis_layout, cub_points, jac, jac_det, jac_inv, in_num_cells);
289  if(weighted_measure.size() > 0)
290  setWeightedMeasure(weighted_measure);
291 
292  const auto elmtspace = getElementSpace();
293  const int num_dims = jac.extent(2);
294 
295  if(elmtspace == PureBasis::HGRAD or elmtspace == PureBasis::CONST or elmtspace == PureBasis::HVOL){
296  getBasisValues(false,true,true);
297  if(build_weighted) getBasisValues(true,true,true);
298  }
299 
300  if(elmtspace == PureBasis::HDIV or elmtspace == PureBasis::HCURL){
301  getVectorBasisValues(false,true,true);
302  if(build_weighted) getVectorBasisValues(true,true,true);
303  }
304 
305  if(elmtspace == PureBasis::HGRAD and compute_derivatives){
306  getGradBasisValues(false,true,true);
307  if(build_weighted) getGradBasisValues(true,true,true);
308  }
309 
310  if(elmtspace == PureBasis::HCURL and compute_derivatives){
311  if(num_dims == 2){
312  getCurl2DVectorBasis(false,true,true);
313  if(build_weighted) getCurl2DVectorBasis(true,true,true);
314  } else if(num_dims == 3) {
315  getCurlVectorBasis(false,true,true);
316  if(build_weighted) getCurlVectorBasis(true,true,true);
317  }
318  }
319 
320  if(elmtspace == PureBasis::HDIV and compute_derivatives){
321  getDivVectorBasis(false,true,true);
322  if(build_weighted) getDivVectorBasis(true,true,true);
323  }
324 
325  // Add the node components
326  if(use_node_coordinates){
327  getBasisCoordinatesRef(true,true);
328  getBasisCoordinates(true,true);
329  }
330 
331  // Orientations have been applied if the number of them is greater than zero
332  orientations_applied_ = (orientations_.size()>0);
333 }
334 
335 template <typename Scalar>
339  const PHX::MDField<Scalar,Cell,IP> & jac_det,
340  const PHX::MDField<Scalar,Cell,IP,Dim,Dim> & jac_inv)
341 {
342  PANZER_FUNC_TIME_MONITOR_DIFF("panzer::basisValues2::evaluateValuesCV(5 arg)",bv_ev_cv_5);
343 
344  PHX::MDField<Scalar,Cell,IP> weighted_measure;
345  PHX::MDField<Scalar,Cell,NODE,Dim> node_coordinates;
346  evaluateValues(cub_points,jac,jac_det,jac_inv,weighted_measure,node_coordinates,false,jac.extent(0));
347 }
348 
349 template <typename Scalar>
353  const PHX::MDField<Scalar,Cell,IP> & jac_det,
354  const PHX::MDField<Scalar,Cell,IP,Dim,Dim> & jac_inv,
355  const PHX::MDField<Scalar,Cell,NODE,Dim> & node_coordinates,
356  bool use_node_coordinates,
357  const int in_num_cells)
358 {
359  PANZER_FUNC_TIME_MONITOR_DIFF("panzer::basisValues2::evaluateValuesCV(7 arg)",bv_ev_cv_7);
360  PHX::MDField<Scalar,Cell,IP> weighted_measure;
361  evaluateValues(cell_cub_points,jac,jac_det,jac_inv,weighted_measure,node_coordinates,use_node_coordinates,in_num_cells);
362 }
363 
364 template <typename Scalar>
367  const int in_num_cells)
368 {
369  num_evaluate_cells_ = in_num_cells < 0 ? node_coordinates.extent(0) : in_num_cells;
370  cell_node_coordinates_ = node_coordinates;
371 
372  getBasisCoordinates(true,true);
373 }
374 
375 // method for applying orientations
376 template <typename Scalar>
378 applyOrientations(const std::vector<Intrepid2::Orientation> & orientations,
379  const int in_num_cells)
380 {
381  if (!intrepid_basis->requireOrientation())
382  return;
383 
384  PANZER_FUNC_TIME_MONITOR_DIFF("panzer::basisValues2::applyOrientations()",bv_ev_app_orts);
385 
386  // We only allow the orientations to be applied once
387  TEUCHOS_ASSERT(not orientations_applied_);
388 
389  const PureBasis::EElementSpace elmtspace = getElementSpace();
390 
391  const int num_cell_basis_layout = in_num_cells < 0 ? basis_layout->numCells() : in_num_cells;
392  const int num_cell_orientation = orientations.size();
393  const int num_cells = num_cell_basis_layout < num_cell_orientation ? num_cell_basis_layout : num_cell_orientation;
394  const int num_dim = basis_layout->dimension();
395 
396  // Copy orientations to device
397  Kokkos::DynRankView<Intrepid2::Orientation,PHX::Device> device_orientations("device_orientations", num_cells);
398  auto host_orientations = Kokkos::create_mirror_view(device_orientations);
399  for(int i=0; i < num_cells; ++i)
400  host_orientations(i) = orientations[i];
401  Kokkos::deep_copy(device_orientations,host_orientations);
402 
403  if (elmtspace == PureBasis::HGRAD){
404  applyOrientationsImpl<Scalar>(num_cells, basis_scalar.get_view(), device_orientations, *intrepid_basis);
405  if(build_weighted) applyOrientationsImpl<Scalar>(num_cells, weighted_basis_scalar.get_view(), device_orientations, *intrepid_basis);
406  if(compute_derivatives) applyOrientationsImpl<Scalar>(num_cells, grad_basis.get_view(), device_orientations, *intrepid_basis);
407  if(compute_derivatives and build_weighted) applyOrientationsImpl<Scalar>(num_cells, weighted_grad_basis.get_view(), device_orientations, *intrepid_basis);
408  }
409 
410  if(elmtspace == PureBasis::HCURL){
411  applyOrientationsImpl<Scalar>(num_cells, basis_vector.get_view(), device_orientations, *intrepid_basis);
412  if(build_weighted) applyOrientationsImpl<Scalar>(num_cells, weighted_basis_vector.get_view(), device_orientations, *intrepid_basis);
413  if(num_dim == 2){
414  if(compute_derivatives) applyOrientationsImpl<Scalar>(num_cells, curl_basis_scalar.get_view(), device_orientations, *intrepid_basis);
415  if(compute_derivatives and build_weighted) applyOrientationsImpl<Scalar>(num_cells, weighted_curl_basis_scalar.get_view(), device_orientations, *intrepid_basis);
416  }
417  if(num_dim == 3){
418  if(compute_derivatives) applyOrientationsImpl<Scalar>(num_cells, curl_basis_vector.get_view(), device_orientations, *intrepid_basis);
419  if(compute_derivatives and build_weighted) applyOrientationsImpl<Scalar>(num_cells, weighted_curl_basis_vector.get_view(), device_orientations, *intrepid_basis);
420  }
421  }
422 
423  if(elmtspace == PureBasis::HDIV){
424  applyOrientationsImpl<Scalar>(num_cells, basis_vector.get_view(), device_orientations, *intrepid_basis);
425  if(build_weighted) applyOrientationsImpl<Scalar>(num_cells, weighted_basis_vector.get_view(), device_orientations, *intrepid_basis);
426  if(compute_derivatives) applyOrientationsImpl<Scalar>(num_cells, div_basis.get_view(), device_orientations, *intrepid_basis);
427  if(compute_derivatives and build_weighted) applyOrientationsImpl<Scalar>(num_cells, weighted_div_basis.get_view(), device_orientations, *intrepid_basis);
428  }
429 
430  orientations_applied_ = true;
431 }
432 
433 // method for applying orientations
434 template <typename Scalar>
437 {
438  TEUCHOS_TEST_FOR_EXCEPT_MSG(true,"panzer::BasisValues2::applyOrientations : this should not be called.");
439 }
440 
441 template <typename Scalar>
443 { return basis_layout->getBasis()->getElementSpace(); }
444 
445 template <typename Scalar>
448  bool computeDerivatives)
449 {
450  MDFieldArrayFactory af(prefix,alloc_arrays);
451 
452  compute_derivatives = computeDerivatives;
453  basis_layout = layout;
454  num_cells_ = basis_layout->numCells();
455  Teuchos::RCP<const panzer::PureBasis> basisDesc = layout->getBasis();
456 
457  // for convience pull out basis and quadrature information
458  int num_quad = layout->numPoints();
459  int dim = basisDesc->dimension();
460  int card = basisDesc->cardinality();
461  int numcells = basisDesc->numCells();
462  panzer::PureBasis::EElementSpace elmtspace = basisDesc->getElementSpace();
463  cell_topology_ = basisDesc->getCellTopology();
464 
465  intrepid_basis = basisDesc->getIntrepid2Basis<PHX::Device::execution_space,Scalar,Scalar>();
466 
467  // allocate field containers
468  // field sizes defined by http://trilinos.sandia.gov/packages/docs/dev/packages/intrepid/doc/html/basis_page.html#basis_md_array_sec
469 
470  // compute basis fields
471  if(elmtspace==panzer::PureBasis::HGRAD) {
472  // HGRAD is a nodal field
473 
474  // build values
476  basis_ref_scalar = af.buildStaticArray<Scalar,BASIS,IP>("basis_ref",card,num_quad); // F, P
477  basis_scalar = af.buildStaticArray<Scalar,Cell,BASIS,IP>("basis",numcells,card,num_quad);
478 
479  if(build_weighted)
480  weighted_basis_scalar = af.buildStaticArray<Scalar,Cell,BASIS,IP>("weighted_basis",numcells,card,num_quad);
481 
482  // build gradients
484 
485  if(compute_derivatives) {
486  grad_basis_ref = af.buildStaticArray<Scalar,BASIS,IP,Dim>("grad_basis_ref",card,num_quad,dim); // F, P, D
487  grad_basis = af.buildStaticArray<Scalar,Cell,BASIS,IP,Dim>("grad_basis",numcells,card,num_quad,dim);
488 
489  if(build_weighted)
490  weighted_grad_basis = af.buildStaticArray<Scalar,Cell,BASIS,IP,Dim>("weighted_grad_basis",numcells,card,num_quad,dim);
491  }
492 
493  // build curl
495 
496  // nothing - HGRAD does not support CURL operation
497  }
498  else if(elmtspace==panzer::PureBasis::HCURL) {
499  // HCURL is a vector field
500 
501  // build values
503 
504  basis_ref_vector = af.buildStaticArray<Scalar,BASIS,IP,Dim>("basis_ref",card,num_quad,dim); // F, P, D
505  basis_vector = af.buildStaticArray<Scalar,Cell,BASIS,IP,Dim>("basis",numcells,card,num_quad,dim);
506 
507  if(build_weighted)
508  weighted_basis_vector = af.buildStaticArray<Scalar,Cell,BASIS,IP,Dim>("weighted_basis",numcells,card,num_quad,dim);
509 
510  // build gradients
512 
513  // nothing - HCURL does not support GRAD operation
514 
515  // build curl
517 
518  if(compute_derivatives) {
519  if(dim==2) {
520  // curl of HCURL basis is not dimension dependent
521  curl_basis_ref_scalar = af.buildStaticArray<Scalar,BASIS,IP>("curl_basis_ref",card,num_quad); // F, P
522  curl_basis_scalar = af.buildStaticArray<Scalar,Cell,BASIS,IP>("curl_basis",numcells,card,num_quad);
523 
524  if(build_weighted)
525  weighted_curl_basis_scalar = af.buildStaticArray<Scalar,Cell,BASIS,IP>("weighted_curl_basis",numcells,card,num_quad);
526  }
527  else if(dim==3){
528  curl_basis_ref_vector = af.buildStaticArray<Scalar,BASIS,IP,Dim>("curl_basis_ref",card,num_quad,dim); // F, P, D
529  curl_basis_vector = af.buildStaticArray<Scalar,Cell,BASIS,IP,Dim>("curl_basis",numcells,card,num_quad,dim);
530 
531  if(build_weighted)
532  weighted_curl_basis_vector = af.buildStaticArray<Scalar,Cell,BASIS,IP,Dim>("weighted_curl_basis",numcells,card,num_quad,dim);
533  }
534  else { TEUCHOS_ASSERT(false); } // what do I do with 1D?
535  }
536  }
537  else if(elmtspace==panzer::PureBasis::HDIV) {
538  // HDIV is a vector field
539 
540  // build values
542 
543  basis_ref_vector = af.buildStaticArray<Scalar,BASIS,IP,Dim>("basis_ref",card,num_quad,dim); // F, P, D
544  basis_vector = af.buildStaticArray<Scalar,Cell,BASIS,IP,Dim>("basis",numcells,card,num_quad,dim);
545 
546  if(build_weighted)
547  weighted_basis_vector = af.buildStaticArray<Scalar,Cell,BASIS,IP,Dim>("weighted_basis",numcells,card,num_quad,dim);
548 
549  // build gradients
551 
552  // nothing - HCURL does not support GRAD operation
553 
554  // build curl
556 
557  // nothing - HDIV does not support CURL operation
558 
559  // build div
561 
562  if(compute_derivatives) {
563  div_basis_ref = af.buildStaticArray<Scalar,BASIS,IP>("div_basis_ref",card,num_quad); // F, P
564  div_basis = af.buildStaticArray<Scalar,Cell,BASIS,IP>("div_basis",numcells,card,num_quad);
565 
566  if(build_weighted)
567  weighted_div_basis = af.buildStaticArray<Scalar,Cell,BASIS,IP>("weighted_div_basis",numcells,card,num_quad);
568  }
569  }
570  else if(elmtspace==panzer::PureBasis::CONST || elmtspace==panzer::PureBasis::HVOL) {
571  // CONST is a nodal field
572 
573  // build values
575  basis_ref_scalar = af.buildStaticArray<Scalar,BASIS,IP>("basis_ref",card,num_quad); // F, P
576  basis_scalar = af.buildStaticArray<Scalar,Cell,BASIS,IP>("basis",numcells,card,num_quad);
577 
578  if(build_weighted)
579  weighted_basis_scalar = af.buildStaticArray<Scalar,Cell,BASIS,IP>("weighted_basis",numcells,card,num_quad);
580 
581  // build gradients
583 
584  // nothing - CONST does not support GRAD operation
585 
586  // build curl
588 
589  // nothing - CONST does not support CURL operation
590 
591  // build div
593 
594  // nothing - CONST does not support DIV operation
595  }
596  else { TEUCHOS_ASSERT(false); }
597 
598  basis_coordinates_ref = af.buildStaticArray<Scalar,BASIS,Dim>("basis_coordinates_ref",card,dim);
599  basis_coordinates = af.buildStaticArray<Scalar,Cell,BASIS,Dim>("basis_coordinates",numcells,card,dim);
600 }
601 
602 
603 //=======================================================================================================
604 // New Interface
605 
606 
607 template <typename Scalar>
608 void
613  PHX::MDField<const Scalar, Cell, IP> point_jacobian_determinant,
614  PHX::MDField<const Scalar, Cell, IP, Dim, Dim> point_jacobian_inverse,
615  const int num_evaluated_cells)
616 {
617  basis_layout = basis;
618  intrepid_basis = basis->getBasis()->getIntrepid2Basis<PHX::Device::execution_space,Scalar,Scalar>();
619  cell_topology_ = basis->getCellTopologyInfo()->getCellTopology();
620  num_cells_ = basis_layout->numCells();
621  num_evaluate_cells_ = num_evaluated_cells >= 0 ? num_evaluated_cells : num_cells_;
622  build_weighted = false;
623  is_uniform_ = false;
624 
625  cubature_points_ref_ = reference_points;
626  cubature_jacobian_ = point_jacobian;
627  cubature_jacobian_determinant_ = point_jacobian_determinant;
628  cubature_jacobian_inverse_ = point_jacobian_inverse;
629 
630  // Reset internal data
631  resetArrays();
632 }
633 
634 template <typename Scalar>
635 void
638  PHX::MDField<const Scalar, IP, Dim> reference_points,
640  PHX::MDField<const Scalar, Cell, IP> point_jacobian_determinant,
641  PHX::MDField<const Scalar, Cell, IP, Dim, Dim> point_jacobian_inverse,
642  const int num_evaluated_cells)
643 {
644  basis_layout = basis;
645  intrepid_basis = basis->getBasis()->getIntrepid2Basis<PHX::Device::execution_space,Scalar,Scalar>();
646  cell_topology_ = basis->getCellTopologyInfo()->getCellTopology();
647  num_cells_ = basis_layout->numCells();
648  num_evaluate_cells_ = num_evaluated_cells >= 0 ? num_evaluated_cells : num_cells_;
649  cubature_points_uniform_ref_ = reference_points;
650  build_weighted = false;
651  is_uniform_ = true;
652 
653  cubature_jacobian_ = point_jacobian;
654  cubature_jacobian_determinant_ = point_jacobian_determinant;
655  cubature_jacobian_inverse_ = point_jacobian_inverse;
656 
657  // Reset internal data
658  resetArrays();
659 }
660 
661 template <typename Scalar>
662 void
664 setOrientations(const std::vector<Intrepid2::Orientation> & orientations,
665  const int num_orientations_cells)
666 {
667  if(num_orientations_cells < 0)
668  num_orientations_cells_ = num_evaluate_cells_;
669  else
670  num_orientations_cells_ = num_orientations_cells;
671  if(orientations.size() == 0){
672  orientations_applied_ = false;
673  // Normally we would reset arrays here, but it seems to causes a lot of problems
674  } else {
675  orientations_ = orientations;
676  orientations_applied_ = true;
677  // Setting orientations means that we need to reset our arrays
678  resetArrays();
679  }
680 }
681 
682 template <typename Scalar>
683 void
686 {
687  cell_node_coordinates_ = node_coordinates;
688 }
689 
690 template <typename Scalar>
692 {
693  auto pure_basis = basis_layout->getBasis();
694  return {pure_basis->order(),pure_basis->type()};
695 }
696 
697 template <typename Scalar>
698 void
701 {
702  // Turn off all evaluated fields (forces re-evaluation)
703  basis_ref_scalar_evaluated_ = false;
704  basis_scalar_evaluated_ = false;
705  basis_ref_vector_evaluated_ = false;
706  basis_vector_evaluated_ = false;
707  grad_basis_ref_evaluated_ = false;
708  grad_basis_evaluated_ = false;
709  curl_basis_ref_scalar_evaluated_ = false;
710  curl_basis_scalar_evaluated_ = false;
711  curl_basis_ref_vector_evaluated_ = false;
712  curl_basis_vector_evaluated_ = false;
713  div_basis_ref_evaluated_ = false;
714  div_basis_evaluated_ = false;
715  weighted_basis_scalar_evaluated_ = false;
716  weighted_basis_vector_evaluated_ = false;
717  weighted_grad_basis_evaluated_ = false;
718  weighted_curl_basis_scalar_evaluated_ = false;
719  weighted_curl_basis_vector_evaluated_ = false;
720  weighted_div_basis_evaluated_ = false;
721  basis_coordinates_ref_evaluated_ = false;
722  basis_coordinates_evaluated_ = false;
723 
724  // TODO: Enable this feature - requires the old interface to go away
725  // De-allocate arrays if necessary
726 // if(not alloc_arrays){
727 // basis_ref_scalar = Array_BasisIP();
728 // basis_scalar = Array_CellBasisIP();
729 // basis_ref_vector = Array_BasisIPDim();
730 // basis_vector = Array_CellBasisIPDim();
731 // grad_basis_ref = Array_BasisIPDim();
732 // grad_basis = Array_CellBasisIPDim();
733 // curl_basis_ref_scalar = Array_BasisIP();
734 // curl_basis_scalar = Array_CellBasisIP();
735 // curl_basis_ref_vector = Array_BasisIPDim();
736 // curl_basis_vector = Array_CellBasisIPDim();
737 // div_basis_ref = Array_BasisIP();
738 // div_basis = Array_CellBasisIP();
739 // weighted_basis_scalar = Array_CellBasisIP();
740 // weighted_basis_vector = Array_CellBasisIPDim();
741 // weighted_grad_basis = Array_CellBasisIPDim();
742 // weighted_curl_basis_scalar = Array_CellBasisIP();
743 // weighted_curl_basis_vector = Array_CellBasisIPDim();
744 // weighted_div_basis = Array_CellBasisIP();
745 // basis_coordinates_ref = Array_BasisDim();
746 // basis_coordinates = Array_CellBasisDim();
747 // }
748 }
749 
750 template <typename Scalar>
751 void
754 {
755  TEUCHOS_TEST_FOR_EXCEPT_MSG(build_weighted,
756  "BasisValues2::setWeightedMeasure : Weighted measure already set. Can only set weighted measure once after setup or setupUniform have beens called.");
757  cubature_weights_ = weighted_measure;
758  build_weighted = true;
759 }
760 
761 // If the array is allocated we can not reassign it - this means we
762 // have to deep copy into it. The use of deep_copy is need when an
763 // applicaiton or the library has cached a BasisValues2 member view
764 // outside of the BasisValues object. This could happen when the basis
765 // values object is embedded in an evalautor for mesh motion.
766 #define PANZER_CACHE_DATA(name) \
767  if(cache) { \
768  if(name.size()==tmp_##name.size()){ \
769  Kokkos::deep_copy(name.get_view(), tmp_##name.get_view()); \
770  } else { \
771  name = tmp_##name; \
772  } \
773  name##_evaluated_ = true; \
774  }
775 
776 template <typename Scalar>
777 typename BasisValues2<Scalar>::ConstArray_BasisDim
779 getBasisCoordinatesRef(const bool cache,
780  const bool force) const
781 {
782  // Check if array already exists
783  if(basis_coordinates_ref_evaluated_ and not force)
784  return basis_coordinates_ref;
785 
786  PANZER_FUNC_TIME_MONITOR_DIFF("panzer::basisValues2::getBasisCoordinatesRef()",bv_get_bc_ref);
787 
788  MDFieldArrayFactory af(prefix,getExtendedDimensions(),true);
789 
790  const int num_card = basis_layout->cardinality();
791  const int num_dim = basis_layout->dimension();
792 
793  using coordsScalarType = typename Intrepid2::Basis<PHX::Device::execution_space,Scalar,Scalar>::scalarType;
794  auto tmp_basis_coordinates_ref = af.buildStaticArray<coordsScalarType,BASIS,Dim>("basis_coordinates_ref", num_card, num_dim);
795  intrepid_basis->getDofCoords(tmp_basis_coordinates_ref.get_view());
796  PHX::Device().fence();
797 
798  // Store for later if cache is enabled
799  PANZER_CACHE_DATA(basis_coordinates_ref)
800 
801  return tmp_basis_coordinates_ref;
802 }
803 
804 template <typename Scalar>
807 getBasisValuesRef(const bool cache,
808  const bool force) const
809 {
810  // Check if array already exists
811  if(basis_ref_scalar_evaluated_ and not force)
812  return basis_ref_scalar;
813 
814  PANZER_FUNC_TIME_MONITOR_DIFF("panzer::basisValues2::getBasisValuesRef()",bv_get_bV_ref);
815 
816  // Reference quantities only exist for a uniform reference space
817  TEUCHOS_ASSERT(hasUniformReferenceSpace());
818 
819  // Make sure basis is valid
820  PureBasis::EElementSpace elmtspace = getElementSpace();
821  TEUCHOS_ASSERT(elmtspace==PureBasis::HGRAD || elmtspace==PureBasis::CONST || elmtspace==PureBasis::HVOL);
822 
823  MDFieldArrayFactory af(prefix,getExtendedDimensions(),true);
824 
825  const int num_quad = basis_layout->numPoints();
826  const int num_card = basis_layout->cardinality();
827 
828  auto tmp_basis_ref_scalar = af.buildStaticArray<Scalar,BASIS,IP>("dyn_basis_ref_scalar",num_card,num_quad);
829  auto cubature_points_uniform_ref = PHX::getNonConstDynRankViewFromConstMDField(cubature_points_uniform_ref_);
830 
831  intrepid_basis->getValues(tmp_basis_ref_scalar.get_view(), cubature_points_uniform_ref, Intrepid2::OPERATOR_VALUE);
832  PHX::Device().fence();
833 
834  // Store for later if cache is enabled
835  PANZER_CACHE_DATA(basis_ref_scalar);
836 
837  return tmp_basis_ref_scalar;
838 }
839 
840 template <typename Scalar>
843 getVectorBasisValuesRef(const bool cache,
844  const bool force) const
845 {
846  // Check if array already exists
847  if(basis_ref_vector_evaluated_ and not force)
848  return basis_ref_vector;
849 
850  PANZER_FUNC_TIME_MONITOR_DIFF("panzer::basisValues2::getVectorBasisValuesRef()",bv_get_vec_bv_ref);
851 
852  // Reference quantities only exist for a uniform reference space
853  TEUCHOS_ASSERT(hasUniformReferenceSpace());
854 
855  // Make sure basis is valid
856  PureBasis::EElementSpace elmtspace = getElementSpace();
857  TEUCHOS_ASSERT(elmtspace==PureBasis::HDIV || elmtspace==PureBasis::HCURL);
858 
859  MDFieldArrayFactory af(prefix,getExtendedDimensions(),true);
860 
861  const int num_quad = basis_layout->numPoints();
862  const int num_card = basis_layout->cardinality();
863  const int num_dim = basis_layout->dimension();
864 
865  auto tmp_basis_ref_vector = af.buildStaticArray<Scalar,BASIS,IP,Dim>("dyn_basis_ref_vector",num_card,num_quad,num_dim);
866  auto cubature_points_uniform_ref = PHX::getNonConstDynRankViewFromConstMDField(cubature_points_uniform_ref_);
867 
868  intrepid_basis->getValues(tmp_basis_ref_vector.get_view(),cubature_points_uniform_ref,Intrepid2::OPERATOR_VALUE);
869  PHX::Device().fence();
870 
871  // Store for later if cache is enabled
872  PANZER_CACHE_DATA(basis_ref_vector);
873 
874  return tmp_basis_ref_vector;
875 }
876 
877 template <typename Scalar>
880 getGradBasisValuesRef(const bool cache,
881  const bool force) const
882 {
883  // Check if array already exists
884  if(grad_basis_ref_evaluated_ and not force)
885  return grad_basis_ref;
886 
887  PANZER_FUNC_TIME_MONITOR_DIFF("panzer::basisValues2::getGradBasisValuesRef()",bv_get_grad_bv_ref);
888 
889  // Reference quantities only exist for a uniform reference space
890  TEUCHOS_ASSERT(hasUniformReferenceSpace());
891 
892  // Make sure basis is valid
893  PureBasis::EElementSpace elmtspace = getElementSpace();
894  TEUCHOS_ASSERT(elmtspace==PureBasis::HGRAD);
895 
896  MDFieldArrayFactory af(prefix,getExtendedDimensions(),true);
897 
898  const int num_quad = basis_layout->numPoints();
899  const int num_card = basis_layout->cardinality();
900  const int num_dim = basis_layout->dimension();
901 
902  auto tmp_grad_basis_ref = af.buildStaticArray<Scalar,BASIS,IP,Dim>("dyn_basis_ref_vector",num_card,num_quad,num_dim);
903  auto cubature_points_uniform_ref = PHX::getNonConstDynRankViewFromConstMDField(cubature_points_uniform_ref_);
904 
905  intrepid_basis->getValues(tmp_grad_basis_ref.get_view(), cubature_points_uniform_ref, Intrepid2::OPERATOR_GRAD);
906  PHX::Device().fence();
907 
908  // Store for later if cache is enabled
909  PANZER_CACHE_DATA(grad_basis_ref);
910 
911  return tmp_grad_basis_ref;
912 }
913 
914 template <typename Scalar>
917 getCurl2DVectorBasisRef(const bool cache,
918  const bool force) const
919 {
920  // Check if array already exists
921  if(curl_basis_ref_scalar_evaluated_ and not force)
922  return curl_basis_ref_scalar;
923 
924  PANZER_FUNC_TIME_MONITOR_DIFF("panzer::basisValues2::getCurl2DVectorBasisRef()",bv_get_curl2_bv_ref);
925 
926  // Reference quantities only exist for a uniform reference space
927  TEUCHOS_ASSERT(hasUniformReferenceSpace());
928  TEUCHOS_ASSERT(basis_layout->dimension() == 2);
929 
930  // Make sure basis is valid
931  PureBasis::EElementSpace elmtspace = getElementSpace();
932  TEUCHOS_ASSERT(elmtspace==PureBasis::HCURL);
933 
934  MDFieldArrayFactory af(prefix,getExtendedDimensions(),true);
935 
936  const int num_quad = basis_layout->numPoints();
937  const int num_card = basis_layout->cardinality();
938 
939  auto tmp_curl_basis_ref_scalar = af.buildStaticArray<Scalar,BASIS,IP>("dyn_curl_basis_ref_scalar",num_card,num_quad);
940  auto cubature_points_uniform_ref = PHX::getNonConstDynRankViewFromConstMDField(cubature_points_uniform_ref_);
941 
942  intrepid_basis->getValues(tmp_curl_basis_ref_scalar.get_view(), cubature_points_uniform_ref, Intrepid2::OPERATOR_CURL);
943  PHX::Device().fence();
944 
945  // Store for later if cache is enabled
946  PANZER_CACHE_DATA(curl_basis_ref_scalar);
947 
948  return tmp_curl_basis_ref_scalar;
949 }
950 
951 template <typename Scalar>
954 getCurlVectorBasisRef(const bool cache,
955  const bool force) const
956 {
957  // Check if array already exists
958  if(curl_basis_ref_vector_evaluated_ and not force)
959  return curl_basis_ref_vector;
960 
961  PANZER_FUNC_TIME_MONITOR_DIFF("panzer::basisValues2::getCurlVectorBasisRef()",bv_get_curl_vec_bv_ref);
962 
963  // Reference quantities only exist for a uniform reference space
964  TEUCHOS_ASSERT(hasUniformReferenceSpace());
965  TEUCHOS_ASSERT(basis_layout->dimension() == 3);
966 
967  // Make sure basis is valid
968  PureBasis::EElementSpace elmtspace = getElementSpace();
969  TEUCHOS_ASSERT(elmtspace==PureBasis::HCURL);
970 
971  MDFieldArrayFactory af(prefix,getExtendedDimensions(),true);
972 
973  const int num_quad = basis_layout->numPoints();
974  const int num_card = basis_layout->cardinality();
975  const int num_dim = basis_layout->dimension();
976 
977  auto tmp_curl_basis_ref_vector = af.buildStaticArray<Scalar,BASIS,IP,Dim>("dyn_curl_basis_ref_vector",num_card,num_quad,num_dim);
978  auto cubature_points_uniform_ref = PHX::getNonConstDynRankViewFromConstMDField(cubature_points_uniform_ref_);
979 
980  intrepid_basis->getValues(tmp_curl_basis_ref_vector.get_view(), cubature_points_uniform_ref, Intrepid2::OPERATOR_CURL);
981  PHX::Device().fence();
982 
983  // Store for later if cache is enabled
984  PANZER_CACHE_DATA(curl_basis_ref_vector);
985 
986  return tmp_curl_basis_ref_vector;
987 }
988 
989 template <typename Scalar>
992 getDivVectorBasisRef(const bool cache,
993  const bool force) const
994 {
995  // Check if array already exists
996  if(div_basis_ref_evaluated_ and not force)
997  return div_basis_ref;
998 
999  PANZER_FUNC_TIME_MONITOR_DIFF("panzer::basisValues2::getDivVectorBasisRef()",bv_get_div_vec_bv_ref);
1000 
1001  // Reference quantities only exist for a uniform reference space
1002  TEUCHOS_ASSERT(hasUniformReferenceSpace());
1003 
1004  // Make sure basis is valid
1005  PureBasis::EElementSpace elmtspace = getElementSpace();
1006  TEUCHOS_ASSERT(elmtspace==PureBasis::HDIV);
1007 
1008  MDFieldArrayFactory af(prefix,getExtendedDimensions(),true);
1009 
1010  const int num_quad = basis_layout->numPoints();
1011  const int num_card = basis_layout->cardinality();
1012 
1013  auto tmp_div_basis_ref = af.buildStaticArray<Scalar,BASIS,IP>("dyn_div_basis_ref_scalar",num_card,num_quad);
1014  auto cubature_points_uniform_ref = PHX::getNonConstDynRankViewFromConstMDField(cubature_points_uniform_ref_);
1015 
1016  intrepid_basis->getValues(tmp_div_basis_ref.get_view(), cubature_points_uniform_ref, Intrepid2::OPERATOR_DIV);
1017  PHX::Device().fence();
1018 
1019  // Store for later if cache is enabled
1020  PANZER_CACHE_DATA(div_basis_ref);
1021 
1022  return tmp_div_basis_ref;
1023 }
1024 
1025 template <typename Scalar>
1028 getBasisCoordinates(const bool cache,
1029  const bool force) const
1030 {
1031  PANZER_FUNC_TIME_MONITOR_DIFF("panzer::basisValues2::getBasisCoordinates()",bv_get_bc);
1032 
1033  // Check if array already exists
1034  if(basis_coordinates_evaluated_ and not force)
1035  return basis_coordinates;
1036 
1037  TEUCHOS_ASSERT(cell_node_coordinates_.size() > 0);
1038 
1039  const std::pair<int,int> cell_range(0,num_evaluate_cells_);
1040  const auto s_node_coordinates = Kokkos::subview(cell_node_coordinates_.get_view(),cell_range,Kokkos::ALL(),Kokkos::ALL());
1041 
1042  MDFieldArrayFactory af(prefix,getExtendedDimensions(),true);
1043 
1044  const int num_card = basis_layout->cardinality();
1045  const int num_dim = basis_layout->dimension();
1046 
1047  auto tmp_basis_coordinates = af.buildStaticArray<Scalar, Cell, BASIS, IP>("basis_coordinates", num_cells_, num_card, num_dim);
1048  auto s_aux = Kokkos::subview(tmp_basis_coordinates.get_view(),cell_range,Kokkos::ALL(),Kokkos::ALL());
1049 
1050  // Don't forget that since we are not caching this, we have to make sure the managed view remains alive while we use the non-const wrapper
1051  auto const_bcr = getBasisCoordinatesRef(false);
1052  auto bcr = PHX::getNonConstDynRankViewFromConstMDField(const_bcr);
1053 
1054  Intrepid2::CellTools<PHX::Device::execution_space> cell_tools;
1055  cell_tools.mapToPhysicalFrame(s_aux, bcr, s_node_coordinates, *cell_topology_);
1056  PHX::Device().fence();
1057 
1058  // Store for later if cache is enabled
1059  PANZER_CACHE_DATA(basis_coordinates);
1060 
1061  return tmp_basis_coordinates;
1062 }
1063 
1064 template <typename Scalar>
1067 getBasisValues(const bool weighted,
1068  const bool cache,
1069  const bool force) const
1070 {
1071  if(weighted){
1072  if(weighted_basis_scalar_evaluated_ and not force)
1073  return weighted_basis_scalar;
1074  } else
1075  if(basis_scalar_evaluated_ and not force)
1076  return basis_scalar;
1077 
1078  PANZER_FUNC_TIME_MONITOR_DIFF("panzer::basisValues2::getBasisValues()",bv_get_bv);
1079 
1080  MDFieldArrayFactory af(prefix,getExtendedDimensions(),true);
1081 
1082  const int num_cells = num_cells_;
1083  const int num_points = basis_layout->numPoints();
1084  const int num_card = basis_layout->cardinality();
1085 
1086  if(weighted){
1087  TEUCHOS_ASSERT(cubature_weights_.size() > 0);
1088 
1089  // Get the basis_scalar values - do not cache
1090  const auto bv = getBasisValues(false, force);
1091 
1092  // Apply the weighted measure (cubature weights)
1093  auto tmp_weighted_basis_scalar = af.buildStaticArray<Scalar, Cell, BASIS, IP>("weighted_basis_scalar", num_cells, num_card, num_points);
1094 
1095  const std::pair<int,int> cell_range(0,num_evaluate_cells_);
1096  auto s_aux = Kokkos::subview(tmp_weighted_basis_scalar.get_view(),cell_range,Kokkos::ALL(),Kokkos::ALL());
1097  auto s_cw = Kokkos::subview(cubature_weights_.get_view(),cell_range,Kokkos::ALL());
1098  auto s_bv = Kokkos::subview(bv.get_view(),cell_range,Kokkos::ALL(),Kokkos::ALL());
1099 
1100  using fst=Intrepid2::FunctionSpaceTools<PHX::Device::execution_space>;
1101  fst::multiplyMeasure(s_aux,s_cw,s_bv);
1102 
1103  // NOTE: Weighted path has orientations already applied so doesn't
1104  // need the applyOrientations call at the bottom of this function.
1105 
1106  // Store for later if cache is enabled
1107  PANZER_CACHE_DATA(weighted_basis_scalar);
1108 
1109  return tmp_weighted_basis_scalar;
1110 
1111  } else {
1112 
1113  const auto element_space = getElementSpace();
1114  TEUCHOS_ASSERT(element_space == PureBasis::HVOL || element_space == PureBasis::HGRAD || element_space == PureBasis::CONST);
1115 
1116  // HVol requires the jacobian determinant
1117  if(element_space == PureBasis::HVOL){
1118  TEUCHOS_ASSERT(cubature_jacobian_determinant_.size() > 0);
1119  }
1120 
1121  auto tmp_basis_scalar = af.buildStaticArray<Scalar,Cell,BASIS,IP>("basis_scalar",num_cells,num_card,num_points);
1122 
1123  if(hasUniformReferenceSpace()){
1124 
1125  auto cubature_points_uniform_ref = PHX::getNonConstDynRankViewFromConstMDField(cubature_points_uniform_ref_);
1126 
1127  // Apply a single reference representation to all cells
1128  auto cell_basis_ref_scalar = af.buildStaticArray<Scalar,BASIS,IP>("cell_basis_ref_scalar",num_card,num_points);
1129  intrepid_basis->getValues(cell_basis_ref_scalar.get_view(),cubature_points_uniform_ref,Intrepid2::OPERATOR_VALUE);
1130 
1131  const std::pair<int,int> cell_range(0,num_evaluate_cells_);
1132  auto s_aux = Kokkos::subview(tmp_basis_scalar.get_view(), cell_range, Kokkos::ALL(), Kokkos::ALL());
1133 
1134  // Apply transformation (HGRAD version is just a copy operation)
1135  using fst=Intrepid2::FunctionSpaceTools<PHX::Device::execution_space>;
1136  if (element_space == PureBasis::HVOL){
1137  auto s_cjd = Kokkos::subview(cubature_jacobian_determinant_.get_view(), cell_range, Kokkos::ALL());
1138  fst::HVOLtransformVALUE(s_aux,s_cjd,cell_basis_ref_scalar.get_view());
1139  } else if (element_space == PureBasis::HGRAD || element_space == PureBasis::CONST) {
1140  fst::HGRADtransformVALUE(s_aux,cell_basis_ref_scalar.get_view());
1141  }
1142  PHX::Device().fence();
1143 
1144  } else {
1145  // getValues currently assumes a single reference cell. Calling
1146  // it serially on host until the function supports multiple
1147  // reference cells to avoid a kernel launch per cell.
1148 
1149  // UVM mirror views can't be used with intrepid basis. Let's do an inefficient copy if using UVM.
1150 #ifdef KOKKOS_ENABLE_CUDA
1151  if constexpr (std::is_same<Kokkos::CudaUVMSpace,typename decltype(tmp_basis_scalar.get_view())::memory_space>::value) {
1152  auto cubature_points_ref_host = Kokkos::create_mirror(Kokkos::HostSpace{},cubature_points_ref_.get_view());
1153  Kokkos::deep_copy(cubature_points_ref_host,cubature_points_ref_.get_view());
1154  auto tmp_basis_scalar_host = Kokkos::create_mirror(Kokkos::HostSpace{},tmp_basis_scalar.get_view());
1155  auto intrepid_basis_host = intrepid_basis->getHostBasis();
1156 
1157  for(int cell=0; cell<num_evaluate_cells_; ++cell) {
1158  auto my_cell_basis_host = Kokkos::subview(tmp_basis_scalar_host,cell,Kokkos::ALL(),Kokkos::ALL());
1159  auto my_cell_cub_points_ref_host = Kokkos::subview(cubature_points_ref_host,cell,Kokkos::ALL(),Kokkos::ALL());
1160  intrepid_basis_host->getValues(my_cell_basis_host,my_cell_cub_points_ref_host);
1161  }
1162  auto tmp_basis_scalar_ref = af.buildStaticArray<Scalar,Cell,BASIS,IP>("tmp_basis_scalar_ref",num_cells,num_card,num_points);
1163  Kokkos::deep_copy(tmp_basis_scalar_ref.get_view(),tmp_basis_scalar_host);
1164  const std::pair<int,int> cell_range(0,num_evaluate_cells_);
1165  auto s_aux = Kokkos::subview(tmp_basis_scalar.get_view(), cell_range, Kokkos::ALL(), Kokkos::ALL());
1166  auto s_ref = Kokkos::subview(tmp_basis_scalar_ref.get_view(), cell_range, Kokkos::ALL(), Kokkos::ALL());
1167 
1168  using fst=Intrepid2::FunctionSpaceTools<PHX::Device>;
1169  if(element_space == PureBasis::HVOL){
1170  auto s_cjd = Kokkos::subview(cubature_jacobian_determinant_.get_view(), cell_range, Kokkos::ALL());
1171  fst::HVOLtransformVALUE(s_aux,s_cjd,s_ref);
1172  } else if(element_space == PureBasis::HGRAD || element_space == PureBasis::CONST) {
1173  fst::HGRADtransformVALUE(s_aux,s_ref);
1174  }
1175  } else {
1176 #endif
1177  auto cubature_points_ref_host = Kokkos::create_mirror_view(cubature_points_ref_.get_view());
1178  Kokkos::deep_copy(cubature_points_ref_host,cubature_points_ref_.get_view());
1179  auto tmp_basis_scalar_host = Kokkos::create_mirror_view(tmp_basis_scalar.get_view());
1180  auto intrepid_basis_host = intrepid_basis->getHostBasis();
1181 
1182  for(int cell=0; cell<num_evaluate_cells_; ++cell) {
1183  auto my_cell_basis_host = Kokkos::subview(tmp_basis_scalar_host,cell,Kokkos::ALL(),Kokkos::ALL());
1184  auto my_cell_cub_points_ref_host = Kokkos::subview(cubature_points_ref_host,cell,Kokkos::ALL(),Kokkos::ALL());
1185  intrepid_basis_host->getValues(my_cell_basis_host,my_cell_cub_points_ref_host);
1186  }
1187  auto tmp_basis_scalar_ref = af.buildStaticArray<Scalar,Cell,BASIS,IP>("tmp_basis_scalar_ref",num_cells,num_card,num_points);
1188  Kokkos::deep_copy(tmp_basis_scalar_ref.get_view(),tmp_basis_scalar_host);
1189  const std::pair<int,int> cell_range(0,num_evaluate_cells_);
1190  auto s_aux = Kokkos::subview(tmp_basis_scalar.get_view(), cell_range, Kokkos::ALL(), Kokkos::ALL());
1191  auto s_ref = Kokkos::subview(tmp_basis_scalar_ref.get_view(), cell_range, Kokkos::ALL(), Kokkos::ALL());
1192 
1193  using fst=Intrepid2::FunctionSpaceTools<PHX::Device>;
1194  if(element_space == PureBasis::HVOL){
1195  auto s_cjd = Kokkos::subview(cubature_jacobian_determinant_.get_view(), cell_range, Kokkos::ALL());
1196  fst::HVOLtransformVALUE(s_aux,s_cjd,s_ref);
1197  } else if(element_space == PureBasis::HGRAD || element_space == PureBasis::CONST) {
1198  fst::HGRADtransformVALUE(s_aux,s_ref);
1199  }
1200 #ifdef KOKKOS_ENABLE_CUDA
1201  }
1202 #endif
1203  PHX::Device().fence();
1204  }
1205 
1206  // NOTE: weighted already has orientations applied, so this code
1207  // should only be reached if non-weighted. This is a by-product of
1208  // the two construction paths in panzer. Unification should help
1209  // fix the logic.
1210  if(orientations_.size() > 0)
1211  applyOrientationsImpl<Scalar>(num_orientations_cells_, tmp_basis_scalar.get_view(), orientations_, *intrepid_basis);
1212 
1213  // Store for later if cache is enabled
1214  PANZER_CACHE_DATA(basis_scalar);
1215 
1216  return tmp_basis_scalar;
1217 
1218  }
1219 
1220 }
1221 
1222 template <typename Scalar>
1225 getVectorBasisValues(const bool weighted,
1226  const bool cache,
1227  const bool force) const
1228 {
1229  if(weighted){
1230  if(weighted_basis_vector_evaluated_ and not force)
1231  return weighted_basis_vector;
1232  } else
1233  if(basis_vector_evaluated_ and not force)
1234  return basis_vector;
1235 
1236  PANZER_FUNC_TIME_MONITOR_DIFF("panzer::basisValues2::getVectorBasisValues()",bv_get_vec_bv);
1237 
1238  MDFieldArrayFactory af(prefix,getExtendedDimensions(),true);
1239 
1240  const int num_cells = num_cells_;
1241  const int num_points = basis_layout->numPoints();
1242  const int num_card = basis_layout->cardinality();
1243  const int num_dim = basis_layout->dimension();
1244 
1245  if(weighted){
1246 
1247  TEUCHOS_ASSERT(cubature_weights_.size() > 0);
1248 
1249  // Get the basis_scalar values - do not cache
1250  const auto bv = getVectorBasisValues(false, force);
1251 
1252  // Apply the weighted measure (cubature weights)
1253  auto tmp_weighted_basis_vector = af.buildStaticArray<Scalar, Cell, BASIS, IP, Dim>("weighted_basis_vector", num_cells, num_card, num_points, num_dim);
1254 
1255  const std::pair<int,int> cell_range(0,num_evaluate_cells_);
1256  auto s_aux = Kokkos::subview(tmp_weighted_basis_vector.get_view(),cell_range,Kokkos::ALL(),Kokkos::ALL(),Kokkos::ALL());
1257  auto s_cw = Kokkos::subview(cubature_weights_.get_view(),cell_range,Kokkos::ALL());
1258  auto s_bv = Kokkos::subview(bv.get_view(),cell_range,Kokkos::ALL(),Kokkos::ALL(),Kokkos::ALL());
1259 
1260  using fst=Intrepid2::FunctionSpaceTools<PHX::Device::execution_space>;
1261  fst::multiplyMeasure(s_aux, s_cw, s_bv);
1262 
1263  // Store for later if cache is enabled
1264  PANZER_CACHE_DATA(weighted_basis_vector);
1265 
1266  return tmp_weighted_basis_vector;
1267 
1268  } else { // non-weighted
1269 
1270  const auto element_space = getElementSpace();
1271  TEUCHOS_ASSERT(element_space == PureBasis::HCURL || element_space == PureBasis::HDIV);
1272  TEUCHOS_ASSERT(num_dim != 1);
1273 
1274  // HDIV and HCURL have unique jacobian requirements
1275  if(element_space == PureBasis::HCURL){
1276  TEUCHOS_ASSERT(cubature_jacobian_inverse_.size() > 0);
1277  } else if(element_space == PureBasis::HDIV){
1278  TEUCHOS_ASSERT(cubature_jacobian_.size() > 0 && cubature_jacobian_determinant_.size() > 0);
1279  }
1280 
1281  auto tmp_basis_vector = af.buildStaticArray<Scalar,Cell,BASIS,IP,Dim>("basis_vector",num_cells,num_card,num_points,num_dim);
1282 
1283  if(hasUniformReferenceSpace()){
1284 
1285  auto cubature_points_uniform_ref = PHX::getNonConstDynRankViewFromConstMDField(cubature_points_uniform_ref_);
1286 
1287  // Apply a single reference representation to all cells
1288  auto cell_basis_ref_vector = af.buildStaticArray<Scalar,BASIS,IP,Dim>("cell_basis_ref_scalar",num_card,num_points,num_dim);
1289  intrepid_basis->getValues(cell_basis_ref_vector.get_view(),cubature_points_uniform_ref,Intrepid2::OPERATOR_VALUE);
1290 
1291  const std::pair<int,int> cell_range(0,num_evaluate_cells_);
1292  auto s_aux = Kokkos::subview(tmp_basis_vector.get_view(), cell_range, Kokkos::ALL(), Kokkos::ALL(), Kokkos::ALL());
1293 
1294  // Apply transformation (HGRAD version is just a copy operation)
1295  using fst=Intrepid2::FunctionSpaceTools<PHX::Device::execution_space>;
1296  if(element_space == PureBasis::HCURL){
1297  auto s_jac_inv = Kokkos::subview(cubature_jacobian_inverse_.get_view(), cell_range, Kokkos::ALL(), Kokkos::ALL(), Kokkos::ALL());
1298  fst::HCURLtransformVALUE(s_aux,s_jac_inv,cell_basis_ref_vector.get_view());
1299  } else if(element_space == PureBasis::HDIV){
1300  auto s_jac = Kokkos::subview(cubature_jacobian_.get_view(), cell_range, Kokkos::ALL(), Kokkos::ALL(), Kokkos::ALL());
1301  auto s_jac_det = Kokkos::subview(cubature_jacobian_determinant_.get_view(), cell_range, Kokkos::ALL());
1302  fst::HDIVtransformVALUE(s_aux,s_jac, s_jac_det, cell_basis_ref_vector.get_view());
1303  }
1304  PHX::Device().fence();
1305 
1306  } else {
1307 
1308  // getValues currently assumes a single reference cell. Calling
1309  // it serially on host until the function supports multiple
1310  // reference cells to avoid a kernel launch per cell.
1311 
1312  // UVM mirror views can't be used with intrepid basis. Let's do an inefficient copy if using UVM.
1313 #ifdef KOKKOS_ENABLE_CUDA
1314  if constexpr (std::is_same<Kokkos::CudaUVMSpace,typename decltype(tmp_basis_vector.get_view())::memory_space>::value) {
1315  auto cubature_points_ref_host = Kokkos::create_mirror(Kokkos::HostSpace{},cubature_points_ref_.get_view());
1316  Kokkos::deep_copy(cubature_points_ref_host,cubature_points_ref_.get_view());
1317  auto tmp_basis_vector_host = Kokkos::create_mirror(Kokkos::HostSpace{},tmp_basis_vector.get_view());
1318 
1319  auto intrepid_basis_host = intrepid_basis->getHostBasis();
1320  for(int cell=0; cell<num_evaluate_cells_; ++cell) {
1321  auto my_cell_basis_host = Kokkos::subview(tmp_basis_vector_host,cell,Kokkos::ALL(),Kokkos::ALL(),Kokkos::ALL());
1322  auto my_cell_cub_points_ref_host = Kokkos::subview(cubature_points_ref_host,cell,Kokkos::ALL(),Kokkos::ALL());
1323  intrepid_basis_host->getValues(my_cell_basis_host,my_cell_cub_points_ref_host);
1324  }
1325  auto tmp_basis_vector_ref = af.buildStaticArray<Scalar,Cell,BASIS,IP,Dim>("tmp_basis_vector_ref",num_cells,num_card,num_points,num_dim);
1326  Kokkos::deep_copy(tmp_basis_vector_ref.get_view(),tmp_basis_vector_host);
1327 
1328  const std::pair<int,int> cell_range(0,num_evaluate_cells_);
1329  auto s_aux = Kokkos::subview(tmp_basis_vector.get_view(), cell_range, Kokkos::ALL(), Kokkos::ALL(), Kokkos::ALL());
1330  auto s_ref = Kokkos::subview(tmp_basis_vector_ref.get_view(), cell_range, Kokkos::ALL(), Kokkos::ALL(), Kokkos::ALL());
1331 
1332  using fst=Intrepid2::FunctionSpaceTools<PHX::Device>;
1333  if(element_space == PureBasis::HCURL){
1334  auto s_jac_inv = Kokkos::subview(cubature_jacobian_inverse_.get_view(), cell_range, Kokkos::ALL(), Kokkos::ALL(), Kokkos::ALL());
1335  fst::HCURLtransformVALUE(s_aux,s_jac_inv,s_ref);
1336  } else if(element_space == PureBasis::HDIV){
1337  auto s_jac = Kokkos::subview(cubature_jacobian_.get_view(), cell_range, Kokkos::ALL(), Kokkos::ALL(), Kokkos::ALL());
1338  auto s_jac_det = Kokkos::subview(cubature_jacobian_determinant_.get_view(), cell_range, Kokkos::ALL());
1339  fst::HDIVtransformVALUE(s_aux,s_jac, s_jac_det, s_ref);
1340  }
1341  } else {
1342 #endif
1343  auto cubature_points_ref_host = Kokkos::create_mirror_view(cubature_points_ref_.get_view());
1344  Kokkos::deep_copy(cubature_points_ref_host,cubature_points_ref_.get_view());
1345  auto tmp_basis_vector_host = Kokkos::create_mirror_view(tmp_basis_vector.get_view());
1346 
1347  auto intrepid_basis_host = intrepid_basis->getHostBasis();
1348  for(int cell=0; cell<num_evaluate_cells_; ++cell) {
1349  auto my_cell_basis_host = Kokkos::subview(tmp_basis_vector_host,cell,Kokkos::ALL(),Kokkos::ALL(),Kokkos::ALL());
1350  auto my_cell_cub_points_ref_host = Kokkos::subview(cubature_points_ref_host,cell,Kokkos::ALL(),Kokkos::ALL());
1351  intrepid_basis_host->getValues(my_cell_basis_host,my_cell_cub_points_ref_host);
1352  }
1353  auto tmp_basis_vector_ref = af.buildStaticArray<Scalar,Cell,BASIS,IP,Dim>("tmp_basis_vector_ref",num_cells,num_card,num_points,num_dim);
1354  Kokkos::deep_copy(tmp_basis_vector_ref.get_view(),tmp_basis_vector_host);
1355 
1356  const std::pair<int,int> cell_range(0,num_evaluate_cells_);
1357  auto s_aux = Kokkos::subview(tmp_basis_vector.get_view(), cell_range, Kokkos::ALL(), Kokkos::ALL(), Kokkos::ALL());
1358  auto s_ref = Kokkos::subview(tmp_basis_vector_ref.get_view(), cell_range, Kokkos::ALL(), Kokkos::ALL(), Kokkos::ALL());
1359 
1360  using fst=Intrepid2::FunctionSpaceTools<PHX::Device>;
1361  if(element_space == PureBasis::HCURL){
1362  auto s_jac_inv = Kokkos::subview(cubature_jacobian_inverse_.get_view(), cell_range, Kokkos::ALL(), Kokkos::ALL(), Kokkos::ALL());
1363  fst::HCURLtransformVALUE(s_aux,s_jac_inv,s_ref);
1364  } else if(element_space == PureBasis::HDIV){
1365  auto s_jac = Kokkos::subview(cubature_jacobian_.get_view(), cell_range, Kokkos::ALL(), Kokkos::ALL(), Kokkos::ALL());
1366  auto s_jac_det = Kokkos::subview(cubature_jacobian_determinant_.get_view(), cell_range, Kokkos::ALL());
1367  fst::HDIVtransformVALUE(s_aux,s_jac, s_jac_det, s_ref);
1368  }
1369 #ifdef KOKKOS_ENABLE_CUDA
1370  }
1371 #endif
1372  PHX::Device().fence();
1373 
1374  }
1375 
1376  if(orientations_.size() > 0)
1377  applyOrientationsImpl<Scalar>(num_orientations_cells_, tmp_basis_vector.get_view(), orientations_, *intrepid_basis);
1378 
1379  // Store for later if cache is enabled
1380  PANZER_CACHE_DATA(basis_vector);
1381 
1382  return tmp_basis_vector;
1383 
1384  }
1385 
1386 }
1387 
1388 template <typename Scalar>
1391 getGradBasisValues(const bool weighted,
1392  const bool cache,
1393  const bool force) const
1394 {
1395  if(weighted){
1396  if(weighted_grad_basis_evaluated_ and not force)
1397  return weighted_grad_basis;
1398  } else
1399  if(grad_basis_evaluated_ and not force)
1400  return grad_basis;
1401 
1402  PANZER_FUNC_TIME_MONITOR_DIFF("panzer::basisValues2::getGradBasisValues()",bv_get_grad_bv);
1403 
1404  MDFieldArrayFactory af(prefix,getExtendedDimensions(),true);
1405 
1406  const int num_cells = num_cells_;
1407  const int num_points = basis_layout->numPoints();
1408  const int num_card = basis_layout->cardinality();
1409  const int num_dim = basis_layout->dimension();
1410 
1411  if(weighted){
1412 
1413  TEUCHOS_ASSERT(cubature_weights_.size() > 0);
1414 
1415  // Get the basis_scalar values - do not cache
1416  const auto bv = getGradBasisValues(false, force);
1417 
1418  // Apply the weighted measure (cubature weights)
1419  auto tmp_weighted_grad_basis = af.buildStaticArray<Scalar, Cell, BASIS, IP, Dim>("weighted_grad_basis", num_cells, num_card, num_points, num_dim);
1420 
1421  const std::pair<int,int> cell_range(0,num_evaluate_cells_);
1422  auto s_aux = Kokkos::subview(tmp_weighted_grad_basis.get_view(), cell_range, Kokkos::ALL(), Kokkos::ALL(), Kokkos::ALL());
1423  auto s_cw = Kokkos::subview(cubature_weights_.get_view(), cell_range, Kokkos::ALL());
1424  auto s_bv = Kokkos::subview(bv.get_view(), cell_range, Kokkos::ALL(), Kokkos::ALL(), Kokkos::ALL());
1425 
1426  using fst=Intrepid2::FunctionSpaceTools<PHX::Device::execution_space>;
1427  fst::multiplyMeasure(s_aux,s_cw,s_bv);
1428 
1429  // Store for later if cache is enabled
1430  PANZER_CACHE_DATA(weighted_grad_basis);
1431 
1432  return tmp_weighted_grad_basis;
1433 
1434  } else {
1435 
1436  TEUCHOS_ASSERT(cubature_jacobian_inverse_.size() > 0);
1437 
1438  const auto element_space = getElementSpace();
1439  TEUCHOS_ASSERT(element_space == PureBasis::CONST || element_space == PureBasis::HGRAD);
1440 
1441  auto cell_grad_basis_ref = af.buildStaticArray<Scalar,BASIS,IP,Dim>("cell_grad_basis_ref",num_card,num_points,num_dim);
1442  auto tmp_grad_basis = af.buildStaticArray<Scalar,Cell,BASIS,IP,Dim>("basis_scalar",num_cells,num_card,num_points,num_dim);
1443 
1444  if(hasUniformReferenceSpace()){
1445 
1446  auto cubature_points_uniform_ref = PHX::getNonConstDynRankViewFromConstMDField(cubature_points_uniform_ref_);
1447 
1448  // Apply a single reference representation to all cells
1449  intrepid_basis->getValues(cell_grad_basis_ref.get_view(),cubature_points_uniform_ref,Intrepid2::OPERATOR_GRAD);
1450 
1451  const std::pair<int,int> cell_range(0,num_evaluate_cells_);
1452  auto s_aux = Kokkos::subview(tmp_grad_basis.get_view(), cell_range, Kokkos::ALL(), Kokkos::ALL(), Kokkos::ALL());
1453  auto s_jac_inv = Kokkos::subview(cubature_jacobian_inverse_.get_view(), cell_range, Kokkos::ALL(), Kokkos::ALL(), Kokkos::ALL());
1454 
1455  // Apply transformation
1456  using fst=Intrepid2::FunctionSpaceTools<PHX::Device::execution_space>;
1457  fst::HGRADtransformGRAD(s_aux, s_jac_inv,cell_grad_basis_ref.get_view());
1458 
1459  PHX::Device().fence();
1460 
1461  } else {
1462 
1463  // getValues currently assumes a single reference cell. Calling
1464  // it serially on host until the function supports multiple
1465  // reference cells to avoid a kernel launch per cell.
1466 
1467  // UVM mirror views can't be used with intrepid basis. Let's do an inefficient copy if using UVM.
1468 #ifdef KOKKOS_ENABLE_CUDA
1469  if constexpr (std::is_same<Kokkos::CudaUVMSpace,typename decltype(tmp_grad_basis.get_view())::memory_space>::value) {
1470  auto cubature_points_ref_host = Kokkos::create_mirror(Kokkos::HostSpace{},cubature_points_ref_.get_view());
1471  Kokkos::deep_copy(cubature_points_ref_host,cubature_points_ref_.get_view());
1472  auto tmp_grad_basis_host = Kokkos::create_mirror(Kokkos::HostSpace{},tmp_grad_basis.get_view());
1473 
1474  auto intrepid_basis_host = intrepid_basis->getHostBasis();
1475  for(int cell=0; cell<num_evaluate_cells_; ++cell) {
1476  auto my_cell_grad_basis_host = Kokkos::subview(tmp_grad_basis_host,cell,Kokkos::ALL(),Kokkos::ALL(),Kokkos::ALL());
1477  auto my_cell_cub_points_ref_host = Kokkos::subview(cubature_points_ref_host,cell,Kokkos::ALL(),Kokkos::ALL());
1478  intrepid_basis_host->getValues(my_cell_grad_basis_host,my_cell_cub_points_ref_host,Intrepid2::OPERATOR_GRAD);
1479  }
1480  auto tmp_grad_basis_ref = af.buildStaticArray<Scalar,Cell,BASIS,IP,Dim>("tmp_grad_basis_ref",num_cells,num_card,num_points,num_dim);
1481  Kokkos::deep_copy(tmp_grad_basis_ref.get_view(),tmp_grad_basis_host);
1482 
1483  const std::pair<int,int> cell_range(0,num_evaluate_cells_);
1484  auto s_aux = Kokkos::subview(tmp_grad_basis.get_view(), cell_range, Kokkos::ALL(), Kokkos::ALL(), Kokkos::ALL());
1485  auto s_jac_inv = Kokkos::subview(cubature_jacobian_inverse_.get_view(), cell_range, Kokkos::ALL(), Kokkos::ALL(), Kokkos::ALL());
1486  auto s_ref = Kokkos::subview(tmp_grad_basis_ref.get_view(),cell_range,Kokkos::ALL(),Kokkos::ALL(),Kokkos::ALL());
1487 
1488  // Apply transformation
1489  using fst=Intrepid2::FunctionSpaceTools<PHX::Device::execution_space>;
1490  fst::HGRADtransformGRAD(s_aux, s_jac_inv, s_ref);
1491  } else {
1492 #endif
1493  auto cubature_points_ref_host = Kokkos::create_mirror_view(cubature_points_ref_.get_view());
1494  Kokkos::deep_copy(cubature_points_ref_host,cubature_points_ref_.get_view());
1495  auto tmp_grad_basis_host = Kokkos::create_mirror_view(tmp_grad_basis.get_view());
1496 
1497  auto intrepid_basis_host = intrepid_basis->getHostBasis();
1498  for(int cell=0; cell<num_evaluate_cells_; ++cell) {
1499  auto my_cell_grad_basis_host = Kokkos::subview(tmp_grad_basis_host,cell,Kokkos::ALL(),Kokkos::ALL(),Kokkos::ALL());
1500  auto my_cell_cub_points_ref_host = Kokkos::subview(cubature_points_ref_host,cell,Kokkos::ALL(),Kokkos::ALL());
1501  intrepid_basis_host->getValues(my_cell_grad_basis_host,my_cell_cub_points_ref_host,Intrepid2::OPERATOR_GRAD);
1502  }
1503  auto tmp_grad_basis_ref = af.buildStaticArray<Scalar,Cell,BASIS,IP,Dim>("tmp_grad_basis_ref",num_cells,num_card,num_points,num_dim);
1504  Kokkos::deep_copy(tmp_grad_basis_ref.get_view(),tmp_grad_basis_host);
1505 
1506  const std::pair<int,int> cell_range(0,num_evaluate_cells_);
1507  auto s_aux = Kokkos::subview(tmp_grad_basis.get_view(), cell_range, Kokkos::ALL(), Kokkos::ALL(), Kokkos::ALL());
1508  auto s_jac_inv = Kokkos::subview(cubature_jacobian_inverse_.get_view(), cell_range, Kokkos::ALL(), Kokkos::ALL(), Kokkos::ALL());
1509  auto s_ref = Kokkos::subview(tmp_grad_basis_ref.get_view(),cell_range,Kokkos::ALL(),Kokkos::ALL(),Kokkos::ALL());
1510 
1511  // Apply transformation
1512  using fst=Intrepid2::FunctionSpaceTools<PHX::Device::execution_space>;
1513  fst::HGRADtransformGRAD(s_aux, s_jac_inv, s_ref);
1514 #ifdef KOKKOS_ENABLE_CUDA
1515  }
1516 #endif
1517  PHX::Device().fence();
1518 
1519  }
1520 
1521  if(orientations_.size() > 0)
1522  applyOrientationsImpl<Scalar>(num_orientations_cells_, tmp_grad_basis.get_view(), orientations_, *intrepid_basis);
1523 
1524  // Store for later if cache is enabled
1525  PANZER_CACHE_DATA(grad_basis);
1526 
1527  return tmp_grad_basis;
1528 
1529  }
1530 
1531 }
1532 
1533 template <typename Scalar>
1536 getCurl2DVectorBasis(const bool weighted,
1537  const bool cache,
1538  const bool force) const
1539 {
1540  if(weighted){
1541  if(weighted_curl_basis_scalar_evaluated_ and not force)
1542  return weighted_curl_basis_scalar;
1543  } else
1544  if(curl_basis_scalar_evaluated_ and not force)
1545  return curl_basis_scalar;
1546 
1547  PANZER_FUNC_TIME_MONITOR_DIFF("panzer::basisValues2::getCurl2DVectorBasis()",bv_get_curl2d_vec_bv);
1548 
1549  MDFieldArrayFactory af(prefix,getExtendedDimensions(),true);
1550 
1551  const int num_cells = num_cells_;
1552  const int num_points = basis_layout->numPoints();
1553  const int num_card = basis_layout->cardinality();
1554  const int num_dim = basis_layout->dimension();
1555 
1556  if(weighted){
1557 
1558  TEUCHOS_ASSERT(cubature_weights_.size() > 0);
1559 
1560  // Get the basis_scalar values - do not cache
1561  const auto bv = getCurl2DVectorBasis(false, force);
1562 
1563  // Apply the weighted measure (cubature weights)
1564  auto tmp_weighted_curl_basis_scalar = af.buildStaticArray<Scalar, Cell, BASIS, IP>("weighted_curl_basis_scalar", num_cells, num_card, num_points);
1565 
1566  const std::pair<int,int> cell_range(0,num_evaluate_cells_);
1567  auto s_aux = Kokkos::subview(tmp_weighted_curl_basis_scalar.get_view(), cell_range, Kokkos::ALL(), Kokkos::ALL());
1568  auto s_cw = Kokkos::subview(cubature_weights_.get_view(), cell_range, Kokkos::ALL());
1569  auto s_bv = Kokkos::subview(bv.get_view(), cell_range, Kokkos::ALL(), Kokkos::ALL());
1570 
1571  using fst=Intrepid2::FunctionSpaceTools<PHX::Device::execution_space>;
1572  fst::multiplyMeasure(s_aux,s_cw,s_bv);
1573 
1574  // Store for later if cache is enabled
1575  PANZER_CACHE_DATA(weighted_curl_basis_scalar);
1576 
1577  return tmp_weighted_curl_basis_scalar;
1578 
1579  } else {
1580 
1581  TEUCHOS_ASSERT(cubature_jacobian_determinant_.size() > 0);
1582  TEUCHOS_ASSERT(num_dim == 2);
1583 
1584  const auto element_space = getElementSpace();
1585  TEUCHOS_ASSERT(element_space == PureBasis::HCURL);
1586 
1587  auto tmp_curl_basis_scalar = af.buildStaticArray<Scalar,Cell,BASIS,IP>("curl_basis_scalar",num_cells,num_card,num_points);
1588 
1589  if(hasUniformReferenceSpace()){
1590 
1591  auto cell_curl_basis_ref_scalar = af.buildStaticArray<Scalar,BASIS,IP>("cell_curl_basis_ref_scalar",num_card,num_points);
1592  auto cubature_points_uniform_ref = PHX::getNonConstDynRankViewFromConstMDField(cubature_points_uniform_ref_);
1593 
1594  intrepid_basis->getValues(cell_curl_basis_ref_scalar.get_view(),cubature_points_uniform_ref,Intrepid2::OPERATOR_CURL);
1595 
1596  const std::pair<int,int> cell_range(0,num_evaluate_cells_);
1597  auto s_aux = Kokkos::subview(tmp_curl_basis_scalar.get_view(), cell_range, Kokkos::ALL(), Kokkos::ALL());
1598  auto s_jac_det = Kokkos::subview(cubature_jacobian_determinant_.get_view(), cell_range, Kokkos::ALL());
1599 
1600  // note only volume deformation is needed!
1601  // this relates directly to this being in
1602  // the divergence space in 2D!
1603  using fst=Intrepid2::FunctionSpaceTools<PHX::Device::execution_space>;
1604  fst::HDIVtransformDIV(s_aux,s_jac_det,cell_curl_basis_ref_scalar.get_view());
1605  PHX::Device().fence();
1606 
1607  } else {
1608 
1609  // getValues currently assumes a single reference cell. Calling
1610  // it serially on host until the function supports multiple
1611  // reference cells to avoid a kernel launch per cell.
1612 
1613  // UVM mirror views can't be used with intrepid basis. Let's do an inefficient copy if using UVM.
1614 #ifdef KOKKOS_ENABLE_CUDA
1615  if constexpr (std::is_same<Kokkos::CudaUVMSpace,typename decltype(tmp_curl_basis_scalar.get_view())::memory_space>::value) {
1616  auto cubature_points_ref_host = Kokkos::create_mirror(Kokkos::HostSpace{},cubature_points_ref_.get_view());
1617  Kokkos::deep_copy(cubature_points_ref_host,cubature_points_ref_.get_view());
1618  auto tmp_curl_basis_scalar_host = Kokkos::create_mirror(Kokkos::HostSpace{},tmp_curl_basis_scalar.get_view());
1619 
1620  auto intrepid_basis_host = intrepid_basis->getHostBasis();
1621  for(int cell=0; cell<num_evaluate_cells_; ++cell) {
1622  auto my_cell_curl_basis_host = Kokkos::subview(tmp_curl_basis_scalar_host,cell,Kokkos::ALL(),Kokkos::ALL());
1623  auto my_cell_cub_points_ref_host = Kokkos::subview(cubature_points_ref_host,cell,Kokkos::ALL(),Kokkos::ALL());
1624  intrepid_basis_host->getValues(my_cell_curl_basis_host,my_cell_cub_points_ref_host,Intrepid2::OPERATOR_CURL);
1625  }
1626  auto tmp_curl_basis_scalar_ref = af.buildStaticArray<Scalar,Cell,BASIS,IP>("tmp_curl_basis_scalar_ref",num_cells,num_card,num_points);
1627  Kokkos::deep_copy(tmp_curl_basis_scalar_ref.get_view(),tmp_curl_basis_scalar_host);
1628 
1629  const std::pair<int,int> cell_range(0,num_evaluate_cells_);
1630  auto s_aux = Kokkos::subview(tmp_curl_basis_scalar.get_view(), cell_range, Kokkos::ALL(), Kokkos::ALL());
1631  auto s_jac_det = Kokkos::subview(cubature_jacobian_determinant_.get_view(), cell_range, Kokkos::ALL());
1632  auto s_ref = Kokkos::subview(tmp_curl_basis_scalar_ref.get_view(), cell_range, Kokkos::ALL(), Kokkos::ALL());
1633 
1634  // note only volume deformation is needed!
1635  // this relates directly to this being in
1636  // the divergence space in 2D!
1637  using fst=Intrepid2::FunctionSpaceTools<PHX::Device::execution_space>;
1638  fst::HDIVtransformDIV(s_aux,s_jac_det,s_ref);
1639  } else {
1640 #endif
1641  auto cubature_points_ref_host = Kokkos::create_mirror_view(cubature_points_ref_.get_view());
1642  Kokkos::deep_copy(cubature_points_ref_host,cubature_points_ref_.get_view());
1643  auto tmp_curl_basis_scalar_host = Kokkos::create_mirror_view(tmp_curl_basis_scalar.get_view());
1644 
1645  auto intrepid_basis_host = intrepid_basis->getHostBasis();
1646  for(int cell=0; cell<num_evaluate_cells_; ++cell) {
1647  auto my_cell_curl_basis_host = Kokkos::subview(tmp_curl_basis_scalar_host,cell,Kokkos::ALL(),Kokkos::ALL());
1648  auto my_cell_cub_points_ref_host = Kokkos::subview(cubature_points_ref_host,cell,Kokkos::ALL(),Kokkos::ALL());
1649  intrepid_basis_host->getValues(my_cell_curl_basis_host,my_cell_cub_points_ref_host,Intrepid2::OPERATOR_CURL);
1650  }
1651  auto tmp_curl_basis_scalar_ref = af.buildStaticArray<Scalar,Cell,BASIS,IP>("tmp_curl_basis_scalar_ref",num_cells,num_card,num_points);
1652  Kokkos::deep_copy(tmp_curl_basis_scalar_ref.get_view(),tmp_curl_basis_scalar_host);
1653 
1654  const std::pair<int,int> cell_range(0,num_evaluate_cells_);
1655  auto s_aux = Kokkos::subview(tmp_curl_basis_scalar.get_view(), cell_range, Kokkos::ALL(), Kokkos::ALL());
1656  auto s_jac_det = Kokkos::subview(cubature_jacobian_determinant_.get_view(), cell_range, Kokkos::ALL());
1657  auto s_ref = Kokkos::subview(tmp_curl_basis_scalar_ref.get_view(), cell_range, Kokkos::ALL(), Kokkos::ALL());
1658 
1659  // note only volume deformation is needed!
1660  // this relates directly to this being in
1661  // the divergence space in 2D!
1662  using fst=Intrepid2::FunctionSpaceTools<PHX::Device::execution_space>;
1663  fst::HDIVtransformDIV(s_aux,s_jac_det,s_ref);
1664 #ifdef KOKKOS_ENABLE_CUDA
1665  }
1666 #endif
1667  PHX::Device().fence();
1668  }
1669 
1670  if(orientations_.size() > 0)
1671  applyOrientationsImpl<Scalar>(num_orientations_cells_, tmp_curl_basis_scalar.get_view(), orientations_, *intrepid_basis);
1672 
1673  // Store for later if cache is enabled
1674  PANZER_CACHE_DATA(curl_basis_scalar);
1675 
1676  return tmp_curl_basis_scalar;
1677 
1678  }
1679 
1680 }
1681 
1682 template <typename Scalar>
1685 getCurlVectorBasis(const bool weighted,
1686  const bool cache,
1687  const bool force) const
1688 {
1689  if(weighted){
1690  if(weighted_curl_basis_vector_evaluated_ and not force)
1691  return weighted_curl_basis_vector;
1692  } else
1693  if(curl_basis_vector_evaluated_ and not force)
1694  return curl_basis_vector;
1695 
1696  PANZER_FUNC_TIME_MONITOR_DIFF("panzer::basisValues2::getCurlVectorBasis()",bv_get_curl_vec_bv);
1697 
1698  MDFieldArrayFactory af(prefix,getExtendedDimensions(),true);
1699 
1700  const int num_cells = num_cells_;
1701  const int num_points = basis_layout->numPoints();
1702  const int num_card = basis_layout->cardinality();
1703  const int num_dim = basis_layout->dimension();
1704 
1705  if(weighted){
1706 
1707  TEUCHOS_ASSERT(cubature_weights_.size() > 0);
1708 
1709  // Get the basis_scalar values - do not cache
1710  const auto bv = getCurlVectorBasis(false, force);
1711 
1712  // Apply the weighted measure (cubature weights)
1713  auto tmp_weighted_curl_basis_vector = af.buildStaticArray<Scalar, Cell, BASIS, IP, Dim>("weighted_curl_basis_vector", num_cells, num_card, num_points, num_dim);
1714 
1715  const std::pair<int,int> cell_range(0,num_evaluate_cells_);
1716  auto s_aux = Kokkos::subview(tmp_weighted_curl_basis_vector.get_view(), cell_range, Kokkos::ALL(), Kokkos::ALL(), Kokkos::ALL());
1717  auto s_cw = Kokkos::subview(cubature_weights_.get_view(), cell_range, Kokkos::ALL());
1718  auto s_bv = Kokkos::subview(bv.get_view(), cell_range, Kokkos::ALL(), Kokkos::ALL(), Kokkos::ALL());
1719 
1720  using fst=Intrepid2::FunctionSpaceTools<PHX::Device::execution_space>;
1721  fst::multiplyMeasure(s_aux, s_cw, s_bv);
1722 
1723  // Store for later if cache is enabled
1724  PANZER_CACHE_DATA(weighted_curl_basis_vector);
1725 
1726  return tmp_weighted_curl_basis_vector;
1727 
1728  } else {
1729 
1730  TEUCHOS_ASSERT(cubature_jacobian_determinant_.size() > 0);
1731  TEUCHOS_ASSERT(num_dim == 3);
1732 
1733  const auto element_space = getElementSpace();
1734  TEUCHOS_ASSERT(element_space == PureBasis::HCURL);
1735 
1736  auto tmp_curl_basis_vector = af.buildStaticArray<Scalar,Cell,BASIS,IP,Dim>("curl_basis_vector",num_cells,num_card,num_points,num_dim);
1737 
1738  if(hasUniformReferenceSpace()){
1739 
1740  auto cell_curl_basis_ref_vector = af.buildStaticArray<Scalar,BASIS,IP,Dim>("cell_curl_basis_ref_vector",num_card,num_points,num_dim);
1741  auto cubature_points_uniform_ref = PHX::getNonConstDynRankViewFromConstMDField(cubature_points_uniform_ref_);
1742 
1743  intrepid_basis->getValues(cell_curl_basis_ref_vector.get_view(),cubature_points_uniform_ref,Intrepid2::OPERATOR_CURL);
1744 
1745  const std::pair<int,int> cell_range(0,num_evaluate_cells_);
1746  auto s_aux = Kokkos::subview(tmp_curl_basis_vector.get_view(), cell_range, Kokkos::ALL(), Kokkos::ALL(), Kokkos::ALL());
1747  auto s_jac = Kokkos::subview(cubature_jacobian_.get_view(), cell_range, Kokkos::ALL(), Kokkos::ALL(), Kokkos::ALL());
1748  auto s_jac_det = Kokkos::subview(cubature_jacobian_determinant_.get_view(), cell_range, Kokkos::ALL());
1749 
1750  using fst=Intrepid2::FunctionSpaceTools<PHX::Device::execution_space>;
1751  fst::HCURLtransformCURL(s_aux, s_jac, s_jac_det,cell_curl_basis_ref_vector.get_view());
1752  PHX::Device().fence();
1753 
1754  } else {
1755 
1756  // getValues currently assumes a single reference cell. Calling
1757  // it serially on host until the function supports multiple
1758  // reference cells to avoid a kernel launch per cell.
1759 
1760  // UVM mirror views can't be used with intrepid basis. Let's do an inefficient copy if using UVM.
1761 #ifdef KOKKOS_ENABLE_CUDA
1762  if constexpr (std::is_same<Kokkos::CudaUVMSpace,typename decltype(tmp_curl_basis_vector.get_view())::memory_space>::value) {
1763  auto cubature_points_ref_host = Kokkos::create_mirror(Kokkos::HostSpace{},cubature_points_ref_.get_view());
1764  Kokkos::deep_copy(cubature_points_ref_host,cubature_points_ref_.get_view());
1765  auto tmp_curl_basis_vector_host = Kokkos::create_mirror(Kokkos::HostSpace{},tmp_curl_basis_vector.get_view());
1766 
1767  auto intrepid_basis_host = intrepid_basis->getHostBasis();
1768  for(int cell=0; cell<num_evaluate_cells_; ++cell) {
1769  auto my_cell_curl_basis_host = Kokkos::subview(tmp_curl_basis_vector_host,cell,Kokkos::ALL(),Kokkos::ALL(),Kokkos::ALL());
1770  auto my_cell_cub_points_ref_host = Kokkos::subview(cubature_points_ref_host,cell,Kokkos::ALL(),Kokkos::ALL());
1771  intrepid_basis_host->getValues(my_cell_curl_basis_host,my_cell_cub_points_ref_host,Intrepid2::OPERATOR_CURL);
1772  }
1773  auto tmp_curl_basis_vector_ref = af.buildStaticArray<Scalar,Cell,BASIS,IP,Dim>("tmp_curl_basis_scalar_ref",num_cells,num_card,num_points,num_dim);
1774  Kokkos::deep_copy(tmp_curl_basis_vector_ref.get_view(),tmp_curl_basis_vector_host);
1775 
1776  const std::pair<int,int> cell_range(0,num_evaluate_cells_);
1777  auto s_aux = Kokkos::subview(tmp_curl_basis_vector.get_view(), cell_range, Kokkos::ALL(), Kokkos::ALL(), Kokkos::ALL());
1778  auto s_jac = Kokkos::subview(cubature_jacobian_.get_view(), cell_range, Kokkos::ALL(), Kokkos::ALL(), Kokkos::ALL());
1779  auto s_jac_det = Kokkos::subview(cubature_jacobian_determinant_.get_view(), cell_range, Kokkos::ALL());
1780  auto s_ref = Kokkos::subview(tmp_curl_basis_vector_ref.get_view(), cell_range, Kokkos::ALL(), Kokkos::ALL(), Kokkos::ALL());
1781 
1782  using fst=Intrepid2::FunctionSpaceTools<PHX::Device::execution_space>;
1783  fst::HCURLtransformCURL(s_aux, s_jac, s_jac_det, s_ref);
1784  } else {
1785 #endif
1786  auto cubature_points_ref_host = Kokkos::create_mirror_view(cubature_points_ref_.get_view());
1787  Kokkos::deep_copy(cubature_points_ref_host,cubature_points_ref_.get_view());
1788  auto tmp_curl_basis_vector_host = Kokkos::create_mirror_view(tmp_curl_basis_vector.get_view());
1789 
1790  auto intrepid_basis_host = intrepid_basis->getHostBasis();
1791  for(int cell=0; cell<num_evaluate_cells_; ++cell) {
1792  auto my_cell_curl_basis_host = Kokkos::subview(tmp_curl_basis_vector_host,cell,Kokkos::ALL(),Kokkos::ALL(),Kokkos::ALL());
1793  auto my_cell_cub_points_ref_host = Kokkos::subview(cubature_points_ref_host,cell,Kokkos::ALL(),Kokkos::ALL());
1794  intrepid_basis_host->getValues(my_cell_curl_basis_host,my_cell_cub_points_ref_host,Intrepid2::OPERATOR_CURL);
1795  }
1796  auto tmp_curl_basis_vector_ref = af.buildStaticArray<Scalar,Cell,BASIS,IP,Dim>("tmp_curl_basis_scalar_ref",num_cells,num_card,num_points,num_dim);
1797  Kokkos::deep_copy(tmp_curl_basis_vector_ref.get_view(),tmp_curl_basis_vector_host);
1798 
1799  const std::pair<int,int> cell_range(0,num_evaluate_cells_);
1800  auto s_aux = Kokkos::subview(tmp_curl_basis_vector.get_view(), cell_range, Kokkos::ALL(), Kokkos::ALL(), Kokkos::ALL());
1801  auto s_jac = Kokkos::subview(cubature_jacobian_.get_view(), cell_range, Kokkos::ALL(), Kokkos::ALL(), Kokkos::ALL());
1802  auto s_jac_det = Kokkos::subview(cubature_jacobian_determinant_.get_view(), cell_range, Kokkos::ALL());
1803  auto s_ref = Kokkos::subview(tmp_curl_basis_vector_ref.get_view(), cell_range, Kokkos::ALL(), Kokkos::ALL(), Kokkos::ALL());
1804 
1805  using fst=Intrepid2::FunctionSpaceTools<PHX::Device::execution_space>;
1806  fst::HCURLtransformCURL(s_aux, s_jac, s_jac_det, s_ref);
1807 #ifdef KOKKOS_ENABLE_CUDA
1808  }
1809 #endif
1810  PHX::Device().fence();
1811 
1812  }
1813 
1814  if(orientations_.size() > 0)
1815  applyOrientationsImpl<Scalar>(num_orientations_cells_, tmp_curl_basis_vector.get_view(), orientations_, *intrepid_basis);
1816 
1817  // Store for later if cache is enabled
1818  PANZER_CACHE_DATA(curl_basis_vector);
1819 
1820  return tmp_curl_basis_vector;
1821 
1822  }
1823 
1824 }
1825 
1826 template <typename Scalar>
1829 getDivVectorBasis(const bool weighted,
1830  const bool cache,
1831  const bool force) const
1832 {
1833  if(weighted){
1834  if(weighted_div_basis_evaluated_ and not force)
1835  return weighted_div_basis;
1836  } else
1837  if(div_basis_evaluated_ and not force)
1838  return div_basis;
1839 
1840  PANZER_FUNC_TIME_MONITOR_DIFF("panzer::basisValues2::getDevVectorBasis()",bv_get_div_vec_bv);
1841 
1842  MDFieldArrayFactory af(prefix,getExtendedDimensions(),true);
1843 
1844  const int num_cells = num_cells_;
1845  const int num_points = basis_layout->numPoints();
1846  const int num_card = basis_layout->cardinality();
1847 
1848  if(weighted){
1849 
1850  TEUCHOS_ASSERT(cubature_weights_.size() > 0);
1851 
1852  // Get the basis_scalar values - do not cache
1853  const auto bv = getDivVectorBasis(false, force);
1854 
1855  // Apply the weighted measure (cubature weights)
1856  auto tmp_weighted_div_basis = af.buildStaticArray<Scalar, Cell, BASIS, IP>("weighted_div_basis", num_cells, num_card, num_points);
1857 
1858  const std::pair<int,int> cell_range(0,num_evaluate_cells_);
1859  auto s_aux = Kokkos::subview(tmp_weighted_div_basis.get_view(), cell_range, Kokkos::ALL(), Kokkos::ALL());
1860  auto s_cw = Kokkos::subview(cubature_weights_.get_view(), cell_range, Kokkos::ALL());
1861  auto s_bv = Kokkos::subview(bv.get_view(), cell_range, Kokkos::ALL(), Kokkos::ALL());
1862 
1863  using fst=Intrepid2::FunctionSpaceTools<PHX::Device::execution_space>;
1864  fst::multiplyMeasure(s_aux, s_cw, s_bv);
1865 
1866  // Store for later if cache is enabled
1867  PANZER_CACHE_DATA(weighted_div_basis);
1868 
1869  return tmp_weighted_div_basis;
1870 
1871  } else {
1872 
1873  TEUCHOS_ASSERT(cubature_jacobian_determinant_.size() > 0);
1874 
1875  const auto element_space = getElementSpace();
1876  TEUCHOS_ASSERT(element_space == PureBasis::HDIV);
1877 
1878  auto tmp_div_basis = af.buildStaticArray<Scalar,Cell,BASIS,IP>("div_basis",num_cells,num_card,num_points);
1879 
1880  if(hasUniformReferenceSpace()){
1881 
1882  auto cell_div_basis_ref = af.buildStaticArray<Scalar,BASIS,IP>("cell_div_basis_ref",num_card,num_points);
1883  auto cubature_points_uniform_ref = PHX::getNonConstDynRankViewFromConstMDField(cubature_points_uniform_ref_);
1884 
1885  intrepid_basis->getValues(cell_div_basis_ref.get_view(),cubature_points_uniform_ref,Intrepid2::OPERATOR_DIV);
1886 
1887  const std::pair<int,int> cell_range(0,num_evaluate_cells_);
1888  auto s_aux = Kokkos::subview(tmp_div_basis.get_view(), cell_range, Kokkos::ALL(), Kokkos::ALL());
1889  auto s_jac_det = Kokkos::subview(cubature_jacobian_determinant_.get_view(), cell_range, Kokkos::ALL());
1890 
1891  using fst=Intrepid2::FunctionSpaceTools<PHX::Device::execution_space>;
1892  fst::HDIVtransformDIV(s_aux,s_jac_det,cell_div_basis_ref.get_view());
1893  PHX::Device().fence();
1894 
1895  } else {
1896 
1897  // getValues currently assumes a single reference cell. Calling
1898  // it serially on host until the function supports multiple
1899  // reference cells to avoid a kernel launch per cell.
1900 
1901  // UVM mirror views can't be used with intrepid basis. Let's do an inefficient copy if using UVM.
1902 #ifdef KOKKOS_ENABLE_CUDA
1903  if constexpr (std::is_same<Kokkos::CudaUVMSpace,typename decltype(tmp_div_basis.get_view())::memory_space>::value) {
1904  auto cubature_points_ref_host = Kokkos::create_mirror(Kokkos::HostSpace{},cubature_points_ref_.get_view());
1905  Kokkos::deep_copy(cubature_points_ref_host,cubature_points_ref_.get_view());
1906  auto tmp_div_basis_host = Kokkos::create_mirror(Kokkos::HostSpace{},tmp_div_basis.get_view());
1907 
1908  auto intrepid_basis_host = intrepid_basis->getHostBasis();
1909  for(int cell=0; cell<num_evaluate_cells_; ++cell) {
1910  auto my_cell_div_basis_host = Kokkos::subview(tmp_div_basis_host,cell,Kokkos::ALL(),Kokkos::ALL());
1911  auto my_cell_cub_points_ref_host = Kokkos::subview(cubature_points_ref_host,cell,Kokkos::ALL(),Kokkos::ALL());
1912  intrepid_basis_host->getValues(my_cell_div_basis_host,my_cell_cub_points_ref_host,Intrepid2::OPERATOR_DIV);
1913  }
1914  auto tmp_div_basis_ref = af.buildStaticArray<Scalar,Cell,BASIS,IP>("tmp_div_basis_ref",num_cells,num_card,num_points);
1915  Kokkos::deep_copy(tmp_div_basis_ref.get_view(),tmp_div_basis_host);
1916 
1917  const std::pair<int,int> cell_range(0,num_evaluate_cells_);
1918  auto s_aux = Kokkos::subview(tmp_div_basis.get_view(), cell_range, Kokkos::ALL(), Kokkos::ALL());
1919  auto s_jac_det = Kokkos::subview(cubature_jacobian_determinant_.get_view(), cell_range, Kokkos::ALL());
1920  auto s_ref = Kokkos::subview(tmp_div_basis_ref.get_view(), cell_range, Kokkos::ALL(), Kokkos::ALL());
1921 
1922  using fst=Intrepid2::FunctionSpaceTools<PHX::Device::execution_space>;
1923  fst::HDIVtransformDIV(s_aux,s_jac_det,s_ref);
1924  } else {
1925 #endif
1926  auto cubature_points_ref_host = Kokkos::create_mirror_view(cubature_points_ref_.get_view());
1927  Kokkos::deep_copy(cubature_points_ref_host,cubature_points_ref_.get_view());
1928  auto tmp_div_basis_host = Kokkos::create_mirror_view(tmp_div_basis.get_view());
1929 
1930  auto intrepid_basis_host = intrepid_basis->getHostBasis();
1931  for(int cell=0; cell<num_evaluate_cells_; ++cell) {
1932  auto my_cell_div_basis_host = Kokkos::subview(tmp_div_basis_host,cell,Kokkos::ALL(),Kokkos::ALL());
1933  auto my_cell_cub_points_ref_host = Kokkos::subview(cubature_points_ref_host,cell,Kokkos::ALL(),Kokkos::ALL());
1934  intrepid_basis_host->getValues(my_cell_div_basis_host,my_cell_cub_points_ref_host,Intrepid2::OPERATOR_DIV);
1935  }
1936  auto tmp_div_basis_ref = af.buildStaticArray<Scalar,Cell,BASIS,IP>("tmp_div_basis_ref",num_cells,num_card,num_points);
1937  Kokkos::deep_copy(tmp_div_basis_ref.get_view(),tmp_div_basis_host);
1938 
1939  const std::pair<int,int> cell_range(0,num_evaluate_cells_);
1940  auto s_aux = Kokkos::subview(tmp_div_basis.get_view(), cell_range, Kokkos::ALL(), Kokkos::ALL());
1941  auto s_jac_det = Kokkos::subview(cubature_jacobian_determinant_.get_view(), cell_range, Kokkos::ALL());
1942  auto s_ref = Kokkos::subview(tmp_div_basis_ref.get_view(), cell_range, Kokkos::ALL(), Kokkos::ALL());
1943 
1944  using fst=Intrepid2::FunctionSpaceTools<PHX::Device::execution_space>;
1945  fst::HDIVtransformDIV(s_aux,s_jac_det,s_ref);
1946 #ifdef KOKKOS_ENABLE_CUDA
1947  }
1948 #endif
1949  PHX::Device().fence();
1950 
1951  }
1952 
1953  if(orientations_.size() > 0)
1954  applyOrientationsImpl<Scalar>(num_orientations_cells_, tmp_div_basis.get_view(), orientations_, *intrepid_basis);
1955 
1956  // Store for later if cache is enabled
1957  PANZER_CACHE_DATA(div_basis);
1958 
1959  return tmp_div_basis;
1960 
1961  }
1962 
1963 }
1964 
1965 //=======================================================================================================
1966 
1967 } // namespace panzer
void setOrientations(const std::vector< Intrepid2::Orientation > &orientations, const int num_orientations_cells=-1)
Set the orientations object for applying orientations using the lazy evaluation path - required for c...
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.
ConstArray_BasisIP getCurl2DVectorBasisRef(const bool cache=true, const bool force=false) const
Get the curl of a vector basis evaluated at reference points.
void evaluateValuesCV(const PHX::MDField< Scalar, Cell, IP, Dim > &cell_cub_points, const PHX::MDField< Scalar, Cell, IP, Dim, Dim > &jac, const PHX::MDField< Scalar, Cell, IP > &jac_det, const PHX::MDField< Scalar, Cell, IP, Dim, Dim > &jac_inv)
bool basis_ref_scalar_evaluated_
Used to check if arrays have been cached.
EElementSpace getElementSpace() const
ConstArray_BasisIPDim getVectorBasisValuesRef(const bool cache=true, const bool force=false) const
Get the vector basis values evaluated at reference points.
Teuchos::RCP< const CellTopologyInfo > getCellTopologyInfo() const
int cardinality() const
Returns the number of basis coefficients.
PHX::MDField< Scalar, T0 > buildStaticArray(const std::string &str, int d0) const
ConstArray_BasisIP getBasisValuesRef(const bool cache=true, const bool force=false) const
Get the basis values evaluated at reference points.
panzer::BasisDescriptor getBasisDescriptor() const
Return the basis descriptor.
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
int dimension() const
Returns the dimension of the basis from the topology.
void applyOrientations(const PHX::MDField< const Scalar, Cell, BASIS > &orientations)
Method to apply orientations to a basis values container.
Teuchos::RCP< const shards::CellTopology > getCellTopology() const
#define TEUCHOS_TEST_FOR_EXCEPT_MSG(throw_exception_test, msg)
ConstArray_CellBasisIP getBasisValues(const bool weighted, const bool cache=true, const bool force=false) const
Get the basis values evaluated at mesh points.
void setup(const Teuchos::RCP< const panzer::BasisIRLayout > &basis, PHX::MDField< const Scalar, Cell, IP, Dim > reference_points, PHX::MDField< const Scalar, Cell, IP, Dim, Dim > point_jacobian, PHX::MDField< const Scalar, Cell, IP > point_jacobian_determinant, PHX::MDField< const Scalar, Cell, IP, Dim, Dim > point_jacobian_inverse, const int num_evaluated_cells=-1)
Setup for lazy evaluation for non-uniform point layout.
ConstArray_CellBasisDim getBasisCoordinates(const bool cache=true, const bool force=false) const
Carterisan coordinates for basis coefficients in mesh space.
PureBasis::EElementSpace getElementSpace() const
Teuchos::RCP< Intrepid2::Basis< PHX::Device::execution_space, double, double > > getIntrepid2Basis() const
ConstArray_BasisIP getDivVectorBasisRef(const bool cache=true, const bool force=false) const
Get the divergence of a vector basis evaluated at reference points.
ConstArray_CellBasisIP getDivVectorBasis(const bool weighted, const bool cache=true, const bool force=false) const
Get the divergence of a vector basis evaluated at mesh points.
#define PANZER_CACHE_DATA(name)
void setupArrays(const Teuchos::RCP< const panzer::BasisIRLayout > &basis, bool computeDerivatives=true)
Sizes/allocates memory for arrays.
int numCells() const
Returns the number of cells in the data layouts.
ConstArray_CellBasisIPDim getVectorBasisValues(const bool weighted, const bool cache=true, const bool force=false) const
Get the vector basis values evaluated at mesh points.
ConstArray_BasisIPDim getCurlVectorBasisRef(const bool cache=true, const bool force=false) const
Get the curl of a vector basis evaluated at reference points.
BasisValues2(const std::string &prefix="", const bool allocArrays=false, const bool buildWeighted=false)
Main constructor.
ConstArray_BasisDim getBasisCoordinatesRef(const bool cache=true, const bool force=false) const
Get the reference coordinates for basis.
void evaluateBasisCoordinates(const PHX::MDField< Scalar, Cell, NODE, Dim > &node_coordinates, const int in_num_cells=-1)
#define TEUCHOS_ASSERT(assertion_test)
void setupUniform(const Teuchos::RCP< const panzer::BasisIRLayout > &basis, PHX::MDField< const Scalar, IP, Dim > reference_points, PHX::MDField< const Scalar, Cell, IP, Dim, Dim > point_jacobian, PHX::MDField< const Scalar, Cell, IP > point_jacobian_determinant, PHX::MDField< const Scalar, Cell, IP, Dim, Dim > point_jacobian_inverse, const int num_evaluated_cells=-1)
Setup for lazy evaluation for uniform point layout.
void setCellNodeCoordinates(PHX::MDField< Scalar, Cell, NODE, Dim > node_coordinates)
Set the cell node coordinates (required for getBasisCoordinates())
void evaluateValues(const PHX::MDField< Scalar, IP, Dim > &cub_points, const PHX::MDField< Scalar, Cell, IP, Dim, Dim > &jac, const PHX::MDField< Scalar, Cell, IP > &jac_det, const PHX::MDField< Scalar, Cell, IP, Dim, Dim > &jac_inv, const int in_num_cells=-1)
ConstArray_CellBasisIPDim getGradBasisValues(const bool weighted, const bool cache=true, const bool force=false) const
Get the gradient of the basis evaluated at mesh points.
void setWeightedMeasure(PHX::MDField< const Scalar, Cell, IP > weighted_measure)
Set the cubature weights (weighted measure) for the basis values object - required to get weighted ba...
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.
ConstArray_BasisIPDim getGradBasisValuesRef(const bool cache=true, const bool force=false) const
Get the gradient of the basis evaluated at reference points.