Browse Source

Fixes elliptic field calculation bug

master
T-bone 7 years ago
parent
commit
e28eeec83c
3 changed files with 53 additions and 15 deletions
  1. 5
    4
      examples/KernelV0-2.cpp
  2. 9
    6
      include/KernelV0.h
  3. 39
    5
      src/KernelV0.cpp

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

41
         Kern->PushCoil( "Coil 2", Rx1 );
41
         Kern->PushCoil( "Coil 2", Rx1 );
42
         Kern->SetLayeredEarthEM( earth );
42
         Kern->SetLayeredEarthEM( earth );
43
 
43
 
44
-        Kern->SetIntegrationSize( (Vector3r() << 200,200,200).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-9);
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]) );
63
         Kern->SetPulseCurrent( I ); // nbins, low, high
63
         Kern->SetPulseCurrent( I ); // nbins, low, high
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
         Real thick = .5;
68
         Real thick = .5;
68
         for (int ilay=1; ilay<interfaces.size(); ++ilay) {
69
         for (int ilay=1; ilay<interfaces.size(); ++ilay) {
69
             interfaces(ilay) = interfaces(ilay-1) + thick;
70
             interfaces(ilay) = interfaces(ilay-1) + thick;
75
     // may be more natural to work with?
76
     // may be more natural to work with?
76
     std::vector<std::string> tx = {std::string("Coil 1")};
77
     std::vector<std::string> tx = {std::string("Coil 1")};
77
     std::vector<std::string> rx = {std::string("Coil 2")};
78
     std::vector<std::string> rx = {std::string("Coil 2")};
78
-    Kern->CalculateK0( tx, rx, false ); // 3rd argument is vtk output
79
+    Kern->CalculateK0( tx, rx, true ); // 3rd argument is vtk output
79
 
80
 
80
     std::ofstream dout = std::ofstream(std::string("Rx-")+std::string(argv[3])+std::string(".dat"));
81
     std::ofstream dout = std::ofstream(std::string("Rx-")+std::string(argv[3])+std::string(".dat"));
81
     dout << "# Transmitters: ";
82
     dout << "# Transmitters: ";

+ 9
- 6
include/KernelV0.h View File

35
 namespace Lemma {
35
 namespace Lemma {
36
 
36
 
37
     struct EllipticB {
37
     struct EllipticB {
38
-        Vector3r  bhat;
39
-        Vector3r  bhatp;
40
         Real      alpha;
38
         Real      alpha;
41
         Real      beta;
39
         Real      beta;
42
-        Complex   eizt;
43
         Real      zeta;
40
         Real      zeta;
41
+        Real      err;
42
+        Complex   eizt;
43
+//        Complex   BperpdotB;
44
+        Vector3r  bhat;
45
+        Vector3r  bhatp;
46
+//        Vector3cr Bperp;
44
     };
47
     };
45
 
48
 
46
     template <typename T> int sgn(T val) {
49
     template <typename T> int sgn(T val) {
279
 
282
 
280
         int                                       ilay;
283
         int                                       ilay;
281
         int                                       nleaves;
284
         int                                       nleaves;
282
-        int                                       minLevel=4;
283
-        int                                       maxLevel=10;
285
+        int                                       minLevel=0;
286
+        int                                       maxLevel=12;
284
 
287
 
285
         Real                                      VOLSUM;
288
         Real                                      VOLSUM;
286
         Real                                      tol=1e-11;
289
         Real                                      tol=1e-11;
310
 
313
 
311
         // Physical constants and conversion factors
314
         // Physical constants and conversion factors
312
         static constexpr Real GAMMA = 2.67518e8;                  // MKS units
315
         static constexpr Real GAMMA = 2.67518e8;                  // MKS units
313
-        static constexpr Real INVSQRT2 = 0.70710678118654746;
316
+        static constexpr Real INVSQRT2 = 0.70710678118654746;     // 1/sqrt(2)
314
         static constexpr Real HBAR = 1.05457148e-34;              // m2 kg / s
317
         static constexpr Real HBAR = 1.05457148e-34;              // m2 kg / s
315
         static constexpr Real NH2O = 6.692e28;                    // [m^3]
318
         static constexpr Real NH2O = 6.692e28;                    // [m^3]
316
         static constexpr Real KB = 1.3805e-23;                    // m^2 kg s-2 K-1
319
         static constexpr Real KB = 1.3805e-23;                    // m^2 kg s-2 K-1

+ 39
- 5
src/KernelV0.cpp View File

282
     //       Class:  KernelV0
282
     //       Class:  KernelV0
283
     //      Method:  f
283
     //      Method:  f
284
     //--------------------------------------------------------------------------------------
284
     //--------------------------------------------------------------------------------------
285
+#if 1
285
     VectorXcr KernelV0::f( const Vector3r& r, const Real& volume, const Vector3cr& Ht, const Vector3cr& Hr ) {
286
     VectorXcr KernelV0::f( const Vector3r& r, const Real& volume, const Vector3cr& Ht, const Vector3cr& Hr ) {
286
 
287
 
287
         // Compute the elliptic fields
288
         // Compute the elliptic fields
294
 
295
 
295
         // Compute Mn0
296
         // Compute Mn0
296
         Vector3r Mn0 = ComputeMn0(1.0, B0);
297
         Vector3r Mn0 = ComputeMn0(1.0, B0);
298
+        //std::cout << "Mn0\t" << Mn0.transpose() << std::endl;
297
         Real Mn0Abs = Mn0.norm();
299
         Real Mn0Abs = Mn0.norm();
298
 
300
 
299
         // Compute phase delay
301
         // Compute phase delay
305
         VectorXcr F = VectorXcr::Zero( PulseI.size() );
307
         VectorXcr F = VectorXcr::Zero( PulseI.size() );
306
         for (int iq=0; iq<PulseI.size(); ++iq) {
308
         for (int iq=0; iq<PulseI.size(); ++iq) {
307
             // Compute the tipping angle
309
             // Compute the tipping angle
308
-            Real sintheta = std::sin(0.5*GAMMA*PulseI(iq)*Taup*(EBT.alpha-EBT.beta)); // why std::abs
310
+            Real sintheta = std::sin(0.5*GAMMA*PulseI(iq)*Taup*(EBT.alpha-EBT.beta));
309
             F(iq) = -volume*Complex(0,Larmor)*Mn0Abs*(EBR.alpha+EBR.beta)*ejztr*sintheta*PhaseTerm;
311
             F(iq) = -volume*Complex(0,Larmor)*Mn0Abs*(EBR.alpha+EBR.beta)*ejztr*sintheta*PhaseTerm;
312
+            //TODO TEST FOR ASYMETRY
313
+            //Real sintheta = std::sin(0.5*GAMMA*PulseI(iq)*Taup*(EBT.alpha-EBT.beta));
314
+            //F(iq) = volume * Complex(EBT.Bperp.real().norm(), EBT.Bperp.imag().norm()); //Complex(sintheta, EBT.Bperp.norm() );
315
+            //F(iq) = volume * Complex(EBT.alpha, EBT.beta);
316
+            //F(iq) = volume * EBT.err;
317
+            //F(iq) = volume * sintheta;
310
         }
318
         }
319
+
320
+        return F;
321
+    }
322
+#endif
323
+#if 0
324
+    VectorXcr KernelV0::f( const Vector3r& r, const Real& volume, const Vector3cr& Ht, const Vector3cr& Hr ) {
325
+        VectorXcr F = VectorXcr::Ones( PulseI.size() );
326
+        F.array() *= volume * Complex(Ht.norm(), Hr.norm()); //*Ht.dot(Hr);
311
         return F;
327
         return F;
312
     }
328
     }
329
+#endif
313
 
330
 
314
 //     //--------------------------------------------------------------------------------------
331
 //     //--------------------------------------------------------------------------------------
315
 //     //       Class:  KernelV0
332
 //     //       Class:  KernelV0
339
     //      Method:  ComputeV0Cell
356
     //      Method:  ComputeV0Cell
340
     //--------------------------------------------------------------------------------------
357
     //--------------------------------------------------------------------------------------
341
     EllipticB KernelV0::EllipticFieldRep (const Vector3cr& B, const Vector3r& B0hat) {
358
     EllipticB KernelV0::EllipticFieldRep (const Vector3cr& B, const Vector3r& B0hat) {
359
+        // This all follows Weichman et. al., 2000. There are some numerical stability isseus
360
+        // below. Reformulating may be welcome, may be in B field calculation too.
342
         EllipticB ElipB = EllipticB();
361
         EllipticB ElipB = EllipticB();
343
-        Vector3cr Bperp = B.array() - B0hat.dot(B)*B0hat.array();
344
-        Real BperpNorm = Bperp.norm();
362
+        Vector3cr Bperp = B - B0hat.dot(B)*B0hat; // complex - real??
363
+        //ElipB.BperpdotB = Bperp.dot(B0hat);       // TODO remove
364
+        Real BperpNorm  = Bperp.norm();
345
         Complex Bp2 = Bperp.transpose() * Bperp;
365
         Complex Bp2 = Bperp.transpose() * Bperp;
346
         VectorXcr iB0 = Complex(0,1)*B0hat.cast<Complex>().array();
366
         VectorXcr iB0 = Complex(0,1)*B0hat.cast<Complex>().array();
347
         ElipB.eizt = std::sqrt(Bp2 / std::abs(Bp2));
367
         ElipB.eizt = std::sqrt(Bp2 / std::abs(Bp2));
348
         ElipB.alpha = INVSQRT2*std::sqrt(BperpNorm*BperpNorm + std::abs(Bp2));
368
         ElipB.alpha = INVSQRT2*std::sqrt(BperpNorm*BperpNorm + std::abs(Bp2));
349
-        ElipB.beta = sgn(std::real(iB0.dot(Bperp.cross(Bperp.conjugate())))) *
350
-                (INVSQRT2)*std::sqrt(std::abs(BperpNorm*BperpNorm-std::abs(Bp2)));
369
+        ElipB.beta = std::copysign(1, std::real(iB0.dot( Bperp.cross(Bperp.conjugate())) )) *
370
+                     (INVSQRT2*std::sqrt(BperpNorm*BperpNorm - std::abs(Bp2)));
351
         ElipB.bhat = ((Real)1./ElipB.alpha)*(((Real)1./ElipB.eizt)*Bperp.array()).real().array();
371
         ElipB.bhat = ((Real)1./ElipB.alpha)*(((Real)1./ElipB.eizt)*Bperp.array()).real().array();
352
         ElipB.bhatp = B0hat.cross(ElipB.bhat);
372
         ElipB.bhatp = B0hat.cross(ElipB.bhat);
353
         ElipB.zeta = std::real(std::log(ElipB.eizt)/Complex(0,1));
373
         ElipB.zeta = std::real(std::log(ElipB.eizt)/Complex(0,1));
374
+        /* use as an error check decomposed field - computed actual */
375
+        Vector3cr Bperp2 = ElipB.eizt * (ElipB.alpha * ElipB.bhat
376
+                       + (Complex(0,1) * ElipB.beta * ElipB.bhatp) );
377
+        ElipB.err = (Bperp-Bperp2).norm();
378
+        if (ElipB.err > 1e-12) {
379
+            std::cout << "Elip error\n";
380
+            std::cout << "Bperp \t" << Bperp.transpose() << std::endl;
381
+            std::cout << "Bperp2\t" << Bperp2.transpose() << std::endl;
382
+            std::cout << "err   \t" << ElipB.err << std::endl;
383
+        }
384
+        //std::cout << "B0\t" << B0hat.transpose() << std::endl;
354
         return ElipB;
385
         return ElipB;
355
     }
386
     }
356
 
387
 
391
         Eigen::Matrix<Complex, 3, 8> Ht = Eigen::Matrix<Complex, 3, 8>::Zero();
422
         Eigen::Matrix<Complex, 3, 8> Ht = Eigen::Matrix<Complex, 3, 8>::Zero();
392
         Eigen::Matrix<Complex, 3, 8> Hr = Eigen::Matrix<Complex, 3, 8>::Zero();
423
         Eigen::Matrix<Complex, 3, 8> Hr = Eigen::Matrix<Complex, 3, 8>::Zero();
393
         for ( auto EMCalc : EMEarths ) {
424
         for ( auto EMCalc : EMEarths ) {
425
+
426
+
427
+
394
             EMCalc.second->GetFieldPoints()->ClearFields();
428
             EMCalc.second->GetFieldPoints()->ClearFields();
395
             EMCalc.second->CalculateWireAntennaFields();
429
             EMCalc.second->CalculateWireAntennaFields();
396
             switch (EMCalc.second->GetTxRxMode()) {
430
             switch (EMCalc.second->GetTxRxMode()) {

Loading…
Cancel
Save