EGSnrc C++ class library  Report PIRS-898 (2021)
Iwan Kawrakow, Ernesto Mainegra-Hing, Frederic Tessier, Reid Townson and Blake Walters
egs_application.cpp
Go to the documentation of this file.
1 /*
2 ###############################################################################
3 #
4 # EGSnrc egs++ application
5 # Copyright (C) 2015 National Research Council Canada
6 #
7 # This file is part of EGSnrc.
8 #
9 # EGSnrc is free software: you can redistribute it and/or modify it under
10 # the terms of the GNU Affero General Public License as published by the
11 # Free Software Foundation, either version 3 of the License, or (at your
12 # option) any later version.
13 #
14 # EGSnrc is distributed in the hope that it will be useful, but WITHOUT ANY
15 # WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS
16 # FOR A PARTICULAR PURPOSE. See the GNU Affero General Public License for
17 # more details.
18 #
19 # You should have received a copy of the GNU Affero General Public License
20 # along with EGSnrc. If not, see <http://www.gnu.org/licenses/>.
21 #
22 ###############################################################################
23 #
24 # Author: Iwan Kawrakow, 2005
25 #
26 # Contributors: Frederic Tessier
27 # Ernesto Mainegra-Hing
28 # Blake Walters
29 # Reid Townson
30 # Hubert Ho
31 # Max Orok
32 # Alexandre Demelo
33 #
34 ###############################################################################
35 */
36 
37 
43 #include "egs_application.h"
44 #include "egs_functions.h"
45 #include "egs_input.h"
46 #include "egs_base_source.h"
47 #include "egs_rndm.h"
48 #include "egs_run_control.h"
49 #include "egs_base_source.h"
50 #include "egs_simple_container.h"
51 #include "egs_ausgab_object.h"
52 #include "egs_base_geometry.h"
53 
54 #include <cstring>
55 #include <cstdio>
56 #include <cstdlib>
57 #include <vector>
58 #include <fstream>
59 #include <sys/types.h>
60 #include <sys/stat.h>
61 #include <unistd.h>
62 
63 using namespace std;
64 
65 #ifdef WIN32
66  const char fs = 92;
67  #define F_OK 0
68  #define W_OK 2
69  #define R_OK 4
70  #include <io.h>
71  #define EGS_ACCESS ::_access
72 #else
73  const char fs = '/';
74  #include <unistd.h>
75  #define EGS_ACCESS ::access
76  #include <sys/statvfs.h>
77 #endif
78 
79 #define MAXIMUM_JOB_NUMBER 8192 // GPSC1: 256 nodes with 16 cores (32 threads)
80 //#define MAXIMUM_JOB_NUMBER 1024
81 
82 static char __egs_app_msg1[] = "EGS_Application::EGS_Application(int,char**):";
83 static char __egs_app_msg2[] = "EGS_Application::initSimulation():";
84 static char __egs_app_msg3[] = "EGS_Application::runSimulation():";
85 
86 static EGS_LOCAL bool __egs_find_pegsfile(const vector<string> &paths,
87  const string &pegs_file, string &abs_pegs_file) {
88  string pfile = pegs_file;
89  if (pfile.find(".pegs4dat") == string::npos) {
90  pfile += ".pegs4dat";
91  }
92  for (unsigned int j=0; j<paths.size(); j++) {
93  string this_pegs =!paths[j].empty() ? egsJoinPath(paths[j],pfile) : pfile;
94  if (!EGS_ACCESS(this_pegs.c_str(),R_OK)) {
95  abs_pegs_file = this_pegs;
96  return true;
97  }
98  }
99  return false;
100 }
101 
102 static EGS_LOCAL EGS_Application *active_egs_application = 0;
103 
104 int EGS_Application::n_apps = 0;
105 
107  return active_egs_application;
108 }
109 
111  active_egs_application = a;
112 };
113 
114 int EGS_Application::userScoring(int iarg, int ir) {
115  if (a_objects) {
116  int early_return = 0;
117  for (int j=0; j<a_objects[iarg].size(); ++j) {
118  int res;
119  if (ir > -1) {
120  res = a_objects[iarg][j]->processEvent((AusgabCall)iarg, ir);
121  }
122  else {
123  res = a_objects[iarg][j]->processEvent((AusgabCall)iarg);
124  }
125  if (res < 0) {
126  return res;
127  }
128  if (res > 0) {
129  early_return = res;
130  }
131  }
132  if (early_return > 0) {
133  return early_return;
134  }
135  }
136  if (ir > -1) {
137  return 0;
138  }
139  else {
140  return ausgab(iarg);
141  }
142 }
143 
144 void EGS_Application::checkEnvironmentVar(int &argc, char **argv,
145  const char *n1, const char *n2, const char *env, string &var) {
146  char *aux = getenv(env);
147  if (aux) {
148  var = aux;
149  }
150  else {
151  var = "";
152  }
153  getArgument(argc,argv,n1,n2,var);
154  if (!var.size()) egsFatal("%s\n the environment variable %s is not set"
155  " and it was not passed as argument\n",__egs_app_msg1,env);
156  int n = var.size()-1;
157  if (var[n] != '/' && var[n] != fs) {
158  var += fs;
159  }
160 }
161 
162 class EGS_LOCAL EGS_GeometryHistory {
163 public:
164  struct Step {
165  EGS_Vector x, u;
166  EGS_Float twant, t;
167  int ireg, inew;
168  Step() {};
169  Step(int Ireg, int Inew, const EGS_Vector &X, const EGS_Vector &U,
170  EGS_Float Twant, EGS_Float T) : x(X), u(U), twant(Twant), t(T),
171  ireg(Ireg), inew(Inew) {};
172  void show() const {
173  egsWarning("old region=%d, position=(%g,%g,%g), "
174  "direction=(%g,%g,%g) intended step=%g, new region=%d, "
175  "step=%g\n",ireg,x.x,x.y,x.z,u.x,u.y,u.z,twant,inew,t);
176  };
177  };
178 
179  EGS_GeometryHistory(int N=2) : steps(new Step [N]), nsize(N), ns(0),
180  wrap(false) {};
182  delete [] steps;
183  };
184  void addStep(int ireg, int inew, const EGS_Vector &x,
185  const EGS_Vector &u, EGS_Float twant, EGS_Float t) {
186  steps[ns++] = Step(ireg,inew,x,u,twant,t);
187  if (ns >= nsize) {
188  ns = 0;
189  wrap = true;
190  }
191  };
192  void reportHistory() const {
193  int nhave = wrap ? nsize : ns;
194  egsWarning("\n************** Last %d geometry steps:\n",nhave);
195  if (wrap) {
196  for (int j=ns; j<nsize; j++) {
197  steps[j].show();
198  }
199  }
200  for (int j=0; j<ns; j++) {
201  steps[j].show();
202  }
203  };
204 
205  Step *steps;
206  int nsize;
207  int ns;
208  bool wrap;
209 };
210 
211 void EGS_Application::reportGeometryError() {
212  ghistory->reportHistory();
213 
214  // check if we are over the tolerated limit for geometry errors
215  run->geomErrorCount++;
216  if (run->geomErrorCount > run->geomErrorMax) {
217  egsFatal("\n\n******** Encountered %d geometry errors (maximum allowed is %d). \n \
218  You can change this limit with the 'geometry error limit' run control input key. \n \
219  Quitting now.\n", run->geomErrorCount, run->geomErrorMax);
220  }
221 }
222 
223 void EGS_Application::storeGeometryStep(int ireg, int inew,
224  const EGS_Vector &x, const EGS_Vector &u, EGS_Float twant, EGS_Float t) {
225  ghistory->addStep(ireg,inew,x,u,twant,t);
226 }
227 
228 EGS_Application::EGS_Application(int argc, char **argv) : input(0), geometry(0),
229  source(0), rndm(0), run(0), simple_run(false), uniform_run(false), current_case(0),
230  last_case(0), data_out(0), data_in(0), a_objects(0),
231  ghistory(new EGS_GeometryHistory) {
232 
233  app_index = n_apps++;
234 
235  if (!active_egs_application) {
236  active_egs_application = this;
237  }
238  {
239  for (int call=BeforeTransport; call<AfterTransport; call++) {
240  ausgab_flag[call] = true;
241  }
242  }
243  {
244  for (int call=AfterTransport; call<UnknownCall; call++) {
245  ausgab_flag[call] = false;
246  }
247  }
248 
249  //
250  // *** get the name of this application
251  //
252  if (!getArgument(argc,argv,"-a","--application",app_name)) {
253  app_name = egsStripPath(argv[0]);
254 
255  // In Windows PowerShell, we need to remove a .exe extension
256  size_t exePos = app_name.rfind(".exe");
257  if (exePos != string::npos) {
258  app_name = app_name.substr(0, exePos);
259  }
260  }
261  if (!app_name.size()) egsFatal("%s\n failed to determine application "
262  "name from %s or command line arguments\n",__egs_app_msg1,argv[0]);
263  //
264  // *** make sure EGS_HOME is set.
265  //
266  checkEnvironmentVar(argc,argv,"-e","--egs-home","EGS_HOME",egs_home);
268  //
269  // *** make sure HEN_HOUSE is set.
270  //
271  checkEnvironmentVar(argc,argv,"-H","--hen-house","HEN_HOUSE",hen_house);
272  //
273  // *** check if there is an input file specified on the command line
274  //
275  getArgument(argc,argv,"-i","--input",input_file);
276  //egsFatal("%s\n no input file specified\n",__egs_app_msg1);
277  //
278  // *** create the name of the working directory
279  //
280  char buf[512];
281  sprintf(buf,"egsrun_%d_",egsGetPid());
282  run_dir = buf;
283  if (input_file.size() > 0) {
284 
285  // Remove the .egsinp extension if it was included
286  size_t ext = input_file.rfind(".egsinp");
287  if (ext != std::string::npos) {
288  input_file = input_file.substr(0,ext);
289  }
290 
291  run_dir += input_file;
292  run_dir += '_';
293  }
294  else {
295  run_dir += "_noinput_";
296  }
297  run_dir += egsHostName();
298 
299  //
300  // *** check if there is a PEGS file specified on the command line
301  //
302  is_pegsless= false;
303  if (!getArgument(argc,argv,"-p","--pegs-file",pegs_file)) {
304  is_pegsless= true;
305  }
306  //gsFatal("%s\n no PEGS file specified\n",__egs_app_msg1);
307 
308  //
309  // *** check if the pegs file exists.
310  //
311  if (pegs_file.size() > 0) {
312  string pdirs = egsJoinPath("pegs4","data");
313  vector<string> pegs_paths;
314  pegs_paths.push_back("");
315  pegs_paths.push_back(egsJoinPath(egs_home,pdirs));
316  pegs_paths.push_back(egsJoinPath(hen_house,pdirs));
317  if (!__egs_find_pegsfile(pegs_paths,pegs_file,abs_pegs_file))
318  egsFatal("%s\n the pegs file %s does not exist or is not "
319  "readable\n",__egs_app_msg1,pegs_file.c_str());
320  }
321 
322  //
323  // *** check if the input file exists.
324  //
325  string ifile;
326  if (input_file.size() > 0) {
327  ifile = egsJoinPath(app_dir,input_file);
328  if (ifile.find(".egsinp") == string::npos) {
329  ifile += ".egsinp";
330  }
331  if (EGS_ACCESS(ifile.c_str(),R_OK))
332  egsFatal("%s\n the input file %s does not exist or is not "
333  "readable\n",__egs_app_msg1,ifile.c_str());
334  }
335 
336  //
337  // *** set the output file
338  //
339  if (!getArgument(argc,argv,"-o","--output",output_file)) {
341  }
342  if (!output_file.size()) {
343  output_file = "test";
344  }
345  //
346  // *** see if a batch run.
347  //
348  batch_run = false;
349  for (int j=1; j<argc; j++) {
350  string tmp = argv[j];
351  if (tmp == "-b" || tmp == "--batch") {
352  batch_run = true;
353  //for(int i=j; i<argc-1; i++) argv[i] = argv[i+1];
354  //argc--;
355  break;
356  }
357  }
358  //
359  // *** see if parallel run.
360  //
361  string npar, ipar, ifirst;
362  n_parallel = i_parallel = 0;
363  first_parallel = 1;
364  bool have_np = getArgument(argc,argv,"-P","--parallel",npar);
365  bool have_ip = getArgument(argc,argv,"-j","--job",ipar);
366  bool have_first = getArgument(argc,argv,"-f","--first-job",ifirst);
367  if (have_np && have_ip) {
368  n_parallel = ::strtol(npar.c_str(),0,10);
369  i_parallel = ::strtol(ipar.c_str(),0,10);
370  if (have_first) {
371  first_parallel = ::strtol(ifirst.c_str(),0,10);
372  if (first_parallel < 0) {
373  egsWarning("%s\n invalid -f argument %d\n",__egs_app_msg1,
374  n_parallel);
375  n_parallel = 0;
376  i_parallel = 0;
377  }
378  }
379  if (n_parallel < 0) {
380  egsWarning("%s\n invalid -P argument %d\n",__egs_app_msg1,
381  n_parallel);
382  n_parallel = 0;
383  }
384  if (i_parallel < 0) {
385  egsWarning("%s\n invalid -j argument %d\n",__egs_app_msg1,
386  i_parallel);
387  i_parallel = 0;
388  n_parallel = 0;
389  }
390  if (i_parallel > n_parallel + first_parallel -1) {
391  egsWarning("%s\n job number (%d) can not be larger than number"
392  " of parallel jobs(%d). Turning off parallel option\n",
393  __egs_app_msg1,i_parallel,n_parallel+ first_parallel -1);
394  n_parallel = 0;
395  i_parallel = 0;
396  }
397  }
398  else if (have_np && !have_ip) { // user wants to reset n_parallel
399  // and combine parallel jobs
400  n_parallel = ::strtol(npar.c_str(),0,10);
401  simple_run = true;
402  }
403  else if (n_parallel && !have_ip) { // user wants to combine
404  // parallel jobs
405  simple_run = true;
406  }
407  else if (!have_np && have_ip) {
408  egsWarning("\n%s\n to specify a parallel run you need both,"
409  " the -P and -j command line options\n\n",__egs_app_msg1);
410  }
411 
412  //
413  // *** see if user wants simple job control
414  //
415  for (int j=1; j<argc; j++) {
416  string tmp = argv[j];
417  if (tmp == "-s" || tmp == "--simple-run") {
418  simple_run = true;
419  //for(int i=j; i<argc-1; i++) argv[i] = argv[i+1];
420  //argc--;
421  break;
422  }
423  }
424 
425  //
426  // *** See if user wants uniform job control.
427  // (Takes precedence over simple job control)
428  //
429  for (int j=1; j<argc; j++) {
430  string tmp = argv[j];
431  if (tmp == "-u" || tmp == "--urc") {
432  uniform_run = true;
433  simple_run = false;
434  break;
435  }
436  }
437 
439  if (i_parallel > 0 && n_parallel > 0) {
440  batch_run = true;
441  char buf[1024];
442  sprintf(buf,"%s_w%d",output_file.c_str(),i_parallel);
443  output_file = buf;
444  }
445 
446  //
447  // *** read the input
448  //
449  input = new EGS_Input;
450  if (ifile.size() > 0) {
451  if (input->setContentFromFile(ifile.c_str()))
452  egsFatal("%s\n error while reading input file %s\n",
453  __egs_app_msg1,ifile.c_str());
454  }
455 
456 }
457 
458 bool EGS_Application::getArgument(int &argc, char **argv,
459  const char *name1, const char *name2, string &arg) {
460  string n1(name1), n2(name2);
461  for (int j=1; j<argc-1; j++) {
462  if (n1 == argv[j] || n2 == argv[j]) {
463  arg = argv[j+1];
464  //for(int i=j; i<argc-2; i++) argv[i] = argv[i+2];
465  //argc -= 2;
466  return true;
467  }
468  }
469  return false;
470 }
471 
472 string EGS_Application::constructIOFileName(const char *extension,
473  bool with_run_dir) const {
474  string iofile = with_run_dir ? egsJoinPath(app_dir,run_dir) : app_dir;
475  iofile = egsJoinPath(iofile,output_file);
476  if (extension) {
477  iofile += extension;
478  }
479  return iofile;
480 }
481 
483 
484  if (data_out) {
485  delete data_out;
486  }
487  string ofile = constructIOFileName(".egsdat",true);
488  /*
489  string ofile = egsJoinPath(app_dir,run_dir);
490  ofile = egsJoinPath(ofile,output_file);
491  ofile += ".egsdat";
492  */
493  data_out = new ofstream(ofile.c_str());
494  if (!(*data_out)) {
495  egsWarning("EGS_Application::outputData: failed to open %s "
496  "for writing\n",ofile.c_str());
497  return 1;
498  }
499  if (!run->storeState(*data_out)) {
500  return 2;
501  }
503  return 3;
504  }
505  (*data_out) << endl;
506  if (!rndm->storeState(*data_out)) {
507  return 4;
508  }
509  if (!source->storeState(*data_out)) {
510  return 5;
511  }
512  for (int j=0; j<a_objects_list.size(); ++j) {
513  if (!a_objects_list[j]->storeState(*data_out)) {
514  return 6;
515  }
516  }
517  return 0;
518 }
519 
521  if (data_in) {
522  delete data_in;
523  }
524  string ifile = constructIOFileName(".egsdat",false);
525  /*
526  string ifile = egsJoinPath(app_dir,output_file);
527  ifile += ".egsdat";
528  */
529  data_in = new ifstream(ifile.c_str());
530  if (!(*data_in)) {
531  egsWarning("EGS_Application::readData: failed to open %s "
532  "for reading\n",ifile.c_str());
533  return 1;
534  }
535  if (!run->setState(*data_in)) {
536  return 2;
537  }
538  if (!egsGetI64(*data_in,current_case)) {
539  return 3;
540  }
542  if (!rndm->setState(*data_in)) {
543  return 4;
544  }
545  if (!source->setState(*data_in)) {
546  return 5;
547  }
548  for (int j=0; j<a_objects_list.size(); ++j) {
549  if (!a_objects_list[j]->setState(*data_in)) {
550  return 6;
551  }
552  }
553  return 0;
554 }
555 
557  last_case = 0;
558  current_case = 0;
559  run->resetCounter();
560  rndm->resetCounter();
561  source->resetCounter();
562  for (int j=0; j<a_objects_list.size(); ++j) {
563  a_objects_list[j]->resetCounter();
564  }
565 
566 }
567 
568 int EGS_Application::addState(istream &data) {
569  if (!run->addState(data)) {
570  return 1;
571  }
572  EGS_I64 tmp_case;
573  if (!egsGetI64(data,tmp_case)) {
574  return 2;
575  }
576  current_case += tmp_case;
578  if (!rndm->addState(data)) {
579  return 3;
580  }
581  if (!source->addState(data)) {
582  return 4;
583  }
584  for (int j=0; j<a_objects_list.size(); ++j)
585  if (!a_objects_list[j]->addState(data)) {
586  return 5;
587  }
588  return 0;
589 }
590 
591 bool fileExists(const string &name) {
592  struct stat buffer;
593  return (stat(name.c_str(), &buffer) == 0);
594 }
595 
597 
598  char buf[512];
599  int n_of_egsdat = 0;
600 
601  for (int i = first_parallel; i < first_parallel + n_parallel; i++) {
602  sprintf(buf,"%s_w%d.egsdat",final_output_file.c_str(),i);
603  string dfile = egsJoinPath(app_dir,buf);
604  if (fileExists(dfile)) {
605  n_of_egsdat++;
606  }
607  }
608 
609  return n_of_egsdat;
610 }
611 
613  int err = combineResults();
614  if (err) {
615  return err;
616  }
617  for (int j=0; j<a_objects_list.size(); ++j) {
618  a_objects_list[j]->reportResults();
619  }
620  outputResults();
621  return 0;
622 }
623 
626  "\n Suming the following .egsdat files:\n"
627  "=======================================================================\n");
628  char buf[512];
629  resetCounter();
630  EGS_Float last_cpu = 0;
631  EGS_I64 last_ncase = 0;
632  int ndat = 0;
633  bool ok = true;
634  /*
635  If trying to combine results and n_parallel set to 0,
636  use a hard-coded value for number of jobs.This is possible
637  if -P njobs was not passed as argument.
638  */
639  if (!n_parallel) {
640  n_parallel = MAXIMUM_JOB_NUMBER;
641  }
642  for (int j=first_parallel; j < first_parallel + n_parallel; j++) {
643  sprintf(buf,"%s_w%d.egsdat",final_output_file.c_str(),j);
644  string dfile = egsJoinPath(app_dir,buf);
645  ifstream data(dfile.c_str());
646  if (data) {
647  int err = addState(data);
648  ++ndat;
649  if (!err) {
650  EGS_I64 ncase = run->getNdone();
651  EGS_Float cpu = run->getCPUTime();
652  egsInformation("%2d %-30s ncase=%-14lld cpu=%-11.2f\n",
653  ndat,buf,ncase-last_ncase,cpu-last_cpu);
654  last_ncase = ncase;
655  last_cpu = cpu;
656  }
657  else {
658  ok = false;
659  egsWarning("%2d %-30s error %d\n",ndat,buf,err);
660  }
661  }
662  }
663  if (ndat > 0) {
665  "=======================================================================\n");
666  egsInformation("%40s%-14lld cpu=%-11.2f\n\n","Total ncase=",last_ncase,
667  last_cpu);
668  }
669  if (ndat > 0) {
670  return ok ? 0 : -1;
671  }
672  else {
673  return 1;
674  }
675 }
676 
678  if (!rndm) {
679  return 0;
680  }
681  return rndm->numbersUsed();
682 }
683 
685  if (!input) {
686  return -1;
687  }
688  //if( geometry ) { delete geometry; geometry = 0; }
691  if (!geometry) {
692  return 1;
693  }
694  geometry->ref();
695  geometry->setApplication(this);
696  return 0;
697 }
698 
700  if (!input) {
701  return -1;
702  }
703  //if( source ) { delete source; source = 0; }
705  if (!source) {
706  return 1;
707  }
708  source->ref();
709  return 0;
710 }
711 
713  if (run) {
714  delete run;
715  }
716  if (simple_run) {
717  run = new EGS_RunControl(this);
718  }
719  else if (uniform_run) {
720  run = new EGS_UniformRunControl(this);
721  }
722  else {
723  run = EGS_RunControl::getRunControlObject(this);
724  }
725  if (!run) {
726  return 1;
727  }
728  return 0;
729 }
730 
732  if (rndm) {
733  delete rndm;
734  }
735  int sequence = 0;
736  if (n_parallel > 0 && i_parallel > 0) {
737  sequence = i_parallel - 1;
738  }
739  if (input) {
741  }
742  if (!rndm) {
743  egsWarning("EGS_Application::initRNG(): using default RNG\n");
745  }
746  if (!rndm) {
747  egsWarning("EGS_Application::initRNG(): got null RNG?\n");
748  return 1;
749  }
750  return 0;
751 }
752 
754  //if( !input ) { egsWarning("%s no input\n",__egs_app_msg2); return -1; }
755  egsInformation("In EGS_Application::initSimulation()\n");
756  int err;
757  bool ok = true;
758  err = initGeometry();
759  if (err) {
760  egsWarning("\n\n%s geometry initialization failed\n",__egs_app_msg2);
761  ok = false;
762  }
763  err = initSource();
764  if (err) {
765  egsWarning("\n\n%s source initialization failed\n",__egs_app_msg2);
766  ok = false;
767  }
768  err = initRNG();
769  if (err) {
770  egsWarning("\n\n%s RNG initialization failed\n",__egs_app_msg2);
771  ok = false;
772  }
773  err = initRunControl();
774  if (err) {
775  egsWarning("\n\n%s run control initialization failed\n",__egs_app_msg2);
776  ok = false;
777  }
778  if (!ok) {
779  return 1;
780  }
781  err = initEGSnrcBackEnd();
782  if (err) {
783  egsWarning("\n\n%s back-end initialization failed\n",__egs_app_msg2);
784  return 2;
785  }
787  err = initCrossSections();
788  if (err) {
789  egsWarning("\n\n%s cross section initialization failed\n",__egs_app_msg2);
790  return 3;
791  }
792  err = initScoring();
793  if (err) {
794  egsWarning("\n\n%s scoring initialization failed with status %d\n",
795  __egs_app_msg2,err);
796  return 4;
797  }
799  //describeSimulation();
800 
801  return 0;
802 }
803 
804 void EGS_Application::setSimulationChunk(EGS_I64 nstart, EGS_I64 nrun, int npar, int nchunk) {
805  if (source) {
806  source->setSimulationChunk(nstart,nrun,npar,nchunk);
807  }
808 }
809 
811  if (!geometry && !source) {
812  return;
813  }
814  egsInformation("\n\n");
815  if (geometry) {
816  geometry->printInfo();
817  }
818  if (source) egsInformation("\n\nThe simulation uses the following source:"
819  "\n========================================="
820  "\n %s\n\n\n",source->getSourceDescription());
821  if (rndm) {
822  rndm->describeRNG();
823  egsInformation("\n\n");
824  }
825  if (run) {
826  run->describeRCO();
827  egsInformation("\n\n");
828  }
829  if (a_objects_list.size() > 0) {
830  egsInformation("The following ausgab objects are included in the simulation\n");
831  egsInformation("===========================================================\n\n");
832  for (int j=0; j<a_objects_list.size(); ++j) {
833  egsInformation("%s",a_objects_list[j]->getObjectDescription());
834  }
835  egsInformation("\n\n");
836  }
837 }
838 
840  bool ok = true;
841  if (!geometry) {
842  egsWarning("%s no geometry\n",__egs_app_msg3);
843  ok = false;
844  }
845  if (!source) {
846  egsWarning("%s no source\n",__egs_app_msg3);
847  ok = false;
848  }
849  if (!rndm) {
850  egsWarning("%s no RNG\n",__egs_app_msg3);
851  ok = false;
852  }
853  if (!run) {
854  egsWarning("%s no run control object\n",__egs_app_msg3);
855  ok = false;
856  }
857  if (!ok) {
858  return 1;
859  }
860 
861  int start_status = run->startSimulation();
862  if (start_status) {
863  if (start_status < 0) {
864  egsWarning("\n%s failed to start the simulation\n\n",__egs_app_msg3);
865  }
866  return start_status;
867  }
868 
869  EGS_I64 ncase;
870  bool next_chunk = true;
871 
872  while (next_chunk && (ncase = run->getNextChunk()) > 0) {
873 
874  egsInformation("\nRunning %lld histories\n",ncase);
875  double f,df;
876  if (run->getCombinedResult(f,df)) {
877  char c = '%';
878  egsInformation(" combined result from this and other parallel"
879  " runs: %lg +/- %7.3lf%c\n\n",f,df,c);
880  }
881  else {
882  egsInformation("\n");
883  }
884  int nbatch = run->getNbatch();
885  EGS_I64 ncase_per_batch = ncase/nbatch;
886  if (!ncase_per_batch) {
887  ncase_per_batch = 1;
888  nbatch = ncase;
889  }
890  for (int ibatch=0; ibatch<nbatch; ibatch++) {
891  if (!run->startBatch(ibatch,ncase_per_batch)) {
892  egsInformation(" startBatch() loop termination\n");
893  next_chunk = false;
894  break;
895  }
896  for (EGS_I64 icase=0; icase<ncase_per_batch; icase++) {
897  if (simulateSingleShower()) {
898  egsInformation(" simulateSingleShower() "
899  "loop termination\n");
900  next_chunk = false;
901  break;
902  }
903  }
904  if (!next_chunk) {
905  break;
906  }
907  if (!run->finishBatch()) {
908  egsInformation(" finishBatch() loop termination\n");
909  next_chunk = false;
910  break;
911  }
912  }
913  }
914  // call this from within finishSimulation()
915  //run->finishSimulation();
916  return 0;
917 }
918 
920  int ireg;
921  int ntry = 0;
923  do {
924  ntry++;
925  if (ntry > 100000) {
926  egsWarning("EGS_Application::simulateSingleShower(): no particle"
927  " from the source has entered the geometry after 100000"
928  " attempts\n");
929  return 1;
930  }
931  setTimeIndex(-1);
932  current_case =
934 
935  // For dynamic geometries, update positions according to the current
936  // time index, which may have been set by getNextParticle
937  geometry->getNextGeom(rndm);
938 
939  ireg = geometry->isWhere(p.x);
940  if (ireg < 0) {
941  EGS_Float t = veryFar;
942  ireg = geometry->howfar(ireg,p.x,p.u,t);
943  if (ireg >= 0) {
944  p.x += p.u*t;
945  }
946  }
947  }
948  while (ireg < 0);
949  p.ir = ireg;
950  int err = startNewShower();
951  if (err) {
952  return err;
953  }
954  err = shower();
955  if (err) {
956  return err;
957  }
958  return finishShower();
959 }
960 
962  if (current_case != last_case) {
963  for (int j=0; j<a_objects_list.size(); ++j) {
964  a_objects_list[j]->setCurrentCase(current_case);
965  }
966  }
967  return 0;
968 }
969 
971  if (rndm) {
972  delete rndm;
973  }
974  if (run) {
975  delete run;
976  }
977  if (input) {
978  delete input;
979  }
981  if (geometry) {
982  if (!geometry->deref()) {
983  EGS_Application *app = active_egs_application;
984  active_egs_application = this;
986  delete geometry;
987  active_egs_application = app;
988  }
989  }
990  /*
991  if( a_objects ) {
992  for(int j=(int)BeforeTransport; j<=(int)AugerEvent; ++j) {
993  while( a_objects[j].size() ) EGS_Object::deleteObject(a_objects[j].pop());
994  }
995  delete [] a_objects;
996  }
997  */
998  if (a_objects) {
999  delete [] a_objects;
1000  }
1001  if (ghistory) {
1002  delete ghistory;
1003  }
1004  if (active_egs_application == this) {
1005  active_egs_application = 0;
1006  }
1007 }
1008 
1010  if (!o) {
1011  return;
1012  }
1013  // only one track scoring object is allowed, otherwise there can be bugs
1014  // if both objects try and write to the same file.
1015  if (o->getObjectType() == "EGS_TrackScoring") {
1016  for (int j=0; j<a_objects_list.size(); ++j) {
1017  if (a_objects_list[j]->getObjectType() == "EGS_TrackScoring") {
1018  egsFatal("error: only one ausgab object of type "
1019  "'EGS_TrackScoring' is allowed\n");
1020  }
1021  }
1022  }
1023  o->setApplication(this);
1024  a_objects_list.add(o);
1025  //int ncall = 1 + (int)AugerEvent;
1026  int ncall = (int)UnknownCall;
1027  if (!a_objects) {
1029  }
1030  for (int call=(int)BeforeTransport; call<ncall; ++call) {
1031  if (o->needsCall((AusgabCall)call)) {
1032  a_objects[call].add(o);
1033  setAusgabCall((AusgabCall)call,true);
1034  }
1035  }
1036 }
1037 
1039  if (!input) {
1040  return;
1041  }
1043  for (int i=0; i<EGS_AusgabObject::nObjects(); ++i) {
1045  }
1046 }
1047 
1049  //I don't think we need a separate analyzeResults function.
1050  //analyzeResults();
1051  int err = 0;
1052  if (run) {
1053  err = run->finishSimulation();
1054  if (err < 0) {
1055  return err;
1056  }
1057  }
1058 
1059  outputResults();
1060  for (int j=0; j<a_objects_list.size(); ++j) {
1061  a_objects_list[j]->reportResults();
1062  }
1063 
1064  if (data_out) {
1065  delete data_out;
1066  data_out = 0;
1067  /*
1068  #ifdef WIN32
1069  string dfile = egsJoinPath(app_dir,run_dir);
1070  dfile = egsJoinPath(dfile,output_file);
1071  dfile += ".egsdat";
1072  string command = "move /Y ";
1073  command += dfile; command += " "; command += app_dir;
1074  egsInformation("About to execute <%s>\n",command.c_str());
1075  int istat = system(command.c_str());
1076  if( istat ) egsWarning("Failed to move the .egsdat file from the"
1077  " working directory\n");
1078  #endif
1079  */
1080  }
1081  finishRun();
1082  run_dir = ""; // i.e. from now on all output will go to the user code
1083  // directory.
1084  return err;
1085 }
1086 
1087 void EGS_Application::fillRandomArray(int n, EGS_Float *rarray) {
1088  rndm->fillArray(n,rarray);
1089 }
1090 
1092 #ifndef WIN32
1093  // quit if space left on disk is less than 1 MB to mitigate disk full problems
1094 
1095  // stat the stream
1096  struct stat tmp;
1097  fstat(fileno(stream), &tmp);
1098 
1099  // check only if the stream is a regular file
1100  if (S_ISREG(tmp.st_mode)) {
1101  struct statvfs fstats;
1102  fstatvfs(fileno(stdout), &fstats);
1103  if (fstats.f_bavail*fstats.f_bsize < 1048576) {
1104  egsFatal("\n\n******** Space left on file system is below 1 MB. Quitting now.\n");
1105  exit(1);
1106  }
1107  }
1108 #endif
1109 }
1110 
1111 void EGS_Application::appInformation(const char *msg) {
1112  if (msg) {
1113  fprintf(stdout,"%s",msg);
1114  fflush(stdout);
1115  checkDeviceFull(stdout);
1116  }
1117 }
1118 
1119 void EGS_Application::appWarning(const char *msg) {
1120  if (msg) {
1121  fprintf(stderr,"%s",msg);
1122  fflush(stderr);
1123  checkDeviceFull(stderr);
1124  }
1125 }
1126 
1127 void EGS_Application::appFatal(const char *msg) {
1128  if (msg) {
1129  fprintf(stderr,"%s",msg);
1130  fflush(stderr);
1131  }
1132  exit(1);
1133 }
Base class for advanced EGSnrc C++ applications.
static bool getArgument(int &argc, char **argv, const char *name1, const char *name2, string &arg)
Finds a command line argument.
string app_dir
The user code directory.
virtual EGS_I64 randomNumbersUsed() const
Returns the number of random numbers used.
static EGS_Application * activeApplication()
Get the active application.
bool uniform_run
Use a uniform run control object for parallel runs.
string run_dir
The working directory during the run.
bool simple_run
Use a simple run control object for parallel runs.
EGS_RandomGenerator * rndm
the random number generator
bool is_pegsless
set to true if a pegsless run
int n_parallel
Number of parallel jobs.
virtual void resetCounter()
Reset the application to a 'pristine' state.
virtual int startNewShower()
Called just before the shower() function.
EGS_Application(int argc, char **argv)
Construct an EGSnrc application.
EGS_SimpleContainer< EGS_AusgabObject * > a_objects_list
The ausgab objects.
string input_file
The input file name.
string output_file
The output file name (no extension)
virtual void setAusgabCall(AusgabCall call, bool on_or_off)
Turns on or off a call to the user scoring function ausgab.
virtual void describeSimulation()
Describe the simulation.
EGS_I64 last_case
The last case simulated.
virtual int addState(istream &data)
Add data from a parallel job.
virtual int finishSimulation()
Analyze and output the results.
static void setActiveApplication(EGS_Application *)
Set the active EGS_Application class.
virtual int initRunControl()
Construct the run control object.
virtual void appFatal(const char *)
Write a warning message and exit.
string pegs_file
The pegs file name.
virtual int outputData()
Output intermediate results.
virtual int initScoring()
Initialize the scoring of quantities of interest.
virtual int initSimulation()
Initializes the EGSnrc application.
EGS_Input * input
the input to this simulation.
string app_name
The application name.
virtual void outputResults()
Output the simulation results.
virtual ~EGS_Application()
Destruct the EGSnrc application.
void initAusgabObjects()
Initialize ausgab objects.
string final_output_file
The final output file name.
void addAusgabObject(EGS_AusgabObject *o)
Adds an ausgab object to the list of ausgab objects.
EGS_BaseGeometry * geometry
the geometry of this simulation
AusgabCall
Possible calls to the user scoring function ausgab().
@ BeforeTransport
before the step
@ UnknownCall
last element in the enumeration
@ AfterTransport
after the step
bool ausgab_flag[UnknownCall]
on/off flags for ausgab calls
EGS_I64 current_case
The current case as returned from the source.
virtual int initGeometry()
Initialize the simulation geometry.
virtual int initRNG()
Initialize the random number generator.
bool batch_run
Interactive or batch run.
int i_parallel
Job index in parallel runs.
istream * data_in
data input stream
string egs_home
The EGS_HOME directory.
int first_parallel
first parallel job number
int app_index
the index of this application.
virtual int initCrossSections()
Initialize the EGSnrc cross sections and cross section/transport options.
int howManyJobsDone()
Counts how many *.egsdat files in app folder.
virtual void appInformation(const char *)
Write an information message.
virtual void setSimulationChunk(EGS_I64 nstart, EGS_I64 nrun, int npar, int nchunk)
Set the simulation chunk.
virtual void describeUserCode() const
Describe the user code.
string abs_pegs_file
The pegs file name including absolute path.
virtual int finishShower()
Called just after the shower() function.
int userScoring(int iarg, int ir=-1)
User scoring function for accumulation of results and VRT implementation.
virtual int simulateSingleShower()
Simulates a single particle shower.
ostream * data_out
data output stream
virtual void appWarning(const char *)
Write a warning message.
virtual int initSource()
Initialize the particle source.
EGS_RunControl * run
the run control object.
EGS_SimpleContainer< EGS_AusgabObject * > * a_objects
The ausgab objects for the various ausgab calls.
virtual int combineResults()
Combine results from parallel runs.
static void checkEnvironmentVar(int &argc, char **argv, const char *env, const char *n1, const char *n2, string &var)
Finds a command line argument.
string constructIOFileName(const char *extension, bool with_run_dir) const
Constructs and returns the name of an input/output file.
virtual void fillRandomArray(int n, EGS_Float *rns)
Fill an array with random numbers using the application's RNG.
string hen_house
The HEN_HOUSE directory.
virtual int runSimulation()
Runs an EGSnrc simulation.
virtual int initEGSnrcBackEnd()
Initialize the EGSnrc backend.
void checkDeviceFull(FILE *)
Check if a device holding a given stream is full.
void setTimeIndex(EGS_Float temp_time)
EGS_BaseSource * source
the particle source
virtual int combinePartialResults()
Combine intermediate results from parallel runs.
virtual int shower()
Simulate a single shower.
virtual int readData()
Read intermediate results.
virtual void setApplication(EGS_Application *App)
Set the application this object belongs to.
static EGS_AusgabObject * getObject(int j)
Returns the j'th ausgab object in the internal list.
static void createAusgabObjects(EGS_Input *)
Create ausgab objects from the information pointed to by input.
static int nObjects()
Returns the number of ausgab objects in the internal list.
virtual bool needsCall(EGS_Application::AusgabCall iarg) const
Is the ausgab call iarg relevant for this object?
int deref()
Decrease the reference count to this geometry.
virtual int howfar(int ireg, const EGS_Vector &x, const EGS_Vector &u, EGS_Float &t, int *newmed=0, EGS_Vector *normal=0)=0
Calculate the distance to a boundary from x along the direction u.
static void setActiveGeometryList(int list)
Set the currently active geometry list.
static EGS_BaseGeometry * createGeometry(EGS_Input *)
Create a geometry (or geometries) from a given input.
virtual void printInfo() const
Print information about this geometry.
int ref()
Increase the reference count to this geometry.
virtual int isWhere(const EGS_Vector &x)=0
In which region is poisition x?
virtual bool addState(istream &data_in)
Add data from the stream data_in to the source state.
const char * getSourceDescription() const
Get a short description of this source.
virtual void resetCounter()
Reset the source state.
virtual EGS_I64 getNextParticle(EGS_RandomGenerator *rndm, int &q, int &latch, EGS_Float &E, EGS_Float &wt, EGS_Vector &x, EGS_Vector &u)=0
Sample the next source particle from the source probability distribution.
static EGS_BaseSource * createSource(EGS_Input *)
Create sources from the information pointed to by input.
virtual bool setState(istream &data_in)
Set the source state based on data from the stream data_in.
virtual void setSimulationChunk(EGS_I64 nstart, EGS_I64 nrun, int npar, int nchunk)
Set the next simulation chunk to start at nstart and to consist of nrun particles.
virtual bool storeState(ostream &data_out) const
Store the source state into the stream data_out.
A class for storing information in a tree-like structure of key-value pairs. This class is used throu...
Definition: egs_input.h:182
int setContentFromFile(const char *fname)
Set the property from the input file fname (which is considered to be an absolute file name)
Definition: egs_input.cpp:200
int ref()
Increase the reference count to this object.
static void deleteObject(EGS_Object *o)
Delete an object.
const string & getObjectType() const
Get the object type.
virtual void fillArray(int n, EGS_Float *array)=0
Fill the array of n elements pointed to by array with random numbers.
static EGS_RandomGenerator * defaultRNG(int sequence=0)
Returns a pointer to the default egspp RNG.
Definition: egs_rndm.cpp:465
static EGS_RandomGenerator * createRNG(EGS_Input *inp, int sequence=0)
Create a RNG object from the information pointed to by inp and return a pointer to it.
Definition: egs_rndm.cpp:409
bool storeState(ostream &data)
Functions for storing, seting and reseting the state of a RNG object.
Definition: egs_rndm.cpp:83
virtual void describeRNG() const
Describe this RNG.
Definition: egs_rndm.h:256
EGS_I64 numbersUsed() const
Returns the number of random numbers used so far.
Definition: egs_rndm.h:125
A simple run control object for advanced EGSnrc C++ applications.
virtual EGS_I64 getNextChunk()
Returns the number of histories to run in the next simulation chunk.
int getNbatch() const
Returns the number of batches per simulation chunk.
virtual int startSimulation()
Starts the simulation.
virtual bool startBatch(int, EGS_I64)
Start a new batch.
virtual bool finishBatch()
Finish a batch.
virtual int finishSimulation()
Finish the simulation.
A job control object for homogeneous computing environments (HCE).
A class representing 3D vectors.
Definition: egs_vector.h:57
EGS_Float y
y-component
Definition: egs_vector.h:62
EGS_Float z
z-component
Definition: egs_vector.h:63
EGS_Float x
x-component
Definition: egs_vector.h:61
EGS_Application class header file.
EGS_AusgabObject interface class header file.
EGS_BaseGeometry class header file.
EGS_BaseSource class header file.
Global egspp functions header file.
EGS_Input class header file.
#define EGS_EXPORT
Export symbols from the egspp library.
Definition: egs_libconfig.h:90
EGS_RandomGenerator class header file.
EGS_RunControl and EGS_JCFControl class header file.
EGS_SimpleContainer template class.
bool EGS_EXPORT egsStoreI64(ostream &data, EGS_I64 n)
Writes the 64 bit integer n to the output stream data and returns true on success,...
string egsHostName()
Get the name of the host the program is running on.
int egsGetPid()
Get the process id.
EGS_InfoFunction EGS_EXPORT egsInformation
Always use this function for reporting the progress of a simulation and any other type of information...
EGS_InfoFunction EGS_EXPORT egsFatal
Always use this function for reporting fatal errors.
bool EGS_EXPORT egsGetI64(istream &data, EGS_I64 &n)
Reads a 64 bit integer from the stream data and assigns it to n. Returns true on success,...
string egsJoinPath(const string &first, const string &second)
Join two path variables (or a path and a file name) using the platform specific directory separator a...
EGS_InfoFunction EGS_EXPORT egsWarning
Always use this function for reporting warnings.
const EGS_Float veryFar
A very large float.
string egsStripPath(const string &aname)
Strip the path from a file name and return the result.
EGS_Vector x
position
EGS_Float E
particle energy in MeV
EGS_Vector u
direction
int ir
particle region index
int latch
latch variable (useful as a flag on many occasions)
EGS_Float wt
statistical weight
int q
particle charge