ngsolve 6.2.2501.post48.dev1__cp311-cp311-win_amd64.whl → 6.2.2501.post60.dev1__cp311-cp311-win_amd64.whl

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.

Potentially problematic release.


This version of ngsolve might be problematic. Click here for more details.

Files changed (42) hide show
  1. netgen/include/mptools.hpp +40 -1131
  2. netgen/include/ngblas.hpp +11 -1
  3. netgen/include/vector.hpp +8 -0
  4. netgen/lib/libngsolve.lib +0 -0
  5. netgen/libngsolve.dll +0 -0
  6. ngsolve/cmake/NGSolveConfig.cmake +1 -1
  7. ngsolve/config/config.py +5 -5
  8. ngsolve/ngslib.pyd +0 -0
  9. {ngsolve-6.2.2501.post48.dev1.dist-info → ngsolve-6.2.2501.post60.dev1.dist-info}/METADATA +2 -2
  10. {ngsolve-6.2.2501.post48.dev1.dist-info → ngsolve-6.2.2501.post60.dev1.dist-info}/RECORD +42 -42
  11. {ngsolve-6.2.2501.post48.dev1.data → ngsolve-6.2.2501.post60.dev1.data}/data/Scripts/ngsolve.tcl +0 -0
  12. {ngsolve-6.2.2501.post48.dev1.data → ngsolve-6.2.2501.post60.dev1.data}/data/share/ngsolve/beam.geo +0 -0
  13. {ngsolve-6.2.2501.post48.dev1.data → ngsolve-6.2.2501.post60.dev1.data}/data/share/ngsolve/beam.vol +0 -0
  14. {ngsolve-6.2.2501.post48.dev1.data → ngsolve-6.2.2501.post60.dev1.data}/data/share/ngsolve/chip.in2d +0 -0
  15. {ngsolve-6.2.2501.post48.dev1.data → ngsolve-6.2.2501.post60.dev1.data}/data/share/ngsolve/chip.vol +0 -0
  16. {ngsolve-6.2.2501.post48.dev1.data → ngsolve-6.2.2501.post60.dev1.data}/data/share/ngsolve/coil.geo +0 -0
  17. {ngsolve-6.2.2501.post48.dev1.data → ngsolve-6.2.2501.post60.dev1.data}/data/share/ngsolve/coil.vol +0 -0
  18. {ngsolve-6.2.2501.post48.dev1.data → ngsolve-6.2.2501.post60.dev1.data}/data/share/ngsolve/coilshield.geo +0 -0
  19. {ngsolve-6.2.2501.post48.dev1.data → ngsolve-6.2.2501.post60.dev1.data}/data/share/ngsolve/coilshield.vol +0 -0
  20. {ngsolve-6.2.2501.post48.dev1.data → ngsolve-6.2.2501.post60.dev1.data}/data/share/ngsolve/cube.geo +0 -0
  21. {ngsolve-6.2.2501.post48.dev1.data → ngsolve-6.2.2501.post60.dev1.data}/data/share/ngsolve/cube.vol +0 -0
  22. {ngsolve-6.2.2501.post48.dev1.data → ngsolve-6.2.2501.post60.dev1.data}/data/share/ngsolve/d10_DGdoubleglazing.pde +0 -0
  23. {ngsolve-6.2.2501.post48.dev1.data → ngsolve-6.2.2501.post60.dev1.data}/data/share/ngsolve/d11_chip_nitsche.pde +0 -0
  24. {ngsolve-6.2.2501.post48.dev1.data → ngsolve-6.2.2501.post60.dev1.data}/data/share/ngsolve/d1_square.pde +0 -0
  25. {ngsolve-6.2.2501.post48.dev1.data → ngsolve-6.2.2501.post60.dev1.data}/data/share/ngsolve/d2_chip.pde +0 -0
  26. {ngsolve-6.2.2501.post48.dev1.data → ngsolve-6.2.2501.post60.dev1.data}/data/share/ngsolve/d3_helmholtz.pde +0 -0
  27. {ngsolve-6.2.2501.post48.dev1.data → ngsolve-6.2.2501.post60.dev1.data}/data/share/ngsolve/d4_cube.pde +0 -0
  28. {ngsolve-6.2.2501.post48.dev1.data → ngsolve-6.2.2501.post60.dev1.data}/data/share/ngsolve/d5_beam.pde +0 -0
  29. {ngsolve-6.2.2501.post48.dev1.data → ngsolve-6.2.2501.post60.dev1.data}/data/share/ngsolve/d6_shaft.pde +0 -0
  30. {ngsolve-6.2.2501.post48.dev1.data → ngsolve-6.2.2501.post60.dev1.data}/data/share/ngsolve/d7_coil.pde +0 -0
  31. {ngsolve-6.2.2501.post48.dev1.data → ngsolve-6.2.2501.post60.dev1.data}/data/share/ngsolve/d8_coilshield.pde +0 -0
  32. {ngsolve-6.2.2501.post48.dev1.data → ngsolve-6.2.2501.post60.dev1.data}/data/share/ngsolve/d9_hybridDG.pde +0 -0
  33. {ngsolve-6.2.2501.post48.dev1.data → ngsolve-6.2.2501.post60.dev1.data}/data/share/ngsolve/doubleglazing.in2d +0 -0
  34. {ngsolve-6.2.2501.post48.dev1.data → ngsolve-6.2.2501.post60.dev1.data}/data/share/ngsolve/doubleglazing.vol +0 -0
  35. {ngsolve-6.2.2501.post48.dev1.data → ngsolve-6.2.2501.post60.dev1.data}/data/share/ngsolve/piezo2d40round4.vol.gz +0 -0
  36. {ngsolve-6.2.2501.post48.dev1.data → ngsolve-6.2.2501.post60.dev1.data}/data/share/ngsolve/shaft.geo +0 -0
  37. {ngsolve-6.2.2501.post48.dev1.data → ngsolve-6.2.2501.post60.dev1.data}/data/share/ngsolve/shaft.vol +0 -0
  38. {ngsolve-6.2.2501.post48.dev1.data → ngsolve-6.2.2501.post60.dev1.data}/data/share/ngsolve/square.in2d +0 -0
  39. {ngsolve-6.2.2501.post48.dev1.data → ngsolve-6.2.2501.post60.dev1.data}/data/share/ngsolve/square.vol +0 -0
  40. {ngsolve-6.2.2501.post48.dev1.dist-info → ngsolve-6.2.2501.post60.dev1.dist-info}/LICENSE +0 -0
  41. {ngsolve-6.2.2501.post48.dev1.dist-info → ngsolve-6.2.2501.post60.dev1.dist-info}/WHEEL +0 -0
  42. {ngsolve-6.2.2501.post48.dev1.dist-info → ngsolve-6.2.2501.post60.dev1.dist-info}/top_level.txt +0 -0
@@ -8,14 +8,14 @@
8
8
 
9
9
  #include <bla.hpp>
10
10
  #include <coefficient.hpp>
11
-
11
+ #include <recursive_pol.hpp>
12
12
 
13
13
  namespace ngfem
14
14
  {
15
15
 
16
16
 
17
17
 
18
- class SphericalHarmonics
18
+ class NGS_DLL_HEADER SphericalHarmonics
19
19
  {
20
20
  int order;
21
21
  Vector<Complex> coefs;
@@ -34,10 +34,10 @@ namespace ngfem
34
34
 
35
35
  auto CoefsN (int n) const
36
36
  {
37
- return FlatVector<Complex> (2*n+1, &coefs(n*(n+1)-n));
37
+ return coefs.RangeN(n*n, 2*n+1);
38
38
  }
39
39
 
40
- auto Polar (Vec<3> x) const
40
+ static std::tuple<double,double> Polar (Vec<3> x)
41
41
  {
42
42
  double phi, theta;
43
43
  if (x(0) == 0 && x(1) == 0)
@@ -50,7 +50,7 @@ namespace ngfem
50
50
  phi = atan2(x(1), x(0));
51
51
  theta = acos(x(2)/L2Norm(x));
52
52
  }
53
- return tuple{theta, phi};
53
+ return { theta, phi };
54
54
  }
55
55
 
56
56
  Complex Eval (Vec<3> x) const
@@ -59,36 +59,7 @@ namespace ngfem
59
59
  return Eval(theta, phi);
60
60
  }
