244 lines
7.6 KiB
C++
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
|
|
}
|