Files
musrfit/src/include/PTheory.h

659 lines
34 KiB
C++
Raw Blame History

This file contains ambiguous Unicode characters
This file contains Unicode characters that might be confused with other characters. If you think that this is intentional, you can safely ignore this warning. Use the Escape button to reveal them.
/***************************************************************************
PTheory.h
Author: Andreas Suter
e-mail: andreas.suter@psi.ch
***************************************************************************/
/***************************************************************************
* Copyright (C) 2007-2025 by Andreas Suter *
* andreas.suter@psi.ch *
* *
* This program is free software; you can redistribute it and/or modify *
* it under the terms of the GNU General Public License as published by *
* the Free Software Foundation; either version 2 of the License, or *
* (at your option) any later version. *
* *
* This program is distributed in the hope that it will be useful, *
* but WITHOUT ANY WARRANTY; without even the implied warranty of *
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the *
* GNU General Public License for more details. *
* *
* You should have received a copy of the GNU General Public License *
* along with this program; if not, write to the *
* Free Software Foundation, Inc., *
* 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. *
***************************************************************************/
#ifndef _PTHEORY_H_
#define _PTHEORY_H_
#include <TSystem.h>
#include <TString.h>
#include "PMusr.h"
#include "PMsrHandler.h"
#include "PUserFcnBase.h"
//-------------------------------------------------------------
/**
* <p>Theory function type tags.
*
* <p>These constants identify the built-in theory functions available in
* the THEORY block of MSR files. Each function represents a specific physical
* model for muon spin relaxation, precession, or depolarization.
*
* <p>Theory functions can be combined using addition (+) and multiplication (*):
* - <b>Addition:</b> Independent relaxation channels (e.g., 1/3 fast + 2/3 slow)
* - <b>Multiplication:</b> Multiple relaxation mechanisms (e.g., precession * damping)
*
* <p><b>Categories:</b>
* - <b>Basic:</b> Constants, asymmetries, simple exponentials
* - <b>Static relaxation:</b> Gaussian, Lorentzian (Kubo-Toyabe)
* - <b>Dynamic relaxation:</b> Motional narrowing, spin fluctuations
* - <b>Precession:</b> Cosine, Bessel functions for oscillations
* - <b>Vortex lattice:</b> Internal field distributions in superconductors
* - <b>Special:</b> Spin glass, Abragam, mu-minus, polynomials, user functions
*/
/// Undefined or invalid theory function
#define THEORY_UNDEFINED -1
/// Constant value (baseline, background)
#define THEORY_CONST 0
/// Initial asymmetry (multiplicative factor)
#define THEORY_ASYMMETRY 1
/// Simple exponential relaxation: exp(-λt)
#define THEORY_SIMPLE_EXP 2
/// General exponential relaxation: exp(-(λt)^β)
#define THEORY_GENERAL_EXP 3
/// Simple Gaussian relaxation: exp(-σ²t²/2)
#define THEORY_SIMPLE_GAUSS 4
/// Static Gaussian Kubo-Toyabe (zero-field)
#define THEORY_STATIC_GAUSS_KT 5
/// Static Gaussian Kubo-Toyabe in longitudinal field
#define THEORY_STATIC_GAUSS_KT_LF 6
/// Dynamic Gaussian Kubo-Toyabe in longitudinal field
#define THEORY_DYNAMIC_GAUSS_KT_LF 7
/// Static Lorentzian Kubo-Toyabe (zero-field)
#define THEORY_STATIC_LORENTZ_KT 8
/// Static Lorentzian Kubo-Toyabe in longitudinal field
#define THEORY_STATIC_LORENTZ_KT_LF 9
/// Dynamic Lorentzian Kubo-Toyabe in longitudinal field
#define THEORY_DYNAMIC_LORENTZ_KT_LF 10
/// Fast dynamic Gauss-Lorentz Kubo-Toyabe (zero-field)
#define THEORY_DYNAMIC_GAULOR_FAST_KT_ZF 11
/// Fast dynamic Gauss-Lorentz Kubo-Toyabe in longitudinal field
#define THEORY_DYNAMIC_GAULOR_FAST_KT_LF 12
/// Dynamic Gauss-Lorentz Kubo-Toyabe in longitudinal field
#define THEORY_DYNAMIC_GAULOR_KT_LF 13
/// Combined Lorentzian-Gaussian Kubo-Toyabe
#define THEORY_COMBI_LGKT 14
/// Stretched Kubo-Toyabe relaxation
#define THEORY_STR_KT 15
/// Spin glass order parameter function
#define THEORY_SPIN_GLASS 16
/// Random anisotropic hyperfine coupling
#define THEORY_RANDOM_ANISOTROPIC_HYPERFINE 17
/// Abragam relaxation function (diffusion)
#define THEORY_ABRAGAM 18
/// Transverse field cosine precession
#define THEORY_TF_COS 19
/// Internal magnetic field distribution (superconductors)
#define THEORY_INTERNAL_FIELD 20
/// Internal field (Kornilov vortex lattice model)
#define THEORY_INTERNAL_FIELD_KORNILOV 21
/// Internal field (Larkin-Ovchinnikov model)
#define THEORY_INTERNAL_FIELD_LARKIN 22
/// Bessel function (modulated precession)
#define THEORY_BESSEL 23
/// Internal Bessel (field distribution with Bessel)
#define THEORY_INTERNAL_BESSEL 24
/// Skewed Gaussian relaxation (asymmetric rates)
#define THEORY_SKEWED_GAUSS 25
/// Static Nakajima zero-field function
#define THEORY_STATIC_ZF_NK 26
/// Static Nakajima transverse field function
#define THEORY_STATIC_TF_NK 27
/// Dynamic Nakajima zero-field function
#define THEORY_DYNAMIC_ZF_NK 28
/// Dynamic Nakajima transverse field function
#define THEORY_DYNAMIC_TF_NK 29
/// F-μ-F (μ-fluorine) oscillation
#define THEORY_F_MU_F 30
/// Negative muon (μ-) exponential TF decay
#define THEORY_MU_MINUS_EXP 31
/// Polynomial function (arbitrary order)
#define THEORY_POLYNOM 32
/// User-defined external function (shared library)
#define THEORY_USER_FCN 33
//-------------------------------------------------------------
/**
* <p>Number of parameters for each theory function.
*
* <p>These constants define how many parameters each theory function requires,
* <b>excluding</b> optional time shift. If a function includes time shift,
* add 1 to the parameter count.
*
* <p>Parameters typically include: rates (λ, σ), frequencies (ω, ν),
* phases (φ), fractions, exponents (β), hopping rates (ν_hop), etc.
*/
#define THEORY_PARAM_CONST 1 // const
#define THEORY_PARAM_ASYMMETRY 1 // asymmetry
#define THEORY_PARAM_SIMPLE_EXP 1 // damping (tshift)
#define THEORY_PARAM_GENERAL_EXP 2 // damping, exponents (tshift)
#define THEORY_PARAM_SIMPLE_GAUSS 1 // damping (tshift)
#define THEORY_PARAM_STATIC_GAUSS_KT 1 // damping (tshift)
#define THEORY_PARAM_STATIC_GAUSS_KT_LF 2 // frequency, damping (tshift)
#define THEORY_PARAM_DYNAMIC_GAUSS_KT_LF 3 // frequency, damping, hop-rate (tshift)
#define THEORY_PARAM_STATIC_LORENTZ_KT 1 // damping (tshift)
#define THEORY_PARAM_STATIC_LORENTZ_KT_LF 2 // frequency, damping (tshift)
#define THEORY_PARAM_DYNAMIC_LORENTZ_KT_LF 3 // frequency, damping, hop-rate (tshift)
#define THEORY_PARAM_DYNAMIC_GAULOR_FAST_KT_ZF 2 // damping, hop-rate (tshift)
#define THEORY_PARAM_DYNAMIC_GAULOR_FAST_KT_LF 3 // frequency, damping, hop-rate (tshift)
#define THEORY_PARAM_DYNAMIC_GAULOR_KT_LF 3 // frequency, damping, hop-rate (tshift)
#define THEORY_PARAM_COMBI_LGKT 2 // Lorentz rate, Gauss rate (tshift)
#define THEORY_PARAM_STR_KT 2 // rate, exponent (tshift)
#define THEORY_PARAM_SPIN_GLASS 3 // rate, hop-rate, order parameter (tshift)
#define THEORY_PARAM_RANDOM_ANISOTROPIC_HYPERFINE 2 // frequency, rate (tshift)
#define THEORY_PARAM_ABRAGAM 2 // rate, hop-rate (tshift)
#define THEORY_PARAM_TF_COS 2 // phase, frequency (tshift)
#define THEORY_PARAM_INTERNAL_FIELD 5 // fraction, phase, frequency, TF damping, damping (tshift)
#define THEORY_PARAM_INTERNAL_FIELD_KORNILOV 5 // fraction, frequency, TF damping, damping, beta (tshift)
#define THEORY_PARAM_INTERNAL_FIELD_LARKIN 4 // fraction, frequency, TF damping, damping (tshift)
#define THEORY_PARAM_BESSEL 2 // phase, frequency (tshift)
#define THEORY_PARAM_INTERNAL_BESSEL 5 // fraction, phase, frequency, TF damping, LF damping (tshift)
#define THEORY_PARAM_SKEWED_GAUSS 4 // phase, frequency, rate minus, rate plus (tshift)
#define THEORY_PARAM_STATIC_ZF_NK 2 // damping D0, R_b=DGbG/D0 (tshift)
#define THEORY_PARAM_STATIC_TF_NK 4 // phase, frequency, damping D0, R_b=DGbG/D0 (tshift)
#define THEORY_PARAM_DYNAMIC_ZF_NK 3 // damping D0, R_b=DGbG/D0, nu_c (tshift)
#define THEORY_PARAM_DYNAMIC_TF_NK 5 // phase, frequency, damping D0, R_b=DGbG/D0, nu_c (tshift)
#define THEORY_PARAM_F_MU_F 1 // frequency (tshift)
#define THEORY_PARAM_MU_MINUS_EXP 6 // N0, tau, A, damping, phase, frequency (tshift)
//-------------------------------------------------------------
/**
* <p>Maximum number of theory functions in database.
*
* <p>This is the total number of built-in theory functions available,
* including all relaxation, precession, and special functions.
*/
#define THEORY_MAX 34
//-------------------------------------------------------------
/**
* <p>Maximum number of parameters for any theory function.
*
* <p>Used to allocate arrays for longitudinal field calculations where
* parameter values from previous iterations must be cached.
*/
#define THEORY_MAX_PARAM 10
//-------------------------------------------------------------
/**
* <p>Conversion factor from degrees to radians.
*
* <p>Value: π/180 = 0.017453292519943295
* <p>Used for phase parameters which are specified in degrees in MSR files
* but converted to radians for calculations.
*/
#define DEG_TO_RAD 0.0174532925199432955
/**
* <p>Mathematical constant 2π.
*
* <p>Used extensively in frequency-to-angular-frequency conversions:
* ω = 2πν
*/
#define TWO_PI 6.28318530717958623
class PTheory;
//--------------------------------------------------------------------------------------
/**
* <p>Database entry for a theory function definition.
*
* <p>This structure stores metadata about each built-in theory function,
* including its identifier, parameter count, name, abbreviation, and
* help text. The database is used for:
* - Parsing THEORY block entries in MSR files
* - Validating parameter counts
* - Generating help text and documentation
* - Writing theory blocks with correct syntax
*/
typedef struct theo_data_base {
UInt_t fType; ///< Theory function type tag (THEORY_CONST, THEORY_SIMPLE_EXP, etc.)
UInt_t fNoOfParam; ///< Number of parameters (excluding optional time shift)
Bool_t fTable; ///< True if function requires pre-calculated lookup table (e.g., LF Kubo-Toyabe)
TString fName; ///< Full function name for MSR files (e.g., "simplExpo", "statGssKt")
TString fAbbrev; ///< Short abbreviation (e.g., "se", "stg")
TString fComment; ///< Parameter list shown as help text in MSR file
TString fCommentTimeShift; ///< Parameter list with time shift included
} PTheoDataBase;
//--------------------------------------------------------------------------------------
/**
* <p> Holds the functions available for the user.
*/
static PTheoDataBase fgTheoDataBase[THEORY_MAX] = {
{THEORY_CONST, THEORY_PARAM_CONST, false,
"const", "c", "", ""},
{THEORY_ASYMMETRY, THEORY_PARAM_ASYMMETRY, false,
"asymmetry", "a", "", ""},
{THEORY_SIMPLE_EXP, THEORY_PARAM_SIMPLE_EXP, false,
"simplExpo", "se", "(rate)", "(rate tshift)"},
{THEORY_GENERAL_EXP, THEORY_PARAM_GENERAL_EXP, false,
"generExpo", "ge", "(rate exponent)", "(rate exponent tshift)"},
{THEORY_SIMPLE_GAUSS, THEORY_PARAM_SIMPLE_GAUSS, false,
"simpleGss", "sg", "(rate)", "(rate tshift)"},
{THEORY_STATIC_GAUSS_KT, THEORY_PARAM_STATIC_GAUSS_KT, false,
"statGssKt", "stg", "(rate)", "(rate tshift)"},
{THEORY_STATIC_GAUSS_KT_LF, THEORY_PARAM_STATIC_GAUSS_KT_LF, true,
"statGssKTLF", "sgktlf", "(frequency damping)", "(frequency damping tshift)"},
{THEORY_DYNAMIC_GAUSS_KT_LF, THEORY_PARAM_DYNAMIC_GAUSS_KT_LF, true,
"dynGssKTLF", "dgktlf", "(frequency damping hopping-rate)", "(frequency damping hopping-rate tshift)"},
{THEORY_STATIC_LORENTZ_KT, THEORY_PARAM_STATIC_LORENTZ_KT, true,
"statExpKT", "sekt", "(rate)", "(rate tshift)"},
{THEORY_STATIC_LORENTZ_KT_LF, THEORY_PARAM_STATIC_LORENTZ_KT_LF, true,
"statExpKTLF", "sektlf", "(frequency damping)", "(frequency damping tshift)"},
{THEORY_DYNAMIC_LORENTZ_KT_LF, THEORY_PARAM_DYNAMIC_LORENTZ_KT_LF, true,
"dynExpKTLF", "dektlf", "(frequency damping hopping-rate)", "(frequency damping hopping-rate tshift)"},
{THEORY_DYNAMIC_GAULOR_FAST_KT_ZF, THEORY_PARAM_DYNAMIC_GAULOR_FAST_KT_ZF, true,
"dynGLKT_F_ZF", "dglktfzf", "(damping hopping-rate)", "(damping hopping-rate tshift)"},
{THEORY_DYNAMIC_GAULOR_FAST_KT_LF, THEORY_PARAM_DYNAMIC_GAULOR_FAST_KT_LF, true,
"dynGLKT_F_LF", "dglktflf", "(frequency damping hopping-rate)", "(frequency damping hopping-rate tshift)"},
{THEORY_DYNAMIC_GAULOR_KT_LF, THEORY_PARAM_DYNAMIC_GAULOR_KT_LF, true,
"dynGLKT_LF", "dglktlf", "(frequency damping hopping-rate)", "(frequency damping hopping-rate tshift)"},
{THEORY_COMBI_LGKT, THEORY_PARAM_COMBI_LGKT, false,
"combiLGKT", "lgkt", "(lorentzRate gaussRate)", "(lorentzRate gaussRate tshift)"},
{THEORY_STR_KT, THEORY_PARAM_STR_KT, false,
"strKT", "skt", "(rate beta)", "(rate beta tshift)"},
{THEORY_SPIN_GLASS, THEORY_PARAM_SPIN_GLASS, false,
"spinGlass", "spg", "(rate hopprate order)", "(rate hopprate order tshift)"},
{THEORY_RANDOM_ANISOTROPIC_HYPERFINE, THEORY_PARAM_RANDOM_ANISOTROPIC_HYPERFINE, false,
"rdAnisoHf", "rahf", "(frequency rate)", "(frequency rate tshift)"},
{THEORY_ABRAGAM, THEORY_PARAM_ABRAGAM, false,
"abragam", "ab", "(rate hopprate)", "(rate hopprate tshift)"},
{THEORY_TF_COS, THEORY_PARAM_TF_COS, false,
"TFieldCos", "tf", "(phase frequency)", "(phase frequency tshift)"},
{THEORY_INTERNAL_FIELD, THEORY_PARAM_INTERNAL_FIELD, false,
"internFld", "ifld", "(fraction phase frequency Trate Lrate)", "(fraction phase frequency Trate Lrate tshift)"},
{THEORY_INTERNAL_FIELD_KORNILOV, THEORY_PARAM_INTERNAL_FIELD_KORNILOV, false,
"internFldGK", "ifgk", "(fraction frequency sigma lambda beta)", "(fraction frequency sigma lambda beta tshift)"},
{THEORY_INTERNAL_FIELD_LARKIN, THEORY_PARAM_INTERNAL_FIELD_LARKIN, false,
"internFldLL", "ifll", "(fraction frequency sigma lambda beta)", "(fraction frequency sigma lambda beta tshift)"},
{THEORY_BESSEL, THEORY_PARAM_BESSEL, false,
"bessel", "b", "(phase frequency)", "(phase frequency tshift)"},
{THEORY_INTERNAL_BESSEL, THEORY_PARAM_INTERNAL_BESSEL, false,
"internBsl", "ib", "(fraction phase frequency Trate Lrate)", "(fraction phase frequency Trate Lrate tshift)"},
{THEORY_SKEWED_GAUSS, THEORY_PARAM_SKEWED_GAUSS, false,
"skewedGss", "skg", "(phase frequency rate_m rate_p)", "(phase frequency rate_m rate_p tshift)"},
{THEORY_STATIC_ZF_NK, THEORY_PARAM_STATIC_ZF_NK, false,
"staticNKZF", "snkzf", "(damping_D0 R_b)", "(damping_D0 R_b tshift)"},
{THEORY_STATIC_TF_NK, THEORY_PARAM_STATIC_TF_NK, false,
"staticNKTF", "snktf", "(phase frequency damping_D0 R_b)", "(phase frequency damping_D0 R_b tshift)"},
{THEORY_DYNAMIC_ZF_NK, THEORY_PARAM_DYNAMIC_ZF_NK, false,
"dynamicNKZF", "dnkzf", "(damping_D0 R_b nu_c)", "(damping_D0 R_b nu_c tshift)"},
{THEORY_DYNAMIC_TF_NK, THEORY_PARAM_DYNAMIC_TF_NK, false,
"dynamicNKTF", "dnktf", "(phase frequency damping_D0 R_b nu_c)", "(phase frequency damping_D0 R_b nu_c tshift)"},
{THEORY_F_MU_F, THEORY_PARAM_F_MU_F, false,
"F_mu_F", "fmuf", "(frequency)", "(frequency tshift)"},
{THEORY_MU_MINUS_EXP, THEORY_PARAM_MU_MINUS_EXP, false,
"muMinusExpTF", "mmsetf", "(N0 tau A lambda phase nu)", "(N0 tau A lambda phase nu tshift)"},
{THEORY_POLYNOM, 0, false,
"polynom", "p", "(tshift p0 p1 ... pn)", "(tshift p0 p1 ... pn)"},
{THEORY_USER_FCN, 0, false,
"userFcn", "u", "", ""}
};
//--------------------------------------------------------------------------------------
/**
* \brief Theory function evaluator and expression tree manager.
*
* PTheory is the core class responsible for parsing, validating, and evaluating
* theory functions specified in the THEORY block of MSR files. It implements
* a binary expression tree to handle complex combinations of theory functions.
*
* \section theory_overview Overview
*
* The theory describes the expected muon polarization as a function of time.
* Different physical phenomena (relaxation, precession, field distributions)
* are represented by different theory functions that can be combined.
*
* \section theory_tree Expression Tree Structure
*
* Theory expressions are parsed into a binary tree where:
* - Each node represents a theory function
* - Left child (fAdd) represents addition (+)
* - Right child (fMul) represents multiplication (*)
*
* Example MSR theory block:
* \verbatim
* THEORY
* a 1 # asymmetry
* tf 2 3 # TFieldCos
* se 4 # simpleExp
* +
* a 5
* tf 6 7
* \endverbatim
*
* Becomes: (par1 * cos(φ₂ + 2πν₃t) * exp(-λ₄t)) + (par5 * cos(φ₆ + 2πν₇t))
*
* \section theory_syntax Syntax Details
*
* <b>Function specification:</b>
* \code
* function_name param1 param2 ... paramN (optional comment)
* \endcode
*
* <b>Parameter types:</b>
* - Direct number: \c 1, \c 2, \c 3 → parameter index (1-based)
* - Map reference: \c map1, \c map2 → indirection via RUN block map
* - Function reference: \c fun1, \c fun2 → evaluated FUNCTIONS block entry
*
* <b>Operators:</b>
* - \c + on separate line: Addition of following terms
* - Consecutive lines without +: Implicit multiplication
*
* \section theory_functions Available Functions
*
* <b>Basic:</b>
* - \c const (c): Constant value
* - \c asymmetry (a): Initial asymmetry
* - \c simplExpo (se): exp(-λt)
* - \c generExpo (ge): exp(-(λt)^β)
* - \c simpleGss (sg): exp(-σ²t²/2)
*
* <b>Kubo-Toyabe (Gaussian):</b>
* - \c statGssKt (stg): Static ZF Gaussian KT
* - \c statGssKTLF (sgktlf): Static LF Gaussian KT
* - \c dynGssKTLF (dgktlf): Dynamic LF Gaussian KT
*
* <b>Kubo-Toyabe (Lorentzian):</b>
* - \c statExpKT (sekt): Static ZF Lorentzian KT
* - \c statExpKTLF (sektlf): Static LF Lorentzian KT
* - \c dynExpKTLF (dektlf): Dynamic LF Lorentzian KT
*
* <b>Precession:</b>
* - \c TFieldCos (tf): cos(φ + 2πνt)
* - \c bessel (b): J₀(2πνt + φ)
* - \c internFld (ifld): Internal field distribution
*
* <b>Special:</b>
* - \c spinGlass (spg): Spin glass relaxation
* - \c abragam (ab): Motional narrowing
* - \c userFcn (u): User-defined external function
*
* \section theory_lf Longitudinal Field Calculations
*
* LF Kubo-Toyabe functions require numerical integration which is cached
* for efficiency. The cache is invalidated when parameters change.
* Caching variables:
* - fPrevParam: Previous parameter values for change detection
* - fLFIntegral: Cached integral values
* - fDynLFFuncValue: Dynamic KT function cache
*
* \section theory_user User Functions
*
* External functions can be loaded from shared libraries:
* \code
* userFcn libMyFunctions.so MyFunctionClass param1 param2 ...
* \endcode
*
* User functions must inherit from PUserFcnBase and implement:
* - operator()(Double_t t, const std::vector<Double_t>& par)
*
* \see PUserFcnBase, PMsrHandler, fgTheoDataBase
*/
class PTheory
{
public:
/**
* \brief Constructor that parses the THEORY block and builds the expression tree.
*
* Parses the theory block from the MSR file, validates function names and
* parameter counts, resolves parameter references, and recursively builds
* the expression tree for operators (+ and *).
*
* <b>Parsing algorithm:</b>
* -# Get current line from theory block
* -# Remove comments (text after '(' or '#')
* -# Tokenize to extract function name and parameters
* -# Look up function in fgTheoDataBase
* -# Validate parameter count
* -# Resolve parameter references (direct, map, fun)
* -# If next line is not '+', recursively create fMul child
* -# If next line is '+', skip it and recursively create fAdd child
* -# For user functions: load shared library and instantiate class
*
* \param msrInfo Pointer to MSR file handler containing theory block
* \param runNo Run number (0-based) for parameter map resolution
* \param hasParent False for root theory, true for child nodes.
* Controls static counter reset for recursive parsing.
*
* \warning If parsing fails, fValid is set to false and error messages
* are output to stderr. Always check IsValid() after construction.
*/
PTheory(PMsrHandler *msrInfo, UInt_t runNo, const Bool_t hasParent = false);
/**
* \brief Destructor that recursively cleans up the expression tree.
*
* Releases all allocated resources:
* - Clears parameter and function value vectors
* - Clears LF integral caches
* - Recursively deletes child theory nodes (fAdd, fMul)
* - Deletes user function object if present
* - Clears global user function vector
*/
virtual ~PTheory();
/**
* \brief Checks if the entire theory expression tree is valid.
*
* Recursively validates all nodes in the tree. A theory is valid only
* if this node and all its children (fAdd and fMul) are valid.
*
* \return true if all nodes are valid, false if any node has errors
*
* \note Call this after construction to verify the theory was parsed
* successfully before attempting evaluation.
*/
virtual Bool_t IsValid();
/**
* \brief Evaluates the theory function at a given time point.
*
* Recursively evaluates the expression tree at time t using the provided
* parameter values. The evaluation follows the tree structure:
* - If both fMul and fAdd exist: this_func * fMul + fAdd
* - If only fMul exists: this_func * fMul
* - If only fAdd exists: this_func + fAdd
* - If neither exists: this_func
*
* \param t Time in microseconds (μs) for μSR fits, or x-value for non-μSR
* \param paramValues Vector of current fit parameter values (FITPARAMETER block)
* \param funcValues Vector of evaluated function values (FUNCTIONS block)
*
* \return Evaluated theory value (polarization or asymmetry) at time t
*
* \note For thread-safety, LF calculations cache results which may need
* recalculation if parameters change between calls.
*/
virtual Double_t Func(Double_t t, const PDoubleVector& paramValues, const PDoubleVector& funcValues) const;
private:
/** \brief Recursively deletes child theory nodes (fAdd and fMul). */
virtual void CleanUp(PTheory *theo);
/** \brief Searches fgTheoDataBase for a function by name or abbreviation.
* \param name Function name (e.g., "simplExpo") or abbreviation (e.g., "se")
* \return Index in fgTheoDataBase, or THEORY_UNDEFINED if not found */
virtual Int_t SearchDataBase(TString name);
/** \brief Returns the index of user functions up to the given line.
* \param lineNo Current line number in theory block
* \return Count of userFcn entries before this line */
virtual Int_t GetUserFcnIdx(UInt_t lineNo) const;
/** \brief Reformats the theory block for clean MSR file output. */
virtual void MakeCleanAndTidyTheoryBlock(PMsrLines* fullTheoryBlock);
/** \brief Formats a polynomial theory line with proper spacing. */
virtual void MakeCleanAndTidyPolynom(UInt_t i, PMsrLines* fullTheoryBlock);
/** \brief Formats a user function theory line with proper spacing. */
virtual void MakeCleanAndTidyUserFcn(UInt_t i, PMsrLines* fullTheoryBlock);
// -------------------- Theory Function Implementations --------------------
// Each function evaluates its specific physical model at time t.
// Parameters are resolved from fParamNo using paramValues and funcValues.
/** \brief Returns constant value. Formula: c */
virtual Double_t Constant(const PDoubleVector& paramValues, const PDoubleVector& funcValues) const;
/** \brief Returns asymmetry value. Formula: A */
virtual Double_t Asymmetry(const PDoubleVector& paramValues, const PDoubleVector& funcValues) const;
/** \brief Simple exponential relaxation. Formula: exp(-λt) */
virtual Double_t SimpleExp(Double_t t, const PDoubleVector& paramValues, const PDoubleVector& funcValues) const;
/** \brief General (stretched) exponential. Formula: exp(-(λt)^β) */
virtual Double_t GeneralExp(Double_t t, const PDoubleVector& paramValues, const PDoubleVector& funcValues) const;
/** \brief Simple Gaussian relaxation. Formula: exp(-σ²t²/2) */
virtual Double_t SimpleGauss(Double_t t, const PDoubleVector& paramValues, const PDoubleVector& funcValues) const;
/** \brief Static Gaussian Kubo-Toyabe (ZF). Formula: 1/3 + 2/3(1-σ²t²)exp(-σ²t²/2) */
virtual Double_t StaticGaussKT(Double_t t, const PDoubleVector& paramValues, const PDoubleVector& funcValues) const;
/** \brief Static Gaussian Kubo-Toyabe (LF). Requires numerical integration. */
virtual Double_t StaticGaussKTLF(Double_t t, const PDoubleVector& paramValues, const PDoubleVector& funcValues) const;
/** \brief Dynamic Gaussian Kubo-Toyabe (LF). Strong collision model. */
virtual Double_t DynamicGaussKTLF(Double_t t, const PDoubleVector& paramValues, const PDoubleVector& funcValues) const;
/** \brief Static Lorentzian Kubo-Toyabe (ZF). Formula: 1/3 + 2/3(1-at)exp(-at) */
virtual Double_t StaticLorentzKT(Double_t t, const PDoubleVector& paramValues, const PDoubleVector& funcValues) const;
/** \brief Static Lorentzian Kubo-Toyabe (LF). Requires numerical integration. */
virtual Double_t StaticLorentzKTLF(Double_t t, const PDoubleVector& paramValues, const PDoubleVector& funcValues) const;
/** \brief Dynamic Lorentzian Kubo-Toyabe (LF). Strong collision model. */
virtual Double_t DynamicLorentzKTLF(Double_t t, const PDoubleVector& paramValues, const PDoubleVector& funcValues) const;
/** \brief Fast dynamic Gaussian-Lorentzian KT (ZF). Approximate fast calculation. */
virtual Double_t DynamicGauLorKTZFFast(Double_t t, const PDoubleVector& paramValues, const PDoubleVector& funcValues) const;
/** \brief Fast dynamic Gaussian-Lorentzian KT (LF). Approximate fast calculation. */
virtual Double_t DynamicGauLorKTLFFast(Double_t t, const PDoubleVector& paramValues, const PDoubleVector& funcValues) const;
/** \brief Dynamic Gaussian-Lorentzian KT (LF). Full numerical calculation. */
virtual Double_t DynamicGauLorKTLF(Double_t t, const PDoubleVector& paramValues, const PDoubleVector& funcValues) const;
/** \brief Combined Lorentzian-Gaussian KT. Product of both relaxation types. */
virtual Double_t CombiLGKT(Double_t t, const PDoubleVector& paramValues, const PDoubleVector& funcValues) const;
/** \brief Stretched Kubo-Toyabe. Formula: exp(-(σt)^β) with KT-like recovery. */
virtual Double_t StrKT(Double_t t, const PDoubleVector& paramValues, const PDoubleVector& funcValues) const;
/** \brief Spin glass relaxation function. Edwards-Anderson order parameter. */
virtual Double_t SpinGlass(Double_t t, const PDoubleVector& paramValues, const PDoubleVector& funcValues) const;
/** \brief Random anisotropic hyperfine coupling. Powder average of anisotropic coupling. */
virtual Double_t RandomAnisotropicHyperfine(Double_t t, const PDoubleVector& paramValues, const PDoubleVector& funcValues) const;
/** \brief Abragam relaxation. Motional narrowing formula. */
virtual Double_t Abragam(Double_t t, const PDoubleVector& paramValues, const PDoubleVector& funcValues) const;
/** \brief Transverse field cosine. Formula: cos(φ + 2πνt) */
virtual Double_t TFCos(Double_t t, const PDoubleVector& paramValues, const PDoubleVector& funcValues) const;
/** \brief Internal field distribution. Gaussian field distribution model. */
virtual Double_t InternalField(Double_t t, const PDoubleVector& paramValues, const PDoubleVector& funcValues) const;
/** \brief Internal field (Kornilov model). Vortex lattice field distribution. */
virtual Double_t InternalFieldGK(Double_t t, const PDoubleVector& paramValues, const PDoubleVector& funcValues) const;
/** \brief Internal field (Larkin-Ovchinnikov model). Vortex lattice field distribution. */
virtual Double_t InternalFieldLL(Double_t t, const PDoubleVector& paramValues, const PDoubleVector& funcValues) const;
/** \brief Bessel function precession. Formula: J₀(2πνt + φ) */
virtual Double_t Bessel(Double_t t, const PDoubleVector& paramValues, const PDoubleVector& funcValues) const;
/** \brief Internal Bessel field distribution. Combines Bessel with relaxation. */
virtual Double_t InternalBessel(Double_t t, const PDoubleVector& paramValues, const PDoubleVector& funcValues) const;
/** \brief Skewed Gaussian. Asymmetric relaxation rates before/after zero crossing. */
virtual Double_t SkewedGauss(Double_t t, const PDoubleVector& paramValues, const PDoubleVector& funcValues) const;
/** \brief Static Nakajima-Keren (ZF). Combined nuclear and electronic relaxation. */
virtual Double_t StaticNKZF(Double_t t, const PDoubleVector& paramValues, const PDoubleVector& funcValues) const;
/** \brief Static Nakajima-Keren (TF). Combined nuclear and electronic relaxation with precession. */
virtual Double_t StaticNKTF(Double_t t, const PDoubleVector& paramValues, const PDoubleVector& funcValues) const;
/** \brief Dynamic Nakajima-Keren (ZF). With spin fluctuations. */
virtual Double_t DynamicNKZF(Double_t t, const PDoubleVector& paramValues, const PDoubleVector& funcValues) const;
/** \brief Dynamic Nakajima-Keren (TF). With spin fluctuations and precession. */
virtual Double_t DynamicNKTF(Double_t t, const PDoubleVector& paramValues, const PDoubleVector& funcValues) const;
/** \brief F-μ-F oscillation. Muon bound between two fluorine atoms. */
virtual Double_t FmuF(Double_t t, const PDoubleVector& paramValues, const PDoubleVector& funcValues) const;
/** \brief μ⁻ exponential TF. Negative muon in transverse field. */
virtual Double_t MuMinusExpTF(Double_t t, const PDoubleVector& paramValues, const PDoubleVector& funcValues) const;
/** \brief Polynomial function. Formula: Σᵢ pᵢtⁱ */
virtual Double_t Polynom(Double_t t, const PDoubleVector& paramValues, const PDoubleVector& funcValues) const;
/** \brief User-defined function. Calls external shared library function. */
virtual Double_t UserFcn(Double_t t, const PDoubleVector& paramValues, const PDoubleVector& funcValues) const;
// -------------------- LF Calculation Helpers --------------------
/** \brief Calculates and caches Gaussian LF integral for static KT. */
virtual void CalculateGaussLFIntegral(const Double_t *val) const;
/** \brief Calculates and caches Lorentzian LF integral for static KT. */
virtual void CalculateLorentzLFIntegral(const Double_t *val) const;
/** \brief Retrieves cached LF integral value at time t using interpolation. */
virtual Double_t GetLFIntegralValue(const Double_t t) const;
/** \brief Calculates dynamic KT in LF using integral equation approach. */
virtual void CalculateDynKTLF(const Double_t *val, Int_t tag) const;
/** \brief Retrieves cached dynamic KT LF value at time t. */
virtual Double_t GetDynKTLFValue(const Double_t t) const;
/** \brief Retrieves cached dynamic Gauss-Lorentz KT LF value at time t. */
virtual Double_t GetDyn_GL_KTLFValue(const Double_t t) const;
// -------------------- Member Variables --------------------
Bool_t fValid; ///< True if this theory node and its parse state are valid
UInt_t fType; ///< Theory function type (THEORY_CONST, THEORY_SIMPLE_EXP, etc.)
std::vector<UInt_t> fParamNo; ///< Resolved parameter indices (0-based). Values >= MSR_PARAM_FUN_OFFSET are function references.
UInt_t fNoOfParam; ///< Expected number of parameters for this function type
PTheory *fAdd; ///< Pointer to addition child node (left branch of tree)
PTheory *fMul; ///< Pointer to multiplication child node (right branch of tree)
// User function members
Int_t fUserFcnIdx; ///< Index of this user function among all userFcn entries (for global state)
TString fUserFcnClassName; ///< ROOT class name for user function (e.g., "TMyFunction")
TString fUserFcnSharedLibName; ///< Shared library path (e.g., "libMyFunctions.so")
PUserFcnBase *fUserFcn; ///< Pointer to instantiated user function object
mutable PDoubleVector fUserParam; ///< Resolved parameter values for user function calls
PMsrHandler *fMsrInfo; ///< Pointer to MSR file handler (not owned)
// LF calculation caching (mutable for const Func() calls)
mutable Double_t fSamplingTime; ///< Time step for LF integral calculation (default 1 ns = 0.001 μs)
mutable Double_t fPrevParam[THEORY_MAX_PARAM]; ///< Previous parameter values for cache invalidation check
mutable PDoubleVector fLFIntegral; ///< Cached static LF KT integral values
mutable Double_t fDynLFdt; ///< Time step for dynamic LF integral equation
mutable PDoubleVector fDynLFFuncValue; ///< Cached dynamic Gaussian/Lorentzian LF KT values
mutable PDoubleVector fDyn_GL_LFFuncValue; ///< Cached dynamic Gauss-Lorentz LF KT values
};
#endif // _PTHEORY_H_