ngsolve 6.2.2501.post55.dev1__cp313-cp313-macosx_10_15_universal2.whl → 6.2.2501.post70.dev1__cp313-cp313-macosx_10_15_universal2.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.
- netgen/include/ectypes.hpp +121 -0
- netgen/include/h1lofe.hpp +3 -0
- netgen/include/mptools.hpp +86 -1176
- netgen/include/vector.hpp +8 -0
- netgen/libngbla.dylib +0 -0
- netgen/libngcomp.dylib +0 -0
- netgen/libngfem.dylib +0 -0
- netgen/libngla.dylib +0 -0
- netgen/libngstd.dylib +0 -0
- ngsolve/__init__.pyi +3 -3
- ngsolve/cmake/NGSolveConfig.cmake +1 -1
- ngsolve/config/__init__.pyi +6 -6
- ngsolve/config/config.py +5 -5
- ngsolve/config/config.pyi +6 -6
- ngsolve/directsolvers.pyi +1 -1
- ngsolve/fem.pyi +20 -3
- ngsolve/krylovspace.pyi +2 -2
- ngsolve/nonlinearsolvers.pyi +1 -1
- ngsolve/timestepping.pyi +3 -3
- ngsolve/timing.pyi +1 -1
- ngsolve/utils.pyi +3 -2
- {ngsolve-6.2.2501.post55.dev1.dist-info → ngsolve-6.2.2501.post70.dev1.dist-info}/METADATA +1 -1
- {ngsolve-6.2.2501.post55.dev1.dist-info → ngsolve-6.2.2501.post70.dev1.dist-info}/RECORD +59 -58
- {ngsolve-6.2.2501.post55.dev1.data → ngsolve-6.2.2501.post70.dev1.data}/data/Netgen.icns +0 -0
- {ngsolve-6.2.2501.post55.dev1.data → ngsolve-6.2.2501.post70.dev1.data}/data/bin/ngscxx +0 -0
- {ngsolve-6.2.2501.post55.dev1.data → ngsolve-6.2.2501.post70.dev1.data}/data/bin/ngsld +0 -0
- {ngsolve-6.2.2501.post55.dev1.data → ngsolve-6.2.2501.post70.dev1.data}/data/bin/ngsolve.tcl +0 -0
- {ngsolve-6.2.2501.post55.dev1.data → ngsolve-6.2.2501.post70.dev1.data}/data/bin/ngspy +0 -0
- {ngsolve-6.2.2501.post55.dev1.data → ngsolve-6.2.2501.post70.dev1.data}/data/share/ngsolve/beam.geo +0 -0
- {ngsolve-6.2.2501.post55.dev1.data → ngsolve-6.2.2501.post70.dev1.data}/data/share/ngsolve/beam.vol +0 -0
- {ngsolve-6.2.2501.post55.dev1.data → ngsolve-6.2.2501.post70.dev1.data}/data/share/ngsolve/chip.in2d +0 -0
- {ngsolve-6.2.2501.post55.dev1.data → ngsolve-6.2.2501.post70.dev1.data}/data/share/ngsolve/chip.vol +0 -0
- {ngsolve-6.2.2501.post55.dev1.data → ngsolve-6.2.2501.post70.dev1.data}/data/share/ngsolve/coil.geo +0 -0
- {ngsolve-6.2.2501.post55.dev1.data → ngsolve-6.2.2501.post70.dev1.data}/data/share/ngsolve/coil.vol +0 -0
- {ngsolve-6.2.2501.post55.dev1.data → ngsolve-6.2.2501.post70.dev1.data}/data/share/ngsolve/coilshield.geo +0 -0
- {ngsolve-6.2.2501.post55.dev1.data → ngsolve-6.2.2501.post70.dev1.data}/data/share/ngsolve/coilshield.vol +0 -0
- {ngsolve-6.2.2501.post55.dev1.data → ngsolve-6.2.2501.post70.dev1.data}/data/share/ngsolve/cube.geo +0 -0
- {ngsolve-6.2.2501.post55.dev1.data → ngsolve-6.2.2501.post70.dev1.data}/data/share/ngsolve/cube.vol +0 -0
- {ngsolve-6.2.2501.post55.dev1.data → ngsolve-6.2.2501.post70.dev1.data}/data/share/ngsolve/d10_DGdoubleglazing.pde +0 -0
- {ngsolve-6.2.2501.post55.dev1.data → ngsolve-6.2.2501.post70.dev1.data}/data/share/ngsolve/d11_chip_nitsche.pde +0 -0
- {ngsolve-6.2.2501.post55.dev1.data → ngsolve-6.2.2501.post70.dev1.data}/data/share/ngsolve/d1_square.pde +0 -0
- {ngsolve-6.2.2501.post55.dev1.data → ngsolve-6.2.2501.post70.dev1.data}/data/share/ngsolve/d2_chip.pde +0 -0
- {ngsolve-6.2.2501.post55.dev1.data → ngsolve-6.2.2501.post70.dev1.data}/data/share/ngsolve/d3_helmholtz.pde +0 -0
- {ngsolve-6.2.2501.post55.dev1.data → ngsolve-6.2.2501.post70.dev1.data}/data/share/ngsolve/d4_cube.pde +0 -0
- {ngsolve-6.2.2501.post55.dev1.data → ngsolve-6.2.2501.post70.dev1.data}/data/share/ngsolve/d5_beam.pde +0 -0
- {ngsolve-6.2.2501.post55.dev1.data → ngsolve-6.2.2501.post70.dev1.data}/data/share/ngsolve/d6_shaft.pde +0 -0
- {ngsolve-6.2.2501.post55.dev1.data → ngsolve-6.2.2501.post70.dev1.data}/data/share/ngsolve/d7_coil.pde +0 -0
- {ngsolve-6.2.2501.post55.dev1.data → ngsolve-6.2.2501.post70.dev1.data}/data/share/ngsolve/d8_coilshield.pde +0 -0
- {ngsolve-6.2.2501.post55.dev1.data → ngsolve-6.2.2501.post70.dev1.data}/data/share/ngsolve/d9_hybridDG.pde +0 -0
- {ngsolve-6.2.2501.post55.dev1.data → ngsolve-6.2.2501.post70.dev1.data}/data/share/ngsolve/doubleglazing.in2d +0 -0
- {ngsolve-6.2.2501.post55.dev1.data → ngsolve-6.2.2501.post70.dev1.data}/data/share/ngsolve/doubleglazing.vol +0 -0
- {ngsolve-6.2.2501.post55.dev1.data → ngsolve-6.2.2501.post70.dev1.data}/data/share/ngsolve/piezo2d40round4.vol.gz +0 -0
- {ngsolve-6.2.2501.post55.dev1.data → ngsolve-6.2.2501.post70.dev1.data}/data/share/ngsolve/shaft.geo +0 -0
- {ngsolve-6.2.2501.post55.dev1.data → ngsolve-6.2.2501.post70.dev1.data}/data/share/ngsolve/shaft.vol +0 -0
- {ngsolve-6.2.2501.post55.dev1.data → ngsolve-6.2.2501.post70.dev1.data}/data/share/ngsolve/square.in2d +0 -0
- {ngsolve-6.2.2501.post55.dev1.data → ngsolve-6.2.2501.post70.dev1.data}/data/share/ngsolve/square.vol +0 -0
- {ngsolve-6.2.2501.post55.dev1.dist-info → ngsolve-6.2.2501.post70.dev1.dist-info}/LICENSE +0 -0
- {ngsolve-6.2.2501.post55.dev1.dist-info → ngsolve-6.2.2501.post70.dev1.dist-info}/WHEEL +0 -0
- {ngsolve-6.2.2501.post55.dev1.dist-info → ngsolve-6.2.2501.post70.dev1.dist-info}/top_level.txt +0 -0
netgen/include/mptools.hpp
CHANGED
|
@@ -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
|
|
37
|
+
return coefs.RangeN(n*n, 2*n+1);
|
|
38
38
|
}
|
|
39
39
|
|
|
40
|
-
|
|
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
|
|
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
|
|
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;
|
|
@@ -251,422 +106,44 @@ namespace ngfem
|
|
|
251
106
|
|
|
252
107
|
// Nail A. Gumerov and Ramani Duraiswami book, formula (2.2.12)
|
|
253
108
|
// add directional derivative divided by kappa to res, both multipoles need same scaling
|
|
254
|
-
void DirectionalDiffAdd (Vec<3> d, SphericalHarmonics & res, double scale = 1)
|
|
255
|
-
{
|
|
256
|
-
double fx = d(0);
|
|
257
|
-
double fy = d(1);
|
|
258
|
-
double fz = d(2);
|
|
259
|
-
double invscale = 1./scale;
|
|
260
|
-
|
|
261
|
-
for (int n = 0; n < order; n++)
|
|
262
|
-
for (int m = -n; m <= n; m++)
|
|
263
|
-
{
|
|
264
|
-
double amn = CalcAmn(m,n);
|
|
265
|
-
double bmn1 = CalcBmn(-m-1, n+1);
|
|
266
|
-
double bmn2 = CalcBmn(m-1,n+1);
|
|
267
|
-
|
|
268
|
-
res.Coef(n+1, m-1) += invscale * Complex(0.5*fx,0.5*fy)*bmn2 * Coef(n,m);
|
|
269
|
-
res.Coef(n+1, m ) -= invscale * fz*amn * Coef(n,m);
|
|
270
|
-
res.Coef(n+1, m+1) += invscale * Complex(0.5*fx,-0.5*fy)*bmn1 * Coef(n,m);
|
|
271
|
-
|
|
272
|
-
res.Coef(n, m) += scale * Complex(-0.5*fx,0.5*fy)*bmn2 * Coef(n+1,m-1);
|
|
273
|
-
res.Coef(n, m) += scale * fz*amn * Coef(n+1,m);
|
|
274
|
-
res.Coef(n, m) += scale * Complex(-0.5*fx,-0.5*fy)*bmn1 * Coef(n+1,m+1);
|
|
275
|
-
}
|
|
276
|
-
}
|
|
277
|
-
|
|
278
|
-
void RotateY (double alpha)
|
|
279
|
-
{
|
|
280
|
-
LocalHeap lh(8*6*sqr(order) + 8*15*order + 500);
|
|
281
|
-
|
|
282
|
-
static Timer t("mptool sh RotateY"); RegionTimer rg(t);
|
|
283
|
-
/*
|
|
284
|
-
static std::map<int, unique_ptr<Timer<>>> timers;
|
|
285
|
-
static std::map<int, unique_ptr<Timer<>>> timerstrafo;
|
|
286
|
-
if (timers.find(order)==timers.end())
|
|
287
|
-
{
|
|
288
|
-
timers[order] = make_unique<Timer<>> (string("mptools sh RotateY ")+ToString(order));
|
|
289
|
-
timerstrafo[order] = make_unique<Timer<>> (string("mptools sh RotateY trafo ")+ToString(order));
|
|
290
|
-
}
|
|
291
|
-
RegionTimer rg(*timers[order]);
|
|
292
|
-
*/
|
|
293
|
-
double s = sin(alpha);
|
|
294
|
-
double c = cos(alpha);
|
|
295
|
-
|
|
296
|
-
FlatMatrix<> normalized_leg_func(order+2, order+2, lh);
|
|
297
|
-
NormalizedLegendreFunctions(order+1, order+1, c, normalized_leg_func);
|
|
298
|
-
|
|
299
|
-
if (alpha < 0)
|
|
300
|
-
for (int i = 1; i <= order+1; i+=2)
|
|
301
|
-
normalized_leg_func.Row(i) *= -1;
|
|
302
|
-
|
|
303
|
-
// cout << "leg = " << endl << normalized_leg_func << endl;
|
|
304
|
-
FlatVector<> Dmn(2*order+1, lh);
|
|
109
|
+
void DirectionalDiffAdd (Vec<3> d, SphericalHarmonics & res, double scale = 1);
|
|
305
110
|
|
|
306
|
-
for (int n=1; n <= order; n++)
|
|
307
|
-
{
|
|
308
|
-
HeapReset hr(lh);
|
|
309
|
-
|
|
310
|
-
FlatMatrix<double> trafo(n+1, 2*n+1, lh);
|
|
311
|
-
/*
|
|
312
|
-
Recursive Computation of Spherical Harmonic Rotation Coefficients of Large Degree
|
|
313
|
-
Nail A. Gumerov and Ramani Duraiswami
|
|
314
|
-
within Excursions in Harmonic Analysis, Volume 3
|
|
315
|
-
|
|
316
|
-
page 130
|
|
317
|
-
*/
|
|
318
|
-
|
|
319
|
-
// Step 2
|
|
320
|
-
// H(0,m)
|
|
321
|
-
trafo.Col(n) = 1.0/sqrt(2*n+1) * normalized_leg_func.Col(n).Range(n+1);
|
|
322
|
-
for (int m = 1; m <= n; m += 2) trafo(m,n) *= -1;
|
|
323
|
-
// Step 3
|
|
324
|
-
// H(1,m)
|
|
325
|
-
FlatVector<double> tmp = 1.0/sqrt(2*n+3) * normalized_leg_func.Col(n+1).Range(n+2) | lh;
|
|
326
|
-
for (int m = 1; m < tmp.Size(); m += 2) tmp(m) *= -1;
|
|
327
|
-
for (int m = 1; m <= n; m++)
|
|
328
|
-
trafo.Col(n+1)(m) = 1/CalcBmn(0,n+1) * ( CalcBmn(-m-1, n+1)*(1-c)/2 * tmp(m+1)
|
|
329
|
-
- CalcBmn(m-1,n+1)*(1+c)/2 * tmp(m-1)
|
|
330
|
-
- CalcAmn(m,n) * s*tmp(m));
|
|
331
|
-
|
|
332
|
-
// Step 4
|
|
333
|
-
// diamond - recursion
|
|
334
|
-
for (int mp = -n; mp <= n; mp++)
|
|
335
|
-
Dmn(order+mp) = CalcDmn(mp, n);
|
|
336
|
-
|
|
337
|
-
for (int mp = 1; mp < n; mp++)
|
|
338
|
-
{
|
|
339
|
-
double invDmn = 1.0 / Dmn(order+mp);
|
|
340
|
-
for (int m = mp; m < n; m++)
|
|
341
|
-
trafo(m, n+mp+1) = invDmn * ( Dmn(order+mp-1) *trafo(m ,n+mp-1)
|
|
342
|
-
-Dmn(order+m-1)*trafo(m-1,n+mp)
|
|
343
|
-
+Dmn(order+m) *trafo(m+1,n+mp));
|
|
344
|
-
int m = n;
|
|
345
|
-
trafo(m, n+mp+1) = invDmn * ( Dmn(order+mp-1,n)*trafo(m ,n+mp-1)
|
|
346
|
-
-Dmn(order+m-1,n)*trafo(m-1,n+mp));
|
|
347
|
-
}
|
|
348
|
-
|
|
349
|
-
// Step 5
|
|
350
|
-
// diamond - recursion, negative
|
|
351
|
-
for (int mp = 0; mp > -n; mp--)
|
|
352
|
-
{
|
|
353
|
-
double invDmn = 1.0 / Dmn(order+mp-1);
|
|
354
|
-
for (int m = -mp+1; m < n; m++)
|
|
355
|
-
trafo(m, n+mp-1) = invDmn * ( Dmn(order+mp,n)*trafo(m ,n+mp+1)
|
|
356
|
-
+Dmn(order+m-1,n)*trafo(m-1,n+mp)
|
|
357
|
-
-Dmn(order+m ,n)*trafo(m+1,n+mp));
|
|
358
|
-
int m = n;
|
|
359
|
-
trafo(m, n+mp-1) = invDmn * ( Dmn(order+mp,n)*trafo(m ,n+mp+1)
|
|
360
|
-
+Dmn(order+m-1,n)*trafo(m-1,n+mp));
|
|
361
|
-
}
|
|
362
|
-
|
|
363
|
-
// RegionTimer rgtrafo(*timerstrafo[order]);
|
|
364
|
-
// Step 6
|
|
365
|
-
// symmetries in m and mp
|
|
366
|
-
for (int m = 0; m <= n; m++)
|
|
367
|
-
{
|
|
368
|
-
auto dst = trafo.Row(m).Range(n+m, n+n+1);
|
|
369
|
-
auto src = trafo.Col(n+m).Range(m, n+1);
|
|
370
|
-
dst = src;
|
|
371
|
-
}
|
|
372
|
-
for (int m = 0; m <= n; m++)
|
|
373
|
-
{
|
|
374
|
-
auto dst = trafo.Row(m).Range(n-n, n-m+1).Reversed();
|
|
375
|
-
auto src = trafo.Col(n-m).Range(m, n+1);
|
|
376
|
-
dst = src;
|
|
377
|
-
}
|
|
378
|
-
/*
|
|
379
|
-
double errortho = L2Norm( Matrix(trafo*Trans(trafo) - Identity(n+1)));
|
|
380
|
-
if (errortho > 1e-10)
|
|
381
|
-
{
|
|
382
|
-
*testout << "n = " << n << " order = " << Order() << ", alpha = " << alpha << ", errortho = " << errortho << endl;
|
|
383
|
-
if (n < 10)
|
|
384
|
-
*testout << trafo*Trans(trafo) << endl;
|
|
385
|
-
}
|
|
386
|
-
*/
|
|
387
|
-
|
|
388
|
-
FlatVector<Complex> cn = CoefsN(n);
|
|
389
|
-
FlatVector<Complex> old = cn | lh;
|
|
390
|
-
|
|
391
|
-
cn.Slice(0,1) = Trans(trafo) * old.Range(n, 2*n+1);
|
|
392
|
-
cn.Slice(0,1).Reversed() += Trans(trafo.Rows(1,n+1)) * old.Range(0,n).Reversed();
|
|
393
|
-
|
|
394
|
-
for (int m = 1; m <= n; m+=2)
|
|
395
|
-
{
|
|
396
|
-
cn(n+m) *= -1;
|
|
397
|
-
cn(n-m) *= -1;
|
|
398
|
-
}
|
|
399
|
-
}
|
|
400
|
-
}
|
|
401
|
-
|
|
402
111
|
};
|
|
403
112
|
|
|
404
113
|
|
|
405
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);
|
|
406
118
|
|
|
407
|
-
|
|
408
|
-
|
|
409
|
-
|
|
410
|
-
FlatVector<Tz> fjs, FlatVector<Tz> fjder)
|
|
411
|
-
{
|
|
412
|
-
/*
|
|
413
|
-
c**********************************************************************
|
|
414
|
-
c
|
|
415
|
-
c PURPOSE:
|
|
416
|
-
c
|
|
417
|
-
c This subroutine evaluates the first NTERMS spherical Bessel
|
|
418
|
-
c functions and if required, their derivatives.
|
|
419
|
-
c It incorporates a scaling parameter SCALE so that
|
|
420
|
-
c
|
|
421
|
-
c fjs_n(z)=j_n(z)/SCALE^n
|
|
422
|
-
c fjder_n(z)=\frac{\partial fjs_n(z)}{\partial z}
|
|
423
|
-
c
|
|
424
|
-
c INPUT:
|
|
425
|
-
c
|
|
426
|
-
c nterms (integer): order of expansion of output array fjs
|
|
427
|
-
c z (complex *16): argument of the spherical Bessel functions
|
|
428
|
-
c scale (real *8) : scaling factor (discussed above)
|
|
429
|
-
c ifder (integer): flag indicating whether to calculate "fjder"
|
|
430
|
-
c 0 NO
|
|
431
|
-
c 1 YES
|
|
432
|
-
c OUTPUT:
|
|
433
|
-
c fjs (complex *16): array of scaled Bessel functions.
|
|
434
|
-
c fjder (complex *16): array of derivs of scaled Bessel functions.
|
|
435
|
-
c
|
|
436
|
-
c
|
|
437
|
-
*/
|
|
119
|
+
NGS_DLL_HEADER
|
|
120
|
+
void besseljs3d (int nterms, Complex z, double scale,
|
|
121
|
+
FlatVector<Complex> fjs, FlatVector<Complex> fjder);
|
|
438
122
|
|
|
439
123
|
|
|
440
|
-
// c ... Initializing ...
|
|
441
|
-
|
|
442
|
-
// set to asymptotic values if argument is sufficiently small
|
|
443
|
-
if (abs(z) < 1e-200)
|
|
444
|
-
{
|
|
445
|
-
fjs(0) = 1;
|
|
446
|
-
for (int i = 1; i <= nterms; i++)
|
|
447
|
-
fjs(i) = 0.0;
|
|
448
|
-
|
|
449
|
-
if (fjder.Size())
|
|
450
|
-
{
|
|
451
|
-
fjder = 0.0;
|
|
452
|
-
fjder(1) = 1.0/(3*scale);
|
|
453
|
-
}
|
|
454
|
-
return;
|
|
455
|
-
}
|
|
456
|
-
|
|
457
|
-
|
|
458
|
-
// ... Step 1: recursion up to find ntop, starting from nterms
|
|
459
|
-
|
|
460
|
-
Tz zinv=1.0/z;
|
|
461
|
-
|
|
462
|
-
Tz fjm1 = 0.0;
|
|
463
|
-
Tz fj0 = 1.0;
|
|
464
|
-
|
|
465
|
-
/*
|
|
466
|
-
c
|
|
467
|
-
cc note max point for upward recurrence is
|
|
468
|
-
c hard coded to nterms + 1000,
|
|
469
|
-
c this might cause loss of accuracy for some
|
|
470
|
-
c arguments in the complex plane for large
|
|
471
|
-
c nterms. For example, it is a terrible idea
|
|
472
|
-
c to use this code for z>>nterms^2
|
|
473
|
-
*/
|
|
474
|
-
|
|
475
|
-
// int lwfjs = nterms + 100000;
|
|
476
|
-
int ntop = nterms+1000;
|
|
477
|
-
|
|
478
|
-
for (int i = nterms; ; i++)
|
|
479
|
-
{
|
|
480
|
-
double dcoef = 2*i+1.0;
|
|
481
|
-
Tz fj1 = dcoef*zinv*fj0-fjm1;
|
|
482
|
-
double dd = sqr(abs(fj1));
|
|
483
|
-
if (dd > 1e40)
|
|
484
|
-
{
|
|
485
|
-
ntop=i+1;
|
|
486
|
-
break;
|
|
487
|
-
}
|
|
488
|
-
fjm1 = fj0;
|
|
489
|
-
fj0 = fj1;
|
|
490
|
-
if (i > nterms+100000)
|
|
491
|
-
throw Exception("bessel failed 1");
|
|
492
|
-
}
|
|
493
|
-
|
|
494
|
-
Array<bool> iscale(ntop+1);
|
|
495
|
-
Vector<Tz> fjtmp(ntop+1);
|
|
496
|
-
|
|
497
|
-
/*
|
|
498
|
-
c ... Step 2: Recursion back down to generate the unscaled jfuns:
|
|
499
|
-
c if magnitude exceeds UPBOUND2, rescale and continue the
|
|
500
|
-
c recursion (saving the order at which rescaling occurred
|
|
501
|
-
c in array iscale.
|
|
502
|
-
*/
|
|
503
|
-
|
|
504
|
-
iscale = false;
|
|
505
|
-
|
|
506
|
-
fjtmp(ntop) = 0.0;
|
|
507
|
-
fjtmp(ntop-1) = 1.0;
|
|
508
|
-
for (int i = ntop-1; i>=1; i--)
|
|
509
|
-
{
|
|
510
|
-
double dcoef = 2*i+1.0;
|
|
511
|
-
fjtmp(i-1) = dcoef*zinv*fjtmp(i)-fjtmp(i+1);
|
|
512
|
-
double dd = sqr(abs(fjtmp(i-1)));
|
|
513
|
-
if (dd > 1e40)
|
|
514
|
-
{
|
|
515
|
-
fjtmp(i) *= 1e-40;
|
|
516
|
-
fjtmp(i-1) *= 1e-40;
|
|
517
|
-
iscale[i] = true;
|
|
518
|
-
}
|
|
519
|
-
}
|
|
520
|
-
|
|
521
|
-
/*
|
|
522
|
-
c
|
|
523
|
-
c ... Step 3: go back up to the top and make sure that all
|
|
524
|
-
c Bessel functions are scaled by the same factor
|
|
525
|
-
c (i.e. the net total of times rescaling was invoked
|
|
526
|
-
c on the way down in the previous loop).
|
|
527
|
-
c At the same time, add scaling to fjs array.
|
|
528
|
-
c
|
|
529
|
-
*/
|
|
530
|
-
|
|
531
|
-
double scalinv = 1.0/scale;
|
|
532
|
-
double sctot = 1.0;
|
|
533
|
-
for (int i = 1; i <= ntop; i++)
|
|
534
|
-
{
|
|
535
|
-
sctot *= scalinv;
|
|
536
|
-
if (iscale[i-1])
|
|
537
|
-
sctot *= 1e-40;
|
|
538
|
-
fjtmp(i) *= sctot;
|
|
539
|
-
}
|
|
540
|
-
|
|
541
|
-
// Determine the normalization parameter:
|
|
542
|
-
|
|
543
|
-
fj0=sin(z)*zinv;
|
|
544
|
-
Tz fj1=fj0*zinv-cos(z)*zinv;
|
|
545
|
-
|
|
546
|
-
double d0=abs(fj0);
|
|
547
|
-
double d1=abs(fj1);
|
|
548
|
-
Tz zscale;
|
|
549
|
-
if (d1 > d0)
|
|
550
|
-
zscale=fj1/(fjtmp(1)*scale);
|
|
551
|
-
else
|
|
552
|
-
zscale=fj0/fjtmp(0);
|
|
553
|
-
|
|
554
|
-
// Scale the jfuns by zscale:
|
|
555
|
-
|
|
556
|
-
Tz ztmp=zscale;
|
|
557
|
-
for (int i = 0; i <= nterms; i++)
|
|
558
|
-
fjs(i)=fjtmp(i)*ztmp;
|
|
559
|
-
|
|
560
|
-
|
|
561
|
-
// Finally, calculate the derivatives if desired:
|
|
562
|
-
|
|
563
|
-
if (fjder.Size())
|
|
564
|
-
{
|
|
565
|
-
fjder(0) = -fjs(1)*scale;
|
|
566
|
-
for (int i = 1; i <= nterms; i++)
|
|
567
|
-
{
|
|
568
|
-
double dc1=i/(2*i+1.0);
|
|
569
|
-
double dc2=1.0-dc1;
|
|
570
|
-
dc1=dc1*scalinv;
|
|
571
|
-
dc2=dc2*scale;
|
|
572
|
-
fjder(i)=(dc1*fjtmp(i-1)-dc2*fjtmp(i+1))*ztmp;
|
|
573
|
-
}
|
|
574
|
-
}
|
|
575
|
-
}
|
|
576
|
-
|
|
577
|
-
|
|
578
|
-
|
|
579
|
-
|
|
580
124
|
/*
|
|
581
|
-
// from A. Barnett
|
|
582
|
-
// http://www.fresco.org.uk/functions/barnett/index.htm
|
|
583
|
-
|
|
584
125
|
spherical bessel functions of first (the j_n) and second (the y_n) kind.
|
|
585
|
-
|
|
126
|
+
|
|
586
127
|
j0(r) = sin(r)/r
|
|
587
128
|
j1(r) = (sin(r)-r cos(r)) / r**2
|
|
588
129
|
|
|
589
130
|
y0(r) = -cos(r)/r
|
|
590
131
|
y1(r) = (-cos(r)-r*sin(r)) / r**2
|
|
591
132
|
*/
|
|
133
|
+
NGS_DLL_HEADER
|
|
592
134
|
void SBESJY (double x, int lmax,
|
|
593
135
|
FlatVector<double> j,
|
|
594
136
|
FlatVector<double> y,
|
|
595
137
|
FlatVector<double> jp,
|
|
596
|
-
FlatVector<double> yp)
|
|
597
|
-
{
|
|
598
|
-
if (x < 1e-8)
|
|
599
|
-
{
|
|
600
|
-
cout << "TODO: special treatment for small x" << endl;
|
|
601
|
-
return;
|
|
602
|
-
}
|
|
603
|
-
|
|
604
|
-
double xinv = 1/x;
|
|
605
|
-
|
|
606
|
-
if (lmax > 0)
|
|
607
|
-
{
|
|
608
|
-
double twoxi = 2*xinv;
|
|
609
|
-
double sl = lmax*xinv;
|
|
610
|
-
double tk = 2*sl+3*xinv;
|
|
611
|
-
double cf1 = sl;
|
|
612
|
-
double den = 1;
|
|
613
|
-
if (abs(cf1) < 1e-8) cf1 = 1e-8;
|
|
614
|
-
double c = cf1;
|
|
615
|
-
double d = 0;
|
|
616
|
-
for (int l = 1; l < 10000; l++)
|
|
617
|
-
{
|
|
618
|
-
c = tk-1/c;
|
|
619
|
-
d = tk-d;
|
|
620
|
-
if (abs(c) < 1e-8) c = 1e-8;
|
|
621
|
-
if (abs(d) < 1e-8) d = 1e-8;
|
|
622
|
-
d = 1/d;
|
|
623
|
-
double dcf1 = d*c;
|
|
624
|
-
cf1 *= dcf1;
|
|
625
|
-
if (d < 0) den = -den;
|
|
626
|
-
if (abs(dcf1-1) < 1e-10)
|
|
627
|
-
break;
|
|
628
|
-
tk += twoxi;
|
|
629
|
-
// nfp = l;
|
|
630
|
-
}
|
|
631
|
-
|
|
632
|
-
j(lmax) = den;
|
|
633
|
-
jp(lmax) = cf1*den;
|
|
634
|
-
for (int l = lmax; l >= 1; l--)
|
|
635
|
-
{
|
|
636
|
-
j(l-1) = (sl+xinv)*j(l) + jp(l);
|
|
637
|
-
sl = sl-xinv;
|
|
638
|
-
jp(l-1) = sl*j(l-1) - j(l);
|
|
639
|
-
}
|
|
640
|
-
}
|
|
641
|
-
|
|
642
|
-
double j0 = j(0);
|
|
643
|
-
double jp0 = jp(0);
|
|
644
|
-
|
|
645
|
-
// C------ CALCULATE THE L=0 SPHERICAL BESSEL FUNCTIONS DIRECTLY
|
|
646
|
-
j(0) = xinv * sin(x);
|
|
647
|
-
y(0) = -xinv * cos(x);
|
|
648
|
-
jp(0) = -y(0)-xinv*j(0);
|
|
649
|
-
yp(0) = j(0)-xinv*y(0);
|
|
650
|
-
|
|
651
|
-
double omega = (abs(j0)>abs(jp0)) ? j(0)/j0 : jp(0) / jp0; // fix for x \approx 2 pi
|
|
652
|
-
double sl = 0;
|
|
653
|
-
for (int l = 1; l <=lmax; l++)
|
|
654
|
-
{
|
|
655
|
-
j(l) *= omega;
|
|
656
|
-
jp(l) *= omega;
|
|
657
|
-
y(l) = sl*y(l-1) - yp(l-1);
|
|
658
|
-
sl += xinv;
|
|
659
|
-
yp(l) = y(l-1) - (sl+xinv)*y(l);
|
|
660
|
-
}
|
|
661
|
-
}
|
|
662
|
-
|
|
138
|
+
FlatVector<double> yp);
|
|
663
139
|
|
|
664
140
|
|
|
141
|
+
|
|
665
142
|
template <typename T>
|
|
666
143
|
void SphericalBessel (int n, double rho, double scale, T && values)
|
|
667
144
|
{
|
|
668
145
|
Vector<double> j(n+1), jp(n+1);
|
|
669
|
-
besseljs3d
|
|
146
|
+
besseljs3d (n, rho, scale, j, jp);
|
|
670
147
|
values = j;
|
|
671
148
|
}
|
|
672
149
|
|
|
@@ -693,6 +170,7 @@ c
|
|
|
693
170
|
Vector j(n+1), y(n+1), jp(n+1), yp(n+1);
|
|
694
171
|
SBESJY (rho, n, j, y, jp, yp);
|
|
695
172
|
|
|
173
|
+
/*
|
|
696
174
|
values = j + Complex(0,1) * y;
|
|
697
175
|
if (scale != 1.0)
|
|
698
176
|
{
|
|
@@ -703,6 +181,28 @@ c
|
|
|
703
181
|
prod *= scale;
|
|
704
182
|
}
|
|
705
183
|
}
|
|
184
|
+
*/
|
|
185
|
+
|
|
186
|
+
|
|
187
|
+
// the bessel-evaluation with scale
|
|
188
|
+
besseljs3d (n, rho, 1/scale, j, jp);
|
|
189
|
+
|
|
190
|
+
// Bessel y directly with the recurrence formula for (y, yp):
|
|
191
|
+
double x = rho;
|
|
192
|
+
double xinv = 1/x;
|
|
193
|
+
y(0) = -xinv * cos(x);
|
|
194
|
+
yp(0) = j(0)-xinv*y(0);
|
|
195
|
+
|
|
196
|
+
double sl = 0;
|
|
197
|
+
for (int l = 1; l <= n; l++)
|
|
198
|
+
{
|
|
199
|
+
y(l) = scale * (sl*y(l-1) - yp(l-1));
|
|
200
|
+
sl += xinv;
|
|
201
|
+
yp(l) = scale * y(l-1) - (sl+xinv)*y(l);
|
|
202
|
+
}
|
|
203
|
+
|
|
204
|
+
for (int i = 0; i <= n; i++)
|
|
205
|
+
values(i) = Complex (j(i), y(i));
|
|
706
206
|
}
|
|
707
207
|
|
|
708
208
|
|
|
@@ -735,7 +235,7 @@ c
|
|
|
735
235
|
|
|
736
236
|
|
|
737
237
|
template <typename RADIAL>
|
|
738
|
-
class MultiPole
|
|
238
|
+
class NGS_DLL_HEADER MultiPole
|
|
739
239
|
{
|
|
740
240
|
SphericalHarmonics sh;
|
|
741
241
|
double kappa;
|
|
@@ -766,86 +266,12 @@ c
|
|
|
766
266
|
return *this;
|
|
767
267
|
}
|
|
768
268
|
|
|
769
|
-
Complex Eval (Vec<3> x) const
|
|
770
|
-
{
|
|
771
|
-
if (sh.Order() < 0) return 0;
|
|
772
|
-
|
|
773
|
-
Vector<Complex> radial(sh.Order()+1);
|
|
774
|
-
Vector<Complex> shvals(sh.Order()+1);
|
|
775
|
-
|
|
776
|
-
RADIAL::Eval(sh.Order(), kappa*L2Norm(x), scale, radial);
|
|
777
|
-
sh.EvalOrders (x, shvals);
|
|
778
|
-
|
|
779
|
-
Complex sum = 0;
|
|
780
|
-
for (int i = 0; i <= sh.Order(); i++)
|
|
781
|
-
sum += shvals(i) * radial(i);
|
|
782
|
-
|
|
783
|
-
return sum;
|
|
784
|
-
}
|
|
785
|
-
|
|
786
|
-
void AddCharge (Vec<3> x, Complex c)
|
|
787
|
-
{
|
|
788
|
-
if constexpr (!std::is_same<RADIAL,MPSingular>())
|
|
789
|
-
throw Exception("AddCharge assumes singular MP");
|
|
790
|
-
|
|
791
|
-
// static Timer t("mptool AddCharge"); RegionTimer rg(t);
|
|
792
|
-
|
|
793
|
-
if (L2Norm(x) < 1e-10)
|
|
794
|
-
{
|
|
795
|
-
sh.Coef(0,0) += c * Complex(0,1)*kappa/sqrt(4*M_PI);
|
|
796
|
-
return;
|
|
797
|
-
}
|
|
798
|
-
|
|
799
|
-
// cout << "add charge, kappa rho = " << kappa*L2Norm(x) << ", order = " << sh.Order() << endl;
|
|
800
|
-
|
|
801
|
-
Vector<Complex> radial(sh.Order()+1);
|
|
802
|
-
Vector<Complex> sh_shapes(sqr (sh.Order()+1));
|
|
803
|
-
|
|
804
|
-
RADIAL::Eval(sh.Order(), kappa*L2Norm(x), 1.0/scale, radial);
|
|
805
|
-
// cout << "radial = " << radial << endl;
|
|
806
|
-
sh.Calc(x, sh_shapes);
|
|
807
|
-
|
|
808
|
-
for (int i = 0; i <= sh.Order(); i++)
|
|
809
|
-
{
|
|
810
|
-
IntRange r(sqr(i), sqr(i+1));
|
|
811
|
-
sh.Coefs().Range(r) += c * Complex(0,1)*kappa * radial(i).real()*Conj(sh_shapes.Range(r));
|
|
812
|
-
}
|
|
813
|
-
}
|
|
269
|
+
Complex Eval (Vec<3> x) const;
|
|
814
270
|
|
|
271
|
+
void AddCharge (Vec<3> x, Complex c);
|
|
272
|
+
void AddDipole (Vec<3> x, Vec<3> d, Complex c);
|
|
273
|
+
|
|
815
274
|
|
|
816
|
-
void AddDipole (Vec<3> x, Vec<3> d, Complex c)
|
|
817
|
-
{
|
|
818
|
-
// static Timer t("mptool AddDipole"); RegionTimer rg(t);
|
|
819
|
-
/*
|
|
820
|
-
double eps = 1e-4;
|
|
821
|
-
AddCharge(x+eps*d, -c/(2*eps));
|
|
822
|
-
AddCharge(x-eps*d, c/(2*eps));
|
|
823
|
-
return;
|
|
824
|
-
*/
|
|
825
|
-
|
|
826
|
-
if constexpr (!std::is_same<RADIAL,MPSingular>())
|
|
827
|
-
throw Exception("AddCharge assumes singular MP");
|
|
828
|
-
|
|
829
|
-
/*
|
|
830
|
-
// book, formula (2.2.20)
|
|
831
|
-
// dipole in origin:
|
|
832
|
-
MultiPole<MPSingular> tmp(1, kappa);
|
|
833
|
-
tmp.SH().Coef(1,1) += Complex(0,1)*sqr(kappa)*sh.CalcBmn(-1,1)/(2*sqrt(4*M_PI)) * d(0)*c;
|
|
834
|
-
tmp.SH().Coef(1,-1) += Complex(0,1)*sqr(kappa)*sh.CalcBmn(-1,1)/(2*sqrt(4*M_PI)) * d(0)*c;
|
|
835
|
-
|
|
836
|
-
tmp.SH().Coef(1,1) += Complex(1,0)*sqr(kappa)*sh.CalcBmn(-1,1)/(2*sqrt(4*M_PI)) * d(1)*c;
|
|
837
|
-
tmp.SH().Coef(1,-1) -= Complex(1,0)*sqr(kappa)*sh.CalcBmn(-1,1)/(2*sqrt(4*M_PI)) * d(1)*c;
|
|
838
|
-
|
|
839
|
-
tmp.SH().Coef(1,0) += -Complex(0,1)*kappa*kappa*sh.CalcAmn(0,0)/sqrt(4*M_PI) *d(2)*c;
|
|
840
|
-
tmp.TransformAdd (*this, -x);
|
|
841
|
-
*/
|
|
842
|
-
|
|
843
|
-
MultiPole<MPSingular> tmp(Order(), kappa, Scale());
|
|
844
|
-
tmp.AddCharge(x, c);
|
|
845
|
-
tmp.SH().DirectionalDiffAdd (kappa*d, this->SH(), Scale());
|
|
846
|
-
}
|
|
847
|
-
|
|
848
|
-
|
|
849
275
|
void ChangeScaleTo (double newscale)
|
|
850
276
|
{
|
|
851
277
|
double fac = scale/newscale;
|
|
@@ -855,6 +281,19 @@ c
|
|
|
855
281
|
scale = newscale;
|
|
856
282
|
}
|
|
857
283
|
|
|
284
|
+
Vector<double> Spectrum (bool scaled) const
|
|
285
|
+
{
|
|
286
|
+
Vector<double> spec(Order()+1);
|
|
287
|
+
double fac = 1;
|
|
288
|
+
for (int n = 0; n <= Order(); n++)
|
|
289
|
+
{
|
|
290
|
+
spec(n) = fac * L2Norm2(sh.CoefsN(n));
|
|
291
|
+
if (!scaled) fac *= sqr(scale);
|
|
292
|
+
}
|
|
293
|
+
return spec;
|
|
294
|
+
}
|
|
295
|
+
|
|
296
|
+
|
|
858
297
|
template <typename TARGET>
|
|
859
298
|
void Transform (MultiPole<TARGET> & target, Vec<3> dist) const
|
|
860
299
|
{
|
|
@@ -903,548 +342,8 @@ c
|
|
|
903
342
|
target.SH().Coefs() += tmp.SH().Coefs();
|
|
904
343
|
}
|
|
905
344
|
|
|
906
|
-
#ifdef VER1
|
|
907
345
|
template <typename TARGET>
|
|
908
|
-
void ShiftZ (double z, MultiPole<TARGET> & target)
|
|
909
|
-
{
|
|
910
|
-
static Timer t("mptool ShiftZ"+ToString(typeid(RADIAL).name())+ToString(typeid(TARGET).name()));
|
|
911
|
-
|
|
912
|
-
RegionTimer rg(t);
|
|
913
|
-
|
|
914
|
-
int os = sh.Order();
|
|
915
|
-
int ot = target.SH().Order();
|
|
916
|
-
|
|
917
|
-
if (os > 100 && ot > 100 && abs(z)*kappa > 0.3*min(os,ot) && is_same<RADIAL,TARGET>())
|
|
918
|
-
{
|
|
919
|
-
MultiPole<TARGET> tmp {target};
|
|
920
|
-
ShiftZ(z/2, tmp);
|
|
921
|
-
tmp.ShiftZ(z/2, target);
|
|
922
|
-
return;
|
|
923
|
-
}
|
|
924
|
-
|
|
925
|
-
|
|
926
|
-
target.SH().Coefs()=0.0;
|
|
927
|
-
|
|
928
|
-
LocalHeap lh( 16*( (os+ot+1)*(os+1) + (os+1 + ot+1) ) + 8*2*(os+ot+1) + 500);
|
|
929
|
-
|
|
930
|
-
FlatMatrix<Complex> trafo(os+ot+1, os+1, lh);
|
|
931
|
-
FlatVector<Complex> hv1(os+1, lh), hv2(ot+1, lh);
|
|
932
|
-
FlatVector<double> amn(os+ot+1, lh);
|
|
933
|
-
FlatVector<double> inv_amn(os+ot+1, lh);
|
|
934
|
-
|
|
935
|
-
// trafo = Complex(0.0);
|
|
936
|
-
|
|
937
|
-
|
|
938
|
-
double tscale = target.Scale();
|
|
939
|
-
double inv_tscale = 1.0/tscale;
|
|
940
|
-
|
|
941
|
-
|
|
942
|
-
// (185) from paper 'fast, exact, stable, Gumerov+Duraiswami
|
|
943
|
-
// RADIAL::Eval(os+ot, kappa*abs(z), trafo.Col(0));
|
|
944
|
-
if (typeid(RADIAL) == typeid(TARGET))
|
|
945
|
-
SphericalBessel (os+ot, kappa*abs(z), tscale, trafo.Col(0));
|
|
946
|
-
else
|
|
947
|
-
SphericalHankel1 (os+ot, kappa*abs(z), inv_tscale, trafo.Col(0));
|
|
948
|
-
|
|
949
|
-
/*
|
|
950
|
-
if (L2Norm(trafo.Col(0)) > 1e5 || std::isnan(L2Norm(trafo.Col(0))))
|
|
951
|
-
{
|
|
952
|
-
*testout << "large Hankel: " << L2Norm(trafo.Col(0)) << endl;
|
|
953
|
-
*testout << "kappa z = " << kappa*z << ", os = " << os << ", ot = " << ot << endl;
|
|
954
|
-
}
|
|
955
|
-
*/
|
|
956
|
-
// if (L2Norm(trafo.Col(0)) > 1e5)
|
|
957
|
-
// throw Exception ("z-shift - coefs large");
|
|
958
|
-
|
|
959
|
-
if (z < 0)
|
|
960
|
-
for (int l = 1; l < trafo.Height(); l+=2) trafo(l,0) *= -1;
|
|
961
|
-
|
|
962
|
-
for (int l = 0; l <= os+ot; l++)
|
|
963
|
-
trafo(l,0) *= sqrt(2*l+1);
|
|
964
|
-
|
|
965
|
-
if (os > 0)
|
|
966
|
-
{
|
|
967
|
-
for (int l = 1; l < os+ot; l++)
|
|
968
|
-
trafo(l,1) = -scale/sh.CalcAmn(0,0) * (sh.CalcAmn(0,l)*tscale*trafo(l+1,0)
|
|
969
|
-
-sh.CalcAmn(0,l-1)*inv_tscale*trafo(l-1,0));
|
|
970
|
-
trafo(0,1) = -scale*tscale*trafo(1,0);
|
|
971
|
-
}
|
|
972
|
-
|
|
973
|
-
for (int n = 1; n < os; n++)
|
|
974
|
-
{
|
|
975
|
-
for (int l = 1; l < os+ot-n; l++)
|
|
976
|
-
trafo(l,n+1) = -scale/sh.CalcAmn(0,n) * (sh.CalcAmn(0,l)*tscale*trafo(l+1,n)
|
|
977
|
-
-sh.CalcAmn(0,l-1)*inv_tscale*trafo(l-1,n)
|
|
978
|
-
-sh.CalcAmn(0,n-1)*scale*trafo(l,n-1));
|
|
979
|
-
trafo(0,n+1) = pow(-scale*tscale,n+1)*trafo(n+1,0);
|
|
980
|
-
}
|
|
981
|
-
|
|
982
|
-
cout << "m = " << 0 << endl
|
|
983
|
-
<< trafo.Rows(0,ot+1) << endl;
|
|
984
|
-
|
|
985
|
-
|
|
986
|
-
for (int n = 0; n <= os; n++)
|
|
987
|
-
hv1(n) = sh.Coef(n,0);
|
|
988
|
-
hv2 = trafo.Rows(ot+1) * hv1;
|
|
989
|
-
for (int n = 0; n <= ot; n++)
|
|
990
|
-
target.SH().Coef(n,0) = hv2(n);
|
|
991
|
-
|
|
992
|
-
|
|
993
|
-
for (int m = 1; m <= min(os,ot); m++)
|
|
994
|
-
{
|
|
995
|
-
// fill recursive formula (187)
|
|
996
|
-
for (int l = m; l <= os+ot-m; l++)
|
|
997
|
-
trafo(l,m) = scale/sh.CalcBmn(-m, m) * (sh.CalcBmn(-m, l)*inv_tscale*trafo(l-1, m-1)
|
|
998
|
-
-sh.CalcBmn(m-1,l+1)*tscale*trafo(l+1,m-1));
|
|
999
|
-
|
|
1000
|
-
|
|
1001
|
-
/*
|
|
1002
|
-
cout << "m = " << m << endl;
|
|
1003
|
-
cout << " norm col0 = " << L2Norm(trafo.Col(m).Range(m,os+ot-m+1)) << endl;
|
|
1004
|
-
*/
|
|
1005
|
-
|
|
1006
|
-
for (int l = m-1; l < os+ot-m; l++)
|
|
1007
|
-
{
|
|
1008
|
-
amn(l) = sh.CalcAmn(m,l);
|
|
1009
|
-
inv_amn(l) = scale/amn(l);
|
|
1010
|
-
}
|
|
1011
|
-
|
|
1012
|
-
double prod = 1;
|
|
1013
|
-
for (int n = m; n < os; n++)
|
|
1014
|
-
{
|
|
1015
|
-
for (int l = m+1; l < os+ot-n; l++)
|
|
1016
|
-
trafo(l,n+1) = -inv_amn(n) * (amn(l)*tscale*trafo(l+1,n)
|
|
1017
|
-
-amn(l-1)*inv_tscale*trafo(l-1,n)
|
|
1018
|
-
-amn(n-1)*scale*trafo(l,n-1));
|
|
1019
|
-
|
|
1020
|
-
prod *= -scale*tscale;
|
|
1021
|
-
trafo(m,n+1) = prod*trafo(n+1,m);
|
|
1022
|
-
}
|
|
1023
|
-
|
|
1024
|
-
/*
|
|
1025
|
-
cout << " norm trafo = "
|
|
1026
|
-
<< L2Norm(trafo.Rows(m,ot+1).Cols(m,os+1))
|
|
1027
|
-
<< " ortho " << L2Norm( Trans(trafo.Rows(m,ot+1).Cols(m,os+1))*trafo.Rows(m,ot+1).Cols(m,os+1)
|
|
1028
|
-
- Identity(os+1-m)) << endl;
|
|
1029
|
-
*/
|
|
1030
|
-
/*
|
|
1031
|
-
*testout << "norm trafo = " << L2Norm(trafo.Rows(m, ot+1).Cols(m,os+1)) << endl;
|
|
1032
|
-
if ( L2Norm(trafo.Rows(m, ot+1).Cols(m,os+1)) > 1e30)
|
|
1033
|
-
{
|
|
1034
|
-
*testout << trafo.Rows(m, ot+1).Cols(m,os+1) << endl;
|
|
1035
|
-
for (int i = m; i < os+1; i++)
|
|
1036
|
-
{
|
|
1037
|
-
*testout << "norm col " << i << " = " << L2Norm(trafo.Col(i).Range(m,os+ot-i)) << endl;
|
|
1038
|
-
*testout << "col " << i << " = " << trafo.Col(i).Range(m,os+ot-i) << endl;
|
|
1039
|
-
}
|
|
1040
|
-
throw Exception("large mat");
|
|
1041
|
-
}
|
|
1042
|
-
*/
|
|
1043
|
-
|
|
1044
|
-
cout << "m = " << m << endl
|
|
1045
|
-
<< trafo.Rows(m,ot+1).Cols(m,os+1) << endl;
|
|
1046
|
-
|
|
1047
|
-
for (int n = m; n <= os; n++)
|
|
1048
|
-
hv1(n) = sh.Coef(n,m);
|
|
1049
|
-
hv2.Range(m,ot+1) = trafo.Rows(m,ot+1).Cols(m,os+1) * hv1.Range(m,os+1);
|
|
1050
|
-
for (int n = m; n <= ot; n++)
|
|
1051
|
-
target.SH().Coef(n,m) = hv2(n);
|
|
1052
|
-
|
|
1053
|
-
for (int n = m; n <= os; n++)
|
|
1054
|
-
hv1(n) = sh.Coef(n,-m);
|
|
1055
|
-
hv2.Range(m,ot+1) = trafo.Rows(m,ot+1).Cols(m,os+1) * hv1.Range(m,os+1);
|
|
1056
|
-
for (int n = m; n <= ot; n++)
|
|
1057
|
-
target.SH().Coef(n,-m) = hv2(n);
|
|
1058
|
-
}
|
|
1059
|
-
}
|
|
1060
|
-
#endif
|
|
1061
|
-
|
|
1062
|
-
|
|
1063
|
-
#ifdef VER2
|
|
1064
|
-
|
|
1065
|
-
template <typename TARGET>
|
|
1066
|
-
void ShiftZ (double z, MultiPole<TARGET> & target)
|
|
1067
|
-
{
|
|
1068
|
-
static Timer t("mptool ShiftZ"+ToString(typeid(RADIAL).name())+ToString(typeid(TARGET).name()));
|
|
1069
|
-
RegionTimer rg(t);
|
|
1070
|
-
|
|
1071
|
-
int os = sh.Order();
|
|
1072
|
-
int ot = target.SH().Order();
|
|
1073
|
-
|
|
1074
|
-
target.SH().Coefs()=0.0;
|
|
1075
|
-
|
|
1076
|
-
LocalHeap lh( 16*( (os+ot+1)*(os+1) + (os+1 + ot+1) ) + 8*2*(os+ot+1) + 500);
|
|
1077
|
-
|
|
1078
|
-
FlatMatrix<Complex> trafo(os+ot+1, os+1, lh);
|
|
1079
|
-
FlatVector<Complex> hv1(os+1, lh), hv2(ot+1, lh);
|
|
1080
|
-
FlatVector<double> amn(os+ot+1, lh);
|
|
1081
|
-
FlatVector<double> inv_amn(os+ot+1, lh);
|
|
1082
|
-
|
|
1083
|
-
// trafo = Complex(0.0);
|
|
1084
|
-
|
|
1085
|
-
double tscale = target.Scale();
|
|
1086
|
-
double inv_tscale = 1.0/tscale;
|
|
1087
|
-
|
|
1088
|
-
|
|
1089
|
-
// (185) from paper 'fast, exact, stable, Gumerov+Duraiswami
|
|
1090
|
-
// RADIAL::Eval(os+ot, kappa*abs(z), trafo.Col(0));
|
|
1091
|
-
if (typeid(RADIAL) == typeid(TARGET))
|
|
1092
|
-
SphericalBessel (os+ot, kappa*abs(z), tscale, trafo.Col(0));
|
|
1093
|
-
else
|
|
1094
|
-
SphericalHankel1 (os+ot, kappa*abs(z), inv_tscale, trafo.Col(0));
|
|
1095
|
-
|
|
1096
|
-
if (z < 0)
|
|
1097
|
-
for (int l = 1; l < trafo.Height(); l+=2) trafo(l,0) *= -1;
|
|
1098
|
-
|
|
1099
|
-
// for (int l = 0; l <= os+ot; l++)
|
|
1100
|
-
// trafo(l,0) *= sqrt(2*l+1);
|
|
1101
|
-
|
|
1102
|
-
if (os > 0)
|
|
1103
|
-
{
|
|
1104
|
-
for (int l = 1; l < os+ot; l++)
|
|
1105
|
-
{
|
|
1106
|
-
/*
|
|
1107
|
-
trafo(l,1) = -scale/sh.CalcAmn(0,0) *
|
|
1108
|
-
(sh.CalcAmn(0,l)*tscale*trafo(l+1,0)
|
|
1109
|
-
-sh.CalcAmn(0,l-1)*inv_tscale*trafo(l-1,0));
|
|
1110
|
-
*/
|
|
1111
|
-
|
|
1112
|
-
int m = 0, n = 0;
|
|
1113
|
-
double fac = ((2*l+1.0)/(2*n+1.0));
|
|
1114
|
-
trafo(l,n+1) = -scale/ ( sqrt((n+1+m)*(n+1-m)) * fac) *
|
|
1115
|
-
(sqrt( (l+1+m)*(l+1-m)) * tscale * trafo(l+1,n)
|
|
1116
|
-
-sqrt( (l+m)*(l-m) ) * inv_tscale * trafo(l-1,n)
|
|
1117
|
-
-sqrt( (n+m)*(n-m) ) * fac * scale * trafo(l,n-1));
|
|
1118
|
-
}
|
|
1119
|
-
trafo(0,1) = -scale*tscale*trafo(1,0);
|
|
1120
|
-
}
|
|
1121
|
-
|
|
1122
|
-
for (int n = 1; n < os; n++)
|
|
1123
|
-
{
|
|
1124
|
-
for (int l = 1; l < os+ot-n; l++)
|
|
1125
|
-
{
|
|
1126
|
-
/*
|
|
1127
|
-
trafo(l,n+1) = -scale/sh.CalcAmn(0,n) * (sh.CalcAmn(0,l)*tscale*trafo(l+1,n)
|
|
1128
|
-
-sh.CalcAmn(0,l-1)*inv_tscale*trafo(l-1,n)
|
|
1129
|
-
-sh.CalcAmn(0,n-1)*scale*trafo(l,n-1));
|
|
1130
|
-
*/
|
|
1131
|
-
|
|
1132
|
-
int m = 0;
|
|
1133
|
-
double fac = ((2*l+1.0)/(2*n+1.0));
|
|
1134
|
-
trafo(l,n+1) = -scale / ( sqrt((n+1+m)*(n+1-m)) * fac) *
|
|
1135
|
-
(sqrt( (l+1+m)*(l+1-m)) * tscale * trafo(l+1,n)
|
|
1136
|
-
-sqrt( (l+m)*(l-m) ) * inv_tscale * trafo(l-1,n)
|
|
1137
|
-
-sqrt( (n+m)*(n-m) ) * fac * scale * trafo(l,n-1));
|
|
1138
|
-
}
|
|
1139
|
-
trafo(0,n+1) = pow(-scale*tscale,n+1)*trafo(n+1,0);
|
|
1140
|
-
}
|
|
1141
|
-
|
|
1142
|
-
|
|
1143
|
-
Matrix<Complex> scaledtrafo(os+ot+1, os+1);
|
|
1144
|
-
for (int l = 0; l <= os+ot; l++)
|
|
1145
|
-
for (int n = 0; n <= os; n++)
|
|
1146
|
-
scaledtrafo(l,n) = trafo(l,n) * sqrt( (2*l+1)*(2*n+1) );
|
|
1147
|
-
|
|
1148
|
-
// cout << "m = " << 0 << endl
|
|
1149
|
-
// << scaledtrafo.Rows(0,ot+1) << endl;
|
|
1150
|
-
|
|
1151
|
-
for (int n = 0; n <= os; n++)
|
|
1152
|
-
hv1(n) = sh.Coef(n,0) * sqrt(2*n+1);
|
|
1153
|
-
hv2 = trafo.Rows(ot+1) * hv1;
|
|
1154
|
-
for (int n = 0; n <= ot; n++)
|
|
1155
|
-
target.SH().Coef(n,0) = hv2(n) * sqrt(2*n+1);
|
|
1156
|
-
|
|
1157
|
-
|
|
1158
|
-
for (int m = 1; m <= min(os,ot); m++)
|
|
1159
|
-
{
|
|
1160
|
-
// fill recursive formula (187)
|
|
1161
|
-
for (int l = m; l <= os+ot-m; l++)
|
|
1162
|
-
{
|
|
1163
|
-
trafo(l,m) = scale/sh.CalcBmn(-m, m) *
|
|
1164
|
-
(sh.CalcBmn(-m, l)*inv_tscale * trafo(l-1, m-1) * sqrt( (2*l-1)*(2*m-1) )
|
|
1165
|
-
-sh.CalcBmn(m-1,l+1)*tscale * trafo(l+1,m-1) * sqrt( (2*l+3)*(2*m-1)) );
|
|
1166
|
-
trafo(l,m) /= sqrt( (2*l+1)*(2*m+1) );
|
|
1167
|
-
}
|
|
1168
|
-
|
|
1169
|
-
cout << "m = " << m << endl;
|
|
1170
|
-
cout << " norm col0 = " << L2Norm(trafo.Col(m).Range(m,os+ot-m+1)) << endl;
|
|
1171
|
-
|
|
1172
|
-
for (int l = m-1; l < os+ot-m; l++)
|
|
1173
|
-
{
|
|
1174
|
-
amn(l) = sh.CalcAmn(m,l);
|
|
1175
|
-
inv_amn(l) = scale/amn(l);
|
|
1176
|
-
}
|
|
1177
|
-
|
|
1178
|
-
double prod = 1;
|
|
1179
|
-
for (int n = m; n < os; n++)
|
|
1180
|
-
{
|
|
1181
|
-
for (int l = m+1; l < os+ot-n; l++)
|
|
1182
|
-
{
|
|
1183
|
-
/*
|
|
1184
|
-
trafo(l,n+1) = -inv_amn(n) * (amn(l)*tscale*trafo(l+1,n)
|
|
1185
|
-
-amn(l-1)*inv_tscale*trafo(l-1,n)
|
|
1186
|
-
-amn(n-1)*scale*trafo(l,n-1));
|
|
1187
|
-
*/
|
|
1188
|
-
|
|
1189
|
-
|
|
1190
|
-
double fac = ((2*l+1.0)/(2*n+1.0));
|
|
1191
|
-
trafo(l,n+1) = -scale / ( sqrt((n+1+m)*(n+1-m)) * fac) *
|
|
1192
|
-
(sqrt( (l+1+m)*(l+1-m)) * tscale * trafo(l+1,n)
|
|
1193
|
-
-sqrt( (l+m)*(l-m) ) * inv_tscale * trafo(l-1,n)
|
|
1194
|
-
-sqrt( (n+m)*(n-m) ) * fac * scale * trafo(l,n-1));
|
|
1195
|
-
}
|
|
1196
|
-
prod *= -scale*tscale;
|
|
1197
|
-
trafo(m,n+1) = prod*trafo(n+1,m);
|
|
1198
|
-
}
|
|
1199
|
-
|
|
1200
|
-
double normleft = 0;
|
|
1201
|
-
for (int l = m; l <= ot; l++)
|
|
1202
|
-
for (int n = m; n <= min(l,os); n++)
|
|
1203
|
-
normleft += sqr(abs(trafo(l,n)));
|
|
1204
|
-
normleft = sqrt(normleft);
|
|
1205
|
-
cout << " norm trafo = "
|
|
1206
|
-
<< L2Norm(trafo.Rows(m,ot+1).Cols(m,os+1)) << ", normleft = " << normleft << endl;
|
|
1207
|
-
|
|
1208
|
-
// << " ortho " << L2Norm( Trans(trafo.Rows(m,ot+1).Cols(m,os+1))*trafo.Rows(m,ot+1).Cols(m,os+1)
|
|
1209
|
-
// - Identity(os+1-m)) << endl;
|
|
1210
|
-
/*
|
|
1211
|
-
*testout << "norm trafo = " << L2Norm(trafo.Rows(m, ot+1).Cols(m,os+1)) << endl;
|
|
1212
|
-
if ( L2Norm(trafo.Rows(m, ot+1).Cols(m,os+1)) > 1e30)
|
|
1213
|
-
{
|
|
1214
|
-
*testout << trafo.Rows(m, ot+1).Cols(m,os+1) << endl;
|
|
1215
|
-
for (int i = m; i < os+1; i++)
|
|
1216
|
-
{
|
|
1217
|
-
*testout << "norm col " << i << " = " << L2Norm(trafo.Col(i).Range(m,os+ot-i)) << endl;
|
|
1218
|
-
*testout << "col " << i << " = " << trafo.Col(i).Range(m,os+ot-i) << endl;
|
|
1219
|
-
}
|
|
1220
|
-
throw Exception("large mat");
|
|
1221
|
-
}
|
|
1222
|
-
*/
|
|
1223
|
-
|
|
1224
|
-
|
|
1225
|
-
/*
|
|
1226
|
-
Matrix<Complex> scaledtrafo(os+ot+1, os+1);
|
|
1227
|
-
for (int l = 0; l <= os+ot; l++)
|
|
1228
|
-
for (int n = 0; n <= os; n++)
|
|
1229
|
-
scaledtrafo(l,n) = trafo(l,n) * sqrt( (2*l+1)*(2*n+1) );
|
|
1230
|
-
|
|
1231
|
-
cout << "m = " << m << endl
|
|
1232
|
-
<< scaledtrafo.Rows(m,ot+1).Cols(m,os+1) << endl;
|
|
1233
|
-
*/
|
|
1234
|
-
|
|
1235
|
-
for (int n = m; n <= os; n++)
|
|
1236
|
-
hv1(n) = sh.Coef(n,m) * sqrt(2*n+1);
|
|
1237
|
-
hv2.Range(m,ot+1) = trafo.Rows(m,ot+1).Cols(m,os+1) * hv1.Range(m,os+1);
|
|
1238
|
-
for (int n = m; n <= ot; n++)
|
|
1239
|
-
target.SH().Coef(n,m) = hv2(n)*sqrt(2*n+1);
|
|
1240
|
-
|
|
1241
|
-
for (int n = m; n <= os; n++)
|
|
1242
|
-
hv1(n) = sh.Coef(n,-m) * sqrt(2*n+1);
|
|
1243
|
-
hv2.Range(m,ot+1) = trafo.Rows(m,ot+1).Cols(m,os+1) * hv1.Range(m,os+1);
|
|
1244
|
-
for (int n = m; n <= ot; n++)
|
|
1245
|
-
target.SH().Coef(n,-m) = hv2(n) * sqrt(2*n+1);
|
|
1246
|
-
}
|
|
1247
|
-
}
|
|
1248
|
-
#endif
|
|
1249
|
-
|
|
1250
|
-
|
|
1251
|
-
|
|
1252
|
-
|
|
1253
|
-
template <typename TARGET>
|
|
1254
|
-
void ShiftZ (double z, MultiPole<TARGET> & target)
|
|
1255
|
-
{
|
|
1256
|
-
static Timer t("mptool ShiftZ"+ToString(typeid(RADIAL).name())+ToString(typeid(TARGET).name()));
|
|
1257
|
-
RegionTimer rg(t);
|
|
1258
|
-
|
|
1259
|
-
int os = sh.Order();
|
|
1260
|
-
int ot = target.SH().Order();
|
|
1261
|
-
|
|
1262
|
-
target.SH().Coefs()=0.0;
|
|
1263
|
-
|
|
1264
|
-
LocalHeap lh( 32*( (os+ot+1)*(os+ot+1) + (os+1 + ot+1) ) + 8*3*(os+ot+1) + 500);
|
|
1265
|
-
|
|
1266
|
-
FlatMatrix<Complex> trafo(os+ot+1, max(os,ot)+1, lh);
|
|
1267
|
-
FlatMatrix<Complex> oldtrafo(os+ot+1, max(os,ot)+1, lh);
|
|
1268
|
-
FlatVector<Complex> hv1(os+1, lh), hv2(ot+1, lh);
|
|
1269
|
-
|
|
1270
|
-
// trafo = Complex(0.0);
|
|
1271
|
-
|
|
1272
|
-
double tscale = target.Scale();
|
|
1273
|
-
double inv_tscale = 1.0/tscale;
|
|
1274
|
-
|
|
1275
|
-
FlatVector<double> amn(os+ot+1, lh);
|
|
1276
|
-
FlatVector<double> inv_amn(os+ot+1, lh);
|
|
1277
|
-
|
|
1278
|
-
FlatVector<double> powscale(os+1, lh);
|
|
1279
|
-
double prod = 1;
|
|
1280
|
-
for (int i = 0; i <= os; i++)
|
|
1281
|
-
{
|
|
1282
|
-
powscale(i) = prod;
|
|
1283
|
-
prod *= -scale*tscale;
|
|
1284
|
-
}
|
|
1285
|
-
|
|
1286
|
-
// (185) from paper 'fast, exact, stable, Gumerov+Duraiswami
|
|
1287
|
-
// RADIAL::Eval(os+ot, kappa*abs(z), trafo.Col(0));
|
|
1288
|
-
if (typeid(RADIAL) == typeid(TARGET))
|
|
1289
|
-
SphericalBessel (os+ot, kappa*abs(z), tscale, trafo.Col(0));
|
|
1290
|
-
else
|
|
1291
|
-
SphericalHankel1 (os+ot, kappa*abs(z), inv_tscale, trafo.Col(0));
|
|
1292
|
-
|
|
1293
|
-
if (z < 0)
|
|
1294
|
-
for (int l = 1; l < trafo.Height(); l+=2) trafo(l,0) *= -1;
|
|
1295
|
-
|
|
1296
|
-
for (int l = 0; l <= os+ot; l++)
|
|
1297
|
-
trafo(l,0) *= sqrt(2*l+1);
|
|
1298
|
-
|
|
1299
|
-
// for (int l = 0; l <= os+ot; l++)
|
|
1300
|
-
// trafo(l,0) *= sqrt(2*l+1);
|
|
1301
|
-
|
|
1302
|
-
if (os > 0)
|
|
1303
|
-
{
|
|
1304
|
-
for (int l = 1; l < os+ot; l++)
|
|
1305
|
-
trafo(l,1) = -scale/sh.CalcAmn(0,0) * (sh.CalcAmn(0,l)*tscale*trafo(l+1,0)
|
|
1306
|
-
-sh.CalcAmn(0,l-1)*inv_tscale*trafo(l-1,0));
|
|
1307
|
-
trafo(0,1) = -scale*tscale*trafo(1,0);
|
|
1308
|
-
}
|
|
1309
|
-
|
|
1310
|
-
for (int n = 1; n < trafo.Width()-1; n++)
|
|
1311
|
-
{
|
|
1312
|
-
for (int l = 1; l < os+ot-n; l++)
|
|
1313
|
-
trafo(l,n+1) = -scale/sh.CalcAmn(0,n) * (sh.CalcAmn(0,l)*tscale*trafo(l+1,n)
|
|
1314
|
-
-sh.CalcAmn(0,l-1)*inv_tscale*trafo(l-1,n)
|
|
1315
|
-
-sh.CalcAmn(0,n-1)*scale*trafo(l,n-1));
|
|
1316
|
-
trafo(0,n+1) = pow(-scale*tscale,n+1)*trafo(n+1,0);
|
|
1317
|
-
}
|
|
1318
|
-
|
|
1319
|
-
for (int n = 0; n <= os; n++)
|
|
1320
|
-
hv1(n) = sh.Coef(n,0);
|
|
1321
|
-
hv2 = trafo.Rows(ot+1).Cols(os+1) * hv1;
|
|
1322
|
-
for (int n = 0; n <= ot; n++)
|
|
1323
|
-
target.SH().Coef(n,0) = hv2(n);
|
|
1324
|
-
|
|
1325
|
-
|
|
1326
|
-
for (int m = 1; m <= min(os,ot); m++)
|
|
1327
|
-
{
|
|
1328
|
-
|
|
1329
|
-
|
|
1330
|
-
for (int l = m-1; l < os+ot-m; l++)
|
|
1331
|
-
{
|
|
1332
|
-
amn(l) = sh.CalcAmn(m,l);
|
|
1333
|
-
inv_amn(l) = scale/amn(l);
|
|
1334
|
-
}
|
|
1335
|
-
|
|
1336
|
-
if (typeid(RADIAL) != typeid(TARGET))
|
|
1337
|
-
|
|
1338
|
-
{
|
|
1339
|
-
// fill recursive formula (187)
|
|
1340
|
-
for (int l = m; l <= os+ot-m; l++)
|
|
1341
|
-
trafo(l,m) = scale/sh.CalcBmn(-m, m) * (sh.CalcBmn(-m, l)*inv_tscale*trafo(l-1, m-1)
|
|
1342
|
-
-sh.CalcBmn(m-1,l+1)*tscale*trafo(l+1,m-1));
|
|
1343
|
-
|
|
1344
|
-
for (int n = m; n < os; n++)
|
|
1345
|
-
{
|
|
1346
|
-
for (int l = n+1; l < os+ot-n; l++)
|
|
1347
|
-
trafo(l,n+1) = -inv_amn(n) * (amn(l)*tscale*trafo(l+1,n)
|
|
1348
|
-
-amn(l-1)*inv_tscale*trafo(l-1,n)
|
|
1349
|
-
-amn(n-1)*scale*trafo(l,n-1));
|
|
1350
|
-
}
|
|
1351
|
-
}
|
|
1352
|
-
|
|
1353
|
-
else
|
|
1354
|
-
|
|
1355
|
-
{
|
|
1356
|
-
/*
|
|
1357
|
-
for (int n = m; n < trafo.Width()-1; n++)
|
|
1358
|
-
{
|
|
1359
|
-
for (int l = n+1; l < os+ot-n; l++)
|
|
1360
|
-
trafo(l,n+1) = -inv_amn(n) * (amn(l)*tscale*trafo(l+1,n)
|
|
1361
|
-
-amn(l-1)*inv_tscale*trafo(l-1,n)
|
|
1362
|
-
-amn(n-1)*scale*trafo(l,n-1));
|
|
1363
|
-
}
|
|
1364
|
-
*/
|
|
1365
|
-
|
|
1366
|
-
trafo.Swap (oldtrafo);
|
|
1367
|
-
trafo = 0.0;
|
|
1368
|
-
|
|
1369
|
-
// fill recursive formula (187)
|
|
1370
|
-
for (int l = m; l <= os+ot-m; l++)
|
|
1371
|
-
trafo(l,m) = scale/sh.CalcBmn(-m, m) * (sh.CalcBmn(-m, l)*inv_tscale*oldtrafo(l-1, m-1)
|
|
1372
|
-
-sh.CalcBmn(m-1,l+1)*tscale*oldtrafo(l+1,m-1));
|
|
1373
|
-
|
|
1374
|
-
for (int n = m; n < trafo.Width()-1; n++)
|
|
1375
|
-
{
|
|
1376
|
-
// int l = 2*order-n-1;
|
|
1377
|
-
int l = trafo.Height()-n-2;
|
|
1378
|
-
|
|
1379
|
-
trafo(l,n+1) = scale/sh.CalcBmn(-m,n+1)* (sh.CalcBmn(m-1,n) * scale*trafo(l,n-1)
|
|
1380
|
-
- sh.CalcBmn(m-1,l+1)*tscale*oldtrafo(l+1,n)
|
|
1381
|
-
+ sh.CalcBmn(-m,l) * 1/tscale*oldtrafo(l-1,n) );
|
|
1382
|
-
|
|
1383
|
-
trafo(l-1,n) = tscale/amn(l-1) * (amn(l) * tscale*trafo(l+1,n)
|
|
1384
|
-
- amn(n-1)* scale*trafo(l,n-1)
|
|
1385
|
-
+ amn(n)* 1/scale*trafo(l,n+1));
|
|
1386
|
-
}
|
|
1387
|
-
|
|
1388
|
-
// the same thing 1 row up
|
|
1389
|
-
for (int n = m; n < trafo.Width()-2; n++)
|
|
1390
|
-
{
|
|
1391
|
-
// int l = 2*order-n-2;
|
|
1392
|
-
int l = trafo.Height()-n-3;
|
|
1393
|
-
|
|
1394
|
-
trafo(l,n+1) = scale/sh.CalcBmn(-m,n+1)* (sh.CalcBmn(m-1,n) * scale*trafo(l,n-1)
|
|
1395
|
-
- sh.CalcBmn(m-1,l+1) * tscale* oldtrafo(l+1,n)
|
|
1396
|
-
+ sh.CalcBmn(-m,l) * 1/tscale* oldtrafo(l-1,n) );
|
|
1397
|
-
|
|
1398
|
-
trafo(l-1,n) = tscale/amn(l-1) * (amn(l) * tscale*trafo(l+1,n)
|
|
1399
|
-
-amn(n-1)* scale*trafo(l,n-1) +
|
|
1400
|
-
amn(n) * 1/scale*trafo(l,n+1)) ;
|
|
1401
|
-
}
|
|
1402
|
-
|
|
1403
|
-
|
|
1404
|
-
// for (int l = 2*order; l >= m; l--)
|
|
1405
|
-
// for (int n = m+1; n < min(2*order-l,l); n++)
|
|
1406
|
-
for (int l = trafo.Height()-1; l >= m; l--)
|
|
1407
|
-
for (int n = m+1; n < min<int>(trafo.Height()-1-l,l); n++)
|
|
1408
|
-
{
|
|
1409
|
-
trafo(l-1,n) = tscale/amn(l-1)* ( amn(l) * tscale*trafo(l+1,n)
|
|
1410
|
-
-amn(n-1)* scale*trafo(l,n-1)
|
|
1411
|
-
+amn(n) * 1/scale*trafo(l,n+1)) ;
|
|
1412
|
-
}
|
|
1413
|
-
}
|
|
1414
|
-
|
|
1415
|
-
|
|
1416
|
-
/*
|
|
1417
|
-
cout << "m = " << m << endl
|
|
1418
|
-
<< trafo << endl;
|
|
1419
|
-
*/
|
|
1420
|
-
for (int n = m; n < os; n++)
|
|
1421
|
-
for (int l = n+1; l <= os; l++)
|
|
1422
|
-
trafo(n,l) = powscale(l-n) * trafo(l,n);
|
|
1423
|
-
// trafo(n,l) = pow(-scale*tscale, l-n) * trafo(l,n);
|
|
1424
|
-
|
|
1425
|
-
/*
|
|
1426
|
-
cout << " norm trafo = "
|
|
1427
|
-
<< L2Norm(trafo.Rows(m,ot+1).Cols(m,os+1)) << endl;
|
|
1428
|
-
*/
|
|
1429
|
-
|
|
1430
|
-
for (int n = m; n <= os; n++)
|
|
1431
|
-
hv1(n) = sh.Coef(n,m);
|
|
1432
|
-
hv2.Range(m,ot+1) = trafo.Rows(m,ot+1).Cols(m,os+1) * hv1.Range(m,os+1);
|
|
1433
|
-
for (int n = m; n <= ot; n++)
|
|
1434
|
-
target.SH().Coef(n,m) = hv2(n);
|
|
1435
|
-
|
|
1436
|
-
for (int n = m; n <= os; n++)
|
|
1437
|
-
hv1(n) = sh.Coef(n,-m);
|
|
1438
|
-
hv2.Range(m,ot+1) = trafo.Rows(m,ot+1).Cols(m,os+1) * hv1.Range(m,os+1);
|
|
1439
|
-
for (int n = m; n <= ot; n++)
|
|
1440
|
-
target.SH().Coef(n,-m) = hv2(n);
|
|
1441
|
-
}
|
|
1442
|
-
}
|
|
1443
|
-
|
|
1444
|
-
|
|
1445
|
-
|
|
1446
|
-
|
|
1447
|
-
|
|
346
|
+
void ShiftZ (double z, MultiPole<TARGET> & target);
|
|
1448
347
|
|
|
1449
348
|
};
|
|
1450
349
|
|
|
@@ -1475,7 +374,7 @@ c
|
|
|
1475
374
|
int total_sources;
|
|
1476
375
|
|
|
1477
376
|
Node (Vec<3> acenter, double ar, int alevel, int order, double kappa)
|
|
1478
|
-
: center(acenter), r(ar), level(alevel), mp(MPOrder(ar*kappa), kappa, min(1.0,
|
|
377
|
+
: center(acenter), r(ar), level(alevel), mp(MPOrder(ar*kappa), kappa, min(1.0, r*kappa))
|
|
1479
378
|
// : center(acenter), r(ar), level(alevel), mp(MPOrder(ar*kappa), kappa, 1.0)
|
|
1480
379
|
{
|
|
1481
380
|
// cout << "singml, add node, level = " << level << endl;
|
|
@@ -1754,7 +653,7 @@ c
|
|
|
1754
653
|
}
|
|
1755
654
|
|
|
1756
655
|
|
|
1757
|
-
class RegularMLMultiPole
|
|
656
|
+
class NGS_DLL_HEADER RegularMLMultiPole
|
|
1758
657
|
{
|
|
1759
658
|
static Array<size_t> nodes_on_level;
|
|
1760
659
|
|
|
@@ -2076,11 +975,22 @@ c
|
|
|
2076
975
|
|
|
2077
976
|
};
|
|
2078
977
|
|
|
2079
|
-
Array<size_t> RegularMLMultiPole::nodes_on_level(100);
|
|
2080
|
-
Array<size_t> SingularMLMultiPole::nodes_on_level(100);
|
|
2081
978
|
|
|
979
|
+
inline ostream & operator<< (ostream & ost, const RegularMLMultiPole & mlmp)
|
|
980
|
+
{
|
|
981
|
+
// mlmp.Print(ost);
|
|
982
|
+
ost << "RegularMLMultiPole" << endl;
|
|
983
|
+
return ost;
|
|
984
|
+
}
|
|
985
|
+
|
|
986
|
+
|
|
987
|
+
|
|
988
|
+
|
|
989
|
+
|
|
990
|
+
|
|
2082
991
|
// ******************** Coefficient Functions *********************
|
|
2083
992
|
|
|
993
|
+
|
|
2084
994
|
class SphericalHarmonicsCF : public CoefficientFunction
|
|
2085
995
|
{
|
|
2086
996
|
SphericalHarmonics sh;
|
|
@@ -2166,20 +1076,20 @@ c
|
|
|
2166
1076
|
|
|
2167
1077
|
class RegularMLMultiPoleCF : public CoefficientFunction
|
|
2168
1078
|
{
|
|
2169
|
-
RegularMLMultiPole mlmp;
|
|
1079
|
+
shared_ptr<RegularMLMultiPole> mlmp;
|
|
2170
1080
|
public:
|
|
2171
1081
|
RegularMLMultiPoleCF (shared_ptr<SingularMLMultiPoleCF> asingmp, Vec<3> center, double r, int order)
|
|
2172
|
-
: CoefficientFunction(1, true), mlmp(asingmp->MLMP(), center, r, order) { }
|
|
1082
|
+
: CoefficientFunction(1, true), mlmp{make_shared<RegularMLMultiPole>(asingmp->MLMP(), center, r, order)} { }
|
|
2173
1083
|
|
|
2174
1084
|
virtual double Evaluate (const BaseMappedIntegrationPoint & ip) const override
|
|
2175
1085
|
{ throw Exception("real eval not available"); }
|
|
2176
1086
|
|
|
2177
1087
|
virtual void Evaluate (const BaseMappedIntegrationPoint & mip, FlatVector<Complex> values) const override
|
|
2178
1088
|
{
|
|
2179
|
-
values(0) = mlmp
|
|
1089
|
+
values(0) = mlmp->Evaluate(mip.GetPoint());
|
|
2180
1090
|
}
|
|
2181
1091
|
|
|
2182
|
-
RegularMLMultiPole
|
|
1092
|
+
shared_ptr<RegularMLMultiPole> MLMP() { return mlmp; }
|
|
2183
1093
|
};
|
|
2184
1094
|
|
|
2185
1095
|
|