ngsolve 6.2.2501.post83.dev1__cp313-cp313-macosx_10_15_universal2.whl → 6.2.2502.post11.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/facetfespace.hpp +2 -0
- netgen/include/fespace.hpp +4 -2
- netgen/include/mptools.hpp +318 -85
- netgen/include/ngblas.hpp +14 -0
- netgen/include/potentialtools.hpp +20 -0
- netgen/include/prolongation.hpp +143 -1
- netgen/include/python_ngstd.hpp +1 -0
- netgen/include/sparsecholesky.hpp +1 -1
- netgen/include/sparsematrix_impl.hpp +71 -5
- netgen/include/tangentialfacetfespace.hpp +7 -22
- netgen/include/tensor.hpp +1 -1
- 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 +2 -2
- ngsolve/cmake/NGSolveConfig.cmake +1 -1
- ngsolve/comp/__init__.pyi +11 -1
- ngsolve/config/__init__.pyi +7 -7
- ngsolve/config/config.py +6 -6
- ngsolve/config/config.pyi +7 -7
- ngsolve/directsolvers.pyi +1 -1
- ngsolve/fem.pyi +33 -1
- ngsolve/krylovspace.pyi +2 -2
- ngsolve/nonlinearsolvers.pyi +1 -1
- ngsolve/timestepping.pyi +3 -3
- ngsolve/utils.pyi +7 -2
- {ngsolve-6.2.2501.post83.dev1.dist-info → ngsolve-6.2.2502.post11.dev1.dist-info}/METADATA +2 -2
- {ngsolve-6.2.2501.post83.dev1.dist-info → ngsolve-6.2.2502.post11.dev1.dist-info}/RECORD +66 -65
- {ngsolve-6.2.2501.post83.dev1.data → ngsolve-6.2.2502.post11.dev1.data}/data/Netgen.icns +0 -0
- {ngsolve-6.2.2501.post83.dev1.data → ngsolve-6.2.2502.post11.dev1.data}/data/bin/ngscxx +0 -0
- {ngsolve-6.2.2501.post83.dev1.data → ngsolve-6.2.2502.post11.dev1.data}/data/bin/ngsld +0 -0
- {ngsolve-6.2.2501.post83.dev1.data → ngsolve-6.2.2502.post11.dev1.data}/data/bin/ngsolve.tcl +0 -0
- {ngsolve-6.2.2501.post83.dev1.data → ngsolve-6.2.2502.post11.dev1.data}/data/bin/ngspy +0 -0
- {ngsolve-6.2.2501.post83.dev1.data → ngsolve-6.2.2502.post11.dev1.data}/data/share/ngsolve/beam.geo +0 -0
- {ngsolve-6.2.2501.post83.dev1.data → ngsolve-6.2.2502.post11.dev1.data}/data/share/ngsolve/beam.vol +0 -0
- {ngsolve-6.2.2501.post83.dev1.data → ngsolve-6.2.2502.post11.dev1.data}/data/share/ngsolve/chip.in2d +0 -0
- {ngsolve-6.2.2501.post83.dev1.data → ngsolve-6.2.2502.post11.dev1.data}/data/share/ngsolve/chip.vol +0 -0
- {ngsolve-6.2.2501.post83.dev1.data → ngsolve-6.2.2502.post11.dev1.data}/data/share/ngsolve/coil.geo +0 -0
- {ngsolve-6.2.2501.post83.dev1.data → ngsolve-6.2.2502.post11.dev1.data}/data/share/ngsolve/coil.vol +0 -0
- {ngsolve-6.2.2501.post83.dev1.data → ngsolve-6.2.2502.post11.dev1.data}/data/share/ngsolve/coilshield.geo +0 -0
- {ngsolve-6.2.2501.post83.dev1.data → ngsolve-6.2.2502.post11.dev1.data}/data/share/ngsolve/coilshield.vol +0 -0
- {ngsolve-6.2.2501.post83.dev1.data → ngsolve-6.2.2502.post11.dev1.data}/data/share/ngsolve/cube.geo +0 -0
- {ngsolve-6.2.2501.post83.dev1.data → ngsolve-6.2.2502.post11.dev1.data}/data/share/ngsolve/cube.vol +0 -0
- {ngsolve-6.2.2501.post83.dev1.data → ngsolve-6.2.2502.post11.dev1.data}/data/share/ngsolve/d10_DGdoubleglazing.pde +0 -0
- {ngsolve-6.2.2501.post83.dev1.data → ngsolve-6.2.2502.post11.dev1.data}/data/share/ngsolve/d11_chip_nitsche.pde +0 -0
- {ngsolve-6.2.2501.post83.dev1.data → ngsolve-6.2.2502.post11.dev1.data}/data/share/ngsolve/d1_square.pde +0 -0
- {ngsolve-6.2.2501.post83.dev1.data → ngsolve-6.2.2502.post11.dev1.data}/data/share/ngsolve/d2_chip.pde +0 -0
- {ngsolve-6.2.2501.post83.dev1.data → ngsolve-6.2.2502.post11.dev1.data}/data/share/ngsolve/d3_helmholtz.pde +0 -0
- {ngsolve-6.2.2501.post83.dev1.data → ngsolve-6.2.2502.post11.dev1.data}/data/share/ngsolve/d4_cube.pde +0 -0
- {ngsolve-6.2.2501.post83.dev1.data → ngsolve-6.2.2502.post11.dev1.data}/data/share/ngsolve/d5_beam.pde +0 -0
- {ngsolve-6.2.2501.post83.dev1.data → ngsolve-6.2.2502.post11.dev1.data}/data/share/ngsolve/d6_shaft.pde +0 -0
- {ngsolve-6.2.2501.post83.dev1.data → ngsolve-6.2.2502.post11.dev1.data}/data/share/ngsolve/d7_coil.pde +0 -0
- {ngsolve-6.2.2501.post83.dev1.data → ngsolve-6.2.2502.post11.dev1.data}/data/share/ngsolve/d8_coilshield.pde +0 -0
- {ngsolve-6.2.2501.post83.dev1.data → ngsolve-6.2.2502.post11.dev1.data}/data/share/ngsolve/d9_hybridDG.pde +0 -0
- {ngsolve-6.2.2501.post83.dev1.data → ngsolve-6.2.2502.post11.dev1.data}/data/share/ngsolve/doubleglazing.in2d +0 -0
- {ngsolve-6.2.2501.post83.dev1.data → ngsolve-6.2.2502.post11.dev1.data}/data/share/ngsolve/doubleglazing.vol +0 -0
- {ngsolve-6.2.2501.post83.dev1.data → ngsolve-6.2.2502.post11.dev1.data}/data/share/ngsolve/piezo2d40round4.vol.gz +0 -0
- {ngsolve-6.2.2501.post83.dev1.data → ngsolve-6.2.2502.post11.dev1.data}/data/share/ngsolve/shaft.geo +0 -0
- {ngsolve-6.2.2501.post83.dev1.data → ngsolve-6.2.2502.post11.dev1.data}/data/share/ngsolve/shaft.vol +0 -0
- {ngsolve-6.2.2501.post83.dev1.data → ngsolve-6.2.2502.post11.dev1.data}/data/share/ngsolve/square.in2d +0 -0
- {ngsolve-6.2.2501.post83.dev1.data → ngsolve-6.2.2502.post11.dev1.data}/data/share/ngsolve/square.vol +0 -0
- {ngsolve-6.2.2501.post83.dev1.dist-info → ngsolve-6.2.2502.post11.dev1.dist-info}/LICENSE +0 -0
- {ngsolve-6.2.2501.post83.dev1.dist-info → ngsolve-6.2.2502.post11.dev1.dist-info}/WHEEL +0 -0
- {ngsolve-6.2.2501.post83.dev1.dist-info → ngsolve-6.2.2502.post11.dev1.dist-info}/top_level.txt +0 -0
netgen/include/mptools.hpp
CHANGED
|
@@ -10,27 +10,31 @@
|
|
|
10
10
|
#include <coefficient.hpp>
|
|
11
11
|
#include <recursive_pol.hpp>
|
|
12
12
|
|
|
13
|
+
|
|
14
|
+
namespace ngcomp
|
|
15
|
+
{
|
|
16
|
+
class Region;
|
|
17
|
+
}
|
|
18
|
+
|
|
13
19
|
namespace ngfem
|
|
14
20
|
{
|
|
15
21
|
|
|
16
22
|
|
|
17
|
-
|
|
23
|
+
template <typename entry_type = Complex>
|
|
18
24
|
class NGS_DLL_HEADER SphericalHarmonics
|
|
19
25
|
{
|
|
20
26
|
int order;
|
|
21
|
-
Vector<
|
|
27
|
+
Vector<entry_type> coefs;
|
|
22
28
|
|
|
23
29
|
public:
|
|
24
30
|
SphericalHarmonics (int aorder)
|
|
25
31
|
: order(aorder), coefs(sqr(order+1)) { coefs=0.0; }
|
|
26
32
|
|
|
27
33
|
int Order() const { return order; }
|
|
28
|
-
FlatVector<
|
|
29
|
-
|
|
30
|
-
|
|
31
|
-
{
|
|
32
|
-
return coefs(n*(n+1) + m);
|
|
33
|
-
}
|
|
34
|
+
FlatVector<entry_type> Coefs() const { return coefs; }
|
|
35
|
+
|
|
36
|
+
entry_type & Coef(int n, int m) { return coefs(n*(n+1) + m); }
|
|
37
|
+
entry_type Coef(int n, int m) const { return coefs(n*(n+1) + m); }
|
|
34
38
|
|
|
35
39
|
auto CoefsN (int n) const
|
|
36
40
|
{
|
|
@@ -53,29 +57,29 @@ namespace ngfem
|
|
|
53
57
|
return { theta, phi };
|
|
54
58
|
}
|
|
55
59
|
|
|
56
|
-
|
|
60
|
+
entry_type Eval (Vec<3> x) const
|
|
57
61
|
{
|
|
58
62
|
auto [theta, phi] = Polar(x);
|
|
59
63
|
return Eval(theta, phi);
|
|
60
64
|
}
|
|
61
65
|
|
|
62
|
-
|
|
66
|
+
entry_type Eval (double theta, double phi) const;
|
|
63
67
|
|
|
64
|
-
|
|
68
|
+
entry_type EvalOrder (int n, Vec<3> x) const
|
|
65
69
|
{
|
|
66
70
|
auto [theta, phi] = Polar (x);
|
|
67
71
|
return EvalOrder(n, theta, phi);
|
|
68
72
|
}
|
|
69
73
|
|
|
70
|
-
|
|
74
|
+
entry_type EvalOrder (int n, double theta, double phi) const;
|
|
71
75
|
|
|
72
|
-
void EvalOrders (Vec<3> x, FlatVector<
|
|
76
|
+
void EvalOrders (Vec<3> x, FlatVector<entry_type> vals) const
|
|
73
77
|
{
|
|
74
78
|
auto [theta, phi] = Polar(x);
|
|
75
79
|
return EvalOrders(theta, phi, vals);
|
|
76
80
|
}
|
|
77
81
|
|
|
78
|
-
void EvalOrders (double theta, double phi, FlatVector<
|
|
82
|
+
void EvalOrders (double theta, double phi, FlatVector<entry_type> vals) const;
|
|
79
83
|
|
|
80
84
|
void Calc (Vec<3> x, FlatVector<Complex> shapes);
|
|
81
85
|
|
|
@@ -106,7 +110,7 @@ namespace ngfem
|
|
|
106
110
|
|
|
107
111
|
// Nail A. Gumerov and Ramani Duraiswami book, formula (2.2.12)
|
|
108
112
|
// add directional derivative divided by kappa to res, both multipoles need same scaling
|
|
109
|
-
void DirectionalDiffAdd (Vec<3> d, SphericalHarmonics & res, double scale = 1);
|
|
113
|
+
void DirectionalDiffAdd (Vec<3> d, SphericalHarmonics<entry_type> & res, double scale = 1) const;
|
|
110
114
|
|
|
111
115
|
};
|
|
112
116
|
|
|
@@ -234,24 +238,24 @@ namespace ngfem
|
|
|
234
238
|
|
|
235
239
|
|
|
236
240
|
|
|
237
|
-
template <typename RADIAL>
|
|
241
|
+
template <typename RADIAL, typename entry_type=Complex>
|
|
238
242
|
class NGS_DLL_HEADER MultiPole
|
|
239
243
|
{
|
|
240
|
-
SphericalHarmonics sh;
|
|
244
|
+
SphericalHarmonics<entry_type> sh;
|
|
241
245
|
double kappa;
|
|
242
246
|
double scale;
|
|
243
247
|
public:
|
|
244
248
|
MultiPole (int aorder, double akappa, double ascale = 1)
|
|
245
249
|
: sh(aorder), kappa(akappa), scale(ascale) { }
|
|
246
250
|
|
|
247
|
-
|
|
251
|
+
entry_type & Coef(int n, int m) { return sh.Coef(n,m); }
|
|
248
252
|
auto & SH() { return sh; }
|
|
249
253
|
const auto & SH() const { return sh; }
|
|
250
254
|
double Kappa() const { return kappa; }
|
|
251
255
|
double Scale() const { return scale; }
|
|
252
256
|
int Order() const { return sh.Order(); }
|
|
253
257
|
|
|
254
|
-
MultiPole
|
|
258
|
+
MultiPole Truncate(int neworder) const
|
|
255
259
|
{
|
|
256
260
|
if (neworder > sh.Order()) neworder=sh.Order();
|
|
257
261
|
MultiPole nmp(neworder, kappa);
|
|
@@ -266,10 +270,12 @@ namespace ngfem
|
|
|
266
270
|
return *this;
|
|
267
271
|
}
|
|
268
272
|
|
|
269
|
-
|
|
273
|
+
entry_type Eval (Vec<3> x) const;
|
|
274
|
+
entry_type EvalDirectionalDerivative (Vec<3> x, Vec<3> d) const;
|
|
270
275
|
|
|
271
|
-
void AddCharge (Vec<3> x,
|
|
272
|
-
void AddDipole (Vec<3> x, Vec<3> d,
|
|
276
|
+
void AddCharge (Vec<3> x, entry_type c);
|
|
277
|
+
void AddDipole (Vec<3> x, Vec<3> d, entry_type c);
|
|
278
|
+
void AddCurrent (Vec<3> ap, Vec<3> ep, Complex j, int num=100);
|
|
273
279
|
|
|
274
280
|
|
|
275
281
|
void ChangeScaleTo (double newscale)
|
|
@@ -295,7 +301,7 @@ namespace ngfem
|
|
|
295
301
|
|
|
296
302
|
|
|
297
303
|
template <typename TARGET>
|
|
298
|
-
void Transform (MultiPole<TARGET> & target, Vec<3> dist) const
|
|
304
|
+
void Transform (MultiPole<TARGET,entry_type> & target, Vec<3> dist) const
|
|
299
305
|
{
|
|
300
306
|
if (target.SH().Order() < 0) return;
|
|
301
307
|
if (SH().Order() < 0)
|
|
@@ -321,7 +327,7 @@ namespace ngfem
|
|
|
321
327
|
phi = atan2(dist(1), dist(0));
|
|
322
328
|
|
|
323
329
|
|
|
324
|
-
MultiPole<RADIAL> tmp(*this);
|
|
330
|
+
MultiPole<RADIAL,entry_type> tmp(*this);
|
|
325
331
|
tmp.SH().RotateZ(phi);
|
|
326
332
|
tmp.SH().RotateY(theta);
|
|
327
333
|
|
|
@@ -332,18 +338,18 @@ namespace ngfem
|
|
|
332
338
|
}
|
|
333
339
|
|
|
334
340
|
template <typename TARGET>
|
|
335
|
-
void TransformAdd (MultiPole<TARGET> & target, Vec<3> dist) const
|
|
341
|
+
void TransformAdd (MultiPole<TARGET,entry_type> & target, Vec<3> dist) const
|
|
336
342
|
{
|
|
337
343
|
if (SH().Order() < 0) return;
|
|
338
344
|
if (target.SH().Order() < 0) return;
|
|
339
345
|
|
|
340
|
-
MultiPole<TARGET> tmp{target};
|
|
346
|
+
MultiPole<TARGET,entry_type> tmp{target};
|
|
341
347
|
Transform(tmp, dist);
|
|
342
348
|
target.SH().Coefs() += tmp.SH().Coefs();
|
|
343
349
|
}
|
|
344
350
|
|
|
345
351
|
template <typename TARGET>
|
|
346
|
-
void ShiftZ (double z, MultiPole<TARGET> & target);
|
|
352
|
+
void ShiftZ (double z, MultiPole<TARGET,entry_type> & target);
|
|
347
353
|
|
|
348
354
|
};
|
|
349
355
|
|
|
@@ -351,12 +357,14 @@ namespace ngfem
|
|
|
351
357
|
|
|
352
358
|
// ***************** parameters ****************
|
|
353
359
|
|
|
354
|
-
static int MPOrder (double rho_kappa)
|
|
360
|
+
static constexpr int MPOrder (double rho_kappa)
|
|
355
361
|
{
|
|
356
362
|
return max (20, int(2*rho_kappa));
|
|
357
363
|
}
|
|
358
364
|
static constexpr int maxdirect = 100;
|
|
359
365
|
|
|
366
|
+
|
|
367
|
+
template <typename entry_type=Complex>
|
|
360
368
|
class SingularMLMultiPole
|
|
361
369
|
{
|
|
362
370
|
static Array<size_t> nodes_on_level;
|
|
@@ -367,10 +375,11 @@ namespace ngfem
|
|
|
367
375
|
double r;
|
|
368
376
|
int level;
|
|
369
377
|
std::array<unique_ptr<Node>,8> childs;
|
|
370
|
-
MultiPole<MPSingular> mp;
|
|
378
|
+
MultiPole<MPSingular, entry_type> mp;
|
|
371
379
|
|
|
372
|
-
Array<tuple<Vec<3>,
|
|
373
|
-
Array<tuple<Vec<3>, Vec<3>,
|
|
380
|
+
Array<tuple<Vec<3>, entry_type>> charges;
|
|
381
|
+
Array<tuple<Vec<3>, Vec<3>, entry_type>> dipoles;
|
|
382
|
+
Array<tuple<Vec<3>, Vec<3>, Complex,int>> currents;
|
|
374
383
|
int total_sources;
|
|
375
384
|
|
|
376
385
|
Node (Vec<3> acenter, double ar, int alevel, int order, double kappa)
|
|
@@ -397,7 +406,7 @@ namespace ngfem
|
|
|
397
406
|
}
|
|
398
407
|
|
|
399
408
|
|
|
400
|
-
void AddCharge (Vec<3> x,
|
|
409
|
+
void AddCharge (Vec<3> x, entry_type c)
|
|
401
410
|
{
|
|
402
411
|
if (childs[0])
|
|
403
412
|
{
|
|
@@ -422,13 +431,16 @@ namespace ngfem
|
|
|
422
431
|
AddCharge (x,c);
|
|
423
432
|
for (auto [x,d,c] : dipoles)
|
|
424
433
|
AddDipole (x,d,c);
|
|
434
|
+
for (auto [sp,ep,j,num] : currents)
|
|
435
|
+
AddCurrent (sp,ep,j,num);
|
|
425
436
|
|
|
426
437
|
charges.SetSize0();
|
|
427
|
-
dipoles.SetSize0();
|
|
438
|
+
dipoles.SetSize0();
|
|
439
|
+
currents.SetSize0();
|
|
428
440
|
}
|
|
429
441
|
|
|
430
442
|
|
|
431
|
-
void AddDipole (Vec<3> x, Vec<3> d,
|
|
443
|
+
void AddDipole (Vec<3> x, Vec<3> d, entry_type c)
|
|
432
444
|
{
|
|
433
445
|
if (childs[0])
|
|
434
446
|
{
|
|
@@ -453,15 +465,70 @@ namespace ngfem
|
|
|
453
465
|
AddCharge (x,c);
|
|
454
466
|
for (auto [x,d,c] : dipoles)
|
|
455
467
|
AddDipole (x,d,c);
|
|
468
|
+
for (auto [sp,ep,j,num] : currents)
|
|
469
|
+
AddCurrent (sp,ep,j,num);
|
|
456
470
|
|
|
457
471
|
charges.SetSize0();
|
|
458
472
|
dipoles.SetSize0();
|
|
473
|
+
currents.SetSize0();
|
|
459
474
|
}
|
|
460
475
|
|
|
476
|
+
void AddCurrent (Vec<3> sp, Vec<3> ep, Complex j, int num)
|
|
477
|
+
{
|
|
478
|
+
if (childs[0])
|
|
479
|
+
{
|
|
480
|
+
// split line and send to childs
|
|
481
|
+
Array<double> split;
|
|
482
|
+
split.Append(0);
|
|
483
|
+
for (int i = 0; i < 3; i++)
|
|
484
|
+
if (sp(i) < center(i) != ep(i) < center(i))
|
|
485
|
+
split += (center(i)-sp(i)) / (ep(i)-sp(i)); // segment cuts i-th coordinate plane
|
|
486
|
+
split.Append(1);
|
|
487
|
+
BubbleSort(split);
|
|
488
|
+
|
|
489
|
+
for (int i = 0; i < split.Size()-1; i++)
|
|
490
|
+
if (split[i+1] > split[i])
|
|
491
|
+
{
|
|
492
|
+
Vec<3> spi = sp + split[i]*(ep-sp);
|
|
493
|
+
Vec<3> epi = sp + split[i+1]*(ep-sp);
|
|
494
|
+
|
|
495
|
+
Vec<3> x = 0.5*(spi+epi);
|
|
496
|
+
|
|
497
|
+
int childnum = 0;
|
|
498
|
+
if (x(0) > center(0)) childnum += 1;
|
|
499
|
+
if (x(1) > center(1)) childnum += 2;
|
|
500
|
+
if (x(2) > center(2)) childnum += 4;
|
|
501
|
+
childs[childnum] -> AddCurrent(spi, epi, j, num);
|
|
502
|
+
}
|
|
503
|
+
return;
|
|
504
|
+
}
|
|
505
|
+
|
|
506
|
+
currents.Append (tuple{sp,ep,j,num});
|
|
507
|
+
|
|
508
|
+
// if (currents.Size() < maxdirect || r < 1e-8)
|
|
509
|
+
if (currents.Size() < 4 || r < 1e-8)
|
|
510
|
+
return;
|
|
511
|
+
|
|
512
|
+
CreateChilds();
|
|
513
|
+
|
|
514
|
+
for (auto [x,c] : charges)
|
|
515
|
+
AddCharge (x,c);
|
|
516
|
+
for (auto [x,d,c] : dipoles)
|
|
517
|
+
AddDipole (x,d,c);
|
|
518
|
+
for (auto [sp,ep,j,num] : currents)
|
|
519
|
+
AddCurrent (sp,ep,j,num);
|
|
520
|
+
|
|
521
|
+
charges.SetSize0();
|
|
522
|
+
dipoles.SetSize0();
|
|
523
|
+
currents.SetSize0();
|
|
524
|
+
}
|
|
525
|
+
|
|
526
|
+
|
|
461
527
|
|
|
462
|
-
|
|
528
|
+
|
|
529
|
+
entry_type Evaluate(Vec<3> p) const
|
|
463
530
|
{
|
|
464
|
-
|
|
531
|
+
entry_type sum{0.0};
|
|
465
532
|
if (childs[0])
|
|
466
533
|
{
|
|
467
534
|
for (auto & child : childs)
|
|
@@ -471,17 +538,63 @@ namespace ngfem
|
|
|
471
538
|
|
|
472
539
|
for (auto [x,c] : charges)
|
|
473
540
|
if (double rho = L2Norm(p-x); rho > 0)
|
|
474
|
-
sum +=
|
|
541
|
+
sum += (1/(4*M_PI))*exp(Complex(0,rho*mp.Kappa())) / rho * c;
|
|
475
542
|
|
|
476
543
|
for (auto [x,d,c] : dipoles)
|
|
477
544
|
if (double rho = L2Norm(p-x); rho > 0)
|
|
478
545
|
{
|
|
479
546
|
Vec<3> drhodp = 1.0/rho * (p-x);
|
|
480
|
-
Complex dGdrho =
|
|
547
|
+
Complex dGdrho = (1/(4*M_PI))*exp(Complex(0,rho*mp.Kappa())) *
|
|
481
548
|
(Complex(0, mp.Kappa())/rho - 1.0/sqr(rho));
|
|
482
|
-
sum += dGdrho * InnerProduct(drhodp, d);
|
|
549
|
+
sum += dGdrho * InnerProduct(drhodp, d) * c;
|
|
483
550
|
}
|
|
484
551
|
|
|
552
|
+
for (auto [sp,ep,j,num] : currents)
|
|
553
|
+
{
|
|
554
|
+
// should use explizit formula instead ...
|
|
555
|
+
|
|
556
|
+
Vec<3> tau = ep-sp;
|
|
557
|
+
Vec<3> tau_num = 1.0/num * tau;
|
|
558
|
+
for (int i = 0; i < num; i++)
|
|
559
|
+
{
|
|
560
|
+
Vec<3> x = sp+(i+0.5)*tau_num;
|
|
561
|
+
|
|
562
|
+
if (double rho = L2Norm(p-x); rho > 0)
|
|
563
|
+
{
|
|
564
|
+
Vec<3> drhodp = 1.0/rho * (p-x);
|
|
565
|
+
Complex dGdrho = (1/(4*M_PI))*exp(Complex(0,rho*mp.Kappa())) *
|
|
566
|
+
(Complex(0, mp.Kappa())/rho - 1.0/sqr(rho));
|
|
567
|
+
|
|
568
|
+
if constexpr (std::is_same<entry_type, Vec<3,Complex>>())
|
|
569
|
+
sum += j*dGdrho * Cross(drhodp, tau_num);
|
|
570
|
+
}
|
|
571
|
+
}
|
|
572
|
+
}
|
|
573
|
+
|
|
574
|
+
return sum;
|
|
575
|
+
}
|
|
576
|
+
|
|
577
|
+
entry_type EvaluateDeriv(Vec<3> p, Vec<3> d) const
|
|
578
|
+
{
|
|
579
|
+
entry_type sum{0.0};
|
|
580
|
+
if (childs[0])
|
|
581
|
+
{
|
|
582
|
+
for (auto & child : childs)
|
|
583
|
+
sum += child->EvaluateDeriv(p, d);
|
|
584
|
+
return sum;
|
|
585
|
+
}
|
|
586
|
+
|
|
587
|
+
if (dipoles.Size())
|
|
588
|
+
throw Exception("EvaluateDeriv not implemented for dipoles in SingularMLMultiPole");
|
|
589
|
+
|
|
590
|
+
for (auto [x,c] : charges)
|
|
591
|
+
if (double rho = L2Norm(p-x); rho > 0)
|
|
592
|
+
{
|
|
593
|
+
Vec<3> drhodp = 1.0/rho * (p-x);
|
|
594
|
+
Complex dGdrho = (1/(4*M_PI))*exp(Complex(0,rho*mp.Kappa())) *
|
|
595
|
+
(Complex(0, mp.Kappa())/rho - 1.0/sqr(rho));
|
|
596
|
+
sum += dGdrho * InnerProduct(drhodp, d) * c;
|
|
597
|
+
}
|
|
485
598
|
return sum;
|
|
486
599
|
}
|
|
487
600
|
|
|
@@ -516,9 +629,9 @@ namespace ngfem
|
|
|
516
629
|
}
|
|
517
630
|
else
|
|
518
631
|
{
|
|
519
|
-
if (charges.Size()+dipoles.Size() == 0)
|
|
632
|
+
if (charges.Size()+dipoles.Size()+currents.Size() == 0)
|
|
520
633
|
{
|
|
521
|
-
mp = MultiPole<MPSingular> (-1, mp.Kappa());
|
|
634
|
+
mp = MultiPole<MPSingular,entry_type> (-1, mp.Kappa());
|
|
522
635
|
return;
|
|
523
636
|
}
|
|
524
637
|
|
|
@@ -527,10 +640,13 @@ namespace ngfem
|
|
|
527
640
|
|
|
528
641
|
for (auto [x,d,c] : dipoles)
|
|
529
642
|
mp.AddDipole (x-center, d, c);
|
|
643
|
+
|
|
644
|
+
for (auto [sp,ep,j,num] : currents)
|
|
645
|
+
mp.AddCurrent (sp-center, ep-center, j, num);
|
|
530
646
|
}
|
|
531
647
|
}
|
|
532
648
|
|
|
533
|
-
|
|
649
|
+
entry_type EvaluateMP(Vec<3> p) const
|
|
534
650
|
{
|
|
535
651
|
if (charges.Size() || dipoles.Size())
|
|
536
652
|
return Evaluate(p);
|
|
@@ -541,22 +657,43 @@ namespace ngfem
|
|
|
541
657
|
if (!childs[0]) // || level==1)
|
|
542
658
|
return Evaluate(p);
|
|
543
659
|
|
|
544
|
-
|
|
660
|
+
entry_type sum{0.0};
|
|
545
661
|
for (auto & child : childs)
|
|
546
662
|
sum += child->EvaluateMP(p);
|
|
547
663
|
return sum;
|
|
548
664
|
}
|
|
549
|
-
|
|
550
|
-
|
|
551
|
-
void Print (ostream & ost) const
|
|
665
|
+
|
|
666
|
+
entry_type EvaluateMPDeriv(Vec<3> p, Vec<3> d) const
|
|
552
667
|
{
|
|
553
|
-
|
|
668
|
+
// cout << "EvaluateMPDeriv Singular, p = " << p << ", d = " << d << ", r = " << r << ", center = " << center << endl;
|
|
669
|
+
// cout << "Norm: " << L2Norm(p-center) << " > " << 3*r << endl;
|
|
670
|
+
// cout << "charges.Size() = " << charges.Size() << ", dipoles.Size() = " << dipoles.Size() << endl;
|
|
671
|
+
if (charges.Size() || dipoles.Size() || !childs[0])
|
|
672
|
+
return EvaluateDeriv(p, d);
|
|
673
|
+
|
|
674
|
+
if (L2Norm(p-center) > 3*r)
|
|
675
|
+
return mp.EvalDirectionalDerivative(p-center, d);
|
|
676
|
+
|
|
677
|
+
entry_type sum{0.0};
|
|
678
|
+
for (auto & child : childs)
|
|
679
|
+
sum += child->EvaluateMPDeriv(p, d);
|
|
680
|
+
return sum;
|
|
681
|
+
}
|
|
682
|
+
|
|
683
|
+
void Print (ostream & ost, size_t childnr = -1) const
|
|
684
|
+
{
|
|
685
|
+
if (childnr == -1)
|
|
686
|
+
ost << "c = " << center << ", r = " << r << ", level = " << level << endl;
|
|
687
|
+
else
|
|
688
|
+
ost << "c = " << center << ", r = " << r << ", level = " << level << ", childnr = " << childnr << endl;
|
|
554
689
|
// for (int i = 0; i < loc_pnts.Size(); i++)
|
|
555
690
|
for (auto [x,c] : charges)
|
|
556
691
|
ost << "xi = " << x << ", ci = " << c << endl;
|
|
692
|
+
for (auto [x,d,c] : dipoles)
|
|
693
|
+
ost << "xi = " << x << ", di = " << d << ", ci = " << c << endl;
|
|
557
694
|
|
|
558
695
|
for (int i = 0; i < 8; i++)
|
|
559
|
-
if (childs[i]) childs[i] -> Print (ost);
|
|
696
|
+
if (childs[i]) childs[i] -> Print (ost, i);
|
|
560
697
|
}
|
|
561
698
|
|
|
562
699
|
double Norm () const
|
|
@@ -596,11 +733,36 @@ namespace ngfem
|
|
|
596
733
|
root.AddCharge(x, c);
|
|
597
734
|
}
|
|
598
735
|
|
|
599
|
-
void AddDipole(Vec<3> x, Vec<3> d,
|
|
736
|
+
void AddDipole(Vec<3> x, Vec<3> d, entry_type c)
|
|
600
737
|
{
|
|
601
738
|
root.AddDipole(x, d, c);
|
|
602
739
|
}
|
|
603
740
|
|
|
741
|
+
void AddCurrent (Vec<3> sp, Vec<3> ep, Complex j, int num)
|
|
742
|
+
{
|
|
743
|
+
if constexpr (!std::is_same<entry_type, Vec<3,Complex>>())
|
|
744
|
+
throw Exception("AddCurrent needs a singular vectorial MP");
|
|
745
|
+
|
|
746
|
+
root.AddCurrent (sp, ep, j, num);
|
|
747
|
+
/*
|
|
748
|
+
// for testing
|
|
749
|
+
Vec<3> tau = ep-sp;
|
|
750
|
+
Vec<3> tau_num = 1.0/num * tau;
|
|
751
|
+
for (int i = 0; i < num; i++)
|
|
752
|
+
{
|
|
753
|
+
for (int k = 0; k < 3; k++)
|
|
754
|
+
{
|
|
755
|
+
Vec<3> ek{0.0}; ek(k) = 1;
|
|
756
|
+
Vec<3> cp = Cross(tau, ek);
|
|
757
|
+
Vec<3,Complex> source{0.0};
|
|
758
|
+
source(k) = j/double(num);
|
|
759
|
+
if constexpr (std::is_same<entry_type, Vec<3,Complex>>())
|
|
760
|
+
root.AddDipole (sp+(i+0.5)*tau_num, cp, source);
|
|
761
|
+
}
|
|
762
|
+
}
|
|
763
|
+
*/
|
|
764
|
+
}
|
|
765
|
+
|
|
604
766
|
void Print (ostream & ost) const
|
|
605
767
|
{
|
|
606
768
|
root.Print(ost);
|
|
@@ -634,7 +796,7 @@ namespace ngfem
|
|
|
634
796
|
havemp = true;
|
|
635
797
|
}
|
|
636
798
|
|
|
637
|
-
|
|
799
|
+
entry_type Evaluate (Vec<3> p) const
|
|
638
800
|
{
|
|
639
801
|
if (havemp)
|
|
640
802
|
return root.EvaluateMP(p);
|
|
@@ -642,17 +804,20 @@ namespace ngfem
|
|
|
642
804
|
return root.Evaluate(p);
|
|
643
805
|
}
|
|
644
806
|
|
|
807
|
+
template <typename entry_type2>
|
|
645
808
|
friend class RegularMLMultiPole;
|
|
646
809
|
};
|
|
647
810
|
|
|
648
811
|
|
|
649
|
-
|
|
812
|
+
template <typename entry_type>
|
|
813
|
+
inline ostream & operator<< (ostream & ost, const SingularMLMultiPole<entry_type> & mlmp)
|
|
650
814
|
{
|
|
651
815
|
mlmp.Print(ost);
|
|
652
816
|
return ost;
|
|
653
817
|
}
|
|
654
818
|
|
|
655
819
|
|
|
820
|
+
template <typename elem_type=Complex>
|
|
656
821
|
class NGS_DLL_HEADER RegularMLMultiPole
|
|
657
822
|
{
|
|
658
823
|
static Array<size_t> nodes_on_level;
|
|
@@ -663,11 +828,11 @@ namespace ngfem
|
|
|
663
828
|
double r;
|
|
664
829
|
int level;
|
|
665
830
|
std::array<unique_ptr<Node>,8> childs;
|
|
666
|
-
MultiPole<MPRegular> mp;
|
|
831
|
+
MultiPole<MPRegular,elem_type> mp;
|
|
667
832
|
Array<Vec<3>> targets;
|
|
668
833
|
int total_targets;
|
|
669
834
|
|
|
670
|
-
Array<const SingularMLMultiPole
|
|
835
|
+
Array<const typename SingularMLMultiPole<elem_type>::Node*> singnodes;
|
|
671
836
|
|
|
672
837
|
Node (Vec<3> acenter, double ar, int alevel, int order, double kappa)
|
|
673
838
|
: center(acenter), r(ar), level(alevel), mp(MPOrder(ar*kappa), kappa, 1.0/min(1.0, 0.25*r*kappa))
|
|
@@ -692,7 +857,7 @@ namespace ngfem
|
|
|
692
857
|
}
|
|
693
858
|
}
|
|
694
859
|
|
|
695
|
-
void AddSingularNode (const SingularMLMultiPole
|
|
860
|
+
void AddSingularNode (const typename SingularMLMultiPole<elem_type>::Node & singnode, bool allow_refine)
|
|
696
861
|
{
|
|
697
862
|
if (mp.SH().Order() < 0) return;
|
|
698
863
|
if (singnode.mp.SH().Order() < 0) return;
|
|
@@ -781,15 +946,15 @@ namespace ngfem
|
|
|
781
946
|
mp.TransformAdd (ch->mp, ch->center-center);
|
|
782
947
|
ch->LocalizeExpansion(allow_refine);
|
|
783
948
|
}
|
|
784
|
-
mp = MultiPole<MPRegular>(-1, mp.Kappa());
|
|
949
|
+
mp = MultiPole<MPRegular,elem_type>(-1, mp.Kappa());
|
|
785
950
|
//mp.SH().Coefs()=0.0;
|
|
786
951
|
}
|
|
787
952
|
}
|
|
788
953
|
|
|
789
|
-
|
|
954
|
+
elem_type Evaluate (Vec<3> p) const
|
|
790
955
|
{
|
|
791
956
|
// *testout << "eval p = " << p << ", level = " << level << ", center = " << center << ", r = " << r << endl;
|
|
792
|
-
|
|
957
|
+
elem_type sum{0.0};
|
|
793
958
|
/*
|
|
794
959
|
if (childs[0])
|
|
795
960
|
{
|
|
@@ -817,6 +982,28 @@ namespace ngfem
|
|
|
817
982
|
return sum;
|
|
818
983
|
}
|
|
819
984
|
|
|
985
|
+
elem_type EvaluateDirectionalDerivative (Vec<3> p, Vec<3> d) const
|
|
986
|
+
{
|
|
987
|
+
elem_type sum{0.0};
|
|
988
|
+
// cout << "EvaluateDirectionalDerivative RegularMLMP, r = " << r << ", level = " << level << ", center = " << center << endl;
|
|
989
|
+
// cout << "Singnodes: " << singnodes.Size() << ", childs: " << childs[0] << endl;
|
|
990
|
+
|
|
991
|
+
int childnum = 0;
|
|
992
|
+
if (p(0) > center(0)) childnum += 1;
|
|
993
|
+
if (p(1) > center(1)) childnum += 2;
|
|
994
|
+
if (p(2) > center(2)) childnum += 4;
|
|
995
|
+
if (childs[childnum])
|
|
996
|
+
sum = childs[childnum]->EvaluateDirectionalDerivative(p, d);
|
|
997
|
+
else
|
|
998
|
+
sum = mp.EvalDirectionalDerivative(p-center, d);
|
|
999
|
+
|
|
1000
|
+
static Timer t("mptool direct evaluate deriv"); RegionTimer r(t);
|
|
1001
|
+
for (auto sn : singnodes)
|
|
1002
|
+
sum += sn->EvaluateMPDeriv(p, d);
|
|
1003
|
+
|
|
1004
|
+
return sum;
|
|
1005
|
+
}
|
|
1006
|
+
|
|
820
1007
|
double Norm() const
|
|
821
1008
|
{
|
|
822
1009
|
double norm = L2Norm(mp.SH().Coefs());
|
|
@@ -886,13 +1073,27 @@ namespace ngfem
|
|
|
886
1073
|
mp = MultiPole<MPRegular>(-1, mp.Kappa());
|
|
887
1074
|
}
|
|
888
1075
|
|
|
1076
|
+
|
|
1077
|
+
void Print (ostream & ost, size_t childnr = -1) const
|
|
1078
|
+
{
|
|
1079
|
+
if (childnr == -1)
|
|
1080
|
+
ost << "c = " << center << ", r = " << r << ", level = " << level << endl;
|
|
1081
|
+
else
|
|
1082
|
+
ost << "c = " << center << ", r = " << r << ", level = " << level << ", childnr = " << childnr << endl;
|
|
1083
|
+
for (auto x : targets)
|
|
1084
|
+
ost << "xi = " << x << endl;
|
|
1085
|
+
|
|
1086
|
+
for (int i = 0; i < 8; i++)
|
|
1087
|
+
if (childs[i]) childs[i] -> Print (ost, i);
|
|
1088
|
+
}
|
|
1089
|
+
|
|
889
1090
|
};
|
|
890
1091
|
|
|
891
1092
|
Node root;
|
|
892
|
-
shared_ptr<SingularMLMultiPole
|
|
1093
|
+
shared_ptr<SingularMLMultiPole<elem_type>> singmp;
|
|
893
1094
|
|
|
894
1095
|
public:
|
|
895
|
-
|
|
1096
|
+
RegularMLMultiPole (shared_ptr<SingularMLMultiPole<elem_type>> asingmp, Vec<3> center, double r, int order)
|
|
896
1097
|
: root(center, r, 0, order, asingmp->Kappa()), singmp(asingmp)
|
|
897
1098
|
{
|
|
898
1099
|
if (!singmp->havemp) throw Exception("first call Calc for singular MP");
|
|
@@ -934,7 +1135,7 @@ namespace ngfem
|
|
|
934
1135
|
root.AddTarget (t);
|
|
935
1136
|
}
|
|
936
1137
|
|
|
937
|
-
void CalcMP(shared_ptr<SingularMLMultiPole
|
|
1138
|
+
void CalcMP(shared_ptr<SingularMLMultiPole<elem_type>> asingmp)
|
|
938
1139
|
{
|
|
939
1140
|
singmp = asingmp;
|
|
940
1141
|
|
|
@@ -955,6 +1156,11 @@ namespace ngfem
|
|
|
955
1156
|
root.LocalizeExpansion(false);
|
|
956
1157
|
}
|
|
957
1158
|
|
|
1159
|
+
void Print (ostream & ost) const
|
|
1160
|
+
{
|
|
1161
|
+
root.Print(ost);
|
|
1162
|
+
}
|
|
1163
|
+
|
|
958
1164
|
double Norm() const
|
|
959
1165
|
{
|
|
960
1166
|
return root.Norm();
|
|
@@ -965,21 +1171,26 @@ namespace ngfem
|
|
|
965
1171
|
return root.NumCoefficients();
|
|
966
1172
|
}
|
|
967
1173
|
|
|
968
|
-
|
|
1174
|
+
elem_type Evaluate (Vec<3> p) const
|
|
969
1175
|
{
|
|
970
1176
|
// static Timer t("mptool Eval MLMP regular"); RegionTimer r(t);
|
|
971
|
-
if (L2Norm(p-root.center) > root.r) return 0.0;
|
|
1177
|
+
if (L2Norm(p-root.center) > root.r) return elem_type{0.0};
|
|
972
1178
|
return root.Evaluate(p);
|
|
973
1179
|
}
|
|
974
1180
|
|
|
975
|
-
|
|
1181
|
+
elem_type EvaluateDirectionalDerivative (Vec<3> p, Vec<3> d) const
|
|
1182
|
+
{
|
|
1183
|
+
if (L2Norm(p-root.center) > root.r) return elem_type{0.0};
|
|
1184
|
+
return root.EvaluateDirectionalDerivative(p, d);
|
|
1185
|
+
}
|
|
1186
|
+
|
|
976
1187
|
};
|
|
977
|
-
|
|
978
1188
|
|
|
979
|
-
|
|
1189
|
+
template <typename elem_type>
|
|
1190
|
+
inline ostream & operator<< (ostream & ost, const RegularMLMultiPole<elem_type> & mlmp)
|
|
980
1191
|
{
|
|
981
|
-
|
|
982
|
-
ost << "RegularMLMultiPole" << endl;
|
|
1192
|
+
mlmp.Print(ost);
|
|
1193
|
+
// ost << "RegularMLMultiPole" << endl;
|
|
983
1194
|
return ost;
|
|
984
1195
|
}
|
|
985
1196
|
|
|
@@ -993,7 +1204,7 @@ namespace ngfem
|
|
|
993
1204
|
|
|
994
1205
|
class SphericalHarmonicsCF : public CoefficientFunction
|
|
995
1206
|
{
|
|
996
|
-
SphericalHarmonics sh;
|
|
1207
|
+
SphericalHarmonics<Complex> sh;
|
|
997
1208
|
public:
|
|
998
1209
|
SphericalHarmonicsCF (int order)
|
|
999
1210
|
: CoefficientFunction(1, true), sh(order) { }
|
|
@@ -1021,16 +1232,19 @@ namespace ngfem
|
|
|
1021
1232
|
|
|
1022
1233
|
|
|
1023
1234
|
|
|
1024
|
-
template <typename
|
|
1235
|
+
template <typename entry_type> class RegularMLMultiPoleCF;
|
|
1236
|
+
|
|
1237
|
+
|
|
1238
|
+
template <typename RADIAL, typename entry_type=Complex>
|
|
1025
1239
|
class MultiPoleCF : public CoefficientFunction
|
|
1026
1240
|
{
|
|
1027
|
-
MultiPole<RADIAL> mp;
|
|
1241
|
+
MultiPole<RADIAL, entry_type> mp;
|
|
1028
1242
|
Vec<3> center;
|
|
1029
1243
|
public:
|
|
1030
1244
|
MultiPoleCF (int order, double kappa, Vec<3> acenter, double scale = 1)
|
|
1031
|
-
: CoefficientFunction(
|
|
1245
|
+
: CoefficientFunction(sizeof(entry_type)/sizeof(Complex), true), mp(order, kappa, scale), center(acenter) { }
|
|
1032
1246
|
|
|
1033
|
-
|
|
1247
|
+
entry_type & Coef(int n, int m) { return mp.Coef(n,m); }
|
|
1034
1248
|
auto & SH() { return mp.SH(); }
|
|
1035
1249
|
auto & MP() { return mp; }
|
|
1036
1250
|
Vec<3> Center() const { return center; }
|
|
@@ -1040,56 +1254,75 @@ namespace ngfem
|
|
|
1040
1254
|
|
|
1041
1255
|
virtual void Evaluate (const BaseMappedIntegrationPoint & mip, FlatVector<Complex> values) const override
|
|
1042
1256
|
{
|
|
1043
|
-
|
|
1257
|
+
if constexpr (std::is_same<entry_type, Complex>())
|
|
1258
|
+
values(0) = mp.Eval(mip.GetPoint()-center);
|
|
1259
|
+
else
|
|
1260
|
+
values = mp.Eval(mip.GetPoint()-center);
|
|
1044
1261
|
}
|
|
1045
1262
|
|
|
1046
1263
|
template <typename TARGET>
|
|
1047
|
-
void ShiftZ (double z, MultiPole<TARGET> & target) { mp.ShiftZ(z, target); }
|
|
1264
|
+
void ShiftZ (double z, MultiPole<TARGET, entry_type> & target) { mp.ShiftZ(z, target); }
|
|
1048
1265
|
|
|
1049
1266
|
using CoefficientFunction::Transform;
|
|
1050
1267
|
template <typename TARGET>
|
|
1051
|
-
void Transform (MultiPoleCF<TARGET> & target)
|
|
1268
|
+
void Transform (MultiPoleCF<TARGET, entry_type> & target)
|
|
1052
1269
|
{
|
|
1053
1270
|
mp.Transform (target.MP(), target.Center()-center);
|
|
1054
1271
|
}
|
|
1055
1272
|
};
|
|
1056
1273
|
|
|
1057
|
-
|
|
1274
|
+
template <typename entry_type>
|
|
1058
1275
|
class SingularMLMultiPoleCF : public CoefficientFunction
|
|
1059
1276
|
{
|
|
1060
|
-
shared_ptr<SingularMLMultiPole
|
|
1277
|
+
shared_ptr<SingularMLMultiPole<entry_type>> mlmp;
|
|
1061
1278
|
public:
|
|
1062
1279
|
SingularMLMultiPoleCF (Vec<3> center, double r, int order, double kappa)
|
|
1063
|
-
: CoefficientFunction(
|
|
1280
|
+
: CoefficientFunction(sizeof(entry_type)/sizeof(Complex), true), mlmp{make_shared<SingularMLMultiPole<entry_type>>(center, r, order, kappa)} { }
|
|
1064
1281
|
|
|
1065
1282
|
virtual double Evaluate (const BaseMappedIntegrationPoint & ip) const override
|
|
1066
1283
|
{ throw Exception("real eval not available"); }
|
|
1067
1284
|
|
|
1068
1285
|
virtual void Evaluate (const BaseMappedIntegrationPoint & mip, FlatVector<Complex> values) const override
|
|
1069
1286
|
{
|
|
1070
|
-
values(0) = mlmp->Evaluate(mip.GetPoint());
|
|
1287
|
+
// values(0) = mlmp->Evaluate(mip.GetPoint());
|
|
1288
|
+
|
|
1289
|
+
if constexpr (std::is_same<entry_type, Complex>())
|
|
1290
|
+
values(0) = mlmp->Evaluate(mip.GetPoint());
|
|
1291
|
+
else
|
|
1292
|
+
values = mlmp->Evaluate(mip.GetPoint());
|
|
1293
|
+
|
|
1294
|
+
|
|
1071
1295
|
}
|
|
1072
1296
|
|
|
1073
|
-
shared_ptr<SingularMLMultiPole
|
|
1297
|
+
shared_ptr<SingularMLMultiPole<entry_type>> MLMP() const { return mlmp; }
|
|
1298
|
+
shared_ptr<RegularMLMultiPoleCF<entry_type>> CreateRegularExpansion(Vec<3> center, double r) const;
|
|
1074
1299
|
};
|
|
1075
1300
|
|
|
1076
1301
|
|
|
1302
|
+
template <typename entry_type>
|
|
1077
1303
|
class RegularMLMultiPoleCF : public CoefficientFunction
|
|
1078
1304
|
{
|
|
1079
|
-
shared_ptr<RegularMLMultiPole
|
|
1305
|
+
shared_ptr<RegularMLMultiPole<entry_type>> mlmp;
|
|
1080
1306
|
public:
|
|
1081
|
-
RegularMLMultiPoleCF (shared_ptr<SingularMLMultiPoleCF
|
|
1082
|
-
: CoefficientFunction(
|
|
1307
|
+
RegularMLMultiPoleCF (shared_ptr<SingularMLMultiPoleCF<entry_type>> asingmp, Vec<3> center, double r, int order)
|
|
1308
|
+
: CoefficientFunction(sizeof(entry_type)/sizeof(Complex), true), mlmp{make_shared<RegularMLMultiPole<entry_type>>(asingmp->MLMP(), center, r, order)} { }
|
|
1309
|
+
RegularMLMultiPoleCF (shared_ptr<SingularMLMultiPole<entry_type>> asingmp, Vec<3> center, double r, int order)
|
|
1310
|
+
: CoefficientFunction(sizeof(entry_type)/sizeof(Complex), true), mlmp{make_shared<RegularMLMultiPole<entry_type>>(asingmp, center, r, order)} { }
|
|
1083
1311
|
|
|
1084
1312
|
virtual double Evaluate (const BaseMappedIntegrationPoint & ip) const override
|
|
1085
1313
|
{ throw Exception("real eval not available"); }
|
|
1086
1314
|
|
|
1087
1315
|
virtual void Evaluate (const BaseMappedIntegrationPoint & mip, FlatVector<Complex> values) const override
|
|
1088
1316
|
{
|
|
1089
|
-
values(0) = mlmp->Evaluate(mip.GetPoint());
|
|
1317
|
+
// values(0) = mlmp->Evaluate(mip.GetPoint());
|
|
1318
|
+
|
|
1319
|
+
if constexpr (std::is_same<entry_type, Complex>())
|
|
1320
|
+
values(0) = mlmp->Evaluate(mip.GetPoint());
|
|
1321
|
+
else
|
|
1322
|
+
values = mlmp->Evaluate(mip.GetPoint());
|
|
1090
1323
|
}
|
|
1091
1324
|
|
|
1092
|
-
shared_ptr<RegularMLMultiPole
|
|
1325
|
+
shared_ptr<RegularMLMultiPole<entry_type>> MLMP() { return mlmp; }
|
|
1093
1326
|
};
|
|
1094
1327
|
|
|
1095
1328
|
|