61
61
 
62
- Complex Eval (double theta, double phi) const
63
- {
64
- static Timer t("mptool sh evaluate"); RegionTimer rg(t);
65
-
66
- Matrix legfunc(order+1, order+1);
67
- NormalizedLegendreFunctions (order, order, cos(theta), legfunc);
68
- Vector<Complex> exp_imphi(order+1);
69
- Complex exp_iphi(cos(phi), sin(phi));
70
- Complex prod = 1.0;
71
- for (int i = 0; i <= order; i++)
72
- {
73
- exp_imphi(i) = prod;
74
- prod *= -exp_iphi;
75
- }
76
-
77
- Complex sum = 0.0;
78
- int ii = 0;
79
- for (int n = 0; n <= order; n++)
80
- {
81
- for (int m = -n; m < 0; m++, ii++)
82
- sum += coefs(ii) * conj(exp_imphi(-m)) * legfunc(-m, n);
83
- for (int m = 0; m <= n; m++, ii++)
84
- sum += coefs(ii) * exp_imphi(m) * legfunc(m, n);
85
- }
86
-
87
- sum /= sqrt(4*M_PI);
88
- return sum;
89
- }
90
-
91
-
62
+ Complex Eval (double theta, double phi) const;
92
63
 
93
64
  Complex EvalOrder (int n, Vec<3> x) const
94
65
  {
@@ -96,39 +67,7 @@ namespace ngfem
96
67
  return EvalOrder(n, theta, phi);
97
68
  }
98
69
 
99
- Complex EvalOrder (int n, double theta, double phi) const
100
- {
101
- static Timer t("mptool sh evalorder");
102
-
103
- RegionTimer rg(t);
104
-
105
- Matrix legfunc(order+1, order+1);
106
- NormalizedLegendreFunctions (order, order, cos(theta), legfunc);
107
- Vector<Complex> exp_imphi(order+1);
108
- Complex exp_iphi(cos(phi), sin(phi));
109
- Complex prod = 1.0;
110
- for (int i = 0; i <= order; i++)
111
- {
112
- exp_imphi(i) = prod;
113
- prod *= -exp_iphi;
114
- }
115
-
116
- Complex sum = 0.0;
117
- auto coefsn = CoefsN(n);
118
- int ii = 0;
119
- // for (int n = 0; n <= order; n++)
120
- {
121
- for (int m = -n; m < 0; m++, ii++)
122
- sum += coefsn(ii) * conj(exp_imphi(-m)) * legfunc(-m, n);
123
- for (int m = 0; m <= n; m++, ii++)
124
- sum += coefsn(ii) * exp_imphi(m) * legfunc(m, n);
125
- }
126
-
127
- sum /= sqrt(4*M_PI);
128
- return sum;
129
- }
130
-
131
-
70
+ Complex EvalOrder (int n, double theta, double phi) const;
132
71
 
133
72
  void EvalOrders (Vec<3> x, FlatVector<Complex> vals) const
134
73
  {
@@ -136,99 +75,15 @@ namespace ngfem
136
75
  return EvalOrders(theta, phi, vals);
137
76
  }
138
77
 
139
- void EvalOrders (double theta, double phi, FlatVector<Complex> vals) const
140
- {
141
- static Timer ts("mptool sh evalorders small");
142
- static Timer tl("mptool sh evalorders large");
143
- // RegionTimer rg(order < 30 ? ts : tl);
144
- // if (order > 30) tl.Start();
145
-
146
- Matrix legfunc(order+1, order+1);
147
- NormalizedLegendreFunctions (order, order, cos(theta), legfunc);
148
- Vector<Complex> exp_imphi(order+1);
149
- Complex exp_iphi(cos(phi), sin(phi));
150
- Complex prod = 1.0;
151
- for (int i = 0; i <= order; i++)
152
- {
153
- exp_imphi(i) = prod;
154
- prod *= -exp_iphi;
155
- }
156
-
157
-
158
- for (int n = 0; n <= order; n++)
159
- {
160
- auto coefsn = CoefsN(n);
161
- int ii = 0;
162
-
163
- Complex sum = 0.0;
164
- for (int m = -n; m < 0; m++, ii++)
165
- sum += coefsn(ii) * conj(exp_imphi(-m)) * legfunc(-m, n);
166
- for (int m = 0; m <= n; m++, ii++)
167
- sum += coefsn(ii) * exp_imphi(m) * legfunc(m, n);
168
- vals(n) = sum;
169
- }
170
-
171
- vals /= sqrt(4*M_PI);
172
-
173
- // if (order > 30) tl.Stop();
174
- }
175
-
176
-
177
- void Calc (Vec<3> x, FlatVector<Complex> shapes)
178
- {
179
- auto [theta, phi] = Polar(x);
180
-
181
- Matrix legfunc(order+1, order+1);
182
- NormalizedLegendreFunctions (order, order, cos(theta), legfunc);
183
- Vector<Complex> exp_imphi(order+1);
184
- Complex exp_iphi(cos(phi), sin(phi));
185
- Complex prod = 1.0;
186
- for (int i = 0; i <= order; i++)
187
- {
188
- exp_imphi(i) = prod;
189
- prod *= -exp_iphi;
190
- }
191
-
192
- int ii = 0;
193
- for (int n = 0; n <= order; n++)
194
- {
195
- for (int m = -n; m < 0; m++, ii++)
196
- shapes(ii) = conj(exp_imphi(-m)) * legfunc(-m, n);
197
- for (int m = 0; m <= n; m++, ii++)
198
- shapes(ii) = exp_imphi(m) * legfunc(m, n);
199
- }
200
-
201
- shapes /= sqrt(4*M_PI);
202
- }
203
-
78
+ void EvalOrders (double theta, double phi, FlatVector<Complex> vals) const;
204
79
 
205
- void RotateZ (double alpha)
206
- {
207
- // static Timer t("mptool sh RotateZ"); RegionTimer rg(t);
208
- if (order < 0) return;
209
-
210
- Vector<Complex> exp_imalpha(order+1);
211
- Complex exp_ialpha(cos(alpha), sin(alpha));
212
- Complex prod = 1.0;
213
- for (int i = 0; i <= order; i++)
214
- {
215
- exp_imalpha(i) = prod;
216
- prod *= exp_ialpha;
217
- }
218
-
219
- int ii = 0;
220
- for (int n = 0; n <= order; n++)
221
- {
222
- for (int m = -n; m < 0; m++, ii++)
223
- coefs(ii) *= conj(exp_imalpha(-m));
224
- for (int m = 0; m <= n; m++, ii++)
225
- coefs(ii) *= exp_imalpha(m);
226
- }
227
- }
228
-
229
-
80
+ void Calc (Vec<3> x, FlatVector<Complex> shapes);
230
81
 
82
+
83
+ void RotateZ (double alpha);
84
+ void RotateY (double alpha);
231
85
 
86
+
232
87
  static double CalcAmn (int m, int n)
233
88
  {
234
89
  if (m < 0) m=-m;
@@ -249,388 +104,46 @@ namespace ngfem
249
104
  return sgn/2 * sqrt((n-m)*(n+m+1));
250
105
  }
251
106
 
