Intrepid2
Intrepid2_OrientationToolsDefModifyBasis.hpp
Go to the documentation of this file.
1// @HEADER
2// ************************************************************************
3//
4// Intrepid2 Package
5// Copyright (2007) Sandia Corporation
6//
7// Under terms of Contract DE-AC04-94AL85000, there is a non-exclusive
8// license for use of this work by or on behalf of the U.S. Government.
9//
10// Redistribution and use in source and binary forms, with or without
11// modification, are permitted provided that the following conditions are
12// met:
13//
14// 1. Redistributions of source code must retain the above copyright
15// notice, this list of conditions and the following disclaimer.
16//
17// 2. Redistributions in binary form must reproduce the above copyright
18// notice, this list of conditions and the following disclaimer in the
19// documentation and/or other materials provided with the distribution.
20//
21// 3. Neither the name of the Corporation nor the names of the
22// contributors may be used to endorse or promote products derived from
23// this software without specific prior written permission.
24//
25// THIS SOFTWARE IS PROVIDED BY SANDIA CORPORATION "AS IS" AND ANY
26// EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
27// IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR
28// PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL SANDIA CORPORATION OR THE
29// CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL,
30// EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO,
31// PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR
32// PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF
33// LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING
34// NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS
35// SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
36//
37// Questions? Contact Kyungjoo Kim (kyukim@sandia.gov), or
38// Mauro Perego (mperego@sandia.gov)
39//
40// ************************************************************************
41// @HEADER
42
43
48#ifndef __INTREPID2_ORIENTATIONTOOLS_DEF_MODIFY_BASIS_HPP__
49#define __INTREPID2_ORIENTATIONTOOLS_DEF_MODIFY_BASIS_HPP__
50
51// disable clang warnings
52#if defined (__clang__) && !defined (__INTEL_COMPILER)
53#pragma clang system_header
54#endif
55
57
58namespace Intrepid2 {
59
60 template<typename DT>
61 template<typename elemOrtValueType, class ...elemOrtProperties,
62 typename elemNodeValueType, class ...elemNodeProperties>
63 void
65 getOrientation( Kokkos::DynRankView<elemOrtValueType,elemOrtProperties...> elemOrts,
66 const Kokkos::DynRankView<elemNodeValueType,elemNodeProperties...> elemNodes,
67 const shards::CellTopology cellTopo,
68 bool isSide) {
69 // small meta data modification and it uses shards; let's do this on host
70 auto elemOrtsHost = Kokkos::create_mirror_view(elemOrts);
71 auto elemNodesHost = Kokkos::create_mirror_view_and_copy(Kokkos::HostSpace(), elemNodes);
72
73 const ordinal_type numCells = elemNodes.extent(0);
74 for (auto cell=0;cell<numCells;++cell) {
75 const auto nodes = Kokkos::subview(elemNodesHost, cell, Kokkos::ALL());
76 elemOrtsHost(cell) = Orientation::getOrientation(cellTopo, nodes, isSide);
77 }
78
79 Kokkos::deep_copy(elemOrts, elemOrtsHost);
80 }
81
82 template<typename ortViewType,
83 typename OutputViewType,
84 typename inputViewType,
85 typename o2tViewType,
86 typename t2oViewType,
87 typename dataViewType>
88 struct F_modifyBasisByOrientation {
89 ortViewType orts;
90 OutputViewType output;
91 inputViewType input;
92 o2tViewType ordinalToTag;
93 t2oViewType tagToOrdinal;
94
95 const dataViewType matData;
96 const ordinal_type cellDim, numVerts, numEdges, numFaces, numPoints, dimBasis;
97 const bool leftMultiply;
98 // for simple left-multiplied basis value modification, numPoints is the dimension after the field dimension
99 // for matrix value modification (C,F1,F2), numPoints is F2 when left multiplied, and F1 when right multiplied
100 const bool transpose; // when true, multiply by the transpose of the matrix
101
102 F_modifyBasisByOrientation(ortViewType orts_,
103 OutputViewType output_,
104 inputViewType input_,
105 o2tViewType ordinalToTag_,
106 t2oViewType tagToOrdinal_,
107 const dataViewType matData_,
108 const ordinal_type cellDim_,
109 const ordinal_type numVerts_,
110 const ordinal_type numEdges_,
111 const ordinal_type numFaces_,
112 const ordinal_type numPoints_,
113 const ordinal_type dimBasis_,
114 const bool leftMultiply_ = true,
115 const bool transpose_ = false)
116 : orts(orts_),
117 output(output_),
118 input(input_),
119 ordinalToTag(ordinalToTag_),
120 tagToOrdinal(tagToOrdinal_),
121 matData(matData_),
122 cellDim(cellDim_),
123 numVerts(numVerts_),
124 numEdges(numEdges_),
125 numFaces(numFaces_),
126 numPoints(numPoints_),
127 dimBasis(dimBasis_),
128 leftMultiply(leftMultiply_),
129 transpose(transpose_)
130 {}
131
132 KOKKOS_INLINE_FUNCTION
133 void operator()(const ordinal_type cell) const {
134 typedef typename inputViewType::non_const_value_type input_value_type;
135
136 auto out = Kokkos::subview(output, cell, Kokkos::ALL(), Kokkos::ALL(), Kokkos::ALL());
137 auto in = (input.rank() == output.rank()) ?
138 Kokkos::subview(input, cell, Kokkos::ALL(), Kokkos::ALL(), Kokkos::ALL())
139 : Kokkos::subview(input, Kokkos::ALL(), Kokkos::ALL(), Kokkos::ALL());
140
141 // edge transformation
142 ordinal_type existEdgeDofs = 0;
143 if (numEdges > 0) {
144 ordinal_type ortEdges[12];
145 orts(cell).getEdgeOrientation(ortEdges, numEdges);
146
147 // apply coeff matrix
148 for (ordinal_type edgeId=0;edgeId<numEdges;++edgeId) {
149 const ordinal_type ordEdge = (1 < tagToOrdinal.extent(0) ? (static_cast<size_type>(edgeId) < tagToOrdinal.extent(1) ? tagToOrdinal(1, edgeId, 0) : -1) : -1);
150
151 if (ordEdge != -1) {
152 existEdgeDofs = 1;
153 const ordinal_type ndofEdge = ordinalToTag(ordEdge, 3);
154 const auto mat = Kokkos::subview(matData,
155 edgeId, ortEdges[edgeId],
156 Kokkos::ALL(), Kokkos::ALL());
157
158 for (ordinal_type j=0;j<numPoints;++j)
159 for (ordinal_type i=0;i<ndofEdge;++i) {
160 const ordinal_type ii = tagToOrdinal(1, edgeId, i);
161
162 for (ordinal_type k=0;k<dimBasis;++k) {
163 input_value_type temp = 0.0;
164 for (ordinal_type l=0;l<ndofEdge;++l) {
165 const ordinal_type ll = tagToOrdinal(1, edgeId, l);
166 auto & input_ = leftMultiply ? in(ll, j, k) : in(j, ll, k);
167 auto & mat_il = transpose ? mat(l,i) : mat(i,l);
168 temp += mat_il*input_;
169 }
170 auto & output_ = leftMultiply ? out(ii, j, k) : out(j, ii, k);
171 output_ = temp;
172 }
173 }
174 }
175 }
176 }
177
178 // face transformation
179 if (numFaces > 0) {
180 ordinal_type ortFaces[12];
181 orts(cell).getFaceOrientation(ortFaces, numFaces);
182
183 // apply coeff matrix
184 for (ordinal_type faceId=0;faceId<numFaces;++faceId) {
185 const ordinal_type ordFace = (2 < tagToOrdinal.extent(0) ? (static_cast<size_type>(faceId) < tagToOrdinal.extent(1) ? tagToOrdinal(2, faceId, 0) : -1) : -1);
186
187 if (ordFace != -1) {
188 const ordinal_type ndofFace = ordinalToTag(ordFace, 3);
189 const auto mat = Kokkos::subview(matData,
190 numEdges*existEdgeDofs+faceId, ortFaces[faceId],
191 Kokkos::ALL(), Kokkos::ALL());
192
193 for (ordinal_type j=0;j<numPoints;++j)
194 for (ordinal_type i=0;i<ndofFace;++i) {
195 const ordinal_type ii = tagToOrdinal(2, faceId, i);
196
197 for (ordinal_type k=0;k<dimBasis;++k) {
198 input_value_type temp = 0.0;
199 for (ordinal_type l=0;l<ndofFace;++l) {
200 const ordinal_type ll = tagToOrdinal(2, faceId, l);
201 auto & input_ = leftMultiply ? in(ll, j, k) : in(j, ll, k);
202 auto & mat_il = transpose ? mat(l,i) : mat(i,l);
203 temp += mat_il*input_;
204 }
205
206 auto & output_ = leftMultiply ? out(ii, j, k) : out(j, ii, k);
207 output_ = temp;
208 }
209 }
210 }
211 }
212 }
213
214 //side orientations
215 ordinal_type faceOrt(0), edgeOrt(0);
216 if(cellDim == 2) orts(cell).getFaceOrientation(&faceOrt, 1);
217 if (faceOrt != 0) {
218 const ordinal_type ordFace = (2 < tagToOrdinal.extent(0) ? (static_cast<size_type>(0) < tagToOrdinal.extent(1) ? tagToOrdinal(2, 0, 0) : -1) : -1);
219
220 if (ordFace != -1) {
221 const ordinal_type ndofFace = ordinalToTag(ordFace, 3);
222 const auto mat = Kokkos::subview(matData,
223 numEdges*existEdgeDofs, faceOrt,
224 Kokkos::ALL(), Kokkos::ALL());
225
226 for (ordinal_type j=0;j<numPoints;++j)
227 for (ordinal_type i=0;i<ndofFace;++i) {
228 const ordinal_type ii = tagToOrdinal(2, 0, i);
229
230 for (ordinal_type k=0;k<dimBasis;++k) {
231 input_value_type temp = 0.0;
232 for (ordinal_type l=0;l<ndofFace;++l) {
233 const ordinal_type ll = tagToOrdinal(2, 0, l);
234 auto & input_ = leftMultiply ? in(ll, j, k) : in(j, ll, k);
235 auto & mat_il = transpose ? mat(l,i) : mat(i,l);
236 temp += mat_il*input_;
237 }
238 auto & output_ = leftMultiply ? out(ii, j, k) : out(j, ii, k);
239 output_ = temp;
240 }
241 }
242 }
243 }
244
245 if(cellDim == 1) orts(cell).getEdgeOrientation(&edgeOrt, 1);
246 if (edgeOrt != 0) {
247 const ordinal_type ordEdge = (1 < tagToOrdinal.extent(0) ? (static_cast<size_type>(0) < tagToOrdinal.extent(1) ? tagToOrdinal(1, 0, 0) : -1) : -1);
248
249 if (ordEdge != -1) {
250 const ordinal_type ndofEdge = ordinalToTag(ordEdge, 3);
251 const auto mat = Kokkos::subview(matData,
252 0, edgeOrt,
253 Kokkos::ALL(), Kokkos::ALL());
254
255 for (ordinal_type j=0;j<numPoints;++j)
256 for (ordinal_type i=0;i<ndofEdge;++i) {
257 const ordinal_type ii = tagToOrdinal(1, 0, i);
258
259 for (ordinal_type k=0;k<dimBasis;++k) {
260 input_value_type temp = 0.0;
261 for (ordinal_type l=0;l<ndofEdge;++l) {
262 const ordinal_type ll = tagToOrdinal(1, 0, l);
263 auto & input_ = leftMultiply ? in(ll, j, k) : in(j, ll, k);
264 auto & mat_il = transpose ? mat(l,i) : mat(i,l);
265 temp += mat_il*input_;
266 }
267 auto & output_ = leftMultiply ? out(ii, j, k) : out(j, ii, k);
268 output_ = temp;
269 }
270 }
271 }
272 }
273 }
274 };
275
276 template<typename DT>
277 template<typename outputValueType, class ...outputProperties,
278 typename inputValueType, class ...inputProperties,
279 typename OrientationViewType,
280 typename BasisType>
281 void
283 modifyBasisByOrientation( Kokkos::DynRankView<outputValueType,outputProperties...> output,
284 const Kokkos::DynRankView<inputValueType, inputProperties...> input,
285 const OrientationViewType orts,
286 const BasisType* basis ) {
287#ifdef HAVE_INTREPID2_DEBUG
288 {
289 if (input.rank() == output.rank())
290 {
291 for (size_type i=0;i<input.rank();++i)
292 INTREPID2_TEST_FOR_EXCEPTION( input.extent(i) != output.extent(i), std::invalid_argument,
293 ">>> ERROR (OrientationTools::modifyBasisByOrientation): Input and output dimensions do not match.");
294 }
295 else if (input.rank() == output.rank() - 1)
296 {
297 for (size_type i=0;i<input.rank();++i)
298 INTREPID2_TEST_FOR_EXCEPTION( input.extent(i) != output.extent(i+1), std::invalid_argument,
299 ">>> ERROR (OrientationTools::modifyBasisByOrientation): Input dimensions must match output dimensions exactly, or else match all but the first dimension (in the case that input does not have a 'cell' dimension).");
300 }
301 else
302 {
303 INTREPID2_TEST_FOR_EXCEPTION(true, std::invalid_argument,
304 ">>> ERROR (OrientationTools::modifyBasisByOrientation): input and output ranks must either match, or input rank must be one less than that of output.")
305 }
306
307 INTREPID2_TEST_FOR_EXCEPTION( static_cast<ordinal_type>(output.extent(1)) != basis->getCardinality(), std::invalid_argument,
308 ">>> ERROR (OrientationTools::modifyBasisByOrientation): Field dimension of input/output does not match to basis cardinality.");
309 }
310#endif
311
312 const shards::CellTopology cellTopo = basis->getBaseCellTopology();
313 const ordinal_type cellDim = cellTopo.getDimension();
314
315 //Initialize output with values from input
316 if(input.rank() == output.rank())
317 Kokkos::deep_copy(output, input);
318 else
319 RealSpaceTools<DT>::clone(output, input);
320
321 if ((cellDim < 3) || basis->requireOrientation()) {
322 auto ordinalToTag = Kokkos::create_mirror_view_and_copy(typename DT::memory_space(), basis->getAllDofTags());
323 auto tagToOrdinal = Kokkos::create_mirror_view_and_copy(typename DT::memory_space(), basis->getAllDofOrdinal());
324
325 const ordinal_type
326 numCells = output.extent(0),
327 //numBasis = output.extent(1),
328 numPoints = output.extent(2),
329 dimBasis = output.extent(3); //returns 1 when output.rank() < 4;
330
331 const CoeffMatrixDataViewType matData = createCoeffMatrix(basis);
332
333 ordinal_type numVerts(0), numEdges(0), numFaces(0);
334
335 if (basis->requireOrientation()) {
336 numVerts = cellTopo.getVertexCount()*ordinal_type(basis->getDofCount(0, 0) > 0);
337 numEdges = cellTopo.getEdgeCount()*ordinal_type(basis->getDofCount(1, 0) > 0);
338 numFaces = cellTopo.getFaceCount()*ordinal_type(basis->getDofCount(2, 0) > 0);
339 }
340
341 const Kokkos::RangePolicy<typename DT::execution_space> policy(0, numCells);
343 <decltype(orts),
344 decltype(output),decltype(input),
345 decltype(ordinalToTag),decltype(tagToOrdinal),
346 decltype(matData)> FunctorType;
347 Kokkos::parallel_for
348 (policy,
349 FunctorType(orts,
350 output, input,
351 ordinalToTag, tagToOrdinal,
352 matData,
353 cellDim, numVerts, numEdges, numFaces,
354 numPoints, dimBasis));
355 }
356 }
357
358 template<typename DT>
359 template<typename outputValueType, class ...outputProperties,
360 typename inputValueType, class ...inputProperties,
361 typename OrientationViewType,
362 typename BasisType>
363 void
365 modifyBasisByOrientationTranspose( Kokkos::DynRankView<outputValueType,outputProperties...> output,
366 const Kokkos::DynRankView<inputValueType, inputProperties...> input,
367 const OrientationViewType orts,
368 const BasisType* basis ) {
369 #ifdef HAVE_INTREPID2_DEBUG
370 {
371 if (input.rank() == output.rank())
372 {
373 for (size_type i=0;i<input.rank();++i)
374 INTREPID2_TEST_FOR_EXCEPTION( input.extent(i) != output.extent(i), std::invalid_argument,
375 ">>> ERROR (OrientationTools::modifyBasisByOrientation): Input and output dimensions do not match.");
376 }
377 else if (input.rank() == output.rank() - 1)
378 {
379 for (size_type i=0;i<input.rank();++i)
380 INTREPID2_TEST_FOR_EXCEPTION( input.extent(i) != output.extent(i+1), std::invalid_argument,
381 ">>> ERROR (OrientationTools::modifyBasisByOrientation): Input dimensions must match output dimensions exactly, or else match all but the first dimension (in the case that input does not have a 'cell' dimension).");
382 }
383 else
384 {
385 INTREPID2_TEST_FOR_EXCEPTION(true, std::invalid_argument,
386 ">>> ERROR (OrientationTools::modifyBasisByOrientation): input and output ranks must either match, or input rank must be one less than that of output.")
387 }
388
389 INTREPID2_TEST_FOR_EXCEPTION( static_cast<ordinal_type>(output.extent(1)) != basis->getCardinality(), std::invalid_argument,
390 ">>> ERROR (OrientationTools::modifyBasisByOrientation): Field dimension of input/output does not match to basis cardinality.");
391 }
392 #endif
393
394 const shards::CellTopology cellTopo = basis->getBaseCellTopology();
395 const ordinal_type cellDim = cellTopo.getDimension();
396
397 //Initialize output with values from input
398 if(input.rank() == output.rank())
399 Kokkos::deep_copy(output, input);
400 else
401 RealSpaceTools<DT>::clone(output, input);
402
403 if ((cellDim < 3) || basis->requireOrientation()) {
404 auto ordinalToTag = Kokkos::create_mirror_view_and_copy(typename DT::memory_space(), basis->getAllDofTags());
405 auto tagToOrdinal = Kokkos::create_mirror_view_and_copy(typename DT::memory_space(), basis->getAllDofOrdinal());
406
407 const ordinal_type
408 numCells = output.extent(0),
409 //numBasis = output.extent(1),
410 numPoints = output.extent(2),
411 dimBasis = output.extent(3); //returns 1 when output.rank() < 4;
412
413 const CoeffMatrixDataViewType matData = createCoeffMatrix(basis);
414
415 ordinal_type numVerts(0), numEdges(0), numFaces(0);
416
417 if (basis->requireOrientation()) {
418 numVerts = cellTopo.getVertexCount()*ordinal_type(basis->getDofCount(0, 0) > 0);
419 numEdges = cellTopo.getEdgeCount()*ordinal_type(basis->getDofCount(1, 0) > 0);
420 numFaces = cellTopo.getFaceCount()*ordinal_type(basis->getDofCount(2, 0) > 0);
421 }
422
423 bool leftMultiply = true;
424 bool transpose = true;
425
426 const Kokkos::RangePolicy<typename DT::execution_space> policy(0, numCells);
428 <decltype(orts),
429 decltype(output),decltype(input),
430 decltype(ordinalToTag),decltype(tagToOrdinal),
431 decltype(matData)> FunctorType;
432 Kokkos::parallel_for
433 (policy,
434 FunctorType(orts,
435 output, input,
436 ordinalToTag, tagToOrdinal,
437 matData,
438 cellDim, numVerts, numEdges, numFaces,
439 numPoints, dimBasis, leftMultiply, transpose));
440 }
441 }
442
443 template<typename DT>
444 template<typename outputValueType, class ...outputProperties,
445 typename inputValueType, class ...inputProperties,
446 typename OrientationViewType,
447 typename BasisTypeLeft,
448 typename BasisTypeRight>
449 void
451 modifyMatrixByOrientation(Kokkos::DynRankView<outputValueType,outputProperties...> output,
452 const Kokkos::DynRankView<inputValueType, inputProperties...> input,
453 const OrientationViewType orts,
454 const BasisTypeLeft* basisLeft,
455 const BasisTypeRight* basisRight)
456 {
457 const ordinal_type numCells = output.extent(0);
458 const ordinal_type numFieldsLeft = basisLeft->getCardinality();
459 const ordinal_type numFieldsRight = basisRight->getCardinality();
460#ifdef HAVE_INTREPID2_DEBUG
461 {
462 if (input.rank() == output.rank())
463 {
464 for (size_type i=0;i<input.rank();++i)
465 INTREPID2_TEST_FOR_EXCEPTION( input.extent(i) != output.extent(i), std::invalid_argument,
466 ">>> ERROR (OrientationTools::modifyMatrixByOrientation): Input and output dimensions do not match.");
467 }
468 else if (input.rank() == output.rank() - 1)
469 {
470 for (size_type i=0;i<input.rank();++i)
471 INTREPID2_TEST_FOR_EXCEPTION( input.extent(i) != output.extent(i+1), std::invalid_argument,
472 ">>> ERROR (OrientationTools::modifyMatrixByOrientation): Input dimensions must match output dimensions exactly, or else match all but the first dimension (in the case that input does not have a 'cell' dimension).");
473 }
474 else
475 {
476 INTREPID2_TEST_FOR_EXCEPTION(true, std::invalid_argument,
477 ">>> ERROR (OrientationTools::modifyMatrixByOrientation): input and output ranks must either match, or input rank must be one less than that of output.")
478 }
479
480 INTREPID2_TEST_FOR_EXCEPTION( static_cast<ordinal_type>(output.extent(1)) != numFieldsLeft, std::invalid_argument,
481 ">>> ERROR (OrientationTools::modifyMatrixByOrientation): First field dimension of input/output does not match left basis cardinality.");
482 INTREPID2_TEST_FOR_EXCEPTION( static_cast<ordinal_type>(output.extent(2)) != numFieldsRight, std::invalid_argument,
483 ">>> ERROR (OrientationTools::modifyMatrixByOrientation): Second field dimension of input/output does not match right basis cardinality.");
484 INTREPID2_TEST_FOR_EXCEPTION( static_cast<ordinal_type>(output.extent(3)) != 1, std::invalid_argument,
485 ">>> ERROR (OrientationTools::modifyMatrixByOrientation): Third dimension of output must be 1.");
486
487 }
488#endif
489 const shards::CellTopology cellTopo = basisLeft->getBaseCellTopology();
490 const ordinal_type cellDim = cellTopo.getDimension();
491
492 // apply orientations on left
493 decltype(output) outputLeft("temp view - output from left application", numCells, numFieldsLeft, numFieldsRight);
494
495 //Initialize outputLeft with values from input
496 if(input.rank() == output.rank())
497 Kokkos::deep_copy(outputLeft, input);
498 else
499 RealSpaceTools<DT>::clone(outputLeft, input);
500
501 if ((cellDim < 3) || basisLeft->requireOrientation()) {
502 bool leftMultiply = true;
503 auto ordinalToTag = Kokkos::create_mirror_view_and_copy(typename DT::memory_space(), basisLeft->getAllDofTags());
504 auto tagToOrdinal = Kokkos::create_mirror_view_and_copy(typename DT::memory_space(), basisLeft->getAllDofOrdinal());
505
506 const ordinal_type
507 numOtherFields = output.extent(2),
508 dimBasis = output.extent(3); //returns 1 when output.rank() < 4;
509
510 const CoeffMatrixDataViewType matData = createCoeffMatrix(basisLeft);
511
512 ordinal_type numVerts(0), numEdges(0), numFaces(0);
513
514 if (basisLeft->requireOrientation()) {
515 numVerts = cellTopo.getVertexCount()*ordinal_type(basisLeft->getDofCount(0, 0) > 0);
516 numEdges = cellTopo.getEdgeCount()*ordinal_type(basisLeft->getDofCount(1, 0) > 0);
517 numFaces = cellTopo.getFaceCount()*ordinal_type(basisLeft->getDofCount(2, 0) > 0);
518 }
519
520 const Kokkos::RangePolicy<typename DT::execution_space> policy(0, numCells);
522 <decltype(orts),
523 decltype(outputLeft),decltype(input),
524 decltype(ordinalToTag),decltype(tagToOrdinal),
525 decltype(matData)> FunctorType;
526 Kokkos::parallel_for
527 (policy,
528 FunctorType(orts,
529 outputLeft, input,
530 ordinalToTag, tagToOrdinal,
531 matData,
532 cellDim, numVerts, numEdges, numFaces,
533 numOtherFields, dimBasis, leftMultiply));
534 }
535
536 // apply orientations on right
537 //Initialize output with values from outputLeft
538 Kokkos::deep_copy(output, outputLeft);
539 if ((cellDim < 3) || basisRight->requireOrientation()) {
540 bool leftMultiply = false;
541 auto ordinalToTag = Kokkos::create_mirror_view_and_copy(typename DT::memory_space(), basisRight->getAllDofTags());
542 auto tagToOrdinal = Kokkos::create_mirror_view_and_copy(typename DT::memory_space(), basisRight->getAllDofOrdinal());
543
544 const ordinal_type
545 numOtherFields = output.extent(1),
546 dimBasis = output.extent(3); //returns 1 when output.rank() < 4;
547
548 const CoeffMatrixDataViewType matData = createCoeffMatrix(basisRight);
549
550 ordinal_type numVerts(0), numEdges(0), numFaces(0);
551
552 if (basisRight->requireOrientation()) {
553 numVerts = cellTopo.getVertexCount()*ordinal_type(basisRight->getDofCount(0, 0) > 0);
554 numEdges = cellTopo.getEdgeCount()*ordinal_type(basisRight->getDofCount(1, 0) > 0);
555 numFaces = cellTopo.getFaceCount()*ordinal_type(basisRight->getDofCount(2, 0) > 0);
556 }
557
558 const Kokkos::RangePolicy<typename DT::execution_space> policy(0, numCells);
560 <decltype(orts),
561 decltype(output),decltype(outputLeft),
562 decltype(ordinalToTag),decltype(tagToOrdinal),
563 decltype(matData)> FunctorType;
564 Kokkos::parallel_for
565 (policy,
566 FunctorType(orts,
567 output, outputLeft,
568 ordinalToTag, tagToOrdinal,
569 matData,
570 cellDim, numVerts, numEdges, numFaces,
571 numOtherFields, dimBasis, leftMultiply));
572 }
573 }
574
575} // namespace Intrepid2
576
577#endif
Header file for the Intrepid2::Orientation class.
static CoeffMatrixDataViewType createCoeffMatrix(const BasisType *basis)
Create coefficient matrix.
Kokkos::View< double ****, DeviceType > CoeffMatrixDataViewType
subcell ordinal, orientation, matrix m x n
static void modifyBasisByOrientation(Kokkos::DynRankView< outputValueType, outputProperties... > output, const Kokkos::DynRankView< inputValueType, inputProperties... > input, const OrientationViewType orts, const BasisType *basis)
Modify basis due to orientation.
static void modifyMatrixByOrientation(Kokkos::DynRankView< outputValueType, outputProperties... > output, const Kokkos::DynRankView< inputValueType, inputProperties... > input, const OrientationViewType orts, const BasisTypeLeft *basisLeft, const BasisTypeRight *basisRight)
Modify an assembled (C,F1,F2) matrix according to orientation of the cells.
static void getOrientation(Kokkos::DynRankView< elemOrtValueType, elemOrtProperties... > elemOrts, const Kokkos::DynRankView< elemNodeValueType, elemNodeProperties... > elemNodes, const shards::CellTopology cellTopo, bool isSide=false)
Compute orientations of cells in a workset.
static void modifyBasisByOrientationTranspose(Kokkos::DynRankView< outputValueType, outputProperties... > output, const Kokkos::DynRankView< inputValueType, inputProperties... > input, const OrientationViewType orts, const BasisType *basis)
Modify basis due to orientation, applying the transpose of the operator applied in modifyBasisByOrien...
static void clone(Kokkos::DynRankView< outputValueType, outputProperties... > output, const Kokkos::DynRankView< inputValueType, inputProperties... > input)
Clone input array.