ngsolve 6.2.2501.post83.dev1__cp313-cp313-win_amd64.whl → 6.2.2502.post11.dev1__cp313-cp313-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 (50) hide show
  1. netgen/include/facetfespace.hpp +2 -0
  2. netgen/include/fespace.hpp +4 -2
  3. netgen/include/mptools.hpp +318 -85
  4. netgen/include/ngblas.hpp +14 -0
  5. netgen/include/potentialtools.hpp +20 -0
  6. netgen/include/prolongation.hpp +143 -1
  7. netgen/include/python_ngstd.hpp +1 -0
  8. netgen/include/sparsecholesky.hpp +1 -1
  9. netgen/include/sparsematrix_impl.hpp +71 -5
  10. netgen/include/tangentialfacetfespace.hpp +7 -22
  11. netgen/include/tensor.hpp +1 -1
  12. netgen/lib/libngsolve.lib +0 -0
  13. netgen/libngsolve.dll +0 -0
  14. ngsolve/cmake/NGSolveConfig.cmake +1 -1
  15. ngsolve/config/config.py +6 -6
  16. ngsolve/ngslib.pyd +0 -0
  17. {ngsolve-6.2.2501.post83.dev1.dist-info → ngsolve-6.2.2502.post11.dev1.dist-info}/METADATA +2 -2
  18. {ngsolve-6.2.2501.post83.dev1.dist-info → ngsolve-6.2.2502.post11.dev1.dist-info}/RECORD +50 -49
  19. {ngsolve-6.2.2501.post83.dev1.data → ngsolve-6.2.2502.post11.dev1.data}/data/Scripts/ngsolve.tcl +0 -0
  20. {ngsolve-6.2.2501.post83.dev1.data → ngsolve-6.2.2502.post11.dev1.data}/data/share/ngsolve/beam.geo +0 -0
  21. {ngsolve-6.2.2501.post83.dev1.data → ngsolve-6.2.2502.post11.dev1.data}/data/share/ngsolve/beam.vol +0 -0
  22. {ngsolve-6.2.2501.post83.dev1.data → ngsolve-6.2.2502.post11.dev1.data}/data/share/ngsolve/chip.in2d +0 -0
  23. {ngsolve-6.2.2501.post83.dev1.data → ngsolve-6.2.2502.post11.dev1.data}/data/share/ngsolve/chip.vol +0 -0
  24. {ngsolve-6.2.2501.post83.dev1.data → ngsolve-6.2.2502.post11.dev1.data}/data/share/ngsolve/coil.geo +0 -0
  25. {ngsolve-6.2.2501.post83.dev1.data → ngsolve-6.2.2502.post11.dev1.data}/data/share/ngsolve/coil.vol +0 -0
  26. {ngsolve-6.2.2501.post83.dev1.data → ngsolve-6.2.2502.post11.dev1.data}/data/share/ngsolve/coilshield.geo +0 -0
  27. {ngsolve-6.2.2501.post83.dev1.data → ngsolve-6.2.2502.post11.dev1.data}/data/share/ngsolve/coilshield.vol +0 -0
  28. {ngsolve-6.2.2501.post83.dev1.data → ngsolve-6.2.2502.post11.dev1.data}/data/share/ngsolve/cube.geo +0 -0
  29. {ngsolve-6.2.2501.post83.dev1.data → ngsolve-6.2.2502.post11.dev1.data}/data/share/ngsolve/cube.vol +0 -0
  30. {ngsolve-6.2.2501.post83.dev1.data → ngsolve-6.2.2502.post11.dev1.data}/data/share/ngsolve/d10_DGdoubleglazing.pde +0 -0
  31. {ngsolve-6.2.2501.post83.dev1.data → ngsolve-6.2.2502.post11.dev1.data}/data/share/ngsolve/d11_chip_nitsche.pde +0 -0
  32. {ngsolve-6.2.2501.post83.dev1.data → ngsolve-6.2.2502.post11.dev1.data}/data/share/ngsolve/d1_square.pde +0 -0
  33. {ngsolve-6.2.2501.post83.dev1.data → ngsolve-6.2.2502.post11.dev1.data}/data/share/ngsolve/d2_chip.pde +0 -0
  34. {ngsolve-6.2.2501.post83.dev1.data → ngsolve-6.2.2502.post11.dev1.data}/data/share/ngsolve/d3_helmholtz.pde +0 -0
  35. {ngsolve-6.2.2501.post83.dev1.data → ngsolve-6.2.2502.post11.dev1.data}/data/share/ngsolve/d4_cube.pde +0 -0
  36. {ngsolve-6.2.2501.post83.dev1.data → ngsolve-6.2.2502.post11.dev1.data}/data/share/ngsolve/d5_beam.pde +0 -0
  37. {ngsolve-6.2.2501.post83.dev1.data → ngsolve-6.2.2502.post11.dev1.data}/data/share/ngsolve/d6_shaft.pde +0 -0
  38. {ngsolve-6.2.2501.post83.dev1.data → ngsolve-6.2.2502.post11.dev1.data}/data/share/ngsolve/d7_coil.pde +0 -0
  39. {ngsolve-6.2.2501.post83.dev1.data → ngsolve-6.2.2502.post11.dev1.data}/data/share/ngsolve/d8_coilshield.pde +0 -0
  40. {ngsolve-6.2.2501.post83.dev1.data → ngsolve-6.2.2502.post11.dev1.data}/data/share/ngsolve/d9_hybridDG.pde +0 -0
  41. {ngsolve-6.2.2501.post83.dev1.data → ngsolve-6.2.2502.post11.dev1.data}/data/share/ngsolve/doubleglazing.in2d +0 -0
  42. {ngsolve-6.2.2501.post83.dev1.data → ngsolve-6.2.2502.post11.dev1.data}/data/share/ngsolve/doubleglazing.vol +0 -0
  43. {ngsolve-6.2.2501.post83.dev1.data → ngsolve-6.2.2502.post11.dev1.data}/data/share/ngsolve/piezo2d40round4.vol.gz +0 -0
  44. {ngsolve-6.2.2501.post83.dev1.data → ngsolve-6.2.2502.post11.dev1.data}/data/share/ngsolve/shaft.geo +0 -0
  45. {ngsolve-6.2.2501.post83.dev1.data → ngsolve-6.2.2502.post11.dev1.data}/data/share/ngsolve/shaft.vol +0 -0
  46. {ngsolve-6.2.2501.post83.dev1.data → ngsolve-6.2.2502.post11.dev1.data}/data/share/ngsolve/square.in2d +0 -0
  47. {ngsolve-6.2.2501.post83.dev1.data → ngsolve-6.2.2502.post11.dev1.data}/data/share/ngsolve/square.vol +0 -0
  48. {ngsolve-6.2.2501.post83.dev1.dist-info → ngsolve-6.2.2502.post11.dev1.dist-info}/WHEEL +0 -0
  49. {ngsolve-6.2.2501.post83.dev1.dist-info → ngsolve-6.2.2502.post11.dev1.dist-info}/licenses/LICENSE +0 -0
  50. {ngsolve-6.2.2501.post83.dev1.dist-info → ngsolve-6.2.2502.post11.dev1.dist-info}/top_level.txt +0 -0
