EGSnrc C++ class library  Report PIRS-898 (2021)
Iwan Kawrakow, Ernesto Mainegra-Hing, Frederic Tessier, Reid Townson and Blake Walters
egs_isotropic_source.cpp
Go to the documentation of this file.
1 /*
2 ###############################################################################
3 #
4 # EGSnrc egs++ isotropic 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: Long Zhang
27 # Hubert Ho
28 # Randle Taylor
29 # Marc Chamberland
30 # Ernesto Mainegra-Hing
31 # Reid Townson
32 #
33 ###############################################################################
34 */
35 
36 
42 #include "egs_isotropic_source.h"
43 #include "egs_input.h"
44 #include "egs_math.h"
45 
46 static string EGS_ISOTROPIC_SOURCE_LOCAL typeStr("egs_isotropic_source");
47 static bool EGS_ISOTROPIC_SOURCE_LOCAL inputSet = false;
48 
50  EGS_ObjectFactory *f) : EGS_BaseSimpleSource(input,f), shape(0), geom(0),
51  regions(0), min_theta(0), max_theta(M_PI), min_phi(0), max_phi(2*M_PI),
52  nrs(0), gc(IncludeAll), media(0), nms(0), gcm(IncludeSelected) {
53  vector<EGS_Float> pos;
54  EGS_Input *ishape = input->takeInputItem("shape");
55  if (ishape) {
57  delete ishape;
58  }
59  if (!shape) {
60  string sname;
61  int err = input->getInput("shape name",sname);
62  if (err)
63  egsWarning("EGS_IsotropicSource: missing/wrong inline shape "
64  "definition and missing wrong 'shape name' input\n");
65  else {
67  if (!shape) egsWarning("EGS_IsotropicSource: a shape named %s"
68  " does not exist\n");
69  }
70  }
71  string geom_name;
72  int err = input->getInput("geometry",geom_name);
73  if (!err) {
74  geom = EGS_BaseGeometry::getGeometry(geom_name);
75  if (!geom) egsWarning("EGS_IsotropicSource: no geometry named %s\n",
76  geom_name.c_str());
77  else {
78  // Filter by region
79  vector<string> reg_options;
80  reg_options.push_back("IncludeAll");
81  reg_options.push_back("ExcludeAll");
82  reg_options.push_back("IncludeSelected");
83  reg_options.push_back("ExcludeSelected");
84  gc = (GeometryConfinement) input->getInput("region selection",reg_options,0);
85  if (gc == IncludeSelected || gc == ExcludeSelected) {
86  vector<int> regs;
87  err = input->getInput("selected regions",regs);
88  if (err || regs.size() < 1) {
89  egsWarning("EGS_IsotropicSource: region selection %d used "
90  "but no 'selected regions' input found\n",gc);
91  gc = gc == IncludeSelected ? IncludeAll : ExcludeAll;
92  egsWarning(" using %d\n",gc);
93  }
94  nrs = regs.size();
95  regions = new int [nrs];
96  for (int j=0; j<nrs; j++) {
97  regions[j] = regs[j];
98  }
99  }
100 
101  // Filter by medium
102  gcm = (GeometryConfinement) input->getInput("medium selection",reg_options,0);
103  if (gcm == IncludeSelected || gcm == ExcludeSelected) {
104  vector<string> selectedMedia;
105  err = input->getInput("selected media",selectedMedia);
106  if (err || selectedMedia.size() < 1) {
107  egsWarning("EGS_IsotropicSource: medium selection %d used "
108  "but no 'selected media' input found\n",gcm);
109  }
110  nms = selectedMedia.size();
111  media = new int [nms];
112  for (int j=0; j<nms; j++) {
113  int mediaID = geom->getMediumIndex(selectedMedia[j]);
114  media[j] = mediaID;
115  }
116  }
117  }
118  }
119  EGS_Float tmp_angle;
120  err = input->getInput("min theta", tmp_angle);
121  if (!err) {
122  min_theta = tmp_angle/180.0*M_PI;
123  }
124 
125  err = input->getInput("max theta", tmp_angle);
126  if (!err) {
127  max_theta = tmp_angle/180.0*M_PI;
128  }
129 
130  if (min_theta > max_theta) {
131  egsFatal("EGS_IsotropicSource: max theta must be greater than min theta (theta ranges from 0 to 180 degrees).\n");
132  }
133 
134  err = input->getInput("min phi", tmp_angle);
135  if (!err) {
136  min_phi = tmp_angle/180.0*M_PI;
137  }
138 
139  err = input->getInput("max phi", tmp_angle);
140  if (!err) {
141  max_phi = tmp_angle/180.0*M_PI;
142  }
143 
144  if (min_phi > max_phi) {
145  egsFatal("EGS_IsotropicSource: max phi must be greater than min phi. To collimate across the 0/360 degree boundary (e.g. from 300 degrees to 60 degrees), set max phi greater than 360 (e.g. min phi = 300, max phi = 420).\n");
146  }
147 
148  buf_1 = cos(min_theta);
149  buf_2 = cos(max_theta);
150 
151  setUp();
152 }
153 
154 void EGS_IsotropicSource::setUp() {
155  otype = "EGS_IsotropicSource";
156  if (!isValid()) {
157  description = "Invalid isotropic source";
158  }
159  else {
160  description = "Isotropic source from a shape of type ";
162  description += " with ";
163  description += s->getType();
164  if (q == -1) {
165  description += ", electrons";
166  }
167  else if (q == 0) {
168  description += ", photons";
169  }
170  else if (q == 1) {
171  description += ", positrons";
172  }
173  else {
174  description += ", unknown particle type";
175  }
176 
177  if (geom) {
178  geom->ref();
179 
180  description += "\n\n";
181  description += " Filtered by regions using option: " + std::to_string(gc);
182 
183  if (nms > 0) {
184  description += "\n\n";
185  description += " Filtered by media using option: " + std::to_string(gcm);
186  description += "\n";
187  description += " Media:";
188  for (auto i=0; i<nms; ++i) {
189  string mediumName = geom->getMediumName(media[i]);
190  description += " " + mediumName + "(" + std::to_string(media[i]) + ")";
191  }
192 
193  description += "\n\n Regions are only included if they match both the region filter and the medium filter.";
194  }
195 
196 
197  }
198  }
199 }
200 
201 extern "C" {
202 
203  static void setInputs() {
204  inputSet = true;
205 
206  setBaseSourceInputs();
207 
208  srcBlockInput->getSingleInput("library")->setValues(vector<string>(1, typeStr));
209 
210  auto shapePtr = srcBlockInput->addBlockInput("shape");
211  /* Commented out because I don't think this input is used
212  Also at this point dependency of a block on an input hasn't been implemented
213  auto shapeNamePtr = srcBlockInput->addSingleInput("shape name", false, "...");
214  shapeNamePtr->addDependency(shapePtr, true);
215  shapePtr->addDependency(shapeNamePtr, true);*/
216 
217  setShapeInputs(shapePtr);
218 
219  auto geomPtr = srcBlockInput->addSingleInput("geometry", false, "The name of a geometry, used for complex source shapes. Only particles generated inside the geometry or some of its regions are used.");
220  auto regPtr = srcBlockInput->addSingleInput("region selection", false, "Include or exclude regions from the named geometry, to define a volume for source particle generation.", {"IncludeAll", "ExcludeAll","IncludeSelected","ExcludeSelected"});
221  regPtr->addDependency(geomPtr);
222  auto selPtr = srcBlockInput->addSingleInput("selected regions", false, "If region selection = IncludeSelected or ExcludeSelected, then this is a list of the regions in the named geometry to include or exclude.");
223  selPtr->addDependency(regPtr, "IncludeSelected");
224  selPtr->addDependency(regPtr, "ExcludeSelected");
225  srcBlockInput->addSingleInput("min theta", false, "The minimum theta angle in degrees, to restrict the directions of source particles. Defaults to 0.");
226  srcBlockInput->addSingleInput("max theta", false, "The maximum theta angle in degrees, to restrict the directions of source particles. Defaults to 180.");
227  srcBlockInput->addSingleInput("min phi", false, "The minimum phi angle in degrees, to restrict the directions of source particles. Defaults to 0.");
228  srcBlockInput->addSingleInput("max phi", false, "The maximum phi angle in degrees, to restrict the directions of source particles. Defaults to 360.");
229  }
230 
231  EGS_ISOTROPIC_SOURCE_EXPORT string getExample() {
232  string example {
233  R"(
234  :start source:
235  name = my_source
236  library = egs_isotropic_source
237  charge = 0
238  geometry = my_envelope
239  region selection = IncludeSelected
240  selected regions = 1 2
241  :start shape:
242  type = box
243  box size = 1 2 3
244  :start media input:
245  media = H2O521ICRU
246  :stop media input:
247  :stop shape:
248  :start spectrum:
249  type = monoenergetic
250  energy = 1
251  :stop spectrum:
252  :stop source:
253 )"};
254  return example;
255  }
256 
257  EGS_ISOTROPIC_SOURCE_EXPORT shared_ptr<EGS_BlockInput> getInputs() {
258  if(!inputSet) {
259  setInputs();
260  }
261  return srcBlockInput;
262  }
263 
264  EGS_ISOTROPIC_SOURCE_EXPORT EGS_BaseSource *createSource(EGS_Input *input,
265  EGS_ObjectFactory *f) {
266  return
267  createSourceTemplate<EGS_IsotropicSource>(input,f,"isotropic source");
268  }
269 
270 }
int ref()
Increase the reference count to this geometry.
static EGS_BaseGeometry * getGeometry(const string &Name)
Get a pointer to the geometry named Name.
static int getMediumIndex(const string &medname)
Get the index of a medium named medname.
static const char * getMediumName(int ind)
Get the name of medium with index ind.
static EGS_BaseShape * getShape(const string &Name)
Get a pointer to the shape named Name.
Definition: egs_shapes.cpp:64
static EGS_BaseShape * createShape(EGS_Input *inp)
Create a shape from the information pointed to by inp.
Definition: egs_shapes.cpp:51
Base class for 'simple' particle sources.
int q
The charge of this simple source.
EGS_BaseSpectrum * s
The energy spectrum of this source.
Base source class. All particle sources must be derived from this class.
string description
A short source description.
const string & getType() const
Get the spectrum type.
A class for storing information in a tree-like structure of key-value pairs. This class is used throu...
Definition: egs_input.h:182
EGS_Input * takeInputItem(const string &key, bool self=true)
Get the property named key.
Definition: egs_input.cpp:229
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:341
EGS_BaseShape * shape
The shape from which particles are emitted.
EGS_IsotropicSource(int Q, EGS_BaseSpectrum *Spec, EGS_BaseShape *Shape, EGS_BaseGeometry *geometry, const string &Name="", EGS_ObjectFactory *f=0)
Constructor.
GeometryConfinement
Geometry confinement options.
EGS_Float min_phi
avoid multi-calculating cos(min_theta) and cos(max_theta)
An object factory.
string otype
The object type.
const string & getObjectType() const
Get the object type.
EGS_Input class header file.
An isotropic source.
Attempts to fix broken math header files.
EGS_InfoFunction EGS_EXPORT egsFatal
Always use this function for reporting fatal errors.
EGS_InfoFunction EGS_EXPORT egsWarning
Always use this function for reporting warnings.