Selaa lähdekoodia

Fixes elliptic field calculation bug

master
T-bone 7 vuotta sitten
vanhempi
commit
e28eeec83c
3 muutettua tiedostoa jossa 53 lisäystä ja 15 poistoa
  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 Näytä tiedosto

@@ -41,9 +41,9 @@ int main(int argc, char** argv) {
41 41
         Kern->PushCoil( "Coil 2", Rx1 );
42 42
         Kern->SetLayeredEarthEM( earth );
43 43
 
44
-        Kern->SetIntegrationSize( (Vector3r() << 200,200,200).finished() );
44
+        Kern->SetIntegrationSize( (Vector3r() << 200,200,100).finished() );
45 45
         Kern->SetIntegrationOrigin( (Vector3r() << -100, -100, .5).finished() );
46
-        Real tol(1e-9);
46
+        Real tol(1e-11); // 13
47 47
         Kern->SetTolerance( tol ); // 1e-12
48 48
 
49 49
 //         Kern->AlignWithAkvoDataset( YAML::LoadFile(argv[2]) );
@@ -63,7 +63,8 @@ int main(int argc, char** argv) {
63 63
         Kern->SetPulseCurrent( I ); // nbins, low, high
64 64
 
65 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 68
         Real thick = .5;
68 69
         for (int ilay=1; ilay<interfaces.size(); ++ilay) {
69 70
             interfaces(ilay) = interfaces(ilay-1) + thick;
@@ -75,7 +76,7 @@ int main(int argc, char** argv) {
75 76
     // may be more natural to work with?
76 77
     std::vector<std::string> tx = {std::string("Coil 1")};
77 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 81
     std::ofstream dout = std::ofstream(std::string("Rx-")+std::string(argv[3])+std::string(".dat"));
81 82
     dout << "# Transmitters: ";

+ 9
- 6
include/KernelV0.h Näytä tiedosto

@@ -35,12 +35,15 @@
35 35
 namespace Lemma {
36 36
 
37 37
     struct EllipticB {
38
-        Vector3r  bhat;
39
-        Vector3r  bhatp;
40 38
         Real      alpha;
41 39
         Real      beta;
42
-        Complex   eizt;
43 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 49
     template <typename T> int sgn(T val) {
@@ -279,8 +282,8 @@ namespace Lemma {
279 282
 
280 283
         int                                       ilay;
281 284
         int                                       nleaves;
282
-        int                                       minLevel=4;
283
-        int                                       maxLevel=10;
285
+        int                                       minLevel=0;
286
+        int                                       maxLevel=12;
284 287
 
285 288
         Real                                      VOLSUM;
286 289
         Real                                      tol=1e-11;
@@ -310,7 +313,7 @@ namespace Lemma {
310 313
 
311 314
         // Physical constants and conversion factors
312 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 317
         static constexpr Real HBAR = 1.05457148e-34;              // m2 kg / s
315 318
         static constexpr Real NH2O = 6.692e28;                    // [m^3]
316 319
         static constexpr Real KB = 1.3805e-23;                    // m^2 kg s-2 K-1

+ 39
- 5
src/KernelV0.cpp Näytä tiedosto

@@ -282,6 +282,7 @@ namespace Lemma {
282 282
     //       Class:  KernelV0
283 283
     //      Method:  f
284 284
     //--------------------------------------------------------------------------------------
285
+#if 1
285 286
     VectorXcr KernelV0::f( const Vector3r& r, const Real& volume, const Vector3cr& Ht, const Vector3cr& Hr ) {
286 287
 
287 288
         // Compute the elliptic fields
@@ -294,6 +295,7 @@ namespace Lemma {
294 295
 
295 296
         // Compute Mn0
296 297
         Vector3r Mn0 = ComputeMn0(1.0, B0);
298
+        //std::cout << "Mn0\t" << Mn0.transpose() << std::endl;
297 299
         Real Mn0Abs = Mn0.norm();
298 300
 
299 301
         // Compute phase delay
@@ -305,11 +307,26 @@ namespace Lemma {
305 307
         VectorXcr F = VectorXcr::Zero( PulseI.size() );
306 308
         for (int iq=0; iq<PulseI.size(); ++iq) {
307 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 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 327
         return F;
312 328
     }
329
+#endif
313 330
 
314 331
 //     //--------------------------------------------------------------------------------------
315 332
 //     //       Class:  KernelV0
@@ -339,18 +356,32 @@ namespace Lemma {
339 356
     //      Method:  ComputeV0Cell
340 357
     //--------------------------------------------------------------------------------------
341 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 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 365
         Complex Bp2 = Bperp.transpose() * Bperp;
346 366
         VectorXcr iB0 = Complex(0,1)*B0hat.cast<Complex>().array();
347 367
         ElipB.eizt = std::sqrt(Bp2 / std::abs(Bp2));
348 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 371
         ElipB.bhat = ((Real)1./ElipB.alpha)*(((Real)1./ElipB.eizt)*Bperp.array()).real().array();
352 372
         ElipB.bhatp = B0hat.cross(ElipB.bhat);
353 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 385
         return ElipB;
355 386
     }
356 387
 
@@ -391,6 +422,9 @@ namespace Lemma {
391 422
         Eigen::Matrix<Complex, 3, 8> Ht = Eigen::Matrix<Complex, 3, 8>::Zero();
392 423
         Eigen::Matrix<Complex, 3, 8> Hr = Eigen::Matrix<Complex, 3, 8>::Zero();
393 424
         for ( auto EMCalc : EMEarths ) {
425
+
426
+
427
+
394 428
             EMCalc.second->GetFieldPoints()->ClearFields();
395 429
             EMCalc.second->CalculateWireAntennaFields();
396 430
             switch (EMCalc.second->GetTxRxMode()) {

Loading…
Peruuta
Tallenna