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

+ 9
- 22
src/KernelV0.cpp View File

325
     //       Class:  KernelV0
325
     //       Class:  KernelV0
326
     //      Method:  f
326
     //      Method:  f
327
     //--------------------------------------------------------------------------------------
327
     //--------------------------------------------------------------------------------------
328
-#if 1
329
     VectorXcr KernelV0::f( const Vector3r& r, const Real& volume, const Vector3cr& Ht, const Vector3cr& Hr ) {
328
     VectorXcr KernelV0::f( const Vector3r& r, const Real& volume, const Vector3cr& Ht, const Vector3cr& Hr ) {
330
 
329
 
331
         // Compute the elliptic fields
330
         // Compute the elliptic fields
352
             // Compute the tipping angle
351
             // Compute the tipping angle
353
             Real sintheta = std::sin(0.5*GAMMA*PulseI(iq)*Taup*(EBT.alpha-EBT.beta));
352
             Real sintheta = std::sin(0.5*GAMMA*PulseI(iq)*Taup*(EBT.alpha-EBT.beta));
354
             F(iq) = -volume*Complex(0,Larmor)*Mn0Abs*(EBR.alpha+EBR.beta)*ejztr*sintheta*PhaseTerm;
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
         return F;
355
         return F;
373
     }
356
     }
374
-#endif
375
 
357
 
376
 //     //--------------------------------------------------------------------------------------
358
 //     //--------------------------------------------------------------------------------------
377
 //     //       Class:  KernelV0
359
 //     //       Class:  KernelV0
404
         // This all follows Weichman et al., 2000.
386
         // This all follows Weichman et al., 2000.
405
         // There are some numerical stability issues that arise when the two terms in the beta
387
         // There are some numerical stability issues that arise when the two terms in the beta
406
         // formulation are nearly equivalent. The current formulation will result in a null-valued
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
         EllipticB ElipB = EllipticB();
391
         EllipticB ElipB = EllipticB();
410
         Vector3cr Bperp = B - B0hat.dot(B)*B0hat;
392
         Vector3cr Bperp = B - B0hat.dot(B)*B0hat;
411
         Real BperpNorm  = Bperp.norm();
393
         Real BperpNorm  = Bperp.norm();
415
         VectorXcr iB0 = Complex(0,1)*B0hat.cast<Complex>().array();
397
         VectorXcr iB0 = Complex(0,1)*B0hat.cast<Complex>().array();
416
         ElipB.eizt = std::sqrt(Bp2 / std::abs(Bp2));
398
         ElipB.eizt = std::sqrt(Bp2 / std::abs(Bp2));
417
         ElipB.alpha = INVSQRT2*std::sqrt(BperpNorm*BperpNorm + std::abs(Bp2));
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
                      (INVSQRT2*std::sqrt(BperpNorm*BperpNorm - std::abs(Bp2)));
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
         ElipB.bhat = ((Real)1./ElipB.alpha)*(((Real)1./ElipB.eizt)*Bperp.array()).real().array();
407
         ElipB.bhat = ((Real)1./ElipB.alpha)*(((Real)1./ElipB.eizt)*Bperp.array()).real().array();
421
         ElipB.bhatp = B0hat.cross(ElipB.bhat);
408
         ElipB.bhatp = B0hat.cross(ElipB.bhat);
422
         ElipB.zeta = std::real(std::log(ElipB.eizt)/Complex(0,1));
409
         ElipB.zeta = std::real(std::log(ElipB.eizt)/Complex(0,1));
468
                         0, step[1], step[2],
455
                         0, step[1], step[2],
469
                   step[0], step[1], step[2] ).finished();
456
                   step[0], step[1], step[2] ).finished();
470
 
457
 
471
-        MatrixXcr kvals(8, PulseI.size());       // individual kernel vals
472
         cpoints->ClearFields();
458
         cpoints->ClearFields();
473
         for (int ichild=0; ichild<8; ++ichild) {
459
         for (int ichild=0; ichild<8; ++ichild) {
474
             Vector3r cp = pos;    // Eigen complains about combining these
460
             Vector3r cp = pos;    // Eigen complains about combining these
498
             }
484
             }
499
         }
485
         }
500
 
486
 
487
+        MatrixXcr kvals(8, PulseI.size());       // individual kernel vals
501
         for (int ichild=0; ichild<8; ++ichild) {
488
         for (int ichild=0; ichild<8; ++ichild) {
502
             Vector3r cp = pos;    // Eigen complains about combining these
489
             Vector3r cp = pos;    // Eigen complains about combining these
503
             cp += posadd.row(ichild);
490
             cp += posadd.row(ichild);

Loading…
Cancel
Save