Browse Source

Opalstack -> GitHub sync test

master
Trevor Irons 3 years ago
parent
commit
85d7200fb4
4 changed files with 49 additions and 2 deletions
  1. 1
    1
      README.md
  2. 15
    0
      include/KernelV0.h
  3. 2
    0
      python/pyMerlin.cpp
  4. 31
    1
      src/KernelV0.cpp

+ 1
- 1
README.md View File

1
 ==About
1
 ==About
2
-Merlin is a NMR modelling module for Lemma. 
2
+Merlin is a surface NMR modelling module for Lemma. 
3
 
3
 
4
 =Capabilities 
4
 =Capabilities 

+ 15
- 0
include/KernelV0.h View File

216
         }
216
         }
217
 
217
 
218
         /**
218
         /**
219
+         * @param[in] dfin is the transmitter offset from Larmor in Hz. Calculated as Txf - Lf
220
+         */
221
+        inline void SetDf( const Real& dfin ) {
222
+            df = dfin;
223
+        }
224
+
225
+        /**
226
+         * @return the pulse offset from the Larmor frequency
227
+         */
228
+        inline Real GetDf ( ) {
229
+            return df;
230
+        }
231
+
232
+        /**
219
          * @param[in] value the 1D-EM model used for calculations
233
          * @param[in] value the 1D-EM model used for calculations
220
          */
234
          */
221
         inline void SetLayeredEarthEM ( std::shared_ptr< LayeredEarthEM > value ) {
235
         inline void SetLayeredEarthEM ( std::shared_ptr< LayeredEarthEM > value ) {
376
         Real                                      Temperature=283.;
390
         Real                                      Temperature=283.;
377
         Real                                      Taup = .020;  // Sec
391
         Real                                      Taup = .020;  // Sec
378
         Real                                      Larmor;
392
         Real                                      Larmor;
393
+        Real                                      df=0;
379
 
394
 
380
         Vector3r                                  Size;
395
         Vector3r                                  Size;
381
         Vector3r                                  Origin;
396
         Vector3r                                  Origin;

+ 2
- 0
python/pyMerlin.cpp View File

56
             .def("SetPulseDuration", &Lemma::KernelV0::SetPulseDuration, "Sets the duration of the pulse")
56
             .def("SetPulseDuration", &Lemma::KernelV0::SetPulseDuration, "Sets the duration of the pulse")
57
             .def("SetDepthLayerInterfaces", &Lemma::KernelV0::SetDepthLayerInterfaces, "Sets the layer depth interfaces")
57
             .def("SetDepthLayerInterfaces", &Lemma::KernelV0::SetDepthLayerInterfaces, "Sets the layer depth interfaces")
58
             .def("SetHankelTransformType", &Lemma::KernelV0::SetHankelTransformType, "Sets the Hankel transform type")
58
             .def("SetHankelTransformType", &Lemma::KernelV0::SetHankelTransformType, "Sets the Hankel transform type")
59
+            .def("SetDf", &Lemma::KernelV0::SetDf, "Sets the transmitter offset frequncy in Hz, (Txf - Lf)")
59
 
60
 
60
             // accessors
61
             // accessors
61
             .def("GetName", &Lemma::KernelV0::GetName, "Returns the name of the class")
62
             .def("GetName", &Lemma::KernelV0::GetName, "Returns the name of the class")
65
             .def("GetInterfaces", &Lemma::KernelV0::GetInterfaces, "Returns the layer interfaces")
66
             .def("GetInterfaces", &Lemma::KernelV0::GetInterfaces, "Returns the layer interfaces")
66
             .def("GetPulseCurrent", &Lemma::KernelV0::GetPulseCurrent, "Returns the pulse current")
67
             .def("GetPulseCurrent", &Lemma::KernelV0::GetPulseCurrent, "Returns the pulse current")
67
             .def("GetPulseDuration", &Lemma::KernelV0::GetPulseDuration, "Returns the length of the pulse moment")
68
             .def("GetPulseDuration", &Lemma::KernelV0::GetPulseDuration, "Returns the length of the pulse moment")
69
+            .def("GetDf", &Lemma::KernelV0::GetDf, "Returns the transmitter offset in Hz")
68
 
70
 
69
             // operations
71
             // operations
70
             .def("CalculateK0", &Lemma::KernelV0::CalculateK0, "Calculates an intial amplitude kernel")
72
             .def("CalculateK0", &Lemma::KernelV0::CalculateK0, "Calculates an intial amplitude kernel")

+ 31
- 1
src/KernelV0.cpp View File

218
                 EMEarths[tx]->SetHankelTransformMethod(HankelType);
218
                 EMEarths[tx]->SetHankelTransformMethod(HankelType);
219
                 EMEarths[tx]->SetTxRxMode(TX);
219
                 EMEarths[tx]->SetTxRxMode(TX);
220
                 TxRx[tx]->SetCurrent(1.);
220
                 TxRx[tx]->SetCurrent(1.);
221
+
222
+                // calculate df TODO, fix for multiple tx frequencies
223
+                df = TxRx[tx]->GetFrequency(0) - Larmor/(2.*PI);
224
+                std::cout << "df=" << df << std::endl;
221
         }
225
         }
