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); } }