EGSnrc C++ class library  Report PIRS-898 (2021)
Iwan Kawrakow, Ernesto Mainegra-Hing, Frederic Tessier, Reid Townson and Blake Walters
egs_phsp_scoring.cpp
Go to the documentation of this file.
1 /*
2 ###############################################################################
3 #
4 # EGSnrc egs++ phase space scoring object
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: Blake Walters, 2018
25 #
26 # Contributors: Reid Townson
27 #
28 ###############################################################################
29 */
30 
31 
37 #include <sstream>
38 #include <fstream>
39 #include <string>
40 #include <cstdlib>
41 
42 #include "egs_phsp_scoring.h"
43 #include "egs_input.h"
44 #include "egs_functions.h"
45 #include "iaea_phsp.h"
46 
47 EGS_PhspScoring::EGS_PhspScoring(const string &Name,
48  EGS_ObjectFactory *f) :
49  EGS_AusgabObject(Name,f), phsp_index(0), store_max(1000), phsp_file(),
50  count(0), countg(0), emin(1.e30), emax(-1.e30), first_flush(true), is_restart(false) {
51  otype = "EGS_PhspScoring";
52 }
53 
54 EGS_PhspScoring::~EGS_PhspScoring() {
55 }
56 
57 void EGS_PhspScoring::setApplication(EGS_Application *App) {
59  if (!app) {
60  return;
61  }
62 
63  char buf[512];//useful character buffer
64  //set up the stack of particles to output to the phase space file
65  //1000 particles at a time
66  p_stack = new Particle[store_max];
67 
68  description = "\n*******************************************\n";
69  description += "Phase Space Scoring Object (";
70  description += name;
71  description += ")\n";
72  description += "*******************************************\n";
73  if (score_type==0) {
74  description += "\n Will output phase space for particles crossing surfaces of geometry:\n";
75  description += phsp_geom->getName();
76  description += "\n Particles scored on: ";
77  if (scoredir == 0) {
78  description += "entering and exiting phase space geometry";
79  }
80  else if (scoredir == 1) {
81  description += "entering phase space geometry";
82  }
83  else if (scoredir == 2) {
84  description += "exiting phase space geometry";
85  }
86  }
87  else if (score_type==1) {
88  description += "\n Will output phase space for the following exit/entry region pairs:\n";
89  description += " Exit regions:\n";
90  for (int i=0; i<fromreg.size(); i++) {
91  sprintf(buf,"%d ",fromreg[i]);
92  description += buf;
93  }
94  description += "\n Entry regions:\n";
95  for (int i=0; i<fromreg.size(); i++) {
96  sprintf(buf,"%d ",toreg[i]);
97  description += buf;
98  }
99  description += "\n";
100  //now, for every region, set up a (possibly empty) array of entry regions
101  int nreg = app->getnRegions();
102  for (int ir=0; ir<nreg; ir++) {
103  vector<int> tolist;
104  for (int i=0; i<fromreg.size(); i++) {
105  if (fromreg[i]==ir) {
106  tolist.push_back(toreg[i]);
107  }
108  }
109  from_to.push_back(tolist);
110  }
111  }
112 
113  //construct name of phase space file -- opening to occur later
114  if (phspoutdir == "") {
115  phspoutdir = app->getAppDir();
116  }
117  if (oformat==0) {
118  description += "\n Data will be output in EGSnrc format.\n";
119  if (app->getNparallel()>0) {
120  sprintf(buf,"%s_w%d.egsphsp1",getObjectName().c_str(),app->getIparallel());
121  }
122  else {
123  sprintf(buf,"%s.egsphsp1",getObjectName().c_str());
124  }
125  phsp_fname=egsJoinPath(phspoutdir,buf);
126  description += "\n Phase space file name:\n";
127  description += phsp_fname;
128  }
129  else if (oformat==1) {
130  description += "\n Data will be output in IAEA format.\n";
131  if (app->getNparallel()>0) {
132  sprintf(buf,"%s_w%d.1",getObjectName().c_str(),app->getIparallel());
133  }
134  else {
135  sprintf(buf,"%s.1",getObjectName().c_str());
136  }
137  phsp_fname=egsJoinPath(phspoutdir,buf);
138 
139  //need to add a null terminator
140  len = phsp_fname.length();
141  phsp_fname_char = new char[len+1];
142  phsp_fname.copy(phsp_fname_char,len,0);
143  phsp_fname_char[len]='\0'; //null terminator on string
144 
145  //iaea particle charge
146  iaea_q_type[0]=2; //e-
147  iaea_q_type[1]=1; //photon
148  iaea_q_type[2]=3; //e+
149 
150  iaea_id = 1;
151 
152  //set up extra float and extra long array indices
153  latch_ind = 2;//type of latch as defined by iaea
154  iaea_n_extra_long=1; //only store latch
155  iaea_i_latch=0; // position of latch in array
156  if (score_time) {
157  iaea_n_extra_float=1;
158  time_ind = 0; //set type to generic float
159  iaea_i_time=0; //position of time index in array
160  }
161  else {
162  iaea_n_extra_float=0; //no extra floats
163  }
164 
165  description += "\n Phase space file names:\n";
166  description += " Header file: " + phsp_fname + ".IAEAheader\n";
167  description += " Data file: " + phsp_fname + ".IAEAphsp";
168  string xyzname[3] = {"X", "Y", "Z"};
169  for (int i=0; i<3; i++) {
170  if (xyz_is_const[i]) {
171  ostringstream xyz;
172  xyz << xyzscore[i];
173  description += "\n Data scored at constant " + xyzname[i] + " = " + xyz.str() + " cm";
174  }
175  }
176  }
177  description += "\n Particles scored: ";
178  if (ocharge == 0) {
179  description += "all";
180  }
181  else if (ocharge == 1) {
182  description += "photons";
183  }
184  else if (ocharge == 2) {
185  description += "charged";
186  }
187  if (oformat ==1 && score_time) {
188  description += "\n time index will be scored (if available)";
189  }
190  if (oformat ==0 && score_mc) {
191  description += "\n will score multiple crossers (and descendents)";
192  }
193 }
194 
195 //final buffer flush and then close file
196 //we want to output some data about particles scored
197 //may ultimately want to allow the user to define scoring zones for output
198 void EGS_PhspScoring::reportResults() {
199  flushBuffer();
200  if (oformat == 1) { //iaea
201  int iaea_iostat;
202  iaea_destroy_source(&iaea_id,&iaea_iostat);
203  if (iaea_iostat<0) {
204  egsFatal("\n EGS_PhspScoring: Error closing phase space file.\n");
205  }
206  }
207  else if (oformat == 0) {
208  phsp_file.close();
209  }
210  egsInformation("\n======================================================\n");
211  egsInformation("Phase Space Scoring Object(%s)\n",name.c_str());
212  egsInformation("======================================================\n");
213  if (oformat==1) {
214  egsInformation("\n IAEA format phase space output:\n");
215  egsInformation(" Header file: %s.IAEAheader\n",phsp_fname.c_str());
216  egsInformation(" Data file: %s.IAEAphsp\n",phsp_fname.c_str());
217  }
218  else if (oformat == 0) {
219  egsInformation("\n EGSnrc format phase space output:\n");
220  egsInformation(" Data file: %s\n",phsp_fname.c_str());
221  }
222  float emintmp;
223  if (count == countg) {
224  emintmp = 0.0;
225  }
226  else {
227  emintmp = emin;
228  }
229  egsInformation("Summary of scored data:\n");
230  egsInformation("=> total no. of particles = %lld \n", count);
231  egsInformation("=> no. of photons = %lld \n", countg);
232  egsInformation("=> max. k.e. of all particles = %g MeV\n",emax);
233  egsInformation("=> min. k.e. of charged particles = %g MeV\n",emintmp);
234  egsInformation("=> no. of primary histories represented = %lld\n",last_case);
235  egsInformation("\n======================================================\n");
236 }
237 
238 //store 1000 particles at a time in p_stack
239 //if we're at 1000, actually write the particles to the file and update
240 //the header info
241 //also, keep track of phase space file counters, min., max. energy
242 void EGS_PhspScoring::storeParticle(EGS_I64 ncase) {
243 
244  //if user requested time index scoring, check if time is available
245  if (score_time && app->getTimeIndex() < 0) {
246  egsWarning("\nEGS_PhspScoring: User requested time index scoring, but time is inavailable with this source.\n");
247  egsWarning("Turning off time index scoring.\n");
248  score_time=false;
249  }
250 
251  //counters, min. and max. k.e.
252  EGS_Float prm = app->getRM();
253  count++;
254  if (app->top_p.q==0) {
255  countg++;
256  }
257  double ke = app->top_p.E-abs(app->top_p.q)*prm;
258  if (ke > emax) {
259  emax = ke;
260  }
261  if (app->top_p.q != 0 && app->top_p.E - prm < emin) {
262  emin = app->top_p.E - prm;
263  }
264 
265  // Store kinetic energy for IAEA format phsp, and total energy for egsphsp
266  double E;
267  if (oformat == 0) {
268  E = app->top_p.E;
269  }
270  else if (oformat == 1) {
271  E = ke;
272  }
273 
274  //set -ve energy marker if this is a new primary hist.
275  if (ncase != last_case) {
276  E = -E;
277  last_case = ncase;
278  }
279 
280  //store particle data in p_stack
281  p_stack[phsp_index].E = E;
282  p_stack[phsp_index].wt = app->top_p.wt;
283  p_stack[phsp_index].x = app->top_p.x.x;
284  p_stack[phsp_index].y = app->top_p.x.y;
285  p_stack[phsp_index].z = app->top_p.x.z;
286  p_stack[phsp_index].u = app->top_p.u.x;
287  p_stack[phsp_index].v = app->top_p.u.y;
288  p_stack[phsp_index].w = app->top_p.u.z;
289  p_stack[phsp_index].q = app->top_p.q;
290  if (score_time) {
291  p_stack[phsp_index].time = app->getTimeIndex();
292  }
293  p_stack[phsp_index++].latch = app->top_p.latch;
294 
295  if (phsp_index > store_max - 1) {
296  //write store_max particles to the file and reset phsp_index counter
297  flushBuffer();
298  }
299 }
300 
301 //open the phase space file for writing/appending data
302 void EGS_PhspScoring::openPhspFile() const {
303 //the file has already been named at this point
304  if (oformat==0) { //EGSnrc format
305  if (is_restart) {
306  phsp_file.open(phsp_fname.c_str(),ios::binary|ios::out|ios::in);
307  if (!(phsp_file))
308  egsFatal("\nEGS_PhspScoring: Failed to open phase space file %s for appending.\n",
309  phsp_fname.c_str());
310  //check that total no. of particles in header = total no. read from .egsdat file
311  unsigned int count4;
312  phsp_file.seekg(5,ios::beg);
313  phsp_file.read((char *) &count4, sizeof(unsigned int));
314  if (count4 != countprev) {
315  egsFatal("\nEGS_PhspScoring: Particle no. mismatch between %s and .egsdat file.\n",phsp_fname.c_str());
316  }
317  //go to the end of the file
318  phsp_file.seekp(0,ios::end);
319  if (phsp_file.tellp() != 28 + countprev*sizeof(egs_phsp_write_struct)) {
320  egsFatal("\nEGS_PhspScoring: File size mismatch in %s and .egsdat file.\n",phsp_fname.c_str());
321  }
322  }
323  else {
324  phsp_file.open(phsp_fname.c_str(),ios::binary|ios::out);
325  if (!(phsp_file))
326  egsFatal("\nEGS_PhspScoring: Failed to open phase space file %s for writing.\n",
327  phsp_fname.c_str());
328  //always MODE0 files--i.e. no ZLAST
329  phsp_file.write("MODE0",5);
330  //leave space for/skip over the rest of the header
331  phsp_file.seekp(28,ios::beg);
332  }
333  }
334  else if (oformat == 1) { //IAEA format
335  int iaea_iostat;
336  iaea_id = 1; //numerical index indicating this is the 1st file associated with this object scored
337  //hard coded to 1
338  if (is_restart) {
339  int rwmode = 3;
340  iaea_new_source(&iaea_id,phsp_fname_char,&rwmode,&iaea_iostat,len);
341  if (iaea_iostat < 0) {
342  egsFatal("\nEGS_PhspScoring: Failed to open phase space file %s.IAEAphsp for appending.\n",phsp_fname.c_str());
343  }
344  //check for consistency with total no. of scored particles as read from .egsdat file
345  EGS_I64 nparticle;
346  int type = -1;
347  int iaea_iostat;
348  iaea_get_max_particles(&iaea_id,&type,&nparticle);
349  if (nparticle != countprev) {
350  egsFatal("\nEGS_PhspScoring: Particle no. mismatch between %s.IAEAphsp and .egsdat file.\n",phsp_fname.c_str());
351  }
352  iaea_check_file_size_byte_order(&iaea_id,&iaea_iostat);
353  if (iaea_iostat != 0) {
354  egsFatal("\nEGS_PhspScoring: Byte order/file size mismatch in %s.IAEAphsp.\n",phsp_fname.c_str());
355  }
356  }
357  else {
358  int rwmode = 2;
359  iaea_new_source(&iaea_id,phsp_fname_char,&rwmode,&iaea_iostat,len);
360  if (iaea_iostat < 0) {
361  egsFatal("\nEGS_PhspScoring: Failed to open phase space file %s.IAEAphsp for writing.\n",phsp_fname.c_str());
362  }
363  }
364 
365 
366  //set up constant variables
367  for (int i=0; i<3; i++) {
368  if (xyz_is_const[i]) {
369  int index = i;
370  float constval = xyzscore[i];
371  iaea_set_constant_variable(&iaea_id,&index,&constval);
372  }
373  }
374  //set up extra floats and int indices and types
375  //need to store below in _tmp variables because this is a const function
376  int latch_ind_tmp = latch_ind;
377  int iaea_n_extra_long_tmp=iaea_n_extra_long;
378  int iaea_i_latch_tmp=iaea_i_latch;
379  int time_ind_tmp = time_ind;
380  int iaea_i_time_tmp = iaea_i_time;
381  int iaea_n_extra_float_tmp=iaea_n_extra_float;
382 
383  iaea_set_extra_numbers(&iaea_id,&iaea_n_extra_float_tmp,&iaea_n_extra_long_tmp);
384  iaea_set_type_extralong_variable(&iaea_id,&iaea_i_latch_tmp,&latch_ind_tmp);
385  if (score_time) {
386  iaea_set_type_extrafloat_variable(&iaea_id,&iaea_i_time_tmp,&time_ind_tmp);
387  }
388  }
389 }
390 
391 //write phsp_index particles to phase space file
392 //update header and reset phsp_index
393 int EGS_PhspScoring::flushBuffer() const {
394 
395  if (first_flush) {
396  openPhspFile(); //here's where we open the phase space file
397  }
398  //awkward logic because we do not know if this is a restart
399  //until after initialization
400  first_flush = false;
401 
402  if (oformat == 1) { //iaea format
403  for (int j=0; j<phsp_index; j++) {
404  //fairly transparent, could probably put a lot of this in a separate method
405  //undo -ve energy marker and use n_stat to indicate new primary hist.
406  int n_stat = p_stack[j].E < 0 ? 1 : 0;
407  float E = abs(p_stack[j].E);
408  //convert charge to iaea type
409  int type = iaea_q_type[p_stack[j].q+1];
410 
411  //store latch in iaea_extra_long
412  EGS_I32 *iaea_extra_long = new EGS_I32[iaea_n_extra_long];
413  iaea_extra_long[iaea_i_latch]=p_stack[j].latch;
414  float *iaea_extra_float = new float[iaea_n_extra_float];
415  if (score_time) {
416  iaea_extra_float[iaea_i_time] = p_stack[j].time;
417  }
418 
419  //now store double precision values in single precision reals
420  float wt = p_stack[j].wt;
421  float x = p_stack[j].x;
422  float y = p_stack[j].y;
423  float z = p_stack[j].z;
424  float u = p_stack[j].u;
425  float v = p_stack[j].v;
426  float w = p_stack[j].w;
427  //now actually write data
428 
429  iaea_write_particle(&iaea_id,&n_stat,&type,&E,&wt,&x,&y,&z,&u,&v,&w,iaea_extra_float,iaea_extra_long);
430  if (n_stat < 0) {
431  egsFatal("\nEGS_PhspScoring: Failed to write particle data to phase space file.");
432  }
433  }
434  //update header with no. of primary histories
435  EGS_I64 last_case_tmp = last_case;
436  iaea_set_total_original_particles(&iaea_id,&last_case_tmp);
437  //update header file
438  int iaea_iostat;
439  iaea_update_header(&iaea_id,&iaea_iostat);
440  if (iaea_iostat<0) {
441  egsFatal("\nEGS_PhspScoring: Failed to update phase space header file.");
442  }
443  }
444  else if (oformat == 0) { //EGSnrc format
445  if (!phsp_file) {
446  egsFatal("\nEGS_PhspScoring: phase space file is not open for writing.");
447  }
448  //don't forget that phsp_index is incremented after every particle written to p_stack
449  for (int j=0; j<phsp_index; j++) {
450  egs_phsp_write_struct ws(p_stack[j]);
451  phsp_file.write((char *) &ws, sizeof(ws));
452  }
453  //store position of end of file
454  iostream::off_type pos = (count+1)*sizeof(egs_phsp_write_struct);
455  //update header
456  phsp_file.seekp(5,ios::beg);
457  unsigned int count4 = count, countg4 = countg;
458  float pinc = last_case;
459  float emintmp;
460  if (countg4==count4) {
461  emintmp = 0.0;
462  }
463  else {
464  emintmp = emin;
465  }
466  phsp_file.write((char *) &count4, sizeof(unsigned int));
467  phsp_file.write((char *) &countg4, sizeof(unsigned int));
468  phsp_file.write((char *) &emax, sizeof(float));
469  phsp_file.write((char *) &emintmp, sizeof(float));
470  phsp_file.write((char *) &pinc, sizeof(float));
471  phsp_file.seekp(pos,ios::beg);
472  }
473 
474  phsp_index=0;
475 
476  return 0;
477 };
478 
479 bool EGS_PhspScoring::storeState(ostream &data) const {
480  if (!egsStoreI64(data,count)) {
481  return false;
482  }
483  if (!egsStoreI64(data,countg)) {
484  return false;
485  }
486  //update phase space file at the end of each batch
487  flushBuffer();
488  return true;
489 }
490 
491 bool EGS_PhspScoring::setState(istream &data) {
492  if (!egsGetI64(data,count)) {
493  return false;
494  }
495  if (!egsGetI64(data,countg)) {
496  return false;
497  }
498  countprev = count;
499  is_restart = true;
500  return true;
501 }
502 
503 bool EGS_PhspScoring::addState(istream &data) {
504  EGS_I64 tmp;
505  if (!egsGetI64(data,tmp)) { //return false;
506  egsWarning("error while reading count\n");
507  return false;
508  }
509  count += tmp;
510  if (!egsGetI64(data,tmp)) { //return false;
511  egsWarning("error while reading countg\n");
512  return false;
513  }
514  countg += tmp;
515  return true;
516 }
517 
518 //*********************************************************************
519 // Process input for this ausgab object
520 //**********************************************************************
521 extern "C" {
522 
523  EGS_PHSP_SCORING_EXPORT EGS_AusgabObject *createAusgabObject(EGS_Input *input,
524  EGS_ObjectFactory *f) {
525  const static char *func = "createAusgabObject(phsp_scoring)";
526  if (!input) {
527  egsWarning("%s: null input?\n",func);
528  return 0;
529  }
530  string str;
531  EGS_BaseGeometry *phspgeom;
532  int iscoremc = 0; //default to not score multiple crossers
533  vector <int> from_reg, to_reg;
534  int stype = 0; //default is to use scoring geom
535  int phspouttype;
536  int ptype;
537  int sdir=0;
538  int itimescore = 0;
539  float xyzconst[3];
540  bool xyzisconst[3] = {false, false, false};
541  string gname;
542  string outdir;
543  int err01 = input->getInput("phase space geometry",gname);
544  if (err01) {
545  stype = 1;
546  }
547  else {
548  phspgeom = EGS_BaseGeometry::getGeometry(gname);
549  if (!phspgeom) {
550  egsWarning("\nEGS_PhspScoring: %s does not name an existing geometry.\n"
551  "Will assume you want to use exit/entry region pairs.\n",gname.c_str());
552  stype = 1;
553  }
554  else {
555  if (input->getInput("score particles on", str) < 0) {
556  egsInformation("EGS_PhspScoring: No input for scoring direction.\n");
557  egsInformation("Will score on entry and exit from phase space geometry.\n");
558  sdir = 0;
559  }
560  else {
561  //get scoring direction
562  vector<string> allowed_sdir;
563  allowed_sdir.push_back("entry and exit");
564  allowed_sdir.push_back("entry");
565  allowed_sdir.push_back("exit");
566  sdir = input->getInput("score particles on",allowed_sdir,-1);
567  if (sdir < 0) {
568  egsFatal("\nEGS_PhspScoring: Invalid scoring direction.\n");
569  }
570  }
571  }
572  }
573  if (stype==1) {
574  // user wants to use exit/entry region pairs
575  int err05 = input->getInput("from regions",from_reg);
576  int err06 = input->getInput("to regions",to_reg);
577  if (err05 || err06) {
578  egsFatal("\nEGS_PhspScoring: Missing/incorrect input for scoring method\n"
579  "(scoring geometry or pairs of exit/entry regions)\n");
580  }
581  else {
582  //run some checks on exit/entry region pairs
583  vector<int>::iterator p,p1;
584  if (from_reg.size() > to_reg.size()) {
585  p = from_reg.begin();
586  egsWarning("\nEGS_PhspScoring: Mismatch in no. of exit/entry regions.\n"
587  "Will only score for matched pairs.\n");
588  p += to_reg.size();
589  from_reg.erase(p,p+from_reg.size()-to_reg.size());
590  }
591  else if (to_reg.size() > from_reg.size()) {
592  p = to_reg.begin();
593  egsWarning("\nEGS_PhspScoring: Mismatch in no. of exit/entry regions.\n"
594  "Will only score for matched pairs.\n");
595  p += from_reg.size();
596  to_reg.erase(p,p+to_reg.size()-from_reg.size());
597  }
598  //now go through and look for exit region = entry region
599  int i=0;
600  while (i<from_reg.size()) {
601  if (from_reg[i]==to_reg[i]) {
602  egsInformation("\nEGS_PhspScoring: Cannot have entry region = exit region (reg no. %d)\n",from_reg[i]);
603  egsInformation("Will delete this pair\n");
604  p=from_reg.begin()+i;
605  p1 =to_reg.begin()+i;
606  from_reg.erase(p);
607  to_reg.erase(p1);
608  }
609  else {
610  //advance counter
611  i++;
612  }
613  }
614  }
615  }
616  //now get common inputs for both scoring methods
617  if (input->getInput("output format", str) < 0) {
618  egsInformation("EGS_PhspScoring: No input for output format type. Will default to EGSnrc.\n");
619  phspouttype = 0;
620  }
621  else {
622  vector<string> allowed_oformat;
623  allowed_oformat.push_back("EGSnrc");
624  allowed_oformat.push_back("IAEA");
625  phspouttype = input->getInput("output format", allowed_oformat, -1);
626  if (phspouttype < 0) {
627  egsFatal("\nEGS_PhspScoring: Invalid output format.\n");
628  }
629  //see if the user wants to specify constant X/Y/Z for IAEA format
630  if (phspouttype == 1) {
631  int err02 = input->getInput("constant X",xyzconst[0]);
632  int err03 = input->getInput("constant Y",xyzconst[1]);
633  int err04 = input->getInput("constant Z",xyzconst[2]);
634  if (!err02) {
635  xyzisconst[0] = true;
636  }
637  if (!err03) {
638  xyzisconst[1] = true;
639  }
640  if (!err04) {
641  xyzisconst[2] = true;
642  }
643  //see if user wants to score time index (if available)
644  //default is not to score
645  // The "score mu" input is supported for backwards compatibility
646  if (!input->getInput("score mu", str)) {
647  vector<string> allowed_timescore;
648  allowed_timescore.push_back("no");
649  allowed_timescore.push_back("yes");
650  itimescore = input->getInput("score mu",allowed_timescore,-1);
651  if (itimescore < 0) {
652  egsWarning("\nEGS_PhspScoring: Invalid input for time index scoring. Will not score time.\n");
653  itimescore = 0;
654  }
655  }
656  // Now "score time index" is used instead of "score mu"
657  if (!input->getInput("score time index", str)) {
658  vector<string> allowed_timescore;
659  allowed_timescore.push_back("no");
660  allowed_timescore.push_back("yes");
661  itimescore = input->getInput("score time index",allowed_timescore,-1);
662  if (itimescore < 0) {
663  egsWarning("\nEGS_PhspScoring: Invalid input for time index scoring. Will not score time.\n");
664  itimescore = 0;
665  }
666  }
667  }
668  }
669  if (phspouttype == 0) {
670  //see if user wants to score multiple crossers
671  if (!input->getInput("score multiple crossers", str)) {
672  vector<string> allowed_scoremc;
673  allowed_scoremc.push_back("no");
674  allowed_scoremc.push_back("yes");
675  iscoremc = input->getInput("score multiple crossers",allowed_scoremc,-1);
676  if (iscoremc < 0) {
677  egsWarning("\nEGS_PhspScoring: Invalid input for score multiple crossers. Will not score.\n");
678  iscoremc = 0;
679  }
680  }
681  }
682  if (input->getInput("output directory",outdir) < 0) {
683  outdir="";
684  }
685  if (input->getInput("particle type", str) < 0) {
686  egsInformation("EGS_PhspScoring: No input for particle type. Will score all.\n");
687  ptype = 0;
688  }
689  else {
690  //get particle type
691  vector<string> allowed_ptype;
692  allowed_ptype.push_back("all");
693  allowed_ptype.push_back("photons");
694  allowed_ptype.push_back("charged");
695  ptype = input->getInput("particle type",allowed_ptype,-1);
696  if (ptype < 0) {
697  egsFatal("\nEGS_PhspScoring: Invalid particle type.\n");
698  }
699  }
700 
701  //=================================================
702 
703  /* Setup phsp scoring object with input parameters */
704  EGS_PhspScoring *result = new EGS_PhspScoring("",f);
705  result->setName(input);
706  if (stype==0) {
707  result->setGeom(phspgeom);
708  }
709  else if (stype==1) {
710  result->setEntryExitReg(from_reg,to_reg);
711  }
712  result->setOType(phspouttype);
713  result->setXYZconst(xyzisconst,xyzconst);
714  result->setOutDir(outdir);
715  result->setParticleType(ptype);
716  result->setScoreDir(sdir);
717  result->setTimeScore(itimescore);
718  result->setScoreMC(iscoremc);
719  return result;
720  }
721 }
Base class for advanced EGSnrc C++ applications.
int getNparallel() const
Returns the number of parallel jobs executing.
EGS_Float getTimeIndex()
Returns the value of the time synchronization parameter.
const string & getAppDir() const
Returns the absolute path to the user code directory.
int getIparallel() const
Returns the job number in a parallel run.
EGS_Particle top_p
The top particle on the stack (i.e., the particle being transported)
virtual void setApplication(EGS_Application *App)
Set the application this object belongs to.
string description
A short ausgab object description.
EGS_Application * app
The application this object belongs to.
Base geometry class. Every geometry class must be derived from EGS_BaseGeometry.
const string & getName() const
Get the name of this geometry.
static EGS_BaseGeometry * getGeometry(const string &Name)
Get a pointer to the geometry named Name.
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 getInput(const string &key, vector< string > &values) const
Assign values to an array of strings from an input identified by key.
Definition: egs_input.cpp:338
An object factory.
void setName(EGS_Input *inp)
Set the name of the object from the information provided by inp.
const string & getObjectName() const
Get the object name.
string name
The object name.
A phase space scoring object: header.
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
Global egspp functions header file.
EGS_Input class header file.
A phase space scoring ausgab object.
EGS_RADIATIVE_SPLITTING_EXPORT EGS_AusgabObject * createAusgabObject(EGS_Input *input, EGS_ObjectFactory *f)
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,...
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.
EGS_Vector x
position
EGS_Float E
particle energy in MeV
EGS_Vector u
direction
int latch
latch variable (useful as a flag on many occasions)
EGS_Float wt
statistical weight
int q
particle charge