DFT-EFE
 
Loading...
Searching...
No Matches
SplineKernels.h
Go to the documentation of this file.
1/******************************************************************************
2 * Copyright (c) 2021. *
3 * The Regents of the University of Michigan and DFT-EFE developers. *
4 * *
5 * This file is part of the DFT-EFE code. *
6 * *
7 * DFT-EFE is free software: you can redistribute it and/or modify *
8 * it under the terms of the Lesser GNU General Public License as *
9 * published by the Free Software Foundation, either version 3 of *
10 * the License, or (at your option) any later version. *
11 * *
12 * DFT-EFE is distributed in the hope that it will be useful, but *
13 * WITHOUT ANY WARRANTY; without even the implied warranty *
14 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. *
15 * See the Lesser GNU General Public License for more details. *
16 * *
17 * You should have received a copy of the GNU Lesser General Public *
18 * License at the top level of DFT-EFE distribution. If not, see *
19 * <https://www.gnu.org/licenses/>. *
20 ******************************************************************************/
21
22/*
23 * Inline DFTEFE_HOST_DEVICE_FUNC definitions for Spline evaluation.
24 * Included unconditionally by Spline.h so that every translation unit
25 * (CPU or GPU) that includes Spline.h gets its own inline copy.
26 *
27 * @author Avirup Sircar
28 */
29
30#ifndef dftefe_SplineDeviceKernels_h
31#define dftefe_SplineDeviceKernels_h
32
33#include <utils/Spline.h>
35#include <cmath>
36
37namespace dftefe
38{
39 namespace utils
40 {
41 namespace
42 {
43 //-----------------------------------------------------------------------
44 // splineFindIdx — device index search: returns the knot index i such
45 // that knotX[i] <= x < knotX[i+1] (or the boundary indices).
46 //-----------------------------------------------------------------------
48 splineFindIdx(const double xi,
49 const double * knotX,
50 const size_type nKnots,
51 const bool isSubdivGrid,
52 const double a_param,
53 const double r_param,
54 const dftefe::size_type numSubDiv)
55 {
56 if (isSubdivGrid)
57 {
58 if (xi > knotX[nKnots - 1])
59 return nKnots - 1;
60 if (xi < knotX[0])
61 return 0;
62 double rDiff = r_param - 1.0;
63 dftefe::size_type n_gp = 0;
64 dftefe::size_type subId = 0;
65 if (rDiff < 1e-6 && rDiff > -1e-6)
66 {
67 subId = static_cast<dftefe::size_type>(xi / a_param);
68 }
69 else
70 {
71 n_gp = static_cast<dftefe::size_type>(
72 log(xi * rDiff / a_param + 1.0) / log(r_param));
73 double segStart =
74 a_param * (pow(r_param, static_cast<double>(n_gp)) - 1.0) /
75 rDiff;
76 double segWidth =
77 a_param * pow(r_param, static_cast<double>(n_gp));
78 subId = static_cast<dftefe::size_type>(
79 static_cast<double>(numSubDiv) * (xi - segStart) / segWidth);
80 }
81 size_type idx = static_cast<size_type>(n_gp * numSubDiv + subId);
82 return (idx >= nKnots) ? nKnots - 1 : idx;
83 }
84 else
85 {
86 if (xi <= knotX[0])
87 return 0;
88 if (xi >= knotX[nKnots - 1])
89 return nKnots - 1;
90 size_type lo = 0;
91 size_type hi = nKnots - 1;
92 while (hi - lo > 1)
93 {
94 size_type mid = (lo + hi) / 2;
95 if (knotX[mid] <= xi)
96 lo = mid;
97 else
98 hi = mid;
99 }
100 return lo;
101 }
102 }
103
104 //-----------------------------------------------------------------------
105 // Scalar device helper: evaluate spline at a single point x.
106 //-----------------------------------------------------------------------
108 SplineEvalKernel(const double x,
109 const double * knotX,
110 const double * knotY,
111 const double * coefB,
112 const double * coefC,
113 const double * coefD,
114 const size_type nKnots,
115 const double c0,
116 const bool isSubdivGrid,
117 const double a_param,
118 const double r_param,
119 const dftefe::size_type numSubDiv)
120 {
121 double xi = x;
122 const size_type idx = splineFindIdx(
123 xi, knotX, nKnots, isSubdivGrid, a_param, r_param, numSubDiv);
124 double h = xi - knotX[idx];
125 double interpol;
126 if (xi < knotX[0])
127 interpol = (c0 * h + coefB[0]) * h + knotY[0];
128 else if (xi > knotX[nKnots - 1])
129 interpol =
130 (coefC[nKnots - 1] * h + coefB[nKnots - 1]) * h + knotY[nKnots - 1];
131 else
132 interpol =
133 ((coefD[idx] * h + coefC[idx]) * h + coefB[idx]) * h + knotY[idx];
134 return interpol;
135 }
136
137 //-----------------------------------------------------------------------
138 // Scalar device helper: evaluate spline derivative at a single point x.
139 //-----------------------------------------------------------------------
141 SplineDerivKernel(const int derivOrder,
142 const double x,
143 const double * knotX,
144 const double * coefB,
145 const double * coefC,
146 const double * coefD,
147 const size_type nKnots,
148 const double c0,
149 const bool isSubdivGrid,
150 const double a_param,
151 const double r_param,
152 const dftefe::size_type numSubDiv)
153 {
154 double xi = x;
155 const size_type idx = splineFindIdx(
156 xi, knotX, nKnots, isSubdivGrid, a_param, r_param, numSubDiv);
157 double h = xi - knotX[idx];
158 double interpol = 0.0;
159 if (xi < knotX[0])
160 {
161 if (derivOrder == 1)
162 interpol = 2.0 * c0 * h + coefB[0];
163 else if (derivOrder == 2)
164 interpol = 2.0 * c0;
165 }
166 else if (xi > knotX[nKnots - 1])
167 {
168 if (derivOrder == 1)
169 interpol = 2.0 * coefC[nKnots - 1] * h + coefB[nKnots - 1];
170 else if (derivOrder == 2)
171 interpol = 2.0 * coefC[nKnots - 1];
172 }
173 else
174 {
175 if (derivOrder == 1)
176 interpol =
177 (3.0 * coefD[idx] * h + 2.0 * coefC[idx]) * h + coefB[idx];
178 else if (derivOrder == 2)
179 interpol = 6.0 * coefD[idx] * h + 2.0 * coefC[idx];
180 else if (derivOrder == 3)
181 interpol = 6.0 * coefD[idx];
182 }
183 return interpol;
184 }
185
186 } // anonymous namespace
187
188 template <dftefe::utils::MemorySpace memorySpace>
190 const double * knotY,
191 const double * coefB,
192 const double * coefC,
193 const double * coefD,
194 size_type nKnots,
195 double c0,
196 bool isSubdivGrid,
197 double a,
198 double r,
199 dftefe::size_type numSubDiv)
200 : d_knotX(knotX)
201 , d_knotY(knotY)
202 , d_coefB(coefB)
203 , d_coefC(coefC)
204 , d_coefD(coefD)
205 , d_nKnots(nKnots)
206 , d_c0(c0)
207 , d_isSubdivGrid(isSubdivGrid)
208 , d_a(a)
209 , d_r(r)
210 , d_numSubDiv(numSubDiv)
211 {}
212
213 template <dftefe::utils::MemorySpace memorySpace>
216 {
217 return SplineEvalKernel(xi,
218 d_knotX,
219 d_knotY,
220 d_coefB,
221 d_coefC,
222 d_coefD,
223 d_nKnots,
224 d_c0,
225 d_isSubdivGrid,
226 d_a,
227 d_r,
229 }
230
231 template <dftefe::utils::MemorySpace memorySpace>
233 Spline::Func<memorySpace>::deriv(int order, double xi) const
234 {
235 return SplineDerivKernel(order,
236 xi,
237 d_knotX,
238 d_coefB,
239 d_coefC,
240 d_coefD,
241 d_nKnots,
242 d_c0,
243 d_isSubdivGrid,
244 d_a,
245 d_r,
247 }
248
249 } // namespace utils
250} // namespace dftefe
251
252#endif // dftefe_SplineDeviceKernels_h
#define DFTEFE_HOST_DEVICE_FUNC
Definition: DeviceKernelLauncherHelpers.h:306
DFTEFE_HOST_DEVICE_FUNC double eval(double xi) const
Definition: SplineKernels.h:215
Func()
Definition: Spline.h:56
DFTEFE_HOST_DEVICE_FUNC double deriv(int order, double xi) const
Definition: SplineKernels.h:233
double d_r
Definition: Spline.h:128
double d_c0
Definition: Spline.h:122
dftefe::size_type d_numSubDiv
Definition: Spline.h:129
double d_a
Definition: Spline.h:128
dealii includes
Definition: AtomFieldDataSpherical.cpp:31
std::uint64_t size_type
Definition: TypeConfig.h:9