Intrepid2
Intrepid2_CellToolsDefPhysToRef.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
16#ifndef __INTREPID2_CELLTOOLS_DEF_PHYS_TO_REF_HPP__
17#define __INTREPID2_CELLTOOLS_DEF_PHYS_TO_REF_HPP__
18
19// disable clang warnings
20#if defined (__clang__) && !defined (__INTEL_COMPILER)
21#pragma clang system_header
22#endif
23
24namespace Intrepid2 {
25
26
27 //============================================================================================//
28 // //
29 // Reference-to-physical frame mapping and its inverse //
30 // //
31 //============================================================================================//
32
33 template<typename DeviceType>
34 template<typename refPointValueType, class ...refPointProperties,
35 typename physPointValueType, class ...physPointProperties,
36 typename worksetCellValueType, class ...worksetCellProperties>
37 void
39 mapToReferenceFrame( Kokkos::DynRankView<refPointValueType,refPointProperties...> refPoints,
40 const Kokkos::DynRankView<physPointValueType,physPointProperties...> physPoints,
41 const Kokkos::DynRankView<worksetCellValueType,worksetCellProperties...> worksetCell,
42 const shards::CellTopology cellTopo ) {
43 constexpr bool are_accessible =
44 Kokkos::Impl::MemorySpaceAccess<MemSpaceType,
45 typename decltype(refPoints)::memory_space>::accessible &&
46 Kokkos::Impl::MemorySpaceAccess<MemSpaceType,
47 typename decltype(physPoints)::memory_space>::accessible &&
48 Kokkos::Impl::MemorySpaceAccess<MemSpaceType,
49 typename decltype(worksetCell)::memory_space>::accessible;
50
51 static_assert(are_accessible, "CellTools<DeviceType>::mapToReferenceFrame(..): input/output views' memory spaces are not compatible with DeviceType");
52
53#ifdef HAVE_INTREPID2_DEBUG
54 CellTools_mapToReferenceFrameArgs(refPoints, physPoints, worksetCell, cellTopo);
55#endif
56 using deviceType = typename decltype(refPoints)::device_type;
57
59 typedef Kokkos::DynRankView<typename ScalarTraits<refPointValueType>::scalar_type,deviceType> refPointViewSpType;
60
61 const auto spaceDim = cellTopo.getDimension();
62 refPointViewSpType
63 cellCenter("CellTools::mapToReferenceFrame::cellCenter", spaceDim);
64 getReferenceCellCenter(cellCenter, cellTopo);
65
66 // Default: map (C,P,D) array of physical pt. sets to (C,P,D) array. Requires (C,P,D) initial guess.
67 const auto numCells = worksetCell.extent(0);
68 const auto numPoints = physPoints.extent(1);
69
70 // init guess is created locally and non fad whatever refpoints type is
71 auto initGuess = Impl::createMatchingDynRankView(refPoints, "CellTools::mapToReferenceFrame::initGuess", numCells, numPoints, spaceDim );
72 rst::clone(initGuess, cellCenter);
73
74 mapToReferenceFrameInitGuess(refPoints, initGuess, physPoints, worksetCell, cellTopo);
75 }
76
77
78 template<typename DeviceType>
79 template<typename refPointValueType, class ...refPointProperties,
80 typename initGuessValueType, class ...initGuessProperties,
81 typename physPointValueType, class ...physPointProperties,
82 typename worksetCellValueType, class ...worksetCellProperties,
83 typename HGradBasisPtrType>
84 void
86 mapToReferenceFrameInitGuess( Kokkos::DynRankView<refPointValueType,refPointProperties...> refPoints,
87 const Kokkos::DynRankView<initGuessValueType,initGuessProperties...> initGuess,
88 const Kokkos::DynRankView<physPointValueType,physPointProperties...> physPoints,
89 const Kokkos::DynRankView<worksetCellValueType,worksetCellProperties...> worksetCell,
90 const HGradBasisPtrType basis ) {
91#ifdef HAVE_INTREPID2_DEBUG
92 CellTools_mapToReferenceFrameInitGuessArgs(refPoints, initGuess, physPoints, worksetCell,
93 basis->getBaseCellTopology());
94
95#endif
96
97 constexpr bool are_accessible =
98 Kokkos::Impl::MemorySpaceAccess<MemSpaceType,
99 typename decltype(refPoints)::memory_space>::accessible &&
100 Kokkos::Impl::MemorySpaceAccess<MemSpaceType,
101 typename decltype(initGuess)::memory_space>::accessible &&
102 Kokkos::Impl::MemorySpaceAccess<MemSpaceType,
103 typename decltype(physPoints)::memory_space>::accessible &&
104 Kokkos::Impl::MemorySpaceAccess<MemSpaceType,
105 typename decltype(worksetCell)::memory_space>::accessible;
106
107 static_assert(are_accessible, "CellTools<DeviceType>::mapToReferenceFrameInitGuess(..): input/output views' memory spaces are not compatible with DeviceType");
108
109
110 const auto cellTopo = basis->getBaseCellTopology();
111 const auto spaceDim = cellTopo.getDimension();
112
113 // Default: map (C,P,D) array of physical pt. sets to (C,P,D) array.
114 // Requires (C,P,D) temp arrays and (C,P,D,D) Jacobians.
115 const auto numCells = worksetCell.extent(0);
116 const auto numPoints = physPoints.extent(1);
117
118 using rst = RealSpaceTools<DeviceType>;
119 const auto tol = tolerence();
120
121 using result_layout = typename DeduceLayout< decltype(refPoints) >::result_layout;
122 // Temp arrays for Newton iterates and Jacobians. Resize according to rank of ref. point array
123 auto xOld = Impl::createMatchingDynRankView(refPoints, "CellTools::mapToReferenceFrameInitGuess::xOld", numCells, numPoints, spaceDim);
124 auto xTmp = Impl::createMatchingDynRankView(refPoints, "CellTools::mapToReferenceFrameInitGuess::xTmp", numCells, numPoints, spaceDim);
125
126 // deep copy may not work with FAD but this is right thing to do as it can move data between devices
127 Kokkos::deep_copy(xOld, initGuess);
128
129 // jacobian should select fad dimension between xOld and worksetCell as they are input; no front interface yet
130 using valueTypeJ = std::common_type_t<typename decltype(refPoints)::value_type, typename decltype(worksetCell)::value_type>;
131 using viewTypeJ = Kokkos::DynRankView<valueTypeJ, result_layout, DeviceType >;
132 using view_factory = Impl::CreateViewFactory<decltype(refPoints), decltype(worksetCell)>;
133 viewTypeJ jacobian = view_factory::template create_view<viewTypeJ>(refPoints, worksetCell, "CellTools::mapToReferenceFrameInitGuess::jacobian", numCells, numPoints, spaceDim, spaceDim);
134 viewTypeJ jacobianInv = view_factory::template create_view<viewTypeJ>(refPoints, worksetCell, "CellTools::mapToReferenceFrameInitGuess::jacobianInv", numCells, numPoints, spaceDim, spaceDim);
135
136 using errorViewType = Kokkos::DynRankView<typename ScalarTraits<refPointValueType>::scalar_type, DeviceType>;
137 errorViewType
138 xScalarTmp ("CellTools::mapToReferenceFrameInitGuess::xScalarTmp", numCells, numPoints, spaceDim),
139 errorPointwise("CellTools::mapToReferenceFrameInitGuess::errorPointwise", numCells, numPoints),
140 errorCellwise ("CellTools::mapToReferenceFrameInitGuess::errorCellwise", numCells);
141
142 // Newton method to solve the equation F(refPoints) - physPoints = 0:
143 // refPoints = xOld - DF^{-1}(xOld)*(F(xOld) - physPoints) = xOld + DF^{-1}(xOld)*(physPoints - F(xOld))
144 for (ordinal_type iter=0;iter<Parameters::MaxNewton;++iter) {
145
146 // Jacobians at the old iterates and their inverses.
147 setJacobian(jacobian, xOld, worksetCell, basis);
148 setJacobianInv(jacobianInv, jacobian);
149
150 // The Newton step.
151 mapToPhysicalFrame(xTmp, xOld, worksetCell, basis); // xTmp <- F(xOld)
152 rst::subtract(xTmp, physPoints, xTmp); // xTmp <- physPoints - F(xOld)
153 rst::matvec(refPoints, jacobianInv, xTmp); // refPoints <- DF^{-1}( physPoints - F(xOld) )
154 rst::add(refPoints, xOld); // refPoints <- DF^{-1}( physPoints - F(xOld) ) + xOld
155
156 // l2 error (Euclidean distance) between old and new iterates: |xOld - xNew|
157 rst::subtract(xTmp, xOld, refPoints);
158
159 // extract values
160 rst::extractScalarValues(xScalarTmp, xTmp);
161 rst::vectorNorm(errorPointwise, xScalarTmp, NORM_TWO);
162
163 // Average L2 error for a multiple sets of physical points: error is rank-2 (C,P) array
164 rst::vectorNorm(errorCellwise, errorPointwise, NORM_ONE);
165
166 auto errorCellwise_h = Kokkos::create_mirror_view(errorCellwise);
167 Kokkos::deep_copy(errorCellwise_h, errorCellwise);
168 const auto errorTotal = rst::Serial::vectorNorm(errorCellwise_h, NORM_ONE);
169
170 // Stopping criterion:
171 if (errorTotal < tol)
172 break;
173
174 // initialize next Newton step ( this is not device friendly )
175 Kokkos::deep_copy(xOld, refPoints);
176 }
177 }
178
179}
180
181#endif
void CellTools_mapToReferenceFrameArgs(const refPointViewType refPoints, const physPointViewType physPoints, const worksetCellViewType worksetCell, const shards::CellTopology cellTopo)
Validates arguments to Intrepid2::CellTools::mapToReferenceFrame with default initial guess.
static void mapToReferenceFrame(Kokkos::DynRankView< refPointValueType, refPointProperties... > refPoints, const Kokkos::DynRankView< physPointValueType, physPointProperties... > physPoints, const Kokkos::DynRankView< worksetCellValueType, worksetCellProperties... > worksetCell, const shards::CellTopology cellTopo)
Computes , the inverse of the reference-to-physical frame map using a default initial guess.
static void mapToReferenceFrameInitGuess(Kokkos::DynRankView< refPointValueType, refPointProperties... > refPoints, const Kokkos::DynRankView< initGuessValueType, initGuessProperties... > initGuess, const Kokkos::DynRankView< physPointValueType, physPointProperties... > physPoints, const Kokkos::DynRankView< worksetCellValueType, worksetCellProperties... > worksetCell, const HGradBasisPtrType basis)
Computation of , the inverse of the reference-to-physical frame map using user-supplied initial guess...
static constexpr ordinal_type MaxNewton
Maximum number of Newton iterations used internally in methods such as computing the action of the in...
Implementation of basic linear algebra functionality in Euclidean space.
layout deduction (temporary meta-function)
Factory to create a view based on the properties of input views The class is useful when the view can...