222
         for (auto rx : Rx) {
226
         for (auto rx : Rx) {
223
             if (EMEarths.count(rx)) {
227
             if (EMEarths.count(rx)) {
482
         // Calcuate vector of all responses
486
         // Calcuate vector of all responses
483
         VectorXcr F = VectorXcr::Zero( PulseI.size() );
487
         VectorXcr F = VectorXcr::Zero( PulseI.size() );
484
         for (int iq=0; iq<PulseI.size(); ++iq) {
488
         for (int iq=0; iq<PulseI.size(); ++iq) {
485
-            // Compute the tipping angle
489
+
490
+            /////////////////////////////////////////////////////////////////////////////
491
+            // Compute the tipping angle for on-resonance
492
+            // Weichman formulation
493
+            /*
486
             Real sintheta = std::sin(0.5*GAMMA*PulseI(iq)*Taup*(EBT.alpha-EBT.beta));
494
             Real sintheta = std::sin(0.5*GAMMA*PulseI(iq)*Taup*(EBT.alpha-EBT.beta));
487
             F(iq) = -volume*Complex(0,Larmor)*Mn0Abs*(EBR.alpha+EBR.beta)*ejztr*sintheta*PhaseTerm;
495
             F(iq) = -volume*Complex(0,Larmor)*Mn0Abs*(EBR.alpha+EBR.beta)*ejztr*sintheta*PhaseTerm;
496
+            */
497
+
498
+            /////////////////////////////////////////////////////////////////////////////
499
+            // compute tipping ange for off-resonance, from MRSMatlab (Mueller, et. al)
500
+            // but based on seperate works by Grombacher and Walbrecher.
501
+            //theta    = atan2(0.5*gamma*pm_vec(n)/taup*(Bcomps.alpha - Bcomps.beta),(2*pi*df));
502
+            //flip_eff = sqrt((0.5*gamma*pm_vec(n)*(Bcomps.alpha - Bcomps.beta)).^2 + ...
503
+            //            (2*pi*df*taup).^2 );
504
+            //m     = sin(flip_eff) .* sin(theta) + ...
505
+            //    1i*(-1)*sin(theta).*cos(theta) .* (cos(flip_eff) - 1);
506
+            //kern = gamma * earth.erdt^2 * 3.29e-3 * Px .* Bcomps.e_zeta.^2 .* ...
507
+            //            (Bcomps.alpha + Bcomps.beta) .* m;
508
+            //K(n,:) = sum(sum(kern.*dh*dz));
509
+            // TODO, benchmark calls to pow below...modern compilers should optimize this
510
+            // Real df = 25;  // Hz? df is a class data member
511
+            Real theta = std::atan2( 0.5*GAMMA*PulseI(iq)*(EBT.alpha-EBT.beta), 2*PI*df );
512
+            Real flip_eff = std::sqrt( std::pow(0.5*GAMMA*PulseI(iq)*Taup*(EBT.alpha-EBT.beta),2) +
513
+                                       std::pow(2*PI*df*Taup,2));
514
+            Complex m = std::sin(flip_eff)*std::sin(theta) +
515
+                Complex(0,-1)*std::sin(theta)*std::cos(theta) * (std::cos(flip_eff) - 1.);
516
+
517
+            F(iq) = -volume*Complex(0,Larmor)*Mn0Abs*(EBR.alpha+EBR.beta)*ejztr*m*PhaseTerm;
488
         }
518
         }
489
         return F;
519
         return F;
490
     }
520
     }

Loading…
Cancel
Save