Index: trunk/src/TableGeneratorSettings.h =================================================================== --- trunk/src/TableGeneratorSettings.h (revision 369) +++ trunk/src/TableGeneratorSettings.h (revision 370) @@ -1,122 +1,122 @@ //============================================================================== // TableGeneratorSettings.h // -// Copyright (C) 2010-2013 Tobias Toll and Thomas Ullrich +// Copyright (C) 2010-2019 Tobias Toll and Thomas Ullrich // // This file is part of Sartre. // // 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. // 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, see . // // Author: Tobias Toll // Last update: // $Date$ // $Author$ //============================================================================== // // Singleton class // //============================================================================== #ifndef TableGeneratorSettings_h #define TableGeneratorSettings_h #include "Settings.h" #include "Enumerations.h" using namespace std; class TableGeneratorSettings : public Settings { public: static TableGeneratorSettings* instance(); void setTmin(double); double tmin() const; void setTmax(double); double tmax() const; void setXmin(double); double xmin() const; void setXmax(double); double xmax() const; void setQ2bins(unsigned int); unsigned int Q2bins() const; void setW2bins(unsigned int); unsigned int W2bins() const; void setTbins(unsigned int); unsigned int tbins() const; void setXbins(unsigned int); unsigned int xbins() const; string bSatLookupPath() const; void setBSatLookupPath(string); unsigned int numberOfConfigurations() const; void setNumberOfConfigurations(unsigned int); vector dipoleModelCustomParameters() const; bool useBackupFile() const; void setUseBackupFile(bool); int startingBinFromBackup() const; void setStartingBinFromBackup(int); int startBin() const; void setStartBin(int); int endBin() const; void setEndBin(int); int modesToCalculate() const; void setModesToCalculate(int); unsigned char priority() const; void setPriority(unsigned char); void consolidateSettings(); private: TableGeneratorSettings(); private: static TableGeneratorSettings* mInstance; private: unsigned int mNumberOfConfigurations; vector mDipoleModelCustomParameters; // developer bool mUseBackupFile; int mStartingBinFromBackup; int mStartBin, mEndBin; int mModesToCalculate; double mTmin; double mTmax; double mXmin; double mXmax; unsigned int mQ2bins; unsigned int mW2bins; unsigned int mTbins; unsigned int mXbins; string mBSatLookupPath; int mPriority; }; #endif Index: trunk/src/Table.cpp =================================================================== --- trunk/src/Table.cpp (revision 369) +++ trunk/src/Table.cpp (revision 370) @@ -1,1431 +1,1431 @@ //============================================================================== // Table.cpp // -// Copyright (C) 2010-2017 Tobias Toll and Thomas Ullrich +// Copyright (C) 2010-2019 Tobias Toll and Thomas Ullrich // // This file is part of Sartre. // // 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. // 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, see . // // Author: Thomas Ullrich // Last update: // $Date$ // $Author$ //============================================================================== // // Table data is stored in a TH3F. // // All information is stored in the histogram title. // // Table ID is encoded as follows: // // histogram title is a number that is to be interpreted // as an uint64_t with the bits set as follows: // // bit 0: content type: 0 for , 1 for (see also bits 33 and 45) // bit 1: polarization: T=1, L=0 // bit 2: t encoding: 0 for |t|, 1 for log(|t|) // bit 3: W2 encoding: 0 for lin, 1 for log // bit 4: Q2 encoding: 0 for lin, 1 for log // bit 5-7: dipole model type (Enumerations.h) // bit 8-15: mass number A // bit 16-31: vector meson ID (PDG) // bit 32: content encoding: 0 in lin, 1 in log // bit 33: content type is lambda_ (bits 0 and 45 are zero in this case) // bit 34-41: priority // bit 42-44: dipole model parameter set (Enumerations.h) // bit 45: content type is variance_A (bit 33 and 45 are zero in this case) // bit 46: upc only table (tables with one Q2 bin only) // bit 47: xpomeron encoding: 0 for lin, 1 for log (UPC only) // bit 48: content type is lambda_skewedness (bits 0, 33, and 45 are zero in this case). // bit 49-63: not used // // log implies ln // bit 0 is the LSB // // Internal histogram: x = Q2, y = W2, z = t (or the logs) // x = xpomeron, y = t (or the logs) // UPC only // // Actual value is taken at the center of the bin. // min/max functions (e.g. minQ2()) return the value of the first/last // bin center. //============================================================================== #include "Table.h" #include "TFile.h" #include "TH2F.h" #include "TH3F.h" #include #include #include #include #include #include #include #include #include #include #include #include "GridSpline.h" #define PR(x) cout << #x << " = " << (x) << endl; Table::Table() { mID = 0; m3DHisto = 0; m2DHisto = 0; mFillCounter = 0; mBackupFrequence = 0; } Table& Table::operator=(const Table& tab) { if (this != &tab) { delete m3DHisto; delete m2DHisto; mID = tab.mID; if (tab.m3DHisto) { m3DHisto = new TH3F(*(tab.m3DHisto)); m3DHisto->SetDirectory(0); } if (tab.m2DHisto) { m2DHisto = new TH2F(*(tab.m2DHisto)); m2DHisto->SetDirectory(0); } mFilename = tab.mID; mFillCounter = tab.mID; mBackupFrequence = tab.mID; mBackupPrefix = tab.mID; mLastBackupFilename = tab.mID; } return *this; } Table::Table(const Table& tab) { mID = tab.mID; if (tab.m3DHisto) { m3DHisto = new TH3F(*(tab.m3DHisto)); m3DHisto->SetDirectory(0); } if (tab.m2DHisto) { m2DHisto = new TH2F(*(tab.m2DHisto)); m2DHisto->SetDirectory(0); } mFilename = tab.mID; mFillCounter = tab.mID; mBackupFrequence = tab.mID; mBackupPrefix = tab.mID; mLastBackupFilename = tab.mID; } Table::~Table() { delete m2DHisto; delete m3DHisto; } unsigned int Table::create(int nbinsQ2, double Q2min, double Q2max, int nbinsW2, double W2min, double W2max, int nbinsT, double tmin, double tmax, bool logQ2, bool logW2, bool logt, bool logC, AmplitudeMoment mom, GammaPolarization pol, unsigned int A, int vm, DipoleModelType model, DipoleModelParameterSet pset, const char* filename, unsigned char priority) { if (m3DHisto != 0) { cout << "Table:create(): cannot create, table already exists." << endl; return 0; } if (filename) mFilename = string(filename); // name of file where table is written to // // Create table ID first // mID = (vm << 16); mID |= (A << 8); mID |= (model << 5); mID |= (static_cast(pset) << 42); if (mom == mean_A2) mID |= 1; if (pol == transverse) mID |= (1 << 1); if (logt) mID |= (1 << 2); if (logW2) mID |= (1 << 3); if (logQ2) mID |= (1 << 4); if (logC) mID |= (static_cast(1) << 32); if (mom == lambda_A) mID |= (static_cast(1) << 33); if (mom == lambda_skew) mID |= (static_cast(1) << 48); mID |= (static_cast(priority) << 34); if (mom == variance_A) mID |= (static_cast(1) << 45); ostringstream titlestream; titlestream << mID; string title = titlestream.str(); // // Binning // // Interpolate() only works up to the bin center // of the first and last bin. To guarantee that // the full range is accessible we shift the min // and max of each axis. // tmin = fabs(tmin); tmax = fabs(tmax); if (tmin > tmax) swap(tmin, tmax); if (logQ2) Q2min = log(Q2min); if (logQ2) Q2max = log(Q2max); if (logW2) W2min = log(W2min); if (logW2) W2max = log(W2max); if (logt) tmin = log(tmin); if (logt) tmax = log(tmax); double binWidthQ2 = (Q2max - Q2min)/(nbinsQ2-1); double binWidthW2 = (W2max - W2min)/(nbinsW2-1); double binWidthT = (tmax - tmin)/(nbinsT-1); // // Book 3D histo to hold table // m3DHisto = new TH3F("table", title.c_str(), nbinsQ2, Q2min-binWidthQ2/2., Q2max+binWidthQ2/2., nbinsW2, W2min-binWidthW2/2., W2max+binWidthW2/2., nbinsT, tmin-binWidthT/2., tmax+binWidthT/2.); m3DHisto->SetDirectory(0); return nbinsQ2*nbinsW2*nbinsT; // return total number of bins } // // Overloaded function for UPC only // unsigned int Table::create(int nbinsX, double Xmin, double Xmax, int nbinsT, double tmin, double tmax, bool logX, bool logt, bool logC, AmplitudeMoment mom, GammaPolarization pol, unsigned int A, int vm, DipoleModelType model, DipoleModelParameterSet pset, const char* filename, unsigned char priority) { if (m2DHisto != 0) { cout << "Table:create(): cannot create, table already exists." << endl; return 0; } if (filename) mFilename = string(filename); // name of file where table is written to // // Create table ID first // mID = (vm << 16); mID |= (A << 8); mID |= (model << 5); mID |= (static_cast(pset) << 42); if (mom == mean_A2) mID |= 1; if (pol == transverse) mID |= (1 << 1); if (logt) mID |= (1 << 2); if (logC) mID |= (static_cast(1) << 32); if (mom == lambda_A) mID |= (static_cast(1) << 33); if (mom == lambda_skew) mID |= (static_cast(1) << 48); mID |= (static_cast(priority) << 34); if (mom == variance_A) mID |= (static_cast(1) << 45); mID |= (static_cast(1) << 46); // flag UPC if (logX) mID |= (static_cast(1) << 47); ostringstream titlestream; titlestream << mID; string title = titlestream.str(); // // Binning // // Interpolate() only works up to the bin center // of the first and last bin. To guarantee that // the full range is accessible we shift the min // and max of each axis. // tmin = fabs(tmin); tmax = fabs(tmax); if (tmin > tmax) swap(tmin, tmax); if (logX) Xmin = log(Xmin); if (logX) Xmax = log(Xmax); if (logt) tmin = log(tmin); if (logt) tmax = log(tmax); double binWidthX = (Xmax - Xmin)/(nbinsX-1); double binWidthT = (tmax - tmin)/(nbinsT-1); // // Book 2D histo to hold table // m2DHisto = new TH2F("table", title.c_str(), nbinsX, Xmin-binWidthX/2., Xmax+binWidthX/2., nbinsT, tmin-binWidthT/2., tmax+binWidthT/2.); m2DHisto->SetDirectory(0); return nbinsX*nbinsT; // return total number of bins } int Table::numberOfEntries() const { if (m3DHisto) { int nx = m3DHisto->GetXaxis()->GetNbins(); int ny = m3DHisto->GetYaxis()->GetNbins(); int nz = m3DHisto->GetZaxis()->GetNbins(); return nx*ny*nz; } else if (m2DHisto) { // UPC case int nx = m2DHisto->GetXaxis()->GetNbins(); int ny = m2DHisto->GetYaxis()->GetNbins(); return nx*ny; } else return 0; } void Table::binXYZ(int globalBin, int& binx, int& biny, int& binz) const { // // Find correct bins for each axis. // Don't use ROOT global bins here, // they are a mess since they cross // over underflow and overflow bins. // // All bins returned count starting // at 1. The global bin starts at // 0 as usual in C++. // int nx = m3DHisto->GetXaxis()->GetNbins(); int ny = m3DHisto->GetYaxis()->GetNbins(); binx = globalBin%nx; biny = ((globalBin-binx)/nx)%ny; binz = ((globalBin-binx)/nx -biny)/ny; binx++; biny++; binz++; } // // UPC version of binXYZ() // void Table::binXY(int globalBin, int& binx, int& biny) const { // // Find correct bins for each axis. // Don't use ROOT global bins here, // they are a mess since they cross // over underflow and overflow bins. // // All bins returned count starting // at 1. The global bin starts at // 0 as usual in C++. // int nx = m2DHisto->GetXaxis()->GetNbins(); binx = globalBin%nx; biny = (globalBin-binx)/nx; binx++; biny++; } void Table::binCenter(int i, double& Q2, double& W2, double& t) const { int binx, biny, binz; binXYZ(i, binx, biny, binz); // cout << i << '\t' << binx << '\t' << biny << '\t' << binz << endl; double x = m3DHisto->GetXaxis()->GetBinCenter(binx); double y = m3DHisto->GetYaxis()->GetBinCenter(biny); double z = m3DHisto->GetZaxis()->GetBinCenter(binz); Q2 = isLogQ2() ? exp(x) : x; W2 = isLogW2() ? exp(y) : y; t = isLogT() ? -exp(z) : -z; if (t > 0) t = 0; // avoid numeric glitch } // // UPC overload // void Table::binCenter(int i, double& xpom, double& t) const { int binx, biny; binXY(i, binx, biny); // cout << i << '\t' << binx << '\t' << biny << endl; double x = m2DHisto->GetXaxis()->GetBinCenter(binx); double y = m2DHisto->GetYaxis()->GetBinCenter(biny); xpom = isLogX() ? exp(x) : x; t = isLogT() ? -exp(y) : -y; if (t > 0) t = 0; // avoid numeric glitch } void Table::fill(int i, double val, double err) { int binx, biny, binz; if (isUPC()) binXY(i, binx, biny); else binXYZ(i, binx, biny, binz); if (isLogContent()) { if (val == 0) { // cout << "Table::fill(): warning, log scale requested but value = 0." << endl; val = numeric_limits::min(); } val = log(fabs(val)); } if (isUPC()) m2DHisto->SetBinContent(binx, biny, val); else m3DHisto->SetBinContent(binx, biny, binz, val); if(err!=0.) { if (isUPC()) m2DHisto->SetBinError(binx, biny, err); else m3DHisto->SetBinError(binx, biny, binz, err); } mFillCounter++; // // Check if backup is due // if (mBackupFrequence) if (mFillCounter%mBackupFrequence == 0) backup(i); } bool Table::fexists(const char* filename) const { ifstream ifs(filename); return !ifs.fail(); } void Table::write(const char* filename) { // // 'filename' is optional argument. Null value implies // that one was already passed via create(). Check // that this is the case. If one is given, it is used // no matter if it already was defined or not. // if (filename) mFilename = string(filename); else { if (mFilename.empty()) { // should be defined but is not cout << "Table::write(): Warning, no filename supplied. Will use 'sartre_table.root'." << endl; mFilename = string("sartre_table.root"); } } // // Check if file exist. If so alter // the filename. Creating tables is // a time consuming business so we do // not want to lose precious data if // something goes wrong here and we do // want to prevent accidents. // while (fexists(mFilename.c_str())) { mFilename += string(".save"); } TFile hfile(mFilename.c_str(),"RECREATE"); if (isUPC()) m2DHisto->Write(); else m3DHisto->Write(); hfile.Close(); cout << "Table::write(): table stored in file '" << mFilename.c_str()<< "'." << endl; if (mBackupFrequence && !mLastBackupFilename.empty()) remove(mLastBackupFilename.c_str()); } bool Table::read(const char* filename) { // // Read histogram into memory // TFile *file = TFile::Open(filename,"READ"); if (file == 0) { cout << "Table::read(): failed opening file '" << filename << "'." << endl; return false; } // // Clean up // delete m3DHisto; m3DHisto = 0; delete m2DHisto; m2DHisto = 0; // // Read plain object first and check title which // tells us if it is an UPC table or a std one. // Then cast into the proper object. // auto ptr = file->Get("table"); if (ptr == 0) { cout << "Table::read(): failed retrieving table from file '" << filename << "'." << endl; return false; } mID = atoll(ptr->GetTitle()); // for isUPC() to work if (isUPC()) { m2DHisto = reinterpret_cast(ptr); m2DHisto->SetDirectory(0); } else { m3DHisto = reinterpret_cast(ptr); m3DHisto->SetDirectory(0); } if (m2DHisto == 0 && m3DHisto == 0) { cout << "Table::read(): failed retrieving table from file '" << filename << "'." << endl; return false; } file->Close(); mFilename = string(filename); return true; } int Table::vectorMesonId() const {return ((mID >> 16) & 0xFFFF);} unsigned int Table::dipoleModelType() const {return ((mID >> 5) & 0x7);} unsigned int Table::dipoleModelParameterSet() const {return ((mID >> 42) & 0x7);} unsigned int Table::A() const {return ((mID >> 8) & 0xFF);} bool Table::isLongitudinal() const {return !isTransverse();} bool Table::isTransverse() const {return (mID & (1 << 1));} GammaPolarization Table::polarization() const {return (isTransverse() ? transverse : longitudinal);} AmplitudeMoment Table::moment() const { if (isLambdaA()) return lambda_A; else if (isMeanA()) return mean_A; else if (isVarianceA()) return variance_A; else if (isLambdaSkew()) return lambda_skew; else return mean_A2; } bool Table::isMeanA() const { // bits 0, 33, 45 and 48 are not set return !(mID & 1) && !(mID & (static_cast(1) << 33)) && !(mID & (static_cast(1) << 45)) && !(mID & (static_cast(1) << 48)); } bool Table::isMeanA2() const { // bit 0 is set, bits 33, 45 and 48 are not set return (mID & 1) && !(mID & (static_cast(1) << 33)) && !(mID & (static_cast(1) << 45)) && !(mID & (static_cast(1) << 48)); } bool Table::isLambdaA() const { // bit 33 is set, bits 0 and 45 are not set return !(mID & 1) && (mID & (static_cast(1) << 33)) && !(mID & (static_cast(1) << 45)) && !(mID & (static_cast(1) << 48)); } bool Table::isLambdaSkew() const { // bit 48 is set, bits 0, 33, and 45 are not set return !(mID & 1) && (mID & (static_cast(1) << 48)) && !(mID & (static_cast(1) << 33)) && !(mID & (static_cast(1) << 45)); } bool Table::isVarianceA() const { // bit 45 is set, bitss 0, 33, and 48 are not set return !(mID & 1) && !(mID & (static_cast(1) << 33)) && (mID & (static_cast(1) << 45)) && !(mID & (static_cast(1) << 48)); } bool Table::isLogQ2() const {return (mID & (1 << 4));} bool Table::isLogW2() const {return (mID & (1 << 3));} bool Table::isLogT() const {return (mID & (1 << 2));} bool Table::isLogX() const {return (mID & (static_cast(1) << 47));} bool Table::isLogContent() const {return (mID & (static_cast(1) << 32));} unsigned int Table::priority() const {return ((mID >> 34) & 0xFF);} bool Table::isUPC() const {return (mID & (static_cast(1) << 46));} uint64_t Table::id() const {return mID;} double Table::binWidthQ2() const { if (!m3DHisto) return 0; return m3DHisto->GetXaxis()->GetBinWidth(1); } double Table::binWidthW2() const { if (!m3DHisto) return 0; return m3DHisto->GetYaxis()->GetBinWidth(1); } double Table::binWidthT() const { if (isUPC()) { return m2DHisto->GetYaxis()->GetBinWidth(1); } else return m3DHisto->GetZaxis()->GetBinWidth(1); } double Table::binWidthX() const { if (!m2DHisto) return 0; return m2DHisto->GetXaxis()->GetBinWidth(1); } double Table::get(double Q2, double W2, double t) const { if (m3DHisto == 0) return 0; // // Transform variables to how they are stored in the table // double x = isLogQ2() ? log(Q2) : Q2; double y = isLogW2() ? log(W2) : W2; t = fabs(t); double z = isLogT() ? log(t) : t; // // Tiny numerical glitches will cause TH3F::Interpolate() to fail // since it requires that the variables lie between the first // and last bin center, excluding the centers. // Here we enforce that this is the case. The downside of this // is that *all* values of Q2, W2, t will be forced to lie within. // Hence the user has to make sure that the values are within // the boundaries (see minQ2(), maxQ2(), minW2() etc.) before // calling get(). // In this case the corrections below are tiny and are only // applied to avoid minor glitches that do not affect the results. // TAxis *axis = m3DHisto->GetXaxis(); x = max(x, axis->GetBinCenter(1)+numeric_limits::epsilon()); x = min(x, axis->GetBinCenter(axis->GetNbins())-numeric_limits::epsilon()); axis = m3DHisto->GetYaxis(); y = max(y, axis->GetBinCenter(1)+numeric_limits::epsilon()); y = min(y, axis->GetBinCenter(axis->GetNbins())-numeric_limits::epsilon()); axis = m3DHisto->GetZaxis(); z = max(z, axis->GetBinCenter(1)+numeric_limits::epsilon()); z = min(z, axis->GetBinCenter(axis->GetNbins())-numeric_limits::epsilon()); // double result = InterpolateGridSpline(x, y, z); // tmp uncommented until 0's in tables are cleared // double result = m3DHisto->Interpolate(x, y, z); double result = modInterpolation(x, y, z); if (result == 0 && isLogContent()) { cout << "Table::get(): warning, 0 is not a valid table content when working in log scale." << endl; } if (isLogContent()) result = exp(result); return result; } // // UPC version // double Table::get(double xpom, double t) const { if (m2DHisto == 0) return 0; // // Transform variables to how they are stored in the table // double x = isLogX() ? log(xpom) : xpom; t = fabs(t); double y = isLogT() ? log(t) : t; // // Tiny numerical glitches will cause TH2F::Interpolate() to fail // since it requires that the variables lie between the first // and last bin center, excluding the centers. // Here we enforce that this is the case. The downside of this // is that *all* values of x, t will be forced to lie within. // Hence the user has to make sure that the values are within // the boundaries (see minX(), maxX(), minT() etc.) before // calling get(). // In this case the corrections below are tiny and are only // applied to avoid minor glitches that do not affect the results. // TAxis *axis = m2DHisto->GetXaxis(); x = max(x, axis->GetBinCenter(1)+numeric_limits::epsilon()); x = min(x, axis->GetBinCenter(axis->GetNbins())-numeric_limits::epsilon()); axis = m2DHisto->GetYaxis(); y = max(y, axis->GetBinCenter(1)+numeric_limits::epsilon()); y = min(y, axis->GetBinCenter(axis->GetNbins())-numeric_limits::epsilon()); double result = modInterpolation(x, y); // xpom, t if (result == 0 && isLogContent()) { cout << "Table::get(): warning, 0 is not a valid table content when working in log scale." << endl; } if (isLogContent()) result = exp(result); return result; } double Table::minQ2() const { if (m3DHisto == 0) return 0; TAxis *axis = m3DHisto->GetXaxis(); double val = axis->GetBinCenter(1); return isLogQ2() ? exp(val) : val; } double Table::maxQ2() const { if (m3DHisto == 0) return 0; TAxis *axis = m3DHisto->GetXaxis(); double val = axis->GetBinCenter(axis->GetNbins()); return isLogQ2() ? exp(val) : val; } double Table::minW2() const { if (m3DHisto == 0) return 0; TAxis *axis = m3DHisto->GetYaxis(); double val = axis->GetBinCenter(1); return isLogW2() ? exp(val) : val; } double Table::maxW2() const { if (m3DHisto == 0) return 0; TAxis *axis = m3DHisto->GetYaxis(); double val = axis->GetBinCenter(axis->GetNbins()); return isLogW2() ? exp(val) : val; } double Table::minT() const { if (m2DHisto == 0 && m3DHisto == 0) return 0; TAxis *axis = 0; if (isUPC()) axis = m2DHisto->GetYaxis(); else axis = m3DHisto->GetZaxis(); double val = axis->GetBinCenter(axis->GetNbins()); // t always as |t| in table return isLogT() ? -exp(val) : -val; } double Table::maxT() const { if (m2DHisto == 0 && m3DHisto == 0) return 0; TAxis *axis = 0; if (isUPC()) axis = m2DHisto->GetYaxis(); else axis = m3DHisto->GetZaxis(); double val = axis->GetBinCenter(1); // t always as |t| in table double result = isLogT() ? -exp(val) : -val; if (result > 0) { // cout << "Table::maxT(): warning, t > 0, t (" << result << ") set to 0 now." << endl; result = 0; } return result; } double Table::minX() const { if (m2DHisto == 0) return 0; TAxis *axis = m2DHisto->GetXaxis(); double val = axis->GetBinCenter(1); return isLogX() ? exp(val) : val; } double Table::maxX() const { if (m2DHisto == 0) return 0; TAxis *axis = m2DHisto->GetXaxis(); double val = axis->GetBinCenter(axis->GetNbins()); return isLogX() ? exp(val) : val; } string Table::filename() const {return mFilename;} bool Table::writeToBinaryFile(const string& filename, bool verbose) const { // // Open binary file // ofstream binaryFile; binaryFile.open (filename, ios::out | ios::binary); if (binaryFile.fail()) { cout << "Table::writeToBinaryFile: failed to open file '" << filename << "'." << endl; return false; } // // Loop over all entries // double Q2, W2, xpom, t; int binx, biny, binz; double rawContent; for (int i=0; iGetBinContent(binx, biny); if (isLogContent()) { rawContent = exp(rawContent); } binaryFile.write(reinterpret_cast(&i), sizeof(i)); binaryFile.write(reinterpret_cast(&xpom), sizeof(xpom)); binaryFile.write(reinterpret_cast(&t), sizeof(t)); binaryFile.write(reinterpret_cast(&rawContent), sizeof(rawContent)); if (verbose) cout << "i=" << i << "\txpom=" << xpom << "\tt=" << t << "\tvalue=" << rawContent << endl; } else { binXYZ(i, binx, biny, binz); binCenter(i, Q2, W2, t); rawContent = m3DHisto->GetBinContent(binx, biny, binz); if (isLogContent()) { rawContent = exp(rawContent); } binaryFile.write(reinterpret_cast(&i), sizeof(i)); binaryFile.write(reinterpret_cast(&Q2), sizeof(Q2)); binaryFile.write(reinterpret_cast(&W2), sizeof(W2)); binaryFile.write(reinterpret_cast(&t), sizeof(t)); binaryFile.write(reinterpret_cast(&rawContent), sizeof(rawContent)); if (verbose) cout << "i=" << i << "\tQ2=" << Q2 << "\tW2=" << W2 << "\tt=" << t << "\tvalue=" << rawContent << endl; } } binaryFile.close(); return true; } void Table::list(ostream& os, bool printContent, bool printStatistics, int startBin, int endBin) const { // // List table info as compact as possible // ios::fmtflags fmt = os.flags(); // store current I/O flags if ((isUPC() && !m2DHisto) || (!isUPC() && !m3DHisto)) { os << "Table::list(): table is undefined." << endl; return; } // // First row: table id, A, and content // os << setw(11) << "Table ID = " << setw(16) << left << mID; os << setw(7) << right << "A = " << setw(4) << left << A(); os << setw(20) << right << "content = " << (isLogContent() ? "log(" : ""); if (isMeanA()) os << ""; else if (isMeanA2()) os << ""; else if (isLambdaA()) os << "lambda_"; else if (isVarianceA()) os << "variance_A"; else if (isLambdaSkew()) os << "lambda_skew"; else os << "unknown"; os << (isLogContent() ? ")" : "") << endl; // // Second row: vm and polarization // os << setw(34) << right << "vmId = " << setw(4) << left << vectorMesonId(); os << setw(20) << right << "polarization = " << (isTransverse() ? 'T' : 'L') << endl; // // Third row: dipole model and parameter set // os << setw(34) << right << "model = " << setw(7) << left; if (dipoleModelType() == bSat) os << "bSat "; else if (dipoleModelType() == bNonSat) os << "bNonSat"; else os << "bCGC "; os << setw(17) << right << "parameter set = "; if (dipoleModelParameterSet() == KMW) os << "KMW "; else if (dipoleModelParameterSet() == HMPZ) os << "HMPZ"; else if (dipoleModelParameterSet() == CUSTOM) os << "CUSTOM"; else os << "? "; os << endl; // // Third row: priority and UPC // os << setw(34) << right << "priority = " << setw(4) << left << priority(); os << setw(20) << right << "UPC = " << (isUPC() ? "yes" : "no") << endl; // // Next three rows: Q2, W2, t bins, range and log/linear // or for UPC: x, t // if (isUPC()) { os << setw(35) << right << "xp = [" << minX() << ", " << maxX() << "; bins = " << m2DHisto->GetXaxis()->GetNbins() << (isLogX() ? "; log]" : "; lin]") << endl; os << setw(35) << right << "t = [" << minT() << ", " << maxT() << "; bins = " << m2DHisto->GetYaxis()->GetNbins() << (isLogT() ? "; log]" : "; lin]") << endl; } else { os << setw(35) << right << "Q2 = [" << minQ2() << ", " << maxQ2() << "; bins = " << m3DHisto->GetXaxis()->GetNbins() << (isLogQ2() ? "; log]" : "; lin]") << endl; os << setw(35) << right << "W2 = [" << minW2() << ", " << maxW2() << "; bins = " << m3DHisto->GetYaxis()->GetNbins() << (isLogW2() ? "; log]" : "; lin]") << endl; os << setw(35) << right << "t = [" << minT() << ", " << maxT() << "; bins = " << m3DHisto->GetZaxis()->GetNbins() << (isLogT() ? "; log]" : "; lin]") << endl; } // // Filename at the end // os << setw(34) << right << "file = " << mFilename.c_str() << endl; os << endl; // // Print content (optional) // double Q2, W2, t, xpom; int binx, biny, binz; if (printContent) { int thePrecision = os.precision(); double rawContent = 0; if(endBin==0) endBin=numberOfEntries(); for (int i=startBin; iGetBinContent(binx, biny); double error = m2DHisto->GetBinError(binx, biny); os << "bin = " << setw(8) << left << i; os << "xp = " << setw(13) << left << fixed << setprecision(5) << xpom; os << "t = " << setw(16) << left << scientific << t; os << "value = " << setw(15) << left << scientific << value; os << "(binx = " << setw(5) << left << binx; os << "biny = " << setw(5) << left << biny; os << "content = " << setw(14) << left << scientific << rawContent; os << "error = " << left << error << ')'; } else { binXYZ(i, binx, biny, binz); binCenter(i, Q2, W2, t); double value = get(Q2, W2, t); rawContent = m3DHisto->GetBinContent(binx, biny, binz); double error = m3DHisto->GetBinError(binx, biny, binz); os << "bin = " << setw(8) << left << i; os << "Q2 = " << setw(13) << left << fixed << setprecision(5) << Q2; os << "W2 = " << setw(12) << left << fixed << W2; os << "t = " << setw(16) << left << scientific << t; os << "value = " << setw(15) << left << scientific << value; os << "(binx = " << setw(5) << left << binx; os << "biny = " << setw(5) << left << biny; os << "binz = " << setw(5) << left << binz; os << "content = " << setw(14) << left << scientific << rawContent; os << "error = " << left << error << ')'; } if ( (isLogContent() && rawContent <= log(numeric_limits::min()*2)) || (rawContent == 0)) cout << " Z"; cout << endl; } os << endl; os.precision(thePrecision); } // // Print statistics (optional) // if (printStatistics) { int nEmpty = 0; int nInvalid = 0; int nNegative = 0; double sum = 0; double maxContent = 0; double minContent = numeric_limits::max(); int minBin, maxBin; minBin = maxBin = 0; double c = 0; for (int i=0; iGetBinContent(binx, biny); } else { binXYZ(i, binx, biny, binz); c = m3DHisto->GetBinContent(binx, biny, binz); } if (c == 0) nEmpty++; if ( !isLogContent() && c < 0) nNegative++; if (std::isnan(c) || std::isinf(c) || !std::isfinite(c)) nInvalid++; if (isLogContent()) c = exp(c); if (c > maxContent) {maxContent = c; maxBin = i;} if (c > 0 && c < minContent) {minContent = c; minBin = i;} if (c > 0) sum += c; } os << setw(34) << right << "total number of cells = " << numberOfEntries() << endl; os << setw(34) << right << "cells with negative content = " << nNegative << endl; os << setw(34) << right << "cells with no (0) content = " << nEmpty << endl; os << setw(34) << right << "cells with invalid content = " << nInvalid << endl; if (isUPC()) { binCenter(minBin, xpom, t); os << setw(34) << right << "minimum content = " << minContent << " at xp = " << xpom << ", t = " << t << endl; binCenter(maxBin, xpom, t); os << setw(34) << right << "maximum content = " << maxContent << " at xp = " << xpom << ", t = " << t << endl; } else { binCenter(minBin, Q2, W2, t); os << setw(34) << right << "minimum content = " << minContent << " at Q2 = " << Q2 << ", W2 = " << W2 << ", t = " << t << endl; binCenter(maxBin, Q2, W2, t); os << setw(34) << right << "maximum content = " << maxContent << " at Q2 = " << Q2 << ", W2 = " << W2 << ", t = " << t << endl; } os << setw(34) << right << "sum = " << sum << endl; os << endl; } os.flags(fmt); // restore I/O flags } double Table::InterpolateGridSpline(double x, double y, double z) const // Q2, W2, t { // // The algorithm was taken from Cristian Constantin Lalescu. // See http://arxiv.org/abs/0905.3564 for details. // // Grid points: 4, 6, or 8 // Spline order: 3,5 for order 4 // 3,5,7,9 for order 6 // 3,5,7,9,11,13 for order 8 // // // Find cell that refer to the position // int nx = m3DHisto->GetXaxis()->FindBin(x); int ny = m3DHisto->GetYaxis()->FindBin(y); int nz = m3DHisto->GetZaxis()->FindBin(z); // // Define the # of grid points depending on how far we are away // from the edge. If at the edge we fall back to linear interpolation // as provided by TH3. // There must be a smarter way doing this than the code below // int gridPoints = 0; if (nx-3 >= 1 && nx+4 <= m3DHisto->GetXaxis()->GetNbins() && ny-3 >= 1 && ny+4 <= m3DHisto->GetYaxis()->GetNbins() && nz-3 >= 1 && nz+4 <= m3DHisto->GetZaxis()->GetNbins()) { gridPoints = 8; } else if (nx-2 >= 1 && nx+3 <= m3DHisto->GetXaxis()->GetNbins() && ny-2 >= 1 && ny+3 <= m3DHisto->GetYaxis()->GetNbins() && nz-2 >= 1 && nz+3 <= m3DHisto->GetZaxis()->GetNbins()) { gridPoints = 6; } else if (nx-1 >= 1 && nx+2 <= m3DHisto->GetXaxis()->GetNbins() && ny-1 >= 1 && ny+2 <= m3DHisto->GetYaxis()->GetNbins() && nz-1 >= 1 && nz+2 <= m3DHisto->GetZaxis()->GetNbins()) { gridPoints = 4; } else { return m3DHisto->Interpolate(x,y,z); } // // Find bin centers // double xc = m3DHisto->GetXaxis()->GetBinCenter(nx); double yc = m3DHisto->GetYaxis()->GetBinCenter(ny); double zc = m3DHisto->GetZaxis()->GetBinCenter(nz); // // Define the scale for coordinate transformations // grid_spline expects x,y,z in bin units // double xscale = m3DHisto->GetXaxis()->GetBinWidth(1); double yscale = m3DHisto->GetYaxis()->GetBinWidth(1); double zscale = m3DHisto->GetZaxis()->GetBinWidth(1); // // Prepare grid spline alogorithm // double result, splineOrder; if (gridPoints == 8) { local_scal_3D<8> lf; for (int i=-3;i<=4;i++) { for(int j=-3;j<=4;j++) { lf(-3,i,j) = m3DHisto->GetBinContent(nx-3, ny+i, nz+j); lf(-2,i,j) = m3DHisto->GetBinContent(nx-2, ny+i, nz+j); lf(-1,i,j) = m3DHisto->GetBinContent(nx-1, ny+i, nz+j); lf( 0,i,j) = m3DHisto->GetBinContent(nx , ny+i, nz+j); lf( 1,i,j) = m3DHisto->GetBinContent(nx+1, ny+i, nz+j); lf( 2,i,j) = m3DHisto->GetBinContent(nx+2, ny+i, nz+j); lf( 3,i,j) = m3DHisto->GetBinContent(nx+3, ny+i, nz+j); lf( 4,i,j) = m3DHisto->GetBinContent(nx+4, ny+i, nz+j); } } splineOrder = 7; result = grid_spline(splineOrder,lf, (x-xc)/xscale,(y-yc)/yscale,(z-zc)/zscale); } else if (gridPoints == 6) { local_scal_3D<6> lf; for (int i=-2;i<=3;i++) { for(int j=-2;j<=3;j++) { lf(-2,i,j) = m3DHisto->GetBinContent(nx-2, ny+i, nz+j); lf(-1,i,j) = m3DHisto->GetBinContent(nx-1, ny+i, nz+j); lf( 0,i,j) = m3DHisto->GetBinContent(nx , ny+i, nz+j); lf( 1,i,j) = m3DHisto->GetBinContent(nx+1, ny+i, nz+j); lf( 2,i,j) = m3DHisto->GetBinContent(nx+2, ny+i, nz+j); lf( 3,i,j) = m3DHisto->GetBinContent(nx+3, ny+i, nz+j); } } splineOrder = 5; result = grid_spline(splineOrder,lf, (x-xc)/xscale,(y-yc)/yscale,(z-zc)/zscale); } else if (gridPoints == 4) { local_scal_3D<4> lf; for (int i=-1;i<=2;i++) { for(int j=-1;j<=2;j++) { lf(-1,i,j) = m3DHisto->GetBinContent(nx-1, ny+i, nz+j); lf( 0,i,j) = m3DHisto->GetBinContent(nx , ny+i, nz+j); lf( 1,i,j) = m3DHisto->GetBinContent(nx+1, ny+i, nz+j); lf( 2,i,j) = m3DHisto->GetBinContent(nx+2, ny+i, nz+j); } } splineOrder = 3; result = grid_spline(splineOrder,lf, (x-xc)/xscale,(y-yc)/yscale,(z-zc)/zscale); } else { cout << "Table::InterpolateGridSpline(): Error, illegal number of grid points." << endl; result = 0; } return result; } double Table::modInterpolation(double x, double y, double z) const{ // Q2, W2, t // // After testing many points: The best results is had for content in log and rest in lin. // However, if any of the bins that participate in the interpolation are zero // the interpolation has to be linear. // // Make sure the point is within the histogram: if(m3DHisto->GetXaxis()->GetBinCenter(1) > x || m3DHisto->GetXaxis()->GetBinCenter(m3DHisto->GetXaxis()->GetNbins()) < x || m3DHisto->GetYaxis()->GetBinCenter(1) > y || m3DHisto->GetYaxis()->GetBinCenter(m3DHisto->GetYaxis()->GetNbins()) < y || m3DHisto->GetZaxis()->GetBinCenter(1) > z || m3DHisto->GetZaxis()->GetBinCenter(m3DHisto->GetZaxis()->GetNbins()) < z ){ cout<<"Table::myInterpolation Error: point lies outside the limits of the table!"<GetXaxis()->FindBin(x); if( x < m3DHisto->GetXaxis()->GetBinCenter(lbx) ) lbx--; int ubx=lbx+1; int lby = m3DHisto->GetYaxis()->FindBin(y); if( y < m3DHisto->GetYaxis()->GetBinCenter(lby) ) lby--; int uby=lby+1; int lbz = m3DHisto->GetZaxis()->FindBin(z); if( z < m3DHisto->GetZaxis()->GetBinCenter(lbz) ) lbz--; int ubz=lbz+1; //The corresponding bin-centers: double ux=m3DHisto->GetXaxis()->GetBinCenter(ubx); double lx=m3DHisto->GetXaxis()->GetBinCenter(lbx); double uy=m3DHisto->GetYaxis()->GetBinCenter(uby); double ly=m3DHisto->GetYaxis()->GetBinCenter(lby); double uz=m3DHisto->GetZaxis()->GetBinCenter(ubz); double lz=m3DHisto->GetZaxis()->GetBinCenter(lbz); ux = isLogQ2() ? exp(ux) : ux; lx = isLogQ2() ? exp(lx) : lx; uy = isLogW2() ? exp(uy) : uy; ly = isLogW2() ? exp(ly) : ly; uz = isLogT() ? exp(uz) : uz; lz = isLogT() ? exp(lz) : lz; x = isLogQ2() ? exp(x) : x; y = isLogW2() ? exp(y) : y; z = isLogT() ? exp(z) : z; //Find the distance to the point: double xd = (x-lx)/(ux-lx); double yd = (y-ly)/(uy-ly); double zd = (z-lz)/(uz-lz); // Make a vector containing all the values of the 8 surrounding bins double v[8] = { m3DHisto->GetBinContent(lbx, lby, lbz), m3DHisto->GetBinContent(lbx, lby, ubz), m3DHisto->GetBinContent(lbx, uby, lbz), m3DHisto->GetBinContent(lbx, uby, ubz), m3DHisto->GetBinContent(ubx, lby, lbz), m3DHisto->GetBinContent(ubx, lby, ubz), m3DHisto->GetBinContent(ubx, uby, lbz), m3DHisto->GetBinContent(ubx, uby, ubz) }; bool logC=true; for(int i=0; i<8; i++){ if(isLogContent() and v[i] <= log(numeric_limits::min()*2) ) logC=false; if(!isLogContent() and v[i] == 0) logC=false; } // Make interpolation in log(content) except for when at least one of the points are zero. if(isLogContent() and !logC){ for(int i=0; i<8; i++){ if (v[i] <= log(numeric_limits::min()*2)) v[i] = 0; else v[i]=exp(v[i]); } } if(!isLogContent() and logC){ for(int i=0; i<8; i++) v[i]=log(v[i]); } // First make four 1D interpolations in the z-direction double i1 = v[0] * (1 - zd) + v[1] * zd; double i2 = v[2] * (1 - zd) + v[3] * zd; double j1 = v[4] * (1 - zd) + v[5] * zd; double j2 = v[6] * (1 - zd) + v[7] * zd; // Secondly, make two 1D interpolations in the y-direction using the values obtained. double w1 = i1 * (1 - yd) + i2 * yd; double w2 = j1 * (1 - yd) + j2 * yd; // Finaly, make 1D interpolation in the x-direction double result= w1 * (1-xd) + w2 * xd; //Reverse exp/log compensation to get real result back: if(isLogContent() and !logC){ if(result == 0) result=log(numeric_limits::min()); else result=log(result); } if(!isLogContent() and logC) result=exp(result); return result; } // // UPC version // double Table::modInterpolation(double x, double y) const{ // x, t // Make sure the point is within the histogram: if(m2DHisto->GetXaxis()->GetBinCenter(1) > x || m2DHisto->GetXaxis()->GetBinCenter(m2DHisto->GetXaxis()->GetNbins()) < x || m2DHisto->GetYaxis()->GetBinCenter(1) > y || m2DHisto->GetYaxis()->GetBinCenter(m2DHisto->GetYaxis()->GetNbins()) < y) { cout<<"Table::myInterpolation Error: point lies outside the limits of the table!"<GetXaxis()->FindBin(x); int bin_y = m2DHisto->GetYaxis()->FindBin(y); // Find quadrant of the bin we are in int quadrant = 0; double dx = m2DHisto->GetXaxis()->GetBinUpEdge(bin_x)-x; double dy = m2DHisto->GetYaxis()->GetBinUpEdge(bin_y)-y; if (dx<=m2DHisto->GetXaxis()->GetBinWidth(bin_x)/2 && dy<=m2DHisto->GetYaxis()->GetBinWidth(bin_y)/2) quadrant = 1; // upper right if (dx>m2DHisto->GetXaxis()->GetBinWidth(bin_x)/2 && dy<=m2DHisto->GetYaxis()->GetBinWidth(bin_y)/2) quadrant = 2; // upper left if (dx>m2DHisto->GetXaxis()->GetBinWidth(bin_x)/2 && dy>m2DHisto->GetYaxis()->GetBinWidth(bin_y)/2) quadrant = 3; // lower left if (dx<=m2DHisto->GetXaxis()->GetBinWidth(bin_x)/2 && dy>m2DHisto->GetYaxis()->GetBinWidth(bin_y)/2) quadrant = 4; // lower right double x1 = 0, x2 = 0, y1 = 0, y2 = 0; switch(quadrant) { case 1: x1 = m2DHisto->GetXaxis()->GetBinCenter(bin_x); y1 = m2DHisto->GetYaxis()->GetBinCenter(bin_y); x2 = m2DHisto->GetXaxis()->GetBinCenter(bin_x+1); y2 = m2DHisto->GetYaxis()->GetBinCenter(bin_y+1); break; case 2: x1 = m2DHisto->GetXaxis()->GetBinCenter(bin_x-1); y1 = m2DHisto->GetYaxis()->GetBinCenter(bin_y); x2 = m2DHisto->GetXaxis()->GetBinCenter(bin_x); y2 = m2DHisto->GetYaxis()->GetBinCenter(bin_y+1); break; case 3: x1 = m2DHisto->GetXaxis()->GetBinCenter(bin_x-1); y1 = m2DHisto->GetYaxis()->GetBinCenter(bin_y-1); x2 = m2DHisto->GetXaxis()->GetBinCenter(bin_x); y2 = m2DHisto->GetYaxis()->GetBinCenter(bin_y); break; case 4: x1 = m2DHisto->GetXaxis()->GetBinCenter(bin_x); y1 = m2DHisto->GetYaxis()->GetBinCenter(bin_y-1); x2 = m2DHisto->GetXaxis()->GetBinCenter(bin_x+1); y2 = m2DHisto->GetYaxis()->GetBinCenter(bin_y); break; } // Now find the bins we interpolate with int bin_x1 = m2DHisto->GetXaxis()->FindBin(x1); if (bin_x1<1) bin_x1=1; int bin_x2 = m2DHisto->GetXaxis()->FindBin(x2); if (bin_x2>m2DHisto->GetXaxis()->GetNbins()) bin_x2=m2DHisto->GetXaxis()->GetNbins(); int bin_y1 = m2DHisto->GetYaxis()->FindBin(y1); if (bin_y1<1) bin_y1=1; int bin_y2 = m2DHisto->GetYaxis()->FindBin(y2); if (bin_y2>m2DHisto->GetYaxis()->GetNbins()) bin_y2=m2DHisto->GetYaxis()->GetNbins(); // Get content int bin_q22 = m2DHisto->GetBin(bin_x2,bin_y2); int bin_q12 = m2DHisto->GetBin(bin_x1,bin_y2); int bin_q11 = m2DHisto->GetBin(bin_x1,bin_y1); int bin_q21 = m2DHisto->GetBin(bin_x2,bin_y1); double q11 = m2DHisto->GetBinContent(bin_q11); double q12 = m2DHisto->GetBinContent(bin_q12); double q21 = m2DHisto->GetBinContent(bin_q21); double q22 = m2DHisto->GetBinContent(bin_q22); // // As explained in the 3D version we interpolate on linear x, y // but on log content, except when 0's are involved. // bool logC = true; if ((isLogContent() && q11 <= log(numeric_limits::min()*2)) || (!isLogContent() && q11 <= 0)) logC = false; if ((isLogContent() && q12 <= log(numeric_limits::min()*2)) || (!isLogContent() && q12 <= 0)) logC = false; if ((isLogContent() && q21 <= log(numeric_limits::min()*2)) || (!isLogContent() && q21 <= 0)) logC = false; if ((isLogContent() && q22 <= log(numeric_limits::min()*2)) || (!isLogContent() && q22 <= 0)) logC = false; if(isLogContent() && !logC) { // 0's present, use linear content if (q11 <= log(numeric_limits::min()*2)) q11 = 0; else q11=exp(q11); if (q12 <= log(numeric_limits::min()*2)) q12 = 0; else q12=exp(q12); if (q21 <= log(numeric_limits::min()*2)) q21 = 0; else q21=exp(q21); if (q22 <= log(numeric_limits::min()*2)) q22 = 0; else q22=exp(q22); } if (!isLogContent() && logC) { q11 = log(q11); q12 = log(q12); q21 = log(q21); q22 = log(q22); } x = isLogX() ? exp(x) : x; x1 = isLogX() ? exp(x1) : x1; x2 = isLogX() ? exp(x2) : x2; y = isLogT() ? exp(y) : y; y1 = isLogT() ? exp(y1) : y1; y2 = isLogT() ? exp(y2) : y2; // Interpolation double d = 1.0*(x2-x1)*(y2-y1); double result = 1.0*q11/d*(x2-x)*(y2-y)+1.0*q21/d*(x-x1)*(y2-y)+1.0*q12/d*(x2-x)*(y-y1)+1.0*q22/d*(x-x1)*(y-y1); // Reverse exp/log compensation to get real result back: if (isLogContent() && !logC){ if (result == 0) result=log(numeric_limits::min()); else result=log(result); } if (!isLogContent() && logC) result=exp(result); return result; } void Table::setAutobackup(const char* prefix, int freq) { mBackupPrefix = string(prefix); mBackupFrequence = freq; } void Table::backup(int backupBin) { ostringstream backupFilenameStream; backupFilenameStream << mBackupPrefix.c_str() << "_backup." << static_cast(getpid()) << '.' << mID << '.' << backupBin << ".root"; string filename = backupFilenameStream.str(); TFile file(filename.c_str(),"RECREATE"); m3DHisto->Write(); file.Close(); if (filename != mLastBackupFilename) remove(mLastBackupFilename.c_str()); mLastBackupFilename = filename; time_t now = time(0); cout << "Table::backup(): autobackup performed, file = '" << mLastBackupFilename.c_str() << "', time = " << ctime(&now); } int Table::globalBin(int binx, int biny, int binz) const { int nbinx = m3DHisto->GetXaxis()->GetNbins(); int nbiny = m3DHisto->GetYaxis()->GetNbins(); return (binz-1)*nbinx*nbiny+(biny-1)*nbinx+(binx-1); } // // UPC version // int Table::globalBin(int binx, int biny) const { int nbinx = m3DHisto->GetXaxis()->GetNbins(); return (biny-1)*nbinx+(binx-1); } Index: trunk/src/FrangibleNucleus.cpp =================================================================== --- trunk/src/FrangibleNucleus.cpp (revision 369) +++ trunk/src/FrangibleNucleus.cpp (revision 370) @@ -1,204 +1,204 @@ //============================================================================== // FrangibleNucleus.cpp // -// Copyright (C) 2010-2013 Tobias Toll and Thomas Ullrich +// Copyright (C) 2010-2019 Tobias Toll and Thomas Ullrich // // This file is part of Sartre. // // 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. // 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, see . // // Author: Thomas Ullrich // Last update: // $Date$ // $Author$ //============================================================================== #include "FrangibleNucleus.h" #include "CNucleus.h" #include "Constants.h" #include "EventGeneratorSettings.h" #include "TRandom3.h" #define PR(x) cout << #x << " = " << (x) << endl; FrangibleNucleus::FrangibleNucleus() { mGeminiNucleus = 0; mExcitationEnergy = 0; } FrangibleNucleus& FrangibleNucleus::operator=(const FrangibleNucleus& gn) { if (this != &gn) { delete mGeminiNucleus; mProducts.clear(); Nucleus::operator=(gn); mExcitationEnergy = gn.mExcitationEnergy; copy(gn.mProducts.begin(), gn.mProducts.end(), mProducts.begin()); if (gn.mGeminiNucleus) mGeminiNucleus = new CNucleus(gn.mZ, gn.mA); else mGeminiNucleus = 0; } return *this; } FrangibleNucleus::FrangibleNucleus(const FrangibleNucleus& gn) : Nucleus(gn) { mExcitationEnergy = gn.mExcitationEnergy; copy(gn.mProducts.begin(), gn.mProducts.end(), mProducts.begin()); if (gn.mGeminiNucleus) mGeminiNucleus = new CNucleus(gn.mZ, gn.mA); else mGeminiNucleus = 0; } void FrangibleNucleus::init(unsigned int A) { Nucleus::init(A); if (mGeminiNucleus) delete mGeminiNucleus; mGeminiNucleus = 0; } void FrangibleNucleus::init(unsigned int A, bool enableBreakup) { Nucleus::init(A); if (mGeminiNucleus) delete mGeminiNucleus; // // Init Gemini. // if (enableBreakup) mGeminiNucleus = new CNucleus(mZ, mA); else mGeminiNucleus = 0; mExcitationEnergy = 0; } FrangibleNucleus::FrangibleNucleus(unsigned int A, bool enableBreakup) : Nucleus(A) { // // Init Gemini. // Only if requested, not needed otherwise. // if (enableBreakup) mGeminiNucleus = new CNucleus(mZ, mA); else mGeminiNucleus = 0; mExcitationEnergy = 0; } FrangibleNucleus::~FrangibleNucleus() { delete mGeminiNucleus; } void FrangibleNucleus::resetBreakup() { mExcitationEnergy = 0; mProducts.clear(); } int FrangibleNucleus::breakup(const TLorentzVector& dissSystem) { EventGeneratorSettings *settings = EventGeneratorSettings::instance(); // // Estimate excitation energy // Note that the dissSystem is given in units of 'per nucleon'. // Hence we have to multiply the excitation energy with A. // mExcitationEnergy = (dissSystem.M()-protonMass)*mA; double Ex = mExcitationEnergy; double maxEx = settings->maxNuclearExcitationEnergy(); if (Ex > maxEx) { if (settings->verboseLevel() > 1) cout << "FrangibleNucleus::breakup(): Actual excitation energy (" << Ex << ") exceeded upper limit (" << maxEx << "). Reset to maximum value." << endl; Ex = maxEx; } Ex *= 1000; // Gemini uses the total energy in MeV // // Setup excited nucleus // // Pass excitation energy and spin to Gemini mGeminiNucleus->setCompoundNucleus(Ex,mSpin); //specify the excitation energy and spin mGeminiNucleus->setVelocityCartesian(); // set initial velocity to zero (CMS) // Set the direction of the spin vector (random) TRandom3 *rndm = Settings::randomGenerator(); double phi = rndm->Uniform(2*M_PI); double theta = acos(rndm->Uniform(-1, 1)); CAngle spin(theta, phi); mGeminiNucleus->setSpinAxis(spin); // // Let the nucleus breakup // mGeminiNucleus->decay(); mProducts.clear(); if (mGeminiNucleus->abortEvent) { cout << "Nucleus::breakup(): Error, decay aborted in Gemini++." << endl; mGeminiNucleus->reset(); return 0; } int nfragments = mGeminiNucleus->getNumberOfProducts(); mProducts.resize(nfragments); for(int i=0; igetProducts(i); //set pointer to first stable product mProducts[i].Z = product->iZ; mProducts[i].A = product->iA; mProducts[i].emissionTime = product->getTime(); mProducts[i].p = product->getLorentzVector(); mProducts[i].p.Boost(dissSystem.BoostVector()); mProducts[i].name = product->getName(); if (product->iZ == 1 && product->iA == 1) mProducts[i].pdgId = 2212; // p else if (product->iZ == 0 && product->iA == 1) mProducts[i].pdgId = 2112; // n else mProducts[i].pdgId = pdgID(product->iZ, product->iA); } mGeminiNucleus->reset(); return nfragments; } const vector& FrangibleNucleus::breakupProducts() const { return mProducts; } void FrangibleNucleus::listBreakupProducts(ostream& os) const { TLorentzVector sys; cout << "Excitation energy = " << mExcitationEnergy << endl; cout << "Number of fragments = " << mProducts.size() << endl; for (unsigned int i=0; i. // // Author: Tobias Toll // Last update: // $Date$ // $Author$ //============================================================================== #include #include #include #include "Integrals.h" #include "Constants.h" #include "Nucleus.h" #include "DipoleModel.h" #include "AlphaStrong.h" #include "Math/IntegratorMultiDim.h" #include "Math/Functor.h" #include "TMath.h" #include "WaveOverlap.h" #include "Kinematics.h" #include "TableGeneratorSettings.h" #include "Enumerations.h" #include "IntegrandWrappers.h" #include "TF1.h" #include "TH1F.h" #include "cuba.h" #define PRf(x) printf(#x); printf("=%g \n", (x)); #define PRi(x) printf(#x); printf("=%d \n", (x)); #define PR(x) cout << #x << " = " << (x) << endl; using namespace std; Integrals::Integrals() { mIsInitialized=false; mRelativePrecisionOfIntegration = 0; mWaveOverlap = 0; mDipoleModel = 0; mDipoleModelForSkewednessCorrection = 0; mIntegralImT = 0; mIntegralImL = 0; mIntegralReT = 0; mIntegralReL = 0; mErrorImT = 0; mErrorImL = 0; mErrorReT = 0; mErrorReL = 0; mProbImT = 0; mProbImL = 0; mProbReT = 0; mProbReL = 0; mIntegralTForSkewedness = 0; mIntegralLForSkewedness = 0; mErrorTForSkewedness = 0; mErrorLForSkewedness = 0; TableGeneratorSettings* settings = TableGeneratorSettings::instance(); mVerbose=settings->verbose(); int VMId=settings->vectorMesonId(); mMV = settings->lookupPDG(VMId)->Mass(); mIsUPC = settings->UPC(); if (VMId==113 || VMId==333 || VMId == 443 || VMId == 553) { mWaveOverlap = new WaveOverlapVM; mWaveOverlap->setProcess(VMId); mWaveOverlap->setWaveOverlapFunctionParameters(VMId); if(mVerbose) mWaveOverlap->testBoostedGaussianParameters(VMId); } else if (VMId==22) { mWaveOverlap = new WaveOverlapDVCS; } else { cout << "Integrals::init(): Error, no exclusive production implemented for: "<< VMId << endl; exit(1); } DipoleModelType model=settings->dipoleModelType(); if (model==bSat) { mDipoleModel = new DipoleModel_bSat; } else if(model==bNonSat){ mDipoleModel = new DipoleModel_bNonSat; } else if (model==bCGC) { mDipoleModel = new DipoleModel_bCGC; } else { cout << "Integrals::init(): Error, model not implemented: "<< model << endl; exit(1); } mCalculateSkewedness=false; if(settings->A()==1 and settings->modesToCalculate()!=1 and settings->numberOfConfigurations()==1 and model==bSat) { mCalculateSkewedness=true; mDipoleModelForSkewednessCorrection = new DipoleModel_bNonSat; } mIsInitialized=true; } Integrals::Integrals(const Integrals& integrals) { mIsInitialized = integrals.mIsInitialized; mRelativePrecisionOfIntegration = integrals.mRelativePrecisionOfIntegration; if (typeid(*mWaveOverlap) == typeid(WaveOverlapDVCS)) mWaveOverlap = new WaveOverlapDVCS; else mWaveOverlap = new WaveOverlapVM; if (typeid(*mDipoleModel) == typeid(DipoleModel_bSat)) mDipoleModel = new DipoleModel_bSat; else if(typeid(*mDipoleModel) == typeid(DipoleModel_bNonSat)) mDipoleModel = new DipoleModel_bNonSat; else mDipoleModel = new DipoleModel_bCGC; if (typeid(*mDipoleModelForSkewednessCorrection) == typeid(DipoleModel_bNonSat)) mDipoleModel = new DipoleModel_bNonSat; mIntegralImT = integrals.mIntegralImT; mIntegralImL = integrals.mIntegralImL; mIntegralReT = integrals.mIntegralReT; mIntegralReL = integrals.mIntegralReL; mErrorImT = integrals.mErrorImT; mErrorImL = integrals.mErrorImL; mErrorReT = integrals.mErrorReT; mErrorReL = integrals.mErrorReL; mProbImT = integrals.mProbImT; mProbImL = integrals.mProbImL; mProbReT = integrals.mProbReT; mProbReL = integrals.mProbReL; mMV = integrals.mMV; } Integrals& Integrals::operator=(const Integrals& integrals) { if (this != &integrals) { delete mWaveOverlap; delete mDipoleModel; delete mDipoleModelForSkewednessCorrection; if (typeid(*mWaveOverlap) == typeid(WaveOverlapDVCS)) mWaveOverlap = new WaveOverlapDVCS; else mWaveOverlap = new WaveOverlapVM; if (typeid(*mDipoleModel) == typeid(DipoleModel_bSat)) mDipoleModel = new DipoleModel_bSat; else if (typeid(*mDipoleModel) == typeid(DipoleModel_bNonSat)) mDipoleModel = new DipoleModel_bNonSat; else mDipoleModel = new DipoleModel_bCGC; if (typeid(*mDipoleModelForSkewednessCorrection) == typeid(DipoleModel_bNonSat)) mDipoleModel = new DipoleModel_bNonSat; mIntegralImT = integrals.mIntegralImT; mIntegralImL = integrals.mIntegralImL; mIntegralReT = integrals.mIntegralReT; mIntegralReL = integrals.mIntegralReL; mIntegralImT = integrals.mIntegralImT; mIntegralImL = integrals.mIntegralImL; mIntegralReT = integrals.mIntegralReT; mIntegralReL = integrals.mIntegralReL; mErrorImT = integrals.mErrorImT; mErrorImL = integrals.mErrorImL; mErrorReT = integrals.mErrorReT; mErrorReL = integrals.mErrorReL; mProbImT = integrals.mProbImT; mProbImL = integrals.mProbImL; mProbReT = integrals.mProbReT; mProbReL = integrals.mProbReL; mMV = integrals.mMV; mIsInitialized = integrals.mIsInitialized; mRelativePrecisionOfIntegration = integrals.mRelativePrecisionOfIntegration; } return *this; } Integrals::~Integrals() { delete mWaveOverlap; delete mDipoleModel; if(mDipoleModelForSkewednessCorrection) delete mDipoleModelForSkewednessCorrection; } void Integrals::operator() (double t, double Q2, double W2) { unsigned int A=dipoleModel()->nucleus()->A(); //make sure the configurations have been generated: if (!mDipoleModel->configurationExists() and A!=1) { // do not use cout cout << "Integrals::init(): Error, configuration has not been generated. Stopping." << endl; exit(1); } if (setKinematicPoint(t, Q2, W2)) { if(A==1){ calculateEp(); if(mCalculateSkewedness){ calculateSkewedness(); } } else calculate(); } else { fillZeroes(); } } void Integrals::operator() (double t, double xpom) //UPC { unsigned int A=dipoleModel()->nucleus()->A(); //make sure the configurations have been generated: if (!mDipoleModel->configurationExists() and A!=1) { // do not use cout cout << "Integrals::init(): Error, configuration has not been generated. Stopping." << endl; exit(1); } if (setKinematicPoint(t, xpom)) { if(A==1){ calculateEp(); if(mCalculateSkewedness){ calculateSkewedness(); } } else calculate(); } else { fillZeroes(); } } void Integrals::fillZeroes(){ //Store the results mIntegralImT=0; mIntegralReT=0; mIntegralImL=0; mIntegralReL=0; //Store the errors: mErrorImT=0; mErrorImL=0; mErrorReT=0; mErrorReL=0; //Store the probabilities: mProbImT=0; mProbImL=0; mProbReT=0; mProbReL=0; } //*********EXCLUSIVE VECTOR MESONS OR DVCS: ******************************** void IntegralsExclusive::coherentIntegrals(double t, double Q2, double W2) { if(setKinematicPoint(t, Q2, W2)){ if (typeid(*mDipoleModel) == typeid(DipoleModel_bSat)){ //store present kinematic point: double xprobe=kinematicPoint[3]; dipoleModel()->createSigma_ep_LookupTable(xprobe); } calculateCoherent(); } else fillZeroes(); } void IntegralsExclusive::coherentIntegrals(double t, double xpom) { if(setKinematicPoint(t, xpom)){ if (typeid(*mDipoleModel) == typeid(DipoleModel_bSat)){ dipoleModel()->createSigma_ep_LookupTable(xpom); } calculateCoherent(); } else fillZeroes(); } IntegralsExclusive::IntegralsExclusive() { } IntegralsExclusive& IntegralsExclusive::operator=(const IntegralsExclusive& cobj) { if (this != &cobj) { Integrals::operator=(cobj); copy(cobj.kinematicPoint, cobj.kinematicPoint+4, kinematicPoint); } return *this; } IntegralsExclusive::IntegralsExclusive(const IntegralsExclusive& cobj) : Integrals(cobj) { copy(cobj.kinematicPoint, cobj.kinematicPoint+4, kinematicPoint); } bool IntegralsExclusive::setKinematicPoint(double t, double xpom) //UPC { bool result = true; kinematicPoint[0]=t; kinematicPoint[1]=0; //Q2 kinematicPoint[2]=0; //W2 is not used kinematicPoint[3]=xpom; return result; } bool IntegralsExclusive::setKinematicPoint(double t, double Q2, double W2) { bool result = true; kinematicPoint[0]=t; kinematicPoint[1]=Q2; kinematicPoint[2]=W2; double xprobe=Kinematics::xpomeron(t, Q2, W2, mMV); if (xprobe<0 || xprobe>1) result = false; kinematicPoint[3]=xprobe; return result; } void IntegralsExclusive::calculate() { // // This function calls a wrapper from where the // integral is calculated with the Cuhre method. // Pass this Integrals object as the fourth (void*) argument of the Cuhre function. // const double epsrel=1.e-2, epsabs=1e-12; const int flags=0, mineval=1e4, maxeval=1e9, key=0; int nregionsTIm, nevalTIm, failTIm; int nregionsTRe, nevalTRe, failTRe; int nregionsLIm, nevalLIm, failLIm; int nregionsLRe, nevalLRe, failLRe; double valTIm=0, errTIm=0, probTIm=0; double valLIm=0, errLIm=0, probLIm=0; double valTRe=0, errTRe=0, probTRe=0; double valLRe=0, errLRe=0, probLRe=0; const char* statefile=0; const int nvec=1; // double probabilityCutOff=1e-6; // // Do the integrations // Cuhre(4, 1, integrandWrapperTIm, this, nvec, epsrel, epsabs, flags, mineval, maxeval, key, statefile, 0, &nregionsTIm, &nevalTIm, &failTIm, &valTIm, &errTIm, &probTIm); if(failTIm!=0 and mVerbose) printf("IntegralsExclusive::calculate(): Warning: Integration TIm did not reach desired precision! Error code=%d \n", failTIm); // // For UPC, calculate only transverse polarisation case // if(!mIsUPC){ Cuhre(4, 1, integrandWrapperLIm, this, nvec, epsrel, epsabs, flags, mineval, maxeval, key, statefile, 0, &nregionsLIm, &nevalLIm, &failLIm, &valLIm, &errLIm, &probLIm); if(failLIm!=0 and mVerbose) printf("IntegralsExclusive::calculate(): Warning: Integration LIm did not reach desired precision! Error code=%d \n", failLIm); } Cuhre(4, 1, integrandWrapperTRe, this, nvec, epsrel, epsabs, flags, mineval, maxeval, key, statefile, 0, &nregionsTRe, &nevalTRe, &failTRe, &valTRe, &errTRe, &probTRe); if(failTRe!=0 and mVerbose) printf("IntegralsExclusive::calculate(): Warning: Integration TRe did not reach desired precision! Error code=%d \n", failTRe); // // For UPC, calculate only transverse polarisation case // if(!mIsUPC){ Cuhre(4, 1, integrandWrapperLRe, this, nvec, epsrel, epsabs, flags, mineval, maxeval, key, statefile, 0, &nregionsLRe, &nevalLRe, &failLRe, &valLRe, &errLRe, &probLRe); if(failLRe!=0 and mVerbose) printf("IntegralsExclusive::calculate(): Warning: Integration LRe did not reach desired precision! Error code=%d \n", failLRe); } // // Store the results: // mIntegralImT=valTIm; mIntegralReT=valTRe; mIntegralImL=valLIm; mIntegralReL=valLRe; // // Store the errors: // mErrorImT=errTIm; mErrorImL=errLIm; mErrorReT=errTRe; mErrorReL=errLRe; // // Store the probabilities: // mProbImT=probTIm; mProbImL=probLIm; mProbReT=probTRe; mProbReL=probLRe; } void IntegralsExclusive::calculateEp() { // // This function calls a wrapper from where the // integral is calculated with the Cuhre method. // Pass this Integrals object as the fourth (void*) argument of the Cuhre function. // const double epsrel=1.e-4, epsabs=1e-12; const int flags=0, maxeval=1e9, key=0; const int mineval=3e6; int nregionsT, nevalT, failT; int nregionsL, nevalL, failL; double valT=0, errT=0, probT=0; double valL=0, errL=0, probL=0; const char* statefile=0; const int nvec=1; // // Do the integrations // /* bool bContinue=true; bool isFirst=true; while(bContinue){ double valTOld=valT; Cuhre(4, 1, integrandWrapperTep, this, nvec, epsrel, epsabs, flags, mineval, maxeval, key, statefile, 0, &nregionsT, &nevalT, &failT, &valT, &errT, &probT); if(abs(valT-valTOld)/valT > epsrel){ mineval*=3; if(isFirst) mineval*=30; isFirst=false; if(mineval>1e4) PR(mineval); } else bContinue=false; } */ Cuhre(4, 1, integrandWrapperTep, this, nvec, epsrel, epsabs, flags, mineval, maxeval, key, statefile, 0, &nregionsT, &nevalT, &failT, &valT, &errT, &probT); if(failT!=0 and mVerbose) printf("IntegralsExclusive::calculateEp(): Warning: Integration T did not reach desired precision! Error code=%d \n", failT); /* if(errT/valT > epsrel) PR(errT/valT); if(errT < epsabs) PR(errT); if(probT>0.5) PR(probT); PR(nevalT); PR(nregionsT); */ // // For UPC, calculate only transverse polarisation case // if(!mIsUPC){ Cuhre(4, 1, integrandWrapperLep, this, nvec, epsrel, epsabs, flags, mineval, maxeval, key, statefile, 0, &nregionsL, &nevalL, &failL, &valL, &errL, &probL); if(failL!=0 and mVerbose) printf("IntegralsExclusive::calculateEp(): Warning: Integration L did not reach desired precision! Error code=%d \n", failL); } // // Store the results: // mIntegralImT=valT; mIntegralImL=valL; // // Store the errors: // mErrorImT=errT; mErrorImL=errL; // // Store the probabilities: // mProbImT=probT; mProbImL=probL; } void IntegralsExclusive::calculateSkewedness() { // // This function calls a wrapper from where the // integral is calculated with the Cuhre method. // Pass this Integrals object as the fourth (void*) argument of the Cuhre function. // const double epsrel=1.e-4, epsabs=1e-12; const int flags=0, maxeval=1e9, key=0; const int mineval=3e6; int nregionsT, nevalT, failT; int nregionsL, nevalL, failL; double valT=0, errT=0, probT=0; double valL=0, errL=0, probL=0; const char* statefile=0; const int nvec=1; // // Do the integrations // /* bool bContinue=true; bool isFirst=true; while(bContinue){ double valTOld=valT; Cuhre(4, 1, integrandWrapperTForSkewedness, this, nvec, epsrel, epsabs, flags, mineval, maxeval, key, statefile, 0, &nregionsT, &nevalT, &failT, &valT, &errT, &probT); if(abs(valT-valTOld)/valT > epsrel){ mineval*=3; if(isFirst) mineval*=30; isFirst=false; if(mineval>1e4) PR(mineval); } else bContinue=false; } */ Cuhre(4, 1, integrandWrapperTForSkewedness, this, nvec, epsrel, epsabs, flags, mineval, maxeval, key, statefile, 0, &nregionsT, &nevalT, &failT, &valT, &errT, &probT); if(failT!=0 and mVerbose) printf("IntegralsExclusive::calculateSkweedness(): Warning: Integration T did not reach desired precision! Error code=%d \n", failT); // // For UPC, calculate only transverse polarisation case // if(!mIsUPC){ Cuhre(4, 1, integrandWrapperLForSkewedness, this, nvec, epsrel, epsabs, flags, mineval, maxeval, key, statefile, 0, &nregionsL, &nevalL, &failL, &valL, &errL, &probL); if(failL!=0 and mVerbose) printf("IntegralsExclusive::calculateSkweedness(): Warning: Integration L did not reach desired precision! Error code=%d \n", failL); } // // Store the results: // mIntegralTForSkewedness=valT; mIntegralLForSkewedness=valL; // // Store the errors: // mErrorTForSkewedness=errT; mErrorLForSkewedness=errL; // // Store the probabilities: // mProbImTForSkewedness=probT; mProbImLForSkewedness=probL; } void IntegralsExclusive::calculateCoherent() { // // As calculate() but for the coherent case // const double epsrel=1e-6, epsabs=1e-12; const int flags=0, mineval=1e1, maxeval=1e9, key=0; int nregionsT, nevalT, failT; int nregionsL, nevalL, failL; double valT, errT, probT; double valL, errL, probL; const int nvec=1; const char* statefile=0; // // Do the integrations // Cuhre(3, 1, integrandWrapperCoherentAmplitudeT, this, nvec, epsrel, epsabs, flags, mineval, maxeval, key, statefile, 0, &nregionsT, &nevalT, &failT, &valT, &errT, &probT); if(failT!=0 and mVerbose) printf("IntegralsExclusive::calculateCoherent(): Warning: Integration T did not reach desired precision! Error code=%d \n", failT); Cuhre(3, 1, integrandWrapperCoherentAmplitudeL, this, nvec, epsrel, epsabs, flags, mineval, maxeval, key, statefile, 0, &nregionsL, &nevalL, &failL, &valL, &errL, &probL); if(failL!=0 and mVerbose) printf("IntegralsExclusive::calculateCoherent(): Warning: Integration L did not reach desired precision! Error code=%d \n", failL); // // Store the results // mIntegralImT=valT; mIntegralImL=valL; // // Store the errors // mErrorImT=errT; mErrorImL=errL; } // // The following functions are the Integrands in the Amplitudes: // double IntegralsExclusive::uiAmplitudeTIm(double b, double z, double r, double phi, double Q2, double xprobe, double Delta) { double cosArg = (b/hbarc)*Delta*cos(phi); double waveOverlap = mWaveOverlap->T(z, Q2, r); double dsigdb2 = dipoleModel()->dsigmadb2(r , b , phi, xprobe); double BesselJ0 = TMath::BesselJ0((1-z)*r*Delta/hbarc); double result=0.5*r/hbarc2*waveOverlap* BesselJ0*b*cos(cosArg)*dsigdb2; return result; } double IntegralsExclusive::uiAmplitudeTRe(double b, double z, double r, double phi, double Q2, double xprobe, double Delta) { double sinArg = b*Delta*cos(phi)/hbarc; double waveOverlap = mWaveOverlap->T(z, Q2, r); double dsigdb2 = dipoleModel()->dsigmadb2(r, b, phi, xprobe); double BesselJ0 = TMath::BesselJ0((1-z)*r*Delta/hbarc); double result=0.5*r/hbarc2*waveOverlap* BesselJ0*b*sin(sinArg)*dsigdb2; return result; } double IntegralsExclusive::uiAmplitudeLIm(double b, double z, double r, double phi, double Q2, double xprobe, double Delta) { double waveOverlap = mWaveOverlap->L(z, Q2, r); double cosArg = b*Delta*cos(phi)/hbarc; double dsigdb2 = dipoleModel()->dsigmadb2(r, b, phi, xprobe); double BesselJ0 = TMath::BesselJ0((1-z)*r*Delta/hbarc); double result=0.5*r/hbarc2*waveOverlap* BesselJ0*b*cos(cosArg)*dsigdb2; return result; } double IntegralsExclusive::uiAmplitudeLRe(double b, double z, double r, double phi, double Q2, double xprobe, double Delta) { double waveOverlap = mWaveOverlap->L(z, Q2, r); double sinArg = b*Delta*cos(phi)/hbarc; double dsigdb2 = dipoleModel()->dsigmadb2(r, b, phi, xprobe); double BesselJ0 = TMath::BesselJ0((1-z)*r*Delta/hbarc); double result=0.5*r/hbarc2*waveOverlap* BesselJ0*b*sin(sinArg)*dsigdb2; return result; } double IntegralsExclusive::uiCoherentAmplitudeT(double b, double z, double r, double Q2, double Delta) { double waveOverlap = mWaveOverlap->T(z, Q2, r); double BesselJ0r = TMath::BesselJ0((1-z)*r*Delta/hbarc); double BesselJ0b = TMath::BesselJ0(b*Delta/hbarc); double xprobe=kinematicPoint[3]; double dsigmadb2Mean=dipoleModel()->coherentDsigmadb2(r, b, xprobe); double result = M_PI*r*b/hbarc2*waveOverlap*BesselJ0r*BesselJ0b*dsigmadb2Mean; return result; } double IntegralsExclusive::uiCoherentAmplitudeL(double b, double z, double r, double Q2, double Delta) { double waveOverlap = mWaveOverlap->L(z, Q2, r); double BesselJ0r = TMath::BesselJ0((1-z)*r*Delta/hbarc); double BesselJ0b = TMath::BesselJ0(b*Delta/hbarc); double xprobe=kinematicPoint[3]; double dsigmadb2Mean=dipoleModel()->coherentDsigmadb2(r, b, xprobe); double result = M_PI*r*b/hbarc2*waveOverlap*BesselJ0r*BesselJ0b*dsigmadb2Mean; return result; } double IntegralsExclusive::uiAmplitudeTep(double b, double z, double r, double Q2, double xprobe, double Delta) { double waveOverlap = mWaveOverlap->T(z, Q2, r); double dsigdb2 = dipoleModel()->dsigmadb2ep(r , b, xprobe); double BesselJ0r = TMath::BesselJ0((1-z)*r*Delta/hbarc); double BesselJ0b = TMath::BesselJ0(b*Delta/hbarc); double result=0.5*r/hbarc2*waveOverlap*BesselJ0r*b*BesselJ0b*dsigdb2; result*=2*M_PI; return result; } double IntegralsExclusive::uiAmplitudeLep(double b, double z, double r, double Q2, double xprobe, double Delta) { double waveOverlap = mWaveOverlap->L(z, Q2, r); double dsigdb2 = dipoleModel()->dsigmadb2ep(r , b, xprobe); double BesselJ0r = TMath::BesselJ0((1-z)*r*Delta/hbarc); double BesselJ0b = TMath::BesselJ0(b*Delta/hbarc); double result=0.5*r/hbarc2*waveOverlap*BesselJ0r*b*BesselJ0b*dsigdb2; result*=2*M_PI; return result; } // // Only for calculating the lamdba for Skewedness Corrections: // double IntegralsExclusive::uiAmplitudeTForSkewedness(double b, double z, double r, double Q2, double xprobe, double Delta) { double waveOverlap = mWaveOverlap->T(z, Q2, r); double dsigdb2 = dipoleModelForSkewednessCorrection()->dsigmadb2ep(r , b, xprobe); double BesselJ0r = TMath::BesselJ0((1-z)*r*Delta/hbarc); double BesselJ0b = TMath::BesselJ0(b*Delta/hbarc); double result=0.5*r/hbarc2*waveOverlap*BesselJ0r*b*BesselJ0b*dsigdb2; result*=2*M_PI; return result; } double IntegralsExclusive::uiAmplitudeLForSkewedness(double b, double z, double r, double Q2, double xprobe, double Delta) { double waveOverlap = mWaveOverlap->L(z, Q2, r); double dsigdb2 = dipoleModelForSkewednessCorrection()->dsigmadb2ep(r, b, xprobe); double BesselJ0r = TMath::BesselJ0((1-z)*r*Delta/hbarc); double BesselJ0b = TMath::BesselJ0(b*Delta/hbarc); double result=0.5*r/hbarc2*waveOverlap*BesselJ0r*b*BesselJ0b*dsigdb2; result*=2*M_PI; return result; } Index: trunk/src/tableMerger.cpp =================================================================== --- trunk/src/tableMerger.cpp (revision 369) +++ trunk/src/tableMerger.cpp (revision 370) @@ -1,558 +1,558 @@ //============================================================================== // tableMerger.cpp // -// Copyright (C) 2010-2013 Tobias Toll and Thomas Ullrich +// Copyright (C) 2010-2019 Tobias Toll and Thomas Ullrich // // This file is part of Sartre. // // 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. // 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, see . // // Author: Thomas Ullrich // Last update: // $Date$ // $Author$ //============================================================================== // // Utility program to merge tables. // // Several checks are performed to ensure the integrity of the merged // tables but in any case the merged table(s) should be examined with // tableInspector. // // Usage: // tableMerger [-n] [-0] [-p prefix] file(s) ... // -n Do not create the new tables but perform all checks // -p prefix Set prefix for output files // -0 Do NOT copy bins with 0 content (ignore them) // Use when merging partially filled tables // -m List missing bins (if any) // // The output files are named _merged.root // where ID is the unique identifier of the table. // // Note it is a good idea to always check with option -n on first. // //============================================================================== #include "Table.h" #include #include #include #include #include #include #include #include #include "TFile.h" #include "TH2F.h" #include "TH3F.h" #define PR(x) cout << #x << " = " << (x) << endl; using namespace std; void usage(const char* prog) { cout << "Usage: " << prog << " [-n] [-0] [-p prefix] [-m] file(s) ..." << endl; cout << " -n Do not create the new tables but perform all checks" << endl; cout << " -p prefix Set prefix for output files" << endl; cout << " -0 Do NOT copy bins with 0 content (ignore them)" << endl; cout << " Use when merging partially filled tables" << endl; cout << " -m List missing bins (if any)" << endl; } class Flags { public: bool listMissingBins; bool noOutput; bool ignoreZero; string prefix; }; bool isUPC(uint64_t id) {return (id & (static_cast(1) << 46));} void createHistogramLists(vector& files, vector& all3DHistograms, vector& all2DHistograms) { for (unsigned i=0; iGet("table"); if (ptr == 0) { cout << "Error: failed retrieving table from file '" << files[i].c_str() << "'." << endl; exit(1); } uint64_t id = atoll(ptr->GetTitle()); if (isUPC(id)) { TH2F *histo = reinterpret_cast(ptr); histo->SetDirectory(0); all2DHistograms.push_back(histo); } else { TH3F *histo = reinterpret_cast(ptr); histo->SetDirectory(0); all3DHistograms.push_back(histo); } file->Close(); } } int merge3DHistos(Flags &flags, vector& allHistograms) { set idSet; for (unsigned i=0; iGetTitle()); idSet.insert(theID); } // // Store histos according to their ID // vector vectorID(idSet.size()); copy(idSet.begin(), idSet.end(), vectorID.begin()); vector > vectorHistos(vectorID.size()); for (unsigned int i=0; iGetTitle()); if (theID == vectorID[i]) vectorHistos[i].push_back(allHistograms[j]); } } cout << "Will merge: " << endl; for (unsigned int i=0; i " << vectorHistos[i].size() << " tables" << endl; // // Merge // for (unsigned int i=0; iGetXaxis()->GetBinWidth(1); double wy = refHisto->GetYaxis()->GetBinWidth(1); double wz = refHisto->GetZaxis()->GetBinWidth(1); bool notSameBinWidth = false; for (unsigned int j=1; jGetXaxis()->GetBinWidth(1) - wx) > numeric_limits::epsilon() || fabs(vectorHistos[i][j]->GetYaxis()->GetBinWidth(1) - wy) > numeric_limits::epsilon() || fabs(vectorHistos[i][j]->GetZaxis()->GetBinWidth(1) - wz) > numeric_limits::epsilon()) { cout << "Error: tables for id = " << vectorID[i] << " have different bin width. Cannot merge." << endl; notSameBinWidth = true; break; } } if (notSameBinWidth) continue; // // Range of new histogram // double lowerEdgeX = refHisto->GetXaxis()->GetXmin(); double upperEdgeX = refHisto->GetXaxis()->GetXmax(); double lowerEdgeY = refHisto->GetYaxis()->GetXmin(); double upperEdgeY = refHisto->GetYaxis()->GetXmax(); double lowerEdgeZ = refHisto->GetZaxis()->GetXmin(); double upperEdgeZ = refHisto->GetZaxis()->GetXmax(); for (unsigned int j=1; jGetXaxis()->GetXmin(), lowerEdgeX); upperEdgeX = max(vectorHistos[i][j]->GetXaxis()->GetXmax(), upperEdgeX); lowerEdgeY = min(vectorHistos[i][j]->GetYaxis()->GetXmin(), lowerEdgeY); upperEdgeY = max(vectorHistos[i][j]->GetYaxis()->GetXmax(), upperEdgeY); lowerEdgeZ = min(vectorHistos[i][j]->GetZaxis()->GetXmin(), lowerEdgeZ); upperEdgeZ = max(vectorHistos[i][j]->GetZaxis()->GetXmax(), upperEdgeZ); } // // New binning // int nbinX = static_cast((upperEdgeX-lowerEdgeX)/wx + 0.5); int nbinY = static_cast((upperEdgeY-lowerEdgeY)/wy + 0.5); int nbinZ = static_cast((upperEdgeZ-lowerEdgeZ)/wz + 0.5); // // Create new histogram // TH3F *mergedHisto = new TH3F("table", refHisto->GetTitle(), nbinX, lowerEdgeX, upperEdgeX, nbinY, lowerEdgeY, upperEdgeY, nbinZ, lowerEdgeZ, upperEdgeZ); // // Fill new histo // Here we also make sure that bin centers between old and new match. // double x, y, z, xx, yy, zz, cellContent; for (unsigned int k=0; kGetNbinsX(); int ny = vectorHistos[i][k]->GetNbinsY(); int nz = vectorHistos[i][k]->GetNbinsZ(); for (int ix = 1; ix <= nx; ix++) { for (int iy = 1; iy <= ny; iy++) { for (int iz = 1; iz <= nz; iz++) { // old table cellContent = vectorHistos[i][k]->GetBinContent(ix, iy, iz); if (flags.ignoreZero && cellContent == 0) continue; // ignore 0 content x = vectorHistos[i][k]->GetXaxis()->GetBinCenter(ix); y = vectorHistos[i][k]->GetYaxis()->GetBinCenter(iy); z = vectorHistos[i][k]->GetZaxis()->GetBinCenter(iz); // new table int globalBin = mergedHisto->FindBin(x, y, z); if (globalBin == -1) { cout << "Error while copying data from old to new table. Cannot find referring bin." << endl; return 1; } int kx, ky, kz; mergedHisto->GetBinXYZ(globalBin, kx, ky, kz); xx = mergedHisto->GetXaxis()->GetBinCenter(kx); yy = mergedHisto->GetYaxis()->GetBinCenter(ky); zz = mergedHisto->GetZaxis()->GetBinCenter(kz); if (fabs(xx-x) > numeric_limits::epsilon() || fabs(yy-y) > numeric_limits::epsilon() || fabs(zz-z) > numeric_limits::epsilon()) { cout << "Error while copying data from old to new table. Bin center mismatch." << endl; return 1; } mergedHisto->SetBinContent(kx, ky, kz, cellContent); } } } } // // At this point the merged histo is filled. // Last check is to look for "holes" in the new table. // int nEmpty = 0; int globalBin = 0; vector missingBins; for (int iz = 1; iz <= nbinZ; iz++) for (int iy = 1; iy <= nbinY; iy++) for (int ix = 1; ix <= nbinX; ix++) { if (mergedHisto->GetBinContent(ix, iy, iz) == 0) { nEmpty++; if (flags.listMissingBins) missingBins.push_back(globalBin); } globalBin++; } if (nEmpty) { cout << "Warning: the new merged table has " << nEmpty << " cells that are empty. This might indicate that\n"; cout << " there are not enough tables available to fully defines the full cubic range.\n"; cout << " Merged table (" << mergedHisto->GetTitle() << ") is not usable in Sartre." << endl; if (flags.listMissingBins) { cout << "List of missing/empty bins:" << endl; for (unsigned int k=0; kGetTitle() << "_merged.root"; string filename = flags.prefix + filenameStream.str(); TFile *hfile = new TFile(filename.c_str(),"RECREATE"); if (!hfile) { cout << "Error writing merged table. Cannot open file '" << filename.c_str() << "'." << endl; } else { mergedHisto->Write(); hfile->Close(); cout << "Merged table written to file '" << filename.c_str() << "'." << endl; delete mergedHisto; mergedHisto = 0; } } } cout << "All 3D tables processed." << endl; return 0; } int merge2DHistos(Flags &flags, vector& allHistograms) { set idSet; for (unsigned i=0; iGetTitle()); idSet.insert(theID); } // // Store histos according to their ID // vector vectorID(idSet.size()); copy(idSet.begin(), idSet.end(), vectorID.begin()); vector > vectorHistos(vectorID.size()); for (unsigned int i=0; iGetTitle()); if (theID == vectorID[i]) vectorHistos[i].push_back(allHistograms[j]); } } cout << "Will merge: " << endl; for (unsigned int i=0; i " << vectorHistos[i].size() << " tables" << endl; cout << "---------------------------------------------------------------------" << endl; // // Merge // for (unsigned int i=0; iGetXaxis()->GetBinWidth(1); double wy = refHisto->GetYaxis()->GetBinWidth(1); bool notSameBinWidth = false; for (unsigned int j=1; jGetXaxis()->GetBinWidth(1) - wx) > numeric_limits::epsilon() || fabs(vectorHistos[i][j]->GetYaxis()->GetBinWidth(1) - wy) > numeric_limits::epsilon() ) { cout << "Error: tables for id = " << vectorID[i] << " have different bin width. Cannot merge." << endl; notSameBinWidth = true; break; } } if (notSameBinWidth) continue; // // Range of new histogram // double lowerEdgeX = refHisto->GetXaxis()->GetXmin(); double upperEdgeX = refHisto->GetXaxis()->GetXmax(); double lowerEdgeY = refHisto->GetYaxis()->GetXmin(); double upperEdgeY = refHisto->GetYaxis()->GetXmax(); for (unsigned int j=1; jGetXaxis()->GetXmin(), lowerEdgeX); upperEdgeX = max(vectorHistos[i][j]->GetXaxis()->GetXmax(), upperEdgeX); lowerEdgeY = min(vectorHistos[i][j]->GetYaxis()->GetXmin(), lowerEdgeY); upperEdgeY = max(vectorHistos[i][j]->GetYaxis()->GetXmax(), upperEdgeY); } // // New binning // int nbinX = static_cast((upperEdgeX-lowerEdgeX)/wx + 0.5); int nbinY = static_cast((upperEdgeY-lowerEdgeY)/wy + 0.5); // // Create new histogram // TH2F *mergedHisto = new TH2F("table", refHisto->GetTitle(), nbinX, lowerEdgeX, upperEdgeX, nbinY, lowerEdgeY, upperEdgeY); // // Fill new histo // Here we also make sure that bin centers between old and new match. // double x, y, xx, yy, cellContent; for (unsigned int k=0; kGetNbinsX(); int ny = vectorHistos[i][k]->GetNbinsY(); for (int ix = 1; ix <= nx; ix++) { for (int iy = 1; iy <= ny; iy++) { // old table cellContent = vectorHistos[i][k]->GetBinContent(ix, iy); if (flags.ignoreZero && cellContent == 0) continue; // ignore 0 content x = vectorHistos[i][k]->GetXaxis()->GetBinCenter(ix); y = vectorHistos[i][k]->GetYaxis()->GetBinCenter(iy); // new table int globalBin = mergedHisto->FindBin(x, y); if (globalBin == -1) { cout << "Error while copying data from old to new table. Cannot find referring bin." << endl; return 1; } int kx, ky, kdummy; mergedHisto->GetBinXYZ(globalBin, kx, ky, kdummy); xx = mergedHisto->GetXaxis()->GetBinCenter(kx); yy = mergedHisto->GetYaxis()->GetBinCenter(ky); if (fabs(xx-x) > numeric_limits::epsilon() || fabs(yy-y) > numeric_limits::epsilon() ) { cout << "Error while copying data from old to new table. Bin center mismatch." << endl; return 1; } mergedHisto->SetBinContent(kx, ky, cellContent); } } } // // At this point the merged histo is filled. // Last check is to look for "holes" in the new table. // int nEmpty = 0; int globalBin = 0; vector missingBins; for (int iy = 1; iy <= nbinY; iy++) { for (int ix = 1; ix <= nbinX; ix++) { if (mergedHisto->GetBinContent(ix, iy) == 0) { nEmpty++; if (flags.listMissingBins) missingBins.push_back(globalBin); } globalBin++; } } if (nEmpty) { cout << "Warning: the new merged table has " << nEmpty << " cells that are empty. This might indicate that\n"; cout << " there are not enough tables available to fully defines the full square range.\n"; cout << " Merged table (" << mergedHisto->GetTitle() << ") is not usable in Sartre." << endl; if (flags.listMissingBins) { cout << "List of missing/empty bins:" << endl; for (unsigned int k=0; kGetTitle() << "_merged.root"; string filename = flags.prefix + filenameStream.str(); TFile *hfile = new TFile(filename.c_str(),"RECREATE"); if (!hfile) { cout << "Error writing merged table. Cannot open file '" << filename.c_str() << "'." << endl; } else { mergedHisto->Write(); hfile->Close(); cout << "Merged table written to file '" << filename.c_str() << "'." << endl; delete mergedHisto; mergedHisto = 0; } } } cout << "All 2D tables processed." << endl; return 0; } int main(int argc, char **argv) { Flags flags; // // Handle command line arguments // if (argc == 1) { usage(argv[0]); return 2; } flags.listMissingBins = false; flags.noOutput = false; flags.ignoreZero = false; int ch; while ((ch = getopt(argc, argv, "m0np:")) != -1) { switch (ch) { case 'm': flags.listMissingBins = true; break; case '0': flags.ignoreZero = true; break; case 'p': flags.prefix = string(optarg); break; case 'n': flags.noOutput = true; break; case '?': default: usage(argv[0]); return 2; break; } } if (optind == argc) { usage(argv[0]); return 2; } vector allFiles; for (int index = optind; index < argc; index++) allFiles.push_back(string(argv[index])); // // Open the files and get all tables/histograms to be merged // vector all3DHistograms; vector all2DHistograms; createHistogramLists(allFiles, all3DHistograms, all2DHistograms); if (all3DHistograms.size() && all3DHistograms.size()) { cout << "The given files contain 2D and 3D tables." << endl; cout << "Will do the 3D tables first then the 2D tables." << endl; } if (all3DHistograms.size()) { cout << "Starting process for 3D histograms (standard tables)" << endl; int rc = merge3DHistos(flags, all3DHistograms); if (rc != 0) { cout << "Errors during merging of 3D histos." << endl; return rc; } } if (all2DHistograms.size()) { cout << "Starting process for 2D histograms (UPC tables)" << endl; int rc = merge2DHistos(flags, all2DHistograms); if (rc != 0) { cout << "Errors during merging of 2D histos." << endl; return rc; } } return 0; } Index: trunk/src/WaveOverlap.cpp =================================================================== --- trunk/src/WaveOverlap.cpp (revision 369) +++ trunk/src/WaveOverlap.cpp (revision 370) @@ -1,274 +1,274 @@ //============================================================================== // WaveOverlap.cpp // -// Copyright (C) 2010-2018 Tobias Toll and Thomas Ullrich +// Copyright (C) 2010-2019 Tobias Toll and Thomas Ullrich // // This file is part of Sartre. // // 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. // 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, see . // // Author: Tobias Toll // Last update: // $Date$ // $Author$ //============================================================================== #include "WaveOverlap.h" #include "Constants.h" #include "TableGeneratorSettings.h" #include "DipoleModelParameters.h" #include "TMath.h" #include #include #include "TF1.h" #include "Math/Functor.h" #include "Math/IntegratorMultiDim.h" #include "Math/WrappedTF1.h" #include "Math/GaussIntegrator.h" using namespace std; #define PR(x) cout << #x << " = " << (x) << endl; WaveOverlap::WaveOverlap() { mParameters = new DipoleModelParameters(TableGeneratorSettings::instance()); } WaveOverlap::~WaveOverlap() {/* no op*/} // // VECTOR MESONS // WaveOverlapVM::WaveOverlapVM() { mNT = mRT2 = 0; mMf = 0; mMf2 = 0; mEf = 0; mMV = 0; mNL = mRL2 = 0; mBoostedGaussianMf = 0; } double WaveOverlapVM::uiNormT(const double* var){ double z=var[0]; double r=var[1]; double phi=transverseWaveFunction(r, z); //GeV0 double dphidr=dDrTransverseWaveFunction(r, z); //GeV1 return 3.*r/hbarc/(z*z*(1-z)*(1-z)) *(mMf2*phi*phi + (z*z + (1-z)*(1-z))*dphidr*dphidr); //GeV1 } double WaveOverlapVM::uiNormL(const double* var){ double z=var[0]; double r=var[1]; double phi=longitudinalWaveFunction(r, z); //GeV0 double d2phidr2=laplaceRLongitudinalWaveFunction(r, z); //GeV2 double term=mMV*phi + (mMf2*phi - d2phidr2)/(mMV*z*(1-z)); //GeV1 return 3.*r/hbarc*term*term; //GeV1 } double WaveOverlapVM::uiDecayWidth(double* var, double*) { double z=*var; double phi=longitudinalWaveFunction(0., z); //GeV0 double d2phidr2=laplaceRLongitudinalWaveFunction(0., z); //GeV0 double result = mEf*3./M_PI*(mMV*phi+(mMf2*phi-d2phidr2)/(mMV*z*(1-z))); //GeV1 return result; } void WaveOverlapVM::testBoostedGaussianParameters(int id) { // // This function calculates the resulting normalisation // and decay width resulting from the boosted gaussian parameters // and compare with the actual values. This can be used to // test or modify the boosted gaussian parameters. // // KMW paper hep-ph/0606272 Eqs. (24)-(28) // // Start with decay width: TF1 fDW("fDW", this, &WaveOverlapVM::uiDecayWidth, 0., 1., 0.); ROOT::Math::WrappedTF1 wfDW(fDW); ROOT::Math::GaussIntegrator giDW; giDW.SetFunction(wfDW); giDW.SetAbsTolerance(0.); giDW.SetRelTolerance(1e-5); double f_VL=giDW.Integral(0., 1.); //GeV PR(f_VL); cout<<"The e+e- decay width is: "<ee)="<<4*M_PI*alpha_em*alpha_em*f_VL*f_VL/3/mMV*1e6 <<" keV"<ee)=1.340 +- 0.018 keV"<ee)=5.55 +- 0.14 +- 0.02 keV"<ee)=1.27 +- 0.04 keV"<ee)=7.04 +- 0.06 keV"<boostedGaussianR2(val); mRT2 = mRL2; mNT = mParameters->boostedGaussianNT(val); mNL = mParameters->boostedGaussianNL(val); mBoostedGaussianMf = mParameters->boostedGaussianQuarkMass(val); mBoostedGaussianMf2 = mBoostedGaussianMf*mBoostedGaussianMf; } void WaveOverlapVM::setProcess(int val) { switch (val) { case 113: mMf = mParameters->quarkMass(1); mMV = 0.776; mEf = 1./sqrt(2.); break; case 333: mMf = mParameters->quarkMass(2); mMV = 1.019; mEf = 1./3.; break; case 443: mMf = mParameters->quarkMass(3); mMV = 3.096916; mEf = 2./3.; break; case 553: mMf = mParameters->quarkMass(4); mMV = 9.46; mEf = -1./3.; break; default: cerr << "WaveOverlap::setProcess(): error no such type: " << val << endl; break; } mMf2 = mMf*mMf; } // // DVCS // double WaveOverlapDVCS::T(double z, double Q2, double r) { // KMW paper hep-ph/0606272 Eq. 17 double term0, term1, term2; double result=0; for (int iFlav=0; iFlav<4; iFlav++) { double mf=mParameters->quarkMass(iFlav); double ef=quarkCharge[iFlav]; double eps2 = z*(1-z)*Q2 + mf*mf; double eps = sqrt(eps2); term0=2.*Nc/M_PI*alpha_em*ef*ef; term1=( z*z+(1-z)*(1-z) )* eps*TMath::BesselK1(eps*r/hbarc)*mf*TMath::BesselK1(mf*r/hbarc); term2=mf*mf*TMath::BesselK0(eps*r/hbarc)*TMath::BesselK0(mf*r/hbarc); result += term0*(term1+term2); } return result; } double WaveOverlapDVCS::L(double, double, double) {return 0;} Index: trunk/src/Kinematics.h =================================================================== --- trunk/src/Kinematics.h (revision 369) +++ trunk/src/Kinematics.h (revision 370) @@ -1,105 +1,105 @@ //============================================================================== // Kinematics.h // -// Copyright (C) 2010-2017 Tobias Toll and Thomas Ullrich +// Copyright (C) 2010-2019 Tobias Toll and Thomas Ullrich // // This file is part of Sartre. // // 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. // 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, see . // // Author: Thomas Ullrich // Last update: // $Date$ // $Author$ // //------------------------------------------------------------------------------ // // Note that Kinematics is only meant for ep and eA diffactive events. // It is not applicable for UPC kinematics. Use UpcKinematics instead. // //============================================================================== #ifndef Kinematics_h #define Kinematics_h #include "Constants.h" #include "Settings.h" #include "TLorentzVector.h" #include "Math/IFunction.h" class Kinematics { public: static double xprobe(double Q2, double W2, double vmM); static TLorentzVector electronBeam(double eE, bool upc = false); static TLorentzVector hadronBeam(double eH); static double s(const TLorentzVector& e, const TLorentzVector& p); static double s(double eE, double hE, bool upc = false); static double x(double Q2, double W2); static double y(double Q2, double x, double s); static double ymin(double s, double vmM); static double ymax(double s, double vmM); static double W2(double Q2, double x); static double W2(double Q2, double xprobe, double vmM); static double W2min(double vmM); static double W2max(double s); static double Q2min(double y); static double Q2max(double s); static double xpomeron(double t, double Q2, double W2, double vmM); static double tmax(double xpom); // often referred to as tmin implying min |T| static double tmax(double t, double Q2, double W2, double vmM); static double tmin(double hE); // the smallest t value possible static double Egamma(double xpom, double t, double vmM, double hBeamEnergy, double eBeamEnergy, double MY2minusM2 = 0); static bool validUPC(double hBeamEnergy, double eBeamEnergy, double t, double xpom, double vmMass, bool verbose = false); // UPC only static bool valid(double s, double t, double Q2, double W2, double vmMass, bool useTrueXp = false, bool verbose = false); static bool error(); static double xpomMin(double massVM, double t, TLorentzVector hBeam, TLorentzVector eBeam, double MY2minusM2 = 0); // UPC only private: static double xpomMin(double s, double vmM, double t); // UPC only private: static bool mError; static double mXpomMin; static double mTold; static bool mXpomMinIsEvaluated; }; //------------------------------------------------------------------------------- // // Helper class needed to find root in // Kinematics::validUPC() // //------------------------------------------------------------------------------- class LowerXpomeronFormula : public ROOT::Math::IBaseFunctionOneDim { public: double DoEval(double) const; ROOT::Math::IBaseFunctionOneDim* Clone() const; void calculateValidRange(double&, double&); public: double mT; double mVmMass2; double mXpomMin; double mMY2; TLorentzVector mElectronBeam; TLorentzVector mHadronBeam; double mMY2minusM2; }; #endif Index: trunk/src/Sartre.cpp =================================================================== --- trunk/src/Sartre.cpp (revision 369) +++ trunk/src/Sartre.cpp (revision 370) @@ -1,1012 +1,1012 @@ //============================================================================== // Sartre.cpp // -// Copyright (C) 2010-2018 Tobias Toll and Thomas Ullrich +// Copyright (C) 2010-2019 Tobias Toll and Thomas Ullrich // // This file is part of Sartre. // // 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. // 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, see . // // Author: Thomas Ullrich // Last update: // $Date$ // $Author$ //============================================================================== // // Note: // When not using runcards, the user must first create an instance of Sartre // then get the settings via one of: // Sartre::runSettings() // EventGeneratorSettings::instance() // Once init() is called settings cannot be changed any more. //============================================================================== #include "Version.h" #include "Kinematics.h" #include "Sartre.h" #include "ModeFinderFunctor.h" #include "Math/BrentMinimizer1D.h" #include "Math/IntegratorMultiDim.h" #include "Math/GSLMinimizer.h" #include "Math/Functor.h" #include "TUnuranMultiContDist.h" #include #include #include #include "TH2D.h" #include "TFile.h" using namespace std; #define PR(x) cout << #x << " = " << (x) << endl; Sartre::Sartre() { mIsInitialized = false; mCurrentEvent = 0; mNucleus = 0; mUpcNucleus= 0; mSettings = 0; mPDF_Functor = 0; mPDF = 0; mEventCounter = 0; mTriesCounter = 0; mTotalCrossSection = 0; mCrossSection = 0; mTableCollection = 0; mProtonTableCollection = 0; mUnuran = 0; mEvents = 0; mTries = 0; mS = 0; mA = 0; } Sartre::~Sartre() { delete mNucleus; delete mUpcNucleus; delete mPDF_Functor; delete mPDF; delete mCrossSection; if (mTableCollection != mProtonTableCollection) { delete mTableCollection; delete mProtonTableCollection; } else delete mTableCollection; delete mUnuran; } bool Sartre::init(const char* runcard) { mStartTime = time(0); bool ok; // // Reset member variables. // Note that one instance of Sartre should be able to get // initialized multiple times. // mEvents = 0; mTries = 0; mTotalCrossSection = 0; // // Print header // string ctstr(ctime(&mStartTime)); ctstr.erase(ctstr.size()-1, 1); cout << "/========================================================================\\" << endl; cout << "| |" << endl; cout << "| Sartre, Version " << setw(54) << left << VERSION << right << '|' << endl; cout << "| |" << endl; cout << "| An event generator for exclusive diffractive vector meson production |" << endl; cout << "| in ep and eA collisions based on the dipole model. |" << endl; cout << "| |" << endl; - cout << "| Copyright (C) 2010-2018 Tobias Toll and Thomas Ullrich |" << endl; + cout << "| Copyright (C) 2010-2019 Tobias Toll and Thomas Ullrich |" << endl; cout << "| |" << endl; cout << "| This program is free software: you can redistribute it and/or modify |" << endl; cout << "| it under the terms of the GNU General Public License as published by |" << endl; cout << "| the Free Software Foundation, either version 3 of the License, or |" << endl; cout << "| any later version. |" << endl; cout << "| |" << endl; cout << "| Code compiled on " << setw(12) << left << __DATE__; cout << setw(41) << left << __TIME__ << right << '|' << endl; cout << "| Run started at " << setw(55) << left << ctstr.c_str() << right << '|' << endl; cout << "\\========================================================================/" << endl; mSettings = EventGeneratorSettings::instance(); // EventGeneratorSettings is a singleton // // Read runcard if available // if (runcard) { if (!mSettings->readSettingsFromFile(runcard)) { cout << "Error, reading runcard '" << runcard << "'. File doesn't exist or is not readable." << endl; exit(1); } else cout << "Runcard is '" << runcard << "'." << endl; } else cout << "No runcard provided." << endl; // // Set beam particles and center of mass energy // Note, that if we are in UPC mode the electron // is actually treated as the hadron beam, i.e. // the mass is the proton mass. // mElectronBeam = mSettings->eBeam(); mHadronBeam = mSettings->hBeam(); mS = Kinematics::s(mElectronBeam, mHadronBeam); mA = mSettings->A(); bool allowBreakup = mSettings->enableNuclearBreakup(); if (mA == 1) allowBreakup = false; if (allowBreakup) { if (!getenv("SARTRE_DIR")) { cout << "Error, environment variable 'SARTRE_DIR' is not defined. It is required\n" "to locate tables needed for the generation if nuclear breakups." << endl; exit(1); } } if (mNucleus) delete mNucleus; mNucleus = new FrangibleNucleus(mA, allowBreakup); if (mSettings->UPC()) { if (mUpcNucleus) delete mUpcNucleus; mUpcNucleus = new FrangibleNucleus(mSettings->UPCA(), allowBreakup); } string upcNucleusName; if (mSettings->UPC()) { upcNucleusName = mUpcNucleus->name(); cout << "Sartre is running in UPC mode" << endl; cout << "Hadron 1 beam species: " << mNucleus->name() << " (" << mA << ")" << endl; cout << "Hadron 1 beam: " << mHadronBeam << endl; cout << "Hadron 2 beam species: " << upcNucleusName << " (" << mSettings->UPCA() << ")" << endl; cout << "Hadron 2 beam: " << mElectronBeam << endl; } else { cout << "Hadron beam species: " << mNucleus->name() << " (" << mA << ")" << endl; cout << "Hadron beam: " << mHadronBeam << endl; cout << "Electron beam: " << mElectronBeam << endl; } // // Get details about the processes and models // mDipoleModelType = mSettings->dipoleModelType(); mDipoleModelParameterSet = mSettings->dipoleModelParameterSet(); mVmID = mSettings->vectorMesonId(); cout << "Dipole model: " << mSettings->dipoleModelName().c_str() << endl; cout << "Dipole model parameter set: " << mSettings->dipoleModelParameterSetName().c_str() << endl; cout << "Process is "; if (mSettings->UPC()) { cout << mNucleus->name() << " + " << upcNucleusName << " -> " << mNucleus->name() << "' + " << upcNucleusName << "' + "; } else { if (mA > 1) cout << "e + " << mNucleus->name() << " -> e' + " << mNucleus->name() << "' + "; else cout << "e + p -> e' + p' + "; } TParticlePDG *vectorMesonPDG = mSettings->lookupPDG(mVmID); cout << vectorMesonPDG->GetName() << endl; // // Print-out seed for reference // cout << "Random generator seed: " << mSettings->seed() << endl; // // Load in the tables containing the amplitude moments // if (!getenv("SARTRE_DIR")) { cout << "Error, required environment variable 'SARTRE_DIR' is not defined." << endl; exit(1); } if (mTableCollection) delete mTableCollection; mTableCollection = new TableCollection; ok = mTableCollection->init(mA, mDipoleModelType, mDipoleModelParameterSet, mVmID); if (!ok) { cout << "Error, could not initialize lookup tables for requested process." << endl; return false; } // // Load in the p tables for the lambda lookup tables (or to calculate lambda if not available) // if (mSettings->correctForRealAmplitude() || mSettings->correctSkewedness()) { if (mA == 1) { mProtonTableCollection = mTableCollection; } else { if (mProtonTableCollection) delete mProtonTableCollection; mProtonTableCollection = new TableCollection; ok = mProtonTableCollection->init(1, mDipoleModelType, mDipoleModelParameterSet, mVmID); if (!ok) { cout << "Error: could not initialize proton lookup tables for requested process." << endl; cout << " These tables are needed for skewedness and real amplitude corrections." << endl; return false; } } } else mProtonTableCollection = 0; // // Kinematic limits and generator range // // There are 3 ranges we have to deal with // 1. the kinematic range requested by the user // if given. // The user can only control Q2 and W but not t. // For UPC that's xpom. // 2. the range of the table(s) // 3. the kinematically allowed range // // Of course (3) is more complex than a simple cube/square. // However, we deal with the detailed shape of the kinematic // range later using Kinematics::valid() when we generate the // individual events. // For setting up UNU.RAN we have to get the cubic/square // envelope that satifies (1)-(3). // Note, that they are correlated which makes the order // in which we do things a bit tricky. // // // Step 1: // Set the limits to that of the table(s). // Note, the indices 0-2 refer to t, Q2, and W2. // For UPC we have only t and xpom. // if (mSettings->UPC()) { mLowerLimit[0] = mTableCollection->minT(); mUpperLimit[0] = mTableCollection->maxT(); mLowerLimit[1] = mTableCollection->minX(); mUpperLimit[1] = mTableCollection->maxX(); mLowerLimit[2] = mUpperLimit[2] = 0; } else { mLowerLimit[0] = mTableCollection->minT(); mUpperLimit[0] = mTableCollection->maxT(); mLowerLimit[1] = mTableCollection->minQ2(); mUpperLimit[1] = mTableCollection->maxQ2(); mLowerLimit[2] = mTableCollection->minW2(); mUpperLimit[2] = mTableCollection->maxW2(); } // // Step 2: // Kinematic limits might overrule boundaries from step 1 // if (mSettings->UPC()) { double kineXpomMin = Kinematics::xpomMin(vectorMesonPDG->Mass(), mUpperLimit[0], mHadronBeam, mElectronBeam); double kineXpomMax = 1; mLowerLimit[1] = max(kineXpomMin, mLowerLimit[1]); mUpperLimit[1] = min(mUpperLimit[1], kineXpomMax); double kineTmax = Kinematics::tmax(kineXpomMin); double kineTmin = Kinematics::tmin(mHadronBeam.E()); mLowerLimit[0] = max(kineTmin, mLowerLimit[0]); mUpperLimit[0] = min(mUpperLimit[0], kineTmax); } else { // double kineYmax = Kinematics::ymax(mS, vectorMesonPDG->Mass()); double kineYmin = Kinematics::ymin(mS, vectorMesonPDG->Mass()); double kineQ2min = Kinematics::Q2min(kineYmin); double kineQ2max = Kinematics::Q2max(mS); double kineW2min = Kinematics::W2min(vectorMesonPDG->Mass()); double kineW2max = Kinematics::W2max(mS); kineQ2min = max(kineQ2min, mLowerLimit[1]); kineQ2max = min(kineQ2max, mUpperLimit[1]); kineW2min = max(kineW2min, mLowerLimit[2]); kineW2max = min(kineW2max, mUpperLimit[2]); double kineXPmin = Kinematics::xpomeron(0, kineQ2min, kineW2max, vectorMesonPDG->Mass()); // first arg (t) set to 0 (recursive) double kineTmax = Kinematics::tmax(kineXPmin); double kineTmin = Kinematics::tmin(mHadronBeam.E()); mLowerLimit[0] = max(kineTmin, mLowerLimit[0]); mUpperLimit[0] = min(mUpperLimit[0], kineTmax); mLowerLimit[1] = max(kineQ2min, mLowerLimit[1]); mUpperLimit[1] = min(mUpperLimit[1], kineQ2max); mLowerLimit[2] = max(kineW2min, mLowerLimit[2]); mUpperLimit[2] = min(mUpperLimit[2], kineW2max); } // // Step 3: // Deal with user provided limits. // User settings are ignored (switched off) if min >= max. // if (mSettings->UPC()) { if (mSettings->xpomMin() < mSettings->xpomMax()) { if (mSettings->xpomMin() < mLowerLimit[1]) { cout << "Warning, requested lower limit of xpomeron (" << mSettings->xpomMin() << ") " << "is smaller than limit given by lookup tables and/or kinematic range (" << mLowerLimit[1] << "). "; cout << "Limit has no effect." << endl; } else { mLowerLimit[1] = mSettings->xpomMin(); } if (mSettings->xpomMax() > mUpperLimit[1]) { cout << "Warning, requested upper limit of xpomeron (" << mSettings->xpomMax() << ") " << "exceeds limit given by lookup tables and/or kinematic range (" << mUpperLimit[1] << "). "; cout << "Limit has no effect." << endl; } else { mUpperLimit[1] = mSettings->xpomMax(); } } } else { if (mSettings->W2min() < mSettings->W2max()) { // W2 first if (mSettings->W2min() < mLowerLimit[2]) { cout << "Warning, requested lower limit of W (" << mSettings->Wmin() << ") " << "is smaller than limit given by lookup tables and/or kinematic range (" << sqrt(mLowerLimit[2]) << "). "; cout << "Limit has no effect." << endl; } else { mLowerLimit[2] = mSettings->W2min(); } if (mSettings->W2max() > mUpperLimit[2]) { cout << "Warning, requested upper limit of W (" << mSettings->Wmax() << ") " << "exceeds limit given by lookup tables and/or kinematic range (" << sqrt(mUpperLimit[2]) << "). "; cout << "Limit has no effect." << endl; } else { mUpperLimit[2] = mSettings->W2max(); } } if (mSettings->Q2min() < mSettings->Q2max()) { // Q2 if (mSettings->Q2min() < mLowerLimit[1]) { cout << "Warning, requested lower limit of Q2 (" << mSettings->Q2min() << ") " << "is smaller than limit given by lookup tables and/or kinematic range (" << mLowerLimit[1] << "). "; cout << "Limit has no effect." << endl; } else { mLowerLimit[1] = mSettings->Q2min(); // ????? kineXPmin = Kinematics::xpomeron(0, kineQ2min, kineW2max, vectorMesonPDG->Mass()); // new Q2min changes tmax // ????? mUpperLimit[0] = min(mUpperLimit[0], Kinematics::tmax(kineXPmin)); } if (mSettings->Q2max() > mUpperLimit[1]) { cout << "Warning, requested upper limit of Q2 (" << mSettings->Q2max() << ") " << "exceeds limit given by lookup tables and/or kinematic range (" << mUpperLimit[1] << "). "; cout << "Limit has no effect." << endl; } else { mUpperLimit[1] = mSettings->Q2max(); } } } // // Check if any phase space is left // if (mLowerLimit[0] >= mUpperLimit[0]) { cout << "Invalid range in t: t=[" << mLowerLimit[0] << ", " << mUpperLimit[0] << "]." << endl; exit(1); } if (mLowerLimit[1] >= mUpperLimit[1]) { if (mSettings->UPC()) cout << "Invalid range in xpomeron: xpomeron=["; else cout << "Invalid range in Q2: Q2=["; cout << mLowerLimit[1] << ", " << mUpperLimit[1] << "]." << endl; exit(1); } if (!mSettings->UPC() && mLowerLimit[2] >= mUpperLimit[2]) { cout << "Invalid range in W: W=[" << sqrt(mLowerLimit[2]) << ", " << sqrt(mUpperLimit[2]) << "]." << endl; exit(1); } // // Print-out limits (all verbose levels) // if (mSettings->verbose()) { cout << "Kinematic limits used for event generation:" << endl; if (mSettings->UPC()) { cout << setw(10) << " t=[" << mLowerLimit[0] << ", " << mUpperLimit[0] << "]" << endl; cout << setw(10) << "xpom=[" << mLowerLimit[1] << ", " << mUpperLimit[1] << "]" << endl; } else { cout << setw(10) << " t=[" << mLowerLimit[0] << ", " << mUpperLimit[0] << "]" << endl; cout << setw(10) << "Q2=[" << mLowerLimit[1] << ", " << mUpperLimit[1] << "]" << endl; cout << setw(10) << " W=[" << sqrt(mLowerLimit[2]) << ", " << sqrt(mUpperLimit[2]) << "]" << endl; } } // // Check if the lambda table covers the kinematic range // or if we have to calculate lambda from the p mean_A table // directly. // This is just to inform the user, no action is taken. // Here we assume that transverse and longitudinal tables // always have the same range and vheck only one. // // If even the p mean_A table is not big enough we switch // corrections off and inform the user. // if (mProtonTableCollection) { bool lambdaTableExists, tooSmallLambda, tooSmallMean; if (mSettings->UPC()) { lambdaTableExists = mProtonTableCollection->tableExists(lambda_A); tooSmallLambda = !mProtonTableCollection->available(mLowerLimit[1]+numeric_limits::epsilon(), mLowerLimit[0]+numeric_limits::epsilon(), lambda_A) || !mProtonTableCollection->available(mLowerLimit[1]+numeric_limits::epsilon(), mUpperLimit[2]-numeric_limits::epsilon(), lambda_A) || !mProtonTableCollection->available(mLowerLimit[1]+numeric_limits::epsilon(), mLowerLimit[0]+numeric_limits::epsilon(), lambda_A) || !mProtonTableCollection->available(mLowerLimit[1]+numeric_limits::epsilon(), mUpperLimit[2]-numeric_limits::epsilon(), lambda_A) || !mProtonTableCollection->available(mUpperLimit[1]-numeric_limits::epsilon(), mLowerLimit[0]+numeric_limits::epsilon(), lambda_A) || !mProtonTableCollection->available(mUpperLimit[1]-numeric_limits::epsilon(), mUpperLimit[2]-numeric_limits::epsilon(), lambda_A) || !mProtonTableCollection->available(mUpperLimit[1]-numeric_limits::epsilon(), mLowerLimit[0]+numeric_limits::epsilon(), lambda_A) || !mProtonTableCollection->available(mUpperLimit[1]-numeric_limits::epsilon(), mUpperLimit[2]-numeric_limits::epsilon(), lambda_A); tooSmallMean = !mProtonTableCollection->available(mLowerLimit[1]+numeric_limits::epsilon(), mLowerLimit[0]+numeric_limits::epsilon(), mean_A) || !mProtonTableCollection->available(mLowerLimit[1]+numeric_limits::epsilon(), mUpperLimit[2]-numeric_limits::epsilon(), mean_A) || !mProtonTableCollection->available(mLowerLimit[1]+numeric_limits::epsilon(), mLowerLimit[0]+numeric_limits::epsilon(), mean_A) || !mProtonTableCollection->available(mLowerLimit[1]+numeric_limits::epsilon(), mUpperLimit[2]-numeric_limits::epsilon(), mean_A) || !mProtonTableCollection->available(mUpperLimit[1]-numeric_limits::epsilon(), mLowerLimit[0]+numeric_limits::epsilon(), mean_A) || !mProtonTableCollection->available(mUpperLimit[1]-numeric_limits::epsilon(), mUpperLimit[2]-numeric_limits::epsilon(), mean_A) || !mProtonTableCollection->available(mUpperLimit[1]-numeric_limits::epsilon(), mLowerLimit[0]+numeric_limits::epsilon(), mean_A) || !mProtonTableCollection->available(mUpperLimit[1]-numeric_limits::epsilon(), mUpperLimit[2]-numeric_limits::epsilon(), mean_A); } else { lambdaTableExists = mProtonTableCollection->tableExists(transverse, lambda_A); tooSmallLambda = !mProtonTableCollection->available(mLowerLimit[1]+numeric_limits::epsilon(), mLowerLimit[2]+numeric_limits::epsilon(), mLowerLimit[0]+numeric_limits::epsilon(), transverse, lambda_A) || !mProtonTableCollection->available(mLowerLimit[1]+numeric_limits::epsilon(), mUpperLimit[2]-numeric_limits::epsilon(), mLowerLimit[0]+numeric_limits::epsilon(), transverse, lambda_A) || !mProtonTableCollection->available(mLowerLimit[1]+numeric_limits::epsilon(), mLowerLimit[2]+numeric_limits::epsilon(), mUpperLimit[0]-numeric_limits::epsilon(), transverse, lambda_A) || !mProtonTableCollection->available(mLowerLimit[1]+numeric_limits::epsilon(), mUpperLimit[2]-numeric_limits::epsilon(), mUpperLimit[0]-numeric_limits::epsilon(), transverse, lambda_A) || !mProtonTableCollection->available(mUpperLimit[1]-numeric_limits::epsilon(), mLowerLimit[2]+numeric_limits::epsilon(), mLowerLimit[0]+numeric_limits::epsilon(), transverse, lambda_A) || !mProtonTableCollection->available(mUpperLimit[1]-numeric_limits::epsilon(), mUpperLimit[2]-numeric_limits::epsilon(), mLowerLimit[0]+numeric_limits::epsilon(), transverse, lambda_A) || !mProtonTableCollection->available(mUpperLimit[1]-numeric_limits::epsilon(), mLowerLimit[2]+numeric_limits::epsilon(), mUpperLimit[0]-numeric_limits::epsilon(), transverse, lambda_A) || !mProtonTableCollection->available(mUpperLimit[1]-numeric_limits::epsilon(), mUpperLimit[2]-numeric_limits::epsilon(), mUpperLimit[0]-numeric_limits::epsilon(), transverse, lambda_A); tooSmallMean = !mProtonTableCollection->available(mLowerLimit[1]+numeric_limits::epsilon(), mLowerLimit[2]+numeric_limits::epsilon(), mLowerLimit[0]+numeric_limits::epsilon(), transverse, mean_A) || !mProtonTableCollection->available(mLowerLimit[1]+numeric_limits::epsilon(), mUpperLimit[2]-numeric_limits::epsilon(), mLowerLimit[0]+numeric_limits::epsilon(), transverse, mean_A) || !mProtonTableCollection->available(mLowerLimit[1]+numeric_limits::epsilon(), mLowerLimit[2]+numeric_limits::epsilon(), mUpperLimit[0]-numeric_limits::epsilon(), transverse, mean_A) || !mProtonTableCollection->available(mLowerLimit[1]+numeric_limits::epsilon(), mUpperLimit[2]-numeric_limits::epsilon(), mUpperLimit[0]-numeric_limits::epsilon(), transverse, mean_A) || !mProtonTableCollection->available(mUpperLimit[1]-numeric_limits::epsilon(), mLowerLimit[2]+numeric_limits::epsilon(), mLowerLimit[0]+numeric_limits::epsilon(), transverse, mean_A) || !mProtonTableCollection->available(mUpperLimit[1]-numeric_limits::epsilon(), mUpperLimit[2]-numeric_limits::epsilon(), mLowerLimit[0]+numeric_limits::epsilon(), transverse, mean_A) || !mProtonTableCollection->available(mUpperLimit[1]-numeric_limits::epsilon(), mLowerLimit[2]+numeric_limits::epsilon(), mUpperLimit[0]-numeric_limits::epsilon(), transverse, mean_A) || !mProtonTableCollection->available(mUpperLimit[1]-numeric_limits::epsilon(), mUpperLimit[2]-numeric_limits::epsilon(), mUpperLimit[0]-numeric_limits::epsilon(), transverse, mean_A); } if (!lambdaTableExists || tooSmallLambda) { if (tooSmallMean) { cout << "Warning: the kinematic coverage of the table containing the lambda values " << endl; cout << " needed for skewedness and/or real amplitude corrections is smaller" << endl; cout << " then the required range (or does not exist). The proton amplitude " << endl; cout << " tables that could be used to calculate them on the fly are too" << endl; cout << " small as well. Corrections will be switched off." << endl; mSettings->setCorrectForRealAmplitude(false); mSettings->setCorrectSkewedness(false); delete mProtonTableCollection; mProtonTableCollection = 0; } else { if (lambdaTableExists) { - cout << "Warning: the kinematic coverage of the table containing the lambda values " << endl; - cout << " needed for skewedness and/or real amplitude corrections is smaller" << endl; - cout << " then the required range. The missing lambda values will be " << endl; - cout << " calculated using the proton amplitude tables directly." << endl; + cout << "Info: the kinematic coverage of the table containing the lambda values " << endl; + cout << " needed for skewedness and/or real amplitude corrections is smaller" << endl; + cout << " then the required range. The missing lambda values will be " << endl; + cout << " calculated using the proton amplitude tables directly." << endl; } else { - cout << "Warning: the table containing the lambda values needed for skewedness and/or real " << endl; - cout << " amplitude corrections is not available. The missing lambda values will be" << endl; - cout << " calculated using the referring proton amplitude tables directly." << endl; + cout << "Info: the table containing the lambda values needed for skewedness and/or real " << endl; + cout << " amplitude corrections is not available. The missing lambda values will be" << endl; + cout << " calculated using the referring proton amplitude tables directly." << endl; } } } } // // Setup cross-section functor // It is this functor that is used by all other functors, // functions, and wrappers when dealing with cross-sections. // if (mCrossSection) delete mCrossSection; mCrossSection = new CrossSection; mCrossSection->setTableCollection(mTableCollection); if (mProtonTableCollection) mCrossSection->setProtonTableCollection(mProtonTableCollection); // // UNU.RAN needs the domain (boundaries) and the mode. // The domain is already defined, here we find the mode, which is tricky. // The max. cross-section is clearly at the domain boundary in Q2=Q2min. // The position in W2 and t is not obvious. It sits along a line given // by tmax(W2). The approach here is to use the BrentMinimizer1D that // performs first a scan a then a Brent fit. // double theMode[3]; if (mSettings->verbose()) cout << "Finding mode of pdf:" << endl; if (mSettings->UPC()) { // // For now we keep the option to create a histogram of the // generated cross-sections(t, log(xpom)) for QA purposes. // if (mSettings->verbose() && mSettings->verboseLevel() > 9) { cout << "Creating 2D histogram of cross-section as fct of t and log(xpom)." << endl; cout << "Be patient this might take a while. Histo stored in file 'landscape.root'" << endl; TFile file("landscape.root", "RECREATE"); int nbins_t = 300; int nbins_logx = 300; TH2D histo("histo", "mode finder studies", nbins_t, mLowerLimit[0], mUpperLimit[0], // t nbins_logx, log(mLowerLimit[1]), log(mUpperLimit[1])); // log(xpom) for (int ix = 1; ix <= nbins_logx; ix++) { for (int it = 1; it <= nbins_t; it++) { double logx = histo.GetYaxis()->GetBinCenter(ix); double x = exp(logx); double t = histo.GetXaxis()->GetBinCenter(it); if (!Kinematics::validUPC(mSettings->hadronBeamEnergy(), mSettings->electronBeamEnergy(), t, x, vectorMesonPDG->Mass(), false)) { histo.SetBinContent(it, ix, -5.e9); } else { histo.SetBinContent(it, ix, (*mCrossSection)(t, x)); } } } histo.Write(); file.Close(); cout << "Histogram written to file. All done." << endl; } // // Create functor // Mode is at the max t available. // Note that the functop works with log(xpom). // theMode[0] = mUpperLimit[0]; // t theMode[1] = mUpperLimit[1]; // xpom for UPC theMode[2] = 0; // not used for UPC UPCModeFinderFunctor modeFunctor(mCrossSection, vectorMesonPDG->Mass(), mSettings->hadronBeamEnergy(), mSettings->electronBeamEnergy()); ROOT::Math::BrentMinimizer1D minimizer; minimizer.SetFunction(modeFunctor, log(mLowerLimit[1]), log(mUpperLimit[1])); minimizer.SetNpx(100000); ok = minimizer.Minimize(1000000, 1.e-8, 1.e-10); if (! ok) { cout << "Error, failed to find mode of pdf." << endl; return false; } // // Get the result // theMode[1] = exp(minimizer.XMinimum()); // xpom theMode[0] = Kinematics::tmax(theMode[1]); double crossSectionAtMode = (*mCrossSection)(theMode[0], theMode[1]); if (mSettings->verbose()) { cout << "\tlocation: t=" << theMode[0] << ", xpom=" << theMode[1] << "; value: " << crossSectionAtMode << endl; } // // Consistency check of mode // if (crossSectionAtMode <= 0) { cout << "Error: cross-section at mode value is invalid." << endl; return false; } if (!Kinematics::validUPC(mSettings->hadronBeamEnergy(), mSettings->electronBeamEnergy(), theMode[0], theMode[1], vectorMesonPDG->Mass(), true)) { cout << "Error: mode of pdf is outside kinematic limits." << endl; return false; } } else { theMode[0] = mUpperLimit[0]; // t theMode[1] = mLowerLimit[1]; // Q2 (xpom for UPC) theMode[2] = mLowerLimit[2]; // W2 (dummy for UPC) ModeFinderFunctor modeFunctor(mCrossSection, theMode[1], vectorMesonPDG->Mass(), mLowerLimit[0], mUpperLimit[0]); ROOT::Math::BrentMinimizer1D minimizer; minimizer.SetFunction(modeFunctor, mLowerLimit[2], mUpperLimit[2]); minimizer.SetNpx(static_cast(mUpperLimit[2]-mLowerLimit[2])); ok = minimizer.Minimize(100000, 0, 1.e-8); if (! ok) { cout << "Error, failed to find mode of pdf." << endl; exit(1); } theMode[2] = minimizer.XMinimum(); // W2 theMode[0] = Kinematics::tmax(0, theMode[1], theMode[2], vectorMesonPDG->Mass()); // first arg (t) must be 0 here if (theMode[0] > mUpperLimit[0]) theMode[0] = mUpperLimit[0]; double crossSectionAtMode = (*mCrossSection)(theMode[0], theMode[1], theMode[2]); if (mSettings->verbose()) { cout << "\tlocation: t=" << theMode[0] << ", Q2=" << theMode[1] << ", W=" << sqrt(theMode[2]); cout << "; value: " << crossSectionAtMode << endl; } } // // Initialize 2D (UPC) or 3D random generator // // Test show that UNU.RAN runs smoother in log(Q2) // and log(cross-section). Functor CrossSection has // a spezialized method for UNU.RAN, unuranPDF(). // // In UPC mode the mPDF_Functor is using a different // method and is only 2D since Q2=0 // // domain and mode for Q2 -> log(Q2) or xpom -> log(xpom) mLowerLimit[1] = log(mLowerLimit[1]); mUpperLimit[1] = log(mUpperLimit[1]); theMode[1] = log(theMode[1]); if (mPDF_Functor) delete mPDF_Functor; if (mPDF) delete mPDF; if (mSettings->UPC()) mPDF_Functor = new ROOT::Math::Functor(mCrossSection, &CrossSection::unuranPDF, 2); else mPDF_Functor = new ROOT::Math::Functor(mCrossSection, &CrossSection::unuranPDF, 3); mPDF = new TUnuranMultiContDist(*mPDF_Functor, true); // last arg = pdf in log or not mPDF->SetDomain(mLowerLimit, mUpperLimit); mPDF->SetMode(theMode); if (mUnuran) delete mUnuran; mUnuran = new TUnuran; mCrossSection->setCheckKinematics(false); // avoid numeric glitch in Init() mUnuran->Init(*mPDF, "method=hitro"); mCrossSection->setCheckKinematics(true); mUnuran->SetSeed(mSettings->seed()); // // Burn in generator // double xrandom[3]; for (int i=0; i<1000; i++) { mUnuran->SampleMulti(xrandom); } mEventCounter = 0; mTriesCounter = 0; mIsInitialized = true; cout << "Sartre is initialized." << endl << endl; return true; } bool Sartre::init(const string& str) // overloaded version of init() { if (str.empty()) return init(); else return init(str.c_str()); } vector > Sartre::kinematicLimits() { vector > array; array.push_back(make_pair(mLowerLimit[0], mUpperLimit[0])); // t array.push_back(make_pair(exp(mLowerLimit[1]), exp(mUpperLimit[1]))); // Q2 or xpom if (!mSettings->UPC()) array.push_back(make_pair(sqrt(mLowerLimit[2]), sqrt(mUpperLimit[2]))); // W return array; } Event* Sartre::generateEvent() { if (!mIsInitialized) { cout << "Sartre::generateEvent(): Error, Sartre is not initialized yet." << endl; cout << " Call init() before trying to generate events." << endl; return 0; } double xrandom[3]; TParticlePDG *vectorMesonPDG = mSettings->lookupPDG(mVmID); double vmMass = vectorMesonPDG->Mass(); // // Generate one event // while (true) { mTriesCounter++; delete mCurrentEvent; mCurrentEvent = new Event; // // Get t, Q2, W2 from TUnuran and check for kinematics. // Q2 is generated as log(Q2) so we transform it back first. // This is the only place where Kinematics::valid() is called // with the fully correct xpomeron calculation switched on. // mUnuran->SampleMulti(xrandom); xrandom[1] = exp(xrandom[1]); // log(Q2) -> Q2 or log(xpom) -> xpom bool isValidEvent; if (mSettings->UPC()) { isValidEvent = Kinematics::validUPC(mSettings->hadronBeamEnergy(), mSettings->electronBeamEnergy(), xrandom[0], xrandom[1], vectorMesonPDG->Mass(), (mSettings->verboseLevel() > 1)); } else { isValidEvent = Kinematics::valid( mS, xrandom[0], xrandom[1], xrandom[2], vmMass, true, (mSettings->verboseLevel() > 1)); } if (!isValidEvent) { if (mSettings->verboseLevel() > 2) cout << "Sartre::generateEvent(): event rejected, not within kinematic limits" << endl; continue; } // // Fill beam particles in Event structure // Kinematics for eA is reported as 'per nucleon' // if (mSettings->UPC()) { // // For UPC some of the event variables // are filled in the final state generator. // They are set to 0 here. // mCurrentEvent->eventNumber = mEventCounter; mCurrentEvent->t = xrandom[0]; // t mCurrentEvent->Q2 = 0; mCurrentEvent->x = 0; mCurrentEvent->y = 0; mCurrentEvent->s = mS; // s mCurrentEvent->W = 0; mCurrentEvent->beta = 1; mCurrentEvent->xpom = xrandom[1]; mCurrentEvent->polarization = GammaPolarization::transverse; mCurrentEvent->diffractiveMode = mCrossSection->diffractiveModeOfLastCall(); Particle eIn, hIn; eIn.index = 0; eIn.pdgId = mUpcNucleus->pdgID(); // misuse ebeam spot for this eIn.status = 1; eIn.p = mElectronBeam; hIn.index = 1; hIn.pdgId = mNucleus->pdgID(); hIn.status = 1; hIn.p = mHadronBeam; mCurrentEvent->particles.push_back(eIn); mCurrentEvent->particles.push_back(hIn); } else { mCurrentEvent->eventNumber = mEventCounter; mCurrentEvent->t = xrandom[0]; // t mCurrentEvent->Q2 = xrandom[1]; // Q2 mCurrentEvent->x = Kinematics::x(xrandom[1], xrandom[2]); // x mCurrentEvent->y = Kinematics::y(xrandom[1], mCurrentEvent->x, mS); // y mCurrentEvent->s = mS; // s mCurrentEvent->W = sqrt(xrandom[2]); mCurrentEvent->polarization = mCrossSection->polarizationOfLastCall(); mCurrentEvent->diffractiveMode = mCrossSection->diffractiveModeOfLastCall(); Particle eIn, hIn; eIn.index = 0; eIn.pdgId = 11; // e- eIn.status = 1; eIn.p = mElectronBeam; hIn.index = 1; hIn.pdgId = mNucleus->pdgID(); hIn.status = 1; hIn.p = mHadronBeam; mCurrentEvent->particles.push_back(eIn); mCurrentEvent->particles.push_back(hIn); } // // Generate the final state particles // bool ok; if (mSettings->UPC()) { // also fills some of the undefined event variables ok = mFinalStateGenerator.generate(mVmID, mCurrentEvent->t, mCurrentEvent->xpom, (mCurrentEvent->diffractiveMode == incoherent), mA, mCurrentEvent); } else { ok = mFinalStateGenerator.generate(mVmID, mCurrentEvent->t, mCurrentEvent->y, mCurrentEvent->Q2, (mCurrentEvent->diffractiveMode == incoherent), mA, mCurrentEvent); } if (!ok) { if (mSettings->verboseLevel() > 1) cout << "Sartre::generateEvent(): failed to generate final state" << endl; continue; } break; } mEventCounter++; // // Nuclear breakup // // If the event is incoherent the final state generator does produce a // 'virtual' proton with m > m_p which is used in Nucleus to calculate // the excitation energy and the boost. // int indexOfScatteredHadron = 6; bool allowBreakup = mSettings->enableNuclearBreakup(); if (mA == 1) allowBreakup = false; if (mNucleus) mNucleus->resetBreakup(); // clear previous event in any case if (allowBreakup && mCurrentEvent->diffractiveMode == incoherent && mNucleus) { int nFragments = mNucleus->breakup(mCurrentEvent->particles[indexOfScatteredHadron].p); // // Merge the list of products into the event list. // We loose some information here. The user can always go back to // the nucleus and check the decay products for more details. // In the original list the energy is per nuclei, here we transform it // to per nucleon to stay consistent with Sartre conventions. // const vector& products = mNucleus->breakupProducts(); for (int i=0; iparticles.size(); fragment.pdgId = products[i].pdgId; fragment.status = 1; fragment.p = products[i].p*(1/static_cast(products[i].A)); fragment.parents.push_back(indexOfScatteredHadron); mCurrentEvent->particles.push_back(fragment); } } // // Complete event record // if (!mSettings->UPC()) { mCurrentEvent->xpom = Kinematics::xpomeron(mCurrentEvent->t, mCurrentEvent->Q2, mCurrentEvent->W*mCurrentEvent->W, vmMass); mCurrentEvent->beta = mCurrentEvent->x/mCurrentEvent->xpom; } return mCurrentEvent; } double Sartre::totalCrossSection() { if (mTotalCrossSection == 0) { // // Limits of integration in t, Q2, W2 // or in the case of UPC t, xpom, dummy // double xmin[3]; double xmax[3]; copy(mLowerLimit, mLowerLimit+3, xmin); copy(mUpperLimit, mUpperLimit+3, xmax); // // At this point mLowerLimit[1] and mUpperLimit[1] // are in log(Q2) or log(xpom). // xmin[1] = exp(xmin[1]); // log Q2 limit -> Q2 limit or equivalent xpom for UPC xmax[1] = exp(xmax[1]); // log Q2 limit -> Q2 limit mTotalCrossSection = calculateTotalCrossSection(xmin, xmax); } return mTotalCrossSection; } double Sartre::totalCrossSection(double lower[3], double upper[3]) // t, Q2, W (or t, xpom, dummy for UPC) { lower[2] *= lower[2]; upper[2] *= upper[2]; // W -> W2 double result = calculateTotalCrossSection(lower, upper); return result; } EventGeneratorSettings* Sartre::runSettings() { return EventGeneratorSettings::instance(); } double Sartre::calculateTotalCrossSection(double lower[3], double upper[3]) { double result = 0; if (!mIsInitialized) { cout << "Sartre::calculateTotalCrossSection(): Error, Sartre is not initialized yet." << endl; cout << " Call init() before trying to generate events." << endl; return result; } // // Calculate integral using adaptive numerical method // // Options: ADAPTIVE, kVEGAS, kPLAIN, kMISER // no abs tolerance given -> relative only const double precision = 5e-4; ROOT::Math::Functor wfL((*mCrossSection), mSettings->UPC() ? 2 : 3); ROOT::Math::IntegratorMultiDim ig(ROOT::Math::IntegrationMultiDim::kADAPTIVE, 0, precision, 1000000); ig.SetFunction(wfL); result = ig.Integral(lower, upper); // // If it fails we switch to a MC integration which is usually more robust // although not as accurate. This should happen very rarely if at all. // if (result <= numeric_limits::epsilon()) { cout << "Sartre::calculateTotalCrossSection(): warning, adaptive integration failed - switching to VEGAS method." << endl; ROOT::Math::IntegratorMultiDim igAlt(ROOT::Math::IntegrationMultiDim::kVEGAS); igAlt.SetFunction(wfL); igAlt.SetRelTolerance(precision); igAlt.SetAbsTolerance(0); result = igAlt.Integral(lower, upper); } // // UPC with symmetric beams requires the cross-section // being multiplied by a factor of 2. // if (mSettings->UPC()) { if (mSettings->A() == mSettings->UPCA()) result *= 2; } return result; } const FrangibleNucleus* Sartre::nucleus() const {return mNucleus;} void Sartre::listStatus(ostream& os) const { os << "Event summary: " << mEventCounter<< " events generated, " << mTriesCounter << " tried" << endl; time_t delta = runTime(); os << "Total time used: " << delta/60 << " min " << delta - 60*(delta/60) << " sec" << endl; } time_t Sartre::runTime() const { time_t now = time(0); return now-mStartTime; } //============================================================================== // // Utility functions and operators (helpers) // //============================================================================== ostream& operator<<(ostream& os, const TLorentzVector& v) { os << v.Px() << '\t' << v.Py() << '\t' << v.Pz() << '\t' << v.E() << '\t'; double m2 = v*v; if (m2 < 0) os << '(' << -sqrt(-m2) << ')'; else os << '(' << sqrt(m2) << ')'; return os; } Index: trunk/src/TableGeneratorNucleus.h =================================================================== --- trunk/src/TableGeneratorNucleus.h (revision 369) +++ trunk/src/TableGeneratorNucleus.h (revision 370) @@ -1,51 +1,51 @@ //============================================================================== // TableGeneratorNucleus.h // -// Copyright (C) 2010-2013 Tobias Toll and Thomas Ullrich +// Copyright (C) 2010-2019 Tobias Toll and Thomas Ullrich // // This file is part of Sartre. // // 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. // 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, see . // // Author: Thomas Ullrich // Last update: // $Date$ // $Author$ //============================================================================== #ifndef TableGeneratorNucleus_h #define TableGeneratorNucleus_h #include "Nucleon.h" #include "Nucleus.h" #include using namespace std; class TH1D; class TableGeneratorNucleus : public Nucleus { public: TableGeneratorNucleus(); TableGeneratorNucleus(unsigned int A); TableGeneratorNucleus(const TableGeneratorNucleus&); ~TableGeneratorNucleus(); TableGeneratorNucleus& operator=(const TableGeneratorNucleus&); bool generate(); const TH1D* getRHisto() const; public: vector configuration; private: TH1D* mRadialDistributionHistogram; }; #endif Index: trunk/src/Nucleon.cpp =================================================================== --- trunk/src/Nucleon.cpp (revision 369) +++ trunk/src/Nucleon.cpp (revision 370) @@ -1,51 +1,51 @@ //============================================================================== // Nucleon.cpp // -// Copyright (C) 2010-2013 Tobias Toll and Thomas Ullrich +// Copyright (C) 2010-2019 Tobias Toll and Thomas Ullrich // // This file is part of Sartre. // // 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. // 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, see . // // Author: Thomas Ullrich // Last update: // $Date$ // $Author$ //============================================================================== #include "Nucleon.h" #include "TVector3.h" Nucleon::Nucleon() { mPosition.SetXYZ(0,0,0); mCharge = 0; } Nucleon::Nucleon(const TVector3& v) { mPosition = v; mCharge = 0; } Nucleon::Nucleon(const TVector3& v, unsigned int c) { mPosition = v; mCharge = c; } const TVector3& Nucleon::position() const {return mPosition;} unsigned int Nucleon::charge() const {return mCharge;} void Nucleon::setPosition(const TVector3& val) {mPosition = val;} void Nucleon::setCharge(unsigned int val){mCharge = val;} Index: trunk/src/tableDumper.cpp =================================================================== --- trunk/src/tableDumper.cpp (revision 369) +++ trunk/src/tableDumper.cpp (revision 370) @@ -1,129 +1,129 @@ //============================================================================== // tableDumper.cpp // -// Copyright (C) 2015 Tobias Toll and Thomas Ullrich +// Copyright (C) 2015-2019 Tobias Toll and Thomas Ullrich // // This file is part of Sartre. // // 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. // 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, see . // // Author: Thomas Ullrich // Last update: // $Date$ // $Author$ //============================================================================== // // Utility program to write an entire table into a binary file. // Usage: tableDumper [-v] table_file binary_file // -v verbose output, print every entry //============================================================================== #include "Table.h" #include #include #include #include #include #include using namespace std; #define PR(x) cout << #x << " = " << (x) << endl; void usage(const char* prog) { cout << "Usage: " << prog << " [-v] table_file binary_file" << endl; } bool fexists(const string &filename) { ifstream ifs(filename); return !ifs.fail(); } int main(int argc, char **argv) { // // Handle command line arguments and verify // file names // if (argc < 3) { usage(argv[0]); return 2; } bool verbose = false; int ch; while ((ch = getopt(argc, argv, "v")) != -1) { switch (ch) { case 'v': verbose = true; break; default: usage(argv[0]); return 2; break; } } if (optind == argc) { usage(argv[0]); return 2; } vector allFiles; for (int index = optind; index < argc; index++) allFiles.push_back(string(argv[index])); if (allFiles.size() != 2) { usage(argv[0]); return 2; } string tableFileName(allFiles[0]); string binaryFileName(allFiles[1]); // // Check files // if (!fexists(tableFileName)) { cerr << "tableDumper: input file '" << tableFileName << "' does not exist." << endl; return 1; } if (fexists(binaryFileName)) { cerr << "tableDumper: output file '" << binaryFileName << "' already exist." << endl; return 1; } // // Open table // Table tbl; if (tbl.read(tableFileName.c_str())) { cout << "Opened '" << tableFileName << "' successfully." << endl; } else { cerr << "tableDumper: cannot open input file '" << tableFileName << "'." << endl; return 1; } // // Write binary file // cout << "Writing binary data to '" << binaryFileName << "'." << endl; if (!tbl.writeToBinaryFile(binaryFileName, verbose)) { cerr << "tableDumper: problems writing binary data to file." << endl; return 1; } cout << "Binary data successfully written." << endl; return 0; } Index: trunk/src/Settings.h =================================================================== --- trunk/src/Settings.h (revision 369) +++ trunk/src/Settings.h (revision 370) @@ -1,190 +1,190 @@ //============================================================================== // Settings.h // -// Copyright (C) 2010-2017 Tobias Toll and Thomas Ullrich +// Copyright (C) 2010-2019 Tobias Toll and Thomas Ullrich // // This file is part of Sartre. // // 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. // 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, see . // // Author: Thomas Ullrich // Last update: // $Date$ // $Author$ //============================================================================== #ifndef Settings_h #define Settings_h #include #include #include #include #include "TDatabasePDG.h" #include "TRandom3.h" #include "Enumerations.h" using namespace std; class TParticlePDG; class SettingsParameterBase { public: virtual ~SettingsParameterBase() {} public: string name; }; template class SettingsParameter : public SettingsParameterBase { public: T* address; T defaultValue; }; class Settings { public: Settings(); virtual ~Settings(); bool readSettingsFromFile(const char*); virtual bool list(ostream& = cout); TParticlePDG* lookupPDG(int) const; string particleName(int pdgID); static TRandom3* randomGenerator(); unsigned int seed() const; void setSeed(unsigned int); int userInt() const; double userDouble() const; string userString() const; void setUserInt(int); void setUserDouble(double); void setUserString(const string&); void setVerbose(bool); bool verbose() const; void setVerboseLevel(int); int verboseLevel() const; void setQ2min(double); double Q2min() const; double Qmin() const; void setQ2max(double); double Q2max() const; double Qmax() const; void setWmin(double); void setW2min(double); double Wmin() const; double W2min() const; void setWmax(double); void setW2max(double); double Wmax() const; double W2max() const; void setXpomMin(double); // UPC only void setXpomMax(double); double xpomMin() const; double xpomMax() const; int vectorMesonId() const; void setVectorMesonId(int); string dipoleModelName() const; DipoleModelType dipoleModelType() const; void setDipoleModelType(DipoleModelType); string dipoleModelParameterSetName() const; DipoleModelParameterSet dipoleModelParameterSet() const; void setDipoleModelParameterSet(DipoleModelParameterSet); string tableSetTypeName() const; TableSetType tableSetType() const; void setTableSetType(TableSetType); unsigned int A() const; void setA(unsigned int); string rootfile() const; void setRootfile(const char*); void setUPC(bool); bool UPC() const; void setUPCA(unsigned int); unsigned int UPCA() const; protected: template void registerParameter(T*, const char*, T); virtual void consolidateSettings() = 0; virtual void consolidateCommonSettings(); protected: vector mRegisteredParameters; static TRandom3 mRandomGenerator; unsigned int mSeed; bool mVerbose; int mVerboseLevel; double mQ2min; double mQ2max; double mWmin; double mWmax; double mXpomMin; double mXpomMax; int mVectorMesonId; string mDipoleModelName; DipoleModelType mDipoleModelType; DipoleModelParameterSet mDipoleModelParameterSet; string mDipoleModelParameterSetName; TableSetType mTableSetType; string mTableSetTypeName; unsigned int mA; string mRootfile; bool mUPC; unsigned int mUPCA; private: string mRuncard; vector mLines; TDatabasePDG *mPDG; map mPeriodicTable; int mUserInt; double mUserDouble; string mUserString; }; template void Settings::registerParameter(T* var, const char* name, T def) { SettingsParameter* sv = new SettingsParameter; sv->address = var; sv->name = name; sv->defaultValue = def; *var = def; mRegisteredParameters.push_back(sv); } inline TRandom3* Settings::randomGenerator() {return &mRandomGenerator;} #endif Index: trunk/src/FinalStateGenerator.h =================================================================== --- trunk/src/FinalStateGenerator.h (revision 369) +++ trunk/src/FinalStateGenerator.h (revision 370) @@ -1,59 +1,59 @@ //============================================================================== // FinalStateGenerator.h // -// Copyright (C) 2010-2013 Tobias Toll and Thomas Ullrich +// Copyright (C) 2010-2019 Tobias Toll and Thomas Ullrich // // This file is part of Sartre. // // 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. // 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, see . // // Author: Thomas Ullrich // Last update: // $Date$ // $Author$ //============================================================================== #ifndef FinalStateGenerator_h #define FinalStateGenerator_h #include "TLorentzVector.h" class Event; class FinalStateGenerator { public: FinalStateGenerator(); virtual ~FinalStateGenerator(); virtual bool generate(int id, double t, double y, double Q2, bool isIncoherent, int A, Event *event) = 0; virtual bool generate(int id, double t, double xpom, bool isIncoherent, int A, Event *event) = 0; bool isValid(TLorentzVector &) const; protected: double mT; double mQ2; double mY; double mS; double mXp; //UPC double mEgam; //UPC double mMY2; double mMassVM; double mA; bool mIsIncoherent; TLorentzVector mElectronBeam; TLorentzVector mHadronBeam; }; #endif Index: trunk/src/TableCollection.h =================================================================== --- trunk/src/TableCollection.h (revision 369) +++ trunk/src/TableCollection.h (revision 370) @@ -1,75 +1,75 @@ //============================================================================== // TableCollection.h // -// Copyright (C) 2010-2013 Tobias Toll and Thomas Ullrich +// Copyright (C) 2010-2019 Tobias Toll and Thomas Ullrich // // This file is part of Sartre. // // 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. // 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, see . // // Author: Thomas Ullrich // Last update: // $Date$ // $Author$ //============================================================================== #ifndef TableCollection_h #define TableCollection_h #include "Enumerations.h" #include #include using namespace std; class Table; class TableCollection { public: TableCollection(); TableCollection(const TableCollection&); TableCollection(int A, DipoleModelType typ, DipoleModelParameterSet set, int vmID); ~TableCollection(); TableCollection& operator=(const TableCollection&); bool init(int A, DipoleModelType typ, DipoleModelParameterSet set, int vmID); bool tableExists(GammaPolarization pol, AmplitudeMoment mom) const; bool tableExists(AmplitudeMoment mom) const; // UPC version bool available(double Q2, double W2, double t, GammaPolarization p, AmplitudeMoment m) const; bool available(double xpom, double t, AmplitudeMoment m) const; // UPC version double get(double Q2, double W2, double t, GammaPolarization p, AmplitudeMoment m) const; double get(double Q2, double W2, double t, GammaPolarization p, AmplitudeMoment m, Table *&) const; double get(double xpom, double t, AmplitudeMoment m) const; // UPC version double get(double xpom, double t, AmplitudeMoment m, Table *&) const; // UPC version void list(ostream& = cout, bool = false) const; double minQ2() const; double maxQ2() const; double minW2() const; double maxW2() const; double minW() const; double maxW() const; double minT() const; double maxT() const; double minX() const; double maxX() const; private: double minimumValue(unsigned int) const; double maximumValue(unsigned int) const; private: vector mTables; }; #endif Index: trunk/src/PhotonFlux.h =================================================================== --- trunk/src/PhotonFlux.h (revision 369) +++ trunk/src/PhotonFlux.h (revision 370) @@ -1,72 +1,72 @@ //============================================================================== // PhotonFlux.h // -// Copyright (C) 2010-2013 Tobias Toll and Thomas Ullrich +// Copyright (C) 2010-2019 Tobias Toll and Thomas Ullrich // // This file is part of Sartre. // // 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. // 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, see . // // Author: Thomas Ullrich // Last update: // $Date$ // $Author$ //============================================================================== // // Functor class. // Photon flux is given in: d2sig/(dQ2 dW2) //============================================================================== #ifndef PhotonFlux_h #define PhotonFlux_h #include "Enumerations.h" #include "EventGeneratorSettings.h" #include "TH1D.h" class Nucleus; class PhotonFlux { public: PhotonFlux(); PhotonFlux(double s); void setS(double); double operator()(double Q2, double W2, GammaPolarization p) const; //UPC: double operator()(double Egamma) const; double nuclearPhotonFlux(double Egamma) const; private: double fluxTransverse(double Q2, double W2) const; double fluxLongitudinal(double Q2, double W2) const; double mS; bool mSIsSet; //UPC: double uiNuclearPhotonFlux(double*, double*) const; double sigma_nn(double) const; double TAA(double); double TAAForIntegration(const double*) const; void calculateTAAlookupTable(); bool mIsUPC; double mEBeamEnergy; TH1D* mTAA_of_b; double mB; Nucleus* mNucleus; Nucleus* mNucleusUPC; EventGeneratorSettings *mSettings; }; #endif Index: trunk/src/tableQuery.cpp =================================================================== --- trunk/src/tableQuery.cpp (revision 369) +++ trunk/src/tableQuery.cpp (revision 370) @@ -1,174 +1,174 @@ //============================================================================== // tableQuery.cpp // -// Copyright (C) 2010-2013 Tobias Toll and Thomas Ullrich +// Copyright (C) 2010-2019 Tobias Toll and Thomas Ullrich // // This file is part of Sartre. // // 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. // 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, see . // // Author: Thomas Ullrich // Last update: // $Date$ // $Author$ //============================================================================== // // Allows to query the content of table(s) interactively. // User is prompted for t, Q2, W values, program returns interpolated values. // Useful to check interpolation mechanism. // // Usage: // tableQuery file(s) // //============================================================================== #include "Table.h" #include #include #include #include #include #include #define PR(x) cout << #x << " = " << (x) << endl; using namespace std; template inline void Prompt(const char *text, T& var) { string line; char c; cout << text << " [" << var << "]: "; while ((c = cin.get()) && c != '\n') line += c; if (line.length() > 0) { istringstream ist(line); ist >> var; } } inline void Prompt(const char *text, bool& var) { string line; char c; string svar = var ? "true" : "false"; cout << text << " [" << svar.c_str() << "]: "; while ((c = cin.get()) && c != '\n') line += c; if (line.length() > 0) { if (line == "true") var = true; else if (line == "t") var = true; else if (line == "yes") var = true; else if (line == "y") var = true; else if (line == "on") var = true; else if (line == "1") var = true; else var = false; } } void usage(const char* prog) { cout << "Usage: " << prog << " file(s) ..." << endl; } int main(int argc, char **argv) { // // Handle command line arguments // if (argc == 1) { usage(argv[0]); return 2; } // // Store tables in vector // vector tables; vector upcTables; for (int i=1; iread(argv[i]); if (oneTable->isUPC()) upcTables.push_back(oneTable); else tables.push_back(oneTable); } if (tables.size() == 0 && upcTables.size() == 0) { cout << "tableQuery: no tables loaded." << endl; } if (tables.size() && upcTables.size()) { cout << "Some of the tables are UPC tables. Will start" << endl; cout << "to loop over non-UPC tables then UPC tables." << endl; } // // Loop until user stops it // bool loop = true; double Q2 = 10; double W = 50; double t = -0.1; double xpom = 0.01; double W2; string bound; if (tables.size()) { while (loop) { Prompt("t", t); Prompt("Q2", Q2); Prompt("W", W); W2 = W*W; for (unsigned int i=0; iget(Q2, W2 , t); if (t >= tables[i]->minT() && t <= tables[i]->maxT() && Q2 >= tables[i]->minQ2() && Q2 <= tables[i]->maxQ2()&& W2 >= tables[i]->minW2() && W2 <= tables[i]->maxW2()) bound = ""; else bound = " (outside boundary)"; cout << tables[i]->filename().c_str() << " --> " << c << bound.c_str() << endl; } Prompt("continue", loop); } } loop = true; if (upcTables.size()) { while (loop) { Prompt("t", t); Prompt("xp", xpom); for (unsigned int i=0; iget(xpom , t); if (t >= upcTables[i]->minT() && t <= upcTables[i]->maxT() && xpom >= upcTables[i]->minX() && xpom <= upcTables[i]->maxX()) bound = ""; else bound = " (outside boundary)"; cout << upcTables[i]->filename().c_str() << " --> " << c << bound.c_str() << endl; } Prompt("continue", loop); } } return 0; } Index: trunk/src/Nucleus.cpp =================================================================== --- trunk/src/Nucleus.cpp (revision 369) +++ trunk/src/Nucleus.cpp (revision 370) @@ -1,343 +1,343 @@ //============================================================================== // Nucleus.cpp // -// Copyright (C) 2010-2016 Tobias Toll and Thomas Ullrich +// Copyright (C) 2010-2019 Tobias Toll and Thomas Ullrich // // This file is part of Sartre. // // 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. // 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, see . // // Author: Thomas Ullrich // Last update: // $Date$ // $Author$ //============================================================================== #include "Nucleus.h" #include "Constants.h" #include "TF1.h" #include "TH1.h" #include "TH1D.h" #include #include #define PR(x) cout << #x << " = " << (x) << endl; Nucleus::Nucleus() { mA = mZ = 0; mRadius = 0; mSpin = 0; mSurfaceThickness = 0; mRho0 = 0; mOmega = 0; mMass = 0; mHulthenA = 0; mHulthenB = 0; } Nucleus::Nucleus(unsigned int A) { mA = mZ = 0; mRadius = 0; mSpin = 0; mSurfaceThickness = 0; mRho0 = 0; mOmega = 0; mMass = 0; mHulthenA = 0; mHulthenB = 0; Nucleus::init(A); } Nucleus& Nucleus::operator=(const Nucleus& n) { if (this != &n) { mA = n.mA; mZ = n.mZ; mRadius = n.mRadius; mSpin = n.mSpin; mSurfaceThickness = n.mSurfaceThickness; mRho0 = n.mRho0; mOmega = n.mOmega; mMass = n.mMass; mName = n.mName; mHulthenA = n.mHulthenA; mHulthenB = n.mHulthenB; mLookupTable = unique_ptr(new TH1D(*(n.mLookupTable))); mLookupTable->SetDirectory(0); } return *this; } Nucleus::Nucleus(const Nucleus& n) { mA = n.mA; mZ = n.mZ; mRadius = n.mRadius; mSpin = n.mSpin; mSurfaceThickness = n.mSurfaceThickness; mRho0 = n.mRho0; mOmega = n.mOmega; mMass = n.mMass; mName = n.mName; mHulthenA = n.mHulthenA; mHulthenB = n.mHulthenB; mLookupTable = unique_ptr(new TH1D(*(n.mLookupTable))); mLookupTable->SetDirectory(0); } Nucleus::~Nucleus() { // // This is a temorary fix of a problem in the code that is not understood. // In the table generation code after all is calculated the ~TH1 of the // look up table histogram causes a crash. This appears (?) to be related // to issues in GSL and ROOT. Releasing the pointer causes a memory leak // but this is not a big problem since it happens at the end of the program. // mLookupTable.release(); } void Nucleus::init(unsigned int A) { mA = A; // // Set the parameters of the nucleus // Woods-Saxon parameter are from Ramona Vogt's paper on nuclear geometry (table 1) // One exception is the deuteron were a Hulthen function is used (nucl-ex/0701025v1). // All version are defined such that Integral(d3r rho(r)) = A // const double unifiedAtomicMass = 0.931494013; switch (mA) { case 208: // Pb mZ = 82; mRadius = 6.624; mSurfaceThickness = 0.549; mOmega = 0; mRho0 = 0.160; mName = "Pb"; mMass = 207.2*unifiedAtomicMass; mSpin = 1./2.; break; case 197: // Au mZ = 79; mRadius = 6.38; mSurfaceThickness = 0.535; mOmega = 0; mRho0 = 0.1693; mName = "Au"; mMass = 196.96655*unifiedAtomicMass; mSpin = 3./2.; break; case 110: // Cd mZ = 48; mRadius = 5.33; mSurfaceThickness = 0.535; mOmega = 0; mRho0 = 0.1577; mName = "Cd"; mMass = 112.411*unifiedAtomicMass; mSpin = 1./2.; break; case 63: // Cu mZ = 29; mRadius = 4.214; mSurfaceThickness = 0.586; mOmega = 0; mRho0 = 0.1701; mName = "Cu"; mMass = 63.546*unifiedAtomicMass; mSpin = 3./2.; break; case 40: // Ca mZ = 20; mRadius = 3.766; mSurfaceThickness = 0.586; mOmega = -0.161; mRho0 = 0.1699; mName = "Ca"; mMass= 40.078*unifiedAtomicMass; mSpin = 7./2.; break; case 27: // Al mZ = 13; mRadius = 3.07; mSurfaceThickness = 0.519; mOmega = 0; mRho0 = 0.1739; mName = "Al"; mMass = 26.981538*unifiedAtomicMass; mSpin = 5./2.; break; case 16: // O mZ = 8; mRadius = 2.608; mSurfaceThickness = 0.513; mOmega = -0.051; mRho0 = 0.1654; mName = "O"; mMass = 15.9994*unifiedAtomicMass; mSpin = 5./2.; break; case 2: // D mZ = 1; mHulthenA = 0.456; mHulthenB = 2.36; mRho0 = 0.39946312; mName = "D"; mMass = 2.014102*unifiedAtomicMass; mSpin = 1; mRadius = 2.116; // not used for density function - taken from Jager et al. break; case 1: // When generating this nucleus, only one nucleon is put at (0, 0, 0) mZ = 1; mRadius = 1.; mMass = protonMass; // 1.00794*unifiedAtomicMass mName = "p"; //The following 3 are dummies, needed for radial distribution etc.: mSurfaceThickness = 0.513; mOmega = -0.051; mRho0 = 0.1654; mSpin = 1./2.; break; default: cout << "Nucleus::init(): Error, cannot handle A=" << mA << ", no parameters defined for this mass number." << endl; exit(1); break; } // // Generate lookup table for overlap integral T // (b and z in fm) // double range = 3*mRadius; TF1* funcToIntegrate = new TF1("funcToIntegrate",this, &Nucleus::rhoForIntegration, -range, range, 1); int nbins = 5000; // size of lookup table mLookupTable = unique_ptr(new TH1D("mLookupTable","T lookup table", nbins, 0, range)); mLookupTable->SetDirectory(0); for (int i=1; i<=nbins; i++) { double b = mLookupTable->GetBinCenter(i); funcToIntegrate->SetNpx(1000); funcToIntegrate->SetParameter(0, b); double res = funcToIntegrate->Integral(-range, range, 1e-8); mLookupTable->SetBinContent(i, res); } delete funcToIntegrate; } unsigned int Nucleus::A() const { return mA; } unsigned int Nucleus::Z() const { return mZ; } float Nucleus::spin() const { return mSpin; } double Nucleus::atomicMass() const { return mMass; } string Nucleus::name() const { return mName; } double Nucleus::radius() const { return mRadius; } double Nucleus::rho(double b, double z) // returns value in units of fm^-3 { // b and z in fm double r = sqrt(b*b+z*z); if (mA == 2) { double term = (exp(-mHulthenA*r)/r) - (exp(-mHulthenB*r)/r); // Hulthen return mRho0*term*term; } else { return mRho0*(1+mOmega*(r/mRadius)*(r/mRadius))/(1+exp((r-mRadius)/mSurfaceThickness)); // 3pF } } double Nucleus::rhoForIntegration(double *x, double* par) { // b and z in fm double b = par[0]; double z = *x; return rho(b, z); } double Nucleus::T(double b) const { // // Returns overlap integral // b in fm, overlap function T in GeV^2 // Returns 0 if b exceeds table range // if (mA == 0) { cout << "Nucleus::T(): Error, instance is not initialized - cannot calculate overlap integral." << endl; return 0; } int bin = mLookupTable->FindBin(b); double res = mLookupTable->GetBinContent(bin); return res*hbarc2; } double Nucleus::TForIntegration(double *x, double*) const { double b = x[0]; return 2*b*M_PI*T(b)/hbarc2; } void Nucleus::normalizationOfT(double eps) { // // This is for internal checks only. // Normalization of rho/T is such that fully integrated // function should yield A. // double range = 3*mRadius; TF1* func = new TF1("func",this, &Nucleus::TForIntegration, 0, range, 0); double res = func->Integral(0, range, eps); cout << "Normalization of T: = " << res << endl; delete func; } double Nucleus::rho0() const { return mRho0; } double Nucleus::TofProton(double b) { // // Gaussian shape for proton // Units: // b in fm // const double BG = 4; // GeV^-2 double arg = b*b/(2*BG); arg /= hbarc2; return 1/(2*M_PI*BG) * exp(-arg); } int Nucleus::pdgID(int Z, int A) const { // PDG for nuclei 10LZZZAAAI // L = number of strange quark (for hypernuclei) // I = isomer level, with I = 0 corresponding to the // ground state and I > 0 to excitations, if (Z==1 && A==1) return 2212; else if (Z==0 && A==1) return 2112; else if (A > 1) return 1000000000 + 10000*Z + 10*A; else return 0; } int Nucleus::pdgID() const { return pdgID(mZ, mA); } Index: trunk/src/tableInspector.cpp =================================================================== --- trunk/src/tableInspector.cpp (revision 369) +++ trunk/src/tableInspector.cpp (revision 370) @@ -1,170 +1,170 @@ //============================================================================== // tableInspector.cpp // -// Copyright (C) 2010-2016 Tobias Toll and Thomas Ullrich +// Copyright (C) 2010-2019 Tobias Toll and Thomas Ullrich // // This file is part of Sartre. // // 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. // 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, see . // // Author: Thomas Ullrich // Last update: // $Date$ // $Author$ //============================================================================== // // Utility program to check the integrity of lookup tables used in Sartre. // Usage: tableInspector [-x bin -y bin -z bin | -g bin | [-a] [-s] [-b]] file(s) ... // -b print table id in binary representation first // -a print position and values of each cell // -s print statstics of table content (min, max, empty bines etc.) // -g bin returns the ROOT/table bins in x,y,z for a given global bin // -x bin -y bin -z bin // returns the global bin for a given set of ROOT/table bins //============================================================================== #include "Table.h" #include #include #include #include #include using namespace std; template string binary(T word) { int nbits = 8*sizeof(T); string bitpattern(nbits+1, ' '); unsigned long long mask = 1; mask <<= (nbits-1); for (int i=0; i>= 1; } bitpattern[nbits] = '\0'; return bitpattern; } template void printBinary(T word) { string bits = binary(word); cout << bits.c_str() << endl; } void usage(const char* prog) { cout << "Usage: " << prog << " [ -x bin -y bin -z bin | -g bin | [-a] [-s] [-b]] file(s) ..." << endl; cout << " " << "-b print table id in binary representation first" << endl; cout << " " << "-a print position and values of each cell" << endl; cout << " " << "-s print statstics of table content (min, max, empty bines etc.)" << endl; cout << " " << "-g bin returns the ROOT/table bins in x,y,z for a given global bin" << endl; cout << " " << "-x bin -y bin -z bin returns the global bin for a given set of ROOT/table bins" << endl; } int main(int argc, char **argv) { // // Handle command line arguments // if (argc == 1) { usage(argv[0]); return 2; } bool listall = false; bool liststat = false; bool calcXYZ = false; bool calcGlobal = false; bool binaryId = false; int globalBin = 0; int binx = 1; int biny = 1; int binz = 1; int ch; while ((ch = getopt(argc, argv, "absg:x:y:z:")) != -1) { switch (ch) { case 'a': listall = true; break; case 'b': binaryId = true; break; case 's': liststat = true; break; case 'g': globalBin = atol(optarg); calcXYZ = true; break; case 'x': binx = atol(optarg); calcGlobal = true; break; case 'y': biny = atol(optarg); calcGlobal = true; break; case 'z': binz = atol(optarg); calcGlobal = true; break; case '?': default: usage(argv[0]); return 2; break; } } if (optind == argc || ( calcXYZ && calcGlobal ) || ( (calcXYZ || calcGlobal) && (listall || liststat) ) ) { usage(argv[0]); return 2; } // // List table info (optionally list all entries) // for (int index = optind; index < argc; index++) { Table tbl; if (tbl.read(argv[index])) { if (binaryId) { uint64_t theId = tbl.id(); cout << "Table ID = "; printBinary(theId); } if (calcXYZ) { cout << argv[index] << ": "; if (tbl.isUPC()) { tbl.binXY(globalBin, binx, biny); cout << globalBin << " --> binx=" << binx << " (xp), biny=" << biny << " (t)" << endl; } else { tbl.binXYZ(globalBin, binx, biny, binz); cout << globalBin << " --> binx=" << binx << " (Q2), biny=" << biny << " (W2), binz=" << binz << " (t)" << endl; } } else if (calcGlobal) { cout << argv[index] << ": "; if (tbl.isUPC()) { globalBin = tbl.globalBin(binx, biny); cout << "binx=" << binx << " (xp), biny=" << biny << " (t) --> " << globalBin << endl; } else { globalBin = tbl.globalBin(binx, biny, binz); cout << "binx=" << binx << " (Q2), biny=" << biny << " (W2), binz=" << binz << " (t) --> " << globalBin << endl; } } else { tbl.list(cout, listall, liststat); } } } return 0; } Index: trunk/src/TableGeneratorSettings.cpp =================================================================== --- trunk/src/TableGeneratorSettings.cpp (revision 369) +++ trunk/src/TableGeneratorSettings.cpp (revision 370) @@ -1,210 +1,210 @@ //============================================================================== // TableGeneratorSettings.cpp // -// Copyright (C) 2010-2017 Tobias Toll and Thomas Ullrich +// Copyright (C) 2010-2019 Tobias Toll and Thomas Ullrich // // This file is part of Sartre. // // 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. // 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, see . // // Author: Tobias Toll // Last update: // $Date$ // $Author$ //============================================================================== #include "Settings.h" #include "TableGeneratorSettings.h" #include "Constants.h" #include #include #include #include using namespace std; TableGeneratorSettings* TableGeneratorSettings::mInstance = 0; // initialize static TableGeneratorSettings* TableGeneratorSettings::instance() { if (mInstance == 0) mInstance = new TableGeneratorSettings; return mInstance; } TableGeneratorSettings::TableGeneratorSettings() { // // Register all the parameters that can be defined // via a runcard. // Arguments for registerParameter(): // 1. pointer to data memeber // 2. text string to be used in the runcard // 3. default parameter set // registerParameter(&mBSatLookupPath, "bSatLookupPath", string("./")); registerParameter(&mTmin, "tmin", -2.); registerParameter(&mTmax, "tmax", 0.); registerParameter(&mXmin, "xmin", 1e-9); //UPC registerParameter(&mXmax, "xmax", 3e-2); //UPC registerParameter(&mQ2bins, "Q2bins", static_cast(1)); registerParameter(&mW2bins, "W2bins", static_cast(1)); registerParameter(&mTbins, "tbins", static_cast(1)); registerParameter(&mXbins, "xbins", static_cast(1)); //UPC registerParameter(&mNumberOfConfigurations, "numberOfConfigurations", static_cast(1000)); vector vec; registerParameter(&mDipoleModelCustomParameters, "dipoleModelCustomParameters", vec); registerParameter(&mUseBackupFile, "useBackupFile", false); registerParameter(&mStartingBinFromBackup, "startingBinFromBackup", 0); registerParameter(&mStartBin, "startBin", -1); registerParameter(&mEndBin, "endBin", -1); registerParameter(&mModesToCalculate, "modesToCalculate", 0); registerParameter(&mPriority, "priority", 0); } void TableGeneratorSettings::consolidateSettings() // called after runcard is read { // // Kinematic limits // if (mQ2min>=mQ2max && !mUPC) { cout << "TableGeneratorSettings::consolidateSettings(): Error, Q2min >= Q2max. Stopping" << endl; exit(1); } if (mWmin>=mWmax && !mUPC) { cout << "TableGeneratorSettings::consolidateSettings(): Error, Wmin >= Wmax. Stopping" << endl; exit(1); } if (mTmin>=mTmax) { cout << "TableGeneratorSettings::consolidateSettings(): Error, tmin >= tmax. Stopping" << endl; exit(1); } if (mTmin>0. || mTmax >0.) { cout << "TableGeneratorSettings::consolidateSettings(): Error, t must be negative, please change t-limits. Stopping" << endl; exit(1); } if (mXmin>=mXmax && mUPC) { cout << "TableGeneratorSettings::consolidateSettings(): Error, xmin >= xmax. Stopping" << endl; exit(1); } if ((mXmin>=1 || mXmin<=0 || mXmax>=1 || mXmax<=0) and mUPC) { cout << "TableGeneratorSettings::consolidateSettings(): Error, xmin or xmax out of range. Stopping" << endl; exit(1); } if (mXmax>0.01 && mUPC){ cout << "TableGeneratorSettings::consolidateSettings(): Warning, xmax>1e-2, model may be unreliable." << endl; } if (mA==1) mNumberOfConfigurations = 1; if (!mUseBackupFile) mStartingBinFromBackup = 0; if (!mUPC) mXbins=1; else { mQ2bins=1; mW2bins=1; } if (mStartBin >= 0 && mEndBin >= 0 && mStartBin>mEndBin) { cout << "TableGeneratorSettings::consolidateSettings(): Error, endBin < startBin : " << mEndBin << " <= " << mStartBin << "! Stopping." << endl; exit(1); } if ( mStartBin < 0 ) mStartBin=0; if ( mStartBin >= signed(mQ2bins*mW2bins*mTbins*mXbins) ) { cout << "TableGeneratorSettings::consolidateSettings(): Error, starting bin >= table! Stopping." << endl; exit(1); } if ( mEndBin > signed(mQ2bins*mW2bins*mTbins*mXbins) || mEndBin < 0) { cout << "TableGeneratorSettings::consolidateSettings(): endBin is set to table size=" << mQ2bins*mW2bins*mTbins << endl; mEndBin=mQ2bins*mW2bins*mTbins*mXbins; } if ( mModesToCalculate < 0 || mModesToCalculate > 2 ) { cout << "TableGeneratorSettings::consolidateSettings(): Error, modeToCalculate can only take values 0, 1, or 2; not " << mModesToCalculate << endl; exit(1); } if ( (mModesToCalculate == 1) && (mA == 1) ){ cout << "TableGeneratorSettings::consolidateSettings(): Error, modeToCalculate and A cannot both be 1 simultaneously. This setting will produce NO tables." << endl; exit(1); } // // Make sure the W range is allowed // double VMMass=lookupPDG(mVectorMesonId)->Mass(); double W2min=VMMass*VMMass+protonMass2; double Wmin=sqrt(W2min); if(mWmin #include #include #include #include #include #include #include #include #define PR(x) cout << #x << " = " << (x) << endl; using namespace std; void usage(const char* prog) { cout << "Usage: " << prog << " [-n | -o output] file_mean_A2 file_mean_A" << endl; cout << "\t\t\t" << "-n Do not create the new tables but perform all checks" << endl; cout << "\t\t\t" << "-o file Output file where new table gets stored" << endl; } TH3F* getHistoFromFile(string&); int main(int argc, char **argv) { // // Handle command line arguments // if (argc < 3) { usage(argv[0]); return 2; } bool noOutput = false; bool printOnly = false; string outputFile; int ch; while ((ch = getopt(argc, argv, "no:")) != -1) { switch (ch) { case 'o': outputFile = string(optarg); break; case 'n': noOutput = true; break; case '?': default: usage(argv[0]); return 2; break; } } if (optind == argc) { usage(argv[0]); return 2; } if (noOutput && !outputFile.empty()) { usage(argv[0]); return 2; } printOnly = (!noOutput && outputFile.empty()); vector inputFiles; for (int index = optind; index < argc; index++) inputFiles.push_back(string(argv[index])); if (inputFiles.size() != 2) { usage(argv[0]); return 2; } // // First we perform all possible checks to ensure the tables // are identical other than their content. Using the Table // class makes things easier. // Table t1, t2; bool ok = t1.read(inputFiles[0].c_str()); if (!ok) { cout << "Error: failed opening input file '" << inputFiles[0].c_str() << "'." << endl; return 1; } ok = t2.read(inputFiles[1].c_str()); if (!ok) { cout << "Error: failed opening input file '" << inputFiles[1].c_str() << "'." << endl; return 1; } ok = (t1.isMeanA() && t2.isMeanA2()) || (t1.isMeanA2() && t2.isMeanA()); // xor if (!ok) { cout << "Error: one input file must contain an amplitude mode of mean_A data, the other mean_A2 data." << endl; return 1; } if (t1.minQ2() != t2.minQ2()) { cout << "Error: lower Q2 bound is different for the two input tables." << endl; return 1; } if (t1.maxQ2() != t2.maxQ2()) { cout << "Error: upper Q2 bound is different for the two input tables." << endl; return 1; } if (t1.minW2() != t2.minW2()) { cout << "Error: lower W2 bound is different for the two input tables." << endl; return 1; } if (t1.maxW2() != t2.maxW2()) { cout << "Error: upper W2 bound is different for the two input tables." << endl; return 1; } if (t1.minT() != t2.minT()) { cout << "Error: lower t bound is different for the two input tables." << endl; return 1; } if (t1.maxT() != t2.maxT()) { cout << "Error: upper t bound is different for the two input tables." << endl; return 1; } if (t1.binWidthQ2() != t2.binWidthQ2()) { cout << "Error: Bin width of Q2 axis is different for the two input tables." << endl; return 1; } if (t1.binWidthW2() != t2.binWidthW2()) { cout << "Error: Bin width of Q2 axis is different for the two input tables." << endl; return 1; } if (t1.binWidthT() != t2.binWidthT()) { cout << "Error: Bin width of Q2 axis is different for the two input tables." << endl; return 1; } if (t1.polarization() != t2.polarization()) { cout << "Error: The two input files hold amplitudes for different polarizations." << endl; return 1; } if (t1.A() != t2.A()) { cout << "Error: The two input files are for different nuclei A." << endl; return 1; } if (t1.vectorMesonId() != t2.vectorMesonId()) { cout << "Error: The two input files are for different vector mesons." << endl; return 1; } if (t1.dipoleModelType() != t2.dipoleModelType()) { cout << "Error: The two input files are for different dipole models." << endl; return 1; } if (t1.dipoleModelParameterSet() != t2.dipoleModelParameterSet()) { cout << "Error: The two input files are were generated with different dipole model parameter sets." << endl; return 1; } if (t1.priority() != t2.priority()) { cout << "Error: The two input files are were generated with different priorities." << endl; return 1; } // // If we get here the two histos should just work fine. Note that we // did not check if the axis are lin/log since if the upper/lower bound // and the bin width are the same we are good. // The *only* thing that matters from here on is if the content is in // lin or log. // cout << "OK - The two input files are consistent and can be used to create a variance_A table." << endl; if (noOutput) return 0; // // Order input files: first = mean_A2, second = mean_A // pair rootfiles(inputFiles[0], inputFiles[1]); if (rootfiles.first != t1.isMeanA2()) swap(rootfiles.first, rootfiles.second); // // Open the files and get the two tables to deal with. // // pair histograms; histograms.first = getHistoFromFile(rootfiles.first); histograms.second = getHistoFromFile(rootfiles.second); // // Create the variance histogram and set the ID. // Also find our if the content is in log or lin. // TH3F* vhisto = reinterpret_cast(histograms.first->Clone()); vhisto->SetDirectory(0); uint64_t theID = atoll(vhisto->GetTitle()); // set bit 0 and 33 to 0, set bit 45 bitset<64> bits(theID); bits[0] = 0; bits[33] = 0; bits[45] = 1; theID = bits.to_ullong(); ostringstream titlestream; titlestream << theID; string title = titlestream.str(); vhisto->Reset("M"); vhisto->SetTitle(title.c_str()); bool varianceAndA2HaveLogContent = bits.test(32); uint64_t meanA_ID = atoll(histograms.second->GetTitle()); bitset<64> meanA_Bits(meanA_ID); bool meanAHasLogContent = meanA_Bits.test(32); cout << "Created new table in memory." << endl; // // Fill the variance histo (all calculations happen here) // int nx = vhisto->GetNbinsX(); int ny = vhisto->GetNbinsY(); int nz = vhisto->GetNbinsZ(); for (int ix = 1; ix <= nx; ix++) { for (int iy = 1; iy <= ny; iy++) { for (int iz = 1; iz <= nz; iz++) { // old table double A2_Content = histograms.first->GetBinContent(ix, iy, iz); double A_Content = histograms.second->GetBinContent(ix, iy, iz); if (varianceAndA2HaveLogContent) A2_Content = exp(A2_Content); if (meanAHasLogContent) A_Content = exp(A_Content); double variance = A2_Content - A_Content*A_Content; if (printOnly) { cout << "bin = " << ix << ", " << iy << ", " << iz << "; mean_A2 = " << A2_Content << ", mean_A = " << A_Content << ", variance_A = " << variance << " (" << (varianceAndA2HaveLogContent? log(variance) : variance) << ")" << endl; } if (varianceAndA2HaveLogContent) variance = log(variance); vhisto->SetBinContent(ix, iy, iz, variance); vhisto->SetBinError(ix, iy, iz, 0); } } } cout << "Variance table is filled. Content is stored in " << (varianceAndA2HaveLogContent ? "log" : "lin") << " scale." << endl; // // Store the table // if (!outputFile.empty()) { cout << "Attempting to write table into new file '" << outputFile << "'." << endl; TFile *hfile = new TFile(outputFile.c_str(),"NEW"); if (hfile && hfile->IsZombie()) return 1; if (!hfile) { cout << "Error writing variance table. Cannot open new file '" << outputFile.c_str() << "'." << endl; } else { vhisto->Write(); hfile->Close(); cout << "Variance table written to file '" << outputFile.c_str() << "'." << endl; delete vhisto; delete histograms.first; delete histograms.second; } } cout << "All done. Bye." << endl; return 0; } TH3F* getHistoFromFile(string& filename) { TFile *file = TFile::Open(filename.c_str(),"READ"); if (file == 0) { cout << "Error: failed opening file '" << filename.c_str() << "'." << endl; exit(1); } TH3F *histo = reinterpret_cast(file->Get("table")); if (histo == 0) { cout << "Error: failed retrieving table from file '" << filename.c_str() << "'." << endl; exit(1); } histo->SetDirectory(0); file->Close(); return histo; } Index: trunk/src/ModeFinderFunctor.h =================================================================== --- trunk/src/ModeFinderFunctor.h (revision 369) +++ trunk/src/ModeFinderFunctor.h (revision 370) @@ -1,70 +1,70 @@ //============================================================================== // ModeFinderFunctor.h // -// Copyright (C) 2010-2013 Tobias Toll and Thomas Ullrich +// Copyright (C) 2010-2019 Tobias Toll and Thomas Ullrich // // This file is part of Sartre. // // 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. // 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, see . // // Author: Thomas Ullrich // Last update: // $Date$ // $Author$ //============================================================================== // // Functor class. // // Used by BrentMinimizer1D algotithm to find maxima in cross-section // in W2 for a given t and Q2. //============================================================================== #ifndef ModeFinderFunctor_h #define ModeFinderFunctor_h #include "Math/IFunction.h" class CrossSection; class ModeFinderFunctor : public ROOT::Math::IGenFunction { public: ModeFinderFunctor(); ModeFinderFunctor(CrossSection*, double Q2, double vmMass, double tmin, double tmax); double DoEval(double) const; ROOT::Math::IGenFunction* Clone() const; void setQ2(double); void setVmMass(double); void setMaxT(double); void setMinT(double); private: CrossSection *mCrossSection; double mQ2; double mVmMass; double mMinT; double mMaxT; }; class UPCModeFinderFunctor : public ROOT::Math::IGenFunction { public: UPCModeFinderFunctor(); UPCModeFinderFunctor(CrossSection*, double vmMass, double hBeamEnergy, double eBeamEnergy); double DoEval(double) const; // xpom ROOT::Math::IGenFunction* Clone() const; private: CrossSection *mCrossSection; double mVmMass; double mHBeamEnergy; double mEBeamEnergy; }; #endif Index: trunk/src/GridSplineInterpolateSums.h =================================================================== --- trunk/src/GridSplineInterpolateSums.h (revision 369) +++ trunk/src/GridSplineInterpolateSums.h (revision 370) @@ -1,191 +1,191 @@ //============================================================================== // GridSplineInterpolateSums.h // -// Copyright (C) 2010-2013 Tobias Toll and Thomas Ullrich +// Copyright (C) 2010-2019 Tobias Toll and Thomas Ullrich // // This file is part of Sartre. // // 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. // 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, see . // // Author: Thomas Ullrich // Last update: // $Date$ // $Author$ //============================================================================== // // Sums that are performed for interpolations, written explicitely // using these expanded forms will always result in a faster code // // This algorithm was written by Cristian Lalescu. // See http://arxiv.org/abs/0905.3564 for details. // The code here is slightly modified for use in Sartre. // //============================================================================== #ifndef GridSplineInterpolateSums_h #define GridSplineInterpolateSums_h #define SUM_1D_Q4_unsafe_macro(f, bx) \ ((f(-1)*bx(-1) + f( 0)*bx( 0))+(f( 1)*bx( 1) + f( 2)*bx( 2))) #define SUM_2D_Q4_unsafe_macro(f, bx, by) \ ((((f(-1,-1)*bx(-1) + f( 0,-1)*bx( 0))+(f( 1,-1)*bx( 1) + f( 2,-1)*bx( 2)))*by(-1) \ + ((f(-1, 0)*bx(-1) + f( 0, 0)*bx( 0))+(f( 1, 0)*bx( 1) + f( 2, 0)*bx( 2)))*by( 0))\ +(((f(-1, 1)*bx(-1) + f( 0, 1)*bx( 0))+(f( 1, 1)*bx( 1) + f( 2, 1)*bx( 2)))*by( 1) \ + ((f(-1, 2)*bx(-1) + f( 0, 2)*bx( 0))+(f( 1, 2)*bx( 1) + f( 2, 2)*bx( 2)))*by( 2))) #define SUM_3D_Q4_unsafe_macro(f, bx, by, bz) \ ((((((f(-1,-1,-1)*bx(-1) + f( 0,-1,-1)*bx( 0))+(f( 1,-1,-1)*bx( 1) + f( 2,-1,-1)*bx( 2)))*by(-1) \ + ((f(-1, 0,-1)*bx(-1) + f( 0, 0,-1)*bx( 0))+(f( 1, 0,-1)*bx( 1) + f( 2, 0,-1)*bx( 2)))*by( 0)) \ +(((f(-1, 1,-1)*bx(-1) + f( 0, 1,-1)*bx( 0))+(f( 1, 1,-1)*bx( 1) + f( 2, 1,-1)*bx( 2)))*by( 1) \ + ((f(-1, 2,-1)*bx(-1) + f( 0, 2,-1)*bx( 0))+(f( 1, 2,-1)*bx( 1) + f( 2, 2,-1)*bx( 2)))*by( 2)))*bz(-1) \ + ((((f(-1,-1, 0)*bx(-1) + f( 0,-1, 0)*bx( 0))+(f( 1,-1, 0)*bx( 1) + f( 2,-1, 0)*bx( 2)))*by(-1) \ + ((f(-1, 0, 0)*bx(-1) + f( 0, 0, 0)*bx( 0))+(f( 1, 0, 0)*bx( 1) + f( 2, 0, 0)*bx( 2)))*by( 0)) \ +(((f(-1, 1, 0)*bx(-1) + f( 0, 1, 0)*bx( 0))+(f( 1, 1, 0)*bx( 1) + f( 2, 1, 0)*bx( 2)))*by( 1) \ + ((f(-1, 2, 0)*bx(-1) + f( 0, 2, 0)*bx( 0))+(f( 1, 2, 0)*bx( 1) + f( 2, 2, 0)*bx( 2)))*by( 2)))*bz( 0))\ +(((((f(-1,-1, 1)*bx(-1) + f( 0,-1, 1)*bx( 0))+(f( 1,-1, 1)*bx( 1) + f( 2,-1, 1)*bx( 2)))*by(-1) \ + ((f(-1, 0, 1)*bx(-1) + f( 0, 0, 1)*bx( 0))+(f( 1, 0, 1)*bx( 1) + f( 2, 0, 1)*bx( 2)))*by( 0)) \ +(((f(-1, 1, 1)*bx(-1) + f( 0, 1, 1)*bx( 0))+(f( 1, 1, 1)*bx( 1) + f( 2, 1, 1)*bx( 2)))*by( 1) \ + ((f(-1, 2, 1)*bx(-1) + f( 0, 2, 1)*bx( 0))+(f( 1, 2, 1)*bx( 1) + f( 2, 2, 1)*bx( 2)))*by( 2)))*bz( 1) \ + ((((f(-1,-1, 2)*bx(-1) + f( 0,-1, 2)*bx( 0))+(f( 1,-1, 2)*bx( 1) + f( 2,-1, 2)*bx( 2)))*by(-1) \ + ((f(-1, 0, 2)*bx(-1) + f( 0, 0, 2)*bx( 0))+(f( 1, 0, 2)*bx( 1) + f( 2, 0, 2)*bx( 2)))*by( 0)) \ +(((f(-1, 1, 2)*bx(-1) + f( 0, 1, 2)*bx( 0))+(f( 1, 1, 2)*bx( 1) + f( 2, 1, 2)*bx( 2)))*by( 1) \ + ((f(-1, 2, 2)*bx(-1) + f( 0, 2, 2)*bx( 0))+(f( 1, 2, 2)*bx( 1) + f( 2, 2, 2)*bx( 2)))*by( 2)))*bz( 2))) #define SUM_1D_Q6_unsafe_macro(f, bx) \ (((f(-2)*bx(-2) + f(-1)*bx(-1))+ f( 0)*bx( 0))+(f( 1)*bx( 1) +(f( 2)*bx( 2) + f( 3)*bx( 3)))) #define SUM_2D_Q6_unsafe_macro(f, bx, by) \ ((((((f(-2,-2)*bx(-2) + f(-1,-2)*bx(-1))+ f( 0,-2)*bx( 0))+(f( 1,-2)*bx( 1) +(f( 2,-2)*bx( 2) + f( 3,-2)*bx( 3))))*by(-2) \ + (((f(-2,-1)*bx(-2) + f(-1,-1)*bx(-1))+ f( 0,-1)*bx( 0))+(f( 1,-1)*bx( 1) +(f( 2,-1)*bx( 2) + f( 3,-1)*bx( 3))))*by(-1)) \ + (((f(-2, 0)*bx(-2) + f(-1, 0)*bx(-1))+ f( 0, 0)*bx( 0))+(f( 1, 0)*bx( 1) +(f( 2, 0)*bx( 2) + f( 3, 0)*bx( 3))))*by( 0)) \ + ((((f(-2, 1)*bx(-2) + f(-1, 1)*bx(-1))+ f( 0, 1)*bx( 0))+(f( 1, 1)*bx( 1) +(f( 2, 1)*bx( 2) + f( 3, 1)*bx( 3))))*by( 1) \ + ((((f(-2, 2)*bx(-2) + f(-1, 2)*bx(-1))+ f( 0, 2)*bx( 0))+(f( 1, 2)*bx( 1) +(f( 2, 2)*bx( 2) + f( 3, 2)*bx( 3))))*by( 2) \ + (((f(-2, 3)*bx(-2) + f(-1, 3)*bx(-1))+ f( 0, 3)*bx( 0))+(f( 1, 3)*bx( 1) +(f( 2, 3)*bx( 2) + f( 3, 3)*bx( 3))))*by( 3)))) #define SUM_3D_Q6_unsafe_macro(f, bx, by, bz) \ (((((((((f(-2,-2,-2)*bx(-2) + f(-1,-2,-2)*bx(-1))+ f( 0,-2,-2)*bx( 0))+(f( 1,-2,-2)*bx( 1) +(f( 2,-2,-2)*bx( 2) + f( 3,-2,-2)*bx( 3))))*by(-2) \ + (((f(-2,-1,-2)*bx(-2) + f(-1,-1,-2)*bx(-1))+ f( 0,-1,-2)*bx( 0))+(f( 1,-1,-2)*bx( 1) +(f( 2,-1,-2)*bx( 2) + f( 3,-1,-2)*bx( 3))))*by(-1)) \ + (((f(-2, 0,-2)*bx(-2) + f(-1, 0,-2)*bx(-1))+ f( 0, 0,-2)*bx( 0))+(f( 1, 0,-2)*bx( 1) +(f( 2, 0,-2)*bx( 2) + f( 3, 0,-2)*bx( 3))))*by( 0)) \ + ((((f(-2, 1,-2)*bx(-2) + f(-1, 1,-2)*bx(-1))+ f( 0, 1,-2)*bx( 0))+(f( 1, 1,-2)*bx( 1) +(f( 2, 1,-2)*bx( 2) + f( 3, 1,-2)*bx( 3))))*by( 1) \ + ((((f(-2, 2,-2)*bx(-2) + f(-1, 2,-2)*bx(-1))+ f( 0, 2,-2)*bx( 0))+(f( 1, 2,-2)*bx( 1) +(f( 2, 2,-2)*bx( 2) + f( 3, 2,-2)*bx( 3))))*by( 2) \ + (((f(-2, 3,-2)*bx(-2) + f(-1, 3,-2)*bx(-1))+ f( 0, 3,-2)*bx( 0))+(f( 1, 3,-2)*bx( 1) +(f( 2, 3,-2)*bx( 2) + f( 3, 3,-2)*bx( 3))))*by( 3))))*bz(-2) \ + ((((((f(-2,-2,-1)*bx(-2) + f(-1,-2,-1)*bx(-1))+ f( 0,-2,-1)*bx( 0))+(f( 1,-2,-1)*bx( 1) +(f( 2,-2,-1)*bx( 2) + f( 3,-2,-1)*bx( 3))))*by(-2) \ + (((f(-2,-1,-1)*bx(-2) + f(-1,-1,-1)*bx(-1))+ f( 0,-1,-1)*bx( 0))+(f( 1,-1,-1)*bx( 1) +(f( 2,-1,-1)*bx( 2) + f( 3,-1,-1)*bx( 3))))*by(-1)) \ + (((f(-2, 0,-1)*bx(-2) + f(-1, 0,-1)*bx(-1))+ f( 0, 0,-1)*bx( 0))+(f( 1, 0,-1)*bx( 1) +(f( 2, 0,-1)*bx( 2) + f( 3, 0,-1)*bx( 3))))*by( 0)) \ + ((((f(-2, 1,-1)*bx(-2) + f(-1, 1,-1)*bx(-1))+ f( 0, 1,-1)*bx( 0))+(f( 1, 1,-1)*bx( 1) +(f( 2, 1,-1)*bx( 2) + f( 3, 1,-1)*bx( 3))))*by( 1) \ + ((((f(-2, 2,-1)*bx(-2) + f(-1, 2,-1)*bx(-1))+ f( 0, 2,-1)*bx( 0))+(f( 1, 2,-1)*bx( 1) +(f( 2, 2,-1)*bx( 2) + f( 3, 2,-1)*bx( 3))))*by( 2) \ + (((f(-2, 3,-1)*bx(-2) + f(-1, 3,-1)*bx(-1))+ f( 0, 3,-1)*bx( 0))+(f( 1, 3,-1)*bx( 1) +(f( 2, 3,-1)*bx( 2) + f( 3, 3,-1)*bx( 3))))*by( 3))))*bz(-1)) \ + ((((((f(-2,-2, 0)*bx(-2) + f(-1,-2, 0)*bx(-1))+ f( 0,-2, 0)*bx( 0))+(f( 1,-2, 0)*bx( 1) +(f( 2,-2, 0)*bx( 2) + f( 3,-2, 0)*bx( 3))))*by(-2) \ + (((f(-2,-1, 0)*bx(-2) + f(-1,-1, 0)*bx(-1))+ f( 0,-1, 0)*bx( 0))+(f( 1,-1, 0)*bx( 1) +(f( 2,-1, 0)*bx( 2) + f( 3,-1, 0)*bx( 3))))*by(-1)) \ + (((f(-2, 0, 0)*bx(-2) + f(-1, 0, 0)*bx(-1))+ f( 0, 0, 0)*bx( 0))+(f( 1, 0, 0)*bx( 1) +(f( 2, 0, 0)*bx( 2) + f( 3, 0, 0)*bx( 3))))*by( 0)) \ + ((((f(-2, 1, 0)*bx(-2) + f(-1, 1, 0)*bx(-1))+ f( 0, 1, 0)*bx( 0))+(f( 1, 1, 0)*bx( 1) +(f( 2, 1, 0)*bx( 2) + f( 3, 1, 0)*bx( 3))))*by( 1) \ + ((((f(-2, 2, 0)*bx(-2) + f(-1, 2, 0)*bx(-1))+ f( 0, 2, 0)*bx( 0))+(f( 1, 2, 0)*bx( 1) +(f( 2, 2, 0)*bx( 2) + f( 3, 2, 0)*bx( 3))))*by( 2) \ + (((f(-2, 3, 0)*bx(-2) + f(-1, 3, 0)*bx(-1))+ f( 0, 3, 0)*bx( 0))+(f( 1, 3, 0)*bx( 1) +(f( 2, 3, 0)*bx( 2) + f( 3, 3, 0)*bx( 3))))*by( 3))))*bz( 0)) \ +(((((((f(-2,-2, 1)*bx(-2) + f(-1,-2, 1)*bx(-1))+ f( 0,-2, 1)*bx( 0))+(f( 1,-2, 1)*bx( 1) +(f( 2,-2, 1)*bx( 2) + f( 3,-2, 1)*bx( 3))))*by(-2) \ + (((f(-2,-1, 1)*bx(-2) + f(-1,-1, 1)*bx(-1))+ f( 0,-1, 1)*bx( 0))+(f( 1,-1, 1)*bx( 1) +(f( 2,-1, 1)*bx( 2) + f( 3,-1, 1)*bx( 3))))*by(-1)) \ + (((f(-2, 0, 1)*bx(-2) + f(-1, 0, 1)*bx(-1))+ f( 0, 0, 1)*bx( 0))+(f( 1, 0, 1)*bx( 1) +(f( 2, 0, 1)*bx( 2) + f( 3, 0, 1)*bx( 3))))*by( 0)) \ + ((((f(-2, 1, 1)*bx(-2) + f(-1, 1, 1)*bx(-1))+ f( 0, 1, 1)*bx( 0))+(f( 1, 1, 1)*bx( 1) +(f( 2, 1, 1)*bx( 2) + f( 3, 1, 1)*bx( 3))))*by( 1) \ + ((((f(-2, 2, 1)*bx(-2) + f(-1, 2, 1)*bx(-1))+ f( 0, 2, 1)*bx( 0))+(f( 1, 2, 1)*bx( 1) +(f( 2, 2, 1)*bx( 2) + f( 3, 2, 1)*bx( 3))))*by( 2) \ + (((f(-2, 3, 1)*bx(-2) + f(-1, 3, 1)*bx(-1))+ f( 0, 3, 1)*bx( 0))+(f( 1, 3, 1)*bx( 1) +(f( 2, 3, 1)*bx( 2) + f( 3, 3, 1)*bx( 3))))*by( 3))))*bz( 1) \ + (((((((f(-2,-2, 2)*bx(-2) + f(-1,-2, 2)*bx(-1))+ f( 0,-2, 2)*bx( 0))+(f( 1,-2, 2)*bx( 1) +(f( 2,-2, 2)*bx( 2) + f( 3,-2, 2)*bx( 3))))*by(-2) \ + (((f(-2,-1, 2)*bx(-2) + f(-1,-1, 2)*bx(-1))+ f( 0,-1, 2)*bx( 0))+(f( 1,-1, 2)*bx( 1) +(f( 2,-1, 2)*bx( 2) + f( 3,-1, 2)*bx( 3))))*by(-1)) \ + (((f(-2, 0, 2)*bx(-2) + f(-1, 0, 2)*bx(-1))+ f( 0, 0, 2)*bx( 0))+(f( 1, 0, 2)*bx( 1) +(f( 2, 0, 2)*bx( 2) + f( 3, 0, 2)*bx( 3))))*by( 0)) \ + ((((f(-2, 1, 2)*bx(-2) + f(-1, 1, 2)*bx(-1))+ f( 0, 1, 2)*bx( 0))+(f( 1, 1, 2)*bx( 1) +(f( 2, 1, 2)*bx( 2) + f( 3, 1, 2)*bx( 3))))*by( 1) \ + ((((f(-2, 2, 2)*bx(-2) + f(-1, 2, 2)*bx(-1))+ f( 0, 2, 2)*bx( 0))+(f( 1, 2, 2)*bx( 1) +(f( 2, 2, 2)*bx( 2) + f( 3, 2, 2)*bx( 3))))*by( 2) \ + (((f(-2, 3, 2)*bx(-2) + f(-1, 3, 2)*bx(-1))+ f( 0, 3, 2)*bx( 0))+(f( 1, 3, 2)*bx( 1) +(f( 2, 3, 2)*bx( 2) + f( 3, 3, 2)*bx( 3))))*by( 3))))*bz( 2) \ + ((((((f(-2,-2, 3)*bx(-2) + f(-1,-2, 3)*bx(-1))+ f( 0,-2, 3)*bx( 0))+(f( 1,-2, 3)*bx( 1) +(f( 2,-2, 3)*bx( 2) + f( 3,-2, 3)*bx( 3))))*by(-2) \ + (((f(-2,-1, 3)*bx(-2) + f(-1,-1, 3)*bx(-1))+ f( 0,-1, 3)*bx( 0))+(f( 1,-1, 3)*bx( 1) +(f( 2,-1, 3)*bx( 2) + f( 3,-1, 3)*bx( 3))))*by(-1)) \ + (((f(-2, 0, 3)*bx(-2) + f(-1, 0, 3)*bx(-1))+ f( 0, 0, 3)*bx( 0))+(f( 1, 0, 3)*bx( 1) +(f( 2, 0, 3)*bx( 2) + f( 3, 0, 3)*bx( 3))))*by( 0)) \ + ((((f(-2, 1, 3)*bx(-2) + f(-1, 1, 3)*bx(-1))+ f( 0, 1, 3)*bx( 0))+(f( 1, 1, 3)*bx( 1) +(f( 2, 1, 3)*bx( 2) + f( 3, 1, 3)*bx( 3))))*by( 1) \ + ((((f(-2, 2, 3)*bx(-2) + f(-1, 2, 3)*bx(-1))+ f( 0, 2, 3)*bx( 0))+(f( 1, 2, 3)*bx( 1) +(f( 2, 2, 3)*bx( 2) + f( 3, 2, 3)*bx( 3))))*by( 2) \ + (((f(-2, 3, 3)*bx(-2) + f(-1, 3, 3)*bx(-1))+ f( 0, 3, 3)*bx( 0))+(f( 1, 3, 3)*bx( 1) +(f( 2, 3, 3)*bx( 2) + f( 3, 3, 3)*bx( 3))))*by( 3))))*bz( 3)))) #define SUM_1D_Q8_unsafe_macro(f, bx) \ ((((f(-3)*bx(-3) + f(-2)*bx(-2))+ f(-1)*bx(-1))+ f( 0)*bx( 0))+(f( 1)*bx( 1) +(f( 2)*bx( 2) +(f( 3)*bx( 3) + f( 4)*bx( 4))))) #define SUM_2D_Q8_unsafe_macro(f, bx, by) \ ((((((((f(-3,-3)*bx(-3) + f(-2,-3)*bx(-2))+ f(-1,-3)*bx(-1))+ f( 0,-3)*bx( 0))+(f( 1,-3)*bx( 1) +(f( 2,-3)*bx( 2) +(f( 3,-3)*bx( 3) + f( 4,-3)*bx( 4)))))*by(-3) \ +((((f(-3,-2)*bx(-3) + f(-2,-2)*bx(-2))+ f(-1,-2)*bx(-1))+ f( 0,-2)*bx( 0))+(f( 1,-2)*bx( 1) +(f( 2,-2)*bx( 2) +(f( 3,-2)*bx( 3) + f( 4,-2)*bx( 4)))))*by(-2)) \ +((((f(-3,-1)*bx(-3) + f(-2,-1)*bx(-2))+ f(-1,-1)*bx(-1))+ f( 0,-1)*bx( 0))+(f( 1,-1)*bx( 1) +(f( 2,-1)*bx( 2) +(f( 3,-1)*bx( 3) + f( 4,-1)*bx( 4)))))*by(-1)) \ +((((f(-3, 0)*bx(-3) + f(-2, 0)*bx(-2))+ f(-1, 0)*bx(-1))+ f( 0, 0)*bx( 0))+(f( 1, 0)*bx( 1) +(f( 2, 0)*bx( 2) +(f( 3, 0)*bx( 3) + f( 4, 0)*bx( 4)))))*by( 0)) \ +(((((f(-3, 1)*bx(-3) + f(-2, 1)*bx(-2))+ f(-1, 1)*bx(-1))+ f( 0, 1)*bx( 0))+(f( 1, 1)*bx( 1) +(f( 2, 1)*bx( 2) +(f( 3, 1)*bx( 3) + f( 4, 1)*bx( 4)))))*by( 1) \ +(((((f(-3, 2)*bx(-3) + f(-2, 2)*bx(-2))+ f(-1, 2)*bx(-1))+ f( 0, 2)*bx( 0))+(f( 1, 2)*bx( 1) +(f( 2, 2)*bx( 2) +(f( 3, 2)*bx( 3) + f( 4, 2)*bx( 4)))))*by( 2) \ +(((((f(-3, 3)*bx(-3) + f(-2, 3)*bx(-2))+ f(-1, 3)*bx(-1))+ f( 0, 3)*bx( 0))+(f( 1, 3)*bx( 1) +(f( 2, 3)*bx( 2) +(f( 3, 3)*bx( 3) + f( 4, 3)*bx( 4)))))*by( 3) \ +((((f(-3, 4)*bx(-3) + f(-2, 4)*bx(-2))+ f(-1, 4)*bx(-1))+ f( 0, 4)*bx( 0))+(f( 1, 4)*bx( 1) +(f( 2, 4)*bx( 2) +(f( 3, 4)*bx( 3) + f( 4, 4)*bx( 4)))))*by( 4))))) #define SUM_3D_Q8_unsafe_macro(f, bx, by, bz) \ ((((((((((((f(-3,-3,-3)*bx(-3) + f(-2,-3,-3)*bx(-2))+ f(-1,-3,-3)*bx(-1))+ f( 0,-3,-3)*bx( 0))+(f( 1,-3,-3)*bx( 1) +(f( 2,-3,-3)*bx( 2) +(f( 3,-3,-3)*bx( 3) + f( 4,-3,-3)*bx( 4)))))*by(-3) \ +((((f(-3,-2,-3)*bx(-3) + f(-2,-2,-3)*bx(-2))+ f(-1,-2,-3)*bx(-1))+ f( 0,-2,-3)*bx( 0))+(f( 1,-2,-3)*bx( 1) +(f( 2,-2,-3)*bx( 2) +(f( 3,-2,-3)*bx( 3) + f( 4,-2,-3)*bx( 4)))))*by(-2)) \ +((((f(-3,-1,-3)*bx(-3) + f(-2,-1,-3)*bx(-2))+ f(-1,-1,-3)*bx(-1))+ f( 0,-1,-3)*bx( 0))+(f( 1,-1,-3)*bx( 1) +(f( 2,-1,-3)*bx( 2) +(f( 3,-1,-3)*bx( 3) + f( 4,-1,-3)*bx( 4)))))*by(-1)) \ +((((f(-3, 0,-3)*bx(-3) + f(-2, 0,-3)*bx(-2))+ f(-1, 0,-3)*bx(-1))+ f( 0, 0,-3)*bx( 0))+(f( 1, 0,-3)*bx( 1) +(f( 2, 0,-3)*bx( 2) +(f( 3, 0,-3)*bx( 3) + f( 4, 0,-3)*bx( 4)))))*by( 0)) \ +(((((f(-3, 1,-3)*bx(-3) + f(-2, 1,-3)*bx(-2))+ f(-1, 1,-3)*bx(-1))+ f( 0, 1,-3)*bx( 0))+(f( 1, 1,-3)*bx( 1) +(f( 2, 1,-3)*bx( 2) +(f( 3, 1,-3)*bx( 3) + f( 4, 1,-3)*bx( 4)))))*by( 1) \ +(((((f(-3, 2,-3)*bx(-3) + f(-2, 2,-3)*bx(-2))+ f(-1, 2,-3)*bx(-1))+ f( 0, 2,-3)*bx( 0))+(f( 1, 2,-3)*bx( 1) +(f( 2, 2,-3)*bx( 2) +(f( 3, 2,-3)*bx( 3) + f( 4, 2,-3)*bx( 4)))))*by( 2) \ +(((((f(-3, 3,-3)*bx(-3) + f(-2, 3,-3)*bx(-2))+ f(-1, 3,-3)*bx(-1))+ f( 0, 3,-3)*bx( 0))+(f( 1, 3,-3)*bx( 1) +(f( 2, 3,-3)*bx( 2) +(f( 3, 3,-3)*bx( 3) + f( 4, 3,-3)*bx( 4)))))*by( 3) \ +((((f(-3, 4,-3)*bx(-3) + f(-2, 4,-3)*bx(-2))+ f(-1, 4,-3)*bx(-1))+ f( 0, 4,-3)*bx( 0))+(f( 1, 4,-3)*bx( 1) +(f( 2, 4,-3)*bx( 2) +(f( 3, 4,-3)*bx( 3) + f( 4, 4,-3)*bx( 4)))))*by( 4)))))*bz(-3) \ +((((((((f(-3,-3,-2)*bx(-3) + f(-2,-3,-2)*bx(-2))+ f(-1,-3,-2)*bx(-1))+ f( 0,-3,-2)*bx( 0))+(f( 1,-3,-2)*bx( 1) +(f( 2,-3,-2)*bx( 2) +(f( 3,-3,-2)*bx( 3) + f( 4,-3,-2)*bx( 4)))))*by(-3) \ +((((f(-3,-2,-2)*bx(-3) + f(-2,-2,-2)*bx(-2))+ f(-1,-2,-2)*bx(-1))+ f( 0,-2,-2)*bx( 0))+(f( 1,-2,-2)*bx( 1) +(f( 2,-2,-2)*bx( 2) +(f( 3,-2,-2)*bx( 3) + f( 4,-2,-2)*bx( 4)))))*by(-2)) \ +((((f(-3,-1,-2)*bx(-3) + f(-2,-1,-2)*bx(-2))+ f(-1,-1,-2)*bx(-1))+ f( 0,-1,-2)*bx( 0))+(f( 1,-1,-2)*bx( 1) +(f( 2,-1,-2)*bx( 2) +(f( 3,-1,-2)*bx( 3) + f( 4,-1,-2)*bx( 4)))))*by(-1)) \ +((((f(-3, 0,-2)*bx(-3) + f(-2, 0,-2)*bx(-2))+ f(-1, 0,-2)*bx(-1))+ f( 0, 0,-2)*bx( 0))+(f( 1, 0,-2)*bx( 1) +(f( 2, 0,-2)*bx( 2) +(f( 3, 0,-2)*bx( 3) + f( 4, 0,-2)*bx( 4)))))*by( 0)) \ +(((((f(-3, 1,-2)*bx(-3) + f(-2, 1,-2)*bx(-2))+ f(-1, 1,-2)*bx(-1))+ f( 0, 1,-2)*bx( 0))+(f( 1, 1,-2)*bx( 1) +(f( 2, 1,-2)*bx( 2) +(f( 3, 1,-2)*bx( 3) + f( 4, 1,-2)*bx( 4)))))*by( 1) \ +(((((f(-3, 2,-2)*bx(-3) + f(-2, 2,-2)*bx(-2))+ f(-1, 2,-2)*bx(-1))+ f( 0, 2,-2)*bx( 0))+(f( 1, 2,-2)*bx( 1) +(f( 2, 2,-2)*bx( 2) +(f( 3, 2,-2)*bx( 3) + f( 4, 2,-2)*bx( 4)))))*by( 2) \ +(((((f(-3, 3,-2)*bx(-3) + f(-2, 3,-2)*bx(-2))+ f(-1, 3,-2)*bx(-1))+ f( 0, 3,-2)*bx( 0))+(f( 1, 3,-2)*bx( 1) +(f( 2, 3,-2)*bx( 2) +(f( 3, 3,-2)*bx( 3) + f( 4, 3,-2)*bx( 4)))))*by( 3) \ +((((f(-3, 4,-2)*bx(-3) + f(-2, 4,-2)*bx(-2))+ f(-1, 4,-2)*bx(-1))+ f( 0, 4,-2)*bx( 0))+(f( 1, 4,-2)*bx( 1) +(f( 2, 4,-2)*bx( 2) +(f( 3, 4,-2)*bx( 3) + f( 4, 4,-2)*bx( 4)))))*by( 4)))))*bz(-2)) \ +((((((((f(-3,-3,-1)*bx(-3) + f(-2,-3,-1)*bx(-2))+ f(-1,-3,-1)*bx(-1))+ f( 0,-3,-1)*bx( 0))+(f( 1,-3,-1)*bx( 1) +(f( 2,-3,-1)*bx( 2) +(f( 3,-3,-1)*bx( 3) + f( 4,-3,-1)*bx( 4)))))*by(-3) \ +((((f(-3,-2,-1)*bx(-3) + f(-2,-2,-1)*bx(-2))+ f(-1,-2,-1)*bx(-1))+ f( 0,-2,-1)*bx( 0))+(f( 1,-2,-1)*bx( 1) +(f( 2,-2,-1)*bx( 2) +(f( 3,-2,-1)*bx( 3) + f( 4,-2,-1)*bx( 4)))))*by(-2)) \ +((((f(-3,-1,-1)*bx(-3) + f(-2,-1,-1)*bx(-2))+ f(-1,-1,-1)*bx(-1))+ f( 0,-1,-1)*bx( 0))+(f( 1,-1,-1)*bx( 1) +(f( 2,-1,-1)*bx( 2) +(f( 3,-1,-1)*bx( 3) + f( 4,-1,-1)*bx( 4)))))*by(-1)) \ +((((f(-3, 0,-1)*bx(-3) + f(-2, 0,-1)*bx(-2))+ f(-1, 0,-1)*bx(-1))+ f( 0, 0,-1)*bx( 0))+(f( 1, 0,-1)*bx( 1) +(f( 2, 0,-1)*bx( 2) +(f( 3, 0,-1)*bx( 3) + f( 4, 0,-1)*bx( 4)))))*by( 0)) \ +(((((f(-3, 1,-1)*bx(-3) + f(-2, 1,-1)*bx(-2))+ f(-1, 1,-1)*bx(-1))+ f( 0, 1,-1)*bx( 0))+(f( 1, 1,-1)*bx( 1) +(f( 2, 1,-1)*bx( 2) +(f( 3, 1,-1)*bx( 3) + f( 4, 1,-1)*bx( 4)))))*by( 1) \ +(((((f(-3, 2,-1)*bx(-3) + f(-2, 2,-1)*bx(-2))+ f(-1, 2,-1)*bx(-1))+ f( 0, 2,-1)*bx( 0))+(f( 1, 2,-1)*bx( 1) +(f( 2, 2,-1)*bx( 2) +(f( 3, 2,-1)*bx( 3) + f( 4, 2,-1)*bx( 4)))))*by( 2) \ +(((((f(-3, 3,-1)*bx(-3) + f(-2, 3,-1)*bx(-2))+ f(-1, 3,-1)*bx(-1))+ f( 0, 3,-1)*bx( 0))+(f( 1, 3,-1)*bx( 1) +(f( 2, 3,-1)*bx( 2) +(f( 3, 3,-1)*bx( 3) + f( 4, 3,-1)*bx( 4)))))*by( 3) \ +((((f(-3, 4,-1)*bx(-3) + f(-2, 4,-1)*bx(-2))+ f(-1, 4,-1)*bx(-1))+ f( 0, 4,-1)*bx( 0))+(f( 1, 4,-1)*bx( 1) +(f( 2, 4,-1)*bx( 2) +(f( 3, 4,-1)*bx( 3) + f( 4, 4,-1)*bx( 4)))))*by( 4)))))*bz(-1)) \ +((((((((f(-3,-3, 0)*bx(-3) + f(-2,-3, 0)*bx(-2))+ f(-1,-3, 0)*bx(-1))+ f( 0,-3, 0)*bx( 0))+(f( 1,-3, 0)*bx( 1) +(f( 2,-3, 0)*bx( 2) +(f( 3,-3, 0)*bx( 3) + f( 4,-3, 0)*bx( 4)))))*by(-3) \ +((((f(-3,-2, 0)*bx(-3) + f(-2,-2, 0)*bx(-2))+ f(-1,-2, 0)*bx(-1))+ f( 0,-2, 0)*bx( 0))+(f( 1,-2, 0)*bx( 1) +(f( 2,-2, 0)*bx( 2) +(f( 3,-2, 0)*bx( 3) + f( 4,-2, 0)*bx( 4)))))*by(-2)) \ +((((f(-3,-1, 0)*bx(-3) + f(-2,-1, 0)*bx(-2))+ f(-1,-1, 0)*bx(-1))+ f( 0,-1, 0)*bx( 0))+(f( 1,-1, 0)*bx( 1) +(f( 2,-1, 0)*bx( 2) +(f( 3,-1, 0)*bx( 3) + f( 4,-1, 0)*bx( 4)))))*by(-1)) \ +((((f(-3, 0, 0)*bx(-3) + f(-2, 0, 0)*bx(-2))+ f(-1, 0, 0)*bx(-1))+ f( 0, 0, 0)*bx( 0))+(f( 1, 0, 0)*bx( 1) +(f( 2, 0, 0)*bx( 2) +(f( 3, 0, 0)*bx( 3) + f( 4, 0, 0)*bx( 4)))))*by( 0)) \ +(((((f(-3, 1, 0)*bx(-3) + f(-2, 1, 0)*bx(-2))+ f(-1, 1, 0)*bx(-1))+ f( 0, 1, 0)*bx( 0))+(f( 1, 1, 0)*bx( 1) +(f( 2, 1, 0)*bx( 2) +(f( 3, 1, 0)*bx( 3) + f( 4, 1, 0)*bx( 4)))))*by( 1) \ +(((((f(-3, 2, 0)*bx(-3) + f(-2, 2, 0)*bx(-2))+ f(-1, 2, 0)*bx(-1))+ f( 0, 2, 0)*bx( 0))+(f( 1, 2, 0)*bx( 1) +(f( 2, 2, 0)*bx( 2) +(f( 3, 2, 0)*bx( 3) + f( 4, 2, 0)*bx( 4)))))*by( 2) \ +(((((f(-3, 3, 0)*bx(-3) + f(-2, 3, 0)*bx(-2))+ f(-1, 3, 0)*bx(-1))+ f( 0, 3, 0)*bx( 0))+(f( 1, 3, 0)*bx( 1) +(f( 2, 3, 0)*bx( 2) +(f( 3, 3, 0)*bx( 3) + f( 4, 3, 0)*bx( 4)))))*by( 3) \ +((((f(-3, 4, 0)*bx(-3) + f(-2, 4, 0)*bx(-2))+ f(-1, 4, 0)*bx(-1))+ f( 0, 4, 0)*bx( 0))+(f( 1, 4, 0)*bx( 1) +(f( 2, 4, 0)*bx( 2) +(f( 3, 4, 0)*bx( 3) + f( 4, 4, 0)*bx( 4)))))*by( 4)))))*bz( 0)) \ + (((((((((f(-3,-3, 1)*bx(-3) + f(-2,-3, 1)*bx(-2))+ f(-1,-3, 1)*bx(-1))+ f( 0,-3, 1)*bx( 0))+(f( 1,-3, 1)*bx( 1) +(f( 2,-3, 1)*bx( 2) +(f( 3,-3, 1)*bx( 3) + f( 4,-3, 1)*bx( 4)))))*by(-3) \ +((((f(-3,-2, 1)*bx(-3) + f(-2,-2, 1)*bx(-2))+ f(-1,-2, 1)*bx(-1))+ f( 0,-2, 1)*bx( 0))+(f( 1,-2, 1)*bx( 1) +(f( 2,-2, 1)*bx( 2) +(f( 3,-2, 1)*bx( 3) + f( 4,-2, 1)*bx( 4)))))*by(-2)) \ +((((f(-3,-1, 1)*bx(-3) + f(-2,-1, 1)*bx(-2))+ f(-1,-1, 1)*bx(-1))+ f( 0,-1, 1)*bx( 0))+(f( 1,-1, 1)*bx( 1) +(f( 2,-1, 1)*bx( 2) +(f( 3,-1, 1)*bx( 3) + f( 4,-1, 1)*bx( 4)))))*by(-1)) \ +((((f(-3, 0, 1)*bx(-3) + f(-2, 0, 1)*bx(-2))+ f(-1, 0, 1)*bx(-1))+ f( 0, 0, 1)*bx( 0))+(f( 1, 0, 1)*bx( 1) +(f( 2, 0, 1)*bx( 2) +(f( 3, 0, 1)*bx( 3) + f( 4, 0, 1)*bx( 4)))))*by( 0)) \ +(((((f(-3, 1, 1)*bx(-3) + f(-2, 1, 1)*bx(-2))+ f(-1, 1, 1)*bx(-1))+ f( 0, 1, 1)*bx( 0))+(f( 1, 1, 1)*bx( 1) +(f( 2, 1, 1)*bx( 2) +(f( 3, 1, 1)*bx( 3) + f( 4, 1, 1)*bx( 4)))))*by( 1) \ +(((((f(-3, 2, 1)*bx(-3) + f(-2, 2, 1)*bx(-2))+ f(-1, 2, 1)*bx(-1))+ f( 0, 2, 1)*bx( 0))+(f( 1, 2, 1)*bx( 1) +(f( 2, 2, 1)*bx( 2) +(f( 3, 2, 1)*bx( 3) + f( 4, 2, 1)*bx( 4)))))*by( 2) \ +(((((f(-3, 3, 1)*bx(-3) + f(-2, 3, 1)*bx(-2))+ f(-1, 3, 1)*bx(-1))+ f( 0, 3, 1)*bx( 0))+(f( 1, 3, 1)*bx( 1) +(f( 2, 3, 1)*bx( 2) +(f( 3, 3, 1)*bx( 3) + f( 4, 3, 1)*bx( 4)))))*by( 3) \ +((((f(-3, 4, 1)*bx(-3) + f(-2, 4, 1)*bx(-2))+ f(-1, 4, 1)*bx(-1))+ f( 0, 4, 1)*bx( 0))+(f( 1, 4, 1)*bx( 1) +(f( 2, 4, 1)*bx( 2) +(f( 3, 4, 1)*bx( 3) + f( 4, 4, 1)*bx( 4)))))*by( 4)))))*bz( 1) \ +(((((((((f(-3,-3, 2)*bx(-3) + f(-2,-3, 2)*bx(-2))+ f(-1,-3, 2)*bx(-1))+ f( 0,-3, 2)*bx( 0))+(f( 1,-3, 2)*bx( 1) +(f( 2,-3, 2)*bx( 2) +(f( 3,-3, 2)*bx( 3) + f( 4,-3, 2)*bx( 4)))))*by(-3) \ +((((f(-3,-2, 2)*bx(-3) + f(-2,-2, 2)*bx(-2))+ f(-1,-2, 2)*bx(-1))+ f( 0,-2, 2)*bx( 0))+(f( 1,-2, 2)*bx( 1) +(f( 2,-2, 2)*bx( 2) +(f( 3,-2, 2)*bx( 3) + f( 4,-2, 2)*bx( 4)))))*by(-2)) \ +((((f(-3,-1, 2)*bx(-3) + f(-2,-1, 2)*bx(-2))+ f(-1,-1, 2)*bx(-1))+ f( 0,-1, 2)*bx( 0))+(f( 1,-1, 2)*bx( 1) +(f( 2,-1, 2)*bx( 2) +(f( 3,-1, 2)*bx( 3) + f( 4,-1, 2)*bx( 4)))))*by(-1)) \ +((((f(-3, 0, 2)*bx(-3) + f(-2, 0, 2)*bx(-2))+ f(-1, 0, 2)*bx(-1))+ f( 0, 0, 2)*bx( 0))+(f( 1, 0, 2)*bx( 1) +(f( 2, 0, 2)*bx( 2) +(f( 3, 0, 2)*bx( 3) + f( 4, 0, 2)*bx( 4)))))*by( 0)) \ +(((((f(-3, 1, 2)*bx(-3) + f(-2, 1, 2)*bx(-2))+ f(-1, 1, 2)*bx(-1))+ f( 0, 1, 2)*bx( 0))+(f( 1, 1, 2)*bx( 1) +(f( 2, 1, 2)*bx( 2) +(f( 3, 1, 2)*bx( 3) + f( 4, 1, 2)*bx( 4)))))*by( 1) \ +(((((f(-3, 2, 2)*bx(-3) + f(-2, 2, 2)*bx(-2))+ f(-1, 2, 2)*bx(-1))+ f( 0, 2, 2)*bx( 0))+(f( 1, 2, 2)*bx( 1) +(f( 2, 2, 2)*bx( 2) +(f( 3, 2, 2)*bx( 3) + f( 4, 2, 2)*bx( 4)))))*by( 2) \ +(((((f(-3, 3, 2)*bx(-3) + f(-2, 3, 2)*bx(-2))+ f(-1, 3, 2)*bx(-1))+ f( 0, 3, 2)*bx( 0))+(f( 1, 3, 2)*bx( 1) +(f( 2, 3, 2)*bx( 2) +(f( 3, 3, 2)*bx( 3) + f( 4, 3, 2)*bx( 4)))))*by( 3) \ +((((f(-3, 4, 2)*bx(-3) + f(-2, 4, 2)*bx(-2))+ f(-1, 4, 2)*bx(-1))+ f( 0, 4, 2)*bx( 0))+(f( 1, 4, 2)*bx( 1) +(f( 2, 4, 2)*bx( 2) +(f( 3, 4, 2)*bx( 3) + f( 4, 4, 2)*bx( 4)))))*by( 4)))))*bz( 2) \ +(((((((((f(-3,-3, 3)*bx(-3) + f(-2,-3, 3)*bx(-2))+ f(-1,-3, 3)*bx(-1))+ f( 0,-3, 3)*bx( 0))+(f( 1,-3, 3)*bx( 1) +(f( 2,-3, 3)*bx( 2) +(f( 3,-3, 3)*bx( 3) + f( 4,-3, 3)*bx( 4)))))*by(-3) \ +((((f(-3,-2, 3)*bx(-3) + f(-2,-2, 3)*bx(-2))+ f(-1,-2, 3)*bx(-1))+ f( 0,-2, 3)*bx( 0))+(f( 1,-2, 3)*bx( 1) +(f( 2,-2, 3)*bx( 2) +(f( 3,-2, 3)*bx( 3) + f( 4,-2, 3)*bx( 4)))))*by(-2)) \ +((((f(-3,-1, 3)*bx(-3) + f(-2,-1, 3)*bx(-2))+ f(-1,-1, 3)*bx(-1))+ f( 0,-1, 3)*bx( 0))+(f( 1,-1, 3)*bx( 1) +(f( 2,-1, 3)*bx( 2) +(f( 3,-1, 3)*bx( 3) + f( 4,-1, 3)*bx( 4)))))*by(-1)) \ +((((f(-3, 0, 3)*bx(-3) + f(-2, 0, 3)*bx(-2))+ f(-1, 0, 3)*bx(-1))+ f( 0, 0, 3)*bx( 0))+(f( 1, 0, 3)*bx( 1) +(f( 2, 0, 3)*bx( 2) +(f( 3, 0, 3)*bx( 3) + f( 4, 0, 3)*bx( 4)))))*by( 0)) \ +(((((f(-3, 1, 3)*bx(-3) + f(-2, 1, 3)*bx(-2))+ f(-1, 1, 3)*bx(-1))+ f( 0, 1, 3)*bx( 0))+(f( 1, 1, 3)*bx( 1) +(f( 2, 1, 3)*bx( 2) +(f( 3, 1, 3)*bx( 3) + f( 4, 1, 3)*bx( 4)))))*by( 1) \ +(((((f(-3, 2, 3)*bx(-3) + f(-2, 2, 3)*bx(-2))+ f(-1, 2, 3)*bx(-1))+ f( 0, 2, 3)*bx( 0))+(f( 1, 2, 3)*bx( 1) +(f( 2, 2, 3)*bx( 2) +(f( 3, 2, 3)*bx( 3) + f( 4, 2, 3)*bx( 4)))))*by( 2) \ +(((((f(-3, 3, 3)*bx(-3) + f(-2, 3, 3)*bx(-2))+ f(-1, 3, 3)*bx(-1))+ f( 0, 3, 3)*bx( 0))+(f( 1, 3, 3)*bx( 1) +(f( 2, 3, 3)*bx( 2) +(f( 3, 3, 3)*bx( 3) + f( 4, 3, 3)*bx( 4)))))*by( 3) \ +((((f(-3, 4, 3)*bx(-3) + f(-2, 4, 3)*bx(-2))+ f(-1, 4, 3)*bx(-1))+ f( 0, 4, 3)*bx( 0))+(f( 1, 4, 3)*bx( 1) +(f( 2, 4, 3)*bx( 2) +(f( 3, 4, 3)*bx( 3) + f( 4, 4, 3)*bx( 4)))))*by( 4)))))*bz( 3) \ +((((((((f(-3,-3, 4)*bx(-3) + f(-2,-3, 4)*bx(-2))+ f(-1,-3, 4)*bx(-1))+ f( 0,-3, 4)*bx( 0))+(f( 1,-3, 4)*bx( 1) +(f( 2,-3, 4)*bx( 2) +(f( 3,-3, 4)*bx( 3) + f( 4,-3, 4)*bx( 4)))))*by(-3) \ +((((f(-3,-2, 4)*bx(-3) + f(-2,-2, 4)*bx(-2))+ f(-1,-2, 4)*bx(-1))+ f( 0,-2, 4)*bx( 0))+(f( 1,-2, 4)*bx( 1) +(f( 2,-2, 4)*bx( 2) +(f( 3,-2, 4)*bx( 3) + f( 4,-2, 4)*bx( 4)))))*by(-2)) \ +((((f(-3,-1, 4)*bx(-3) + f(-2,-1, 4)*bx(-2))+ f(-1,-1, 4)*bx(-1))+ f( 0,-1, 4)*bx( 0))+(f( 1,-1, 4)*bx( 1) +(f( 2,-1, 4)*bx( 2) +(f( 3,-1, 4)*bx( 3) + f( 4,-1, 4)*bx( 4)))))*by(-1)) \ +((((f(-3, 0, 4)*bx(-3) + f(-2, 0, 4)*bx(-2))+ f(-1, 0, 4)*bx(-1))+ f( 0, 0, 4)*bx( 0))+(f( 1, 0, 4)*bx( 1) +(f( 2, 0, 4)*bx( 2) +(f( 3, 0, 4)*bx( 3) + f( 4, 0, 4)*bx( 4)))))*by( 0)) \ +(((((f(-3, 1, 4)*bx(-3) + f(-2, 1, 4)*bx(-2))+ f(-1, 1, 4)*bx(-1))+ f( 0, 1, 4)*bx( 0))+(f( 1, 1, 4)*bx( 1) +(f( 2, 1, 4)*bx( 2) +(f( 3, 1, 4)*bx( 3) + f( 4, 1, 4)*bx( 4)))))*by( 1) \ +(((((f(-3, 2, 4)*bx(-3) + f(-2, 2, 4)*bx(-2))+ f(-1, 2, 4)*bx(-1))+ f( 0, 2, 4)*bx( 0))+(f( 1, 2, 4)*bx( 1) +(f( 2, 2, 4)*bx( 2) +(f( 3, 2, 4)*bx( 3) + f( 4, 2, 4)*bx( 4)))))*by( 2) \ +(((((f(-3, 3, 4)*bx(-3) + f(-2, 3, 4)*bx(-2))+ f(-1, 3, 4)*bx(-1))+ f( 0, 3, 4)*bx( 0))+(f( 1, 3, 4)*bx( 1) +(f( 2, 3, 4)*bx( 2) +(f( 3, 3, 4)*bx( 3) + f( 4, 3, 4)*bx( 4)))))*by( 3) \ +((((f(-3, 4, 4)*bx(-3) + f(-2, 4, 4)*bx(-2))+ f(-1, 4, 4)*bx(-1))+ f( 0, 4, 4)*bx( 0))+(f( 1, 4, 4)*bx( 1) +(f( 2, 4, 4)*bx( 2) +(f( 3, 4, 4)*bx( 3) + f( 4, 4, 4)*bx( 4)))))*by( 4)))))*bz( 4))))) #endif Index: trunk/src/Kinematics.cpp =================================================================== --- trunk/src/Kinematics.cpp (revision 369) +++ trunk/src/Kinematics.cpp (revision 370) @@ -1,454 +1,454 @@ //============================================================================== // Kinematics.cpp // -// Copyright (C) 2010-2017 Tobias Toll and Thomas Ullrich +// Copyright (C) 2010-2019 Tobias Toll and Thomas Ullrich // // This file is part of Sartre. // // 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. // 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, see . // // Author: Thomas Ullrich // Last update: // $Date$ // $Author$ //------------------------------------------------------------------------------ // // Note that Kinematics is only meant for ep and eA scattering. // It is not applicable for UPC kinematics. Use UpcKinematics instead. // //============================================================================== #include "Kinematics.h" #include #include #include "Math/RootFinder.h" #include "Math/BrentRootFinder.h" #include "Math/GSLRootFinder.h" #include "Math/RootFinderAlgorithms.h" #include "Math/IFunction.h" #include "Math/BrentMinimizer1D.h" // TMP #include "TH1D.h" #include "TFile.h" #define PR(x) cout << #x << " = " << (x) << endl; using namespace std; bool Kinematics::mError = false; bool Kinematics::error() {return mError;} //UPC: double Kinematics::mXpomMin=0; double Kinematics::mTold=0; bool Kinematics::mXpomMinIsEvaluated=false; // double Kinematics::xprobe(double Q2, double W2, double vmMass) { mError = false; double val = ( Q2 + vmMass*vmMass ) / (W2 - protonMass2 + Q2); if (val > 1 || val < 0) mError = true; return val; } TLorentzVector Kinematics::electronBeam(double eE, bool upc) { mError = false; if (upc) return TLorentzVector(0, 0, -sqrt(eE*eE-protonMass2), eE); else return TLorentzVector(0, 0, -sqrt(eE*eE-electronMass2), eE); } TLorentzVector Kinematics::hadronBeam(double hE) { mError = false; return TLorentzVector(0, 0, sqrt(hE*hE-protonMass2), hE); } double Kinematics::s(const TLorentzVector& e, const TLorentzVector& p) { mError = false; return (e+p)*(e+p); } double Kinematics::s(double eE, double hE, bool upc) { mError = false; TLorentzVector e = electronBeam(eE, upc); TLorentzVector p = hadronBeam(hE); return (e+p)*(e+p); } double Kinematics::x(double Q2, double W2) { mError = false; double val = Q2/(W2-protonMass2+Q2); if (val > 1 || val < 0) mError = true; return val; } double Kinematics::y(double Q2, double x, double s) { mError = false; double val = Q2/(x*(s-electronMass2-protonMass2)); if (val > 1 || val < 0) mError = true; return val; } double Kinematics::ymin(double s, double vmMass) { mError = false; double W2min = Kinematics::W2min(vmMass); double val = (s + W2min - sqrt((s-W2min)*(s-W2min)-4*electronMass2*W2min))/2/(s+electronMass2); if (val > 1 || val < 0) mError = true; return val; } double Kinematics::ymax(double s, double vmMass) { mError = false; double W2min = Kinematics::W2min(vmMass); double val = (s + W2min + sqrt((s-W2min)*(s-W2min)-4*electronMass2*W2min))/2/(s+electronMass2); if (val > 1 || val < 0) mError = true; return val; } double Kinematics::W2(double Q2, double x) { // // Returns W2 at a given Q2 and Bjorken x // mError = false; return protonMass2 + Q2*(1-x)/x; } double Kinematics::W2(double Q2, double xprobe, double vmMass) { // // Returns W2 at a given Q2 and xprobe // where xprobe is // xprobe = xBJ * (1 + MV^2/Q2) // mError = false; return protonMass2 + vmMass*vmMass/xprobe + Q2*(1-xprobe)/xprobe; } double Kinematics::W2min(double vmMass) { mError = false; return vmMass*vmMass + protonMass2; } double Kinematics::W2max(double s) { mError = false; return s; // check !? } double Kinematics::Q2min(double y) { mError = false; return electronMass2*y*y/(1-y); } double Kinematics::Q2max(double s) { mError = false; return s-electronMass2-protonMass2; } double Kinematics::xpomeron(double t, double Q2, double W2, double vmM) { mError = false; double val = (vmM*vmM + Q2 - t)/(W2 + Q2 - protonMass2); // full expression if (val > 1 || val < 0) mError = true; return val; } double Kinematics::tmax(double xpom) { mError = false; return (- xpom*xpom * protonMass2 / (1-xpom)); // only if m_p (in) = m_p' (out) - to be fixed } double Kinematics::tmax(double t, double Q2, double W2, double vmM) { return tmax(xpomeron(t, Q2, W2, vmM)); } double Kinematics::tmin(double eE) { mError = false; return -2*(eE*protonMass-protonMass2); // check ?! } // // UPC only // double Kinematics::xpomMin(double massVM, double t, TLorentzVector hBeam, TLorentzVector eBeam, double MY2minusM2){ if(mXpomMinIsEvaluated and mTold == t) return mXpomMin; LowerXpomeronFormula formula; mTold = t; formula.mT = t; formula.mVmMass2=massVM*massVM; formula.mElectronBeam = eBeam; formula.mHadronBeam = hBeam; formula.mMY2minusM2 = MY2minusM2; // //Find starting brackets // double lower=1e-12; double upper=1e-1; // // Find minimum and use as lower // bracket to avoid two roots // ROOT::Math::BrentMinimizer1D bm; bm.SetFunction(formula, log(lower), log(upper)); bm.Minimize(100000, 1e-8, 1e-10); double theMin = bm.XMinimum(); // // Run root finder // ROOT::Math::RootFinder rootfinder(ROOT::Math::RootFinder::kBRENT); rootfinder.SetFunction(formula, theMin, log(upper)); rootfinder.Solve(100000000, 1e-14, 0); // // Now some fine adjustements // double bestGuess = rootfinder.Root(); int ntimes = 0; while (formula.DoEval(bestGuess) < 0) { bestGuess += 1e-14; ntimes++; if (ntimes> 10000) break; } double result = exp(bestGuess); double s = (hBeam+eBeam).M2(); mXpomMin = max(result, xpomMin(s, massVM, t)); mXpomMinIsEvaluated = true; return mXpomMin; } double Kinematics::xpomMin(double s, double vmM, double t) { // // This is the threshold value. // In some cases a more restrictive value may be needed // return (electronMass2 + protonMass2 + vmM*vmM - t)/s; } double Kinematics::Egamma(double xpom, double t, double vmM, double hBeamEnergy, double eBeamEnergy, double MY2minusM2) { // // We use that the vector meson = photon + pomeron to calculate Egamma // (keeping the pomeron variables from above) // We solve a quadratic equation to get the photon energy such that // the vector meson has the correct mass. // double Ep=hBeamEnergy; double Pp=-sqrt(Ep*Ep-protonMass2); double Ee=eBeamEnergy; double Pe=sqrt(Ee*Ee-protonMass2); double sqrtarg= 1 - ( (2*xpom - xpom*xpom)*Pp*Pp + t - MY2minusM2) / (Ep*Ep); double Epom=Ep*(1-sqrt(sqrtarg)); //this is close to xpom*Ep double Ppom=xpom*Pp; double AA = vmM*vmM - Epom*Epom - t + Ppom*Ppom + 2*Pe*(Pe+Ppom); //GeV^2 double aa = 4*(Pe+Ppom)*(Pe+Ppom) - 4*(Ee+Epom)*(Ee+Epom); //GeV^2 double bb = 4*AA*(Ee+Epom) - 8*(Pe+Ppom)*(Pe+Ppom)*Ee; //GeV^3 double cc = 4*(Pe+Ppom)*(Pe+Ppom)*Pe*Pe - AA*AA; sqrtarg = bb*bb-4*aa*cc; if (sqrtarg < 0) { //This is used by validUPC as a sign of failure, needs to return something negative return -1.; } return ( -bb + sqrt(sqrtarg) )/(2*aa); //GeV } // // UPC only // bool Kinematics::validUPC(double hBeamEnergy, double eBeamEnergy, double t, double xpom, double vmMass, bool verbose) { // // Here we perform all complete test of all kinematic variables // // // xpom // double s = Kinematics::s(eBeamEnergy, hBeamEnergy, true); double Egam = Egamma(xpom, t, vmMass, hBeamEnergy, eBeamEnergy); double minxpom = xpomMin(s, vmMass, t); if (xpom < minxpom) { if(verbose) cout << "Kinematics::validUPC(): reject t=" << t << " and xpom=" << xpom << " because xpom < xpomMin (" << minxpom << ")" << endl; return false; } if (Egam < 0) { if(verbose) cout << "Kinematics::validUPC(): reject t=" << t << " and xpom=" << xpom << " because Egamma < 0 (" << Egam << ")" << endl; return false; } if (xpom > 1) { if(verbose) cout << "Kinematics::validUPC(): reject xpom="< 1" << endl; return false; } // // t // double t_max=tmax(xpom); if (t > t_max) { if (verbose) cout << "Kinematics::validUPC(): reject t=" << t << " because t > tmax (" << t_max << ")" << endl; return false; } return true; //survived all tests } bool Kinematics::valid(double s, double t, double Q2, double W2, double vmMass, bool useTrueXp, bool verbose) { // // Here we perform all complete test of all kinematic variables // double x = Kinematics::x(Q2, W2); double y = Kinematics::y(Q2, x, s); // // W // if (W2 < Kinematics::W2min(vmMass)) { if (verbose) cout << "Kinematics::valid(): reject W=" << sqrt(W2) << " because W < Wmin" << endl; return false; } if (W2 > Kinematics::W2max(s)) { if (verbose) cout << "Kinematics::valid(): reject W=" << sqrt(W2) << " because W > Wmax" << endl; return false; } // // y range // double ymin = Kinematics::ymin(s, vmMass); double ymax = Kinematics::ymax(s, vmMass); if (y < ymin || y > ymax) { if (verbose) cout << "Kinematics::valid(): reject y=" << y << " because y < ymin (" << ymin << ") || y > ymax (" << ymax << ")" << endl; return false; } // // x and y // if (x < 0 || x > 1) { if (verbose) cout << "Kinematics::valid(): reject x=" << x << " because x < 0 || x > 1" << endl; return false; } // // Q2 // if (Q2 > Kinematics::Q2max(s)) { if (verbose) cout << "Kinematics::valid(): reject Q2=" << Q2 << " because Q2 > Q2max" << endl; return false; } if (Q2 < Kinematics::Q2min(y)) { if (verbose) cout << "Kinematics::valid(): reject Q2=" << Q2 << " because Q2 < Q2min" << endl; return false; } // // t // // On calculating xpomeron. xpomeron() provides the correct value // (not neglecting t or nucleon mass). However, during initialization // to avoid recursion we set t=0. Calling valid() with t != 0 would // reject these values. In this case useTrueXp is set to false. // For final checks if an event has the correct kinematics we have // to set useTrueXp = true. // double xpom; if (useTrueXp) xpom = Kinematics::xpomeron(t, Q2, W2, vmMass); else xpom = Kinematics::xpomeron(0, Q2, W2, vmMass); double tmax = Kinematics::tmax(xpom); if (t > tmax) { if (verbose) cout << "Kinematics::valid(): reject t=" << t << " because t > tmax (" << tmax << ")" << endl; return false; } // // xpom // if (xpom < 0 || xpom > 1) { if (verbose) cout << "Kinematics::valid(): reject xpom=" << xpom << " because xpom < 0 || xpom > 1" << endl; return false; } if (x > xpom) { if (verbose) cout << "Kinematics::valid(): reject since x=" << x << " > xpom = " << xpom << endl; return false; } return true; // survived all tests } ROOT::Math::IBaseFunctionOneDim* LowerXpomeronFormula::Clone() const { return new LowerXpomeronFormula(); } double LowerXpomeronFormula::DoEval(double logxpom) const { double xpom = exp(logxpom); //Start by setting up the knowns: Incoming beams, xpom, and t: double Ee=mElectronBeam.E(); double Pe=mElectronBeam.Pz(); double Pp=mHadronBeam.Pz(); double Ep=mHadronBeam.E(); double E, pz; // // Use scattered proton to set up four momentum of pomeron (so far assuming no break-up): // double sqrtarg= 1 - ( (2*xpom - xpom*xpom)*Pp*Pp + mT - mMY2minusM2) / (Ep*Ep); E=Ep*(1-sqrt(sqrtarg)); //this is close to xpom*Ep pz=xpom*Pp; // // Next we use that the vector meson = photon + pomeron to calculate Egamma // (keeping the pomeron variables from above) // We solve a quadratic equation to get the photon energy such that // the vector meson has the correct mass. // double AA = mVmMass2 - E*E - mT + pz*pz + 2*Pe*(Pe+pz); //GeV^2 double aa = 4*(Pe+pz)*(Pe+pz) - 4*(Ee+E)*(Ee+E); //GeV^2 double bb = 4*AA*(Ee+E) - 8*(Pe+pz)*(Pe+pz)*Ee; //GeV^3 double cc = 4*(Pe+pz)*(Pe+pz)*Pe*Pe - AA*AA; sqrtarg = bb*bb-4*aa*cc; return sqrtarg; } Index: trunk/src/GridSplineBetaPolynomials.h =================================================================== --- trunk/src/GridSplineBetaPolynomials.h (revision 369) +++ trunk/src/GridSplineBetaPolynomials.h (revision 370) @@ -1,342 +1,342 @@ //============================================================================== // GridSplineBetaPolynomials.h // -// Copyright (C) 2010-2013 Tobias Toll and Thomas Ullrich +// Copyright (C) 2010-2019 Tobias Toll and Thomas Ullrich // // This file is part of Sartre. // // 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. // 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, see . // // Author: Thomas Ullrich // Last update: // $Date$ // $Author$ //============================================================================== // // Definitions for the spline polynomials of the second kind (beta-s) // in addition, various wrappers (in case they are needed) // // // This algorithm was written by Cristian Lalescu. // See http://arxiv.org/abs/0905.3564 for details. // The code here is slightly modified for use in Sartre. // //============================================================================== #ifndef GridSplineBetaPolynomials_h #define GridSplineBetaPolynomials_h inline double BETA_n1_q2_j1 (double x) { return ((x>=0 && x<=1) ? (1-x) : 0); } inline double OMEGA_n1_q2 (double x) { return ((x>=0) ? BETA_n1_q2_j1(x) : BETA_n1_q2_j1(-x)); } inline double BETA_n3_q4_j1 (double x) { return ((x*((4-3*x)*x+1))/2); } inline double BETA_n3_q4_j2 (double x) { return (((x-1)*x*x)/2); } inline double OMEGA_n3_q4_half (double x) { return ((x>=0 && x<=2) ? ((x>=0 && x<=1) ? BETA_n3_q4_j1(1-x) : BETA_n3_q4_j2(2-x)) : 0); } inline double OMEGA_n3_q4 (double x) { return ((x>=0) ? OMEGA_n3_q4_half(x) : OMEGA_n3_q4_half(-x) ); } inline double BETA_n5_q4_j1 (double x) { return ((x*(x*(x*(x*(6*x-15)+9)+1)+1))/2); } inline double BETA_n5_q4_j2 (double x) { return ((x*x*x*((5-2*x)*x-3))/2); } inline double OMEGA_n5_q4_half (double x) { return ((x>=0 && x<=2) ? ((x>=0 && x<=1) ? BETA_n5_q4_j1(1-x) : BETA_n5_q4_j2(2-x)) : 0); } inline double OMEGA_n5_q4 (double x) { return ((x>=0) ? OMEGA_n5_q4_half(x) : OMEGA_n5_q4_half(-x) ); } inline double BETA_n3_q6_j3 (double x) { return (((1-x)*x*x)/12); } inline double BETA_n3_q6_j2 (double x) { return ((x*(x*(7*x-6)-1))/12); } inline double BETA_n3_q6_j1 (double x) { return ((x*((5-4*x)*x+2))/3); } inline double OMEGA_n3_q6_half (double x) { return ((x>=0 && x<=3) ? ((x>=0 && x<=2) ? ((x>=0 && x<=1) ? BETA_n3_q6_j1(1-x) : BETA_n3_q6_j2(2-x)) : BETA_n3_q6_j3(3-x)) : 0); } inline double OMEGA_n3_q6 (double x) { return ((x>=0) ? OMEGA_n3_q6_half(x) : OMEGA_n3_q6_half(-x)); } inline double BETA_n5_q6_j3 (double x) { return ((x*x*x*(x*(5*x-12)+7))/24); } inline double BETA_n5_q6_j2 (double x) { return ((x*(x*(x*((61-25*x)*x-33)-1)-2))/24); } inline double BETA_n5_q6_j1 (double x) { return ((x*(x*(x*(x*(25*x-62)+33)+8)+8))/12); } inline double OMEGA_n5_q6_half (double x) { return ((x>=0 && x<=3) ? ((x>=0 && x<=2) ? ((x>=0 && x<=1) ? BETA_n5_q6_j1(1-x) : BETA_n5_q6_j2(2-x)) : BETA_n5_q6_j3(3-x)) : 0); } inline double OMEGA_n5_q6 (double x) { return ((x>=0) ? OMEGA_n5_q6_half(x) : OMEGA_n5_q6_half(-x)); } inline double BETA_n7_q6_j3 (double x) { return ((x*x*x*x*(x*((49-14*x)*x-58)+23))/24); } inline double BETA_n7_q6_j2 (double x) { return ((x*(x*(x*(x*(x*(x*(70*x-245)+290)-114)+2)-1)-2))/24); } inline double BETA_n7_q6_j1 (double x) { return ((x*(x*(x*(x*(x*((245-70*x)*x-290)+113)-2)+8)+8))/12); } inline double OMEGA_n7_q6_half (double x) { return ((x>=0 && x<=3) ? ((x>=0 && x<=2) ? ((x>=0 && x<=1) ? BETA_n7_q6_j1(1-x) : BETA_n7_q6_j2(2-x)) : BETA_n7_q6_j3(3-x)) : 0); } inline double OMEGA_n7_q6 (double x) { return ((x>=0) ? OMEGA_n7_q6_half(x) : OMEGA_n7_q6_half(-x)); } inline double BETA_n9_q6_j3 (double x) { return ((x*x*x*x*x*(x*(x*(x*(46*x-207)+354)-273)+80))/24); } inline double BETA_n9_q6_j2 (double x) { return ((x*(x*(x*(x*(x*(x*(x*((1035-230*x)*x-1770)+1365)-400)+1)+2)-1)-2))/24); } inline double BETA_n9_q6_j1 (double x) { return ((x*(x*(x*(x*(x*(x*(x*(x*(230*x-1035)+1770)-1365)+400)-2)-2)+8)+8))/12); } inline double OMEGA_n9_q6_half (double x) { return ((x>=0 && x<=3) ? ((x>=0 && x<=2) ? ((x>=0 && x<=1) ? BETA_n9_q6_j1(1-x) : BETA_n9_q6_j2(2-x)) : BETA_n9_q6_j3(3-x)) : 0); } inline double OMEGA_n9_q6 (double x) { return ((x>=0) ? OMEGA_n9_q6_half(x) : OMEGA_n9_q6_half(-x)); } inline double BETA_n3_q8_j4 (double x) { return (((x-1)*x*x)/60); } inline double BETA_n3_q8_j3 (double x) { return ((x*((7-8*x)*x+1))/60); } inline double BETA_n3_q8_j2 (double x) { return ((x*(x*(12*x-9)-3))/20); } inline double BETA_n3_q8_j1 (double x) { return ((x*((6-5*x)*x+3))/4); } inline double OMEGA_n3_q8_half (double x) { return ((x>=0 && x<=4) ? ((x>=0 && x<=3) ? ((x>=0 && x<=2) ? ((x>=0 && x<=1) ? BETA_n3_q8_j1(1-x) : BETA_n3_q8_j2(2-x)) : BETA_n3_q8_j3(3-x)) : BETA_n3_q8_j4(4-x)):0); } inline double OMEGA_n3_q8 (double x) { return ((x>=0) ? OMEGA_n3_q8_half(x) : OMEGA_n3_q8_half(-x)); } inline double BETA_n5_q8_j4 (double x) { return ((x*x*x*((19-8*x)*x-11))/180); } inline double BETA_n5_q8_j3 (double x) { return ((x*(x*(x*(x*(115*x-270)+147)+2)+6))/360); } inline double BETA_n5_q8_j2 (double x) { return ((x*(x*(x*((93-39*x)*x-45)-3)-6))/40); } inline double BETA_n5_q8_j1 (double x) { return ((x*(x*(x*(x*(59*x-145)+68)+27)+27))/36); } inline double OMEGA_n5_q8_half (double x) { return ((x>=0 && x<=4) ? ((x>=0 && x<=3) ? ((x>=0 && x<=2) ? ((x>=0 && x<=1) ? BETA_n5_q8_j1(1-x) : BETA_n5_q8_j2(2-x)) : BETA_n5_q8_j3(3-x)) : BETA_n5_q8_j4(4-x)):0); } inline double OMEGA_n5_q8 (double x) { return ((x>=0) ? OMEGA_n5_q8_half(x) : OMEGA_n5_q8_half(-x)); } inline double BETA_n7_q8_j4 (double x) { return ((x*x*x*x*(x*(x*(89*x-311)+367)-145))/720); } inline double BETA_n7_q8_j3 (double x) { return ((x*(x*(x*(x*(x*((2178-623*x)*x-2566)+1010)-15)+4)+12))/720); } inline double BETA_n7_q8_j2 (double x) { return ((x*(x*(x*(x*(x*(x*(623*x-2179)+2565)-995)+40)-18)-36))/240); } inline double BETA_n7_q8_j1 (double x) { return ((x*(x*(x*(x*(x*((2180-623*x)*x-2566)+976)-39)+108)+108))/144); } inline double OMEGA_n7_q8_half (double x) { return ((x>=0 && x<=4) ? ((x>=0 && x<=3) ? ((x>=0 && x<=2) ? ((x>=0 && x<=1) ? BETA_n7_q8_j1(1-x) : BETA_n7_q8_j2(2-x)) : BETA_n7_q8_j3(3-x)) : BETA_n7_q8_j4(4-x)):0); } inline double OMEGA_n7_q8 (double x) { return ((x>=0) ? OMEGA_n7_q8_half(x) : OMEGA_n7_q8_half(-x)); } inline double BETA_n9_q8_j4 (double x) { return ((x*x*x*x*x*(x*(x*((1305-290*x)*x-2231)+1719)-503))/720); } inline double BETA_n9_q8_j3 (double x) { return ((x*(x*(x*(x*(x*(x*(x*(x*(2030*x-9135)+15617)-12032)+3524)-5)-15)+4)+12))/720); } inline double BETA_n9_q8_j2 (double x) { return ((x*(x*(x*(x*(x*(x*(x*((9135-2030*x)*x-15617)+12031)-3525)+20)+40)-18)-36))/240); } inline double BETA_n9_q8_j1 (double x) { return ((x*(x*(x*(x*(x*(x*(x*(x*(2030*x-9135)+15617)-12030)+3524)-39)-39)+108)+108))/144); } inline double OMEGA_n9_q8_half (double x) { return ((x>=0 && x<=4) ? ((x>=0 && x<=3) ? ((x>=0 && x<=2) ? ((x>=0 && x<=1) ? BETA_n9_q8_j1(1-x) : BETA_n9_q8_j2(2-x)) : BETA_n9_q8_j3(3-x)) : BETA_n9_q8_j4(4-x)):0); } inline double OMEGA_n9_q8 (double x) { return ((x>=0) ? OMEGA_n9_q8_half(x) : OMEGA_n9_q8_half(-x)); } inline double BETA_n11_q8_j4 (double x) { return ((x*x*x*x*x*x*(x*(x*(x*(x*(1006*x-5533)+12285)-13785)+7829)-1802))/720); } inline double BETA_n11_q8_j3 (double x) { return ((x*(x*(x*(x*(x*(x*(x*(x*(x*((38731-7042*x)*x-85995)+96495)-54803)+12615)+3)-5)-15)+4)+12))/720); } inline double BETA_n11_q8_j2 (double x) { return ((x*(x*(x*(x*(x*(x*(x*(x*(x*(x*(7042*x-38731)+85995)-96495)+54803)-12616)-4)+20)+40)-18)-36))/240); } inline double BETA_n11_q8_j1 (double x) { return ((x*(x*(x*(x*(x*(x*(x*(x*(x*((38731-7042*x)*x-85995)+96495)-54803)+12617)+3)-39)-39)+108)+108))/144); } inline double OMEGA_n11_q8_half(double x) { return ((x>=0 && x<=4) ? ((x>=0 && x<=3) ? ((x>=0 && x<=2) ? ((x>=0 && x<=1) ? BETA_n11_q8_j1(1-x) : BETA_n11_q8_j2(2-x)) : BETA_n11_q8_j3(3-x)) : BETA_n11_q8_j4(4-x)):0); } inline double OMEGA_n11_q8 (double x) { return ((x>=0) ? OMEGA_n11_q8_half(x) : OMEGA_n11_q8_half(-x)); } inline double BETA_n13_q8_j4 (double x) { return ((x*x*x*x*x*x*x*(x*(x*(x*(x*((23426-3604*x)*x-63866)+93577)-77815)+34869)-6587))/720); } inline double BETA_n13_q8_j3 (double x) { return ((x*(x*(x*(x*(x*(x*(x*(x*(x*(x*(x*(x*(25228*x-163982)+447062)-655039)+544705)-244083)+46109)+1)+3)-5)-15)+4)+12))/720); } inline double BETA_n13_q8_j2 (double x) { return ((x*(x*(x*(x*(x*(x*(x*(x*(x*(x*(x*((163982-25228*x)*x-447062)+655039)-544705)+244083)-46109)-2)-4)+20)+40)-18)-36))/240); } inline double BETA_n13_q8_j1 (double x) { return ((x*(x*(x*(x*(x*(x*(x*(x*(x*(x*(x*(x*(25228*x-163982)+447062)-655039)+544705)-244083)+46109)+3)+3)-39)-39)+108)+108))/144); } inline double OMEGA_n13_q8_half(double x) { return ((x>=0 && x<=4) ? ((x>=0 && x<=3) ? ((x>=0 && x<=2) ? ((x>=0 && x<=1) ? BETA_n13_q8_j1(1-x) : BETA_n13_q8_j2(2-x)) : BETA_n13_q8_j3(3-x)) : BETA_n13_q8_j4(4-x)):0); } inline double OMEGA_n13_q8 (double x) { return ((x>=0) ? OMEGA_n13_q8_half(x) : OMEGA_n13_q8_half(-x)); } /********************************/ // (probably inefficient) wrappers inline double BETA_n3_q4 (int grid_point, double x) { switch(grid_point) { case -1: return BETA_n3_q4_j2(1-x); case 0: return BETA_n3_q4_j1(1-x); case 1: return BETA_n3_q4_j1(x); case 2: return BETA_n3_q4_j2(x); default: return 0; } } inline double BETA_n5_q4 (int grid_point, double x) { switch(grid_point) { case -1: return BETA_n5_q4_j2(1-x); case 0: return BETA_n5_q4_j1(1-x); case 1: return BETA_n5_q4_j1(x); case 2: return BETA_n5_q4_j2(x); default: return 0; } } inline double BETA_n3_q6 (int grid_point, double x) { switch(grid_point) { case -2: return BETA_n3_q6_j3(1-x); case -1: return BETA_n3_q6_j2(1-x); case 0: return BETA_n3_q6_j1(1-x); case 1: return BETA_n3_q6_j1(x); case 2: return BETA_n3_q6_j2(x); case 3: return BETA_n3_q6_j3(x); default: return 0; } } inline double BETA_n5_q6 (int grid_point, double x) { switch(grid_point) { case -2: return BETA_n5_q6_j3(1-x); case -1: return BETA_n5_q6_j2(1-x); case 0: return BETA_n5_q6_j1(1-x); case 1: return BETA_n5_q6_j1(x); case 2: return BETA_n5_q6_j2(x); case 3: return BETA_n5_q6_j3(x); default: return 0; } } inline double BETA_n7_q6 (int grid_point, double x) { switch(grid_point) { case -2: return BETA_n7_q6_j3(1-x); case -1: return BETA_n7_q6_j2(1-x); case 0: return BETA_n7_q6_j1(1-x); case 1: return BETA_n7_q6_j1(x); case 2: return BETA_n7_q6_j2(x); case 3: return BETA_n7_q6_j3(x); default: return 0; } } inline double BETA_n9_q6 (int grid_point, double x) { switch(grid_point) { case -2: return BETA_n9_q6_j3(1-x); case -1: return BETA_n9_q6_j2(1-x); case 0: return BETA_n9_q6_j1(1-x); case 1: return BETA_n9_q6_j1(x); case 2: return BETA_n9_q6_j2(x); case 3: return BETA_n9_q6_j3(x); default: return 0; } } inline double BETA_n3_q8 (int grid_point, double x) { switch(grid_point) { case -3: return BETA_n3_q8_j4(1-x); case -2: return BETA_n3_q8_j3(1-x); case -1: return BETA_n3_q8_j2(1-x); case 0: return BETA_n3_q8_j1(1-x); case 1: return BETA_n3_q8_j1(x); case 2: return BETA_n3_q8_j2(x); case 3: return BETA_n3_q8_j3(x); case 4: return BETA_n3_q8_j4(x); default: return 0; } } inline double BETA_n5_q8 (int grid_point, double x) { switch(grid_point) { case -3: return BETA_n5_q8_j4(1-x); case -2: return BETA_n5_q8_j3(1-x); case -1: return BETA_n5_q8_j2(1-x); case 0: return BETA_n5_q8_j1(1-x); case 1: return BETA_n5_q8_j1(x); case 2: return BETA_n5_q8_j2(x); case 3: return BETA_n5_q8_j3(x); case 4: return BETA_n5_q8_j4(x); default: return 0; } } inline double BETA_n7_q8 (int grid_point, double x) { switch(grid_point) { case -3: return BETA_n7_q8_j4(1-x); case -2: return BETA_n7_q8_j3(1-x); case -1: return BETA_n7_q8_j2(1-x); case 0: return BETA_n7_q8_j1(1-x); case 1: return BETA_n7_q8_j1(x); case 2: return BETA_n7_q8_j2(x); case 3: return BETA_n7_q8_j3(x); case 4: return BETA_n7_q8_j4(x); default: return 0; } } inline double BETA_n9_q8 (int grid_point, double x) { switch(grid_point) { case -3: return BETA_n9_q8_j4(1-x); case -2: return BETA_n9_q8_j3(1-x); case -1: return BETA_n9_q8_j2(1-x); case 0: return BETA_n9_q8_j1(1-x); case 1: return BETA_n9_q8_j1(x); case 2: return BETA_n9_q8_j2(x); case 3: return BETA_n9_q8_j3(x); case 4: return BETA_n9_q8_j4(x); default: return 0; } } inline double BETA_n11_q8 (int grid_point, double x) { switch(grid_point) { case -3: return BETA_n11_q8_j4(1-x); case -2: return BETA_n11_q8_j3(1-x); case -1: return BETA_n11_q8_j2(1-x); case 0: return BETA_n11_q8_j1(1-x); case 1: return BETA_n11_q8_j1(x); case 2: return BETA_n11_q8_j2(x); case 3: return BETA_n11_q8_j3(x); case 4: return BETA_n11_q8_j4(x); default: return 0; } } inline double BETA_n13_q8 (int grid_point, double x) { switch(grid_point) { case -3: return BETA_n13_q8_j4(1-x); case -2: return BETA_n13_q8_j3(1-x); case -1: return BETA_n13_q8_j2(1-x); case 0: return BETA_n13_q8_j1(1-x); case 1: return BETA_n13_q8_j1(x); case 2: return BETA_n13_q8_j2(x); case 3: return BETA_n13_q8_j3(x); case 4: return BETA_n13_q8_j4(x); default: return 0; } } inline double BETA_q4 (int spline_order, int grid_point, double x) { switch(spline_order) { case 3: return BETA_n3_q4(grid_point,x); case 5: return BETA_n5_q4(grid_point,x); default: return 0; } } inline double BETA_q6 (int spline_order, int grid_point, double x) { switch(spline_order) { case 3: return BETA_n3_q6(grid_point,x); case 5: return BETA_n5_q6(grid_point,x); case 7: return BETA_n7_q6(grid_point,x); case 9: return BETA_n9_q6(grid_point,x); default: return 0; } } inline double BETA_q8 (int spline_order, int grid_point, double x) { switch(spline_order) { case 3: return BETA_n3_q8(grid_point,x); case 5: return BETA_n5_q8(grid_point,x); case 7: return BETA_n7_q8(grid_point,x); case 9: return BETA_n9_q8(grid_point,x); case 11: return BETA_n11_q8(grid_point,x); case 13: return BETA_n13_q8(grid_point,x); default: return 0; } } inline double BETA (int spline_order, int grid_size, int grid_point, double x) { switch(grid_size) { case 4: return BETA_q4(spline_order, grid_point, x); case 6: return BETA_q6(spline_order, grid_point, x); case 8: return BETA_q8(spline_order, grid_point, x); default: return 0; } } #endif//__BETA_POLYNOMIALS_H__ Index: trunk/src/Version.h =================================================================== --- trunk/src/Version.h (revision 369) +++ trunk/src/Version.h (revision 370) @@ -1,29 +1,29 @@ //============================================================================== // Version.h // -// Copyright (C) 2010-2017 Tobias Toll and Thomas Ullrich +// Copyright (C) 2010-2019 Tobias Toll and Thomas Ullrich // // This file is part of Sartre. // // 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. // 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, see . // // Author: Thomas Ullrich // Last update: // $Date$ // $Author$ //============================================================================== #ifndef Version_h #define Version_h -#define VERSION "1.32" -#define VERSION_NUMBER 1.32 +#define VERSION "1.33" +#define VERSION_NUMBER 1.33 #endif Index: trunk/src/Table.h =================================================================== --- trunk/src/Table.h (revision 369) +++ trunk/src/Table.h (revision 370) @@ -1,208 +1,208 @@ //============================================================================== // Table.h // -// Copyright (C) 2010-2016 Tobias Toll and Thomas Ullrich +// Copyright (C) 2010-2019 Tobias Toll and Thomas Ullrich // // This file is part of Sartre. // // 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. // 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, see . // // Author: Thomas Ullrich // Last update: // $Date$ // $Author$ //============================================================================== // // To read/load an existing table: // // Table tbl; // tbl.read("filename"); // read table into memory // double content = tbl.get(Q2, W2, t); // return content for Q2, W2, t // // To create a table: // // Table tbl; // int n = tbl.create(nbinQ2, Q2min, Q2max, // nBinW2, W2min, W2max, // nBinT, tmin, tmax, // logQ2, logW2, logT, logC // all bools // AmplitudeMoment m, GammaPolarization p, // massA, vmPDG, model); // // for (int i=0; i_backup....root // where // is a unique name passed to setAutobackup() // is the process ID (see getpid()) // is the number of the last bin filled // is the table ID // // If a new backup file is created the old/previous one gets deleted. // The last valid backup file is deleted after a successful call to write(). //============================================================================== #ifndef Table_h #define Table_h #include #include #include "Enumerations.h" #include using namespace std; class TH2F; class TH3F; class Table { public: Table(); Table(const Table&); ~Table(); Table& operator=(const Table&); // // Reading and using a table // bool read(const char*); double get(double Q2, double W2, double t) const; double get(double xpom, double t) const; // UPC version // // Creating, filling, and storing a table // unsigned int create(int, double, double, int, double, double, int, double, double, bool logQ2, bool logW2, bool logt, bool logContent, AmplitudeMoment, GammaPolarization, unsigned int A, int vm, DipoleModelType model, DipoleModelParameterSet pset, const char* filename = 0, unsigned char priority = 0); unsigned int create(int, double, double, // UPC version int, double, double, bool logx, bool logt, bool logContent, AmplitudeMoment, GammaPolarization, unsigned int A, int vm, DipoleModelType model, DipoleModelParameterSet pset, const char* filename = 0, unsigned char priority = 0); void binCenter(int, double& Q2, double& W2, double& t) const; void binCenter(int, double& xpom, double& t) const; // UPC version void fill(int, double, double err = 0); void write(const char* filename = 0); // // Backup mechanism // void setAutobackup(const char* prefix, int freq); // // Query functions // unsigned int A() const; // mass number bool isTransverse() const; bool isLongitudinal() const; GammaPolarization polarization() const; bool isMeanA2() const; bool isMeanA() const; bool isLambdaA() const; bool isLambdaSkew() const; bool isVarianceA() const; AmplitudeMoment moment() const; int vectorMesonId() const; unsigned int dipoleModelType() const; unsigned int dipoleModelParameterSet() const; int numberOfEntries() const; double minQ2() const; double maxQ2() const; double minW2() const; double maxW2() const; double minT() const; double maxT() const; double minX() const; double maxX() const; double binWidthQ2() const; double binWidthW2() const; double binWidthT() const; double binWidthX() const; unsigned int priority() const; bool isUPC() const; uint64_t id() const; void list(ostream& = cout, bool = false, bool = false, int = 0, int = 0) const; string filename() const; int globalBin(int binx, int biny, int binz) const; int globalBin(int binx, int biny) const; // UPC version void binXYZ(int globalBin, int& binx, int& biny, int& binz) const; void binXY(int globalBin, int& binx, int& biny) const; // UPC version bool writeToBinaryFile(const string&, bool verbose=false) const; private: bool isLogQ2() const; bool isLogW2() const; bool isLogT() const; bool isLogX() const; bool isLogContent() const; bool fexists(const char*) const; double InterpolateGridSpline(double x, double y, double z) const; double modInterpolation(double, double, double) const; double modInterpolation(double, double) const; // UPC version void backup(int); private: uint64_t mID; TH3F *m3DHisto; TH2F *m2DHisto; // UPC table string mFilename; int mFillCounter; int mBackupFrequence; string mBackupPrefix; string mLastBackupFilename; }; #endif Index: trunk/src/Integrals.h =================================================================== --- trunk/src/Integrals.h (revision 369) +++ trunk/src/Integrals.h (revision 370) @@ -1,187 +1,187 @@ //============================================================================== // Integrals.h // -// Copyright (C) 2010-2018 Tobias Toll and Thomas Ullrich +// Copyright (C) 2010-2019 Tobias Toll and Thomas Ullrich // // This file is part of Sartre. // // 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. // 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, see . // // Author: Tobias Toll // Last update: // $Date$ // $Author$ //============================================================================== // // This class calculate the integrals over the // unintegrated amplitude for \gamma-A collisions // It calculates four 4dimensional integrals for a given (t, Q2, W2): // Imaginary part for T photon // Real part for T photon // Imaginary part for L photon // Real part for L photon // // The results are accessed via: // double integralImT() // double integralReT() // double integralImL() // double integralReL() // //============================================================================== #ifndef Integrals_h #define Integrals_h class WaveOverlap; class DipoleModel; class TH1F; class Integrals { public: Integrals(); virtual ~Integrals(); Integrals(const Integrals&); Integrals& operator=(const Integrals&); void operator() (double, double, double); void operator() (double, double); //#TT UPC only takes two arguments double integralImT() const; double integralImL() const; double integralReT() const; double integralReL() const; double errorImT() const; double errorImL() const; double errorReT() const; double errorReL() const; double probImT() const; double probImL() const; double probReT() const; double probReL() const; double integralTForSkewedness() const; double integralLForSkewedness() const; double errorTForSkewedness() const; double errorLForSkewedness() const; DipoleModel* dipoleModel() const; DipoleModel* dipoleModelForSkewednessCorrection() const; protected: virtual void calculate() = 0; virtual bool setKinematicPoint(double, double, double) = 0; virtual bool setKinematicPoint(double, double) = 0; virtual void calculateCoherent() = 0; virtual void calculateSkewedness() = 0; virtual void calculateEp() = 0; protected: //the wave-overlap: WaveOverlap* mWaveOverlap; //the dipole model: DipoleModel* mDipoleModel; DipoleModel* mDipoleModelForSkewednessCorrection; bool mIsInitialized; double mRelativePrecisionOfIntegration; double mMV; //The result from each integral: double mIntegralImT; double mIntegralImL; double mIntegralReT; double mIntegralReL; //The (absolute) error from each integral: double mErrorImT; double mErrorImL; double mErrorReT; double mErrorReL; //The probability for each integral: double mProbImT; double mProbImL; double mProbReT; double mProbReL; bool mVerbose; void fillZeroes(); bool mIsUPC; bool mCalculateSkewedness; double mIntegralTForSkewedness; double mIntegralLForSkewedness; double mErrorTForSkewedness; double mErrorLForSkewedness; double mProbImTForSkewedness; double mProbImLForSkewedness; }; class IntegralsExclusive : public Integrals { public: IntegralsExclusive(); IntegralsExclusive(const IntegralsExclusive&); IntegralsExclusive& operator=(const IntegralsExclusive&); double uiAmplitudeTIm(double, double, double, double, double, double, double); double uiAmplitudeLIm(double, double, double, double, double, double, double); double uiAmplitudeTRe(double, double, double, double, double, double, double); double uiAmplitudeLRe(double, double, double, double, double, double, double); double uiAmplitudeTep(double, double, double, double, double, double); double uiAmplitudeLep(double, double, double, double, double, double); double uiCoherentAmplitudeT(double, double, double, double, double); double uiCoherentAmplitudeL(double, double, double, double, double); void coherentIntegrals(double, double, double); void coherentIntegrals(double, double); double uiAmplitudeTForSkewedness(double, double, double, double, double, double); double uiAmplitudeLForSkewedness(double, double, double, double, double, double); public: double kinematicPoint[4]; private: void calculate(); void calculateSkewedness(); void calculateCoherent(); void calculateEp(); bool setKinematicPoint(double, double, double); bool setKinematicPoint(double, double); }; inline double Integrals::integralImT() const { return mIntegralImT; } inline double Integrals::integralImL() const { return mIntegralImL; } inline double Integrals::integralReT() const { return mIntegralReT; } inline double Integrals::integralReL() const { return mIntegralReL; } inline double Integrals::errorImT() const { return mErrorImT; } inline double Integrals::errorImL() const { return mErrorImL; } inline double Integrals::errorReT() const { return mErrorReT; } inline double Integrals::errorReL() const { return mErrorReL; } inline double Integrals::probImT() const {return mProbImT; } inline double Integrals::probImL() const {return mProbImL; } inline double Integrals::probReT() const {return mProbReT; } inline double Integrals::probReL() const {return mProbReL; } inline double Integrals::integralTForSkewedness() const {return mIntegralTForSkewedness;} inline double Integrals::integralLForSkewedness() const {return mIntegralLForSkewedness;} inline double Integrals::errorTForSkewedness() const {return mErrorTForSkewedness;} inline double Integrals::errorLForSkewedness() const {return mErrorLForSkewedness;} inline DipoleModel* Integrals::dipoleModel() const { return mDipoleModel; } inline DipoleModel* Integrals::dipoleModelForSkewednessCorrection() const { return mDipoleModelForSkewednessCorrection; } #endif Index: trunk/src/FrangibleNucleus.h =================================================================== --- trunk/src/FrangibleNucleus.h (revision 369) +++ trunk/src/FrangibleNucleus.h (revision 370) @@ -1,58 +1,58 @@ //============================================================================== // FrangibleNucleus.h // -// Copyright (C) 2010-2013 Tobias Toll and Thomas Ullrich +// Copyright (C) 2010-2019 Tobias Toll and Thomas Ullrich // // This file is part of Sartre. // // 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. // 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, see . // // Author: Thomas Ullrich // Last update: // $Date$ // $Author$ //============================================================================== #ifndef FrangibleNucleus_h #define FrangibleNucleus_h #include "Nucleus.h" #include "BreakupProduct.h" #include #include using namespace std; class CNucleus; // gemini++ class FrangibleNucleus : public Nucleus { public: FrangibleNucleus(); FrangibleNucleus(const FrangibleNucleus&); FrangibleNucleus(unsigned int A, bool enableBreakup = false); ~FrangibleNucleus(); void init(unsigned int A); void init(unsigned int A, bool enableBreakup); FrangibleNucleus& operator=(const FrangibleNucleus&); int breakup(const TLorentzVector&); // breaks nucleus up const vector& breakupProducts() const; void listBreakupProducts(ostream& = cout) const; // lists all stable final fragments void resetBreakup(); private: CNucleus* mGeminiNucleus; double mExcitationEnergy; // GeV vector mProducts; }; #endif Index: trunk/src/TableGeneratorNucleus.cpp =================================================================== --- trunk/src/TableGeneratorNucleus.cpp (revision 369) +++ trunk/src/TableGeneratorNucleus.cpp (revision 370) @@ -1,197 +1,197 @@ //============================================================================== // TableGeneratorNucleus.cpp // -// Copyright (C) 2010-2016 Tobias Toll and Thomas Ullrich +// Copyright (C) 2010-2019 Tobias Toll and Thomas Ullrich // // This file is part of Sartre. // // 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. // 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, see . // // Author: Thomas Ullrich // Last update: // $Date$ // $Author$ //============================================================================== #include "TableGeneratorNucleus.h" #include "TableGeneratorSettings.h" #include "TH1D.h" #include #include TableGeneratorNucleus::TableGeneratorNucleus() { mRadialDistributionHistogram = 0; } TableGeneratorNucleus::TableGeneratorNucleus(unsigned int A) : Nucleus(A) { // // Generate a radial distribution histograms according to the Woods Saxon potential * Volume: // dN/dr=4*pi*r^2*dN/dV; dN/dV=rho: // int numRadialBins = 10000; mRadialDistributionHistogram = new TH1D("mRadialDistributionHistogram", "Woods Saxon for Random Generator", numRadialBins, 0., 3.*mRadius); for (int i=1; i <= numRadialBins; i++) { double radius=mRadialDistributionHistogram->GetBinCenter(i); mRadialDistributionHistogram->SetBinContent(i, 4.*M_PI*radius*radius*rho(radius, 0.)); } } TableGeneratorNucleus& TableGeneratorNucleus::operator=(const TableGeneratorNucleus& n) { if (this != &n) { delete mRadialDistributionHistogram; configuration.clear(); Nucleus::operator=(n); // copy assign for base class mRadialDistributionHistogram = new TH1D(*(n.mRadialDistributionHistogram)); mRadialDistributionHistogram->SetDirectory(0); copy(n.configuration.begin(), n.configuration.end(), configuration.begin()); } return *this; } TableGeneratorNucleus::TableGeneratorNucleus(const TableGeneratorNucleus& n) : Nucleus(n) { mRadialDistributionHistogram = new TH1D(*(n.mRadialDistributionHistogram)); mRadialDistributionHistogram->SetDirectory(0); copy(n.configuration.begin(), n.configuration.end(), configuration.begin()); } TableGeneratorNucleus::~TableGeneratorNucleus() { delete mRadialDistributionHistogram; } const TH1D* TableGeneratorNucleus::getRHisto() const {return mRadialDistributionHistogram;} bool TableGeneratorNucleus::generate() { // // This function generate a Nucleus in the format of a vector of nucleons of size A // It generates the position of each nucleon according to the Woods-Saxon potential, // or in the case of deuterium, the Hulthen potential. // // Must clean up each event such that the new Nucleus is not just added to the last one. // TRandom3 *random = TableGeneratorSettings::randomGenerator(); configuration.clear(); if(mA==2){ //Deuterium Nucleon nucleon1, nucleon2; // // Generate the distance between the nucleons // double distance=mRadialDistributionHistogram->GetRandom(); // // Generate x, y, and z given radius=distance/2 // and set nucleons position. // double x, y, z; random->Sphere(x, y, z, distance/2.); nucleon1.setPosition(TVector3(x, y, z)); nucleon2.setPosition(TVector3(-x, -y, -z)); // // Add nucleons to the configuration: // configuration.push_back(nucleon1); configuration.push_back(nucleon2); } else{ TVector3 centerOfMass; Nucleon tmpNucleon; double *radiusArray = new double [mA]; const double dCore=0.7; // core size of each nucleon const double dCore2 = dCore*dCore; // // Generate radii according to Woods-Saxon*Volume and // sort them for a more linear check of the distance between nucleons for (unsigned int iR=0; iRGetRandom(); } sort(radiusArray, radiusArray+mA); for (unsigned int iA=0; iA 10) { delete [] radiusArray; return false; } // // Generate x, y, and z given radius // and set nucleons position. // double x, y, z; random->Sphere(x, y, z, radius); tmpNucleon.setPosition(TVector3(x, y, z)); // // Find out how many previous nucleons are within dCore // from this one in radius... // unsigned int iTooClose=0; unsigned int ii=1; while ( iA > ii && (radius-radiusArray[iA-ii]) < dCore) { iTooClose++; ii++; } loop = false; // // Check if any of those are overlapping in 3D. // If so regenerate the angles. // for(unsigned int j=1; j<=iTooClose; j++){ if((configuration[iA-j].position()-tmpNucleon.position()).Mag2() < dCore2) { loop = true; break; } } }//while loop // // A nucleon has been generated. // Add it to the configuration and // to the center of mass vector // configuration.push_back( tmpNucleon ); centerOfMass.SetXYZ((centerOfMass.X()+tmpNucleon.position().X())/mA, (centerOfMass.Y()+tmpNucleon.position().Y())/mA, (centerOfMass.Z()+tmpNucleon.position().Z())/mA); }// iA loop // // Adjust the origin to the center of mass // for (unsigned int iA=0; iA. // // Author: Thomas Ullrich // Last update: // $Date$ // $Author$ //============================================================================== #include "Settings.h" #include #include #include #include #include #include "TParticlePDG.h" #include #define PR(x) cout << #x << " = " << (x) << endl; TRandom3 Settings::mRandomGenerator; Settings::Settings() { mPDG = new TDatabasePDG; mPDG->ReadPDGTable(); // // Setup name table (map) for nuclei // mPeriodicTable[1] = "H"; mPeriodicTable[2] = "He"; mPeriodicTable[3] = "Li"; mPeriodicTable[4] = "Be"; mPeriodicTable[5] = "B"; mPeriodicTable[6] = "C"; mPeriodicTable[7] = "N"; mPeriodicTable[8] = "O"; mPeriodicTable[9] = "F"; mPeriodicTable[10] = "Ne"; mPeriodicTable[11] = "Na"; mPeriodicTable[12] = "Mg"; mPeriodicTable[13] = "Al"; mPeriodicTable[14] = "Si"; mPeriodicTable[15] = "P"; mPeriodicTable[16] = "S"; mPeriodicTable[17] = "Cl"; mPeriodicTable[18] = "Ar"; mPeriodicTable[19] = "K"; mPeriodicTable[20] = "Ca"; mPeriodicTable[21] = "Sc"; mPeriodicTable[22] = "Ti"; mPeriodicTable[23] = "V"; mPeriodicTable[24] = "Cr"; mPeriodicTable[25] = "Mn"; mPeriodicTable[26] = "Fe"; mPeriodicTable[27] = "Co"; mPeriodicTable[28] = "Ni"; mPeriodicTable[29] = "Cu"; mPeriodicTable[30] = "Zn"; mPeriodicTable[31] = "Ga"; mPeriodicTable[32] = "Ge"; mPeriodicTable[33] = "As"; mPeriodicTable[34] = "Se"; mPeriodicTable[35] = "Br"; mPeriodicTable[36] = "Kr"; mPeriodicTable[37] = "Rb"; mPeriodicTable[38] = "Sr"; mPeriodicTable[39] = "Y"; mPeriodicTable[40] = "Zr"; mPeriodicTable[41] = "Nb"; mPeriodicTable[42] = "Mo"; mPeriodicTable[43] = "Tc"; mPeriodicTable[44] = "Ru"; mPeriodicTable[45] = "Rh"; mPeriodicTable[46] = "Pd"; mPeriodicTable[47] = "Ag"; mPeriodicTable[48] = "Cd"; mPeriodicTable[49] = "In"; mPeriodicTable[50] = "Sn"; mPeriodicTable[51] = "Sb"; mPeriodicTable[52] = "Te"; mPeriodicTable[53] = "I"; mPeriodicTable[54] = "Xe"; mPeriodicTable[55] = "Cs"; mPeriodicTable[56] = "Ba"; mPeriodicTable[57] = "La"; mPeriodicTable[58] = "Ce"; mPeriodicTable[59] = "Pr"; mPeriodicTable[60] = "Nd"; mPeriodicTable[61] = "Pm"; mPeriodicTable[62] = "Sm"; mPeriodicTable[63] = "Eu"; mPeriodicTable[64] = "Gd"; mPeriodicTable[65] = "Tb"; mPeriodicTable[66] = "Dy"; mPeriodicTable[67] = "Ho"; mPeriodicTable[68] = "Er"; mPeriodicTable[69] = "Tm"; mPeriodicTable[70] = "Yb"; mPeriodicTable[71] = "Lu"; mPeriodicTable[72] = "Hf"; mPeriodicTable[73] = "Ta"; mPeriodicTable[74] = "W"; mPeriodicTable[75] = "Re"; mPeriodicTable[76] = "Os"; mPeriodicTable[77] = "Ir"; mPeriodicTable[78] = "Pt"; mPeriodicTable[79] = "Au"; mPeriodicTable[80] = "Hg"; mPeriodicTable[81] = "Tl"; mPeriodicTable[82] = "Pb"; mPeriodicTable[83] = "Bi"; mPeriodicTable[84] = "Po"; mPeriodicTable[85] = "At"; mPeriodicTable[86] = "Rn"; mPeriodicTable[87] = "Fr"; mPeriodicTable[88] = "Ra"; mPeriodicTable[89] = "Ac"; mPeriodicTable[90] = "Th"; mPeriodicTable[91] = "Pa"; mPeriodicTable[92] = "U"; mPeriodicTable[93] = "Np"; mPeriodicTable[94] = "Pu"; mPeriodicTable[95] = "Am"; mPeriodicTable[96] = "Cm"; mPeriodicTable[97] = "Bk"; mPeriodicTable[251] = "Cf"; mPeriodicTable[252] = "Es"; mPeriodicTable[100] = "Fm"; mPeriodicTable[258] = "Md"; mPeriodicTable[102] = "No"; mPeriodicTable[103] = "Lr"; mPeriodicTable[261] = "Rf"; mPeriodicTable[105] = "Db"; mPeriodicTable[106] = "Sg"; mPeriodicTable[107] = "Bh"; mPeriodicTable[108] = "Hs"; mPeriodicTable[109] = "Mt"; // // Register parameters (ptr, name, default) // registerParameter(&mUserInt, "userInt", 0); registerParameter(&mUserDouble, "userDouble", 0.); registerParameter(&mUserString, "userString", string("")); registerParameter(&mA, "A", static_cast(1)); registerParameter(&mVectorMesonId, "vectorMesonId", 443); // J/psi registerParameter(&mDipoleModelName, "dipoleModel", string("bSat")); registerParameter(&mDipoleModelParameterSetName, "dipoleModelParameterSet", string("KMW")); registerParameter(&mTableSetTypeName, "tableSetType", string("total_and_coherent")); registerParameter(&mQ2min, "Q2min", 1000.); // no limits if max <= min registerParameter(&mQ2max, "Q2max", 0.); registerParameter(&mWmin, "Wmin", 1000.); registerParameter(&mWmax, "Wmax", 0.); registerParameter(&mXpomMin, "xpomMin", 1e-8); registerParameter(&mXpomMax, "xpomMax", 1.); registerParameter(&mVerbose, "verbose", false); registerParameter(&mVerboseLevel, "verboseLevel", 0); registerParameter(&mRootfile, "rootfile", string("sartre.root")); registerParameter(&mSeed, "seed", static_cast(time(0))); registerParameter(&mUPC, "UPC", false); registerParameter(&mUPCA, "UPCA", static_cast(1)); } Settings::~Settings() { for (unsigned int k=0; kSetSeed(mSeed); // needed for TH1::GetRandom() } bool Settings::readSettingsFromFile(const char *file) { if (!file) return false; // nothing to do mRuncard = string(file); mLines.clear(); // // Open file // ifstream ifs(file); if (!ifs) { cout << "Settings::readSettingsFromFile(): error, cannot open file '" << file << "'." << endl; return false; } // // Read file into vector of strings, skip comments and empty lines // while (ifs.good() && !ifs.eof()) { string line; getline (ifs, line); if (ifs.eof() && line.empty()) break; // empty line if (line.find_first_not_of(" \n\t\v\b\r\f\a") == string::npos) continue; // if first character is not a letter/digit, then taken to be a comment. int firstChar = line.find_first_not_of(" \n\t\v\b\r\f\a"); if (!isalnum(line[firstChar])) continue; mLines.push_back(line); } ifs.close(); // done with I/O // // Process vector of strings one at a time and use // it to set registered variables. // for (unsigned int i=0; i> name; // find value string string valueString; splitLine >> valueString; if (!splitLine) { cout << "Settings::readSettingsFromFile(): error, value of variable '" << name.c_str() << "' not recognized." << endl; } istringstream modeData(valueString); // // Loop over registered variables and see which fits. // Not particular elegant but does the job and saves // a lot of programming in derived classes. // bool isRegistered = false; for (unsigned int k=0; k>)) { // test SettingsParameter> *var = dynamic_cast>*> (mRegisteredParameters[k]); if (var->name == name) { var->address->push_back(atof(valueString.c_str())); // first value while (splitLine.good() && !splitLine.eof()) { // get remaining string nextValue; splitLine >> nextValue; var->address->push_back(atof(nextValue.c_str())); if (splitLine.eof()) break; } isRegistered = true; } } else if (typeid(*mRegisteredParameters[k]) == typeid(SettingsParameter)) { SettingsParameter *var = dynamic_cast*> (mRegisteredParameters[k]); if (var->name == name) { modeData >> (*(var->address)); isRegistered = true; } } else if (typeid(*mRegisteredParameters[k]) == typeid(SettingsParameter)) { SettingsParameter *var = dynamic_cast*> (mRegisteredParameters[k]); if (var->name == name) { modeData >> (*(var->address)); isRegistered = true; } } else if (typeid(*mRegisteredParameters[k]) == typeid(SettingsParameter)) { SettingsParameter *var = dynamic_cast*> (mRegisteredParameters[k]); if (var->name == name) { modeData >> (*(var->address)); isRegistered = true; } } else if (typeid(*mRegisteredParameters[k]) == typeid(SettingsParameter)) { SettingsParameter *var = dynamic_cast*> (mRegisteredParameters[k]); if (var->name == name) { modeData >> (*(var->address)); isRegistered = true; } } else if (typeid(*mRegisteredParameters[k]) == typeid(SettingsParameter)) { SettingsParameter *var = dynamic_cast*> (mRegisteredParameters[k]); if (var->name == name) { *(var->address) = valueString; isRegistered = true; } } else if (typeid(*mRegisteredParameters[k]) == typeid(SettingsParameter)) { SettingsParameter *var = dynamic_cast*> (mRegisteredParameters[k]); if (var->name == name) { isRegistered = true; if (valueString == string("true") || valueString == string("True") || valueString == string("TRUE") || valueString == string("on") || valueString == string("On") || valueString == string("ON") || valueString == string("Yes") || valueString == string("yes") || valueString == string("YES") || valueString == string("T") || valueString == string("t") || valueString == string("1") ) { *(var->address) = true; } else { *(var->address) = false; } } } } if (!isRegistered) { cout << "Settings::readSettingsFromFile(): error, parameter identifier '" << name.c_str() << "' not recognized." << endl; } } // // Consolidate input (after burner) // consolidateCommonSettings(); consolidateSettings(); // overloaded return true; } bool Settings::list(ostream& os) { const int fieldWidth = 28; os << "\nRun Settings:" << endl; for (unsigned int k=0; k)) { SettingsParameter *var = dynamic_cast*> (mRegisteredParameters[k]); os << setw(fieldWidth) << var->name.c_str() << "\t" << *(var->address) << endl; } else if (typeid(*mRegisteredParameters[k]) == typeid(SettingsParameter)) { SettingsParameter *var = dynamic_cast*> (mRegisteredParameters[k]); os << setw(fieldWidth) << var->name.c_str() << "\t" << *(var->address) << endl; } else if (typeid(*mRegisteredParameters[k]) == typeid(SettingsParameter)) { SettingsParameter *var = dynamic_cast*> (mRegisteredParameters[k]); os << setw(fieldWidth) << var->name.c_str() << "\t" << *(var->address) << endl; } else if (typeid(*mRegisteredParameters[k]) == typeid(SettingsParameter)) { SettingsParameter *var = dynamic_cast*> (mRegisteredParameters[k]); os << setw(fieldWidth) << var->name.c_str() << "\t" << *(var->address) << endl; } else if (typeid(*mRegisteredParameters[k]) == typeid(SettingsParameter)) { SettingsParameter *var = dynamic_cast*> (mRegisteredParameters[k]); os << setw(fieldWidth) << var->name.c_str() << "\t" << var->address->c_str() << endl; } else if (typeid(*mRegisteredParameters[k]) == typeid(SettingsParameter)) { SettingsParameter *var = dynamic_cast*> (mRegisteredParameters[k]); os << setw(fieldWidth) << var->name.c_str() << "\t" << (*(var->address) ? "true" : "false") << endl; } } os << endl; return true; } TParticlePDG* Settings::lookupPDG(int id) const { if (mPDG) return mPDG->GetParticle(id); else return 0; } string Settings::particleName(int pdgID) { string name("unknown"); if (abs(pdgID) < 1000000000) { // particle if (mPDG) { TParticlePDG *part = lookupPDG(pdgID); if (part) name = part->GetName(); } if (abs(pdgID) == 990) name = "pomeron"; } else { // nucleus in 10LZZZAAAI PDG format int id = pdgID; // int iso = id%10; id /= 10; int A = id%1000; id /= 1000; int Z = id%1000; stringstream namestream; namestream << mPeriodicTable[Z] << "(" << A << ")"; name = namestream.str(); } return name; } void Settings::setVerbose(bool val) { mVerbose = val; if (mVerbose && mVerboseLevel == 0) mVerboseLevel = 1; if (!mVerbose && mVerboseLevel != 0) mVerboseLevel = 0; } bool Settings::verbose() const {return mVerbose;} void Settings::setVerboseLevel(int val) { mVerboseLevel = val; if (!mVerbose && mVerboseLevel != 0) mVerbose = true; if (mVerbose && mVerboseLevel == 0) mVerbose = false; } int Settings::verboseLevel() const {return mVerboseLevel;} void Settings::setQ2min(double val) { mQ2min = val;} double Settings::Q2min() const {return mQ2min;} double Settings::Qmin() const {return sqrt(mQ2min);} void Settings::setQ2max(double val) { mQ2max = val;} double Settings::Q2max() const {return mQ2max;} double Settings::Qmax() const {return sqrt(mQ2max);} void Settings::setW2min(double val) { mWmin = sqrt(val);} void Settings::setWmin(double val) { mWmin = val;} double Settings::Wmin() const {return mWmin;} double Settings::W2min() const {return mWmin*mWmin;} void Settings::setW2max(double val) { mWmax = sqrt(val);} void Settings::setWmax(double val) { mWmax = val;} double Settings::Wmax() const {return mWmax;} double Settings::W2max() const {return mWmax*mWmax;} void Settings::setXpomMin(double val) {mXpomMin = val;} void Settings::setXpomMax(double val) {mXpomMax = val;} double Settings::xpomMin() const {return mXpomMin;} double Settings::xpomMax() const {return mXpomMax;} int Settings::vectorMesonId() const {return mVectorMesonId;} void Settings::setVectorMesonId(int val) {mVectorMesonId = val;} string Settings::dipoleModelName() const {return mDipoleModelName;} DipoleModelType Settings::dipoleModelType() const {return mDipoleModelType;} void Settings::setDipoleModelType(DipoleModelType val) { mDipoleModelType = val; if (mDipoleModelType == bSat) mDipoleModelName = string("bSat"); else if (mDipoleModelType == bNonSat) mDipoleModelName = string("bNonSat"); else if (mDipoleModelType == bCGC) mDipoleModelName = string("bCGC"); } unsigned int Settings::A() const {return mA;} void Settings::setA(unsigned int val) {mA = val;} void Settings::setRootfile(const char* val){ mRootfile = val; } string Settings::rootfile() const { return mRootfile; } string Settings::dipoleModelParameterSetName() const {return mDipoleModelParameterSetName;} DipoleModelParameterSet Settings::dipoleModelParameterSet() const {return mDipoleModelParameterSet;} void Settings::setDipoleModelParameterSet(DipoleModelParameterSet val) { mDipoleModelParameterSet = val; if (mDipoleModelParameterSet == KMW) mDipoleModelParameterSetName = string("KMW"); else if (mDipoleModelParameterSet == HMPZ) mDipoleModelParameterSetName = string("HMPZ"); else if (mDipoleModelParameterSet == CUSTOM) mDipoleModelParameterSetName = string("CUSTOM"); } string Settings::tableSetTypeName() const {return mTableSetTypeName;} TableSetType Settings::tableSetType() const {return mTableSetType;} void Settings::setTableSetType(TableSetType val) { mTableSetType = val; if (mTableSetType == total_and_coherent) mTableSetTypeName = string("total_and_coherent"); else if (mTableSetType == coherent_and_incoherent) mTableSetTypeName = string("coherent_and_incoherent"); } void Settings::consolidateCommonSettings() { // // Check if verbose levels and flags are consistent // The verbose flag superseeds the verboseLevel. // if (mVerbose && mVerboseLevel == 0) mVerboseLevel = 1; if (mVerboseLevel != 0 && !mVerbose) mVerboseLevel = 0; // // Set random generator seed // mRandomGenerator.SetSeed(mSeed); gRandom->SetSeed(mSeed); // needed for TH1::GetRandom() // // Dipole Model // if (mDipoleModelName == string("bSat")) mDipoleModelType = bSat; else if (mDipoleModelName == string("bNonSat")) mDipoleModelType = bNonSat; else if (mDipoleModelName == string("bCGC")) mDipoleModelType = bCGC; else { cout << "Settings::consolidateCommonSettings(): Error, dipole model '" << mDipoleModelName.c_str() << "' is not defined." << endl; exit(1); } // // Dipole Model Parameter Set // if (mDipoleModelParameterSetName == string("KMW")) mDipoleModelParameterSet = KMW; else if (mDipoleModelParameterSetName == string("HMPZ")) mDipoleModelParameterSet = HMPZ; else if (mDipoleModelParameterSetName == string("CUSTOM")) mDipoleModelParameterSet = CUSTOM; else { cout << "Settings::consolidateCommonSettings(): Error, dipole model parameter set'" << mDipoleModelParameterSetName.c_str() << "' is not defined." << endl; exit(1); } // // Table Set Type // if (mTableSetTypeName == string("total_and_coherent")) mTableSetType = total_and_coherent; else if (mTableSetTypeName == string("coherent_and_incoherent")) mTableSetType = coherent_and_incoherent; else { cout << "Settings::consolidateCommonSettings(): Error, table set type '" << mTableSetTypeName.c_str() << "' is not defined." << endl; exit(1); } } void Settings::setUPC(bool val){ mUPC = val; } bool Settings::UPC() const { return mUPC; } void Settings::setUPCA(unsigned int val){ mUPCA = val; } unsigned int Settings::UPCA() const { return mUPCA; } Index: trunk/src/WaveOverlap.h =================================================================== --- trunk/src/WaveOverlap.h (revision 369) +++ trunk/src/WaveOverlap.h (revision 370) @@ -1,82 +1,82 @@ //============================================================================== // WaveOverlap.h // -// Copyright (C) 2010-2018 Tobias Toll and Thomas Ullrich +// Copyright (C) 2010-2019 Tobias Toll and Thomas Ullrich // // This file is part of Sartre. // // 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. // 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, see . // // Author: Tobias Toll // Last update: // $Date$ // $Author$ //============================================================================== #ifndef WaveOverlap_h #define WaveOverlap_h class DipoleModelParameters; class WaveOverlap { public: WaveOverlap(); virtual ~WaveOverlap(); virtual void setWaveOverlapFunctionParameters(int); virtual double T(double, double, double)=0; virtual double L(double, double, double)=0; virtual void setProcess(int); virtual void testBoostedGaussianParameters(int); protected: DipoleModelParameters *mParameters; }; class WaveOverlapVM : public WaveOverlap { public: WaveOverlapVM(); void setWaveOverlapFunctionParameters(int); void setProcess(int); void testBoostedGaussianParameters(int); private: double T(double, double, double); double L(double, double, double); double transverseWaveFunction(double, double); double longitudinalWaveFunction(double, double); double dDrTransverseWaveFunction(double, double); double laplaceRLongitudinalWaveFunction(double, double); double uiDecayWidth(double*, double*); double uiNormL(const double*); double uiNormT(const double*); private: double mNT, mRT2; double mMf; // mass of quarks in vector meson double mBoostedGaussianMf; // // mass of quarks in vector meson's boosted Gaussian wave fct. double mMf2; double mBoostedGaussianMf2; double mEf; double mMV; double mNL, mRL2; }; class WaveOverlapDVCS : public WaveOverlap { private: double T(double, double, double); double L(double, double, double); }; inline void WaveOverlap::setWaveOverlapFunctionParameters(int) {/* no op*/} inline void WaveOverlap::setProcess(int) {/* no op*/}; inline void WaveOverlap::testBoostedGaussianParameters(int) {/* no op*/}; #endif Index: trunk/src/TableCollection.cpp =================================================================== --- trunk/src/TableCollection.cpp (revision 369) +++ trunk/src/TableCollection.cpp (revision 370) @@ -1,570 +1,569 @@ //============================================================================== // TableCollection.cpp // -// Copyright (C) 2010-2016 Tobias Toll and Thomas Ullrich +// Copyright (C) 2010-2019 Tobias Toll and Thomas Ullrich // // This file is part of Sartre. // // 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. // 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, see . // // Author: Thomas Ullrich // Last update: // $Date$ // $Author$ //============================================================================== // // Note that we do not take the lambda_A table into account when calculating // the range since there is a fall back solution to calculate lambda if the // table is not present. See class CrossSection. // //============================================================================== #include "TSystemDirectory.h" #include "TSystem.h" #include "TList.h" #include "EventGeneratorSettings.h" #include "TableCollection.h" #include "Table.h" #include #include #include #include #include #define PR(x) cout << #x << " = " << (x) << endl; TableCollection::TableCollection() {/* no op */} TableCollection::TableCollection(int A, DipoleModelType typ, DipoleModelParameterSet set, int vmID) { init(A, typ, set, vmID); } TableCollection& TableCollection::operator=(const TableCollection& tc) { if (this != &tc) { for (unsigned int i=0; iWorkingDirectory(); // // Build directory path // stringstream pathstream; pathstream << getenv("SARTRE_DIR") << "/tables/" << A << '/'; if (type == bSat) pathstream << "bSat"; else if (type == bNonSat) pathstream << "bNonSat"; else pathstream << "bCGC"; pathstream << '/' << vmID; string path = pathstream.str(); // // Query list of all files in directory // and create tables for each file ending // in ".root", ignore others. // TSystemDirectory directory; directory.SetDirectory(path.c_str()); TList *list = directory.GetListOfFiles(); if (!list) { cout << "TableCollection::init(): Error, cannot find directory '" << path.c_str() << "' holding tables." << endl; return false; } TIter next(list); unsigned int numberOfTablesRead = 0; bool upcMode = EventGeneratorSettings::instance()->UPC(); while (TSystemFile* file = dynamic_cast(next()) ) { if (file->IsDirectory()) continue; // ignore directories string name(file->GetName()); size_t pos = name.find(".root"); if (pos == string::npos || name.substr(pos) != string(".root")) continue; // ignore files not ending in .root string fullpath = path + '/' + name; Table *table = new Table; if (table->read(fullpath.c_str()) && table->dipoleModelParameterSet() == set) { if ( (!upcMode && !table->isUPC()) || (upcMode && table->isUPC())) mTables.push_back(table); numberOfTablesRead++; if (EventGeneratorSettings::instance()->verboseLevel() > 1) cout << "Loaded table from file '" << fullpath.c_str() << "'." << endl; } } // // Cleanup // // Change ROOT directory back to directory we were before reading the tables. // Otherwise reading tables interferes with user application. // list->Delete(); gSystem->ChangeDirectory(saveCWD.c_str()); if (!numberOfTablesRead) { cout << "TableCollection::init(): Error, could not find any tables at '" << path.c_str() << "'" << endl; cout << " that fit the requested parameters: A=" << A << ", type=" << type << ", set=" << set << " , vmID=" << vmID << endl; return false; } return true; } bool TableCollection::tableExists(GammaPolarization pol, AmplitudeMoment mom) const { Table* currentTable; for (unsigned int i=0; ipolarization() != pol) continue; if (currentTable->moment() != mom) continue; return true; } return false; } // // UPC version // bool TableCollection::tableExists(AmplitudeMoment mom) const { Table* currentTable; for (unsigned int i=0; imoment() != mom) continue; return true; } return false; } bool TableCollection::available(double Q2, double W2, double t, GammaPolarization pol, AmplitudeMoment mom) const { // // Check if table can provide this value // unsigned short nTables = 0; Table* currentTable; for (unsigned int i=0; ipolarization() != pol) continue; if (currentTable->moment() != mom) continue; if (t >= currentTable->minT() && t <= currentTable->maxT()) { if (Q2 >= currentTable->minQ2() && Q2 <= currentTable->maxQ2()) { if (W2 >= currentTable->minW2() && W2 <= currentTable->maxW2()) { nTables++; } } } } if (nTables) return true; else return false; } bool TableCollection::available(double xpom, double t, AmplitudeMoment mom) const { // // Check if table can provide this value // unsigned short nTables = 0; Table* currentTable; for (unsigned int i=0; imoment() != mom) continue; if (t >= currentTable->minT() && t <= currentTable->maxT()) { if (xpom >= currentTable->minX() && xpom <= currentTable->maxX()) { nTables++; } } } if (nTables) return true; else return false; } double TableCollection::get(double Q2, double W2, double t, GammaPolarization pol, AmplitudeMoment mom) const { Table *table; return get(Q2, W2, t, pol, mom, table); } // // UPC version // double TableCollection::get(double xpom, double t, AmplitudeMoment mom) const { Table *table; return get(xpom, t, mom, table); } double TableCollection::get(double Q2, double W2, double t, GammaPolarization pol, AmplitudeMoment mom, Table *&table) const { static unsigned int errorCount = 0; const unsigned int maxErrorCount = 10; // // First get the tables that contain the necessary info. // Later this should be a bit refined, here we simply // loop over all tables to collect the relevant one(s). // vector associatedTables; Table* currentTable; for (unsigned int i=0; ipolarization() != pol) continue; if (currentTable->moment() != mom) continue; if (t >= currentTable->minT() && t <= currentTable->maxT()) { if (Q2 >= currentTable->minQ2() && Q2 <= currentTable->maxQ2()) { if (W2 >= currentTable->minW2() && W2 <= currentTable->maxW2()) { associatedTables.push_back(currentTable); } } } } if (associatedTables.size() == 0) { table = 0; - if (mom != lambda_A) { // no warnings needed for lambda_A (can be calculated w/o tables) + if (mom != lambda_A && mom != lambda_skew) { // no warnings needed (can be calculated w/o tables) string txt; if (mom == mean_A) txt = "mean_A"; else if (mom == mean_A2) txt = "mean_A2"; else if (mom == variance_A) txt = "variance_A"; else txt = "unknown"; cout << "TableCollection::get(): Warning, could not find any table containing t=" << t << ", Q2=" << Q2 << ", W2=" << W2 << endl; cout << " Tables searched were for moment = " << txt.c_str() << ", polarization = " << (pol == transverse ? 'T' : 'L') << endl; errorCount++; if (errorCount > maxErrorCount) { cout << "TableCollection::get(): Error: Too many warnings (>" << maxErrorCount << "), possibly due to missing table(s)." << endl; cout << " Stop execution now. Please check the installation of tables." << endl; exit(1); } } return 0; } // // In case of overlap of tables the following // policy applies: // 1. Use the table with the highest priority. // 2. If there's more than one high priority table // we average their values (if > 0). // unsigned int maxPriority = 0; for (unsigned int i=0; ipriority() > maxPriority) maxPriority = associatedTables[i]->priority(); } double result = 0; int validCounter = 0; table = 0; for (unsigned int i=0; ipriority() == maxPriority) { double value = associatedTables[i]->get(Q2, W2, t); if (value > 0) { validCounter++; result += value; table = associatedTables[i]; } } } if (validCounter) result /= validCounter; return result; } // // UPC version // double TableCollection::get(double xpom, double t, AmplitudeMoment mom, Table *&table) const { static unsigned int errorCount = 0; const unsigned int maxErrorCount = 10; // // First get the tables that contain the necessary info. // Later this should be a bit refined, here we simply // loop over all tables to collect the relevant one(s). // vector associatedTables; Table* currentTable; for (unsigned int i=0; imoment() != mom) continue; if (t >= currentTable->minT() && t <= currentTable->maxT()) { if (xpom >= currentTable->minX() && xpom <= currentTable->maxX()) { associatedTables.push_back(currentTable); } } } if (associatedTables.size() == 0) { table = 0; - if (mom != lambda_A ) // no warnings needed for lambda_A (can be calculated w/o tables) - if( mom != lambda_skew ){ // no warnings needed for lambda_skew (can be calculated from lambda_A) - string txt; - if (mom == mean_A) - txt = "mean_A"; - else if (mom == mean_A2) - txt = "mean_A2"; - else if (mom == variance_A) - txt = "variance_A"; - else - txt = "unknown"; + if ( mom != lambda_skew && mom != lambda_A ) { // no warnings needed (can be calculated w/o tables) + string txt; + if (mom == mean_A) + txt = "mean_A"; + else if (mom == mean_A2) + txt = "mean_A2"; + else if (mom == variance_A) + txt = "variance_A"; + else + txt = "unknown"; + + cout << "TableCollection::get(): Warning, could not find any table containing t=" << t << ", xp=" << xpom + << ". Moment = " << txt << ", " << mom << endl; - cout << "TableCollection::get(): Warning, could not find any table containing t=" << t << ", xp=" << xpom - << ". Moment = "< maxErrorCount) { - cout << "TableCollection::get(): Error: Too many warnings (>" - << maxErrorCount - << "), possibly due to missing table(s)." << endl; - cout << " Stop execution now. Please check the installation of tables." << endl; - exit(1); - } - } - return 0; + if (errorCount > maxErrorCount) { + cout << "TableCollection::get(): Error: Too many warnings (>" + << maxErrorCount + << "), possibly due to missing table(s)." << endl; + cout << " Stop execution now. Please check the installation of tables." << endl; + exit(1); + } + } + return 0; } // // In case of overlap of tables the following // policy applies: // 1. Use the table with the highest priority. // 2. If there's more than one high priority table // we average their values (if > 0). // unsigned int maxPriority = 0; for (unsigned int i=0; ipriority() > maxPriority) maxPriority = associatedTables[i]->priority(); } double result = 0; int validCounter = 0; table = 0; double value = 0; for (unsigned int i=0; ipriority() == maxPriority) { value = associatedTables[i]->get(xpom, t); if (value > 0) { validCounter++; result += value; table = associatedTables[i]; } } } if (validCounter) result /= validCounter; return result; } void TableCollection::list(ostream& os, bool opt) const { for (unsigned int i=0; ilist(os, opt); } double TableCollection::minQ2() const { if (EventGeneratorSettings::instance()->UPC()) return 0; return minimumValue(0); } double TableCollection::maxQ2() const { if (EventGeneratorSettings::instance()->UPC()) return 0; return maximumValue(0); } double TableCollection::minW2() const { if (EventGeneratorSettings::instance()->UPC()) return 0; return minimumValue(1); } double TableCollection::maxW2() const { if (EventGeneratorSettings::instance()->UPC()) return 0; return maximumValue(1); } double TableCollection::minW() const {return sqrt(minW2());} double TableCollection::maxW() const {return sqrt(maxW2());} double TableCollection::minT() const { if (EventGeneratorSettings::instance()->UPC()) return minimumValue(1); else return minimumValue(2); } double TableCollection::maxT() const { if (EventGeneratorSettings::instance()->UPC()) return maximumValue(1); else return maximumValue(2); } double TableCollection::minX() const { if (EventGeneratorSettings::instance()->UPC()) return minimumValue(0); else return 0; } double TableCollection::maxX() const { if (EventGeneratorSettings::instance()->UPC()) return maximumValue(0); else return 0; } // // For regular tables: kind: Q2=0, W2=1, T=2 // For UPC tables: kind: xpom = 0, t=1 // double TableCollection::minimumValue(unsigned int kind) const { double minPerTableType[4]; // L, L2, T, T2 fill(minPerTableType, minPerTableType+4, numeric_limits::max()); for (unsigned int i=0; iUPC()) { switch (kind) { case (0): val = mTables[i]->minX(); break; case (1): val = mTables[i]->minT(); break; } } else { switch (kind) { case (0): val = mTables[i]->minQ2(); break; case (1): val = mTables[i]->minW2(); break; default: val = mTables[i]->minT(); break; } } if (mTables[i]->isLongitudinal()) { // L or L2 if (mTables[i]->isMeanA()) minPerTableType[0] = min(minPerTableType[0],val); // L else minPerTableType[1] = min(minPerTableType[1],val); // L2 } else { // T or T2 if (mTables[i]->isMeanA()) minPerTableType[2] = min(minPerTableType[2],val); // T else minPerTableType[3] = min(minPerTableType[3],val); // T2 } } int startElement = EventGeneratorSettings::instance()->UPC() ? 2 : 0; double largestMin = *max_element(minPerTableType+startElement, minPerTableType+4); return largestMin; } double TableCollection::maximumValue(unsigned int kind) const { double maxPerTableType[4]; // L, L2, T, T2 fill(maxPerTableType, maxPerTableType+4, -numeric_limits::max()); for (unsigned int i=0; iUPC()) { switch (kind) { case (0): val = mTables[i]->maxX(); break; case (1): val = mTables[i]->maxT(); break; } } else { switch (kind) { case (0): val = mTables[i]->maxQ2(); break; case (1): val = mTables[i]->maxW2(); break; default: val = mTables[i]->maxT(); break; } } if (mTables[i]->isLongitudinal()) { // L or L2 if (mTables[i]->isMeanA()) maxPerTableType[0] = max(maxPerTableType[0],val); // L else maxPerTableType[1] = max(maxPerTableType[1],val); // L2 } else { // T or T2 if (mTables[i]->isMeanA()) maxPerTableType[2] = max(maxPerTableType[2],val); // T else maxPerTableType[3] = max(maxPerTableType[3],val); // T2 } } int startElement = EventGeneratorSettings::instance()->UPC() ? 2 : 0; double smallestMax = *min_element(maxPerTableType+startElement, maxPerTableType+4); return smallestMax; } Index: trunk/src/IntegrandWrappers.h =================================================================== --- trunk/src/IntegrandWrappers.h (revision 369) +++ trunk/src/IntegrandWrappers.h (revision 370) @@ -1,255 +1,255 @@ //============================================================================== // IntegrandWrappers.h // -// Copyright (C) 2010-2018 Tobias Toll and Thomas Ullrich +// Copyright (C) 2010-2019 Tobias Toll and Thomas Ullrich // // This file is part of Sartre. // // 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. // 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, see . // // Author: Tobias Toll // Last update: // $Date$ // $Author$ //============================================================================== // // Wrapper functions meeting the definition of an integrand (see cuba.h): // typedef int (*integrand_t)(const int *ndim, const double x[], // const int *ncomp, double f[], void *userdata); // // Use the void* argument of the integrand to pass a pointer to an // integrals object, which does the actual calculation via its // uiAmplitudeXXX method. // // Cuba only allows integrations with limits 0 and 1, therefore all variables // in the integrations have to be scaled to their actual limits, // and compensated by a Jacobian. // // It saves time to do the integration over four separate functions rather than // letting the integrand being 4D, since in the latter case the integration // continues until all 4 integrals have reached the desired precision, // which is not necessary. // A quick test yields that this way is ~20% faster. // //============================================================================== int integrandWrapperTIm( const int*, const double x[], const int *, double fval[], void* ptr2integrals) { IntegralsExclusive* ip = static_cast( ptr2integrals ); double upperBRValue=2.5*ip->dipoleModel()->nucleus()->radius(); double low[4] = {0, 0, 1e-2, 0}; // b, z, r, phi - lower double high[4] = {upperBRValue, 1, upperBRValue, 2.*M_PI}; // b, z, r, phi - upper double b = low[0] + (high[0] - low[0]) * x[0]; //fm double z = low[1] + (high[1] - low[1]) * x[1]; double r = low[2] + (high[2] - low[2]) * x[2]; //fm double phi = low[3] + (high[3] - low[3]) * x[3]; double jacobian = (high[0]-low[0])*(high[1]-low[1])*(high[2]-low[2])*(high[3]-low[3]); double t=ip->kinematicPoint[0]; double Q2=ip->kinematicPoint[1]; double xprobe=ip->kinematicPoint[3]; double Delta = sqrt(fabs(t)); fval[0]=ip->uiAmplitudeTIm(b, z, r, phi, Q2, xprobe, Delta)*jacobian; return 0; } int integrandWrapperTRe( const int *, const double x[], const int *, double fval[], void* ptr2integrals) { IntegralsExclusive* ip = static_cast( ptr2integrals ); double upperBRValue=2.5*ip->dipoleModel()->nucleus()->radius(); double low[4] = {0, 0, 1e-2, 0}; // b, z, r, phi - lower double high[4] = {upperBRValue, 1, upperBRValue, 2.*M_PI}; // b, z, r, phi - upper double b = low[0] + (high[0] - low[0]) * x[0]; //fm double z = low[1] + (high[1] - low[1]) * x[1]; double r = low[2] + (high[2] - low[2]) * x[2]; //fm double phi = low[3] + (high[3] - low[3]) * x[3]; double jacobian = (high[0]-low[0])*(high[1]-low[1])*(high[2]-low[2])*(high[3]-low[3]); double t=ip->kinematicPoint[0]; double Q2=ip->kinematicPoint[1]; double xprobe=ip->kinematicPoint[3]; double Delta = sqrt(fabs(t)); fval[0]=ip->uiAmplitudeTRe(b, z, r, phi, Q2, xprobe, Delta)*jacobian; return 0; } int integrandWrapperLIm( const int *, const double x[], const int *, double fval[], void* ptr2integrals) { IntegralsExclusive* ip = static_cast( ptr2integrals ); double upperBRValue=2.5*ip->dipoleModel()->nucleus()->radius(); double low[4] = {0, 0, 1e-2, 0}; // b, z, r, phi - lower double high[4] = {upperBRValue, 1, upperBRValue, 2.*M_PI}; // b, z, r, phi - upper double b = low[0] + (high[0] - low[0]) * x[0]; //fm double z = low[1] + (high[1] - low[1]) * x[1]; double r = low[2] + (high[2] - low[2]) * x[2]; //fm double phi = low[3] + (high[3] - low[3]) * x[3]; double jacobian = (high[0]-low[0])*(high[1]-low[1])*(high[2]-low[2])*(high[3]-low[3]); double t=ip->kinematicPoint[0]; double Q2=ip->kinematicPoint[1]; double xprobe=ip->kinematicPoint[3]; double Delta = sqrt(fabs(t)); fval[0]=ip->uiAmplitudeLIm(b, z, r, phi, Q2, xprobe, Delta)*jacobian; return 0; } int integrandWrapperLRe( const int *, const double x[], const int *, double fval[], void* ptr2integrals) { IntegralsExclusive* ip = static_cast( ptr2integrals ); double upperBRValue=2.5*ip->dipoleModel()->nucleus()->radius(); double low[4] = {0, 0, 1e-2, 0}; // b, z, r, phi - lower double high[4] = {upperBRValue, 1, upperBRValue, 2.*M_PI}; // b, z, r, phi - upper double b = low[0] + (high[0] - low[0]) * x[0]; //fm double z = low[1] + (high[1] - low[1]) * x[1]; double r = low[2] + (high[2] - low[2]) * x[2]; //fm double phi = low[3] + (high[3] - low[3]) * x[3]; double jacobian = (high[0]-low[0])*(high[1]-low[1])*(high[2]-low[2])*(high[3]-low[3]); double t=ip->kinematicPoint[0]; double Q2=ip->kinematicPoint[1]; double xprobe=ip->kinematicPoint[3]; double Delta = sqrt(fabs(t)); fval[0]=ip->uiAmplitudeLRe(b, z, r, phi, Q2, xprobe, Delta)*jacobian; return 0; } int integrandWrapperCoherentAmplitudeT( const int *, const double x[], const int *, double fval[], void* ptr2integrals) { IntegralsExclusive* ip = static_cast( ptr2integrals ); double upperBRValue=2.5*ip->dipoleModel()->nucleus()->radius(); double low[5] = {0, 0, 1e-2}; // b, z, r - lower double high[5] = {upperBRValue, 1, upperBRValue}; // b, z, r - upper double b = low[0] + (high[0] - low[0]) * x[0]; //fm double z = low[1] + (high[1] - low[1]) * x[1]; double r = low[2] + (high[2] - low[2]) * x[2]; //fm double jacobian = (high[0]-low[0])*(high[1]-low[1])*(high[2]-low[2]); double t=ip->kinematicPoint[0]; double Q2=ip->kinematicPoint[1]; double Delta = sqrt(fabs(t)); fval[0]=ip->uiCoherentAmplitudeT(b, z, r, Q2, Delta)*jacobian; return 0; } int integrandWrapperCoherentAmplitudeL( const int *, const double x[], const int *, double fval[], void* ptr2integrals) { IntegralsExclusive* ip = static_cast( ptr2integrals ); double upperBRValue=2.5*ip->dipoleModel()->nucleus()->radius(); double low[5] = {0, 0, 1e-2}; // b, z, r - lower double high[5] = {upperBRValue, 1, upperBRValue}; // b, z, r - upper double b = low[0] + (high[0] - low[0]) * x[0]; //fm double z = low[1] + (high[1] - low[1]) * x[1]; double r = low[2] + (high[2] - low[2]) * x[2]; //fm double jacobian = (high[0]-low[0])*(high[1]-low[1])*(high[2]-low[2]); double t=ip->kinematicPoint[0]; double Q2=ip->kinematicPoint[1]; double Delta = sqrt(fabs(t)); fval[0]=ip->uiCoherentAmplitudeL(b, z, r, Q2, Delta)*jacobian; return 0; } int integrandWrapperTForSkewedness( const int*, const double x[], const int *, double fval[], void* ptr2integrals) { IntegralsExclusive* ip = static_cast( ptr2integrals ); double upperBRValue=2.5*ip->dipoleModel()->nucleus()->radius(); double low[3] = {0, 0, 1e-2}; // b, z, r, phi - lower double high[3] = {upperBRValue, 1, upperBRValue}; // b, z, r, phi - upper double b = low[0] + (high[0] - low[0]) * x[0]; //fm double z = low[1] + (high[1] - low[1]) * x[1]; double r = low[2] + (high[2] - low[2]) * x[2]; //fm double jacobian = (high[0]-low[0])*(high[1]-low[1])*(high[2]-low[2]); double t=ip->kinematicPoint[0]; double Q2=ip->kinematicPoint[1]; double xprobe=ip->kinematicPoint[3]; double Delta = sqrt(fabs(t)); fval[0]=ip->uiAmplitudeTForSkewedness(b, z, r, Q2, xprobe, Delta)*jacobian; return 0; } int integrandWrapperLForSkewedness( const int*, const double x[], const int *, double fval[], void* ptr2integrals) { IntegralsExclusive* ip = static_cast( ptr2integrals ); double upperBRValue=2.5*ip->dipoleModel()->nucleus()->radius(); double low[3] = {0, 0, 1e-2}; // b, z, r, phi - lower double high[3] = {upperBRValue, 1, upperBRValue}; // b, z, r, phi - upper double b = low[0] + (high[0] - low[0]) * x[0]; //fm double z = low[1] + (high[1] - low[1]) * x[1]; double r = low[2] + (high[2] - low[2]) * x[2]; //fm double jacobian = (high[0]-low[0])*(high[1]-low[1])*(high[2]-low[2]); double t=ip->kinematicPoint[0]; double Q2=ip->kinematicPoint[1]; double xprobe=ip->kinematicPoint[3]; double Delta = sqrt(fabs(t)); fval[0]=ip->uiAmplitudeLForSkewedness(b, z, r, Q2, xprobe, Delta)*jacobian; return 0; } int integrandWrapperTep( const int*, const double x[], const int *, double fval[], void* ptr2integrals) { IntegralsExclusive* ip = static_cast( ptr2integrals ); double upperBRValue=2.5*ip->dipoleModel()->nucleus()->radius(); double low[3] = {0, 0, 1e-2}; // b, z, r, phi - lower double high[3] = {upperBRValue, 1, upperBRValue}; // b, z, r, phi - upper double b = low[0] + (high[0] - low[0]) * x[0]; //fm double z = low[1] + (high[1] - low[1]) * x[1]; double r = low[2] + (high[2] - low[2]) * x[2]; //fm double jacobian = (high[0]-low[0])*(high[1]-low[1])*(high[2]-low[2]); double t=ip->kinematicPoint[0]; double Q2=ip->kinematicPoint[1]; double xprobe=ip->kinematicPoint[3]; double Delta = sqrt(fabs(t)); fval[0]=ip->uiAmplitudeTep(b, z, r, Q2, xprobe, Delta)*jacobian; return 0; } int integrandWrapperLep( const int*, const double x[], const int *, double fval[], void* ptr2integrals) { IntegralsExclusive* ip = static_cast( ptr2integrals ); double upperBRValue=2.5*ip->dipoleModel()->nucleus()->radius(); double low[3] = {0, 0, 1e-2}; // b, z, r, phi - lower double high[3] = {upperBRValue, 1, upperBRValue}; // b, z, r, phi - upper double b = low[0] + (high[0] - low[0]) * x[0]; //fm double z = low[1] + (high[1] - low[1]) * x[1]; double r = low[2] + (high[2] - low[2]) * x[2]; //fm double jacobian = (high[0]-low[0])*(high[1]-low[1])*(high[2]-low[2]); double t=ip->kinematicPoint[0]; double Q2=ip->kinematicPoint[1]; double xprobe=ip->kinematicPoint[3]; double Delta = sqrt(fabs(t)); fval[0]=ip->uiAmplitudeLep(b, z, r, Q2, xprobe, Delta)*jacobian; return 0; } Index: trunk/src/GridSpline.h =================================================================== --- trunk/src/GridSpline.h (revision 369) +++ trunk/src/GridSpline.h (revision 370) @@ -1,280 +1,280 @@ //============================================================================== // GridSpline.h // -// Copyright (C) 2010-2013 Tobias Toll and Thomas Ullrich +// Copyright (C) 2010-2019 Tobias Toll and Thomas Ullrich // // This file is part of Sartre. // // 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. // 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, see . // // Author: Thomas Ullrich // Last update: // $Date$ // $Author$ //============================================================================== // // Implementation of grid splines (a type of spline interpolations) // // This algorithm was written by Cristian Lalescu. // See http://arxiv.org/abs/0905.3564 for details. // The code here is slightly modified for use in Sartre. // //============================================================================== #ifndef GridSpline_h #define GridSpline_h #include "GridSplineBetaPolynomials.h" #include "GridSplineInterpolateSums.h" template class local_scal_1D { private: double val[q]; int g; public: local_scal_1D(){g = (q-2)/2;} ~local_scal_1D(){} inline double &operator()(int grid_point) { return val[(grid_point+g)%q]; } }; template class local_scal_3D { private: double val[q][q][q]; int g; public: local_scal_3D(){g = (q-2)/2;} ~local_scal_3D(){} inline double &operator()(int grid_pointx, int grid_pointy, int grid_pointz) { return val[(grid_pointx+g)%q][(grid_pointy+g)%q][(grid_pointz+g)%q]; } }; inline void beta_n3(local_scal_1D<4> &bx, double x) { bx(-1) = BETA_n3_q4_j2(1-x); bx( 0) = BETA_n3_q4_j1(1-x); bx( 1) = BETA_n3_q4_j1(x); bx( 2) = BETA_n3_q4_j2(x); } inline void beta_n5(local_scal_1D<4> &bx, double x) { bx(-1) = BETA_n5_q4_j2(1-x); bx( 0) = BETA_n5_q4_j1(1-x); bx( 1) = BETA_n5_q4_j1(x); bx( 2) = BETA_n5_q4_j2(x); } inline void beta_n3(local_scal_1D<6> &bx, double x) { bx(-2) = BETA_n3_q6_j3(1-x); bx(-1) = BETA_n3_q6_j2(1-x); bx( 0) = BETA_n3_q6_j1(1-x); bx( 1) = BETA_n3_q6_j1(x); bx( 2) = BETA_n3_q6_j2(x); bx( 3) = BETA_n3_q6_j3(x); } inline void beta_n5(local_scal_1D<6> &bx, double x) { bx(-2) = BETA_n5_q6_j3(1-x); bx(-1) = BETA_n5_q6_j2(1-x); bx( 0) = BETA_n5_q6_j1(1-x); bx( 1) = BETA_n5_q6_j1(x); bx( 2) = BETA_n5_q6_j2(x); bx( 3) = BETA_n5_q6_j3(x); } inline void beta_n7(local_scal_1D<6> &bx, double x) { bx(-2) = BETA_n7_q6_j3(1-x); bx(-1) = BETA_n7_q6_j2(1-x); bx( 0) = BETA_n7_q6_j1(1-x); bx( 1) = BETA_n7_q6_j1(x); bx( 2) = BETA_n7_q6_j2(x); bx( 3) = BETA_n7_q6_j3(x); } inline void beta_n9(local_scal_1D<6> &bx, double x) { bx(-2) = BETA_n9_q6_j3(1-x); bx(-1) = BETA_n9_q6_j2(1-x); bx( 0) = BETA_n9_q6_j1(1-x); bx( 1) = BETA_n9_q6_j1(x); bx( 2) = BETA_n9_q6_j2(x); bx( 3) = BETA_n9_q6_j3(x); } inline void beta_n3(local_scal_1D<8> &bx, double x) { bx(-3) = BETA_n3_q8_j4(1-x); bx(-2) = BETA_n3_q8_j3(1-x); bx(-1) = BETA_n3_q8_j2(1-x); bx( 0) = BETA_n3_q8_j1(1-x); bx( 1) = BETA_n3_q8_j1(x); bx( 2) = BETA_n3_q8_j2(x); bx( 3) = BETA_n3_q8_j3(x); bx( 4) = BETA_n3_q8_j4(x); } inline void beta_n5(local_scal_1D<8> &bx, double x) { bx(-3) = BETA_n5_q8_j4(1-x); bx(-2) = BETA_n5_q8_j3(1-x); bx(-1) = BETA_n5_q8_j2(1-x); bx( 0) = BETA_n5_q8_j1(1-x); bx( 1) = BETA_n5_q8_j1(x); bx( 2) = BETA_n5_q8_j2(x); bx( 3) = BETA_n5_q8_j3(x); bx( 4) = BETA_n5_q8_j4(x); } inline void beta_n7(local_scal_1D<8> &bx, double x) { bx(-3) = BETA_n7_q8_j4(1-x); bx(-2) = BETA_n7_q8_j3(1-x); bx(-1) = BETA_n7_q8_j2(1-x); bx( 0) = BETA_n7_q8_j1(1-x); bx( 1) = BETA_n7_q8_j1(x); bx( 2) = BETA_n7_q8_j2(x); bx( 3) = BETA_n7_q8_j3(x); bx( 4) = BETA_n7_q8_j4(x); } inline void beta_n9(local_scal_1D<8> &bx, double x) { bx(-3) = BETA_n9_q8_j4(1-x); bx(-2) = BETA_n9_q8_j3(1-x); bx(-1) = BETA_n9_q8_j2(1-x); bx( 0) = BETA_n9_q8_j1(1-x); bx( 1) = BETA_n9_q8_j1(x); bx( 2) = BETA_n9_q8_j2(x); bx( 3) = BETA_n9_q8_j3(x); bx( 4) = BETA_n9_q8_j4(x); } inline void beta_n11(local_scal_1D<8> &bx, double x) { bx(-3) = BETA_n11_q8_j4(1-x); bx(-2) = BETA_n11_q8_j3(1-x); bx(-1) = BETA_n11_q8_j2(1-x); bx( 0) = BETA_n11_q8_j1(1-x); bx( 1) = BETA_n11_q8_j1(x); bx( 2) = BETA_n11_q8_j2(x); bx( 3) = BETA_n11_q8_j3(x); bx( 4) = BETA_n11_q8_j4(x); } inline void beta_n13(local_scal_1D<8> &bx, double x) { bx(-3) = BETA_n13_q8_j4(1-x); bx(-2) = BETA_n13_q8_j3(1-x); bx(-1) = BETA_n13_q8_j2(1-x); bx( 0) = BETA_n13_q8_j1(1-x); bx( 1) = BETA_n13_q8_j1(x); bx( 2) = BETA_n13_q8_j2(x); bx( 3) = BETA_n13_q8_j3(x); bx( 4) = BETA_n13_q8_j4(x); } double grid_spline(int spline_order, local_scal_3D<4> &f, double x, double y, double z) { local_scal_1D<4> bx, by, bz; switch(spline_order) { case 3: beta_n3(bx,x); beta_n3(by,y); beta_n3(bz,z); break; case 5: beta_n5(bx,x); beta_n5(by,y); beta_n5(bz,z); break; } return SUM_3D_Q4_unsafe_macro(f,bx,by,bz); } double grid_spline(int spline_order, local_scal_3D<6> &f, double x, double y, double z) { local_scal_1D<6> bx, by, bz; switch(spline_order) { case 3: beta_n3(bx,x); beta_n3(by,y); beta_n3(bz,z); break; case 5: beta_n5(bx,x); beta_n5(by,y); beta_n5(bz,z); break; case 7: beta_n7(bx,x); beta_n7(by,y); beta_n7(bz,z); break; case 9: beta_n9(bx,x); beta_n9(by,y); beta_n9(bz,z); break; } return SUM_3D_Q6_unsafe_macro(f,bx,by,bz); } double grid_spline(int spline_order, local_scal_3D<8> &f, double x, double y, double z) { local_scal_1D<8> bx, by, bz; switch(spline_order) { case 3: beta_n3(bx,x); beta_n3(by,y); beta_n3(bz,z); break; case 5: beta_n5(bx,x); beta_n5(by,y); beta_n5(bz,z); break; case 7: beta_n7(bx,x); beta_n7(by,y); beta_n7(bz,z); break; case 9: beta_n9(bx,x); beta_n9(by,y); beta_n9(bz,z); break; case 11: beta_n11(bx,x); beta_n11(by,y); beta_n11(bz,z); break; case 13: beta_n13(bx,x); beta_n13(by,y); beta_n13(bz,z); break; } return SUM_3D_Q8_unsafe_macro(f,bx,by,bz); } #endif Index: trunk/src/Sartre.h =================================================================== --- trunk/src/Sartre.h (revision 369) +++ trunk/src/Sartre.h (revision 370) @@ -1,111 +1,111 @@ //============================================================================== // Sartre.h // -// Copyright (C) 2010-2016 Tobias Toll and Thomas Ullrich +// Copyright (C) 2010-2019 Tobias Toll and Thomas Ullrich // // This file is part of Sartre. // // 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. // 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, see . // // Author: Thomas Ullrich // Last update: // $Date$ // $Author$ //============================================================================== #ifndef Sartre_h #define Sartre_h #include "Event.h" #include "EventGeneratorSettings.h" #include "ExclusiveFinalStateGenerator.h" #include "CrossSection.h" #include "TableCollection.h" #include "FrangibleNucleus.h" #include "Enumerations.h" #include "TLorentzVector.h" #include "Math/Functor.h" #include "TUnuran.h" #include #include #include using namespace std; class TUnuranMultiContDist; class Sartre { public: Sartre(); virtual ~Sartre(); virtual bool init(const char* = 0); virtual bool init(const string&); virtual Event* generateEvent(); virtual double totalCrossSection(); // in kinematic limits used for generation virtual double totalCrossSection(double lower[3], double upper[3]); // t, Q2, W EventGeneratorSettings* runSettings(); const FrangibleNucleus* nucleus() const; void listStatus(ostream& os=cout) const; time_t runTime() const; vector > kinematicLimits(); // t, Q2, W private: virtual double calculateTotalCrossSection(double lower[3], double upper[3]); // t, Q2, W2 private: Sartre(const Sartre&); Sartre operator=(const Sartre&); bool mIsInitialized; time_t mStartTime; unsigned long mEvents; unsigned long mTries; double mTotalCrossSection; TLorentzVector mElectronBeam; TLorentzVector mHadronBeam; double mS; unsigned int mA; int mVmID; DipoleModelType mDipoleModelType; DipoleModelParameterSet mDipoleModelParameterSet; Event *mCurrentEvent; FrangibleNucleus *mNucleus; FrangibleNucleus *mUpcNucleus; TableCollection *mTableCollection; TableCollection *mProtonTableCollection; CrossSection *mCrossSection; EventGeneratorSettings *mSettings; double mLowerLimit[3]; // t, Q2, W2 (t, xpom for UPC) double mUpperLimit[3]; // t, Q2, W2 ROOT::Math::Functor *mPDF_Functor; TUnuran *mUnuran; TUnuranMultiContDist *mPDF; unsigned long mEventCounter; unsigned long mTriesCounter; ExclusiveFinalStateGenerator mFinalStateGenerator; }; ostream& operator<<(ostream& os, const TLorentzVector&); #endif Index: trunk/src/PhotonFlux.cpp =================================================================== --- trunk/src/PhotonFlux.cpp (revision 369) +++ trunk/src/PhotonFlux.cpp (revision 370) @@ -1,258 +1,258 @@ //============================================================================== // PhotonFlux.cpp // -// Copyright (C) 2010-2013 Tobias Toll and Thomas Ullrich +// Copyright (C) 2010-2019 Tobias Toll and Thomas Ullrich // // This file is part of Sartre. // // 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. // 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, see . // // Author: Thomas Ullrich // Last update: // $Date$ // $Author$ //============================================================================== #include "PhotonFlux.h" #include "Constants.h" #include "Kinematics.h" #include "EventGeneratorSettings.h" #include "Nucleus.h" #include #include "TF1.h" #include "Math/Functor.h" #include "Math/IntegratorMultiDim.h" #include "Math/WrappedTF1.h" #include "Math/GaussIntegrator.h" #define PR(x) cout << #x << " = " << (x) << endl; PhotonFlux::PhotonFlux() { mS = 0; mIsUPC=false; mSettings = EventGeneratorSettings::instance(); if(mSettings->UPC()){ mNucleusUPC = new Nucleus(mSettings->UPCA()); mNucleus = new Nucleus(mSettings->A()); if(mSettings->UPCA()>1 and mSettings->A()>1){ cout<<"Calculating TAA table..."<electronBeamEnergy(); //The beam that shines mIsUPC=true; } mSIsSet=false; } PhotonFlux::PhotonFlux(double s) { mS = s; mIsUPC=false; mSettings = EventGeneratorSettings::instance(); if (mSettings->UPC()) { mNucleusUPC = new Nucleus(mSettings->UPCA()); mNucleus = new Nucleus(mSettings->A()); if(mSettings->UPCA()>1 and mSettings->A()>1){ cout<<"Calculating TAA table..."<electronBeamEnergy(); //The beam that shines mIsUPC=true; cout<<"Warning in PhotonFlux::PhotonFlux() Sartre is not yet ready for UPC..."<1 || Kinematics::error()) return 0; if (Q2 > Kinematics::Q2max(mS)) return 0; double result = alpha_em/(2*M_PI*Q2*mS*y); result *= (1 + (1-y)*(1-y)) - (2*(1-y)*Kinematics::Q2min(y)/Q2); return result; } double PhotonFlux::fluxLongitudinal(double Q2, double W2) const { // // Longitudinal photon flux // double y = Kinematics::y(Q2, Kinematics::x(Q2, W2), mS); if (y<0 || y>1 || Kinematics::error()) return 0; if (Q2 > Kinematics::Q2max(mS)) return 0; double result = alpha_em/(2*M_PI*Q2*mS*y); result *= 2*(1-y); return result; } double PhotonFlux::nuclearPhotonFlux(double Egamma) const { if (Egamma < 0) { if (mSettings->verbose() && mSettings->verboseLevel() > 4) cout << "PhotonFlux::nuclearPhotonFlux(): Warning, negative Egamma as argument.\n" << " Return 0 for photon flux." << endl; return 0; } double bmin=0.; double bmax=1e10; //Could be arbitrary large (TF1 doesn't care) TF1 fFluxAA("fluxAA", this, &PhotonFlux::uiNuclearPhotonFlux, bmin, bmax, 1); fFluxAA.SetParameter(0, Egamma); ROOT::Math::WrappedTF1 wfFluxAA(fFluxAA); ROOT::Math::GaussIntegrator giFluxAA; giFluxAA.SetFunction(wfFluxAA); giFluxAA.SetAbsTolerance(0.); giFluxAA.SetRelTolerance(1e-5); return giFluxAA.IntegralUp(bmin)/hbarc; //dN/dEgamma GeV-1 } double PhotonFlux::uiNuclearPhotonFlux(double* var, double* par) const { // // https://arxiv.org/abs/1607.03838v1 // double b=var[0]; //fm double eGamma=par[0]; //GeV int Apom=mNucleus->A(); int AUPC=mNucleusUPC->A(); double Z=mNucleusUPC->Z(); double ebeamMass=mNucleusUPC->atomicMass()/mNucleusUPC->A(); //Mass per nucleon //GeV double beamLorentzGamma=mEBeamEnergy/ebeamMass; double beamLorentzGamma2=beamLorentzGamma*beamLorentzGamma; double xi=eGamma*b/hbarc/beamLorentzGamma; //GeV0 double K0=TMath::BesselK0(xi); double K1=TMath::BesselK1(xi); double prefactor=Z*Z*alpha_em/(M_PI*M_PI)*eGamma/beamLorentzGamma2; //GeV1 double N=prefactor*(K1*K1+K0*K0/beamLorentzGamma2); //GeV1 //Spectrum is calculated under the assumption that there is no //hadronic interaction between the beam particles. //Therefore it has to be multiplied by the probability for this: double Pnohad=1; if(Apom>1 and AUPC>1){ //nucleus-nucleus interaction Pnohad=exp(-sigma_nn(mS)*mTAA_of_b->Interpolate(b)); //GeV0 } else if(Apom==1 and AUPC>1){ //proton-nucleus Pnohad=exp(-sigma_nn(mS)*mNucleusUPC->T(b)); } else if(Apom>1 and AUPC==1){ //nucleus-proton Pnohad=exp(-sigma_nn(mS)*mNucleus->T(b)); } else{ //proton-proton double b02=19.8; //GeV-2 double scamp=1-exp(-b*b/hbarc2/2./b02); Pnohad=scamp*scamp; } double result=2*M_PI*b/hbarc*N*Pnohad; //GeV0 return result; } void PhotonFlux::calculateTAAlookupTable(){ double rbhigh=upperIntegrationLimit*(mNucleus->radius()+mNucleusUPC->radius()); mTAA_of_b=new TH1D("mTAA_of_b", "mTAA_of_b", 1000, 0, rbhigh); for(unsigned int i=1; i<=1000; i++){ double b=mTAA_of_b->GetBinCenter(i); mTAA_of_b->SetBinContent(i, TAA(b)); } } double PhotonFlux::sigma_nn(double s) const{ //parameters http://ntrs.nasa.gov/archive/nasa/casi.ntrs.nasa.gov/20080014212.pdf table 2 // // Following KNSGB: http://arxiv.org/abs/1607.03838v1 (eq.6) // double Z=33.73; //mb double B=0.2838; //mb double s0=1.;//GeV2 double Y1=13.67; //mb double s1=1.; //GeV2 double eta1=0.412; double Y2=7.77; //mb double eta2=0.5626; double result = Z+B*log(s/s0)*log(s/s0)+Y1*pow(s1/s, eta1)-Y2*pow(s1/s, eta2); //mb = 1e-3b = 1e-1 fm2 result *= 1e-1; //fm2 (1 barn = 1e2 fm2) return result/hbarc2; //GeV^-2 } double PhotonFlux::TAA(double b){ //Integral over dr^2=2*pi*r*dr for double rbhigh=upperIntegrationLimit*(mNucleus->radius()+mNucleusUPC->radius()); double lo[2]={0., 0.}; //r, theta double hi[2]={rbhigh, 2*M_PI}; ROOT::Math::Functor wf(this, &PhotonFlux::TAAForIntegration, 2); ROOT::Math::IntegratorMultiDim ig(ROOT::Math::IntegrationMultiDim::kADAPTIVE); ig.SetFunction(wf); ig.SetAbsTolerance(0.); ig.SetRelTolerance(1e-4); mB=b; double result=ig.Integral(lo, hi); //GeV^3*fm result/=hbarc; //GeV^2 return result; } double PhotonFlux::TAAForIntegration(const double* var) const{ double r=var[0]; //fm double phi=var[1]; double b=mB; //fm //Put A1 in the origin, and A2 on the y-axis at distance b: double arg1=r; double arg2=sqrt(r*r+b*b-2*b*r*sin(phi)); //fm double T1 = mNucleusUPC->T(arg1); //GeV^2 double T2 = mNucleus->T(arg2); //GeV^2 return r/hbarc*T1*T2; //GeV^3 } Index: trunk/src/Nucleon.h =================================================================== --- trunk/src/Nucleon.h (revision 369) +++ trunk/src/Nucleon.h (revision 370) @@ -1,48 +1,48 @@ //============================================================================== // Nucleon.h // -// Copyright (C) 2010-2013 Tobias Toll and Thomas Ullrich +// Copyright (C) 2010-2019 Tobias Toll and Thomas Ullrich // // This file is part of Sartre. // // 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. // 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, see . // // Author: Thomas Ullrich // Last update: // $Date$ // $Author$ //============================================================================== #ifndef Nucleon_h #define Nucleon_h #include #include "TVector3.h" using namespace std; class Nucleon { public: Nucleon(); Nucleon(const TVector3&, unsigned int); Nucleon(const TVector3&); const TVector3& position() const; unsigned int charge() const; void setPosition(const TVector3&); void setCharge(unsigned int); private: TVector3 mPosition; unsigned int mCharge; }; #endif Index: trunk/src/ModeFinderFunctor.cpp =================================================================== --- trunk/src/ModeFinderFunctor.cpp (revision 369) +++ trunk/src/ModeFinderFunctor.cpp (revision 370) @@ -1,110 +1,110 @@ //============================================================================== // ModeFinderFunctor.cpp // -// Copyright (C) 2010-2013 Tobias Toll and Thomas Ullrich +// Copyright (C) 2010-2019 Tobias Toll and Thomas Ullrich // // This file is part of Sartre. // // 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. // 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, see . // // Author: Thomas Ullrich // Last update: // $Date$ // $Author$ //============================================================================== #include "ModeFinderFunctor.h" #include "CrossSection.h" #include "Kinematics.h" #include using namespace std; #define PR(x) cout << #x << " = " << (x) << endl; ModeFinderFunctor::ModeFinderFunctor() { mCrossSection = 0; mQ2 = mVmMass = mMinT = mMaxT = 0; } ModeFinderFunctor::ModeFinderFunctor(CrossSection* cs, double Q2, double vmMass, double tmin, double tmax) { mCrossSection = cs; mQ2 = Q2; mVmMass = vmMass; mMinT = tmin; mMaxT = tmax; } void ModeFinderFunctor::setVmMass(double val) {mVmMass = val;} void ModeFinderFunctor::setQ2(double val) {mQ2 = val;} void ModeFinderFunctor::setMinT(double val) {mMinT = val;} void ModeFinderFunctor::setMaxT(double val) {mMaxT = val;} double ModeFinderFunctor::DoEval(double W2) const { if (mCrossSection) { double t = Kinematics::tmax(0, mQ2, W2, mVmMass); // first arg (t) set to 0 here if (t > mMaxT) t = mMaxT; // don't exceed given (table) maximum (smallest |t|) if (t < mMinT) return 0; // lower table limits (treat different than max limit) double result = (*mCrossSection)(t, mQ2, W2); // t, Q2, W2 return -result; // minimum=maximum } else { return 0; } } ROOT::Math::IGenFunction* ModeFinderFunctor::Clone() const { return new ModeFinderFunctor(mCrossSection, mQ2, mVmMass, mMinT, mMaxT); } UPCModeFinderFunctor::UPCModeFinderFunctor() { mCrossSection = 0; mVmMass = mHBeamEnergy = mEBeamEnergy = 0; } UPCModeFinderFunctor::UPCModeFinderFunctor(CrossSection* cs, double vmMass, double hEnergy, double eEnergy) { mCrossSection = cs; mVmMass = vmMass; mHBeamEnergy = hEnergy; mEBeamEnergy = eEnergy; } double UPCModeFinderFunctor::DoEval(double val) const { if (mCrossSection) { double xpom = exp(val); // x comes as log(x) double t = Kinematics::tmax(xpom); bool ok = Kinematics::validUPC(mHBeamEnergy, mEBeamEnergy, t, xpom, mVmMass, false); if (ok) { double result = (*mCrossSection)(t, xpom); return -result; // minimum=maximum } else { return 0; } } else { return 0; } } ROOT::Math::IGenFunction* UPCModeFinderFunctor::Clone() const { return new UPCModeFinderFunctor(mCrossSection, mVmMass, mHBeamEnergy, mEBeamEnergy); } Index: trunk/src/Nucleus.h =================================================================== --- trunk/src/Nucleus.h (revision 369) +++ trunk/src/Nucleus.h (revision 370) @@ -1,76 +1,76 @@ //============================================================================== // Nucleus.h // -// Copyright (C) 2010-2016 Tobias Toll and Thomas Ullrich +// Copyright (C) 2010-2019 Tobias Toll and Thomas Ullrich // // This file is part of Sartre. // // 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. // 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, see . // // Author: Thomas Ullrich // Last update: // $Date$ // $Author$ //============================================================================== #ifndef Nucleus_h #define Nucleus_h #include #include using namespace std; class TH1D; class Nucleus { public: Nucleus(); Nucleus(unsigned int A); Nucleus(const Nucleus&); virtual ~Nucleus(); Nucleus& operator=(const Nucleus&); virtual void init(unsigned int A); double T(double b) const; // b in fm, returns in GeV^2 double TofProton(double b); unsigned int A() const; unsigned int Z() const; float spin() const; // in hbar double radius() const; // in fm string name() const; int pdgID() const; // id of this nucleus int pdgID(int Z, int A) const; double atomicMass() const; void normalizationOfT(double eps = 1.e-8); // for checks only double rho0() const; //in fm protected: double rho(double, double); double rhoForIntegration(double*, double*); double TForIntegration(double*, double*) const; protected: unsigned int mA; unsigned int mZ; float mSpin; double mMass; // atomic mass in GeV double mRadius; // fm - Wood-Saxon double mSurfaceThickness; // fm - Wood-Saxon double mRho0; // fm^-3 - Wood-Saxon double mOmega; // Wood-Saxon double mHulthenA; // for Hulthen distribution double mHulthenB; string mName; unique_ptr mLookupTable; // T lookup table }; #endif