252
-
253
- void RotateY (double alpha)
254
- {
255
- LocalHeap lh(8*6*sqr(order) + 8*15*order + 500);
256
-
257
- static Timer t("mptool sh RotateY"); RegionTimer rg(t);
258
-
259
- double s = sin(alpha);
260
- double c = cos(alpha);
261
-
262
- FlatMatrix<> normalized_leg_func(order+2, order+2, lh);
263
- NormalizedLegendreFunctions(order+1, order+1, c, normalized_leg_func);
264
-
265
- if (alpha < 0)
266
- for (int i = 1; i <= order+1; i+=2)
267
- normalized_leg_func.Row(i) *= -1;
268
-
269
- // cout << "leg = " << endl << normalized_leg_func << endl;
270
- FlatVector<> Dmn(2*order+1, lh);
271
-
272
- for (int n=1; n <= order; n++)
273
- {
274
- HeapReset hr(lh);
275
-
276
- FlatMatrix<double> trafo(n+1, 2*n+1, lh);
277
- /*
278
- Recursive Computation of Spherical Harmonic Rotation Coefficients of Large Degree
279
- Nail A. Gumerov and Ramani Duraiswami
280
- within Excursions in Harmonic Analysis, Volume 3
281
-
282
- page 130
283
- */
284
-
285
- // Step 2
286
- // H(0,m)
287
- trafo.Col(n) = 1.0/sqrt(2*n+1) * normalized_leg_func.Col(n).Range(n+1);
288
- for (int m = 1; m <= n; m += 2) trafo(m,n) *= -1;
289
- // Step 3
290
- // H(1,m)
291
- FlatVector<double> tmp = 1.0/sqrt(2*n+3) * normalized_leg_func.Col(n+1).Range(n+2) | lh;
292
- for (int m = 1; m < tmp.Size(); m += 2) tmp(m) *= -1;
293
- for (int m = 1; m <= n; m++)
294
- trafo.Col(n+1)(m) = 1/CalcBmn(0,n+1) * ( CalcBmn(-m-1, n+1)*(1-c)/2 * tmp(m+1)
295
- - CalcBmn(m-1,n+1)*(1+c)/2 * tmp(m-1)
296
- - CalcAmn(m,n) * s*tmp(m));
297
-
298
- // Step 4
299
- // diamond - recursion
300
- for (int mp = -n; mp <= n; mp++)
301
- Dmn(order+mp) = CalcDmn(mp, n);
302
-
303
- for (int mp = 1; mp < n; mp++)
304
- {
305
- double invDmn = 1.0 / Dmn(order+mp);
306
- for (int m = mp; m < n; m++)
307
- trafo(m, n+mp+1) = invDmn * ( Dmn(order+mp-1) *trafo(m ,n+mp-1)
308
- -Dmn(order+m-1)*trafo(m-1,n+mp)
309
- +Dmn(order+m) *trafo(m+1,n+mp));
310
- int m = n;
311
- trafo(m, n+mp+1) = invDmn * ( Dmn(order+mp-1,n)*trafo(m ,n+mp-1)
312
- -Dmn(order+m-1,n)*trafo(m-1,n+mp));
313
- }
314
-
315
- // Step 5
316
- // diamond - recursion, negative
317
- for (int mp = 0; mp > -n; mp--)
318
- {
319
- double invDmn = 1.0 / Dmn(order+mp-1);
320
- for (int m = -mp+1; m < n; m++)
321
- trafo(m, n+mp-1) = invDmn * ( Dmn(order+mp,n)*trafo(m ,n+mp+1)
322
- +Dmn(order+m-1,n)*trafo(m-1,n+mp)
323
- -Dmn(order+m ,n)*trafo(m+1,n+mp));
324
- int m = n;
325
- trafo(m, n+mp-1) = invDmn * ( Dmn(order+mp,n)*trafo(m ,n+mp+1)
326
- +Dmn(order+m-1,n)*trafo(m-1,n+mp));
327
- }
328
- // Step 6
329
- // symmetries in m and mp
330
- for (int m = 0; m <= n; m++)
331
- {
332
- auto dst = trafo.Row(m).Range(n+m, n+n+1);
333
- auto src = trafo.Col(n+m).Range(m, n+1);
334
- dst = src;
335
- }
336
- for (int m = 0; m <= n; m++)
337
- {
338
- auto dst = trafo.Row(m).Range(n-n, n-m+1).Reversed();
339
- auto src = trafo.Col(n-m).Range(m, n+1);
340
- dst = src;
341
- }
342
- /*
343
- double errortho = L2Norm( Matrix(trafo*Trans(trafo) - Identity(n+1)));
344
- if (errortho > 1e-10)
345
- {
346
- *testout << "n = " << n << " order = " << Order() << ", alpha = " << alpha << ", errortho = " << errortho << endl;
347
- if (n < 10)
348
- *testout << trafo*Trans(trafo) << endl;
349
- }
350
- */
351
-
352
- FlatVector<Complex> cn = CoefsN(n);
353
- FlatVector<Complex> old = cn | lh;
354
-
355
- cn = Trans(trafo) * old.Range(n, 2*n+1);
356
- cn.Slice(0,1).Reversed() += Trans(trafo.Rows(1,n+1)) * old.Range(0,n).Reversed();
107
+ // Nail A. Gumerov and Ramani Duraiswami book, formula (2.2.12)
108
+ // add directional derivative divided by kappa to res, both multipoles need same scaling
109
+ void DirectionalDiffAdd (Vec<3> d, SphericalHarmonics & res, double scale = 1);
357
110
 
358
- for (int m = 1; m <= n; m+=2)
359
- {
360
- cn(n+m) *= -1;
361
- cn(n-m) *= -1;
362
- }
363
- }
364
- }
365
-
366
111
  };
367
112
 
368
113
 
369
114
  // https://fortran-lang.discourse.group/t/looking-for-spherical-bessel-and-hankel-functions-of-first-and-second-kind-and-arbitrary-order/2308/2
115
+ NGS_DLL_HEADER
116
+ void besseljs3d (int nterms, double z, double scale,
117
+ FlatVector<double> fjs, FlatVector<double> fjder);
370
118
 
