Index: trunk/examples/sartreMain.cpp
===================================================================
--- trunk/examples/sartreMain.cpp (revision 437)
+++ trunk/examples/sartreMain.cpp (revision 438)
@@ -1,291 +1,297 @@
//==============================================================================
// sartreMain.cpp
//
// 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$
//==============================================================================
//
-// Example main program. Use to get started.
+// Example main program. Useful to get started and easy to modify to fit
+// the user need. Data are stored in a simple but complete Root TTree.
//
//==============================================================================
#include
#include
#include "TTree.h"
#include "TFile.h"
-#include "Sartre.h"
-#include "DipoleModelParameters.h"
#include "TGenPhaseSpace.h"
-#include "Settings.h"
#include "TH1D.h"
#include "TROOT.h"
#include "TLorentzVector.h"
#include "TClonesArray.h"
+#include "Sartre.h"
+#include "Settings.h"
+#include "DipoleModelParameters.h"
+#include "TwoBodyVectorMesonDecay.h"
#define PR(x) cout << #x << " = " << (x) << endl;
using namespace std;
struct rootSartreEvent {
double t;
double Q2;
double x;
double s;
double y;
double W;
double xpom;
int iEvent;
int pol; // 0=transverse or 1=longitudinal
int dmode; // 0=coherent, 1=Incoherent
};
rootSartreEvent myRootSartreEvent;
void randomlyReverseBeams(Event* ); // for UPC mode
int main(int argc, char *argv[])
{
//
// Check command line arguments
//
if (! (argc == 2 || argc == 3) ) {
cout << "Usage: " << argv[0] << " runcard [rootfile]" << endl;
return 2;
}
string runcard = argv[1];
//
// Create the generator and initialize it.
// Once initialized you cannot (should not) change
// the settings w/o re-initialing sartre.
//
Sartre sartre;
bool ok = sartre.init(runcard);
if (!ok) {
- cerr << "Initialization of sartre failed." << endl;
+ cerr << "Error: Initialization of sartre failed." << endl;
return 1;
}
EventGeneratorSettings* settings = sartre.runSettings();
//
// ROOT file
// Use the one from command line unless not given
// in which case the one in the runcard is used.
//
string rootfile;
if (argc == 3) {
rootfile = argv[2];
settings->setRootfile(argv[2]);
}
else
rootfile = settings->rootfile();
//
// Print out all Sartre settings
//
settings->list();
TFile *hfile = 0;
if (rootfile.size()) {
hfile = new TFile(rootfile.c_str(),"RECREATE");
cout << "ROOT file is '" << rootfile.c_str() << "'." << endl;
}
//
// Setup ROOT tree
//
TLorentzVector *eIn = new TLorentzVector;
TLorentzVector *pIn = new TLorentzVector;
TLorentzVector *vm = new TLorentzVector;
TLorentzVector *eOut = new TLorentzVector;
TLorentzVector *pOut = new TLorentzVector;
TLorentzVector *gamma = new TLorentzVector;
TLorentzVector *vmDaughter1 = new TLorentzVector;
TLorentzVector *vmDaughter2 = new TLorentzVector;
TClonesArray protons("TLorentzVector");
TClonesArray neutrons("TLorentzVector");
TClonesArray remnants("TLorentzVector");
TTree tree("tree","sartre");
tree.Branch("event", &myRootSartreEvent.t,
"t/D:Q2/D:x/D:s/D:y/D:W/D:xpom/D:iEvent/I:pol/I:dmode/I");
tree.Branch("eIn", "TLorentzVector", &eIn, 32000, 0);
tree.Branch("pIn", "TLorentzVector", &pIn, 32000, 0);
tree.Branch("vm", "TLorentzVector", &vm, 32000, 0);
tree.Branch("eOut", "TLorentzVector", &eOut, 32000, 0);
tree.Branch("pOut", "TLorentzVector", &pOut, 32000, 0);
tree.Branch("gamma","TLorentzVector", &gamma, 32000, 0);
tree.Branch("vmDaughter1", "TLorentzVector", &vmDaughter1, 32000, 0);
tree.Branch("vmDaughter2", "TLorentzVector", &vmDaughter2, 32000, 0);
if(settings->enableNuclearBreakup()){
tree.Branch("protons", &protons);
tree.Branch("neutrons", &neutrons);
tree.Branch("nuclearRemnants", &remnants);
}
//
// Prepare event generation
//
- TGenPhaseSpace decay; // for VM decays
- int daughterID = settings->userInt();
- double daughterMasses[2] = {0, 0};
+ TwoBodyVectorMesonDecay decayEngine;
+ pair daughters;
+ int daughterID = settings->userInt();
bool doPerformDecay = false;
+
if (daughterID && settings->vectorMesonId() != 22) {
- doPerformDecay = true;
- daughterMasses[0] = settings->lookupPDG(daughterID)->Mass();
- daughterMasses[1] = settings->lookupPDG(-daughterID)->Mass();
- cout << "Will decay vector meson: ";
- cout << settings->lookupPDG(settings->vectorMesonId())->GetName();
- cout << " -> ";
- cout << settings->lookupPDG(daughterID)->GetName();
- cout << " ";
- cout << settings->lookupPDG(-daughterID)->GetName();
- cout << endl;
+ if (abs(daughterID) == 11 || abs(daughterID) == 13 ||
+ abs(daughterID) == 211 || abs(daughterID) == 321) {
+ doPerformDecay = true;
+ cout << "Will decay vector meson: ";
+ cout << settings->lookupPDG(settings->vectorMesonId())->GetName();
+ cout << " -> ";
+ cout << settings->lookupPDG(daughterID)->GetName();
+ cout << " ";
+ cout << settings->lookupPDG(-daughterID)->GetName();
+ cout << endl;
+ }
+ else {
+ cerr << "Error: Cannot decay vector meson to daughters with ID=" << daughterID << "." << endl;
+ return 1;
+ }
}
+ //
+ // Events and how often to show status
+ //
int nPrint;
if (settings->timesToShow())
nPrint = settings->numberOfEvents()/settings->timesToShow();
else
nPrint = 0;
unsigned long maxEvents = settings->numberOfEvents();
cout << "Generating " << maxEvents << " events." << endl << endl;
//
// Event generation
//
for (unsigned long iEvent = 0; iEvent < maxEvents; iEvent++) {
+
//
// Generate one event
//
Event *event = sartre.generateEvent();
if (nPrint && (iEvent+1)%nPrint == 0 && iEvent != 0) {
cout << "processed " << iEvent+1 << " events" << endl;
}
//
// If Sartre is run in UPC mode, half of the events needs to be
// rotated around and axis perpendicular to z:
//
- if(settings->UPC() and settings->A()==settings->UPCA()){
+ if(settings->UPC() && settings->A() == settings->UPCA()){
randomlyReverseBeams(event);
}
//
// Print out (here only for the first few events)
//
if (iEvent < 10) event->list();
//
// Fill ROOT tree
//
myRootSartreEvent.iEvent = event->eventNumber;
myRootSartreEvent.t = event->t;
myRootSartreEvent.Q2 = event->Q2;
myRootSartreEvent.x = event->x;
myRootSartreEvent.y = event->y;
myRootSartreEvent.s = event->s;
myRootSartreEvent.W = event->W;
myRootSartreEvent.xpom = event->xpom;
myRootSartreEvent.pol = event->polarization == transverse ? 0 : 1;
myRootSartreEvent.dmode = event->diffractiveMode == coherent ? 0 : 1;
eIn = &event->particles[0].p;
pIn = &event->particles[1].p;
eOut = &event->particles[2].p;
pOut = &event->particles[6].p;
vm = &event->particles[4].p;
gamma = &event->particles[3].p;
//If the event is incoherent, and nuclear breakup is enabled, fill the remnants to the tree
if(settings->enableNuclearBreakup() and event->diffractiveMode == incoherent){
protons.Clear();
neutrons.Clear();
remnants.Clear();
for(unsigned int iParticle=7; iParticle < event->particles.size(); iParticle++){
if(event->particles[iParticle].status == 1) { // Final-state particle
const Particle& particle = event->particles[iParticle];
switch (abs(particle.pdgId)) {
case 2212: // (Anti-)proton
new(protons[protons.GetEntries()]) TLorentzVector(particle.p);
break;
case 2112: // (Anti-)neutron
new(neutrons[neutrons.GetEntries()]) TLorentzVector(particle.p);
break;
default: // Any other remnant
new(remnants[remnants.GetEntries()]) TLorentzVector(particle.p);
break;
} // switch
} // if
} // for
} // if
//
- // Decay the vector meson and fill the decay roducts in the tree:
+ // Decay the vector meson and fill the decay products in the tree.
+ // For the decay we use the version that is sensitive to the
+ // polarization of the virtual photon (on a statistical basis).
//
- if(doPerformDecay) {
- if( decay.SetDecay(*vm, 2, daughterMasses) ){
- double weight = decay.Generate(); // weight is always 1 here
- if ( (weight-1) > FLT_EPSILON) {
- cout << "sartreMain: Warning weight != 1, weight = " << weight << endl;
- }
- vmDaughter1 = decay.GetDecay(0);
- vmDaughter2 = decay.GetDecay(1);
- }
- else {
- cout << "sartreMain: Warning: Kinematics of Vector Meson does not allow decay!" << endl;
- }
+ if (doPerformDecay) {
+ daughters = decayEngine.decayVectorMeson(*vm, *event, daughterID);
+ vmDaughter1 = &daughters.first;
+ vmDaughter2 = &daughters.second;
}
tree.Fill();
}
cout << "All events processed\n" << endl;
//
// That's it, finish up
//
double totalCS=sartre.totalCrossSection();
TH1D* histoForCSandNumberOfEvents = new TH1D("histoForCSandNumberOfEvents", "Cross-section and Number of Events", 2, 0., 1.);
histoForCSandNumberOfEvents->SetBinContent(1, totalCS);
histoForCSandNumberOfEvents->SetBinContent(2, maxEvents);
double runTime = sartre.runTime();
hfile->Write();
cout << rootfile.c_str() << " written." << endl;
cout << "Total cross-section: " << totalCS << " nb" << endl;
sartre.listStatus();
cout << "CPU Time/event: " << 1000*runTime/maxEvents << " msec/evt" << endl;
return 0;
}
// UPC only
-void randomlyReverseBeams(Event* myEvent) {
-
+void randomlyReverseBeams(Event* myEvent)
+{
TRandom3 *random = EventGeneratorSettings::randomGenerator();
if(random->Uniform(1) > 0.5){
for(unsigned int i=0; iparticles.size(); i++)
myEvent->particles.at(i).p.RotateX(M_PI);
}
}