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 
24 namespace 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 
58  typedef RealSpaceTools<deviceType> rst;
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 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...
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...
Implementation of basic linear algebra functionality in Euclidean space.