371
- // adapted from fmm3d
372
- template <typename Tz>
373
- void besseljs3d (int nterms, Tz z, double scale,
374
- FlatVector<Tz> fjs, FlatVector<Tz> fjder)
375
- {
376
- /*
377
- c**********************************************************************
378
- c
379
- c PURPOSE:
380
- c
381
- c This subroutine evaluates the first NTERMS spherical Bessel
382
- c functions and if required, their derivatives.
383
- c It incorporates a scaling parameter SCALE so that
384
- c
385
- c fjs_n(z)=j_n(z)/SCALE^n
386
- c fjder_n(z)=\frac{\partial fjs_n(z)}{\partial z}
387
- c
388
- c INPUT:
389
- c
390
- c nterms (integer): order of expansion of output array fjs
391
- c z (complex *16): argument of the spherical Bessel functions
392
- c scale (real *8) : scaling factor (discussed above)
393
- c ifder (integer): flag indicating whether to calculate "fjder"
394
- c 0 NO
395
- c 1 YES
396
- c OUTPUT:
397
- c fjs (complex *16): array of scaled Bessel functions.
398
- c fjder (complex *16): array of derivs of scaled Bessel functions.
399
- c
400
- c
401
- */
402
-
403
-
404
- // c ... Initializing ...
405
-
406
- // set to asymptotic values if argument is sufficiently small
407
- if (abs(z) < 1e-200)
408
- {
409
- fjs(0) = 1;
410
- for (int i = 1; i <= nterms; i++)
411
- fjs(i) = 0.0;
412
-
413
- if (fjder.Size())
414
- {
415
- fjder = 0.0;
416
- fjder(1) = 1.0/(3*scale);
417
- }
418
- return;
419
- }
420
-
421
-
422
- // ... Step 1: recursion up to find ntop, starting from nterms
423
-
424
- Tz zinv=1.0/z;
425
-
426
- Tz fjm1 = 0.0;
427
- Tz fj0 = 1.0;
119
+ NGS_DLL_HEADER
120
+ void besseljs3d (int nterms, Complex z, double scale,
121
+ FlatVector<Complex> fjs, FlatVector<Complex> fjder);
428
122
 
429
- /*
430
- c
431
- cc note max point for upward recurrence is
432
- c hard coded to nterms + 1000,
433
- c this might cause loss of accuracy for some
434
- c arguments in the complex plane for large
435
- c nterms. For example, it is a terrible idea
436
- c to use this code for z>>nterms^2
437
- */
438
123
 
439
- // int lwfjs = nterms + 100000;
440
- int ntop = nterms+1000;
441
-
442
- for (int i = nterms; ; i++)
443
- {
444
- double dcoef = 2*i+1.0;
445
- Tz fj1 = dcoef*zinv*fj0-fjm1;
446
- double dd = sqr(abs(fj1));
447
- if (dd > 1e40)
448
- {
449
- ntop=i+1;
450
- break;
451
- }
452
- fjm1 = fj0;
453
- fj0 = fj1;
454
- if (i > nterms+100000)
455
- throw Exception("bessel failed 1");
456
- }
457
-
458
- Array<bool> iscale(ntop+1);
459
- Vector<Tz> fjtmp(ntop+1);
460
-
461
124
  /*
462
- c ... Step 2: Recursion back down to generate the unscaled jfuns:
463
- c if magnitude exceeds UPBOUND2, rescale and continue the
464
- c recursion (saving the order at which rescaling occurred
465
- c in array iscale.
466
- */
467
-
468
- iscale = false;
469
-
470
- fjtmp(ntop) = 0.0;
471
- fjtmp(ntop-1) = 1.0;
472
- for (int i = ntop-1; i>=1; i--)
473
- {
474
- double dcoef = 2*i+1.0;
475
- fjtmp(i-1) = dcoef*zinv*fjtmp(i)-fjtmp(i+1);
476
- double dd = sqr(abs(fjtmp(i-1)));
477
- if (dd > 1e40)
478
- {
479
- fjtmp(i) *= 1e-40;
480
- fjtmp(i-1) *= 1e-40;
481
- iscale[i] = true;
482
- }
483
- }
484
-
485
- /*
486
- c
487
- c ... Step 3: go back up to the top and make sure that all
488
- c Bessel functions are scaled by the same factor
489
- c (i.e. the net total of times rescaling was invoked
490
- c on the way down in the previous loop).
491
- c At the same time, add scaling to fjs array.
492
- c
493
- */
494
-
495
- double scalinv = 1.0/scale;
496
- double sctot = 1.0;
497
- for (int i = 1; i <= ntop; i++)
498
- {
499
- sctot *= scalinv;
500
- if (iscale[i-1])
501
- sctot *= 1e-40;
502
- fjtmp(i) *= sctot;
503
- }
504
-
505
- // Determine the normalization parameter:
506
-
507
- fj0=sin(z)*zinv;
508
- Tz fj1=fj0*zinv-cos(z)*zinv;
509
-
510
- double d0=abs(fj0);
511
- double d1=abs(fj1);
512
- Tz zscale;
513
- if (d1 > d0)
514
- zscale=fj1/(fjtmp(1)*scale);
515
- else
516
- zscale=fj0/fjtmp(0);
517
-
518
- // Scale the jfuns by zscale:
519
-
520
- Tz ztmp=zscale;
521
- for (int i = 0; i <= nterms; i++)
522
- fjs(i)=fjtmp(i)*ztmp;
523
-
524
-
525
- // Finally, calculate the derivatives if desired:
526
-
527
- if (fjder.Size())
528
- {
529
- fjder(0) = -fjs(1)*scale;
530
- for (int i = 1; i <= nterms; i++)
531
- {
532
- double dc1=i/(2*i+1.0);
533
- double dc2=1.0-dc1;
534
- dc1=dc1*scalinv;
535
- dc2=dc2*scale;
536
- fjder(i)=(dc1*fjtmp(i-1)-dc2*fjtmp(i+1))*ztmp;
537
- }
538
- }
539
- }
540
-
541
-
542
-
543
-
544
- /*
545
- // from A. Barnett
546
- // http://www.fresco.org.uk/functions/barnett/index.htm
547
-
548
125
  spherical bessel functions of first (the j_n) and second (the y_n) kind.
549
-
126
+
550
127
  j0(r) = sin(r)/r
551
128
  j1(r) = (sin(r)-r cos(r)) / r**2
552
129
 
553
130
  y0(r) = -cos(r)/r
554
131
  y1(r) = (-cos(r)-r*sin(r)) / r**2
555
132
  */
133
+ NGS_DLL_HEADER
556
134
  void SBESJY (double x, int lmax,
557
135
  FlatVector<double> j,
558
136
  FlatVector<double> y,
559
137
  FlatVector<double> jp,
560
- FlatVector<double> yp)
561
- {
562
- if (x < 1e-8)
563
- {
564
- cout << "TODO: special treatment for small x" << endl;
565
- return;
566
- }
567
-
568
- double xinv = 1/x;
569
-
570
- if (lmax > 0)
571
- {
572
- double twoxi = 2*xinv;
573
- double sl = lmax*xinv;
574
- double tk = 2*sl+3*xinv;
575
- double cf1 = sl;
576
- double den = 1;
577
- if (abs(cf1) < 1e-8) cf1 = 1e-8;
578
- double c = cf1;
579
- double d = 0;
580
- for (int l = 1; l < 10000; l++)
581
- {
582
- c = tk-1/c;
583
- d = tk-d;
584
- if (abs(c) < 1e-8) c = 1e-8;
585
- if (abs(d) < 1e-8) d = 1e-8;
586
- d = 1/d;
587
- double dcf1 = d*c;
588
- cf1 *= dcf1;
589
- if (d < 0) den = -den;
590
- if (abs(dcf1-1) < 1e-10)
591
- break;
592
- tk += twoxi;
593
- // nfp = l;
594
- }
595
-
596
- j(lmax) = den;
597
- jp(lmax) = cf1*den;
598
- for (int l = lmax; l >= 1; l--)
599
- {
600
- j(l-1) = (sl+xinv)*j(l) + jp(l);
601
- sl = sl-xinv;
602
- jp(l-1) = sl*j(l-1) - j(l);
603
- }
604
- }
605
-
606
- double j0 = j(0);
607
- double jp0 = jp(0);
608
-
609
- // C------ CALCULATE THE L=0 SPHERICAL BESSEL FUNCTIONS DIRECTLY
610
- j(0) = xinv * sin(x);
611
- y(0) = -xinv * cos(x);
612
- jp(0) = -y(0)-xinv*j(0);
613
- yp(0) = j(0)-xinv*y(0);
614
-
615
- double omega = (abs(j0)>abs(jp0)) ? j(0)/j0 : jp(0) / jp0; // fix for x \approx 2 pi
616
- double sl = 0;
617
- for (int l = 1; l <=lmax; l++)
618
- {
619
- j(l) *= omega;
620
- jp(l) *= omega;
621
- y(l) = sl*y(l-1) - yp(l-1);
622
- sl += xinv;
623
- yp(l) = y(l-1) - (sl+xinv)*y(l);
624
- }
625
- }
626
-
138
+ FlatVector<double> yp);
627
139
 
628
140
 
141
+
629
142
  template <typename T>
630
143
  void SphericalBessel (int n, double rho, double scale, T && values)
631
144
  {
632
145
  Vector<double> j(n+1), jp(n+1);
633
- besseljs3d<double> (n, rho, scale, j, jp);
146
+ besseljs3d (n, rho, scale, j, jp);
634
147
  values = j;
635
148
  }
636
149
 
@@ -699,7 +212,7 @@ c
699
212
 
700
213
 
701
214
  template <typename RADIAL>
702
- class MultiPole
215
+ class NGS_DLL_HEADER MultiPole
703
216
  {
704
217
  SphericalHarmonics sh;
705
218
  double kappa;
@@ -730,80 +243,12 @@ c
730
243
  return *this;
731
244
  }
732
245
 
