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