2013-12-16 08:26:42 +00:00

244 lines
7.6 KiB
C++

/***************************************************************************
PPhotoMeissner.cpp
Author: Andreas Suter
e-mail: andreas.suter@psi.ch
$Id$
***************************************************************************/
/***************************************************************************
* Copyright (C) 2013 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. *
***************************************************************************/
#include <cmath>
#include <cassert>
#include <iostream>
using namespace std;
#include <gsl/gsl_sf_bessel.h>
#include <TSAXParser.h>
#include "PMusr.h"
#include "../include/PPhotoMeissner.h"
ClassImp(PPhotoMeissner) // for ROOT dictionary
//--------------------------------------------------------------------------
// Constructor
//--------------------------------------------------------------------------
/**
* <p>
*/
PPhotoMeissner::PPhotoMeissner()
{
// init
fStartupHandler = 0;
fValid = true;
// read XML startup file
char startup_path_name[128];
TSAXParser *saxParser = new TSAXParser();
fStartupHandler = new PStartupHandler_PM();
strcpy(startup_path_name, fStartupHandler->GetStartupFilePath().Data());
saxParser->ConnectToHandler("PStartupHandler_PM", fStartupHandler);
//Int_t status = saxParser->ParseFile(startup_path_name);
// parsing the file as above seems to lead to problems in certain environments;
// use the parseXmlFile function instead (see PUserFcnBase.cpp for the definition)
Int_t status = parseXmlFile(saxParser, startup_path_name);
// check for parse errors
if (status) { // error
cout << endl << ">> PPhotoMeissner::PPhotoMeissner: **WARNING** Reading/parsing photoMeissner_startup.xml failed.";
cout << endl;
fValid = false;
}
// clean up
if (saxParser) {
delete saxParser;
saxParser = 0;
}
// check if everything went fine with the startup handler
if (!fStartupHandler->IsValid()) {
cout << endl << ">> PPhotoMeissner::PPhotoMeissner **PANIC ERROR**";
cout << endl << ">> startup handler too unhappy. Will terminate unfriendly, sorry.";
cout << endl;
fValid = false;
}
}
//--------------------------------------------------------------------------
// Destructor
//--------------------------------------------------------------------------
/**
*
*/
PPhotoMeissner::~PPhotoMeissner()
{
if (fStartupHandler)
delete fStartupHandler;
}
//--------------------------------------------------------------------------
// operator()
//--------------------------------------------------------------------------
/**
* <p>
*
* \param t
* \param par
*/
Double_t PPhotoMeissner::operator()(Double_t t, const vector<Double_t> &par) const
{
// expected parameters: (0) implantation energy (kV), (1) dead layer (nm), (2) Bext (G), (3) lambdaLondon (nm),
// (4) lambdaPhoto (nm), (5) z0 (nm), (6) detector phase (°), [(7) layer thickness]
assert((par.size() == 7) || (par.size() == 8));
if (t < 0.0)
return 1.0;
Double_t result = 0.0;
Double_t dz = 1.0; // go in 1A steps
Double_t zz = 0.0;
Double_t nn = 0.0;
Double_t sum = 0.0;
Double_t BB = 0.0;
Double_t gamma = fTwoPi*GAMMA_BAR_MUON;
int done = 0;
if (par.size() == 7) { // semi-infinite sample
do {
nn = fStartupHandler->GetRgeValue(par[0], zz);
BB = FieldHalfSpace(zz, par);
result += nn*cos(gamma*BB*t+fDegToRad*par[6]);
zz += dz;
sum += nn;
if (nn == 0.0)
done++;
} while (done < 5);
} else { // film
do {
nn = fStartupHandler->GetRgeValue(par[0], zz);
BB = FieldFilm(zz, par);
result += nn*cos(gamma*BB*t+fDegToRad*par[6]);
zz += dz;
sum += nn;
if (nn == 0.0)
done++;
} while (done < 5);
}
if (sum == 0.0) {
cerr << endl << ">> PPhotoMeissner::operator(): **PANIC ERROR** sum of RGE values == 0!" << endl;
assert(0);
}
return result/sum;
}
//--------------------------------------------------------------------------
// InuMinus() : private
//--------------------------------------------------------------------------
/**
* <p>
*
* \param nu
* \param x
*/
Double_t PPhotoMeissner::InuMinus(const Double_t nu, const Double_t x) const
{
return gsl_sf_bessel_Inu(nu,x) + M_2_PI * sin(nu*M_PI) * gsl_sf_bessel_Knu(nu,x);
}
//--------------------------------------------------------------------------
// FieldFilm() : private
//--------------------------------------------------------------------------
/**
* <p>
*
* \param par
*/
Double_t PPhotoMeissner::FieldFilm(const Double_t z, const vector<Double_t> &par) const
{
// prevent dividing by zero
double lamL = par[3];
double lamP = par[4];
if (lamL < 1.0e-3) lamL = 1.0e-3;
if (lamP < 1.0e-3) lamP = 1.0e-3;
double b = 0;
double nuPlus = 2.0*par[5]/lamL; // 2*z0/lamL
double nuPhoto = 2.0*par[5]/lamP; // 2*z0/lamP
double beta = exp(-(par[7]/2.0-par[1])/par[5]); // par[7]=layer thickness, par[1]=deadLayer, par[5]=z0
double NN = InuMinus(nuPlus, nuPhoto*beta)*gsl_sf_bessel_Inu(nuPlus, nuPhoto) -
InuMinus(nuPlus, nuPhoto)*gsl_sf_bessel_Inu(nuPlus, nuPhoto*beta);
if (fabs(NN) < 1.0e-2) // far from being good, hence get out of here
return 5.0*par[2];
if ((z < par[1]) || (z > par[7]-par[1])) {
b = 1.0;
} else {
b = (InuMinus(nuPlus, nuPhoto*exp(-(z-par[1])/(2.0*par[5])))*(gsl_sf_bessel_Inu(nuPlus, nuPhoto)-gsl_sf_bessel_Inu(nuPlus, nuPhoto*beta))-
gsl_sf_bessel_Inu(nuPlus, nuPhoto*exp(-(z-par[1])/(2.0*par[5])))*(InuMinus(nuPlus, nuPhoto)-InuMinus(nuPlus, nuPhoto*beta)))/NN;
}
return par[2]*b; // Bext*b
}
//--------------------------------------------------------------------------
// FieldHalfSpace() : private
//--------------------------------------------------------------------------
/**
* <p>
*
* \param par
*/
Double_t PPhotoMeissner::FieldHalfSpace(const Double_t z, const vector<Double_t> &par) const
{
// prevent dividing by zero
double lamL = par[3];
double lamP = par[4];
if (lamL < 1.0e-3) lamL = 1.0e-3;
if (lamP < 1.0e-3) lamP = 1.0e-3;
double nuPlus = 2.0*par[5]/lamL; // 2*z0/lamL
double nuPhoto = 2.0*par[5]/lamP; // 2*z0/lamP
double b=0.0, b1=0.0;
if (z < par[1]) { // z < deadLayer
b = 1.0;
} else {
b1 = gsl_sf_bessel_Inu(nuPlus, nuPhoto);
assert(b1>0.0);
b = gsl_sf_bessel_Inu(nuPlus, nuPhoto * sqrt(exp(-(z-par[1])/par[5])))/b1;
}
return par[2]*b; // Bext*b
}