ECCE @ EIC Software
 All Classes Namespaces Files Functions Variables Typedefs Enumerations Enumerator Friends Macros Groups Pages
RunActionMaster.cc
Go to the documentation of this file. Or view the newest version in sPHENIX GitHub for file RunActionMaster.cc
1 //
2 // ********************************************************************
3 // * License and Disclaimer *
4 // * *
5 // * The Geant4 software is copyright of the Copyright Holders of *
6 // * the Geant4 Collaboration. It is provided under the terms and *
7 // * conditions of the Geant4 Software License, included in the file *
8 // * LICENSE and available at http://cern.ch/geant4/license . These *
9 // * include a list of copyright holders. *
10 // * *
11 // * Neither the authors of this software system, nor their employing *
12 // * institutes,nor the agencies providing financial support for this *
13 // * work make any representation or warranty, express or implied, *
14 // * regarding this software system or assume any liability for its *
15 // * use. Please see the license in the file LICENSE and URL above *
16 // * for the full disclaimer and the limitation of liability. *
17 // * *
18 // * This code implementation is the result of the scientific and *
19 // * technical work of the GEANT4 collaboration. *
20 // * By using, copying, modifying or distributing the software (or *
21 // * any work based on the software) you agree to acknowledge its *
22 // * use in resulting scientific publications, and indicate your *
23 // * acceptance of all terms of the Geant4 Software license. *
24 // ********************************************************************
25 //
26 //
29 
30 #include "G4MPImanager.hh"
31 #include <stdio.h>
32 #include "G4Threading.hh"
33 #include "Analysis.hh"
34 #include "RunActionMaster.hh"
35 #include "g4root.hh" //ROOT Format for output
36 #include "RunMerger.hh"
37 #include "G4MPIscorerMerger.hh"
38 #include "G4MPIhistoMerger.hh"
39 #include "G4MPIntupleMerger.hh"
40 #include "Run.hh"
41 
42 //....oooOO0OOooo........oooOO0OOooo........oooOO0OOooo........oooOO0OOooo......
44  : G4UserRunAction(),
45  fMPIntupleMerger(nullptr)
46 {
47 #ifndef G4MULTITHREADED
48  if ( mergeNtuple &&
49  G4MPImanager::GetManager()->GetTotalSize() >= 2 ) {
50  // Activate MPI ntuple merging
51  // The merger must be created before creating G4AnalysisManager:
52  // (= the first call to G4AnalysisManager::Instance())
53  // and deleted only at the end of program
54  G4int nofReducedNtupleFiles = 0;
55  // Multiple reduced ntuple files are not yet supported
56  G4bool rowWise = false;
57  G4bool rowMode = true;
58  fMPIntupleMerger = new G4MPIntupleMerger(nofReducedNtupleFiles, rowWise, rowMode);
59  }
60 #endif
61 
62  // Book analysis in ctor
64  myana->SetUseNtuple(useNtuple);
65  myana->SetMergeNtuple(mergeNtuple);
66  myana->Book();
67 }
68 
69 //....oooOO0OOooo........oooOO0OOooo........oooOO0OOooo........oooOO0OOooo......
71 {
72  return new Run;
73 }
74 
75 //....oooOO0OOooo........oooOO0OOooo........oooOO0OOooo........oooOO0OOooo......
77 {
78  delete fMPIntupleMerger;
79 }
80 
81 //....oooOO0OOooo........oooOO0OOooo........oooOO0OOooo........oooOO0OOooo......
82 void
84 {
85  G4cout << "RunActionMaster::BeginOfRunAction" << G4endl;
86 
88 
90  std::ostringstream fname;
91  fname<<"dose-rank"<<rank;
92  myana->OpenFile(fname.str());
93  // OpenFile triggeres creating collecting/sending ntuples objects;
94  // must be called at BeginOfRunAction
95 }
96 
97 //....oooOO0OOooo........oooOO0OOooo........oooOO0OOooo........oooOO0OOooo......
98 void
100 {
101  G4cout << "RunActionMaster::EndOfRunAction" << G4endl;
102 
103  //This is executed by master thread only. Worker threads have already
104  //merged their results into this master threads.
105 
106  //We are going to merge the results via MPI for:
107  // 1. User-defined "Run" object
108  // 2. Command line scorers, if exists
109  // 3. G4Analysis objects
110 
111  // For debugging purposes in the following we write out results twice:
112  // BEFORE and AFTER the merging, so that rank 0 actually
113  // writes two files, the one called "*rank000*" will contain the partial
114  // results only from rank #0,
115  // the file *merged* contains the reduction from all ranks.
116  // It should be very easy to adapt this code
117 
118 
119  const G4int rank = G4MPImanager::GetManager()-> GetRank();
120 
121  G4cout << "=====================================================" << G4endl;
122  G4cout << "Start EndOfRunAction for master thread in rank: " << rank<<G4endl;
123  G4cout << "=====================================================" << G4endl;
124 
125  if ( ! G4MPImanager::GetManager()->IsExtraWorker() ) {
126  G4cout << "Go to merge on processing workers" << G4endl;
127 
128  //Merging of G4Run object:
129  //All ranks > 0 merge to rank #0
130  RunMerger rm(static_cast<const Run*>(arun), G4MPImanager::kRANK_MASTER, 5);
131  G4int ver = 0 ; //Use 4 for lots of info
132  if ( rank == 0 && ver == 0) ver = 1;
133 
134  if ( ver > 1 ) {
135  G4cout<<"Before merge the Run object has test counter value: "
136  <<static_cast<const Run*>(arun)->GetCounter()<<G4endl;
137  }
138  rm.SetVerbosity( ver );
139  rm.Merge();
140  if ( ver > 1 ) {
141  G4cout<<"After merge the Run object has test counter value: "
142  <<static_cast<const Run*>(arun)->GetCounter()
143  <<" (with 1 thread== number of ranks)"<<G4endl;
144  }
145 
146  //Merge of scorers
147  ver = 0;
149  const auto scor = G4ScoringManager::GetScoringManager();
150  G4MPIscorerMerger sm(scor);
151  sm.SetVerbosity(ver);
152  //Debug!
153  auto debugme = [&scor](){
154  for ( size_t idx = 0 ; idx < scor->GetNumberOfMesh() ; ++idx) {
155  const auto m = scor->GetMesh(idx);
156  const auto map = m->GetScoreMap();
157  std::for_each(map.begin(),map.end(),
158  [](const G4VScoringMesh::MeshScoreMap::value_type& e) {
159  G4cout<<e.first<<"("<<e.second<<"):"<<G4endl;
160  const auto data = e.second->GetMap();
161  for( auto it = data->begin() ; it != data->end() ; ++it ) {
162  G4cout<<it->first<<" => G4StatDouble(n,sum_w,sum_w2,sum_wx,sum_wx2): "
163  <<it->second->n()<<" "<<it->second->sum_w()<<" "
164  <<it->second->sum_w2()<<" "<<it->second->sum_wx()<<" "
165  <<it->second->sum_wx2()<<G4endl;
166  }
167  });
168  }
169  };
170  //Debug!
171  if ( ver > 4 ) {
172  G4cout<<"Before merging: Meshes dump"<<G4endl;
173  debugme();
174  }
175  //Write partial scorers from single ranks *before* merging
176  //Do not rely on UI command to write out scorers, because rank-specific
177  //files will have same file name: need to add rank # to file name
178  if ( true ) {
179  for ( size_t idx = 0 ; idx < scor->GetNumberOfMesh() ; ++idx) {
180  const auto m = scor->GetMesh(idx);
181  const auto& mn = m->GetWorldName();
182  std::ostringstream fname;
183  fname<<"scorer-"<<mn<<"-rank"<<rank<<".csv";
184  scor->DumpAllQuantitiesToFile(mn,fname.str());
185  }
186  }
187 
188  //Now reduce all scorers to rank #0
189  sm.Merge();
190 
191  //Debug!
192  if ( ver > 4 ) {
193  G4cout<<"After merging: Meshes dump"<<G4endl;
194  debugme();
195  }
196  //For rank #0 write out the merged files
197  if ( rank == 0 ) {
198  for ( size_t idx = 0 ; idx < scor->GetNumberOfMesh() ; ++idx) {
199  const auto m = scor->GetMesh(idx);
200  const auto& mn = m->GetWorldName();
201  std::ostringstream fname;
202  fname<<"scorer-"<<mn<<"-merged.csv";
203  scor->DumpAllQuantitiesToFile(mn,fname.str());
204  }
205  }
206  }
207 
208  //Save histograms *before* MPI merging for rank #0
209  if (rank == 0)
210  {
211  Analysis* myana = Analysis::GetAnalysis();
212  myana-> Save();
213  myana-> Close(false); // close without resetting histograms
214  }
215  //Merge of g4analysis objects
216  G4cout << "Go to merge histograms " << G4endl;
217  ver=1;
219  hm.SetVerbosity(ver);
220  hm.Merge();
221  G4cout << "Done merge histograms " << G4endl;
222  }
223 
224  //Save g4analysis objects to a file
225  //NB: It is important that the save is done *after* MPI-merging of histograms
226 
227  //One can save all ranks or just rank0, chane the if
228  if (true /*rank == 0*/)
229  // if (rank == 0)
230  {
231  Analysis* myana = Analysis::GetAnalysis();
232  if (rank == 0) {
233  myana->OpenFile("dose-merged");
234  }
235  myana-> Save();
236  myana-> Close();
237  }
238 
239  G4cout << "===================================================" << G4endl;
240  G4cout << "End EndOfRunAction for master thread in rank: " << rank << G4endl;
241  G4cout << "===================================================" << G4endl;
242 }