|
@@ -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);
|