48 #ifndef __INTREPID2_ORIENTATIONTOOLS_DEF_MODIFY_BASIS_HPP__
49 #define __INTREPID2_ORIENTATIONTOOLS_DEF_MODIFY_BASIS_HPP__
52 #if defined (__clang__) && !defined (__INTEL_COMPILER)
53 #pragma clang system_header
58 template<
typename SpT>
59 template<
typename ptViewType>
60 KOKKOS_INLINE_FUNCTION
63 #ifdef HAVE_INTREPID2_DEBUG
64 INTREPID2_TEST_FOR_ABORT( pts.rank() != 2,
65 ">>> ERROR (Intrepid::OrientationTools::isLeftHandedCell): " \
66 "Point array is supposed to have rank 2.");
68 typedef typename ptViewType::value_type value_type;
70 const auto dim = pts.extent(1);
75 const value_type v[2][2] = { { pts(1,0) - pts(0,0), pts(1,1) - pts(0,1) },
76 { pts(2,0) - pts(0,0), pts(2,1) - pts(0,1) } };
78 det = (v[0][0]*v[1][1] - v[1][0]*v[0][1]);
83 const value_type v[3][3] = { { pts(1,0) - pts(0,0), pts(1,1) - pts(0,1), pts(1,2) - pts(0,2) },
84 { pts(2,0) - pts(0,0), pts(2,1) - pts(0,1), pts(2,2) - pts(0,2) },
85 { pts(3,0) - pts(0,0), pts(3,1) - pts(0,1), pts(3,2) - pts(0,2) } };
87 det = (v[0][0] * v[1][1] * v[2][2] +
88 v[0][1] * v[1][2] * v[2][0] +
89 v[0][2] * v[1][0] * v[2][1] -
90 v[0][2] * v[1][1] * v[2][0] -
91 v[0][0] * v[1][2] * v[2][1] -
92 v[0][1] * v[1][0] * v[2][2]);
96 INTREPID2_TEST_FOR_ABORT(
true,
97 ">>> ERROR (Intrepid::Orientation::isLeftHandedCell): " \
98 "Dimension of points must be 2 or 3");
104 template<
typename SpT>
105 template<
typename elemOrtValueType,
class ...elemOrtProperties,
106 typename elemNodeValueType,
class ...elemNodeProperties>
109 getOrientation( Kokkos::DynRankView<elemOrtValueType,elemOrtProperties...> elemOrts,
110 const Kokkos::DynRankView<elemNodeValueType,elemNodeProperties...> elemNodes,
111 const shards::CellTopology cellTopo) {
113 typedef typename Kokkos::Impl::is_space<SpT>::host_mirror_space::execution_space host_space_type;
114 auto elemOrtsHost = Kokkos::create_mirror_view(
typename host_space_type::memory_space(), elemOrts);
115 auto elemNodesHost = Kokkos::create_mirror_view_and_copy(
typename host_space_type::memory_space(), elemNodes);
117 const ordinal_type numCells = elemNodes.extent(0);
118 for (
auto cell=0;cell<numCells;++cell) {
119 const auto nodes = Kokkos::subview(elemNodesHost, cell, Kokkos::ALL());
120 elemOrtsHost(cell) = Orientation::getOrientation(cellTopo, nodes);
123 Kokkos::deep_copy(elemOrts, elemOrtsHost);
126 template<
typename ortViewType,
127 typename OutputViewType,
128 typename inputViewType,
129 typename o2tViewType,
130 typename t2oViewType,
131 typename dataViewType>
134 OutputViewType output;
136 o2tViewType ordinalToTag;
137 t2oViewType tagToOrdinal;
139 const dataViewType matData;
140 const ordinal_type cellDim, numVerts, numEdges, numFaces, numPoints, dimBasis;
143 OutputViewType output_,
144 inputViewType input_,
145 o2tViewType ordinalToTag_,
146 t2oViewType tagToOrdinal_,
147 const dataViewType matData_,
148 const ordinal_type cellDim_,
149 const ordinal_type numVerts_,
150 const ordinal_type numEdges_,
151 const ordinal_type numFaces_,
152 const ordinal_type numPoints_,
153 const ordinal_type dimBasis_)
157 ordinalToTag(ordinalToTag_),
158 tagToOrdinal(tagToOrdinal_),
164 numPoints(numPoints_),
168 KOKKOS_INLINE_FUNCTION
169 void operator()(
const ordinal_type cell)
const {
170 typedef typename inputViewType::non_const_value_type input_value_type;
172 auto out = Kokkos::subview(output, cell, Kokkos::ALL(), Kokkos::ALL(), Kokkos::ALL());
173 auto in = (input.rank() == output.rank()) ?
174 Kokkos::subview(input, cell, Kokkos::ALL(), Kokkos::ALL(), Kokkos::ALL())
175 : Kokkos::subview(input, Kokkos::ALL(), Kokkos::ALL(), Kokkos::ALL());
178 for (ordinal_type vertId=0;vertId<numVerts;++vertId) {
179 const ordinal_type i = (
static_cast<size_type
>(vertId) < tagToOrdinal.extent(1) ? tagToOrdinal(0, vertId, 0) : -1);
181 for (ordinal_type j=0;j<numPoints;++j)
182 for (ordinal_type k=0;k<dimBasis;++k)
183 out(i, j, k) = in(i, j, k);
188 const ordinal_type ordIntr = (
static_cast<size_type
>(cellDim) < tagToOrdinal.extent(0) ? tagToOrdinal(cellDim, 0, 0) : -1);
190 const ordinal_type ndofIntr = ordinalToTag(ordIntr, 3);
191 for (ordinal_type i=0;i<ndofIntr;++i) {
192 const ordinal_type ii = tagToOrdinal(cellDim, 0, i);
193 for (ordinal_type j=0;j<numPoints;++j)
194 for (ordinal_type k=0;k<dimBasis;++k)
195 out(ii, j, k) = in(ii, j, k);
201 ordinal_type existEdgeDofs = 0;
203 ordinal_type ortEdges[12];
204 orts(cell).getEdgeOrientation(ortEdges, numEdges);
207 for (ordinal_type edgeId=0;edgeId<numEdges;++edgeId) {
208 const ordinal_type ordEdge = (1 < tagToOrdinal.extent(0) ? (
static_cast<size_type
>(edgeId) < tagToOrdinal.extent(1) ? tagToOrdinal(1, edgeId, 0) : -1) : -1);
212 const ordinal_type ndofEdge = ordinalToTag(ordEdge, 3);
213 const auto mat = Kokkos::subview(matData,
214 edgeId, ortEdges[edgeId],
215 Kokkos::ALL(), Kokkos::ALL());
217 for (ordinal_type j=0;j<numPoints;++j)
218 for (ordinal_type i=0;i<ndofEdge;++i) {
219 const ordinal_type ii = tagToOrdinal(1, edgeId, i);
221 for (ordinal_type k=0;k<dimBasis;++k) {
222 input_value_type temp = 0.0;
223 for (ordinal_type l=0;l<ndofEdge;++l) {
224 const ordinal_type ll = tagToOrdinal(1, edgeId, l);
225 temp += mat(i,l)*in(ll, j, k);
227 out(ii, j, k) = temp;
236 ordinal_type ortFaces[12];
237 orts(cell).getFaceOrientation(ortFaces, numFaces);
240 for (ordinal_type faceId=0;faceId<numFaces;++faceId) {
241 const ordinal_type ordFace = (2 < tagToOrdinal.extent(0) ? (
static_cast<size_type
>(faceId) < tagToOrdinal.extent(1) ? tagToOrdinal(2, faceId, 0) : -1) : -1);
244 const ordinal_type ndofFace = ordinalToTag(ordFace, 3);
245 const auto mat = Kokkos::subview(matData,
246 numEdges*existEdgeDofs+faceId, ortFaces[faceId],
247 Kokkos::ALL(), Kokkos::ALL());
249 for (ordinal_type j=0;j<numPoints;++j)
250 for (ordinal_type i=0;i<ndofFace;++i) {
251 const ordinal_type ii = tagToOrdinal(2, faceId, i);
253 for (ordinal_type k=0;k<dimBasis;++k) {
254 input_value_type temp = 0.0;
255 for (ordinal_type l=0;l<ndofFace;++l) {
256 const ordinal_type ll = tagToOrdinal(2, faceId, l);
257 temp += mat(i,l)*in(ll, j, k);
259 out(ii, j, k) = temp;
268 template<
typename SpT>
269 template<
typename outputValueType,
class ...outputProperties,
270 typename inputValueType,
class ...inputProperties,
271 typename ortValueType,
class ...ortProperties,
276 const Kokkos::DynRankView<inputValueType, inputProperties...> input,
277 const Kokkos::DynRankView<ortValueType, ortProperties...> orts,
278 const BasisType* basis ) {
279 #ifdef HAVE_INTREPID2_DEBUG
281 if (input.rank() == output.rank())
283 for (size_type i=0;i<input.rank();++i)
284 INTREPID2_TEST_FOR_EXCEPTION( input.extent(i) != output.extent(i), std::invalid_argument,
285 ">>> ERROR (OrientationTools::modifyBasisByOrientation): Input and output dimension does not match.");
287 else if (input.rank() == output.rank() - 1)
289 for (size_type i=0;i<input.rank();++i)
290 INTREPID2_TEST_FOR_EXCEPTION( input.extent(i) != output.extent(i+1), std::invalid_argument,
291 ">>> 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).");
295 INTREPID2_TEST_FOR_EXCEPTION(
true, std::invalid_argument,
296 ">>> ERROR (OrientationTools::modifyBasisByOrientation): input and output ranks must either match, or input rank must be one less than that of output.")
299 INTREPID2_TEST_FOR_EXCEPTION( static_cast<ordinal_type>(output.extent(1)) != basis->getCardinality(), std::invalid_argument,
300 ">>> ERROR (OrientationTools::modifyBasisByOrientation): Field dimension of input/output does not match to basis cardinality.");
304 if (basis->requireOrientation()) {
305 auto ordinalToTag = Kokkos::create_mirror_view(
typename SpT::memory_space(), basis->getAllDofTags());
306 auto tagToOrdinal = Kokkos::create_mirror_view(
typename SpT::memory_space(), basis->getAllDofOrdinal());
308 Kokkos::deep_copy(ordinalToTag, basis->getAllDofTags());
309 Kokkos::deep_copy(tagToOrdinal, basis->getAllDofOrdinal());
312 numCells = output.extent(0),
314 numPoints = output.extent(2),
315 dimBasis = output.extent(3);
318 const shards::CellTopology cellTopo = basis->getBaseCellTopology();
321 cellDim = cellTopo.getDimension(),
322 numVerts = cellTopo.getVertexCount()*ordinal_type(basis->getDofCount(0, 0) > 0),
323 numEdges = cellTopo.getEdgeCount()*ordinal_type(basis->getDofCount(1, 0) > 0),
324 numFaces = cellTopo.getFaceCount();
326 const Kokkos::RangePolicy<SpT> policy(0, numCells);
329 decltype(output),decltype(input),
330 decltype(ordinalToTag),decltype(tagToOrdinal),
331 decltype(matData)> FunctorType;
332 Kokkos::parallel_for(policy,
335 ordinalToTag, tagToOrdinal,
337 cellDim, numVerts, numEdges, numFaces,
338 numPoints, dimBasis));
340 Kokkos::deep_copy(output, input);