00001 // BLCollectiveComputation.hh 00002 /* 00003 This source file is part of G4beamline, http://g4beamline.muonsinc.com 00004 Copyright (C) 2003,2004,2005,2006 by Tom Roberts, all rights reserved. 00005 00006 This program is free software; you can redistribute it and/or 00007 modify it under the terms of the GNU General Public License 00008 as published by the Free Software Foundation; either version 2 00009 of the License, or (at your option) any later version. 00010 00011 This program is distributed in the hope that it will be useful, 00012 but WITHOUT ANY WARRANTY; without even the implied warranty of 00013 MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the 00014 GNU General Public License for more details. 00015 00016 http://www.gnu.org/copyleft/gpl.html 00017 */ 00018 00019 #ifndef BLCOLLECTIVECOMPUTATION_H 00020 #define BLCOLLECTIVECOMPUTATION_H 00021 00022 #include "G4Event.hh" 00023 #include "G4Track.hh" 00024 00025 /** struct BLTrackData -- data related to a track (for collective tracking) 00026 **/ 00027 struct BLTrackData { 00028 G4Event *event; 00029 G4Track *track; 00030 public: 00031 /// Constructor. 00032 BLTrackData(G4Event *e, G4Track *t) { event = e; track=t; } 00033 00034 /// destructor. DOES NOT DELETE ANY OTHER OBJECTS. 00035 ~BLTrackData() { } 00036 }; 00037 00038 /** class BLCollectiveComputation -- base class for a collective computation 00039 * 00040 * Normally a command class that implements a collective computation 00041 * will be derived from this class as well as BLCommand. 00042 * Its command() function should register itself with 00043 * BLRunManager::getObject()->registerCollectiveComputation(this); 00044 * and then call 00045 * BLRunManager::getObject()->setCollectiveMode(true); 00046 * 00047 * If steps in time are also desired, it should call 00048 * BLRunManager::getObject()->setDeltaT(0.1*ns); 00049 * (with desired delta-T). Note that steps in time are not exact, so 00050 * the computation should probably check that the variation in time 00051 * among the tracks is small enough (in practive, 1 ps accuracy is 00052 * normal). 00053 * 00054 * Note that setDeltaT() can be called at any time, and will affect the 00055 * next step. It is probably desirable to adjust deltaT depending on the 00056 * importance of the collective computation (when the bunch is diffuse, 00057 * bigger deltaT won't affect the accuracy but will reduce the CPU time). 00058 * Caveat: if steps in time are to be used, setDeltaT() must be called 00059 * before tracking begins, and should never be <= 0.0 (values <= 0.0 00060 * means each track takes individual steps in space, which is probably 00061 * not useful). 00062 * 00063 * Note that runmanager->rejectCollectiveStep() can be called during 00064 * tracking or in collectiveStep() to reject the current step and 00065 * re-process it. This only makes sense if setDeltaT() has been 00066 * called with a smaller value of deltaT. Attempts to reject the very 00067 * first step are silently ignored (that step is used to process all 00068 * tracks to the same time). 00069 * 00070 * The basic sequence of collective tracking, including callbacks from 00071 * BLRunManger to each registered collective computation is: 00072 * 00073 * (generate beam tracks from beam commands, filling trackVector) 00074 * stepTime = (largest time from beam tracks) 00075 * beginCollectiveTracking() 00076 * first=true 00077 * loop over steps { 00078 * rejected=false 00079 * nActive=0 00080 * loop over tracks in trackVector { 00081 * if(rejected && !first) break; 00082 * beginTrack() 00083 * (discard remaining secondaries, if any) 00084 * process track to stepTime or killed 00085 * if(track is active) ++nActive 00086 * if(keepSecondaries) 00087 * append secondaries to trackVector 00088 * else 00089 * discard secondaries 00090 * } 00091 * if(!rejected || first) collectiveStep() 00092 * if(rejected && !first) { 00093 * restore saved tracks and stepTime 00094 * } else { 00095 * save tracks and stepTime 00096 * stepTime += deltaT 00097 * } 00098 * first=false 00099 * } while(nActive > 0) 00100 * endCollectiveTracking() 00101 * 00102 * Note: if multiple BLCollectiveComputation instances are registered 00103 * with BLRUnManager, the callbacks to them will occur in the order 00104 * in which they were registered (normally the order in which their 00105 * commands appear in the input file). 00106 * 00107 **/ 00108 class BLCollectiveComputation { 00109 public: 00110 BLCollectiveComputation() { }; 00111 virtual ~BLCollectiveComputation() { } 00112 00113 /// beginCollectiveTracking() is called after the track vector is 00114 /// constructed but before trackng begins. 00115 /// Can be used to allocate internal arrays or create NTuple-s. 00116 /// Note that additional tracks can be added to v as tracking proceeds; 00117 /// no tracks are ever removed (but they will change status). 00118 /// The vector v will not change during the run. 00119 virtual void beginCollectiveTracking(std::vector<BLTrackData>& v) { } 00120 00121 /// beginTrack() is called just before the track v[index] is 00122 /// tracked for the next step. Note that the user class can be 00123 /// derived from G4UserTrackingAction and registered to be called 00124 /// at the start and end of tracking for each track. The difference 00125 /// is this routine relates the track to the entry in v[], and 00126 /// also: BLRunManager::processOneTrack() can be called here, but 00127 /// not in PreUserTrackingAction(). 00128 virtual void beginTrack(std::vector<BLTrackData>& v, int index) { } 00129 00130 /// collectiveStep() is called after each collective step 00131 /// to perform the computation. 00132 /// It can store data for later use, and can modify the tracks. 00133 /// Note that collectiveStep() is not called until after the 00134 /// first step is taken, so you might want to call your 00135 /// collectiveStep() function at the end of beginCollectiveTracking() 00136 /// to store the state of tracks at the earliest time. 00137 /// Note: collectiveStep() can call runmanager->rejectCollectiveStep(), 00138 /// in which case the tracking since the previous return from 00139 /// collectiveStep() will be discarded and re-done; for this to make 00140 /// sense, runmanager->setDeltaT() should also be called with a 00141 /// smaller value -- this is one way to adapt deltaT dynamically. 00142 virtual void collectiveStep(std::vector<BLTrackData>& v) = 0; 00143 00144 /// endCollectiveTracking() is called after tracking is complete. 00145 /// Can be used to delete internal arrays and print a summary. 00146 virtual void endCollectiveTracking(std::vector<BLTrackData>& v) { } 00147 }; 00148 00149 #endif // BLCOLLECTIVECOMPUTATION_H