Compadre 1.6.4
Loading...
Searching...
No Matches
Compadre_ScalarTaylorPolynomial.hpp
Go to the documentation of this file.
1// @HEADER
2// *****************************************************************************
3// Compadre: COMpatible PArticle Discretization and REmap Toolkit
4//
5// Copyright 2018 NTESS and the Compadre contributors.
6// SPDX-License-Identifier: BSD-2-Clause
7// *****************************************************************************
8// @HEADER
9#ifndef _COMPADRE_SCALAR_TAYLORPOLYNOMIAL_BASIS_HPP_
10#define _COMPADRE_SCALAR_TAYLORPOLYNOMIAL_BASIS_HPP_
11
12#include "Compadre_GMLS.hpp"
13
14namespace Compadre {
15/*! \brief Definition of scalar Taylor polynomial basis
16
17 For order P, the sum of the basis is defined by:
18 \li in 1D) \f[\sum_{n=0}^{n=P} \frac{(x/h)^n}{n!}\f]
19 \li in 2D) \f[\sum_{n=0}^{n=P} \sum_{k=0}^{k=n} \frac{(x/h)^{n-k}*(y/h)^k}{(n-k)!k!}\f]
20 \li in 3D) \f[\sum_{p=0}^{p=P} \sum_{k_1+k_2+k_3=n} \frac{(x/h)^{k_1}*(y/h)^{k_2}*(z/h)^{k_3}}{k_1!k_2!k_3!}\f]
21*/
22namespace ScalarTaylorPolynomialBasis {
23
24 /*! \brief Returns size of basis
25 \param degree [in] - highest degree of polynomial
26 \param dimension [in] - spatial dimension to evaluate
27 */
28 KOKKOS_INLINE_FUNCTION
29 int getSize(const int degree, const int dimension) {
30 if (dimension == 3) return (degree+1)*(degree+2)*(degree+3)/6;
31 else if (dimension == 2) return (degree+1)*(degree+2)/2;
32 else return degree+1;
33 }
34
35 /*! \brief Evaluates the scalar Taylor polynomial basis
36 * delta[j] = weight_of_original_value * delta[j] + weight_of_new_value * (calculation of this function)
37 \param delta [in/out] - scratch space that is allocated so that each thread has its own copy. Must be at least as large as the _basis_multipler*the dimension of the polynomial basis.
38 \param workspace [in/out] - scratch space that is allocated so that each thread has its own copy. Must be at least as large as the _poly_order*the spatial dimension of the polynomial basis.
39 \param dimension [in] - spatial dimension to evaluate
40 \param max_degree [in] - highest degree of polynomial
41 \param h [in] - epsilon/window size
42 \param x [in] - x coordinate (already shifted by target)
43 \param y [in] - y coordinate (already shifted by target)
44 \param z [in] - z coordinate (already shifted by target)
45 \param starting_order [in] - polynomial order to start with (default=0)
46 \param weight_of_original_value [in] - weighting to assign to original value in delta (default=0, replace, 1-increment current value)
47 \param weight_of_new_value [in] - weighting to assign to new contribution (default=1, add to/replace)
48 */
49 KOKKOS_INLINE_FUNCTION
50 void evaluate(const member_type& teamMember, double* delta, double* workspace, const int dimension, const int max_degree, const double h, const double x, const double y, const double z, const int starting_order = 0, const double weight_of_original_value = 0.0, const double weight_of_new_value = 1.0) {
51 Kokkos::single(Kokkos::PerThread(teamMember), [&] () {
52 const double factorial[] = {1, 1, 2, 6, 24, 120, 720, 5040, 40320, 362880, 3628800, 39916800, 479001600, 6227020800, 87178291200};
53 if (dimension==3) {
54 scratch_vector_type x_over_h_to_i(workspace, max_degree+1);
55 scratch_vector_type y_over_h_to_i(workspace+1*(max_degree+1), max_degree+1);
56 scratch_vector_type z_over_h_to_i(workspace+2*(max_degree+1), max_degree+1);
57 x_over_h_to_i[0] = 1;
58 y_over_h_to_i[0] = 1;
59 z_over_h_to_i[0] = 1;
60 for (int i=1; i<=max_degree; ++i) {
61 x_over_h_to_i[i] = x_over_h_to_i[i-1]*(x/h);
62 y_over_h_to_i[i] = y_over_h_to_i[i-1]*(y/h);
63 z_over_h_to_i[i] = z_over_h_to_i[i-1]*(z/h);
64 }
65 // (in 3D) \sum_{p=0}^{p=P} \sum_{k1+k2+k3=n} (x/h)^k1*(y/h)^k2*(z/h)^k3 / (k1!k2!k3!)
66 int alphax, alphay, alphaz;
67 double alphaf;
68 int i=0, s=0;
69 for (int n = starting_order; n <= max_degree; n++){
70 for (alphaz = 0; alphaz <= n; alphaz++){
71 s = n - alphaz;
72 for (alphay = 0; alphay <= s; alphay++){
73 alphax = s - alphay;
74 alphaf = factorial[alphax]*factorial[alphay]*factorial[alphaz];
75 *(delta+i) = weight_of_original_value * *(delta+i) + weight_of_new_value * x_over_h_to_i[alphax]*y_over_h_to_i[alphay]*z_over_h_to_i[alphaz]/alphaf;
76 i++;
77 }
78 }
79 }
80 } else if (dimension==2) {
81 scratch_vector_type x_over_h_to_i(workspace, max_degree+1);
82 scratch_vector_type y_over_h_to_i(workspace+1*(max_degree+1), max_degree+1);
83 x_over_h_to_i[0] = 1;
84 y_over_h_to_i[0] = 1;
85 for (int i=1; i<=max_degree; ++i) {
86 x_over_h_to_i[i] = x_over_h_to_i[i-1]*(x/h);
87 y_over_h_to_i[i] = y_over_h_to_i[i-1]*(y/h);
88 }
89 // (in 2D) \sum_{n=0}^{n=P} \sum_{k=0}^{k=n} (x/h)^(n-k)*(y/h)^k / ((n-k)!k!)
90 int alphax, alphay;
91 double alphaf;
92 int i = 0;
93 for (int n = starting_order; n <= max_degree; n++){
94 for (alphay = 0; alphay <= n; alphay++){
95 alphax = n - alphay;
96 alphaf = factorial[alphax]*factorial[alphay];
97 *(delta+i) = weight_of_original_value * *(delta+i) + weight_of_new_value * x_over_h_to_i[alphax]*y_over_h_to_i[alphay]/alphaf;
98 i++;
99 }
100 }
101 } else {
102 scratch_vector_type x_over_h_to_i(workspace, max_degree+1);
103 x_over_h_to_i[0] = 1;
104 for (int i=1; i<=max_degree; ++i) {
105 x_over_h_to_i[i] = x_over_h_to_i[i-1]*(x/h);
106 }
107 // (in 1D) \sum_{n=0}^{n=P} (x/h)^n / n!
108 for (int i=starting_order; i<=max_degree; ++i) {
109 *(delta+i) = weight_of_original_value * *(delta+i) + weight_of_new_value * x_over_h_to_i[i]/factorial[i];
110 }
111 }
112 });
113 }
114
115 /*! \brief Evaluates the first partial derivatives of scalar Taylor polynomial basis
116 * delta[j] = weight_of_original_value * delta[j] + weight_of_new_value * (calculation of this function)
117 \param delta [in/out] - scratch space that is allocated so that each thread has its own copy. Must be at least as large as the _basis_multipler*the dimension of the polynomial basis.
118 \param workspace [in/out] - scratch space that is allocated so that each thread has its own copy. Must be at least as large as the _poly_order*the spatial dimension of the polynomial basis.
119 \param dimension [in] - spatial dimension to evaluate
120 \param max_degree [in] - highest degree of polynomial
121 \param partial_direction [in] - direction in which to take partial derivative
122 \param h [in] - epsilon/window size
123 \param x [in] - x coordinate (already shifted by target)
124 \param y [in] - y coordinate (already shifted by target)
125 \param z [in] - z coordinate (already shifted by target)
126 \param starting_order [in] - polynomial order to start with (default=0)
127 \param weight_of_original_value [in] - weighting to assign to original value in delta (default=0, replace, 1-increment current value)
128 \param weight_of_new_value [in] - weighting to assign to new contribution (default=1, add to/replace)
129 */
130 KOKKOS_INLINE_FUNCTION
131 void evaluatePartialDerivative(const member_type& teamMember, double* delta, double* workspace, const int dimension, const int max_degree, const int partial_direction, const double h, const double x, const double y, const double z, const int starting_order = 0, const double weight_of_original_value = 0.0, const double weight_of_new_value = 1.0) {
132 Kokkos::single(Kokkos::PerThread(teamMember), [&] () {
133 const double factorial[] = {1, 1, 2, 6, 24, 120, 720, 5040, 40320, 362880, 3628800, 39916800, 479001600, 6227020800, 87178291200};
134 if (dimension==3) {
135 scratch_vector_type x_over_h_to_i(workspace, max_degree+1);
136 scratch_vector_type y_over_h_to_i(workspace+1*(max_degree+1), max_degree+1);
137 scratch_vector_type z_over_h_to_i(workspace+2*(max_degree+1), max_degree+1);
138 x_over_h_to_i[0] = 1;
139 y_over_h_to_i[0] = 1;
140 z_over_h_to_i[0] = 1;
141 for (int i=1; i<=max_degree; ++i) {
142 x_over_h_to_i[i] = x_over_h_to_i[i-1]*(x/h);
143 y_over_h_to_i[i] = y_over_h_to_i[i-1]*(y/h);
144 z_over_h_to_i[i] = z_over_h_to_i[i-1]*(z/h);
145 }
146 // (in 3D) \sum_{p=0}^{p=P} \sum_{k1+k2+k3=n} (x/h)^k1*(y/h)^k2*(z/h)^k3 / (k1!k2!k3!)
147 int alphax, alphay, alphaz;
148 double alphaf;
149 int i=0, s=0;
150 for (int n = starting_order; n <= max_degree; n++){
151 for (alphaz = 0; alphaz <= n; alphaz++){
152 s = n - alphaz;
153 for (alphay = 0; alphay <= s; alphay++){
154 alphax = s - alphay;
155
156 int var_pow[3] = {alphax, alphay, alphaz};
157 var_pow[partial_direction]--;
158
159 if (var_pow[0]<0 || var_pow[1]<0 || var_pow[2]<0) {
160 *(delta+i) = weight_of_original_value * *(delta+i) + weight_of_new_value * 0.0;
161 } else {
162 alphaf = factorial[var_pow[0]]*factorial[var_pow[1]]*factorial[var_pow[2]];
163 *(delta+i) = weight_of_original_value * *(delta+i) + weight_of_new_value * 1./h * x_over_h_to_i[var_pow[0]]*y_over_h_to_i[var_pow[1]]*z_over_h_to_i[var_pow[2]]/alphaf;
164 }
165 i++;
166 }
167 }
168 }
169 } else if (dimension==2) {
170 scratch_vector_type x_over_h_to_i(workspace, max_degree+1);
171 scratch_vector_type y_over_h_to_i(workspace+1*(max_degree+1), max_degree+1);
172 x_over_h_to_i[0] = 1;
173 y_over_h_to_i[0] = 1;
174 for (int i=1; i<=max_degree; ++i) {
175 x_over_h_to_i[i] = x_over_h_to_i[i-1]*(x/h);
176 y_over_h_to_i[i] = y_over_h_to_i[i-1]*(y/h);
177 }
178 // (in 3D) \sum_{p=0}^{p=P} \sum_{k1+k2+k3=n} (x/h)^k1*(y/h)^k2*(z/h)^k3 / (k1!k2!k3!)
179 int alphax, alphay;
180 double alphaf;
181 int i=0;
182 for (int n = starting_order; n <= max_degree; n++){
183 for (alphay = 0; alphay <= n; alphay++){
184 alphax = n - alphay;
185
186 int var_pow[2] = {alphax, alphay};
187 var_pow[partial_direction]--;
188
189 if (var_pow[0]<0 || var_pow[1]<0) {
190 *(delta+i) = weight_of_original_value * *(delta+i) + weight_of_new_value * 0.0;
191 } else {
192 alphaf = factorial[var_pow[0]]*factorial[var_pow[1]];
193 *(delta+i) = weight_of_original_value * *(delta+i) + weight_of_new_value * 1./h * x_over_h_to_i[var_pow[0]]*y_over_h_to_i[var_pow[1]]/alphaf;
194 }
195 i++;
196 }
197 }
198 } else {
199 scratch_vector_type x_over_h_to_i(workspace, max_degree+1);
200 x_over_h_to_i[0] = 1;
201 for (int i=1; i<=max_degree; ++i) {
202 x_over_h_to_i[i] = x_over_h_to_i[i-1]*(x/h);
203 }
204 int alphax;
205 double alphaf;
206 int i=0;
207 for (int n = starting_order; n <= max_degree; n++){
208 alphax = n;
209
210 int var_pow[1] = {alphax};
211 var_pow[partial_direction]--;
212
213 if (var_pow[0]<0) {
214 *(delta+i) = weight_of_original_value * *(delta+i) + weight_of_new_value * 0.0;
215 } else {
216 alphaf = factorial[var_pow[0]];
217 *(delta+i) = weight_of_original_value * *(delta+i) + weight_of_new_value * 1./h * x_over_h_to_i[var_pow[0]]/alphaf;
218 }
219 i++;
220 }
221 }
222 });
223 }
224
225 /*! \brief Evaluates the second partial derivatives of scalar Taylor polynomial basis
226 * delta[j] = weight_of_original_value * delta[j] + weight_of_new_value * (calculation of this function)
227 \param delta [in/out] - scratch space that is allocated so that each thread has its own copy. Must be at least as large as the _basis_multipler*the dimension of the polynomial basis.
228 \param workspace [in/out] - scratch space that is allocated so that each thread has its own copy. Must be at least as large as the _poly_order*the spatial dimension of the polynomial basis.
229 \param dimension [in] - spatial dimension to evaluate
230 \param max_degree [in] - highest degree of polynomial
231 \param partial_direction_1 [in] - direction in which to take first partial derivative
232 \param partial_direction_2 [in] - direction in which to take second partial derivative
233 \param h [in] - epsilon/window size
234 \param x [in] - x coordinate (already shifted by target)
235 \param y [in] - y coordinate (already shifted by target)
236 \param z [in] - z coordinate (already shifted by target)
237 \param starting_order [in] - polynomial order to start with (default=0)
238 \param weight_of_original_value [in] - weighting to assign to original value in delta (default=0, replace, 1-increment current value)
239 \param weight_of_new_value [in] - weighting to assign to new contribution (default=1, add to/replace)
240 */
241 KOKKOS_INLINE_FUNCTION
242 void evaluateSecondPartialDerivative(const member_type& teamMember, double* delta, double* workspace, const int dimension, const int max_degree, const int partial_direction_1, const int partial_direction_2, const double h, const double x, const double y, const double z, const int starting_order = 0, const double weight_of_original_value = 0.0, const double weight_of_new_value = 1.0) {
243 Kokkos::single(Kokkos::PerThread(teamMember), [&] () {
244 const double factorial[] = {1, 1, 2, 6, 24, 120, 720, 5040, 40320, 362880, 3628800, 39916800, 479001600, 6227020800, 87178291200};
245 if (dimension==3) {
246 scratch_vector_type x_over_h_to_i(workspace, max_degree+1);
247 scratch_vector_type y_over_h_to_i(workspace+1*(max_degree+1), max_degree+1);
248 scratch_vector_type z_over_h_to_i(workspace+2*(max_degree+1), max_degree+1);
249 x_over_h_to_i[0] = 1;
250 y_over_h_to_i[0] = 1;
251 z_over_h_to_i[0] = 1;
252 for (int i=1; i<=max_degree; ++i) {
253 x_over_h_to_i[i] = x_over_h_to_i[i-1]*(x/h);
254 y_over_h_to_i[i] = y_over_h_to_i[i-1]*(y/h);
255 z_over_h_to_i[i] = z_over_h_to_i[i-1]*(z/h);
256 }
257 // (in 3D) \sum_{p=0}^{p=P} \sum_{k1+k2+k3=n} (x/h)^k1*(y/h)^k2*(z/h)^k3 / (k1!k2!k3!)
258 int alphax, alphay, alphaz;
259 double alphaf;
260 int i=0, s=0;
261 for (int n = starting_order; n <= max_degree; n++){
262 for (alphaz = 0; alphaz <= n; alphaz++){
263 s = n - alphaz;
264 for (alphay = 0; alphay <= s; alphay++){
265 alphax = s - alphay;
266
267 int var_pow[3] = {alphax, alphay, alphaz};
268 var_pow[partial_direction_1]--;
269 var_pow[partial_direction_2]--;
270
271 if (var_pow[0]<0 || var_pow[1]<0 || var_pow[2]<0) {
272 *(delta+i) = weight_of_original_value * *(delta+i) + weight_of_new_value * 0.0;
273 } else {
274 alphaf = factorial[var_pow[0]]*factorial[var_pow[1]]*factorial[var_pow[2]];
275 *(delta+i) = weight_of_original_value * *(delta+i) + weight_of_new_value * 1./h * x_over_h_to_i[var_pow[0]]*y_over_h_to_i[var_pow[1]]*z_over_h_to_i[var_pow[2]]/alphaf;
276 }
277 i++;
278 }
279 }
280 }
281 } else if (dimension==2) {
282 scratch_vector_type x_over_h_to_i(workspace, max_degree+1);
283 scratch_vector_type y_over_h_to_i(workspace+1*(max_degree+1), max_degree+1);
284 x_over_h_to_i[0] = 1;
285 y_over_h_to_i[0] = 1;
286 for (int i=1; i<=max_degree; ++i) {
287 x_over_h_to_i[i] = x_over_h_to_i[i-1]*(x/h);
288 y_over_h_to_i[i] = y_over_h_to_i[i-1]*(y/h);
289 }
290 // (in 3D) \sum_{p=0}^{p=P} \sum_{k1+k2+k3=n} (x/h)^k1*(y/h)^k2*(z/h)^k3 / (k1!k2!k3!)
291 int alphax, alphay;
292 double alphaf;
293 int i=0;
294 for (int n = starting_order; n <= max_degree; n++){
295 for (alphay = 0; alphay <= n; alphay++){
296 alphax = n - alphay;
297
298 int var_pow[2] = {alphax, alphay};
299 var_pow[partial_direction_1]--;
300 var_pow[partial_direction_2]--;
301
302 if (var_pow[0]<0 || var_pow[1]<0) {
303 *(delta+i) = weight_of_original_value * *(delta+i) + weight_of_new_value * 0.0;
304 } else {
305 alphaf = factorial[var_pow[0]]*factorial[var_pow[1]];
306 *(delta+i) = weight_of_original_value * *(delta+i) + weight_of_new_value * 1./h * x_over_h_to_i[var_pow[0]]*y_over_h_to_i[var_pow[1]]/alphaf;
307 }
308 i++;
309 }
310 }
311 } else {
312 scratch_vector_type x_over_h_to_i(workspace, max_degree+1);
313 x_over_h_to_i[0] = 1;
314 for (int i=1; i<=max_degree; ++i) {
315 x_over_h_to_i[i] = x_over_h_to_i[i-1]*(x/h);
316 }
317 int alphax;
318 double alphaf;
319 int i=0;
320 for (int n = starting_order; n <= max_degree; n++){
321 alphax = n;
322
323 int var_pow[1] = {alphax};
324 var_pow[partial_direction_1]--;
325 var_pow[partial_direction_2]--;
326
327 if (var_pow[0]<0) {
328 *(delta+i) = weight_of_original_value * *(delta+i) + weight_of_new_value * 0.0;
329 } else {
330 alphaf = factorial[var_pow[0]];
331 *(delta+i) = weight_of_original_value * *(delta+i) + weight_of_new_value * 1./h * x_over_h_to_i[var_pow[0]]/alphaf;
332 }
333 i++;
334 }
335 }
336 });
337 }
338
339} // ScalarTaylorPolynomialBasis
340
341} // Compadre
342
343#endif
KOKKOS_INLINE_FUNCTION void evaluate(const member_type &teamMember, double *delta, double *workspace, const int dimension, const int max_degree, const double h, const double x, const double y, const double z, const int starting_order=0, const double weight_of_original_value=0.0, const double weight_of_new_value=1.0)
Evaluates the scalar Taylor polynomial basis delta[j] = weight_of_original_value * delta[j] + weight_...
KOKKOS_INLINE_FUNCTION int getSize(const int degree, const int dimension)
Returns size of basis.
KOKKOS_INLINE_FUNCTION void evaluatePartialDerivative(const member_type &teamMember, double *delta, double *workspace, const int dimension, const int max_degree, const int partial_direction, const double h, const double x, const double y, const double z, const int starting_order=0, const double weight_of_original_value=0.0, const double weight_of_new_value=1.0)
Evaluates the first partial derivatives of scalar Taylor polynomial basis delta[j] = weight_of_origin...
KOKKOS_INLINE_FUNCTION void evaluateSecondPartialDerivative(const member_type &teamMember, double *delta, double *workspace, const int dimension, const int max_degree, const int partial_direction_1, const int partial_direction_2, const double h, const double x, const double y, const double z, const int starting_order=0, const double weight_of_original_value=0.0, const double weight_of_new_value=1.0)
Evaluates the second partial derivatives of scalar Taylor polynomial basis delta[j] = weight_of_origi...
Kokkos::View< double *, Kokkos::MemoryTraits< Kokkos::Unmanaged > > scratch_vector_type
team_policy::member_type member_type