@@ -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<Complex> coefs;
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<Complex> Coefs() const { return coefs; }
29
-
30
- Complex & Coef(int n, int m)
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
- Complex Eval (Vec<3> x) const
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
- Complex Eval (double theta, double phi) const;
66
+ entry_type Eval (double theta, double phi) const;
63
67
 
64
- Complex EvalOrder (int n, Vec<3> x) const
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
- Complex EvalOrder (int n, double theta, double phi) const;
74
+ entry_type EvalOrder (int n, double theta, double phi) const;
71
75
 
72
- void EvalOrders (Vec<3> x, FlatVector<Complex> vals) const
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<Complex> vals) const;
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
- Complex & Coef(int n, int m) { return sh.Coef(n,m); }
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<RADIAL> Truncate(int neworder) const
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
- Complex Eval (Vec<3> x) const;
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, Complex c);
272
- void AddDipole (Vec<3> x, Vec<3> d, Complex c);
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>, Complex>> charges;
373
- Array<tuple<Vec<3>, Vec<3>, Complex>> dipoles;
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, Complex c)
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, Complex c)
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
- Complex Evaluate(Vec<3> p) const
528
+
529
+ entry_type Evaluate(Vec<3> p) const
463
530
  {
464
- Complex sum = 0;
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 += c*(1/(4*M_PI))*exp(Complex(0,rho*mp.Kappa())) / rho;
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 = c*(1/(4*M_PI))*exp(Complex(0,rho*mp.Kappa())) *
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
- Complex EvaluateMP(Vec<3> p) const
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
- Complex sum = 0.0;
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
- ost << "c = " << center << ", r = " << r << endl;
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, Complex c)
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
- Complex Evaluate (Vec<3> p) const
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
- inline ostream & operator<< (ostream & ost, const SingularMLMultiPole & mlmp)
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::Node*> singnodes;
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::Node & singnode, bool allow_refine)
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
- Complex Evaluate (Vec<3> p) const
954
+ elem_type Evaluate (Vec<3> p) const
790
955
  {
791
956
  // *testout << "eval p = " << p << ", level = " << level << ", center = " << center << ", r = " << r << endl;
792
- Complex sum = 0.0;
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> singmp;
1093
+ shared_ptr<SingularMLMultiPole<elem_type>> singmp;
893
1094
 
894
1095
  public:
895
- RegularMLMultiPole (shared_ptr<SingularMLMultiPole> asingmp, Vec<3> center, double r, int order)
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> asingmp)
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
- Complex Evaluate (Vec<3> p) const
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
- inline ostream & operator<< (ostream & ost, const RegularMLMultiPole & mlmp)
1189
+ template <typename elem_type>
1190
+ inline ostream & operator<< (ostream & ost, const RegularMLMultiPole<elem_type> & mlmp)
980
1191
  {
981
- // mlmp.Print(ost);
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 RADIAL>
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(1, true), mp(order, kappa, scale), center(acenter) { }
1245
+ : CoefficientFunction(sizeof(entry_type)/sizeof(Complex), true), mp(order, kappa, scale), center(acenter) { }
1032
1246
 
1033
- Complex & Coef(int n, int m) { return mp.Coef(n,m); }
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
- values(0) = mp.Eval(mip.GetPoint()-center);
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> mlmp;
1277
+ shared_ptr<SingularMLMultiPole<entry_type>> mlmp;
1061
1278
  public:
1062
1279
  SingularMLMultiPoleCF (Vec<3> center, double r, int order, double kappa)
1063
- : CoefficientFunction(1, true), mlmp{make_shared<SingularMLMultiPole>(center, r, order, kappa)} { }
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> MLMP() { return mlmp; }
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> mlmp;
1305
+ shared_ptr<RegularMLMultiPole<entry_type>> mlmp;
1080
1306
  public:
1081
- RegularMLMultiPoleCF (shared_ptr<SingularMLMultiPoleCF> asingmp, Vec<3> center, double r, int order)
1082
- : CoefficientFunction(1, true), mlmp{make_shared<RegularMLMultiPole>(asingmp->MLMP(), center, r, order)} { }
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> MLMP() { return mlmp; }
1325
+ shared_ptr<RegularMLMultiPole<entry_type>> MLMP() { return mlmp; }
1093
1326
  };
1094
1327
 
1095
1328