swh:1:snp:f30673f02b42ace27f53f6913584bdb4995c7964
Tip revision: 3649eaadb14351fe03e1e61611fdd286311637fd authored by Rong WANG on 31 July 2018, 09:34:03 UTC
add a CMakeLists.txt
add a CMakeLists.txt
Tip revision: 3649eaa
nIMParton.cpp
#include<iostream>
#include<fstream>
#include<string>
#include<vector>
extern "C"{
#include<math.h>
}
#include"nIMParton.h"
using namespace std;
//a method used to choose a data set
void nIMParton::setDataSet(int dataset)
{
if(dataset==1)
{
gridD = gridDA;
gridD_largex = gridDA_largex;
gridA = gridAA;
gridA_largex = gridAA_largex;
cout<<" Using data set A."<<endl;
}
else if(dataset==2)
{
gridD = gridDB;
gridD_largex = gridDB_largex;
gridA = gridAB;
gridA_largex = gridAB_largex;
cout<<" Using data set B."<<endl;
}
else
{
cout<<"!!->Error: Unknown data set."<<endl;
cout<<"!!->Data set should be 1 or 2, for set A and B respectviely."<<endl;
}
}
//get ratio of bound proton parton distribution in the nucleus to free proton parton distribution
double nIMParton::getRToN_p(int Iparton, double x, double Q2) const
{
return getPDF(Iparton, x, Q2)/getPDFN(Iparton, x, Q2);
}
//get ratio of bound proton parton distribution in the nucleus to bound proton parton distribution in the deuteron
double nIMParton::getRToD_p(int Iparton, double x, double Q2) const
{
return getPDF(Iparton, x, Q2)/getPDFD(Iparton, x, Q2);
}
//get ratio of bound neutron parton distribution in the nucleus to free neutron parton distribution
double nIMParton::getRToN_n(int Iparton, double x, double Q2) const
{
if(Iparton==1) return getPDF(2, x, Q2)/getPDFN(2, x, Q2);
else if(Iparton==2) return getPDF(1, x, Q2)/getPDFN(1, x, Q2);
else return getPDF(Iparton, x, Q2)/getPDFN(Iparton, x, Q2);
}
//get ratio of bound neutron parton distribution in the nucleus to bound neutron parton distribution in the deuteron
double nIMParton::getRToD_n(int Iparton, double x, double Q2) const
{
if(Iparton==1) return getPDF(2, x, Q2)/getPDFD(2, x, Q2);
else if(Iparton==2) return getPDF(1, x, Q2)/getPDFD(1, x, Q2);
else return getPDF(Iparton, x, Q2)/getPDFD(Iparton, x, Q2);
}
//the constructor and initialization
nIMParton::nIMParton(unsigned int Z_temp, unsigned int A_temp)
:Z(Z_temp),A(A_temp) //Z and A are parameters for a nuclei
{
cout<<" nIMParton version - v1.1"<<endl;
char filename[50];
ifstream datain;
double x, Q2;
unsigned int i, j;
xMax=61;
Q2Max=32;
flavorMax=7;
lnxstep=log(10)/((xMax-1)/6);
lnQ2step=log(2.0);
//vectors to store the grid tables
vector<double>* vectorAA_largex = new vector<double>(7840);
vector<double>* vectorAB_largex = new vector<double>(7840);
vector<double>* vectorDA_largex = new vector<double>(7840);
vector<double>* vectorDB_largex = new vector<double>(7840);
vector<double>* vectorN_largex = new vector<double>(7840);
vector<double>* vectorAA = new vector<double>(13664);
vector<double>* vectorAB = new vector<double>(13664);
vector<double>* vectorDA = new vector<double>(13664);
vector<double>* vectorDB = new vector<double>(13664);
vector<double>* vectorN = new vector<double>(13664);
vectorAA_largex->resize(7849);
vectorAB_largex->resize(7849);
vectorDA_largex->resize(7849);
vectorDB_largex->resize(7849);
vectorN_largex->resize(7849);
vectorAA->resize(13669);
vectorAB->resize(13669);
vectorDA->resize(13669);
vectorDB->resize(13669);
vectorN->resize(13669);
gridAA = vectorAA->data();
gridAB = vectorAB->data();
gridDA = vectorDA->data();
gridDB = vectorDB->data();
gridN = vectorN->data();
gridAA_largex = vectorAA_largex->data();
gridAB_largex = vectorAB_largex->data();
gridDA_largex = vectorDA_largex->data();
gridDB_largex = vectorDB_largex->data();
gridN_largex = vectorN_largex->data();
//read grid data for interpolation
//reading data set A
sprintf(filename,"grid_data/gridn_%d_%d_SetA.dat",Z,A);
cout<<" Loading "<<filename<<endl;
datain.open(filename);
if(!datain.good())cout<<"!!->Error: Error while opening "<<filename<<"!\n!!->grid data file not exist?"<<endl;
else
for(i=0;i<Q2Max;i++)
{
for(j=0;j<xMax;j++)
{
datain>>Q2>>x>>(*(gridAA+(xMax*i+j)*7))>>(*(gridAA+(xMax*i+j)*7+1))>>(*(gridAA+(xMax*i+j)*7+2))>>(*(gridAA+(xMax*i+j)*7+3))>>(*(gridAA+(xMax*i+j)*7+4))>>(*(gridAA+(xMax*i+j)*7+5))>>(*(gridAA+(xMax*i+j)*7+6));
}
}
datain.close();
sprintf(filename,"grid_data/gridn_%d_%d_SetA.dat",1,2);
cout<<" Loading "<<filename<<endl;
datain.open(filename);
if(!datain.good())cout<<"!!->Error: Error while opening "<<filename<<"!\n!!->grid data file not exist?"<<endl;
else
for(i=0;i<Q2Max;i++)
{
for(j=0;j<xMax;j++)
{
datain>>Q2>>x>>(*(gridDA+(xMax*i+j)*7))>>(*(gridDA+(xMax*i+j)*7+1))>>(*(gridDA+(xMax*i+j)*7+2))>>(*(gridDA+(xMax*i+j)*7+3))>>(*(gridDA+(xMax*i+j)*7+4))>>(*(gridDA+(xMax*i+j)*7+5))>>(*(gridDA+(xMax*i+j)*7+6));
}
}
datain.close();
sprintf(filename,"grid_data/gridn_%d_%d_largex_SetA.dat",Z,A); //nuclear data at large x
cout<<" Loading "<<filename<<endl;
datain.open(filename);
if(!datain.good())cout<<"!!->Error: Error while opening "<<filename<<"!\n!!->grid data file not exist?"<<endl;
else
for(i=0;i<Q2Max;i++)
{
for(j=0;j<35;j++)
{
datain>>Q2>>x>>(*(gridAA_largex+(xMax*i+j)*7))>>(*(gridAA_largex+(xMax*i+j)*7+1))>>(*(gridAA_largex+(xMax*i+j)*7+2))>>(*(gridAA_largex+(xMax*i+j)*7+3))>>(*(gridAA_largex+(xMax*i+j)*7+4))>>(*(gridAA_largex+(xMax*i+j)*7+5))>>(*(gridAA_largex+(xMax*i+j)*7+6));
}
}
datain.close();
sprintf(filename,"grid_data/gridn_%d_%d_largex_SetA.dat",1,2); //deteron data at large x
cout<<" Loading "<<filename<<endl;
datain.open(filename);
if(!datain.good())cout<<"!!->Error: Error while opening "<<filename<<"!\n!!->grid data file not exist?"<<endl;
else
for(i=0;i<Q2Max;i++)
{
for(j=0;j<35;j++)
{
datain>>Q2>>x>>(*(gridDA_largex+(xMax*i+j)*7))>>(*(gridDA_largex+(xMax*i+j)*7+1))>>(*(gridDA_largex+(xMax*i+j)*7+2))>>(*(gridDA_largex+(xMax*i+j)*7+3))>>(*(gridDA_largex+(xMax*i+j)*7+4))>>(*(gridDA_largex+(xMax*i+j)*7+5))>>(*(gridDA_largex+(xMax*i+j)*7+6));
}
}
datain.close();
//reading data set B
sprintf(filename,"grid_data/gridn_%d_%d_SetB.dat",Z,A);
cout<<" Loading "<<filename<<endl;
datain.open(filename);
if(!datain.good())cout<<"!!->Error: Error while opening "<<filename<<"!\n!!->grid data file not exist?"<<endl;
else
for(i=0;i<Q2Max;i++)
{
for(j=0;j<xMax;j++)
{
datain>>Q2>>x>>(*(gridAB+(xMax*i+j)*7+0))>>(*(gridAB+(xMax*i+j)*7+1))>>(*(gridAB+(xMax*i+j)*7+2))>>(*(gridAB+(xMax*i+j)*7+3))>>(*(gridAB+(xMax*i+j)*7+4))>>(*(gridAB+(xMax*i+j)*7+5))>>(*(gridAB+(xMax*i+j)*7+6));
}
}
datain.close();
sprintf(filename,"grid_data/gridn_%d_%d_SetB.dat",1,2);
cout<<" Loading "<<filename<<endl;
datain.open(filename);
if(!datain.good())cout<<"!!->Error: Error while opening "<<filename<<"!\n!!->grid data file not exist?"<<endl;
else
for(i=0;i<Q2Max;i++)
{
for(j=0;j<xMax;j++)
{
datain>>Q2>>x>>(*(gridDB+(xMax*i+j)*7+0))>>(*(gridDB+(xMax*i+j)*7+1))>>(*(gridDB+(xMax*i+j)*7+2))>>(*(gridDB+(xMax*i+j)*7+3))>>(*(gridDB+(xMax*i+j)*7+4))>>(*(gridDB+(xMax*i+j)*7+5))>>(*(gridDB+(xMax*i+j)*7+6));
}
}
datain.close();
sprintf(filename,"grid_data/gridn_%d_%d_largex_SetB.dat",Z,A); //nuclear data at large x
cout<<" Loading "<<filename<<endl;
datain.open(filename);
if(!datain.good())cout<<"!!->Error: Error while opening "<<filename<<"!\n!!->grid data file not exist?"<<endl;
else
for(i=0;i<Q2Max;i++)
{
for(j=0;j<35;j++)
{
datain>>Q2>>x>>(*(gridAB_largex+(xMax*i+j)*7))>>(*(gridAB_largex+(xMax*i+j)*7+1))>>(*(gridAB_largex+(xMax*i+j)*7+2))>>(*(gridAB_largex+(xMax*i+j)*7+3))>>(*(gridAB_largex+(xMax*i+j)*7+4))>>(*(gridAB_largex+(xMax*i+j)*7+5))>>(*(gridAB_largex+(xMax*i+j)*7+6));
}
}
datain.close();
sprintf(filename,"grid_data/gridn_%d_%d_largex_SetB.dat",1,2); //deteron data at large x
cout<<" Loading "<<filename<<endl;
datain.open(filename);
if(!datain.good())cout<<"!!->Error: Error while opening "<<filename<<"!\n!!->grid data file not exist?"<<endl;
else
for(i=0;i<Q2Max;i++)
{
for(j=0;j<35;j++)
{
datain>>Q2>>x>>(*(gridDB_largex+(xMax*i+j)*7))>>(*(gridDB_largex+(xMax*i+j)*7+1))>>(*(gridDB_largex+(xMax*i+j)*7+2))>>(*(gridDB_largex+(xMax*i+j)*7+3))>>(*(gridDB_largex+(xMax*i+j)*7+4))>>(*(gridDB_largex+(xMax*i+j)*7+5))>>(*(gridDB_largex+(xMax*i+j)*7+6));
}
}
datain.close();
sprintf(filename,"grid_data/gridn_%d_%d.dat",1,1);
cout<<" Loading "<<filename<<endl;
datain.open(filename);
if(!datain.good())cout<<"!!->Error: Error while opening "<<filename<<"!\n!!->grid data file not exist?"<<endl;
else
for(i=0;i<Q2Max;i++)
{
for(j=0;j<xMax;j++)
{
datain>>Q2>>x>>(*(gridN+(xMax*i+j)*7+0))>>(*(gridN+(xMax*i+j)*7+1))>>(*(gridN+(xMax*i+j)*7+2))>>(*(gridN+(xMax*i+j)*7+3))>>(*(gridN+(xMax*i+j)*7+4))>>(*(gridN+(xMax*i+j)*7+5))>>(*(gridN+(xMax*i+j)*7+6));
}
}
datain.close();
sprintf(filename,"grid_data/gridn_%d_%d_largex.dat",1,1);
cout<<" Loading "<<filename<<endl;
datain.open(filename);
if(!datain.good())cout<<"!!->Error: Error while opening "<<filename<<"!\n!!->grid data file not exist?"<<endl;
else
for(i=0;i<Q2Max;i++)
{
for(j=0;j<35;j++)
{
datain>>Q2>>x>>(*(gridN_largex+(xMax*i+j)*7+0))>>(*(gridN_largex+(xMax*i+j)*7+1))>>(*(gridN_largex+(xMax*i+j)*7+2))>>(*(gridN_largex+(xMax*i+j)*7+3))>>(*(gridN_largex+(xMax*i+j)*7+4))>>(*(gridN_largex+(xMax*i+j)*7+5))>>(*(gridN_largex+(xMax*i+j)*7+6));
}
}
datain.close();
//the default is data set B
gridD = gridDB;
gridD_largex = gridDB_largex;
gridA = gridAB;
gridA_largex = gridAB_largex;
}
//the deconstructor
nIMParton::~nIMParton(void){}
//return the parton distributions of a nucleus of different kinds at x and Q^2
double nIMParton::getPDF(int Iparton, double x, double Q2) const
{
if(Iparton==-3 || Iparton==3)return getXSSea(x,Q2)/2.0/x;
else if(Iparton==-2)return getXDSea(x,Q2)/2.0/x;
else if(Iparton==2)return getXDSea(x,Q2)/2.0/x+getXDV(x,Q2)/x;
else if(Iparton==-1)return getXUSea(x,Q2)/2.0/x;
else if(Iparton==1)return getXUSea(x,Q2)/2.0/x+getXUV(x,Q2)/x;
else if(Iparton==0)return getXGluon(x,Q2)/x;
else
{
cout<<"!!->Error: Unknown Iparton type."<<" (Iparton = "<<Iparton<<"?)"<<endl;
cout<<"!!->Iparton should be one of these: [-3,-2, ... 2, 3]"<<endl;
return 0;
}
}
//a method which returns xuv of a nucleus
double nIMParton::getXUV(double x, double Q2) const
{
return getPDFType(1,x,Q2);
}
//a method which returns xdv of a nucleus
double nIMParton::getXDV(double x, double Q2) const
{
return getPDFType(2,x,Q2);
}
//a method which returns xusea of a nucleus
double nIMParton::getXUSea(double x, double Q2) const
{
return getPDFType(3,x,Q2);
}
//a method which returns xdsea of a nucleus
double nIMParton::getXDSea(double x, double Q2) const
{
return getPDFType(4,x,Q2);
}
//a method which returns xssea of a nucleus
double nIMParton::getXSSea(double x, double Q2) const
{
return getPDFType(5,x,Q2);
}
//a method which returns structure function F2 of a nucleus
double nIMParton::getF2(double x, double Q2) const
{
return getPDFType(6,x,Q2);
}
//a method which returns xgluon of a nucleus
double nIMParton::getXGluon(double x, double Q2) const
{
return getPDFType(0,x,Q2);
}
//a method which returns different types of distributions of a nucleus
double nIMParton::getPDFType(int Iparton, double x, double Q2) const
{
if(Iparton<0 || Iparton>6)
{
cout<<"!!->Error: Wrong Iparton input for getPDFType(int Iparton, double x, double Q2)."<<endl;
return 0;
}
else
{
double lnx, lnQ2;
int i=(int)(lnx=log(x*1e6)/lnxstep);
int j=(int)(lnQ2=log(Q2*8)/lnQ2step);
double g0[3], g1[3], g2[3], g[3]={0};
if(i<0)i=0;
if(i>(int)(xMax-3))i=xMax-3;
if(j<0)j=0;
if(j>29)j=29;
//avoid log(1-x) calculation in below algorithm
if(x>0.9999)return 0.0;
//if x>0.47, we use A(1-x)^B to do the interpolation
else if(x>0.47)
{
double lnxstep2 = log(10)/100.0;
int i2 = 32 + (int)(log(x)/lnxstep2);
if(i2<=0) i2 = 0;
double vln1_x[2]={log(1-exp((i2-34)*lnxstep2)), log(1-exp((i2-33)*lnxstep2))};
g0[0]=log(gridA_largex[(xMax*j+i2)*7+Iparton]);
g0[1]=log(gridA_largex[(xMax*j+i2+1)*7+Iparton]);
j++;
g1[0]=log(gridA_largex[(xMax*j+i2)*7+Iparton]);
g1[1]=log(gridA_largex[(xMax*j+i2+1)*7+Iparton]);
j++;
g2[0]=log(gridA_largex[(xMax*j+i2)*7+Iparton]);
g2[1]=log(gridA_largex[(xMax*j+i2+1)*7+Iparton]);
g[0]=exp(fitLinear(log(1-x),vln1_x,g0));
g[1]=exp(fitLinear(log(1-x),vln1_x,g1));
g[2]=exp(fitLinear(log(1-x),vln1_x,g2));
}
//if x<1e-5, we use A*x^B to do the interpolation
//for valance quark, B>0; for gluon and sea quark, B<0
else if(x<1e-4)
{
double vlnx[2]={(double)i,(double)(i+1)};
g0[0]=log(gridA[(xMax*j+i)*7+Iparton]);
g0[1]=log(gridA[(xMax*j+i+1)*7+Iparton]);
j++;
g1[0]=log(gridA[(xMax*j+i)*7+Iparton]);
g1[1]=log(gridA[(xMax*j+i+1)*7+Iparton]);
j++;
g2[0]=log(gridA[(xMax*j+i)*7+Iparton]);
g2[1]=log(gridA[(xMax*j+i+1)*7+Iparton]);
g[0]=exp(fitLinear(lnx,vlnx,g0));
g[1]=exp(fitLinear(lnx,vlnx,g1));
g[2]=exp(fitLinear(lnx,vlnx,g2));
}
//we use quadratic interpolation method for other situations
else
{
double vlnx[3]={(double)i,(double)(i+1),(double)(i+2)};
g0[0]=gridA[(xMax*j+i)*7+Iparton];
g0[1]=gridA[(xMax*j+i+1)*7+Iparton];
g0[2]=gridA[(xMax*j+i+2)*7+Iparton];
j++;
g1[0]=gridA[(xMax*j+i)*7+Iparton];
g1[1]=gridA[(xMax*j+i+1)*7+Iparton];
g1[2]=gridA[(xMax*j+i+2)*7+Iparton];
j++;
g2[0]=gridA[(xMax*j+i)*7+Iparton];
g2[1]=gridA[(xMax*j+i+1)*7+Iparton];
g2[2]=gridA[(xMax*j+i+2)*7+Iparton];
g[0]=fitQuadratic(lnx,vlnx,g0);
g[1]=fitQuadratic(lnx,vlnx,g1);
g[2]=fitQuadratic(lnx,vlnx,g2);
}
//if Q2>1, we do the interpolation to the variable ln(Q^2)
if(Q2>1)
{
double vlnQ2[3]={(double)(j-2),(double)(j-1),(double)j};
return fitQuadratic(lnQ2,vlnQ2,g);
}
//if Q2<1, we do the interpolation to the variable Q^2
else
{
double vQ2[3]={0.125*pow(2,j-2),0.125*pow(2,j-1),0.125*pow(2,j)};
return fitQuadratic(Q2,vQ2,g);
}
}
}
//return the parton distributions of deuteron of different kinds at x and Q^2
double nIMParton::getPDFD(int Iparton, double x, double Q2) const
{
if(Iparton==-3 || Iparton==3)return getXSSeaD(x,Q2)/2.0/x;
else if(Iparton==-2)return getXDSeaD(x,Q2)/2.0/x;
else if(Iparton==2)return getXDSeaD(x,Q2)/2.0/x+getXDVD(x,Q2)/x;
else if(Iparton==-1)return getXUSeaD(x,Q2)/2.0/x;
else if(Iparton==1)return getXUSeaD(x,Q2)/2.0/x+getXUVD(x,Q2)/x;
else if(Iparton==0)return getXGluonD(x,Q2)/x;
else
{
cout<<"!!->Error: Unknown Iparton type."<<" (Iparton = "<<Iparton<<"?)"<<endl;
cout<<"!!->Iparton should be one of these: [-3,-2, ... 2, 3]"<<endl;
return 0;
}
}
//a method which returns xuv of deuteron
double nIMParton::getXUVD(double x, double Q2) const
{
return getPDFTypeD(1,x,Q2);
}
//a method which returns xdv of deuteron
double nIMParton::getXDVD(double x, double Q2) const
{
return getPDFTypeD(2,x,Q2);
}
//a method which returns xusea of deuteron
double nIMParton::getXUSeaD(double x, double Q2) const
{
return getPDFTypeD(3,x,Q2);
}
//a method which returns xdsea of deuteron
double nIMParton::getXDSeaD(double x, double Q2) const
{
return getPDFTypeD(4,x,Q2);
}
//a method which returns xssea of deuteron
double nIMParton::getXSSeaD(double x, double Q2) const
{
return getPDFTypeD(5,x,Q2);
}
//a method which returns structure function F2 of deuteron
double nIMParton::getF2D(double x, double Q2) const
{
return getPDFTypeD(6,x,Q2);
}
//a method which returns xgluon of deuteron
double nIMParton::getXGluonD(double x, double Q2) const
{
return getPDFTypeD(0,x,Q2);
}
//a method which returns different types of distributions of deuteron
double nIMParton::getPDFTypeD(int Iparton, double x, double Q2) const
{
if(Iparton<0 || Iparton>6)
{
cout<<"!!->Error: Wrong Iparton input for getPDFType(int Iparton, double x, double Q2)."<<endl;
return 0;
}
else
{
double lnx, lnQ2;
int i=(int)(lnx=log(x*1e6)/lnxstep);
int j=(int)(lnQ2=log(Q2*8)/lnQ2step);
double g0[3], g1[3], g2[3], g[3]={0};
if(i<0)i=0;
if(i>(int)(xMax-3))i=xMax-3;
if(j<0)j=0;
if(j>29)j=29;
//avoid log(1-x) calculation in below algorithm
if(x>0.9999)return 0.0;
//if x>0.47, we use A(1-x)^B to do the interpolation
else if(x>0.47)
{
double lnxstep2 = log(10)/100.0;
int i2 = 32 + (int)(log(x)/lnxstep2);
if(i2<=0) i2 = 0;
double vln1_x[2]={log(1-exp((i2-34)*lnxstep2)), log(1-exp((i2-33)*lnxstep2))};
g0[0]=log(gridD_largex[(xMax*j+i2)*7+Iparton]);
g0[1]=log(gridD_largex[(xMax*j+i2+1)*7+Iparton]);
j++;
g1[0]=log(gridD_largex[(xMax*j+i2)*7+Iparton]);
g1[1]=log(gridD_largex[(xMax*j+i2+1)*7+Iparton]);
j++;
g2[0]=log(gridD_largex[(xMax*j+i2)*7+Iparton]);
g2[1]=log(gridD_largex[(xMax*j+i2+1)*7+Iparton]);
g[0]=exp(fitLinear(log(1-x),vln1_x,g0));
g[1]=exp(fitLinear(log(1-x),vln1_x,g1));
g[2]=exp(fitLinear(log(1-x),vln1_x,g2));
}
//if x<1e-5, we use A*x^B to do the interpolation
//for valance quark, B>0; for gluon and sea quark, B<0
else if(x<1e-4)
{
double vlnx[2]={(double)i,(double)(i+1)};
g0[0]=log(gridD[(xMax*j+i)*7+Iparton]);
g0[1]=log(gridD[(xMax*j+i+1)*7+Iparton]);
j++;
g1[0]=log(gridD[(xMax*j+i)*7+Iparton]);
g1[1]=log(gridD[(xMax*j+i+1)*7+Iparton]);
j++;
g2[0]=log(gridD[(xMax*j+i)*7+Iparton]);
g2[1]=log(gridD[(xMax*j+i+1)*7+Iparton]);
g[0]=exp(fitLinear(lnx,vlnx,g0));
g[1]=exp(fitLinear(lnx,vlnx,g1));
g[2]=exp(fitLinear(lnx,vlnx,g2));
}
//we use quadratic interpolation method for other situations
else
{
double vlnx[3]={(double)i,(double)(i+1),(double)(i+2)};
g0[0]=gridD[(xMax*j+i)*7+Iparton];
g0[1]=gridD[(xMax*j+i+1)*7+Iparton];
g0[2]=gridD[(xMax*j+i+2)*7+Iparton];
j++;
g1[0]=gridD[(xMax*j+i)*7+Iparton];
g1[1]=gridD[(xMax*j+i+1)*7+Iparton];
g1[2]=gridD[(xMax*j+i+2)*7+Iparton];
j++;
g2[0]=gridD[(xMax*j+i)*7+Iparton];
g2[1]=gridD[(xMax*j+i+1)*7+Iparton];
g2[2]=gridD[(xMax*j+i+2)*7+Iparton];
g[0]=fitQuadratic(lnx,vlnx,g0);
g[1]=fitQuadratic(lnx,vlnx,g1);
g[2]=fitQuadratic(lnx,vlnx,g2);
}
//if Q2>1, we do the interpolation to the variable ln(Q^2)
if(Q2>1)
{
double vlnQ2[3]={(double)(j-2),(double)(j-1),(double)j};
return fitQuadratic(lnQ2,vlnQ2,g);
}
//if Q2<1, we do the interpolation to the variable Q^2
else
{
double vQ2[3]={0.125*pow(2,j-2),0.125*pow(2,j-1),0.125*pow(2,j)};
return fitQuadratic(Q2,vQ2,g);
}
}
}
//return the parton distributions of free nucleon of different kinds at x and Q^2
double nIMParton::getPDFN(int Iparton, double x, double Q2) const
{
if(Iparton==-3 || Iparton==3)return getXSSeaN(x,Q2)/2.0/x;
else if(Iparton==-2)return getXDSeaN(x,Q2)/2.0/x;
else if(Iparton==2)return getXDSeaN(x,Q2)/2.0/x+getXDVN(x,Q2)/x;
else if(Iparton==-1)return getXUSeaN(x,Q2)/2.0/x;
else if(Iparton==1)return getXUSeaN(x,Q2)/2.0/x+getXUVN(x,Q2)/x;
else if(Iparton==0)return getXGluonN(x,Q2)/x;
else
{
cout<<"!!->Error: Unknown Iparton type."<<" (Iparton = "<<Iparton<<"?)"<<endl;
cout<<"!!->Iparton should be one of these: [-3,-2, ... 2, 3]"<<endl;
return 0;
}
}
//a method which returns xuv of free nucleon
double nIMParton::getXUVN(double x, double Q2) const
{
return getPDFTypeN(1,x,Q2);
}
//a method which returns xdv of free nucleon
double nIMParton::getXDVN(double x, double Q2) const
{
return getPDFTypeN(2,x,Q2);
}
//a method which returns xusea of free nucleon
double nIMParton::getXUSeaN(double x, double Q2) const
{
return getPDFTypeN(3,x,Q2);
}
//a method which returns xdsea of free nucleon
double nIMParton::getXDSeaN(double x, double Q2) const
{
return getPDFTypeN(4,x,Q2);
}
//a method which returns xssea of free nucleon
double nIMParton::getXSSeaN(double x, double Q2) const
{
return getPDFTypeN(5,x,Q2);
}
//a method which returns structure function F2 of free nucleon
double nIMParton::getF2N(double x, double Q2) const
{
return getPDFTypeN(6,x,Q2);
}
//a method which returns xgluon of free nucleon
double nIMParton::getXGluonN(double x, double Q2) const
{
return getPDFTypeN(0,x,Q2);
}
//a method which returns different types of distributions of free nucleon
double nIMParton::getPDFTypeN(int Iparton, double x, double Q2) const
{
if(Iparton<0 || Iparton>6)
{
cout<<"!!->Error: Wrong Iparton input for getPDFType(int Iparton, double x, double Q2)."<<endl;
return 0;
}
else
{
double lnx, lnQ2;
int i=(int)(lnx=log(x*1e6)/lnxstep);
int j=(int)(lnQ2=log(Q2*8)/lnQ2step);
double g0[3], g1[3], g2[3], g[3]={0};
if(i<0)i=0;
if(i>(int)(xMax-3))i=xMax-3;
if(j<0)j=0;
if(j>29)j=29;
//avoid log(1-x) calculation in below algorithm
if(x>0.9999)return 0.0;
//if x>0.47, we use A(1-x)^B to do the interpolation
else if(x>0.47)
{
double lnxstep2 = log(10)/100.0;
int i2 = 32 + (int)(log(x)/lnxstep2);
if(i2<=0) i2 = 0;
double vln1_x[2]={log(1-exp((i2-34)*lnxstep2)), log(1-exp((i2-33)*lnxstep2))};
g0[0]=log(gridN_largex[(xMax*j+i2)*7+Iparton]);
g0[1]=log(gridN_largex[(xMax*j+i2+1)*7+Iparton]);
j++;
g1[0]=log(gridN_largex[(xMax*j+i2)*7+Iparton]);
g1[1]=log(gridN_largex[(xMax*j+i2+1)*7+Iparton]);
j++;
g2[0]=log(gridN_largex[(xMax*j+i2)*7+Iparton]);
g2[1]=log(gridN_largex[(xMax*j+i2+1)*7+Iparton]);
g[0]=exp(fitLinear(log(1-x),vln1_x,g0));
g[1]=exp(fitLinear(log(1-x),vln1_x,g1));
g[2]=exp(fitLinear(log(1-x),vln1_x,g2));
}
//if x<1e-5, we use A*x^B to do the interpolation
//for valance quark, B>0; for gluon and sea quark, B<0
else if(x<1e-4)
{
double vlnx[2]={(double)i,(double)(i+1)};
g0[0]=log(gridN[(xMax*j+i)*7+Iparton]);
g0[1]=log(gridN[(xMax*j+i+1)*7+Iparton]);
j++;
g1[0]=log(gridN[(xMax*j+i)*7+Iparton]);
g1[1]=log(gridN[(xMax*j+i+1)*7+Iparton]);
j++;
g2[0]=log(gridN[(xMax*j+i)*7+Iparton]);
g2[1]=log(gridN[(xMax*j+i+1)*7+Iparton]);
g[0]=exp(fitLinear(lnx,vlnx,g0));
g[1]=exp(fitLinear(lnx,vlnx,g1));
g[2]=exp(fitLinear(lnx,vlnx,g2));
}
//we use quadratic interpolation method for other situations
else
{
double vlnx[3]={(double)i,(double)(i+1),(double)(i+2)};
g0[0]=gridN[(xMax*j+i)*7+Iparton];
g0[1]=gridN[(xMax*j+i+1)*7+Iparton];
g0[2]=gridN[(xMax*j+i+2)*7+Iparton];
j++;
g1[0]=gridN[(xMax*j+i)*7+Iparton];
g1[1]=gridN[(xMax*j+i+1)*7+Iparton];
g1[2]=gridN[(xMax*j+i+2)*7+Iparton];
j++;
g2[0]=gridN[(xMax*j+i)*7+Iparton];
g2[1]=gridN[(xMax*j+i+1)*7+Iparton];
g2[2]=gridN[(xMax*j+i+2)*7+Iparton];
g[0]=fitQuadratic(lnx,vlnx,g0);
g[1]=fitQuadratic(lnx,vlnx,g1);
g[2]=fitQuadratic(lnx,vlnx,g2);
}
//if Q2>1, we do the interpolation to the variable ln(Q^2)
if(Q2>1)
{
double vlnQ2[3]={(double)(j-2),(double)(j-1),(double)j};
return fitQuadratic(lnQ2,vlnQ2,g);
}
//if Q2<1, we do the interpolation to the variable Q^2
else
{
double vQ2[3]={0.125*pow(2,j-2),0.125*pow(2,j-1),0.125*pow(2,j)};
return fitQuadratic(Q2,vQ2,g);
}
}
}
//get F2 ratio of a nucleus to free nucleon
double nIMParton::getF2RToN(double x, double Q2) const
{
return getF2(x, Q2)/getF2N(x, Q2);
}
//get F2 ratio of a nucleus to deuteron
double nIMParton::getF2RToD(double x, double Q2) const
{
return getF2(x, Q2)/getF2D(x, Q2);
}
//linear interpolation method
double nIMParton::fitQuadratic(double x, double* px, double* pf) const
{
double f01=(pf[1]-pf[0])/(px[1]-px[0]);
double f12=(pf[2]-pf[1])/(px[2]-px[1]);
double f012=(f12-f01)/(px[2]-px[0]);
return pf[0]+f01*(x-px[0])+f012*(x-px[0])*(x-px[1]);
}
//quadratic interpolation method
double nIMParton::fitLinear(double x, double* px, double* pf) const
{
double f01=(pf[1]-pf[0])/(px[1]-px[0]);
return pf[0]+f01*(x-px[0]);
}