EGSnrc C++ class library  Report PIRS-898 (2021)
Iwan Kawrakow, Ernesto Mainegra-Hing, Frederic Tessier, Reid Townson and Blake Walters
egs_beam_source.cpp
Go to the documentation of this file.
1 /*
2 ###############################################################################
3 #
4 # EGSnrc egs++ beam source
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: Blake Walters
27 # Frederic Tessier
28 # Reid Townson
29 # Ernesto Mainegra-Hing
30 # Alexandre Demelo
31 #
32 ###############################################################################
33 */
34 
35 
41 #include "egs_beam_source.h"
42 #include "egs_input.h"
43 #include "egs_functions.h"
44 #include "egs_library.h"
45 #include "egs_application.h"
46 
47 #include <cstdlib>
48 #include <cstring>
49 
50 #define STRINGIFY(s) HELP_S(s)
51 #define HELP_S(s) #s
52 #define F77_NAME(fname,FNAME) STRINGIFY(F77_OBJ(fname,FNAME))
53 #define F77_NAME_(fname,FNAME) STRINGIFY(F77_OBJ_(fname,FNAME))
54 
56  EGS_BaseSource(input,f) {
57  n_reuse_photon = 0;
58  n_reuse_electron = 0;
59  i_reuse_photon = 0;
60  i_reuse_electron = 0;
61  is_valid = false;
62  time_stored = false;
63  lib = 0;
64  Xmin = -veryFar;
65  Xmax = veryFar;
66  Ymin = -veryFar;
67  Ymax = veryFar;
68  wmin = -veryFar;
69  wmax = veryFar;
70  string beam_code;
71  int err1 = input->getInput("beam code",beam_code);
72  string pegs_file;
73  int err2 = input->getInput("pegs file",pegs_file);
74  string input_file;
75  int err3 = input->getInput("input file",input_file);
76  if (err1) {
77  egsWarning("EGS_BeamSource: no 'beam code' input\n");
78  }
79  if (err2) {
80  egsWarning("EGS_BeamSource: no 'pegs file' input\n");
81  }
82  if (err3) {
83  egsWarning("EGS_BeamSource: no 'input file' input\n");
84  }
85  if (err1 || err2 || err3) {
86  return;
87  }
88  string egs_home;
89  int err_eh = input->getInput("egs_home",egs_home);
90  if (err_eh) {
91  char *eh = getenv("EGS_HOME");
92  if (!eh) {
93  egsWarning("EGS_BeamSource: EGS_HOME is not defined\n");
94  return;
95  }
96  else {
97  egs_home = eh;
98  }
99  }
100  else {
101  egs_home = egsExpandPath(egs_home);
102  }
103  string hen_house;
104  int err_hh = input->getInput("hen_house",hen_house);
105  if (err_hh) {
106  char *hh = getenv("HEN_HOUSE");
107  if (!hh) {
108  egsWarning("EGS_BeamSource: HEN_HOUSE is not defined\n");
109  return;
110  }
111  else {
112  hen_house = hh;
113  }
114  }
115  else {
116  hen_house = egsExpandPath(hen_house);
117  }
118  string path = egs_home;
119  path += "bin/";
120  path += CONFIG_NAME;
121  lib = new EGS_Library(beam_code.c_str(),path.c_str());
122 
123  InitFunction init = (InitFunction)
124  lib->resolve(F77_NAME_(beamlib_init,BEAMLIB_INIT));
125  finish = (FinishFunction)
126  lib->resolve(F77_NAME_(beamlib_finish,BEAMLIB_FINISH));
127  sample = (SampleFunction)
128  lib->resolve(F77_NAME_(beamlib_sample,BEAMLIB_SAMPLE));
129  motionsample = (MotionSampleFunction)
130  lib->resolve(F77_NAME_(beamlib_motionsample,BEAMLIB_MOTIONSAMPLE));
131  MaxEnergyFunction maxenergy = (MaxEnergyFunction)
132  lib->resolve(F77_NAME_(beamlib_max_energy,BEAMLIB_MAX_ENERGY));
133  if (!init) {
134  egsWarning("EGS_BeamSource: failed to resolve the init function\n");
135  }
136  if (!sample) {
137  egsWarning("EGS_BeamSource: failed to resolve the sample function\n");
138  }
139  if (!motionsample) {
140  egsWarning("EGS_BeamSource: failed to resolve the motionsample function\n");
141  }
142  if (!finish) {
143  egsWarning("EGS_BeamSource: failed to resolve the finish function\n");
144  }
145  if (!maxenergy) {
146  egsWarning("EGS_BeamSource: failed to resolve the max. energy function\n");
147  }
148  if (!init || !sample || !finish || !maxenergy) {
149  return;
150  }
151 
152  int ipar=0, ilog=6;
153  int npar=0;
155  if (app) {
156  ipar = app->getIparallel();
157  npar = app->getNparallel();
158  }
159 
160  init(&ipar,&npar,&ilog,hen_house.c_str(),egs_home.c_str(),
161  beam_code.c_str(),pegs_file.c_str(),input_file.c_str(),
162  hen_house.size(), egs_home.size(),
163  beam_code.size(),pegs_file.size(),input_file.size());
164  maxenergy(&Emax);
165 
166  is_valid = true;
167 
168  vector<EGS_Float> cutout;
169  int err = input->getInput("cutout",cutout);
170  if (!err && cutout.size() == 4) {
171  setCutout(cutout[0],cutout[1],cutout[2],cutout[3]);
172  }
173  vector<string> ptype;
174  ptype.push_back("electrons");
175  ptype.push_back("photons");
176  ptype.push_back("positrons");
177  ptype.push_back("all");
178  ptype.push_back("charged");
179  particle_type = input->getInput("particle type",ptype,3)-1;
180 
181  vector<EGS_Float> wwindow;
182  err = input->getInput("weight window",wwindow);
183  if (!err && wwindow.size() == 2) {
184  wmin = wwindow[0];
185  wmax = wwindow[1];
186  }
187 
188  int ntmp;
189  err = input->getInput("reuse photons",ntmp);
190  if (!err && ntmp > 1) {
191  n_reuse_photon = ntmp;
192  }
193  err = input->getInput("reuse electrons",ntmp);
194  if (!err && ntmp > 1) {
195  n_reuse_electron = ntmp;
196  }
197 
198  // now see if time is returned from the BEAM source use motionsample
199  // function, ttime will be -1 if not provided by BEAM have to save the
200  // values read here to use as the first particle in the simulation
201  motionsample(&tei,&txi,&tyi,&tzi,&tui,&tvi,&twi,&twti,&tqi,&tlatchi,&counti,&tiphati,&ttimei);
202 
203  if (!time_stored) {
204  if (ttimei >= 0.0 && ttimei <= 1.0) {
205  egsInformation("EGS_BeamSource:: Time index passed from this source.\n");
206  time_stored = true;
207  }
208  }
209 
210  use_iparticle = true;
211 
212  description = beam_code;
213  description += "(";
214  description += input_file;
215  description += ") simulation source";
216  otype="EGS_BeamSource";
217 }
218 
219 EGS_I64 EGS_BeamSource::getNextParticle(EGS_RandomGenerator *, int &q,
220  int &latch, EGS_Float &E, EGS_Float &wt, EGS_Vector &x, EGS_Vector &u) {
221  if (n_reuse_photon > 0 && i_reuse_photon < n_reuse_photon) {
222  q = q_save;
223  latch = latch_save;
224  E = E_save;
225  wt = wt_save;
226  x = x_save;
227  u = u_save;
228  time = time_save;
229  ++i_reuse_photon;
230  return count;
231  }
232  if (n_reuse_electron > 0 && i_reuse_electron < n_reuse_electron) {
233  q = q_save;
234  latch = latch_save;
235  E = E_save;
236  wt = wt_save;
237  x = x_save;
238  u = u_save;
239  time = time_save;
240  ++i_reuse_electron;
241  return count;
242  }
243  EGS_Float te,tx,ty,tz,tu,tv,tw,twt,ttime;
244  int tq,tlatch,tiphat;
245  bool ok;
246  do {
247  if (use_iparticle) {
248  //reuse data for first particle read in when setting up the source
249  te=tei;
250  tx=txi;
251  ty=tyi;
252  tz=tzi;
253  tu=tui;
254  tv=tvi;
255  tw=twi;
256  twt=twti;
257  tq=tqi;
258  tlatch=tlatchi;
259  count=counti;
260  tiphat=tiphati;
261  ttime=ttimei;
262  use_iparticle=false;
263  }
264  else {
265  motionsample(&te,&tx,&ty,&tz,&tu,&tv,&tw,&twt,&tq,&tlatch,&count,&tiphat,&ttime);
266  //sample(&te,&tx,&ty,&tz,&tu,&tv,&tw,&twt,&tq,&tlatch,&count,&tiphat);
267  //egsInformation("EGS_BeamSource::getNextParticle: Got E=%g q=%d wt=%g"
268  // " x=(%g,%g,%g) latch=%d count=%lld\n",te,tq,twt,tx,ty,tz,
269  // tlatch,count);
270  if (time_stored && (ttime < 0. || ttime > 1.0)) {
271  //something's wrong
272  egsWarning("EGS_BeamSource::getNextParticle: Time index is stored in this source but time returned < 0\n");
273  egsWarning("Will no longer read time.\n");
274  time_stored = false;
275  }
276  }
277  if (tq) {
278  te -= EGS_Application::activeApplication()->getRM();
279  }
280  ok = true;
281  if (te > Emax + epsilon) {
282  ok = false;
283  } //egsInformation("Emax rejection\n"); }
284  if (particle_type < 2 && tq != particle_type) {
285  ok = false;
286  } // egsInformation("charge rejection"); }
287  if (particle_type == 3 && !tq) {
288  ok = false;
289  }
290  if (tx < Xmin || tx > Xmax || ty < Ymin || ty > Ymax) {
291  ok = false;
292  } // egsInformation("cutout rejection\n"); }
293  if (twt < wmin || twt > wmax) {
294  ok = false; // egsInformation("weight rejection\n");
295  }
296  }
297  while (!ok);
298  i_reuse_electron = n_reuse_electron;
299  i_reuse_photon = n_reuse_photon;
300  //egsInformation("returning particle\n");
301  E = te;
302  q = tq;
303  latch = 0; //latch = tlatch;
304  bool save_it = false;
305  if (n_reuse_photon > 1 && !tq) {
306  twt /= n_reuse_photon;
307  i_reuse_photon = 1;
308  save_it = true;
309  }
310  if (n_reuse_electron > 1 && tq) {
311  twt /= n_reuse_electron;
312  i_reuse_electron = 1;
313  save_it = true;
314  }
315  wt = twt;
316  x = EGS_Vector(tx,ty,tz);
317  u = EGS_Vector(tu,tv,tw);
318  time = ttime;
319  if (save_it) {
320  q_save = tq;
321  latch_save = 0;
322  E_save = E;
323  wt_save = twt;
324  x_save = x;
325  u_save = u;
326  time_save = time;
327  }
328 
329  if (time_stored) {
330  setTimeIndex(time);
331  /* this is setting the time index using the base source set call. We get
332  * rid of the local getTimeIndex function and it should allow for saving
333  * time in the base source like all the other sources do */
334  }
335  else {
336  setTimeIndex(-1);
337  }
338 
339  return count;
340 }
341 
347 void EGS_BeamSource::containsDynamic(bool &hasdynamic) {
348  hasdynamic = time_stored;
349 }
350 
351 EGS_BeamSource::~EGS_BeamSource() {
352  if (lib) {
353  if (is_valid) {
354  finish();
355  }
356  delete lib;
357  }
358 }
359 
360 extern "C" {
361 
362  EGS_BEAM_SOURCE_EXPORT EGS_BaseSource *createSource(EGS_Input *input,
363  EGS_ObjectFactory *f) {
364  return
365  createSourceTemplate<EGS_BeamSource>(input,f,"beam source");
366  }
367 
368 }
Base class for advanced EGSnrc C++ applications.
static EGS_Application * activeApplication()
Get the active application.
int getNparallel() const
Returns the number of parallel jobs executing.
int getIparallel() const
Returns the job number in a parallel run.
Base source class. All particle sources must be derived from this class.
string description
A short source description.
SampleFunction sample
The function that returns the next particle.
void containsDynamic(bool &hasdynamic)
Check if the simulation source contains time indices.
EGS_BeamSource(EGS_Input *, EGS_ObjectFactory *f=0)
Create a BEAM simulation source from the input inp.
bool time_stored
true if time index stored
FinishFunction finish
EGS_Library * lib
The BEAMnrc user code library.
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
A class for dynamically loading shared libraries.
Definition: egs_library.h:52
void * resolve(const char *func)
Returns the address of the exported symbol func.
An object factory.
string otype
The object type.
Base random number generator class. All random number generators should be derived from this class.
Definition: egs_rndm.h:67
A class representing 3D vectors.
Definition: egs_vector.h:57
EGS_Application class header file.
A BEAM simulation source.
Global egspp functions header file.
EGS_Input class header file.
EGS_Library class header file.
EGS_InfoFunction EGS_EXPORT egsInformation
Always use this function for reporting the progress of a simulation and any other type of information...
string egsExpandPath(const string &aname)
Expands first environment variable found in a file name.
const EGS_Float epsilon
The epsilon constant for floating point comparisons.
Definition: egs_functions.h:62
EGS_InfoFunction EGS_EXPORT egsWarning
Always use this function for reporting warnings.
const EGS_Float veryFar
A very large float.