733
- Complex Eval (Vec<3> x) const
734
- {
735
- if (sh.Order() < 0) return 0;
736
-
737
- Vector<Complex> radial(sh.Order()+1);
738
- Vector<Complex> shvals(sh.Order()+1);
739
-
740
- RADIAL::Eval(sh.Order(), kappa*L2Norm(x), scale, radial);
741
- sh.EvalOrders (x, shvals);
742
-
743
- Complex sum = 0;
744
- for (int i = 0; i <= sh.Order(); i++)
745
- sum += shvals(i) * radial(i);
746
-
747
- return sum;
748
- }
749
-
750
- void AddCharge (Vec<3> x, Complex c)
751
- {
752
- if constexpr (!std::is_same<RADIAL,MPSingular>())
753
- throw Exception("AddCharge assumes singular MP");
754
-
755
- // static Timer t("mptool AddCharge"); RegionTimer rg(t);
756
-
757
- if (L2Norm(x) < 1e-10)
758
- {
759
- sh.Coef(0,0) += c * Complex(0,1)*kappa/sqrt(4*M_PI);
760
- return;
761
- }
762
-
763
- // cout << "add charge, kappa rho = " << kappa*L2Norm(x) << ", order = " << sh.Order() << endl;
764
-
765
- Vector<Complex> radial(sh.Order()+1);
766
- Vector<Complex> sh_shapes(sqr (sh.Order()+1));
767
-
768
- RADIAL::Eval(sh.Order(), kappa*L2Norm(x), 1.0/scale, radial);
769
- // cout << "radial = " << radial << endl;
770
- sh.Calc(x, sh_shapes);
771
-
772
- for (int i = 0; i <= sh.Order(); i++)
773
- {
774
- IntRange r(sqr(i), sqr(i+1));
775
- sh.Coefs().Range(r) += c * Complex(0,1)*kappa * radial(i).real()*Conj(sh_shapes.Range(r));
776
- }
777
- }
246
+ Complex Eval (Vec<3> x) const;
778
247
 
248
+ void AddCharge (Vec<3> x, Complex c);
249
+ void AddDipole (Vec<3> x, Vec<3> d, Complex c);
250
+
779
251
 
780
- void AddDipole (Vec<3> x, Vec<3> d, Complex c)
781
- {
782
- // static Timer t("mptool AddDipole"); RegionTimer rg(t);
783
- /*
784
- double eps = 1e-4;
785
- AddCharge(x+eps*d, -c/(2*eps));
786
- AddCharge(x-eps*d, c/(2*eps));
787
- return;
788
- */
789
-
790
- // book, formula (2.2.20)
791
- if constexpr (!std::is_same<RADIAL,MPSingular>())
792
- throw Exception("AddCharge assumes singular MP");
793
-
794
- // dipole in origin:
795
- MultiPole<MPSingular> tmp(1, kappa);
796
- tmp.SH().Coef(1,1) += Complex(0,1)*sqr(kappa)*sh.CalcBmn(-1,1)/(2*sqrt(4*M_PI)) * d(0)*c;
797
- tmp.SH().Coef(1,-1) += Complex(0,1)*sqr(kappa)*sh.CalcBmn(-1,1)/(2*sqrt(4*M_PI)) * d(0)*c;
798
-
799
- tmp.SH().Coef(1,1) += Complex(1,0)*sqr(kappa)*sh.CalcBmn(-1,1)/(2*sqrt(4*M_PI)) * d(1)*c;
800
- tmp.SH().Coef(1,-1) -= Complex(1,0)*sqr(kappa)*sh.CalcBmn(-1,1)/(2*sqrt(4*M_PI)) * d(1)*c;
801
-
802
- tmp.SH().Coef(1,0) += -Complex(0,1)*kappa*kappa*sh.CalcAmn(0,0)/sqrt(4*M_PI) *d(2)*c;
803
- tmp.TransformAdd (*this, -x);
804
- }
805
-
806
-
807
252
  void ChangeScaleTo (double newscale)
808
253
  {
809
254
  double fac = scale/newscale;
@@ -861,548 +306,8 @@ c
861
306
  target.SH().Coefs() += tmp.SH().Coefs();
862
307
  }
863
308
 
864
- #ifdef VER1
865
309
  template <typename TARGET>
