Geant4 Cross Reference |
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