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

Applications | User Support | Publications | Collaboration