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 using result_layout = typename DeduceLayout< decltype(refPoints) >::result_layout;
72 auto vcprop = Kokkos::common_view_alloc_prop(refPoints);
73 using common_value_type = typename decltype(vcprop)::value_type;
74 Kokkos::DynRankView< common_value_type, result_layout, deviceType > initGuess ( Kokkos::view_alloc("CellTools::mapToReferenceFrame::initGuess", vcprop), numCells, numPoints, spaceDim );
75 //refPointViewSpType initGuess("CellTools::mapToReferenceFrame::initGuess", numCells, numPoints, spaceDim);
76 rst::clone(initGuess, cellCenter);
77
78 mapToReferenceFrameInitGuess(refPoints, initGuess, physPoints, worksetCell, cellTopo);
79 }
80
81
82 template<typename DeviceType>
83 template<typename refPointValueType, class ...refPointProperties,
84 typename initGuessValueType, class ...initGuessProperties,
85 typename physPointValueType, class ...physPointProperties,
86 typename worksetCellValueType, class ...worksetCellProperties,
87 typename HGradBasisPtrType>
88 void
90 mapToReferenceFrameInitGuess( Kokkos::DynRankView<refPointValueType,refPointProperties...> refPoints,
91 const Kokkos::DynRankView<initGuessValueType,initGuessProperties...> initGuess,
92 const Kokkos::DynRankView<physPointValueType,physPointProperties...> physPoints,
93 const Kokkos::DynRankView<worksetCellValueType,worksetCellProperties...> worksetCell,
94 const HGradBasisPtrType basis ) {
95#ifdef HAVE_INTREPID2_DEBUG
96 CellTools_mapToReferenceFrameInitGuessArgs(refPoints, initGuess, physPoints, worksetCell,
97 basis->getBaseCellTopology());
98
99#endif
100
101 constexpr bool are_accessible =
102 Kokkos::Impl::MemorySpaceAccess<MemSpaceType,
103 typename decltype(refPoints)::memory_space>::accessible &&
104 Kokkos::Impl::MemorySpaceAccess<MemSpaceType,
105 typename decltype(initGuess)::memory_space>::accessible &&
106 Kokkos::Impl::MemorySpaceAccess<MemSpaceType,
107 typename decltype(physPoints)::memory_space>::accessible &&
108 Kokkos::Impl::MemorySpaceAccess<MemSpaceType,
109 typename decltype(worksetCell)::memory_space>::accessible;
110
111 static_assert(are_accessible, "CellTools<DeviceType>::mapToReferenceFrameInitGuess(..): input/output views' memory spaces are not compatible with DeviceType");
112
113
114 const auto cellTopo = basis->getBaseCellTopology();
115 const auto spaceDim = cellTopo.getDimension();
116
117 // Default: map (C,P,D) array of physical pt. sets to (C,P,D) array.
118 // Requires (C,P,D) temp arrays and (C,P,D,D) Jacobians.
119 const auto numCells = worksetCell.extent(0);
120 const auto numPoints = physPoints.extent(1);
121
122 using rst = RealSpaceTools<DeviceType>;
123 const auto tol = tolerence();
124
125 using result_layout = typename DeduceLayout< decltype(refPoints) >::result_layout;
126 auto vcprop = Kokkos::common_view_alloc_prop(refPoints);
127 using viewType = Kokkos::DynRankView<typename decltype(vcprop)::value_type, result_layout, DeviceType >;
128
129 // Temp arrays for Newton iterates and Jacobians. Resize according to rank of ref. point array
130 viewType xOld(Kokkos::view_alloc("CellTools::mapToReferenceFrameInitGuess::xOld", vcprop), numCells, numPoints, spaceDim);
131 viewType xTmp(Kokkos::view_alloc("CellTools::mapToReferenceFrameInitGuess::xTmp", vcprop), numCells, numPoints, spaceDim);
132
133 // deep copy may not work with FAD but this is right thing to do as it can move data between devices
134 Kokkos::deep_copy(xOld, initGuess);
135
136 // jacobian should select fad dimension between xOld and worksetCell as they are input; no front interface yet
137 auto vcpropJ = Kokkos::common_view_alloc_prop(refPoints, worksetCell);
138 using viewTypeJ = Kokkos::DynRankView<typename decltype(vcpropJ)::value_type, result_layout, DeviceType >;
139 viewTypeJ jacobian(Kokkos::view_alloc("CellTools::mapToReferenceFrameInitGuess::jacobian", vcpropJ), numCells, numPoints, spaceDim, spaceDim);
140 viewTypeJ jacobianInv(Kokkos::view_alloc("CellTools::mapToReferenceFrameInitGuess::jacobianInv", vcpropJ), numCells, numPoints, spaceDim, spaceDim);
141
142 using errorViewType = Kokkos::DynRankView<typename ScalarTraits<refPointValueType>::scalar_type, DeviceType>;
143 errorViewType
144 xScalarTmp ("CellTools::mapToReferenceFrameInitGuess::xScalarTmp", numCells, numPoints, spaceDim),
145 errorPointwise("CellTools::mapToReferenceFrameInitGuess::errorPointwise", numCells, numPoints),
146 errorCellwise ("CellTools::mapToReferenceFrameInitGuess::errorCellwise", numCells);
147
148 // Newton method to solve the equation F(refPoints) - physPoints = 0:
149 // refPoints = xOld - DF^{-1}(xOld)*(F(xOld) - physPoints) = xOld + DF^{-1}(xOld)*(physPoints - F(xOld))
150 for (ordinal_type iter=0;iter<Parameters::MaxNewton;++iter) {
151
152 // Jacobians at the old iterates and their inverses.
153 setJacobian(jacobian, xOld, worksetCell, basis);
154 setJacobianInv(jacobianInv, jacobian);
155
156 // The Newton step.
157 mapToPhysicalFrame(xTmp, xOld, worksetCell, basis); // xTmp <- F(xOld)
158 rst::subtract(xTmp, physPoints, xTmp); // xTmp <- physPoints - F(xOld)
159 rst::matvec(refPoints, jacobianInv, xTmp); // refPoints <- DF^{-1}( physPoints - F(xOld) )
160 rst::add(refPoints, xOld); // refPoints <- DF^{-1}( physPoints - F(xOld) ) + xOld
161
162 // l2 error (Euclidean distance) between old and new iterates: |xOld - xNew|
163 rst::subtract(xTmp, xOld, refPoints);
164
165 // extract values
166 rst::extractScalarValues(xScalarTmp, xTmp);
167 rst::vectorNorm(errorPointwise, xScalarTmp, NORM_TWO);
168
169 // Average L2 error for a multiple sets of physical points: error is rank-2 (C,P) array
170 rst::vectorNorm(errorCellwise, errorPointwise, NORM_ONE);
171
172 auto errorCellwise_h = Kokkos::create_mirror_view(errorCellwise);
173 Kokkos::deep_copy(errorCellwise_h, errorCellwise);
174 const auto errorTotal = rst::Serial::vectorNorm(errorCellwise_h, NORM_ONE);
175
176 // Stopping criterion:
177 if (errorTotal < tol)
178 break;
179
180 // initialize next Newton step ( this is not device friendly )
181 Kokkos::deep_copy(xOld, refPoints);
182 }
183 }
184
185}
186
187#endif
static 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 mapToPhysicalFrame(PhysPointValueType physPoints, const RefPointValueType refPoints, const WorksetType worksetCell, const HGradBasisPtrType basis)
Computes F, the reference-to-physical frame map.
static void setJacobianInv(JacobianInvViewType jacobianInv, const JacobianViewType jacobian)
Computes the inverse of the Jacobian matrix DF of the reference-to-physical frame map F.
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 void setJacobian(JacobianViewType jacobian, const PointViewType points, const WorksetType worksetCell, const Teuchos::RCP< HGradBasisType > basis, const int startCell=0, const int endCell=-1)
Computes the Jacobian matrix DF of the reference-to-physical frame map F.
static void getReferenceCellCenter(Kokkos::DynRankView< cellCenterValueType, cellCenterProperties... > cellCenter, const shards::CellTopology cell)
Computes the Cartesian coordinates of reference cell barycenter.
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)