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