Geant4 Cross Reference

Cross-Referencing   Geant4
Geant4/examples/extended/parallel/ThreadsafeScorers/src/TSRunAction.cc

Version: [ ReleaseNotes ] [ 1.0 ] [ 1.1 ] [ 2.0 ] [ 3.0 ] [ 3.1 ] [ 3.2 ] [ 4.0 ] [ 4.0.p1 ] [ 4.0.p2 ] [ 4.1 ] [ 4.1.p1 ] [ 5.0 ] [ 5.0.p1 ] [ 5.1 ] [ 5.1.p1 ] [ 5.2 ] [ 5.2.p1 ] [ 5.2.p2 ] [ 6.0 ] [ 6.0.p1 ] [ 6.1 ] [ 6.2 ] [ 6.2.p1 ] [ 6.2.p2 ] [ 7.0 ] [ 7.0.p1 ] [ 7.1 ] [ 7.1.p1 ] [ 8.0 ] [ 8.0.p1 ] [ 8.1 ] [ 8.1.p1 ] [ 8.1.p2 ] [ 8.2 ] [ 8.2.p1 ] [ 8.3 ] [ 8.3.p1 ] [ 8.3.p2 ] [ 9.0 ] [ 9.0.p1 ] [ 9.0.p2 ] [ 9.1 ] [ 9.1.p1 ] [ 9.1.p2 ] [ 9.1.p3 ] [ 9.2 ] [ 9.2.p1 ] [ 9.2.p2 ] [ 9.2.p3 ] [ 9.2.p4 ] [ 9.3 ] [ 9.3.p1 ] [ 9.3.p2 ] [ 9.4 ] [ 9.4.p1 ] [ 9.4.p2 ] [ 9.4.p3 ] [ 9.4.p4 ] [ 9.5 ] [ 9.5.p1 ] [ 9.5.p2 ] [ 9.6 ] [ 9.6.p1 ] [ 9.6.p2 ] [ 9.6.p3 ] [ 9.6.p4 ] [ 10.0 ] [ 10.0.p1 ] [ 10.0.p2 ] [ 10.0.p3 ] [ 10.0.p4 ] [ 10.1 ] [ 10.1.p1 ] [ 10.1.p2 ] [ 10.1.p3 ] [ 10.2 ] [ 10.2.p1 ] [ 10.2.p2 ] [ 10.2.p3 ] [ 10.3 ] [ 10.3.p1 ] [ 10.3.p2 ] [ 10.3.p3 ] [ 10.4 ] [ 10.4.p1 ] [ 10.4.p2 ] [ 10.4.p3 ] [ 10.5 ] [ 10.5.p1 ] [ 10.6 ] [ 10.6.p1 ] [ 10.6.p2 ] [ 10.6.p3 ] [ 10.7 ] [ 10.7.p1 ] [ 10.7.p2 ] [ 10.7.p3 ] [ 10.7.p4 ] [ 11.0 ] [ 11.0.p1 ] [ 11.0.p2 ] [ 11.0.p3, ] [ 11.0.p4 ] [ 11.1 ] [ 11.1.1 ] [ 11.1.2 ] [ 11.1.3 ] [ 11.2 ] [ 11.2.1 ] [ 11.2.2 ] [ 11.3.0 ]

  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 /// \file parallel/ThreadsafeScorers/src/TSRunAction.cc
 27 /// \brief Implementation of the TSRunAction class
 28 //
 29 //
 30 //
 31 //
 32 //
 33 //
 34 //....oooOO0OOooo........oooOO0OOooo........oooOO0OOooo........oooOO0OOooo......
 35 //....oooOO0OOooo........oooOO0OOooo........oooOO0OOooo........oooOO0OOooo......
 36 
 37 #include "TSRunAction.hh"
 38 
 39 #include "TSActionInitialization.hh"
 40 #include "TSDetectorConstruction.hh"
 41 #include "TSRun.hh"
 42 
 43 #include "G4Run.hh"
 44 #include "G4RunManager.hh"
 45 #include "G4StatAnalysis.hh"
 46 #include "G4TaskRunManager.hh"
 47 #include "G4Timer.hh"
 48 
 49 //....oooOO0OOooo........oooOO0OOooo........oooOO0OOooo........oooOO0OOooo......
 50 
 51 TSRunAction::TSRunAction()
 52   : fDetector(TSDetectorConstruction::Instance()), fName(fDetector->GetMFDName())
 53 {}
 54 
 55 //....oooOO0OOooo........oooOO0OOooo........oooOO0OOooo........oooOO0OOooo......
 56 
 57 TSRunAction::~TSRunAction() {}
 58 
 59 //....oooOO0OOooo........oooOO0OOooo........oooOO0OOooo........oooOO0OOooo......
 60 
 61 G4Run* TSRunAction::GenerateRun()
 62 {
 63   return new TSRun(fName);
 64 }
 65 
 66 //....oooOO0OOooo........oooOO0OOooo........oooOO0OOooo........oooOO0OOooo......
 67 
 68 void TSRunAction::BeginOfRunAction(const G4Run* aRun)
 69 {
 70   // G4int evts_to_process = aRun->GetNumberOfEventToBeProcessed();
 71   // G4RunManager::GetRunManager()->SetPrintProgress(
 72   //  (evts_to_process > 1000) ? evts_to_process / 1000 : 1);
 73   if (IsMaster() && aRun != nullptr) G4PrintEnv();
 74 }
 75 
 76 //....oooOO0OOooo........oooOO0OOooo........oooOO0OOooo........oooOO0OOooo......
 77 
 78 void TSRunAction::EndOfRunAction(const G4Run* aRun)
 79 {
 80   if (IsMaster()) {
 81     G4cout << " ###### EndOfTSRunAction ###### " << G4endl;
 82 
 83     aRun->GetNumberOfEvent();
 84     std::ofstream fileout;
 85     G4String fname = "";
 86     std::stringstream separator;
 87 
 88     separator << "============================================================";
 89 
 90     typedef std::set<G4int> IDSet_t;
 91     IDSet_t IDs;
 92 
 93     //- TSRun object.
 94     const TSRun* tsRun = static_cast<const TSRun*>(aRun);
 95     //--- Dump all scored quantities involved in TSRun.
 96 
 97     //---------------------------------------------
 98     // Dump accumulated quantities for this RUN.
 99     //---------------------------------------------
100     std::vector<G4String> primScorerNames{"EnergyDeposit", "NumberOfSteps"};
101     std::vector<G4String> fnames{"mfd_tl", "mfd_tg"};
102     std::vector<G4double> units{CLHEP::eV, CLHEP::keV, 1, 1};
103     std::vector<G4String> unitstr{"keV", "steps"};
104 
105     //----------------------------------------------------------------------//
106     // lambda to print double value
107     auto print = [](std::ostream& fout, G4int first, G4double second, G4double unit1,
108                     G4double unit2, G4String unit2str) {
109       if (fout) fout << first << "     " << second / unit1 << G4endl;
110 
111       G4cout << "    " << std::setw(10) << first << "    " << std::setw(15) << std::setprecision(6)
112              << std::fixed << second / unit2 << " " << unit2str << G4endl;
113       G4cout.unsetf(std::ios::fixed);
114     };
115     //----------------------------------------------------------------------//
116     // lambda to print statistics
117     auto stat_print = [](std::ostream& fout, G4int first, G4StatAnalysis* stat,
118                          G4ConvergenceTester* conv, G4double unit1, G4double unit2,
119                          G4String unit2str) {
120       if (!stat || !conv) return;
121       auto fsecond = (*stat);
122       auto psecond = (*stat);
123       fsecond /= unit1;
124       psecond /= unit2;
125       if (fout) {
126         fout << first << "     " << fsecond << G4endl;
127         conv->ShowResult(fout);
128       }
129       std::stringstream ss;
130       ss << "    " << std::setw(10) << first << "    " << std::setw(15) << std::setprecision(6)
131          << std::fixed << psecond << " " << unit2str;
132       // skip print of ConvergenceTester to stdout
133       G4cout << ss.str() << G4endl;
134     };
135     //----------------------------------------------------------------------//
136 
137     for (unsigned i = 0; i < primScorerNames.size(); ++i) {
138       for (unsigned j = 0; j < fnames.size(); ++j) {
139         fname = fnames.at(j) + "_" + primScorerNames.at(i) + ".out";
140         fileout.open(fname);
141         G4cout << separator.str() << G4endl;
142         G4cout << " opened file " << fname << " for output" << G4endl;
143         G4cout << separator.str() << G4endl;
144 
145         G4bool valid = true;
146         if (j == 0) {
147           G4THitsMap<G4double>* hitmap = tsRun->GetHitsMap(fName + "/" + primScorerNames.at(i));
148           G4StatContainer<G4StatAnalysis>* statmap =
149             tsRun->GetStatMap(fName + "/" + primScorerNames.at(i));
150           G4StatContainer<G4ConvergenceTester>* convmap =
151             tsRun->GetConvMap(fName + "/" + primScorerNames.at(i));
152 
153           if (hitmap && hitmap->size() != 0) {
154             for (auto itr = hitmap->begin(); itr != hitmap->end(); itr++) {
155               if (!hitmap->GetObject(itr)) continue;
156               IDs.insert(itr->first);
157               std::get<0>(fTypeCompare[primScorerNames.at(i)][itr->first]) =
158                 *itr->second / units.at(i);
159               print(fileout, itr->first, *itr->second, units.at(i), units.at(i + 1), unitstr.at(i));
160             }
161           }
162           else {
163             valid = false;
164           }
165 
166           if (statmap && statmap->size() != 0 && convmap && convmap->size() != 0) {
167             auto stat_fname = "stat_" + fname;
168             std::ofstream statout;
169             statout.open(stat_fname);
170             for (auto itr = statmap->begin(); itr != statmap->end(); itr++) {
171               G4int _f = statmap->GetIndex(itr);
172               G4StatAnalysis* _s = statmap->GetObject(itr);
173               G4ConvergenceTester* _c = convmap->GetObject(_f);
174               stat_print(statout, _f, _s, _c, units.at(i), units.at(i + 1), unitstr.at(i));
175             }
176             statout.close();
177           }
178           else {
179             std::stringstream ss;
180             ss << " StatMap/ConvMap is either not "
181                << "created or the StatMap/ConvMap was empty";
182             if (statmap) ss << " (StatMap size == " << statmap->size() << ")";
183             if (convmap) ss << " (ConvMap size == " << convmap->size() << ")";
184 
185             G4Exception("TSRunAction", "002", JustWarning,
186                         G4String(primScorerNames.at(i) + ss.str()).c_str());
187           }
188 
189           if (!valid) {
190             G4Exception("TSRunAction", "000", JustWarning,
191                         G4String(primScorerNames.at(i)
192                                  + " HitsMap is either not "
193                                    "created or the HitsMap was empty")
194                           .c_str());
195           }
196         }
197         else {
198           G4TAtomicHitsMap<G4double>* hitmap =
199             tsRun->GetAtomicHitsMap(fName + "/" + primScorerNames.at(i));
200           if (hitmap && hitmap->size() != 0) {
201             for (auto itr = hitmap->begin(); itr != hitmap->end(); itr++) {
202               IDs.insert(itr->first);
203               std::get<1>(fTypeCompare[primScorerNames.at(i)][itr->first]) =
204                 *itr->second / units.at(i);
205               print(fileout, itr->first, *itr->second, units.at(i), units.at(i + 1), unitstr.at(i));
206             }
207           }
208           else {
209             valid = false;
210           }
211 
212           if (!valid) {
213             G4Exception("TSRunAction", "001", JustWarning,
214                         G4String(primScorerNames.at(i)
215                                  + " HitsMap is either not "
216                                    "created or the HitsMap was empty")
217                           .c_str());
218           }
219         }
220 
221         fileout.close();
222         G4cout << separator.str() << G4endl;
223         G4cout << " closed file " << fname << " for output" << G4endl;
224       }
225       // add the mutex data
226       TSRun::MutexHitsMap_t* hitmap = tsRun->GetMutexHitsMap(fName + "/" + primScorerNames.at(i));
227       if (hitmap && hitmap->size() != 0) {
228         for (auto itr = hitmap->begin(); itr != hitmap->end(); itr++) {
229           IDs.insert(itr->first);
230           std::get<2>(fTypeCompare[primScorerNames.at(i)][itr->first]) = itr->second / units.at(i);
231         }
232       }
233     }
234 
235     //--------------------------------------------------------------------//
236     // Check that the values are equivalent and there are no
237     // IDs in one container that aren't in another
238     //--------------------------------------------------------------------//
239 
240     fname = "mfd_diff.out";
241     fileout.open(fname);
242 
243     G4cout << separator.str() << G4endl;
244     G4cout << " opened file " << fname << " for difference output" << G4endl;
245     G4cout << separator.str() << G4endl;
246 
247     fileout << "    " << std::setw(10) << "ID"
248             << "    " << std::setw(30) << std::setprecision(12) << std::fixed << "MFD value"
249             << "    " << std::setw(30) << std::setprecision(12) << std::fixed
250             << "Atomic Hits Map value"
251             << "    " << std::setw(30) << std::setprecision(8) << std::scientific << "Difference"
252             << "    " << std::setw(30) << std::setprecision(8) << std::scientific
253             << "Diff (MFD - MUTEXED)"
254             << "    " << std::setw(30) << std::setprecision(8) << std::scientific
255             << "Diff (ATOM_HIT_MAP - MUTEXED)" << G4endl << G4endl;
256 
257     //----------------------------------------------------------------------//
258     //
259     //    Example of using tasking in the user-application. Although this
260     //    is sort of trivial case and might not result in any speed-up
261     //    it is a good validation test because the order that strings
262     //    are joined matters. Although the tasks are executed asynchronously
263     //    and may complete at different times, the return values from
264     //    the tasks are stored in futures and are "joined" in the order
265     //    that they were submitted to the task-group
266     //
267     //----------------------------------------------------------------------//
268     // do not directly call G4TaskManager::GetInstance() as this will generate
269     // an instance
270     auto tm = dynamic_cast<G4TaskRunManager*>(G4RunManager::GetRunManager());
271     // Get the thread-pool if available
272     auto tp = (tm) ? tm->GetThreadPool() : nullptr;
273     // write a join algorithm which combines the strings from the tasks
274     auto join_output = [](std::string& lhs, std::string&& rhs) {
275       return (lhs += rhs);
276     };
277 
278     // this is the outer-loop of tasks
279     auto report_type_comparison = [=](const G4String& id, const IDcompare_t& comp) {
280       // the 'report_type_comparison' generates more tasks
281       auto report_subtype_comparison = [](const G4int& idx, const Compare_t& value) {
282         std::stringstream streamout;
283         G4double d01 = std::fabs(std::get<0>(value) - std::get<1>(value));
284         G4double d02 = std::fabs(std::get<0>(value) - std::get<2>(value));
285         G4double d03 = std::fabs(std::get<1>(value) - std::get<2>(value));
286 
287         auto _print_diff = [&](const G4double& _dval) {
288           if (_dval > 0.0)
289             streamout << std::setprecision(8) << std::scientific << std::setw(30) << _dval
290                       << "    ";
291           else
292             streamout << std::setprecision(1) << std::fixed << std::setw(30) << _dval << "    ";
293         };
294 
295         streamout << "    " << std::setw(10) << idx << "    " << std::setw(30)
296                   << std::setprecision(12) << std::fixed << std::get<0>(value) << "    "
297                   << std::setw(30) << std::setprecision(12) << std::fixed << std::get<1>(value)
298                   << "    ";
299 
300         _print_diff(d01);
301         _print_diff(d02);
302         _print_diff(d03);
303 
304         streamout << G4endl;
305         return streamout.str();
306       };
307 
308       std::stringstream streamout;
309       streamout << "\n\nType = " << id << "\n" << G4endl;
310       if (tp) {
311         // create a task group (nested inside the 'report_type_comparison' task)
312         G4TaskGroup<std::string> tg(join_output, tp);
313         // create the tasks in the task-group
314         for (auto titr = comp.begin(); titr != comp.end(); ++titr)
315           tg.exec(report_subtype_comparison, titr->first, titr->second);
316         // wait on the tasks to finish and execute the join function
317         // this will block the outer task from completing until all the inner
318         // tasks have been completed
319         streamout << tg.join();
320       }
321       else {
322         // if there isn't a tasking thread-pool then we make traditional
323         // function call on this thread
324         for (auto titr = comp.begin(); titr != comp.end(); ++titr)
325           streamout << report_subtype_comparison(titr->first, titr->second);
326       }
327       // this is the completion of the outer tasks
328       return streamout.str();
329     };
330 
331     G4String tasking_result = "";
332     if (tp) {
333       G4cout << "\n\nGenerating diff output via tasking... ";
334       // create a task group to
335       G4TaskGroup<std::string> tg(join_output, tp);
336       for (auto itr = fTypeCompare.begin(); itr != fTypeCompare.end(); ++itr)
337         tg.exec(report_type_comparison, itr->first, itr->second);
338       // wait on the tasks to finish and execute the join function
339       tasking_result = tg.join();
340     }
341 
342     // if thread-pool was available, lets validate that tasking did what was
343     // expected
344     if (tp) {
345       // generate the output serially
346       G4String serial_result = "";
347       for (auto itr = fTypeCompare.begin(); itr != fTypeCompare.end(); ++itr)
348         serial_result += report_type_comparison(itr->first, itr->second);
349 
350       // write the tasking result even if it was bad so that it can viewed
351       fileout << tasking_result;
352 
353       // compare the strings -- should be the same
354       if (serial_result != tasking_result) {
355         G4Exception("TSRunAction", "003", JustWarning,
356                     "Output written via tasking did not match output written "
357                     "serially. Appending serial result to output file");
358         fileout << "\n\n#================CORRECT_SERIAL_OUTPUT================#\n\n";
359         fileout << serial_result;
360       }
361     }
362     else {
363       // if thread-pool was not available, then just write serially
364       for (auto itr = fTypeCompare.begin(); itr != fTypeCompare.end(); ++itr)
365         fileout << report_type_comparison(itr->first, itr->second);
366     }
367 
368     fileout.close();
369     G4cout << " closed file " << fname << " for difference output" << G4endl;
370     G4cout << separator.str() << G4endl;
371   }
372 }
373 
374 //....oooOO0OOooo........oooOO0OOooo........oooOO0OOooo........oooOO0OOooo......
375