10 #include "MooseUtils.h"
18 #define MAX_DIRECT_CALCULATION_ZERNIKE 10
23 const std::vector<std::size_t> & order,
30 else if (expansion_type ==
"sqrt_mu")
32 else if (expansion_type ==
"standard")
35 mooseError(
"The specified type of normalization for expansion does not exist");
39 else if (generation_type ==
"sqrt_mu")
41 else if (generation_type ==
"standard")
44 mooseError(
"The specified type of normalization for generation does not exist");
50 return ((order[0] + 1) * (order[0] + 2)) / 2;
60 if (bounds.size() != 3)
61 mooseError(
"Zernike: Invalid number of bounds specified for single series!");
72 const Real rho2 = rho * rho;
73 const Real rho4 = rho2 * rho2;
75 if (MooseUtils::absoluteFuzzyEqual(rho, 0.0))
77 for (n = 0; n <=
_orders[0]; n += 2)
82 save(j, -1 * (n + 1) / M_PI);
84 save(j, 1 * (n + 1) / M_PI);
93 case MAX_DIRECT_CALCULATION_ZERNIKE:
94 save(65, rho4 * rho4 * rho2
96 save(64, (10 * rho2 - 9) * rho4 * rho4
98 save(63, ((45 * rho2 - 72) * rho2 + 28) * rho4 * rho2
100 save(62, (((120 * rho2 - 252) * rho2 + 168) * rho2- 35) * rho4
102 save(61, ((((210 * rho2 - 504) * rho2 + 420) * rho2 - 140) * rho2 + 15) * rho2
104 save(60, (((((252 * rho2 - 630) * rho2 + 560) * rho2 - 210) * rho2 + 30) * rho2 - 1)
106 libmesh_fallthrough();
109 save(54, rho4 * rho4 * rho
111 save(53, (9 * rho2 - 8) * rho4 * rho2 * rho
113 save(52, ((36 * rho2 - 56) * rho2 + 21) * rho4 * rho
115 save(51, (((84 * rho2 - 168) * rho2 + 105) * rho2 - 20) * rho2 * rho
117 save(50, ((((126 * rho2 - 280) * rho2 + 210) * rho2 - 60) * rho2 + 5) * rho
119 libmesh_fallthrough();
124 save(43, (8 * rho2 - 7) * rho4 * rho2
126 save(42, ((28 * rho2 - 42) * rho2 + 15) * rho4
128 save(41, (((56 * rho2 - 105) * rho2 + 60) * rho2 - 10) * rho2
130 save(40, ((((70 * rho2 - 140) * rho2 + 90) * rho2 - 20) * rho2 + 1)
132 libmesh_fallthrough();
135 save(35, rho4 * rho2 * rho
137 save(34, (7 * rho2 - 6) * rho4 * rho
139 save(33, ((21 * rho2 - 30) * rho2 + 10) * rho2 * rho
141 save(32, (((35 * rho2 - 60) * rho2 + 30) * rho2 - 4) * rho
143 libmesh_fallthrough();
148 save(26, (6 * rho2 - 5) * rho4
150 save(25, ((15 * rho2 - 20) * rho2 + 6) * rho2
152 save(24, (((20 * rho2 - 30) * rho2 + 12) * rho2 - 1)
154 libmesh_fallthrough();
159 save(19, (5 * rho2 - 4) * rho2 * rho
161 save(18, ((10 * rho2 - 12) * rho2 + 3) * rho
163 libmesh_fallthrough();
168 save(13, (4 * rho2 - 3) * rho2
170 save(12, ((6 * rho2 - 6) * rho2 + 1)
172 libmesh_fallthrough();
177 save(8, (3 * rho2 - 2) * rho
179 libmesh_fallthrough();
184 save(4, (2 * rho2 - 1)
186 libmesh_fallthrough();
191 libmesh_fallthrough();
198 for (n = MAX_DIRECT_CALCULATION_ZERNIKE + 1; n <=
_orders[0]; ++n)
202 * (n + n + 2) / M_PI);
207 for (q = n; q >= 4; q -= 2)
209 H3 = (-4 * (q - 2) * (q - 3)) / ((n + q - 2) * (n - q + 4.0));
210 H2 = (H3 * (n + q) * (n - q + 2)) / (4.0 * (q - 1)) + (q - 2);
211 H1 = q * (q - 1) / 2 - q * H2 + (H3 * (n + q + 2) * (n - q)) / 8.0;
214 save(j, (H1 *
load(j + 2) + (H2 + H3 / rho2) *
load(j + 1))
217 save(j, H1 *
load(j + 2) + (H2 + H3 / rho2) *
load(j + 1));
231 for (
size_t n = 1; n <
_orders[0] + 1; ++n)
233 for (
size_t m = 0; m < n + 1; ++m)
235 if (m != 0 && n / m == 2 && n % m == 0)
236 save(j,
load(j) * std::sqrt((n + 1) / M_PI));
238 save(j,
load(j) * std::sqrt((2 * n + 2) / M_PI));
251 const Real rho2 = rho * rho;
252 const Real rho4 = rho2 * rho2;
254 if (MooseUtils::absoluteFuzzyLessEqual(rho, 0))
256 for (n = 0; n <=
_orders[0]; n += 2)
260 if ((n / 2) % 2 != 0)
272 case MAX_DIRECT_CALCULATION_ZERNIKE:
273 save(65, rho4 * rho4 * rho2);
274 save(64, (10 * rho2 - 9) * rho4 * rho4);
275 save(63, ((45 * rho2 - 72) * rho2 + 28) * rho4 * rho2);
276 save(62, (((120 * rho2 - 252) * rho2 + 168) * rho2 - 35) * rho4);
277 save(61, ((((210 * rho2 - 504) * rho2 + 420) * rho2 - 140) * rho2 + 15) * rho2);
278 save(60, ((((252 * rho2 - 630) * rho2 + 560) * rho2 - 210) * rho2 + 30) * rho2 - 1);
279 libmesh_fallthrough();
282 save(54, rho4 * rho4 * rho);
283 save(53, (9 * rho2 - 8) * rho4 * rho2 * rho);
284 save(52, ((36 * rho2 - 56) * rho2 + 21) * rho4 * rho);
285 save(51, (((84 * rho2 - 168) * rho2 + 105) * rho2 - 20) * rho2 * rho);
286 save(50, ((((126 * rho2 - 280) * rho2 + 210) * rho2 - 60) * rho2 + 5) * rho);
287 libmesh_fallthrough();
290 save(44, rho4 * rho4);
291 save(43, (8 * rho2 - 7) * rho4 * rho2);
292 save(42, ((28 * rho2 - 42) * rho2 + 15) * rho4);
293 save(41, (((56 * rho2 - 105) * rho2 + 60) * rho2 - 10) * rho2);
294 save(40, (((70 * rho2 - 140) * rho2 + 90) * rho2 - 20) * rho2 + 1);
295 libmesh_fallthrough();
298 save(35, rho4 * rho2 * rho);
299 save(34, (7 * rho2 - 6) * rho4 * rho);
300 save(33, ((21 * rho2 - 30) * rho2 + 10) * rho2 * rho);
301 save(32, (((35 * rho2 - 60) * rho2 + 30) * rho2 - 4) * rho);
302 libmesh_fallthrough();
305 save(27, rho4 * rho2);
306 save(26, (6 * rho2 - 5) * rho4);
307 save(25, ((15 * rho2 - 20) * rho2 + 6) * rho2);
308 save(24, ((20 * rho2 - 30) * rho2 + 12) * rho2 - 1);
309 libmesh_fallthrough();
312 save(20, rho4 * rho);
313 save(19, (5 * rho2 - 4) * rho2 * rho);
314 save(18, ((10 * rho2 - 12) * rho2 + 3) * rho);
315 libmesh_fallthrough();
319 save(13, (4 * rho2 - 3) * rho2);
320 save(12, (6 * rho2 - 6) * rho2 + 1);
321 libmesh_fallthrough();
325 save(8, (3 * rho2 - 2) * rho);
326 libmesh_fallthrough();
330 save(4, 2 * rho2 - 1);
331 libmesh_fallthrough();
335 libmesh_fallthrough();
341 for (n = MAX_DIRECT_CALCULATION_ZERNIKE + 1; n <=
_orders[0]; ++n)
349 for (q = n; q >= 4; q -= 2)
351 H3 = (-4 * (q - 2) * (q - 3)) / ((n + q - 2) * (n - q + 4.0));
352 H2 = (H3 * (n + q) * (n - q + 2)) / (4.0 * (q - 1)) + (q - 2);
353 H1 = q * (q - 1) / 2 - q * H2 + (H3 * (n + q + 2) * (n - q)) / 8.0;
355 save(j, H1 *
load(j + 2) + (H2 + H3 / rho2) *
load(j + 1));
370 for (n = 1; n <=
_orders[0]; ++n)
373 for (m = 0, q = a = n; m < q; ++m, --q, a -= 2)
375 save(j + m,
load(j + q) * sin(a * phi));
376 save(j + q,
load(j + q) * cos(a * phi));
381 const std::vector<Real> &
385 static const std::vector<Real> standardizedFunctionLimits = {0, 1, -M_PI, M_PI};
387 return standardizedFunctionLimits;
406 const Real standardizedRadius = sqrt(offset1 * offset1 + offset2 * offset2) / radius;
408 const Real theta = atan2(offset2, offset1);
410 return {standardizedRadius, theta};
429 if (standardized_location[0] > 1.0)
438 return (n * (n + 2) + m) / 2;