209#include "TRestAxionField.h"
213#include <gsl/gsl_errno.h>
214#include <gsl/gsl_integration.h>
252 Double_t lengthInMeters = Lcoh *
units(
"m");
256 Double_t sol = lengthInMeters * Bmag * tm;
270 Double_t lengthInMeters = Lcoh *
units(
"m");
274 Double_t sol = lengthInMeters * Bmag * tm / 2;
275 sol = sol * sol * 1.0e-20;
295 Double_t absLength) {
299 Double_t photonMass = mg;
303 RESTDebug <<
"+--------------------------------------------------------------------------+" << RESTendl;
304 RESTDebug <<
" TRestAxionField::GammaTransmissionProbability. Parameter summary" << RESTendl;
305 RESTDebug <<
" Photon mass : " << photonMass <<
" eV" << RESTendl;
306 RESTDebug <<
" Axion mass : " << ma <<
" eV" << RESTendl;
307 RESTDebug <<
" Axion energy : " <<
fEa <<
" keV" << RESTendl;
308 RESTDebug <<
" Lcoh : " <<
fLcoh <<
" mm" << RESTendl;
309 RESTDebug <<
" Bmag : " <<
fBmag <<
" T" << RESTendl;
310 RESTDebug <<
"+--------------------------------------------------------------------------+" << RESTendl;
314 Double_t q = (ma * ma - photonMass * photonMass) / 2. / (
fEa *
units(
"eV"));
316 Double_t phi = q * l;
318 Double_t Gamma = absLength;
320 Double_t GammaL = Gamma * cohLength *
units(
"cm") /
units(
"m");
323 std::cout <<
"+------------------------+" << std::endl;
324 std::cout <<
" Intermediate calculations" << std::endl;
325 std::cout <<
" q : " << q <<
" eV" << std::endl;
326 std::cout <<
" l : " << l <<
" eV-1" << std::endl;
327 std::cout <<
" phi : " << phi << std::endl;
328 std::cout <<
"Gamma : " << Gamma << std::endl;
329 std::cout <<
"GammaL : " << GammaL << std::endl;
330 std::cout <<
"+------------------------+" << std::endl;
333 Double_t MFactor = phi * phi + GammaL * GammaL / 4.0;
334 MFactor = 1.0 / MFactor;
337 std::cout <<
"Mfactor : " << MFactor << std::endl;
339 std::cout <<
"cos(phi) : " << cos(phi) << std::endl;
340 std::cout <<
"Exp(-GammaL) : " << exp(-GammaL) << std::endl;
344 (1 + exp(-GammaL) - 2 * exp(-GammaL / 2) * cos(phi)));
346 if (fDebug) std::cout <<
"Axion-photon transmission probability : " << sol << std::endl;
356 Double_t mg, Double_t absLength) {
384 Double_t Ea, Double_t ma, Double_t mg,
385 Double_t absLength) {
387 Double_t Lcoh = (Bmag.size() - 1) * deltaL;
388 Double_t cohLength = Lcoh *
units(
"m");
390 Double_t photonMass = mg;
394 Double_t fieldAverage = 0;
395 if (Bmag.size() > 0) fieldAverage = std::accumulate(Bmag.begin(), Bmag.end(), 0.0) / Bmag.size();
398 std::cout <<
"+--------------------------------------------------------------------------+"
400 std::cout <<
" TRestAxionField::GammaTransmissionProbability. Parameter summary" << std::endl;
401 std::cout <<
" Photon mass : " << photonMass <<
" eV" << std::endl;
402 std::cout <<
" Axion mass : " << ma <<
" eV" << std::endl;
403 std::cout <<
" Axion energy : " << Ea <<
" keV" << std::endl;
404 std::cout <<
" Lcoh : " << cohLength <<
" m" << std::endl;
405 std::cout <<
" Bmag average : " << fieldAverage <<
" T" << std::endl;
406 std::cout <<
"+--------------------------------------------------------------------------+"
411 if (ma == 0.0 && photonMass == 0.0)
return BLHalfSquared(fieldAverage, Lcoh);
413 Double_t q = (ma * ma - photonMass * photonMass) / 2. / (Ea *
units(
"eV"));
415 Double_t phi = q * l;
417 Double_t Gamma = absLength;
419 Double_t GammaL = Gamma * cohLength *
units(
"cm") /
units(
"m");
422 std::cout <<
"+------------------------+" << std::endl;
423 std::cout <<
" Intermediate calculations" << std::endl;
424 std::cout <<
" q : " << q <<
" eV" << std::endl;
425 std::cout <<
" l : " << l <<
" eV-1" << std::endl;
426 std::cout <<
" phi : " << phi << std::endl;
427 std::cout <<
"Gamma : " << Gamma << std::endl;
428 std::cout <<
"GammaL : " << GammaL << std::endl;
429 std::cout <<
"+------------------------+" << std::endl;
432 Double_t MFactor = phi * phi + GammaL * GammaL / 4.0;
433 MFactor = 1.0 / MFactor;
436 std::cout <<
"Mfactor : " << MFactor << std::endl;
437 std::cout <<
"(BL/2)^2 : " <<
BLHalfSquared(fieldAverage, Lcoh) << std::endl;
438 std::cout <<
"cos(phi) : " << cos(phi) << std::endl;
439 std::cout <<
"Exp(-GammaL) : " << exp(-GammaL) << std::endl;
445 for (
unsigned int n = 0; n < Bmag.size() - 1; n++) {
446 Double_t Bmiddle = 0.5 * (Bmag[n] + Bmag[n + 1]);
448 Double_t lStepIneV = ((double)n + 0.5) * deltaIneV;
449 Double_t lStepInCm = ((double)n + 0.5) * deltaL *
units(
"cm");
451 TComplex qCgC(0.5 * Gamma * lStepInCm, -q * lStepIneV);
452 qCgC = TComplex::Exp(qCgC);
454 TComplex integrand = Bmiddle * deltaL * qCgC;
459 Double_t sol = exp(-GammaL) * sum.Rho2() *
BLHalfSquared(1, 1);
462 if (fDebug) std::cout <<
"Axion-photon transmission probability : " << sol << std::endl;
464 return (Double_t)sol;
488 gsl_set_error_handler_off();
491 RESTError <<
"TRestAxionField::GammaTransmissionFieldMapProbability requires a magnetic field map!"
493 RESTError <<
"Use TRestAxionField::AssignMagneticField method to assign one" << RESTendl;
499 double photonMass = 0;
503 std::cout <<
"+--------------------------------------------------------------------------+"
505 std::cout <<
" TRestAxionField::GammaTransmissionProbability. Parameter summary" << std::endl;
506 std::cout <<
" Photon mass : " << photonMass <<
" eV" << std::endl;
507 std::cout <<
" Axion mass : " << ma <<
" eV" << std::endl;
508 std::cout <<
" Axion energy : " << Ea <<
" keV" << std::endl;
509 std::cout <<
"+--------------------------------------------------------------------------+"
513 double q = (ma * ma - photonMass * photonMass) / 2. / (Ea *
units(
"eV"));
520 std::cout <<
"+------------------------+" << std::endl;
521 std::cout <<
" Intermediate calculations" << std::endl;
522 std::cout <<
" q : " << q <<
" eV" << std::endl;
523 std::cout <<
"Gamma : " << Gamma << std::endl;
524 std::cout <<
"+------------------------+" << std::endl;
552 Int_t num_intervals) {
555 std::pair<TRestAxionMagneticField*, double> params = {
fMagneticField, Gamma};
557 gsl_integration_workspace* workspace = gsl_integration_workspace_alloc(num_intervals);
563 auto start = std::chrono::system_clock::now();
565 int status = gsl_integration_qag(&F, 0,
fMagneticField->GetTrackLength(), accuracy, accuracy,
566 num_intervals, GSL_INTEG_GAUSS61, workspace, &reprob, &rerr);
568 if (status > 0)
return {0, status};
570 auto end = std::chrono::system_clock::now();
571 auto seconds = std::chrono::duration_cast<std::chrono::milliseconds>(end - start);
576 double prob = C * reprob * reprob;
577 double proberr = 2 * C * reprob * rerr;
580 std::cout <<
" ---- TRestAxionField::ComputeResonanceIntegral (QAG) ----" << std::endl;
581 std::cout <<
"Gamma: " << Gamma <<
" mm-1" << std::endl;
582 std::cout <<
"accuracy: " << accuracy << std::endl;
583 std::cout <<
"num_intervals: " << num_intervals << std::endl;
584 std::cout <<
" -------" << std::endl;
585 std::cout <<
"Probability: " << prob << std::endl;
586 std::cout <<
"Probability error: " << proberr << std::endl;
587 std::cout <<
"Computing time: " << seconds.count() << std::endl;
588 std::cout <<
" -------" << std::endl;
591 std::pair<Double_t, Double_t> sol = {prob, proberr};
616 double improb, imerr;
618 std::pair<TRestAxionMagneticField*, double> params = {
fMagneticField, Gamma};
620 gsl_integration_workspace* workspace = gsl_integration_workspace_alloc(num_intervals);
626 auto start = std::chrono::system_clock::now();
628 gsl_integration_qawo_table* wf =
629 gsl_integration_qawo_table_alloc(q,
fMagneticField->GetTrackLength(), GSL_INTEG_COSINE, qawo_levels);
631 gsl_integration_qawo(&F, 0, accuracy, accuracy, num_intervals, workspace, wf, &reprob, &rerr);
633 gsl_integration_qawo_table_free(wf);
637 gsl_integration_qawo_table_set(wf, q,
fMagneticField->GetTrackLength(), GSL_INTEG_SINE);
638 status = gsl_integration_qawo(&F, 0, accuracy, accuracy, num_intervals, workspace, wf, &improb, &imerr);
640 gsl_integration_qawo_table_free(wf);
644 auto end = std::chrono::system_clock::now();
645 auto seconds = std::chrono::duration_cast<std::chrono::milliseconds>(end - start);
650 double prob = C * (reprob * reprob + improb * improb);
651 double proberr = 2 * C * TMath::Sqrt(reprob * reprob * rerr * rerr + improb * improb * imerr * imerr);
654 std::cout <<
" ---- TRestAxionField::ComputeOffResonanceIntegral (QAWO) ----" << std::endl;
655 std::cout <<
"Gamma: " << Gamma <<
" mm-1" << std::endl;
656 std::cout <<
"q: " << q <<
"mm-1" << std::endl;
657 std::cout <<
"accuracy: " << accuracy << std::endl;
658 std::cout <<
"num_intervals: " << num_intervals << std::endl;
659 std::cout <<
"qawo_levels: " << qawo_levels << std::endl;
660 std::cout <<
" -------" << std::endl;
661 std::cout <<
"Probability: " << prob << std::endl;
662 std::cout <<
"Probability error: " << proberr << std::endl;
663 std::cout <<
"Computing time: " << seconds.count() << std::endl;
664 std::cout <<
" -------" << std::endl;
667 std::pair<Double_t, Double_t> sol = {prob, proberr};
687 Double_t photonMass = mg;
691 RESTDebug <<
"+--------------------------------------------------------------------------+"
693 RESTDebug <<
" TRestAxionField::AxionAbsorptionProbability. Parameter summary" << RESTendl;
694 RESTDebug <<
" Photon mass : " << photonMass <<
" eV" << RESTendl;
695 RESTDebug <<
" Axion mass : " << ma <<
" eV" << RESTendl;
696 RESTDebug <<
" Axion energy : " <<
fEa <<
" keV" << RESTendl;
697 RESTDebug <<
" Lcoh : " <<
fLcoh <<
" mm" << RESTendl;
698 RESTDebug <<
" Bmag : " <<
fBmag <<
" T" << RESTendl;
699 RESTDebug <<
"+--------------------------------------------------------------------------+"
705 Double_t q = (ma * ma - photonMass * photonMass) / 2. / (
fEa *
units(
"eV"));
707 Double_t phi = q * l;
709 Double_t Gamma = absLength;
711 Double_t GammaL = Gamma * cohLength *
units(
"cm") /
units(
"m");
714 RESTDebug <<
"+------------------------+" << RESTendl;
715 RESTDebug <<
" Intermediate calculations" << RESTendl;
716 RESTDebug <<
" q : " << q <<
" eV" << RESTendl;
717 RESTDebug <<
" l : " << l <<
" eV-1" << RESTendl;
718 RESTDebug <<
" phi : " << phi << RESTendl;
719 RESTDebug <<
"Gamma : " << Gamma << RESTendl;
720 RESTDebug <<
"GammaL : " << GammaL << RESTendl;
721 RESTDebug <<
"+------------------------+" << RESTendl;
724 Double_t MFactor = phi * phi + GammaL * GammaL / 4.0;
725 MFactor = 1.0 / MFactor;
728 RESTDebug <<
"Mfactor : " << MFactor << RESTendl;
730 RESTDebug <<
"cos(phi) : " << cos(phi) << RESTendl;
731 RESTDebug <<
"Exp(-GammaL) : " << exp(-GammaL) << RESTendl;
736 if (fDebug) RESTDebug <<
"Axion-photon absorption probability : " << sol << RESTendl;
746 Double_t mg, Double_t absLength) {
767 Double_t maxMass = 10;
769 Double_t resonanceMass = 0;
773 Double_t scanMass = resonanceMass;
777 if (scanMass > maxMass) {
778 RESTError <<
"TRestAxionField::GammaTransmissionProbability. Something went wrong when "
785 Double_t fwhm = scanMass - resonanceMass;
787 RESTError <<
"TRestAxionField::GammaTransmissionProbability. Problem calculating FWHM!" << RESTendl;
819 std::vector<std::pair<Double_t, Double_t>> massDensityPairs;
835 Double_t ma = firstMass;
839 massDensityPairs.push_back(std::make_pair(ma, density));
842 Double_t factor = TMath::Exp(-ma * rampDown) + 1;
848 massDensityPairs.push_back(std::make_pair(ma, density));
854 return massDensityPairs;
A metadata class to define the gas properties used in axion search calculations.
Double_t GetPhotonMass(double en)
It returns the equivalent photon mass (in eV) for the gas mixture at the given input energy expressed...
Double_t GetDensityForMass(double m_gamma, double en=4.2)
It returns the equivalent gas density for a given photon mass expressed in eV and a given axion energ...
void SetGasDensity(TString gasName, Double_t density)
It adds a new gas component to the mixture. If it already exists it will update its density.
Double_t GetPhotonAbsorptionLength(Double_t energy)
It returns the inverse of the absorption lenght, for the gas mixture, in cm-1, for the given energy i...
A basic class to define analytical axion-photon conversion calculations for axion helioscopes.
std::pair< Double_t, Double_t > GammaTransmissionFieldMapProbability(Double_t Ea, Double_t ma, Double_t accuracy=1.e-1, Int_t num_intervals=100, Int_t qawo_levels=20)
Performs the calculation of axion-photon conversion probability using directly equation (28) from J....
Double_t BL(Double_t Bmag, Double_t Lcoh)
Performs the calculation of (BL) factor in natural units.
Double_t AxionAbsorptionProbability(Double_t ma, Double_t mg=0, Double_t absLength=0)
Performs the calculation of axion-photon absorption probability using directly equation (18) from van...
void Initialize()
Initialization of TRestAxionField class.
static double Integrand(double x, void *params)
Integrand used for axion-photon probability integration.
void AssignBufferGas(TRestAxionBufferGas *buffGas)
It assigns a gas buffer medium to the calculation.
~TRestAxionField()
Default destructor.
Double_t BLHalfSquared(Double_t Bmag, Double_t Lcoh)
Performs the calculation of (BL/2)^2 factor in natural units.
Double_t fEa
The energy of the axion in keV.
std::vector< std::pair< Double_t, Double_t > > GetMassDensityScanning(std::string gasName="He", Double_t maMax=0.15, Double_t rampDown=5.0)
This method determines the proper densities to be used in an axion helioscope experiment in order to ...
std::pair< Double_t, Double_t > ComputeOffResonanceIntegral(Double_t q, Double_t Gamma, Double_t accuracy, Int_t num_intervals, Int_t qawo_levels)
Performs the calculation of axion-photon conversion probability using directly equation (28) from J....
Double_t GammaTransmissionProbability(Double_t Ea, Double_t ma, Double_t mg=0, Double_t absLength=0)
Performs the calculation of axion-photon conversion probability using directly equation (11) from van...
TRestAxionMagneticField * fMagneticField
A pointer to the magnetic field definition.
TRestAxionBufferGas * fBufferGas
A pointer to the buffer gas definition.
Double_t fBmag
The magnetic field in Teslas (used for constant field formulas)
Double_t fLcoh
The coherence lenght (in mm) where the magnetic field is defined (for constant field)
TRestAxionField()
Default constructor.
Double_t GammaTransmissionFWHM(Double_t step=0.00001)
Performs the calculation of the FWHM for the axion-photon conversion probability computed in TRestAxi...
std::pair< Double_t, Double_t > ComputeResonanceIntegral(Double_t Gamma, Double_t accuracy, Int_t num_intervals)
Performs the calculation of axion-photon conversion probability using directly equation (28) from J....
constexpr double lightSpeed
Speed of light in m/s.
constexpr double PhMeterIneV
A meter in eV.
constexpr double naturalElectron
Electron charge in natural units.