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