Intrepid2
Intrepid2_OrientationToolsDefModifyBasis.hpp
Go to the documentation of this file.
1// @HEADER
2// *****************************************************************************
3// Intrepid2 Package
4//
5// Copyright 2007 NTESS and the Intrepid2 contributors.
6// SPDX-License-Identifier: BSD-3-Clause
7// *****************************************************************************
8// @HEADER
9
10
15#ifndef __INTREPID2_ORIENTATIONTOOLS_DEF_MODIFY_BASIS_HPP__
16#define __INTREPID2_ORIENTATIONTOOLS_DEF_MODIFY_BASIS_HPP__
17
18// disable clang warnings
19#if defined (__clang__) && !defined (__INTEL_COMPILER)
20#pragma clang system_header
21#endif
22
24
25namespace Intrepid2 {
26
27 template<typename DT>
28 template<typename elemOrtValueType, class ...elemOrtProperties,
29 typename elemNodeValueType, class ...elemNodeProperties>
30 void
32 getOrientation( Kokkos::DynRankView<elemOrtValueType,elemOrtProperties...> elemOrts,
33 const Kokkos::DynRankView<elemNodeValueType,elemNodeProperties...> elemNodes,
34 const shards::CellTopology cellTopo,
35 bool isSide) {
36 // small meta data modification and it uses shards; let's do this on host
37 auto elemOrtsHost = Kokkos::create_mirror_view(elemOrts);
38 auto elemNodesHost = Kokkos::create_mirror_view_and_copy(Kokkos::HostSpace(), elemNodes);
39
40 const ordinal_type numCells = elemNodes.extent(0);
41 for (auto cell=0;cell<numCells;++cell) {
42 const auto nodes = Kokkos::subview(elemNodesHost, cell, Kokkos::ALL());
43 elemOrtsHost(cell) = Orientation::getOrientation(cellTopo, nodes, isSide);
44 }
45
46 Kokkos::deep_copy(elemOrts, elemOrtsHost);
47 }
48
49 template<typename OrtViewType,
50 typename OutputViewType,
51 typename InputViewType,
52 typename OperatorViewType>
54 OrtViewType orts;
55 OutputViewType output;
56 InputViewType input;
57
58 const OperatorViewType edgeOperatorData, faceOperatorData;
59 const ordinal_type numEdges, numFaces, numPoints, dimBasis;
60 const bool leftMultiply;
61 const ordinal_type transpose;
62 // for simple left-multiplied basis value modification, numPoints is the dimension after the field dimension
63 // for matrix value modification (C,F1,F2), numPoints is F2 when left multiplied, and F1 when right multiplied
64
65 F_modifyBasisByOrientationOperator(OrtViewType orts_,
66 OutputViewType output_,
67 InputViewType input_,
68 const OperatorViewType edgeOperatorData_,
69 const OperatorViewType faceOperatorData_,
70 const ordinal_type numEdges_,
71 const ordinal_type numFaces_,
72 const ordinal_type numPoints_,
73 const ordinal_type dimBasis_,
74 const bool leftMultiply_ = true,
75 const bool transpose_ = false)
76 : orts(orts_),
77 output(output_),
78 input(input_),
79 edgeOperatorData(edgeOperatorData_),
80 faceOperatorData(faceOperatorData_),
81 numEdges(numEdges_),
82 numFaces(numFaces_),
83 numPoints(numPoints_),
84 dimBasis(dimBasis_),
85 leftMultiply(leftMultiply_),
86 transpose(static_cast<ordinal_type>(transpose_))
87 {}
88
89 KOKKOS_INLINE_FUNCTION
90 void operator()(const ordinal_type cell) const {
91 using input_value_type = typename InputViewType::non_const_value_type;
92
93 auto out = Kokkos::subview(output, cell, Kokkos::ALL(), Kokkos::ALL(), Kokkos::ALL());
94 auto in = (input.rank() == output.rank()) ?
95 Kokkos::subview(input, cell, Kokkos::ALL(), Kokkos::ALL(), Kokkos::ALL())
96 : Kokkos::subview(input, Kokkos::ALL(), Kokkos::ALL(), Kokkos::ALL());
97
98 // edge transformation
99 if (numEdges > 0)
100 {
101 ordinal_type ortEdges[12];
102 orts(cell).getEdgeOrientation(ortEdges, numEdges);
103
104 if ((numEdges != 1) || (ortEdges[0] != 0)) // numEdges == 1 is "side" orientation case; can skip if ort is 0.
105 {
106 // apply operators on each edge
107 for (ordinal_type edgeId=0;edgeId<numEdges;++edgeId)
108 {
109 // bool havePrinted = false;
110 const auto edgeOp = edgeOperatorData(edgeId, ortEdges[edgeId], transpose);
111 const auto rowIndices = edgeOp.rowIndices;
112 const auto colIndices = edgeOp.packedColumnIndices;
113 const auto weights = edgeOp.packedWeights;
114
115 const ordinal_type numRowIndices = rowIndices.extent_int(0);
116 if (edgeOp.isWeightedPermutation)
117 {
118 for (ordinal_type pointOrdinal=0;pointOrdinal<numPoints;pointOrdinal++)
119 {
120 for (ordinal_type rowOrdinal=0; rowOrdinal<numRowIndices; rowOrdinal++)
121 {
122 const ordinal_type & i = rowIndices(rowOrdinal);
123 const ordinal_type & j = colIndices(rowOrdinal);
124 const auto & mat_ij = weights(rowOrdinal);
125
126 for (int d=0; d<dimBasis; d++)
127 {
128 auto & input_ = leftMultiply ? in.access(j, pointOrdinal, d) : in.access(pointOrdinal, j, d);
129 auto & output_ = leftMultiply ? out.access(i, pointOrdinal, d) : out.access(pointOrdinal, i, d);
130 output_ = mat_ij * input_;
131 }
132 }
133 }
134 }
135 else
136 {
137 const auto rowOffsets = edgeOp.offsetsForRowOrdinal;
138 for (ordinal_type pointOrdinal=0;pointOrdinal<numPoints;pointOrdinal++)
139 {
140 for (ordinal_type rowOrdinal=0; rowOrdinal<numRowIndices; rowOrdinal++)
141 {
142 const ordinal_type & i = rowIndices[rowOrdinal];
143 const ordinal_type & thisRowOffset = rowOffsets(rowOrdinal);
144 const ordinal_type & nextRowOffset = rowOffsets(rowOrdinal+1);
145
146 for (int d=0; d<dimBasis; d++)
147 {
148 input_value_type temp = 0.0;
149 for (ordinal_type rowOffset=thisRowOffset; rowOffset<nextRowOffset; rowOffset++)
150 {
151 const ordinal_type & j = colIndices(rowOffset);
152 const auto & mat_ij = weights(rowOffset);
153
154 auto & input_ = leftMultiply ? in.access(j, pointOrdinal, d) : in.access(pointOrdinal, j, d);
155 temp += mat_ij * input_;
156 }
157 auto & output_ = leftMultiply ? out.access(i, pointOrdinal, d) : out.access(pointOrdinal, i, d);
158 output_ = temp;
159 }
160 }
161 }
162 }
163 }
164 }
165 }
166
167 // face transformation
168 if (numFaces > 0)
169 {
170 ordinal_type ortFaces[12];
171 orts(cell).getFaceOrientation(ortFaces, numFaces);
172
173 if ((numFaces != 1) || (ortFaces[0] != 0)) // numFaces == 1 is "side" orientation case; can skip if ort is 0.
174 {
175 // apply operators on each face
176 for (ordinal_type faceId=0;faceId<numFaces;++faceId)
177 {
178 const auto faceOp = faceOperatorData(faceId, ortFaces[faceId], transpose);
179 const auto rowIndices = faceOp.rowIndices;
180 const auto colIndices = faceOp.packedColumnIndices;
181 const auto weights = faceOp.packedWeights;
182
183 ordinal_type numRowIndices = rowIndices.extent_int(0);
184 if (faceOp.isWeightedPermutation)
185 {
186 for (ordinal_type pointOrdinal=0;pointOrdinal<numPoints;pointOrdinal++)
187 {
188 for (ordinal_type rowOrdinal=0; rowOrdinal<numRowIndices; rowOrdinal++)
189 {
190 const ordinal_type & i = rowIndices[rowOrdinal];
191 const ordinal_type & j = colIndices(rowOrdinal);
192 const auto & mat_ij = weights(rowOrdinal);
193
194 for (int d=0; d<dimBasis; d++)
195 {
196 auto & input_ = leftMultiply ? in.access(j, pointOrdinal, d) : in.access(pointOrdinal, j, d);
197 auto & output_ = leftMultiply ? out.access(i, pointOrdinal, d) : out.access(pointOrdinal, i, d);
198 output_ = mat_ij * input_;
199 }
200 }
201 }
202 }
203 else
204 {
205 const auto rowOffsets = faceOp.offsetsForRowOrdinal;
206 for (ordinal_type pointOrdinal=0;pointOrdinal<numPoints;pointOrdinal++)
207 {
208 for (ordinal_type rowOrdinal=0; rowOrdinal<numRowIndices; rowOrdinal++)
209 {
210 const ordinal_type & i = rowIndices[rowOrdinal];
211 const ordinal_type & thisRowOffset = rowOffsets(rowOrdinal);
212 const ordinal_type & nextRowOffset = rowOffsets(rowOrdinal+1);
213
214 for (int d=0; d<dimBasis; d++)
215 {
216 input_value_type temp = 0.0;
217 for (ordinal_type rowOffset=thisRowOffset; rowOffset<nextRowOffset; rowOffset++)
218 {
219 const ordinal_type & j = colIndices(rowOffset);
220 const auto & mat_ij = weights(rowOffset);
221
222 auto & input_ = leftMultiply ? in.access(j, pointOrdinal, d) : in.access(pointOrdinal, j, d);
223 temp += mat_ij * input_;
224 }
225 auto & output_ = leftMultiply ? out.access(i, pointOrdinal, d) : out.access(pointOrdinal, i, d);
226 output_ = temp;
227 }
228 }
229 }
230 }
231 }
232 }
233 }
234 }
235 };
236
237 template<typename DT>
238 template<typename outputValueType, class ...outputProperties,
239 typename inputValueType, class ...inputProperties,
240 typename OrientationViewType,
241 typename BasisType>
242 void
244 modifyBasisByOrientation( Kokkos::DynRankView<outputValueType,outputProperties...> output,
245 const Kokkos::DynRankView<inputValueType, inputProperties...> input,
246 const OrientationViewType orts,
247 const BasisType* basis,
248 const bool transpose) {
249#ifdef HAVE_INTREPID2_DEBUG
250 {
251 if (input.rank() == output.rank())
252 {
253 for (size_type i=0;i<input.rank();++i)
254 INTREPID2_TEST_FOR_EXCEPTION( input.extent(i) != output.extent(i), std::invalid_argument,
255 ">>> ERROR (OrientationTools::modifyBasisByOrientation): Input and output dimensions do not match.");
256 }
257 else if (input.rank() == output.rank() - 1)
258 {
259 for (size_type i=0;i<input.rank();++i)
260 INTREPID2_TEST_FOR_EXCEPTION( input.extent(i) != output.extent(i+1), std::invalid_argument,
261 ">>> 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).");
262 }
263 else
264 {
265 INTREPID2_TEST_FOR_EXCEPTION(true, std::invalid_argument,
266 ">>> ERROR (OrientationTools::modifyBasisByOrientation): input and output ranks must either match, or input rank must be one less than that of output.")
267 }
268
269 INTREPID2_TEST_FOR_EXCEPTION( static_cast<ordinal_type>(output.extent(1)) != basis->getCardinality(), std::invalid_argument,
270 ">>> ERROR (OrientationTools::modifyBasisByOrientation): Field dimension of input/output does not match to basis cardinality.");
271 }
272#endif
273 const ordinal_type EDGE_DIM = 1;
274 const ordinal_type FACE_DIM = 2;
275
276 const shards::CellTopology cellTopo = basis->getBaseCellTopology();
277 const ordinal_type cellDim = cellTopo.getDimension();
278
279 //Initialize output with values from input
280 if(input.rank() == output.rank())
281 Kokkos::deep_copy(output, input);
282 else
283 RealSpaceTools<DT>::clone(output, input);
284
285 if ((cellDim < 3) || basis->requireOrientation()) {
286 const ordinal_type
287 numCells = output.extent(0),
288 //numBasis = output.extent(1),
289 numPoints = output.extent(2),
290 dimBasis = output.extent(3); //returns 1 when output.rank() < 4;
291
292 const auto op_tuple = createOperators(basis);
293
294 const auto edgeOpData = std::get<0>(op_tuple);
295 const auto faceOpData = std::get<1>(op_tuple);
296
297 ordinal_type numEdges(0), numFaces(0);
298 if (basis->requireOrientation()) {
299 numEdges = cellTopo.getEdgeCount()*ordinal_type(basis->getDofCount(EDGE_DIM, 0) > 0);
300 numFaces = cellTopo.getFaceCount()*ordinal_type(basis->getDofCount(FACE_DIM, 0) > 0);
301 }
302 // "side" orientations
303 if (cellDim == 1) numEdges = 1;
304 else if (cellDim == 2) numFaces = 1;
305
306 bool leftMultiply = true;
307
308 const Kokkos::RangePolicy<typename DT::execution_space> policy(0, numCells);
309 using FunctorType = F_modifyBasisByOrientationOperator
310 <decltype(orts),
311 decltype(output),decltype(input),
312 decltype(edgeOpData)>;
313 Kokkos::parallel_for
314 (policy,
315 FunctorType(orts,
316 output, input,
317 edgeOpData, faceOpData, numEdges, numFaces,
318 numPoints, dimBasis, leftMultiply, transpose));
319 }
320 }
321
322 template<typename DT>
323 template<typename outputValueType, class ...outputProperties,
324 typename inputValueType, class ...inputProperties,
325 typename OrientationViewType,
326 typename BasisType>
327 void
329 modifyBasisByOrientationTranspose( Kokkos::DynRankView<outputValueType,outputProperties...> output,
330 const Kokkos::DynRankView<inputValueType, inputProperties...> input,
331 const OrientationViewType orts,
332 const BasisType* basis ) {
333 bool transpose = true;
334 modifyBasisByOrientation(output, input, orts, basis, transpose);
335 }
336
337 template<typename DT>
338 template<typename outputValueType, class ...outputProperties,
339 typename inputValueType, class ...inputProperties,
340 typename OrientationViewType,
341 typename BasisType>
342 void
344 modifyBasisByOrientationInverse( Kokkos::DynRankView<outputValueType,outputProperties...> output,
345 const Kokkos::DynRankView<inputValueType, inputProperties...> input,
346 const OrientationViewType orts,
347 const BasisType* basis,
348 const bool transpose ) {
349 #ifdef HAVE_INTREPID2_DEBUG
350 {
351 if (input.rank() == output.rank())
352 {
353 for (size_type i=0;i<input.rank();++i)
354 INTREPID2_TEST_FOR_EXCEPTION( input.extent(i) != output.extent(i), std::invalid_argument,
355 ">>> ERROR (OrientationTools::modifyBasisByOrientation): Input and output dimensions do not match.");
356 }
357 else if (input.rank() == output.rank() - 1)
358 {
359 for (size_type i=0;i<input.rank();++i)
360 INTREPID2_TEST_FOR_EXCEPTION( input.extent(i) != output.extent(i+1), std::invalid_argument,
361 ">>> 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).");
362 }
363 else
364 {
365 INTREPID2_TEST_FOR_EXCEPTION(true, std::invalid_argument,
366 ">>> ERROR (OrientationTools::modifyBasisByOrientation): input and output ranks must either match, or input rank must be one less than that of output.")
367 }
368
369 INTREPID2_TEST_FOR_EXCEPTION( static_cast<ordinal_type>(output.extent(1)) != basis->getCardinality(), std::invalid_argument,
370 ">>> ERROR (OrientationTools::modifyBasisByOrientation): Field dimension of input/output does not match to basis cardinality.");
371 }
372 #endif
373 const ordinal_type EDGE_DIM = 1;
374 const ordinal_type FACE_DIM = 2;
375
376 const shards::CellTopology cellTopo = basis->getBaseCellTopology();
377 const ordinal_type cellDim = cellTopo.getDimension();
378
379 //Initialize output with values from input
380 if(input.rank() == output.rank())
381 Kokkos::deep_copy(output, input);
382 else
383 RealSpaceTools<DT>::clone(output, input);
384
385 if ((cellDim < 3) || basis->requireOrientation()) {
386 const ordinal_type
387 numCells = output.extent(0),
388 //numBasis = output.extent(1),
389 numPoints = output.extent(2),
390 dimBasis = output.extent(3); //returns 1 when output.rank() < 4;
391
392 auto opData = createInvOperators(basis);
393 auto edgeOpData = std::get<0>(opData);
394 auto faceOpData = std::get<1>(opData);
395
396 ordinal_type numEdges(0), numFaces(0);
397
398 if (basis->requireOrientation()) {
399 numEdges = cellTopo.getEdgeCount()*ordinal_type(basis->getDofCount(EDGE_DIM, 0) > 0);
400 numFaces = cellTopo.getFaceCount()*ordinal_type(basis->getDofCount(FACE_DIM, 0) > 0);
401 }
402 // "side" orientations
403 if (cellDim == 1) numEdges = 1;
404 else if (cellDim == 2) numFaces = 1;
405
406 bool leftMultiply = true;
407
408 const Kokkos::RangePolicy<typename DT::execution_space> policy(0, numCells);
410 <decltype(orts),
411 decltype(output),decltype(input),
412 decltype(edgeOpData)> FunctorType;
413 Kokkos::parallel_for
414 (policy,
415 FunctorType(orts,
416 output, input,
417 edgeOpData, faceOpData, numEdges, numFaces,
418 numPoints, dimBasis, leftMultiply, transpose));
419 }
420 }
421
422 template<typename DT>
423 template<typename outputValueType, class ...outputProperties,
424 typename inputValueType, class ...inputProperties,
425 typename OrientationViewType,
426 typename BasisTypeLeft,
427 typename BasisTypeRight>
428 void
430 modifyMatrixByOrientation(Kokkos::DynRankView<outputValueType,outputProperties...> output,
431 const Kokkos::DynRankView<inputValueType, inputProperties...> input,
432 const OrientationViewType orts,
433 const BasisTypeLeft* basisLeft,
434 const BasisTypeRight* basisRight)
435 {
436 const ordinal_type EDGE_DIM = 1;
437 const ordinal_type FACE_DIM = 2;
438
439 const shards::CellTopology cellTopo = basisLeft->getBaseCellTopology();
440 const ordinal_type cellDim = cellTopo.getDimension();
441
442 const ordinal_type numCells = output.extent(0);
443 const ordinal_type numFieldsLeft = basisLeft->getCardinality();
444 const ordinal_type numFieldsRight = basisRight->getCardinality();
445
446 // apply orientations on left
447 decltype(output) outputLeft("temp view - output from left application", numCells, numFieldsLeft, numFieldsRight);
448
449 //Initialize outputLeft with values from input
450 if(input.rank() == output.rank())
451 Kokkos::deep_copy(outputLeft, input);
452 else
453 RealSpaceTools<DT>::clone(outputLeft, input);
454
455#ifdef HAVE_INTREPID2_DEBUG
456 {
457 if (input.rank() == output.rank())
458 {
459 for (size_type i=0;i<input.rank();++i)
460 INTREPID2_TEST_FOR_EXCEPTION( input.extent(i) != output.extent(i), std::invalid_argument,
461 ">>> ERROR (OrientationTools::modifyMatrixByOrientation): Input and output dimensions do not match.");
462 }
463 else if (input.rank() == output.rank() - 1)
464 {
465 for (size_type i=0;i<input.rank();++i)
466 INTREPID2_TEST_FOR_EXCEPTION( input.extent(i) != output.extent(i+1), std::invalid_argument,
467 ">>> 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).");
468 }
469 else
470 {
471 INTREPID2_TEST_FOR_EXCEPTION(true, std::invalid_argument,
472 ">>> ERROR (OrientationTools::modifyMatrixByOrientation): input and output ranks must either match, or input rank must be one less than that of output.")
473 }
474
475 INTREPID2_TEST_FOR_EXCEPTION( static_cast<ordinal_type>(output.extent(1)) != numFieldsLeft, std::invalid_argument,
476 ">>> ERROR (OrientationTools::modifyMatrixByOrientation): First field dimension of input/output does not match left basis cardinality.");
477 INTREPID2_TEST_FOR_EXCEPTION( static_cast<ordinal_type>(output.extent(2)) != numFieldsRight, std::invalid_argument,
478 ">>> ERROR (OrientationTools::modifyMatrixByOrientation): Second field dimension of input/output does not match right basis cardinality.");
479 INTREPID2_TEST_FOR_EXCEPTION( static_cast<ordinal_type>(output.extent(3)) != 1, std::invalid_argument,
480 ">>> ERROR (OrientationTools::modifyMatrixByOrientation): Third dimension of output must be 1.");
481
482 }
483#endif
484
485 if ((cellDim < 3) || basisLeft->requireOrientation()) {
486 const bool leftMultiply = true;
487 const bool transpose = false;
488
489 const ordinal_type
490 numOtherFields = numFieldsRight,
491 dimBasis = output.extent(3); //returns 1 when output.rank() < 4;
492
493 ordinal_type numEdges(0), numFaces(0);
494 if (basisLeft->requireOrientation()) {
495 numEdges = cellTopo.getEdgeCount()*ordinal_type(basisLeft->getDofCount(EDGE_DIM, 0) > 0);
496 numFaces = cellTopo.getFaceCount()*ordinal_type(basisLeft->getDofCount(FACE_DIM, 0) > 0);
497 }
498 // "side" orientations
499 if (cellDim == 1) numEdges = 1;
500 else if (cellDim == 2) numFaces = 1;
501
502 const auto op_tuple = createOperators(basisLeft);
503 auto edgeOpData = std::get<0>(op_tuple);
504 auto faceOpData = std::get<1>(op_tuple);
505
506 const Kokkos::RangePolicy<typename DT::execution_space> policy(0, numCells);
507 using FunctorType = F_modifyBasisByOrientationOperator
508 <decltype(orts),
509 decltype(outputLeft),decltype(input),
510 decltype(edgeOpData)>;
511 Kokkos::parallel_for
512 (policy,
513 FunctorType(orts,
514 outputLeft, input,
515 edgeOpData, faceOpData, numEdges, numFaces,
516 numOtherFields, dimBasis, leftMultiply, transpose));
517 }
518
519 // apply orientations on right
520 //Initialize output with values from outputLeft
521 Kokkos::deep_copy(output, outputLeft);
522 if ((cellDim < 3) || basisRight->requireOrientation()) {
523 const bool leftMultiply = false;
524 const bool transpose = true; // NVR: added this September 2025; I think to date we have only ever run this with symmetric orientation operations, so that it has not mattered to date.
525 const ordinal_type
526 numOtherFields = numFieldsLeft,
527 dimBasis = output.extent(3); //returns 1 when output.rank() < 4;
528
529 ordinal_type numEdges(0), numFaces(0);
530 if (basisRight->requireOrientation()) {
531 numEdges = cellTopo.getEdgeCount()*ordinal_type(basisRight->getDofCount(1, 0) > 0);
532 numFaces = cellTopo.getFaceCount()*ordinal_type(basisRight->getDofCount(2, 0) > 0);
533 }
534 else
535 {
536 // "side" orientations
537 if (cellDim == 1) numEdges = 1;
538 else if (cellDim == 2) numFaces = 1;
539 }
540
541 const auto op_tuple = createOperators(basisRight);
542 auto edgeOpData = std::get<0>(op_tuple);
543 auto faceOpData = std::get<1>(op_tuple);
544
545 const Kokkos::RangePolicy<typename DT::execution_space> policy(0, numCells);
546 using FunctorType = F_modifyBasisByOrientationOperator
547 <decltype(orts),
548 decltype(output),decltype(input),
549 decltype(edgeOpData)>;
550 Kokkos::parallel_for
551 (policy,
552 FunctorType(orts,
553 output, outputLeft,
554 edgeOpData, faceOpData, numEdges, numFaces,
555 numOtherFields, dimBasis, leftMultiply, transpose));
556 }
557 }
558
559} // namespace Intrepid2
560
561#endif
Header file for the Intrepid2::Orientation class.
static void modifyBasisByOrientationInverse(Kokkos::DynRankView< outputValueType, outputProperties... > output, const Kokkos::DynRankView< inputValueType, inputProperties... > input, const OrientationViewType orts, const BasisType *basis, const bool transpose=false)
Modify basis due to orientation, applying the inverse of the operator applied in modifyBasisByOrienta...
static void modifyBasisByOrientation(Kokkos::DynRankView< outputValueType, outputProperties... > output, const Kokkos::DynRankView< inputValueType, inputProperties... > input, const OrientationViewType orts, const BasisType *basis, const bool transpose=false)
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.