866
- void ShiftZ (double z, MultiPole<TARGET> & target)
867
- {
868
- static Timer t("mptool ShiftZ"+ToString(typeid(RADIAL).name())+ToString(typeid(TARGET).name()));
869
-
870
- RegionTimer rg(t);
871
-
872
- int os = sh.Order();
873
- int ot = target.SH().Order();
874
-
875
- if (os > 100 && ot > 100 && abs(z)*kappa > 0.3*min(os,ot) && is_same<RADIAL,TARGET>())
876
- {
877
- MultiPole<TARGET> tmp {target};
878
- ShiftZ(z/2, tmp);
879
- tmp.ShiftZ(z/2, target);
880
- return;
881
- }
882
-
883
-
884
- target.SH().Coefs()=0.0;
885
-
886
- LocalHeap lh( 16*( (os+ot+1)*(os+1) + (os+1 + ot+1) ) + 8*2*(os+ot+1) + 500);
887
-
888
- FlatMatrix<Complex> trafo(os+ot+1, os+1, lh);
889
- FlatVector<Complex> hv1(os+1, lh), hv2(ot+1, lh);
890
- FlatVector<double> amn(os+ot+1, lh);
891
- FlatVector<double> inv_amn(os+ot+1, lh);
892
-
893
- // trafo = Complex(0.0);
894
-
895
-
896
- double tscale = target.Scale();
897
- double inv_tscale = 1.0/tscale;
898
-
899
-
900
- // (185) from paper 'fast, exact, stable, Gumerov+Duraiswami
901
- // RADIAL::Eval(os+ot, kappa*abs(z), trafo.Col(0));
902
- if (typeid(RADIAL) == typeid(TARGET))
903
- SphericalBessel (os+ot, kappa*abs(z), tscale, trafo.Col(0));
904
- else
905
- SphericalHankel1 (os+ot, kappa*abs(z), inv_tscale, trafo.Col(0));
906
-
907
- /*
908
- if (L2Norm(trafo.Col(0)) > 1e5 || std::isnan(L2Norm(trafo.Col(0))))
909
- {
910
- *testout << "large Hankel: " << L2Norm(trafo.Col(0)) << endl;
911
- *testout << "kappa z = " << kappa*z << ", os = " << os << ", ot = " << ot << endl;
912
- }
913
- */
914
- // if (L2Norm(trafo.Col(0)) > 1e5)
915
- // throw Exception ("z-shift - coefs large");
916
-
917
- if (z < 0)
918
- for (int l = 1; l < trafo.Height(); l+=2) trafo(l,0) *= -1;
919
-
920
- for (int l = 0; l <= os+ot; l++)
921
- trafo(l,0) *= sqrt(2*l+1);
922
-
923
- if (os > 0)
924
- {
925
- for (int l = 1; l < os+ot; l++)
926
- trafo(l,1) = -scale/sh.CalcAmn(0,0) * (sh.CalcAmn(0,l)*tscale*trafo(l+1,0)
927
- -sh.CalcAmn(0,l-1)*inv_tscale*trafo(l-1,0));
928
- trafo(0,1) = -scale*tscale*trafo(1,0);
929
- }
930
-
931
- for (int n = 1; n < os; n++)
932
- {
933
- for (int l = 1; l < os+ot-n; l++)
934
- trafo(l,n+1) = -scale/sh.CalcAmn(0,n) * (sh.CalcAmn(0,l)*tscale*trafo(l+1,n)
935
- -sh.CalcAmn(0,l-1)*inv_tscale*trafo(l-1,n)
936
- -sh.CalcAmn(0,n-1)*scale*trafo(l,n-1));
937
- trafo(0,n+1) = pow(-scale*tscale,n+1)*trafo(n+1,0);
938
- }
939
-
940
- cout << "m = " << 0 << endl
941
- << trafo.Rows(0,ot+1) << endl;
942
-
943
-
944
- for (int n = 0; n <= os; n++)
945
- hv1(n) = sh.Coef(n,0);
946
- hv2 = trafo.Rows(ot+1) * hv1;
947
- for (int n = 0; n <= ot; n++)
948
- target.SH().Coef(n,0) = hv2(n);
949
-
950
-
951
- for (int m = 1; m <= min(os,ot); m++)
952
- {
953
- // fill recursive formula (187)
954
- for (int l = m; l <= os+ot-m; l++)
955
- trafo(l,m) = scale/sh.CalcBmn(-m, m) * (sh.CalcBmn(-m, l)*inv_tscale*trafo(l-1, m-1)
956
- -sh.CalcBmn(m-1,l+1)*tscale*trafo(l+1,m-1));
957
-
958
-
959
- /*
960
- cout << "m = " << m << endl;
961
- cout << " norm col0 = " << L2Norm(trafo.Col(m).Range(m,os+ot-m+1)) << endl;
962
- */
963
-
964
- for (int l = m-1; l < os+ot-m; l++)
965
- {
966
- amn(l) = sh.CalcAmn(m,l);
967
- inv_amn(l) = scale/amn(l);
968
- }
969
-
970
- double prod = 1;
971
- for (int n = m; n < os; n++)
972
- {
973
- for (int l = m+1; l < os+ot-n; l++)
974
- trafo(l,n+1) = -inv_amn(n) * (amn(l)*tscale*trafo(l+1,n)
975
- -amn(l-1)*inv_tscale*trafo(l-1,n)
976
- -amn(n-1)*scale*trafo(l,n-1));
977
-
978
- prod *= -scale*tscale;
979
- trafo(m,n+1) = prod*trafo(n+1,m);
980
- }
981
-
982
- /*
983
- cout << " norm trafo = "
984
- << L2Norm(trafo.Rows(m,ot+1).Cols(m,os+1))
985
- << " ortho " << L2Norm( Trans(trafo.Rows(m,ot+1).Cols(m,os+1))*trafo.Rows(m,ot+1).Cols(m,os+1)
986
- - Identity(os+1-m)) << endl;
987
- */
988
- /*
989
- *testout << "norm trafo = " << L2Norm(trafo.Rows(m, ot+1).Cols(m,os+1)) << endl;
990
- if ( L2Norm(trafo.Rows(m, ot+1).Cols(m,os+1)) > 1e30)
991
- {
992
- *testout << trafo.Rows(m, ot+1).Cols(m,os+1) << endl;
993
- for (int i = m; i < os+1; i++)
994
- {
995
- *testout << "norm col " << i << " = " << L2Norm(trafo.Col(i).Range(m,os+ot-i)) << endl;
996
- *testout << "col " << i << " = " << trafo.Col(i).Range(m,os+ot-i) << endl;
997
- }
998
- throw Exception("large mat");
999
- }
1000
- */
1001
-
1002
- cout << "m = " << m << endl
1003
- << trafo.Rows(m,ot+1).Cols(m,os+1) << endl;
1004
-
1005
- for (int n = m; n <= os; n++)
1006
- hv1(n) = sh.Coef(n,m);
1007
- hv2.Range(m,ot+1) = trafo.Rows(m,ot+1).Cols(m,os+1) * hv1.Range(m,os+1);
1008
- for (int n = m; n <= ot; n++)
1009
- target.SH().Coef(n,m) = hv2(n);
1010
-
1011
- for (int n = m; n <= os; n++)
1012
- hv1(n) = sh.Coef(n,-m);
1013
- hv2.Range(m,ot+1) = trafo.Rows(m,ot+1).Cols(m,os+1) * hv1.Range(m,os+1);
1014
- for (int n = m; n <= ot; n++)
1015
- target.SH().Coef(n,-m) = hv2(n);
1016
- }
1017
- }
1018
- #endif
1019
-
1020
-
1021
- #ifdef VER2
1022
-
1023
- template <typename TARGET>
1024
- void ShiftZ (double z, MultiPole<TARGET> & target)
1025
- {
1026
- static Timer t("mptool ShiftZ"+ToString(typeid(RADIAL).name())+ToString(typeid(TARGET).name()));
1027
- RegionTimer rg(t);
1028
-
1029
- int os = sh.Order();
1030
- int ot = target.SH().Order();
1031
-
1032
- target.SH().Coefs()=0.0;
1033
-
1034
- LocalHeap lh( 16*( (os+ot+1)*(os+1) + (os+1 + ot+1) ) + 8*2*(os+ot+1) + 500);
1035
-
1036
- FlatMatrix<Complex> trafo(os+ot+1, os+1, lh);
1037
- FlatVector<Complex> hv1(os+1, lh), hv2(ot+1, lh);
1038
- FlatVector<double> amn(os+ot+1, lh);
1039
- FlatVector<double> inv_amn(os+ot+1, lh);
1040
-
1041
- // trafo = Complex(0.0);
1042
-
1043
- double tscale = target.Scale();
1044
- double inv_tscale = 1.0/tscale;
1045
-
1046
-
1047
- // (185) from paper 'fast, exact, stable, Gumerov+Duraiswami
1048
- // RADIAL::Eval(os+ot, kappa*abs(z), trafo.Col(0));
1049
- if (typeid(RADIAL) == typeid(TARGET))
1050
- SphericalBessel (os+ot, kappa*abs(z), tscale, trafo.Col(0));
1051
- else
1052
- SphericalHankel1 (os+ot, kappa*abs(z), inv_tscale, trafo.Col(0));
1053
-
1054
- if (z < 0)
1055
- for (int l = 1; l < trafo.Height(); l+=2) trafo(l,0) *= -1;
1056
-
1057
- // for (int l = 0; l <= os+ot; l++)
1058
- // trafo(l,0) *= sqrt(2*l+1);
1059
-
1060
- if (os > 0)
1061
- {
1062
- for (int l = 1; l < os+ot; l++)
1063
- {
1064
- /*
1065
- trafo(l,1) = -scale/sh.CalcAmn(0,0) *
1066
- (sh.CalcAmn(0,l)*tscale*trafo(l+1,0)
1067
- -sh.CalcAmn(0,l-1)*inv_tscale*trafo(l-1,0));
1068
- */
1069
-
1070
- int m = 0, n = 0;
1071
- double fac = ((2*l+1.0)/(2*n+1.0));
1072
- trafo(l,n+1) = -scale/ ( sqrt((n+1+m)*(n+1-m)) * fac) *
1073
- (sqrt( (l+1+m)*(l+1-m)) * tscale * trafo(l+1,n)
1074
- -sqrt( (l+m)*(l-m) ) * inv_tscale * trafo(l-1,n)
1075
- -sqrt( (n+m)*(n-m) ) * fac * scale * trafo(l,n-1));
1076
- }
1077
- trafo(0,1) = -scale*tscale*trafo(1,0);
1078
- }
1079
-
1080
- for (int n = 1; n < os; n++)
1081
- {
1082
- for (int l = 1; l < os+ot-n; l++)
1083
- {
1084
- /*
1085
- trafo(l,n+1) = -scale/sh.CalcAmn(0,n) * (sh.CalcAmn(0,l)*tscale*trafo(l+1,n)
1086
- -sh.CalcAmn(0,l-1)*inv_tscale*trafo(l-1,n)
1087
- -sh.CalcAmn(0,n-1)*scale*trafo(l,n-1));
1088
- */
1089
-
1090
- int m = 0;
1091
- double fac = ((2*l+1.0)/(2*n+1.0));
1092
- trafo(l,n+1) = -scale / ( sqrt((n+1+m)*(n+1-m)) * fac) *
1093
- (sqrt( (l+1+m)*(l+1-m)) * tscale * trafo(l+1,n)
1094
- -sqrt( (l+m)*(l-m) ) * inv_tscale * trafo(l-1,n)
1095
- -sqrt( (n+m)*(n-m) ) * fac * scale * trafo(l,n-1));
1096
- }
1097
- trafo(0,n+1) = pow(-scale*tscale,n+1)*trafo(n+1,0);
1098
- }
1099
-
1100
-
1101
- Matrix<Complex> scaledtrafo(os+ot+1, os+1);
1102
- for (int l = 0; l <= os+ot; l++)
1103
- for (int n = 0; n <= os; n++)
1104
- scaledtrafo(l,n) = trafo(l,n) * sqrt( (2*l+1)*(2*n+1) );
1105
-
1106
- // cout << "m = " << 0 << endl
1107
- // << scaledtrafo.Rows(0,ot+1) << endl;
1108
-
1109
- for (int n = 0; n <= os; n++)
1110
- hv1(n) = sh.Coef(n,0) * sqrt(2*n+1);
1111
- hv2 = trafo.Rows(ot+1) * hv1;
1112
- for (int n = 0; n <= ot; n++)
1113
- target.SH().Coef(n,0) = hv2(n) * sqrt(2*n+1);
1114
-
1115
-
1116
- for (int m = 1; m <= min(os,ot); m++)
1117
- {
1118
- // fill recursive formula (187)
1119
- for (int l = m; l <= os+ot-m; l++)
1120
- {
1121
- trafo(l,m) = scale/sh.CalcBmn(-m, m) *
1122
- (sh.CalcBmn(-m, l)*inv_tscale * trafo(l-1, m-1) * sqrt( (2*l-1)*(2*m-1) )
1123
- -sh.CalcBmn(m-1,l+1)*tscale * trafo(l+1,m-1) * sqrt( (2*l+3)*(2*m-1)) );
1124
- trafo(l,m) /= sqrt( (2*l+1)*(2*m+1) );
1125
- }
1126
-
1127
- cout << "m = " << m << endl;
1128
- cout << " norm col0 = " << L2Norm(trafo.Col(m).Range(m,os+ot-m+1)) << endl;
1129
-
1130
- for (int l = m-1; l < os+ot-m; l++)
1131
- {
1132
- amn(l) = sh.CalcAmn(m,l);
1133
- inv_amn(l) = scale/amn(l);
1134
- }
1135
-
1136
- double prod = 1;
1137
- for (int n = m; n < os; n++)
1138
- {
1139
- for (int l = m+1; l < os+ot-n; l++)
1140
- {
1141
- /*
1142
- trafo(l,n+1) = -inv_amn(n) * (amn(l)*tscale*trafo(l+1,n)
1143
- -amn(l-1)*inv_tscale*trafo(l-1,n)
1144
- -amn(n-1)*scale*trafo(l,n-1));
1145
- */
1146
-
1147
-
1148
- double fac = ((2*l+1.0)/(2*n+1.0));
1149
- trafo(l,n+1) = -scale / ( sqrt((n+1+m)*(n+1-m)) * fac) *
1150
- (sqrt( (l+1+m)*(l+1-m)) * tscale * trafo(l+1,n)
1151
- -sqrt( (l+m)*(l-m) ) * inv_tscale * trafo(l-1,n)
1152
- -sqrt( (n+m)*(n-m) ) * fac * scale * trafo(l,n-1));
1153
- }
1154
- prod *= -scale*tscale;
1155
- trafo(m,n+1) = prod*trafo(n+1,m);
1156
- }
1157
-
1158
- double normleft = 0;
1159
- for (int l = m; l <= ot; l++)
1160
- for (int n = m; n <= min(l,os); n++)
1161
- normleft += sqr(abs(trafo(l,n)));
1162
- normleft = sqrt(normleft);
1163
- cout << " norm trafo = "
1164
- << L2Norm(trafo.Rows(m,ot+1).Cols(m,os+1)) << ", normleft = " << normleft << endl;
1165
-
1166
- // << " ortho " << L2Norm( Trans(trafo.Rows(m,ot+1).Cols(m,os+1))*trafo.Rows(m,ot+1).Cols(m,os+1)
1167
- // - Identity(os+1-m)) << endl;
1168
- /*
1169
- *testout << "norm trafo = " << L2Norm(trafo.Rows(m, ot+1).Cols(m,os+1)) << endl;
1170
- if ( L2Norm(trafo.Rows(m, ot+1).Cols(m,os+1)) > 1e30)
1171
- {
1172
- *testout << trafo.Rows(m, ot+1).Cols(m,os+1) << endl;
1173
- for (int i = m; i < os+1; i++)
1174
- {
1175
- *testout << "norm col " << i << " = " << L2Norm(trafo.Col(i).Range(m,os+ot-i)) << endl;
1176
- *testout << "col " << i << " = " << trafo.Col(i).Range(m,os+ot-i) << endl;
1177
- }
1178
- throw Exception("large mat");
1179
- }
1180
- */
1181
-
1182
-
1183
- /*
1184
- Matrix<Complex> scaledtrafo(os+ot+1, os+1);
1185
- for (int l = 0; l <= os+ot; l++)
1186
- for (int n = 0; n <= os; n++)
1187
- scaledtrafo(l,n) = trafo(l,n) * sqrt( (2*l+1)*(2*n+1) );
1188
-
1189
- cout << "m = " << m << endl
1190
- << scaledtrafo.Rows(m,ot+1).Cols(m,os+1) << endl;
1191
- */
1192
-
1193
- for (int n = m; n <= os; n++)
1194
- hv1(n) = sh.Coef(n,m) * sqrt(2*n+1);
1195
- hv2.Range(m,ot+1) = trafo.Rows(m,ot+1).Cols(m,os+1) * hv1.Range(m,os+1);
1196
- for (int n = m; n <= ot; n++)
1197
- target.SH().Coef(n,m) = hv2(n)*sqrt(2*n+1);
1198
-
1199
- for (int n = m; n <= os; n++)
1200
- hv1(n) = sh.Coef(n,-m) * sqrt(2*n+1);
1201
- hv2.Range(m,ot+1) = trafo.Rows(m,ot+1).Cols(m,os+1) * hv1.Range(m,os+1);
1202
- for (int n = m; n <= ot; n++)
1203
- target.SH().Coef(n,-m) = hv2(n) * sqrt(2*n+1);
1204
- }
1205
- }
1206
- #endif
1207
-
1208
-
1209
-
1210
-
1211
- template <typename TARGET>
1212
- void ShiftZ (double z, MultiPole<TARGET> & target)
1213
- {
1214
- static Timer t("mptool ShiftZ"+ToString(typeid(RADIAL).name())+ToString(typeid(TARGET).name()));
1215
- RegionTimer rg(t);
1216
-
1217
- int os = sh.Order();
1218
- int ot = target.SH().Order();
1219
-
1220
- target.SH().Coefs()=0.0;
1221
-
1222
- LocalHeap lh( 32*( (os+ot+1)*(os+ot+1) + (os+1 + ot+1) ) + 8*3*(os+ot+1) + 500);
1223
-
1224
- FlatMatrix<Complex> trafo(os+ot+1, max(os,ot)+1, lh);
1225
- FlatMatrix<Complex> oldtrafo(os+ot+1, max(os,ot)+1, lh);
1226
- FlatVector<Complex> hv1(os+1, lh), hv2(ot+1, lh);
1227
-
1228
- // trafo = Complex(0.0);
1229
-
1230
- double tscale = target.Scale();
1231
- double inv_tscale = 1.0/tscale;
1232
-
1233
- FlatVector<double> amn(os+ot+1, lh);
1234
- FlatVector<double> inv_amn(os+ot+1, lh);
1235
-
1236
- FlatVector<double> powscale(os+1, lh);
1237
- double prod = 1;
1238
- for (int i = 0; i <= os; i++)
1239
- {
1240
- powscale(i) = prod;
1241
- prod *= -scale*tscale;
1242
- }
1243
-
1244
- // (185) from paper 'fast, exact, stable, Gumerov+Duraiswami
1245
- // RADIAL::Eval(os+ot, kappa*abs(z), trafo.Col(0));
1246
- if (typeid(RADIAL) == typeid(TARGET))
1247
- SphericalBessel (os+ot, kappa*abs(z), tscale, trafo.Col(0));
1248
- else
1249
- SphericalHankel1 (os+ot, kappa*abs(z), inv_tscale, trafo.Col(0));
1250
-
1251
- if (z < 0)
1252
- for (int l = 1; l < trafo.Height(); l+=2) trafo(l,0) *= -1;
1253
-
1254
- for (int l = 0; l <= os+ot; l++)
1255
- trafo(l,0) *= sqrt(2*l+1);
1256
-
1257
- // for (int l = 0; l <= os+ot; l++)
1258
- // trafo(l,0) *= sqrt(2*l+1);
1259
-
1260
- if (os > 0)
1261
- {
1262
- for (int l = 1; l < os+ot; l++)
1263
- trafo(l,1) = -scale/sh.CalcAmn(0,0) * (sh.CalcAmn(0,l)*tscale*trafo(l+1,0)
1264
- -sh.CalcAmn(0,l-1)*inv_tscale*trafo(l-1,0));
1265
- trafo(0,1) = -scale*tscale*trafo(1,0);
1266
- }
1267
-
1268
- for (int n = 1; n < trafo.Width()-1; n++)
1269
- {
1270
- for (int l = 1; l < os+ot-n; l++)
1271
- trafo(l,n+1) = -scale/sh.CalcAmn(0,n) * (sh.CalcAmn(0,l)*tscale*trafo(l+1,n)
1272
- -sh.CalcAmn(0,l-1)*inv_tscale*trafo(l-1,n)
1273
- -sh.CalcAmn(0,n-1)*scale*trafo(l,n-1));
1274
- trafo(0,n+1) = pow(-scale*tscale,n+1)*trafo(n+1,0);
1275
- }
1276
-
1277
- for (int n = 0; n <= os; n++)
1278
- hv1(n) = sh.Coef(n,0);
1279
- hv2 = trafo.Rows(ot+1).Cols(os+1) * hv1;
1280
- for (int n = 0; n <= ot; n++)
1281
- target.SH().Coef(n,0) = hv2(n);
1282
-
1283
-
1284
- for (int m = 1; m <= min(os,ot); m++)
1285
- {
1286
-
1287
-
1288
- for (int l = m-1; l < os+ot-m; l++)
1289
- {
1290
- amn(l) = sh.CalcAmn(m,l);
1291
- inv_amn(l) = scale/amn(l);
1292
- }
1293
-
1294
- if (typeid(RADIAL) != typeid(TARGET))
1295
-
1296
- {
1297
- // fill recursive formula (187)
1298
- for (int l = m; l <= os+ot-m; l++)
1299
- trafo(l,m) = scale/sh.CalcBmn(-m, m) * (sh.CalcBmn(-m, l)*inv_tscale*trafo(l-1, m-1)
1300
- -sh.CalcBmn(m-1,l+1)*tscale*trafo(l+1,m-1));
1301
-
1302
- for (int n = m; n < os; n++)
1303
- {
1304
- for (int l = n+1; l < os+ot-n; l++)
1305
- trafo(l,n+1) = -inv_amn(n) * (amn(l)*tscale*trafo(l+1,n)
1306
- -amn(l-1)*inv_tscale*trafo(l-1,n)
1307
- -amn(n-1)*scale*trafo(l,n-1));
1308
- }
1309
- }
1310
-
1311
- else
1312
-
1313
- {
1314
- /*
1315
- for (int n = m; n < trafo.Width()-1; n++)
1316
- {
1317
- for (int l = n+1; l < os+ot-n; l++)
1318
- trafo(l,n+1) = -inv_amn(n) * (amn(l)*tscale*trafo(l+1,n)
1319
- -amn(l-1)*inv_tscale*trafo(l-1,n)
1320
- -amn(n-1)*scale*trafo(l,n-1));
1321
- }
1322
- */
1323
-
1324
- trafo.Swap (oldtrafo);
1325
- trafo = 0.0;
1326
-
1327
- // fill recursive formula (187)
1328
- for (int l = m; l <= os+ot-m; l++)
1329
- trafo(l,m) = scale/sh.CalcBmn(-m, m) * (sh.CalcBmn(-m, l)*inv_tscale*oldtrafo(l-1, m-1)
1330
- -sh.CalcBmn(m-1,l+1)*tscale*oldtrafo(l+1,m-1));
1331
-
1332
- for (int n = m; n < trafo.Width()-1; n++)
1333
- {
1334
- // int l = 2*order-n-1;
1335
- int l = trafo.Height()-n-2;
1336
-
1337
- trafo(l,n+1) = scale/sh.CalcBmn(-m,n+1)* (sh.CalcBmn(m-1,n) * scale*trafo(l,n-1)
1338
- - sh.CalcBmn(m-1,l+1)*tscale*oldtrafo(l+1,n)
1339
- + sh.CalcBmn(-m,l) * 1/tscale*oldtrafo(l-1,n) );
1340
-
1341
- trafo(l-1,n) = tscale/amn(l-1) * (amn(l) * tscale*trafo(l+1,n)
1342
- - amn(n-1)* scale*trafo(l,n-1)
1343
- + amn(n)* 1/scale*trafo(l,n+1));
1344
- }
1345
-
1346
- // the same thing 1 row up
1347
- for (int n = m; n < trafo.Width()-2; n++)
1348
- {
1349
- // int l = 2*order-n-2;
1350
- int l = trafo.Height()-n-3;
1351
-
1352
- trafo(l,n+1) = scale/sh.CalcBmn(-m,n+1)* (sh.CalcBmn(m-1,n) * scale*trafo(l,n-1)
1353
- - sh.CalcBmn(m-1,l+1) * tscale* oldtrafo(l+1,n)
1354
- + sh.CalcBmn(-m,l) * 1/tscale* oldtrafo(l-1,n) );
1355
-
1356
- trafo(l-1,n) = tscale/amn(l-1) * (amn(l) * tscale*trafo(l+1,n)
1357
- -amn(n-1)* scale*trafo(l,n-1) +
1358
- amn(n) * 1/scale*trafo(l,n+1)) ;
1359
- }
1360
-
1361
-
1362
- // for (int l = 2*order; l >= m; l--)
1363
- // for (int n = m+1; n < min(2*order-l,l); n++)
1364
- for (int l = trafo.Height()-1; l >= m; l--)
1365
- for (int n = m+1; n < min<int>(trafo.Height()-1-l,l); n++)
1366
- {
1367
- trafo(l-1,n) = tscale/amn(l-1)* ( amn(l) * tscale*trafo(l+1,n)
1368
- -amn(n-1)* scale*trafo(l,n-1)
1369
- +amn(n) * 1/scale*trafo(l,n+1)) ;
1370
- }
1371
- }
1372
-
1373
-
1374
- /*
1375
- cout << "m = " << m << endl
1376
- << trafo << endl;
1377
- */
1378
- for (int n = m; n < os; n++)
1379
- for (int l = n+1; l <= os; l++)
1380
- trafo(n,l) = powscale(l-n) * trafo(l,n);
1381
- // trafo(n,l) = pow(-scale*tscale, l-n) * trafo(l,n);
1382
-
1383
- /*
1384
- cout << " norm trafo = "
1385
- << L2Norm(trafo.Rows(m,ot+1).Cols(m,os+1)) << endl;
1386
- */
1387
-
1388
- for (int n = m; n <= os; n++)
1389
- hv1(n) = sh.Coef(n,m);
1390
- hv2.Range(m,ot+1) = trafo.Rows(m,ot+1).Cols(m,os+1) * hv1.Range(m,os+1);
1391
- for (int n = m; n <= ot; n++)
1392
- target.SH().Coef(n,m) = hv2(n);
1393
-
1394
- for (int n = m; n <= os; n++)
1395
- hv1(n) = sh.Coef(n,-m);
1396
- hv2.Range(m,ot+1) = trafo.Rows(m,ot+1).Cols(m,os+1) * hv1.Range(m,os+1);
1397
- for (int n = m; n <= ot; n++)
1398
- target.SH().Coef(n,-m) = hv2(n);
1399
- }
1400
- }
1401
-
1402
-
1403
-
1404
-
1405
-
310
+ void ShiftZ (double z, MultiPole<TARGET> & target);
1406
311
 
1407
312
  };
1408
313
 
@@ -1712,7 +617,7 @@ c
1712
617
  }
1713
618
 
1714
619
 
1715
- class RegularMLMultiPole
620
+ class NGS_DLL_HEADER RegularMLMultiPole
1716
621
  {
1717
622
  static Array<size_t> nodes_on_level;
1718
623
 
@@ -2034,11 +939,15 @@ c
2034
939
 
2035
940
  };
2036
941
 
2037
- Array<size_t> RegularMLMultiPole::nodes_on_level(100);
2038
- Array<size_t> SingularMLMultiPole::nodes_on_level(100);
2039
942
 
943
+
944
+
945
+
946
+
947
+
2040
948
  // ******************** Coefficient Functions *********************
2041
949
 
950
+
2042
951
  class SphericalHarmonicsCF : public CoefficientFunction
2043
952
  {
2044
953
  SphericalHarmonics sh;