EGSnrc C++ class library  Report PIRS-898 (2021)
Iwan Kawrakow, Ernesto Mainegra-Hing, Frederic Tessier, Reid Townson and Blake Walters
egs_phsp_scoring.h
Go to the documentation of this file.
1 /*
2 ###############################################################################
3 #
4 # EGSnrc egs++ phase space scoring object headers
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 #ifndef EGS_PHSP_SCORING_
38 #define EGS_PHSP_SCORING_
39 
40 #include "egs_ausgab_object.h"
41 #include "egs_application.h"
42 #include "egs_scoring.h"
43 #include "egs_base_geometry.h"
44 
45 #ifdef WIN32
46 
47  #ifdef BUILD_PHSP_SCORING_DLL
48  #define EGS_PHSP_SCORING_EXPORT __declspec(dllexport)
49  #else
50  #define EGS_PHSP_SCORING_EXPORT __declspec(dllimport)
51  #endif
52  #define EGS_PHSP_SCORING_LOCAL
53 
54 #else
55 
56  #ifdef HAVE_VISIBILITY
57  #define EGS_PHSP_SCORING_EXPORT __attribute__ ((visibility ("default")))
58  #define EGS_PHSP_SCORING_LOCAL __attribute__ ((visibility ("hidden")))
59  #else
60  #define EGS_PHSP_SCORING_EXPORT
61  #define EGS_PHSP_SCORING_LOCAL
62  #endif
63 
64 #endif
65 
250 class EGS_PHSP_SCORING_EXPORT EGS_PhspScoring : public EGS_AusgabObject {
251 
252 public:
253 
254  EGS_PhspScoring(const string &Name="", EGS_ObjectFactory *f = 0);
255 
256  ~EGS_PhspScoring();
257 
259  //only score if particle has correct charge
260  if (ocharge==0 || 1+abs(app->top_p.q)==ocharge) {
261  EGS_Vector x = app->top_p.x;
262  int ir = app->top_p.ir;
263  int latch = app->top_p.latch;
264 
265  // Skip this particle if it's outside the overall geometry and we're scoring on entry only
266  if (scoredir == 1 && ir < 0) {
267  return 0;
268  }
269 
270  //only score if: 1) it has not been scored before or
271  //2) we are scoring multiple crossers (EGSnrc format only)
272  if (!(latch & bsmc()) || (oformat==0 && score_mc)) {
273  if (score_type==0) { //using scoring geometry
274  if (iarg == 0) {
275  phsp_before = phsp_geom->isInside(x);
276  }
277 
278  if (iarg == 5) {
279  phsp_after = phsp_geom->isInside(x);
280  if (phsp_after != phsp_before) {
281  if (scoredir == 0 || (scoredir == 1 && phsp_after) ||
282  (scoredir == 2 && phsp_before)) {
283  storeParticle(current_case);
284  }
285  //set bit 31 to flag this as having been scored
286  latch = (latch | bsmc());
287  app->setLatch(latch);
288  return 0;
289  }
290  }
291  }
292  else if (score_type==1) { //pairs of exit/entry regions
293  if (iarg == 0) {
294  ir_before = ir;
295  }
296 
297  if (iarg == 5) {
298  ir_after = ir;
299  if (from_to[ir_before].size()>0 && ir_before != ir_after) {
300  for (int i=0; i< from_to[ir_before].size(); i++) {
301  if (ir_after == from_to[ir_before][i]) {
302  storeParticle(current_case);
303  latch = (latch | bsmc());
304  app->setLatch(latch);
305  return 0;
306  }
307  }
308  }
309  }
310  }
311  }
312  }
313  return 0;
314  };
315 
316  int processEvent(EGS_Application::AusgabCall iarg, int ir) {
317  // Skip this particle if it's outside the overall geometry and we're scoring on entry only
318  if (scoredir == 1 && ir < 0) {
319  return 0;
320  }
321 
322  //same as above, we don't need the region no.
323  if (ocharge==0 || 1+abs(app->top_p.q)==ocharge) {
324  EGS_Vector x = app->top_p.x;
325  int latch = app->top_p.latch;
326  //only score if: 1) it has not been scored before or
327  //2) we are scoring multiple crossers (EGSnrc format only)
328  if (!(latch & bsmc()) || (oformat==0 && score_mc)) {
329  if (score_type==0) { //using scoring geometry
330  if (iarg == 0) {
331  phsp_before = phsp_geom->isInside(x);
332  }
333 
334  if (iarg == 5) {
335  phsp_after = phsp_geom->isInside(x);
336  if (phsp_after != phsp_before) {
337  if (scoredir == 0 || (scoredir == 1 && phsp_after) ||
338  (scoredir == 2 && phsp_before)) {
339  storeParticle(current_case);
340  }
341  //set bit 31 to flag this as having been scored
342  latch = (latch | bsmc());
343  app->setLatch(latch);
344  return 0;
345  }
346  }
347  }
348  else if (score_type==1) { //pairs of exit/entry regions
349  if (iarg == 0) {
350  ir_before = ir;
351  }
352 
353  if (iarg == 5) {
354  ir_after = ir;
355  if (from_to[ir_before].size()>0 && ir_before != ir_after) {
356  for (int i=0; i< from_to[ir_before].size(); i++) {
357  if (ir_after == from_to[ir_before][i]) {
358  storeParticle(current_case);
359  latch = (latch | bsmc());
360  app->setLatch(latch);
361  return 0;
362  }
363  }
364  }
365  }
366  }
367  }
368  }
369  return 0;
370  };
371 
372  bool needsCall(EGS_Application::AusgabCall iarg) const {
373  if (iarg == 0 || iarg == 5) {
374  return true;
375  }
376  else {
377  return false;
378  }
379  };
380 
381  //below gets called from startNewShower if current_case != last_case
382  //don't update last_case yet
383  void setCurrentCase(EGS_I64 ncase) {
384  current_case=ncase;
385  };
386 
387  void setGeom(EGS_BaseGeometry *phspgeom) {
388  score_type=0;
389  phsp_geom = phspgeom;
390  }
391 
392  void setEntryExitReg(const vector <int> from_reg, const vector <int> to_reg) {
393  score_type=1;
394  fromreg=from_reg;
395  toreg=to_reg;
396  }
397 
398  void setOType(const int phspouttype) {
399  oformat = phspouttype;
400  }
401 
402  //set output directory
403  void setOutDir(const string outdir) {
404  phspoutdir = outdir;
405  }
406 
407  void setParticleType(const int ptype) {
408  ocharge = ptype;
409  }
410 
411  void setScoreDir(const int sdir) {
412  scoredir = sdir;
413  }
414 
415  void setTimeScore(const int itimescore) {
416  if (itimescore == 1) {
417  score_time = true;
418  }
419  else {
420  score_time = false;
421  }
422  }
423 
424  void setScoreMC(const int iscoremc) {
425  if (iscoremc==1) {
426  score_mc = true;
427  }
428  else {
429  score_mc = false;
430  }
431  }
432 
433  //method below pertains only to IAEA format
434  //set array element 0/1/2 of xyz_is_constant equal to true
435  //if scoring at a constant X/Y/Z value and store the
436  //constant value in element 0/1/2 of array xyzscore
437  void setXYZconst(bool xyzisconst[3], float xyzconst[3]) {
438  for (int i=0; i<3; i++) {
439  xyz_is_const[i] = xyzisconst[i];
440  xyzscore[i]=xyzconst[i];
441  }
442  }
443 
444  void storeParticle(EGS_I64 ncase);
445 
446  int flushBuffer() const;
447 
448  void openPhspFile() const;
449 
450  void setApplication(EGS_Application *App);
451 
452  void reportResults();
453 
454  bool storeState(ostream &data) const;
455  bool setState(istream &data);
456  bool addState(istream &data);
457 
458 protected:
459 
460  struct Particle {
461  int q, latch;
462  EGS_Float E, x, y, z, u, v, w, wt, time;
463  };
464 
465  //functions, struct and variables used to write EGSnrc format phsp files
466  static unsigned int bclr() {
467  return ~((1 << 30) | (1 << 29));
468  }
469  static unsigned int bsqe() {
470  return (1 << 30);
471  }
472  static unsigned int bsqp() {
473  return (1 << 29);
474  }
476  int latch;
477  float E;
478  float x,y;
479  float u,v;
480  float wt;
482  egs_phsp_write_struct(const Particle &p) {
483  latch = (p.latch & bclr());
484  if (p.q == -1) {
485  latch = (latch | bsqe());
486  }
487  else if (p.q == 1) {
488  latch = (latch | bsqp());
489  }
490  E = p.E;
491  x = p.x;
492  y = p.y;
493  u = p.u;
494  v = p.v;
495  wt = p.w >= 0 ? p.wt : -p.wt;
496  };
497  };
498 
499  bool score_mc; //set to true to score multiple crossers and their descendents
500 
501  //variables specific to IAEA format
502  mutable int iaea_id; //file id--mutable so we can write to it during storeState
503  int latch_ind; //IAEA id for latch variable (set to 2)
504  int time_ind; //IAEA id for time--no ID for now so set to generic float (0)
505  int iaea_n_extra_float, iaea_n_extra_long; //no. of extra floats, ints
506  int iaea_i_latch, iaea_i_time; //indices of indicated variables in arrays
507  int iaea_q_type[3]; //easy conversion from q to iaea type
508  bool xyz_is_const[3]; //set to true if scoring at constant X/Y/Z
509  float xyzscore[3]; //constant X/Y/Z scoring values
510  int len; //length of name
511  char *phsp_fname_char; //need file name in char format
512  bool score_time; //set to true if scoring time index
513  float ptime; //time index value associated with particle
514 
515  //back to variables common to EGSnrc and IAEA formats
516 
517  Particle *p_stack; //the stored particle stack
518 
519  //below used to set bit 31 to denote the particle has been scored
520  static unsigned int bsmc() {
521  return (1 << 31);
522  }
523 
524  mutable int phsp_index; //index in p_stack array -- mutable so we can change it in storeState
525  int store_max; //max. no. of particles to store in p_stack
526  mutable fstream phsp_file; //output file -- mutable so we can write to it during storeState
527  EGS_I64 count; //total no. of particles in file
528  EGS_I64 countg; //no. of photons in file
529  float emin; //min. k.e. of charged particles in file
530  float emax; //max. k.e. of particles in phsp file
531  mutable bool first_flush; //first time writing to file in this run -- mutable so we can change it in storeState
532 
533  bool is_resume; //true if this is a resumed simulation
534  EGS_I64 countprev; //no. of particles written to file before resume
535 
536  EGS_I64 last_case; //last primary history scored
537  EGS_I64 current_case; //current primary history
538 
539  int oformat; //0 for EGSnrc format, 1 for IAEA format
540 
541  int ocharge; //particle type for output: 0--all; 1--photons; 2--charged particles
542 
543  string phsp_fname; //name of phase space file
544 
545  string phspoutdir; //output directory
546 
547  int score_type; //0 if scoring on exiting/entering a phase space geometry
548  //1 if using pairs of exit/entry regions
549 
550  //for method 1: scoring using predefined geometry
551  EGS_BaseGeometry *phsp_geom; //geometry on entrance to/exit from which phase space data is scored
552  int scoredir; //scoring direction: 0--on entry and exit; 1--on entry; 2--on exit
553  bool phsp_before; //true if inside scoring geometry before step
554  bool phsp_after; //true if inside scoring geometry after step
555 
556  //for method 2: scoring using exit/entry region pairs
557  vector <int> fromreg; //array of exit regions
558  vector <int> toreg; //array of entry regions
559  vector <vector <int> > from_to; //from a given global exit region, an array of possible entry regions
560  int ir_before, ir_after; //reg. no. before and after step
561 };
562 
563 #endif
Base class for advanced EGSnrc C++ applications.
AusgabCall
Possible calls to the user scoring function ausgab().
virtual void setApplication(EGS_Application *App)
Set the application this object belongs to.
virtual int processEvent(EGS_Application::AusgabCall iarg)=0
Process an ausgab call for event iarg.
virtual bool setState(istream &data_in)
Set the ausgab object state based on data from the stream data_in.
virtual void reportResults()
Report results.
virtual bool storeState(ostream &data_out) const
Store the source state into the stream data_out.
virtual void setCurrentCase(EGS_I64 ncase)
Set the current event.
virtual bool addState(istream &data_in)
Add data from the stream data_in to the ausgab object state.
virtual bool needsCall(EGS_Application::AusgabCall iarg) const
Is the ausgab call iarg relevant for this object?
Base geometry class. Every geometry class must be derived from EGS_BaseGeometry.
An object factory.
A phase space scoring object: header.
A class representing 3D vectors.
Definition: egs_vector.h:57
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_ScoringSingle and EGS_ScoringArray class header file.