Browse Source

Underflow in beta calculation of elliptic field. Only ocurred with small loops. Now falls back to 0.

master
T-bone 7 years ago
parent
commit
9fac32206f
2 changed files with 13 additions and 26 deletions
  1. 4
    4
      examples/KernelV0-2.cpp
  2. 9
    22
      src/KernelV0.cpp

+ 4
- 4
examples/KernelV0-2.cpp View File

@@ -43,7 +43,7 @@ int main(int argc, char** argv) {
43 43
 
44 44
         Kern->SetIntegrationSize( (Vector3r() << 200, 200., 100).finished() );
45 45
         Kern->SetIntegrationOrigin( (Vector3r() << -100, -100, .5).finished() );
46
-        Real tol(1e-13); // 13
46
+        Real tol(1e-11); // 13
47 47
         Kern->SetTolerance( tol ); // 1e-12
48 48
 
49 49
 //         Kern->AlignWithAkvoDataset( YAML::LoadFile(argv[2]) );
@@ -64,11 +64,11 @@ int main(int argc, char** argv) {
64 64
 
65 65
         //VectorXr interfaces = VectorXr::LinSpaced( 41, .5, 45.5 ); // nlay, low, high
66 66
         //VectorXr interfaces = VectorXr::LinSpaced( 61, .5, 45.5 ); // nlay, low, high
67
-        VectorXr interfaces = VectorXr::LinSpaced( 2, .5, 45.5 ); // nlay, low, high
67
+        VectorXr interfaces = VectorXr::LinSpaced( 61, .5, 45.5 ); // nlay, low, high
68 68
         Real thick = .1;
69 69
         for (int ilay=1; ilay<interfaces.size(); ++ilay) {
70 70
             interfaces(ilay) = interfaces(ilay-1) + thick;
71
-            thick *= 1.05;
71
+            thick *= 1.075;
72 72
         }
73 73
         Kern->SetDepthLayerInterfaces( interfaces ); // nlay, low, high
74 74
 
@@ -80,7 +80,7 @@ int main(int argc, char** argv) {
80 80
     //std::cout << "KERNEL.yaml" << std::endl;
81 81
     //std::cout << *Kern << std::endl;
82 82
 
83
-    Kern->CalculateK0( tx, rx, true ); // 3rd argument is vtk output
83
+    Kern->CalculateK0( tx, rx, false ); // 3rd argument is vtk output
84 84
 
85 85
     std::ofstream dout = std::ofstream(std::string("Rx-")+std::string(argv[3])+std::string(".dat"));
86 86
     dout << "# Transmitters: ";

+ 9
- 22
src/KernelV0.cpp View File

@@ -325,7 +325,6 @@ namespace Lemma {
325 325
     //       Class:  KernelV0
326 326
     //      Method:  f
327 327
     //--------------------------------------------------------------------------------------
328
-#if 1
329 328
     VectorXcr KernelV0::f( const Vector3r& r, const Real& volume, const Vector3cr& Ht, const Vector3cr& Hr ) {
330 329
 
331 330
         // Compute the elliptic fields
@@ -352,26 +351,9 @@ namespace Lemma {
352 351
             // Compute the tipping angle
353 352
             Real sintheta = std::sin(0.5*GAMMA*PulseI(iq)*Taup*(EBT.alpha-EBT.beta));
354 353
             F(iq) = -volume*Complex(0,Larmor)*Mn0Abs*(EBR.alpha+EBR.beta)*ejztr*sintheta*PhaseTerm;
355
-            //TODO TEST FOR ASYMETRY
356
-            //Real sintheta = std::sin(0.5*GAMMA*PulseI(iq)*Taup*(EBT.alpha-EBT.beta));
357
-            //F(iq) = volume * Complex(EBT.Bperp.real().norm(), EBT.Bperp.imag().norm());
358
-            //Complex(sintheta, EBT.Bperp.norm() );
359
-            //F(iq) = volume * Complex(EBT.alpha, EBT.beta);
360
-            //F(iq) = volume * MU0*Hr.norm();
361
-            //F(iq) = volume * EBT.err;
362
-            //F(iq) = volume * sintheta;
363 354
         }
364
-
365
-        return F;
366
-    }
367
-#endif
368
-#if 0
369
-    VectorXcr KernelV0::f( const Vector3r& r, const Real& volume, const Vector3cr& Ht, const Vector3cr& Hr ) {
370
-        VectorXcr F = VectorXcr::Ones( PulseI.size() );
371
-        F.array() *= volume * Complex(Ht.norm(), Hr.norm()); //*Ht.dot(Hr);
372 355
         return F;
373 356
     }
374
-#endif
375 357
 
376 358
 //     //--------------------------------------------------------------------------------------
377 359
 //     //       Class:  KernelV0
@@ -404,8 +386,8 @@ namespace Lemma {
404 386
         // This all follows Weichman et al., 2000.
405 387
         // There are some numerical stability issues that arise when the two terms in the beta
406 388
         // formulation are nearly equivalent. The current formulation will result in a null-valued
407
-        // beta, although this does not entirely recreate the true value of B perp. Error is checked
408
-        // to be below 1%, but reformulating may be welcome
389
+        // beta, or can underflow. However, this does not entirely recreate the true value of B perp.
390
+        // Error is checked to be below 1%, but reformulating for numeric stability may be welcome
409 391
         EllipticB ElipB = EllipticB();
410 392
         Vector3cr Bperp = B - B0hat.dot(B)*B0hat;
411 393
         Real BperpNorm  = Bperp.norm();
@@ -415,8 +397,13 @@ namespace Lemma {
415 397
         VectorXcr iB0 = Complex(0,1)*B0hat.cast<Complex>().array();
416 398
         ElipB.eizt = std::sqrt(Bp2 / std::abs(Bp2));
417 399
         ElipB.alpha = INVSQRT2*std::sqrt(BperpNorm*BperpNorm + std::abs(Bp2));
418
-        ElipB.beta = std::copysign(1, std::real(iB0.dot( Bperp.cross(Bperp.conjugate())) )) *
400
+        //ElipB.beta = std::copysign(1, std::real(iB0.dot( Bperp.cross(Bperp.conjugate())) )) *
401
+        ElipB.beta = sgn( std::real(iB0.dot( Bperp.cross(Bperp.conjugate())) )) *
419 402
                      (INVSQRT2*std::sqrt(BperpNorm*BperpNorm - std::abs(Bp2)));
403
+        // Correct underflow in beta calculation
404
+        // could use cerrno instead...
405
+        // http://en.cppreference.com/w/cpp/numeric/math/sqrt
406
+        if (ElipB.beta != ElipB.beta) ElipB.beta = 0;
420 407
         ElipB.bhat = ((Real)1./ElipB.alpha)*(((Real)1./ElipB.eizt)*Bperp.array()).real().array();
421 408
         ElipB.bhatp = B0hat.cross(ElipB.bhat);
422 409
         ElipB.zeta = std::real(std::log(ElipB.eizt)/Complex(0,1));
@@ -468,7 +455,6 @@ namespace Lemma {
468 455
                         0, step[1], step[2],
469 456
                   step[0], step[1], step[2] ).finished();
470 457
 
471
-        MatrixXcr kvals(8, PulseI.size());       // individual kernel vals
472 458
         cpoints->ClearFields();
473 459
         for (int ichild=0; ichild<8; ++ichild) {
474 460
             Vector3r cp = pos;    // Eigen complains about combining these
@@ -498,6 +484,7 @@ namespace Lemma {
498 484
             }
499 485
         }
500 486
 
487
+        MatrixXcr kvals(8, PulseI.size());       // individual kernel vals
501 488
         for (int ichild=0; ichild<8; ++ichild) {
502 489
             Vector3r cp = pos;    // Eigen complains about combining these
503 490
             cp += posadd.row(ichild);

Loading…
Cancel
Save