EGSnrc C++ class library  Report PIRS-898 (2021)
Iwan Kawrakow, Ernesto Mainegra-Hing, Frederic Tessier, Reid Townson and Blake Walters
egs_source_collection.h
Go to the documentation of this file.
1 /*
2 ###############################################################################
3 #
4 # EGSnrc egs++ source collection 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: Iwan Kawrakow, 2005
25 #
26 # Contributors: Reid Townson
27 # Marc Chamberland
28 # Blake Walters
29 #
30 ###############################################################################
31 */
32 
33 
39 #ifndef EGS_SOURCE_COLLECTION_
40 #define EGS_SOURCE_COLLECTION_
41 
42 #include "egs_vector.h"
43 #include "egs_base_source.h"
44 #include "egs_rndm.h"
45 #include "egs_alias_table.h"
46 
47 #include <algorithm>
48 
49 #ifdef WIN32
50 
51  #ifdef BUILD_SOURCE_COLLECTION_DLL
52  #define EGS_SOURCE_COLLECTION_EXPORT __declspec(dllexport)
53  #else
54  #define EGS_SOURCE_COLLECTION_EXPORT __declspec(dllimport)
55  #endif
56  #define EGS_SOURCE_COLLECTION_LOCAL
57 
58 #else
59 
60  #ifdef HAVE_VISIBILITY
61  #define EGS_SOURCE_COLLECTION_EXPORT __attribute__ ((visibility ("default")))
62  #define EGS_SOURCE_COLLECTION_LOCAL __attribute__ ((visibility ("hidden")))
63  #else
64  #define EGS_SOURCE_COLLECTION_EXPORT
65  #define EGS_SOURCE_COLLECTION_LOCAL
66  #endif
67 
68 #endif
69 
123 class EGS_SOURCE_COLLECTION_EXPORT EGS_SourceCollection :
124  public EGS_BaseSource {
125 
126 public:
127 
133  EGS_SourceCollection(const vector<EGS_BaseSource *> &S,
134  const vector<EGS_Float> &prob,
135  const string &Name="", EGS_ObjectFactory *f=0) :
136  EGS_BaseSource(Name,f), nsource(0), count(0) {
137  setUp(S,prob);
138  };
139 
146  if (nsource > 0) {
147  for (int j=0; j<nsource; j++) {
148  EGS_Object::deleteObject(sources[j]);
149  }
150  delete [] sources;
151  delete table;
152  delete [] p;
153  delete [] last_cases;
154  delete [] last_flu;
155  delete [] p_group;
156  }
157  };
158 
159  EGS_I64 getNextParticle(EGS_RandomGenerator *rndm,
160  int &q, int &latch, EGS_Float &E, EGS_Float &wt,
161  EGS_Vector &x, EGS_Vector &u) {
162  int j = table->sample(rndm);
163  EGS_I64 this_case = sources[j]->getNextParticle(rndm,q,latch,E,wt,x,u);
164  count += this_case - last_cases[j];
165  last_cases[j] = this_case;
166  for (int i=0; i<nsource; i++) {
167  //prevent "false" fluence counts in case of a collection consisting of multiple
168  //transformations of a common base source using a vector that, for each source,
169  //stores all other sources sharing the same base source
170  //use fluence increments in the unselected sources to detect this
171  if (i != j && sources[i]->getFluence() > last_flu[i]) {
172  if (std::find(p_group[i].begin(), p_group[i].end(), j) == p_group[i].end()) {
173  p_group[i].push_back(j);
174  p_group[j].push_back(i);
175  }
176  //set last_case for this source equal to that for source j
177  last_cases[i]=last_cases[j];
178  }
179  last_flu[i] = sources[i]->getFluence();
180  }
181  return count;
182  };
183  EGS_Float getEmax() const {
184  return Emax;
185  };
186  EGS_Float getFluence() const {
187  EGS_Float flu = 0;
188  for (int j=0; j<nsource; j++) {
189  EGS_Float p_tot=p[j];
190  for (int i=0; i<p_group[j].size(); i++) {
191  p_tot += p[p_group[j][i]];
192  }
193  int norm = 1;
194  //if we've combined results where a group of sources using a single base source
195  //is used, then at this point the summed fluence for EACH source is actually multiplied
196  //by the number of sources in the group
197  if (i_add) {
198  norm = p_group[j].size()+1;
199  }
200  flu += p[j]/p_tot*sources[j]->getFluence()/norm;
201  }
202  return flu;
203  };
204  bool storeState(ostream &data) const {
205  bool res = EGS_BaseSource::storeState(data);
206  if (!res) {
207  return res;
208  }
209  res = egsStoreI64(data,count);
210  if (!res) {
211  return res;
212  }
213  data << " ";
214  for (int j=0; j<nsource; j++) {
215  res = egsStoreI64(data,last_cases[j]);
216  if (!res) {
217  return res;
218  }
219  data << " ";
220  for (int i=0; i<p_group[j].size(); i++) {
221  data << p_group[j][i] << " ";
222  }
223  // use -1 to denote end of group sharing a common base source
224  data << -1 << " ";
225  if (!sources[j]->storeState(data)) {
226  return false;
227  }
228  }
229  return true;
230  };
231  bool setState(istream &data) {
232  bool res = EGS_BaseSource::setState(data);
233  if (!res) {
234  return res;
235  }
236  res = egsGetI64(data,count);
237  if (!res) {
238  return res;
239  }
240  for (int j=0; j<nsource; j++) {
241  res = egsGetI64(data,last_cases[j]);
242  if (!res) {
243  return res;
244  }
245  EGS_I64 tmp_int;
246  data >> tmp_int;
247  while (tmp_int != -1) {
248  if (std::find(p_group[j].begin(), p_group[j].end(), tmp_int) == p_group[j].end()) {
249  p_group[j].push_back(tmp_int);
250  }
251  data >> tmp_int;
252  }
253  if (!sources[j]->setState(data)) {
254  return false;
255  }
256  last_flu[j]=sources[j]->getFluence();
257  }
258  return true;
259  }
260 
261  void resetCounter() {
263  count = 0;
264  for (int j=0; j<nsource; ++j) {
265  last_cases[j] = 0;
266  last_flu[j] = 0;
267  sources[j]->resetCounter();
268  }
269  };
270 
271  virtual bool addState(istream &data_in) {
272  EGS_I64 tmp;
273  bool res = EGS_BaseSource::addState(data_in);
274  if (!res) {
275  return res;
276  }
277  res = egsGetI64(data_in,tmp);
278  if (!res) {
279  return res;
280  }
281  count += tmp;
282  for (int j=0; j<nsource; j++) {
283  res = egsGetI64(data_in,tmp);
284  if (!res) {
285  return res;
286  }
287  last_cases[j] += tmp;
288  EGS_I64 tmp_int;
289  data_in >> tmp_int;
290  while (tmp_int != -1) {
291  if (std::find(p_group[j].begin(), p_group[j].end(), tmp_int) == p_group[j].end()) {
292  p_group[j].push_back(tmp_int);
293  }
294  data_in >> tmp_int;
295  }
296  if (!sources[j]->addState(data_in)) {
297  return false;
298  }
299  last_flu[j]=sources[j]->getFluence();
300  }
301  i_add = true;
302  return true;
303  };
304 
305  bool isValid() const {
306  return (nsource > 0);
307  };
308 
309  void setSimulationChunk(EGS_I64 nstart, EGS_I64 nrun, int npar, int nchunk) {
310  for (int j=0; j<nsource; j++) {
311  sources[j]->setSimulationChunk(nstart, nrun, npar, nchunk);
312  }
313  };
314 
315  void containsDynamic(bool &hasdynamic);
316 
317  void printSampledEmissions() {
318  for (int j=0; j<nsource; j++) {
319  sources[j]->printSampledEmissions();
320  }
321  }
322 
323  vector<EGS_Ensdf *> getRadionuclideEnsdf() {
324  vector<EGS_Ensdf *> allDecays;
325  for (int j=0; j<nsource; j++) {
326  for (auto decays: sources[j]->getRadionuclideEnsdf()) {
327  allDecays.push_back(decays);
328  }
329  }
330  return allDecays;
331  };
332 
333 protected:
334 
335  int nsource;
338  EGS_I64 *last_cases;
339  EGS_Float *p;
340  EGS_Float *last_flu;
341  EGS_Float Emax;
342  EGS_I64 count;
343  vector<EGS_I64> *p_group;
344  bool i_add;
345 
346  void setUp(const vector<EGS_BaseSource *> &S, const vector<EGS_Float> &);
347 
348 };
349 
350 #endif
Base source class. All particle sources must be derived from this class.
virtual bool addState(istream &data_in)
Add data from the stream data_in to the source state.
virtual void printSampledEmissions()
Print statistics on what was sampled from the source.
virtual EGS_Float getEmax() const =0
Return the maximum energy of this source.
virtual EGS_Float getFluence() const =0
Return the fluence this source has emitted so far.
virtual void resetCounter()
Reset the source state.
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.
virtual bool setState(istream &data_in)
Set the source state based on data from the stream data_in.
virtual void setSimulationChunk(EGS_I64 nstart, EGS_I64 nrun, int npar, int nchunk)
Set the next simulation chunk to start at nstart and to consist of nrun particles.
virtual vector< EGS_Ensdf * > getRadionuclideEnsdf()
Get the radionuclide ENSDF object from the source.
virtual bool storeState(ostream &data_out) const
Store the source state into the stream data_out.
A class for storing information in a tree-like structure of key-value pairs. This class is used throu...
Definition: egs_input.h:182
An object factory.
static void deleteObject(EGS_Object *o)
Delete an object.
Base random number generator class. All random number generators should be derived from this class.
Definition: egs_rndm.h:67
A class for sampling random bins from a given probability distribution using the alias table techniqu...
A source collection.
EGS_Float * last_flu
Saved value of source_flu.
EGS_SimpleAliasTable * table
Alias table for randomly picking a source.
EGS_SourceCollection(const vector< EGS_BaseSource * > &S, const vector< EGS_Float > &prob, const string &Name="", EGS_ObjectFactory *f=0)
Constructor.
bool i_add
Set to true if parallel results have been combined.
EGS_Float Emax
Maximum energy (max of s[j]->getEmax()).
vector< EGS_I64 > * p_group
Vector of sources using the same base source.
EGS_BaseSource ** sources
The sources in the collection.
EGS_Float * p
The probabilities.
EGS_I64 count
Independent particles delivered.
EGS_I64 * last_cases
Last case returned from each source.
A class representing 3D vectors.
Definition: egs_vector.h:57
EGS_AliasTable class header file.
EGS_BaseSource class header file.
EGS_RandomGenerator class header file.
EGS_Vector methods for the manipulation of 3D vectors in cartesian co-ordinates.
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,...
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,...