From e891f0489adf92c49f5f61c339c8f90f785f5679 Mon Sep 17 00:00:00 2001 From: Andreas Suter Date: Fri, 6 Jun 2025 10:21:09 +0200 Subject: [PATCH] 1st full Gauss/Lorentz LF. Still room for optimization, and further testing. --- src/classes/PTheory.cpp | 172 ++++++++++++++++++++++++++++++++++++---- src/include/PTheory.h | 2 + 2 files changed, 157 insertions(+), 17 deletions(-) diff --git a/src/classes/PTheory.cpp b/src/classes/PTheory.cpp index d1be50fd..3fd45c08 100644 --- a/src/classes/PTheory.cpp +++ b/src/classes/PTheory.cpp @@ -29,6 +29,7 @@ #include #include +#include #include #include @@ -1759,16 +1760,128 @@ Double_t PTheory::DynamicGauLorKTLFFast(Double_t t, const PDoubleVector& paramVa //-------------------------------------------------------------------------- /** - * @brief PTheory::DynamicGauLorKTLF - * @param t - * @param paramValues - * @param funcValues - * @return + *

Local Gaussian, global Lorentzian in LF. + * For details see "Muon Spin Rotation, Relaxation, and Resonance", + * A. Yaouanc and P. Dalmas Sec. 6.4, Eq.(6.86). + * + * @param t time in \f$(\mu\mathrm{s})\f$, or x-axis value for non-muSR fit + * @param paramValues parameter values + * @param funcValues vector with the functions (i.e. functions of the parameters) + * + * @return Polarization value of this function */ Double_t PTheory::DynamicGauLorKTLF(Double_t t, const PDoubleVector& paramValues, const PDoubleVector& funcValues) const { - // NOT YET IMPLEMENTED. Will be Eq.(6.86) - return 0.0; + // expected parameters: frequency damping hopping [tshift] + + Double_t val[4]; + + assert(fParamNo.size() <= 4); + + // check if FUNCTIONS are used + for (UInt_t i=0; i 5.0) // nu/Delta > 5.0 + useKeren = true; + + if (!useKeren && !isOneVec) { + CalculateDynKTLF(par, 0); // 0 means Gauss + } + + // calculate polarization vector for the given parameters + up = -std::erf(sqrtTwoInv/rr[i]); + scale = up - low; + low = up; + + const Double_t dt=0.001; + for (UInt_t i=0; i<20000; i++) { + if (isOneVec) { + fDyn_GL_LFFuncValue[i] += scale; + } else if (useKeren && !isOneVec) {// see PRB50, 10039 (1994) + Double_t wL = TWO_PI * par[0]; + Double_t wL2 = wL*wL; + Double_t nu2 = par[2]*par[2]; + Double_t Gamma_t = 2.0*par[1]*par[1]/((wL2+nu2)*(wL2+nu2))* + ((wL2+nu2)*val[2]*i*dt + + (wL2-nu2)*(1.0 - TMath::Exp(-val[2]*i*dt)*TMath::Cos(wL*i*dt)) + - 2.0*val[2]*wL*TMath::Exp(-val[2]*i*dt)*TMath::Sin(wL*i*dt)); + fDyn_GL_LFFuncValue[i] += scale*TMath::Exp(-Gamma_t); + } else if (!useKeren && !isOneVec) { + fDyn_GL_LFFuncValue[i] += scale*GetDynKTLFValue(i*dt); + } + } + } + } + + + // get the proper value from the look-up table + Double_t result{1.0}; + if (tt>=0) + result=GetDyn_GL_KTLFValue(tt); + + return result; } //-------------------------------------------------------------------------- @@ -2619,22 +2732,22 @@ Double_t PTheory::FmuF(Double_t t, const PDoubleVector& paramValues, const PDoub assert(fParamNo.size() <= 2); if (t < 0.0) - return 1.0; + return 1.0; // check if FUNCTIONS are used for (UInt_t i=0; i(t/fDynLFdt); if (idx + 2 > fDynLFFuncValue.size()) return fDynLFFuncValue.back(); - // linearly interpolate between the two relvant function bins + // linearly interpolate between the two relevant function bins Double_t df = (fDynLFFuncValue[idx+1]-fDynLFFuncValue[idx])*(t/fDynLFdt-static_cast(idx)); return fDynLFFuncValue[idx]+df; } +//-------------------------------------------------------------------------- +/** + *

Gets value of the dynamic local Gauss / global Lorentzian Kubo-Toyabe LF function. + * + * return: function value + * + * \param t time in (usec) + */ +Double_t PTheory::GetDyn_GL_KTLFValue(const Double_t t) const +{ + if (t < 0.0) + return 1.0; + + const Double_t dt=0.001; // 1ns + UInt_t idx = static_cast(t/dt); + + if (idx + 2 > fDyn_GL_LFFuncValue.size()) + return fDyn_GL_LFFuncValue.back(); + + // linearly interpolate between the two relevant function bins + Double_t df = (fDyn_GL_LFFuncValue[idx+1]-fDyn_GL_LFFuncValue[idx])*(t/dt-static_cast(idx)); + + return fDyn_GL_LFFuncValue[idx]+df; +} + //-------------------------------------------------------------------------- /** *

theory function: MuMinusExpTF diff --git a/src/include/PTheory.h b/src/include/PTheory.h index ddbccf9c..d873c62d 100644 --- a/src/include/PTheory.h +++ b/src/include/PTheory.h @@ -310,6 +310,7 @@ class PTheory virtual Double_t GetLFIntegralValue(const Double_t t) const; virtual void CalculateDynKTLF(const Double_t *val, Int_t tag) const; virtual Double_t GetDynKTLFValue(const Double_t t) const; + virtual Double_t GetDyn_GL_KTLFValue(const Double_t t) const; // variables Bool_t fValid; ///< flag to tell if the theory is valid @@ -331,6 +332,7 @@ class PTheory mutable PDoubleVector fLFIntegral; ///< needed for LF. Keeps the non-analytic integral values mutable Double_t fDynLFdt; ///< needed for LF. Keeps the time step for the dynamic LF calculation, used in the integral equation approach mutable PDoubleVector fDynLFFuncValue; ///< needed for LF. Keeps the dynamic LF KT function values + mutable PDoubleVector fDyn_GL_LFFuncValue; ///< needed for LF. Keeps the dynamic LF local Gauss/global Lorentzian KT function values }; #endif // _PTHEORY_H_