EGSnrc C++ class library  Report PIRS-898 (2021)
Iwan Kawrakow, Ernesto Mainegra-Hing, Frederic Tessier, Reid Townson and Blake Walters
egs_rz.cpp
Go to the documentation of this file.
1 /*
2 ###############################################################################
3 #
4 # EGSnrc egs++ rz geometry
5 # Copyright (C) 2016 Randle E. P. Taylor, Rowan M. Thomson,
6 # Marc J. P. Chamberland, Dave W. O. Rogers
7 #
8 # This file is part of EGSnrc.
9 #
10 # EGSnrc is free software: you can redistribute it and/or modify it under
11 # the terms of the GNU Affero General Public License as published by the
12 # Free Software Foundation, either version 3 of the License, or (at your
13 # option) any later version.
14 #
15 # EGSnrc is distributed in the hope that it will be useful, but WITHOUT ANY
16 # WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS
17 # FOR A PARTICULAR PURPOSE. See the GNU Affero General Public License for
18 # more details.
19 #
20 # You should have received a copy of the GNU Affero General Public License
21 # along with EGSnrc. If not, see <http://www.gnu.org/licenses/>.
22 #
23 ###############################################################################
24 #
25 # Author: Randle Taylor, 2016
26 #
27 # Contributors: Marc Chamberland
28 # Rowan Thomson
29 # Dave Rogers
30 # Martin Martinov
31 # Hannah Gallop
32 #
33 ###############################################################################
34 #
35 # egs_rz was developed for the Carleton Laboratory for Radiotherapy Physics.
36 #
37 ###############################################################################
38 */
39 
40 
46 #include <map>
47 #include "egs_input.h"
48 #include "egs_rz.h"
49 #include "../egs_cylinders/egs_cylinders.h"
50 #include "../egs_planes/egs_planes.h"
51 
52 static bool EGS_RZ_LOCAL inputSet = false;
53 
54 string EGS_RZGeometry::RZType = "EGS_RZ";
55 
56 EGS_RZGeometry::EGS_RZGeometry(vector<EGS_BaseGeometry *> geoms,
57  vector<EGS_Float> rads, vector<EGS_Float> zbs, const string &name) :
58  EGS_NDGeometry(geoms, name), radii(rads), zbounds(zbs) {
59 
60  /* we always set inner most radii to 0 (simplifies volume calcs) */
61  if (radii[0] != 0) {
62  radii.insert(radii.begin(), 0.);
63  }
64 
65  vector<EGS_Float> vol;
66  for (size_t r=0; r < radii.size()-1; r++) {
67 
68  EGS_Float rmin = radii[r];
69  EGS_Float rmax = radii[r+1];
70 
71  EGS_Float area = M_PI*(rmax*rmax - rmin*rmin);
72 
73  for (size_t plane = 0; plane < zbounds.size()-1; plane++) {
74  EGS_Float zmin = zbounds[plane];
75  EGS_Float zmax = zbounds[plane+1];
76  reg_vol.push_back((zmax-zmin)*area);
77  }
78  }
79 
80 };
81 
82 EGS_Float EGS_RZGeometry::getBound(int idir, int ind) {
83  if (idir == ZDIR && ind >= 0 && ind < (int)zbounds.size()) {
84  return zbounds[ind];
85  }
86  else if (idir == RDIR && ind >= 0 && ind < (int)radii.size()) {
87  return radii[ind];
88  }
89  return 0.;
90 }
91 
92 
94  if (dir == ZDIR) {
95  return zbounds.size() - 1;
96  }
97  else if (dir == RDIR) {
98  return radii.size() - 1;
99  }
100  return 0;
101 }
102 
103 EGS_Float EGS_RZGeometry::getVolume(int ireg) {
104  if (ireg < 0 || ireg >= nreg) {
105  return -1;
106  }
107  return reg_vol[ireg];
108 }
109 
110 
111 /* Initialization helpers for EGS_RZ */
112 namespace egs_rz {
113 
114 vector<EGS_Float> getRadiiByShells(EGS_Input *input) {
115 
116  vector<EGS_Float> radii;
117 
118  vector<int> nshells;
119  int err = input->getInput("number of shells", nshells);
120  if (err) {
121  return radii;
122  }
123 
124  vector<EGS_Float> thick;
125  err = input->getInput("shell thickness", thick);
126  if (err) {
127  return radii;
128  }
129 
130  EGS_Float cur_r = 0;
131  for (size_t shell_group=0; shell_group < min(thick.size(), nshells.size()); shell_group++) {
132 
133  for (int shell = 0; shell < nshells[shell_group]; shell++) {
134  cur_r += thick[shell_group];
135  radii.push_back(cur_r);
136 
137  }
138  }
139 
140  return radii;
141 
142 }
143 
144 vector<EGS_Float> getRadii(EGS_Input *input) {
145 
146  vector<EGS_Float> radii;
147  int err = input->getInput("radii", radii);
148  if (err) {
149  /* no explicit radii input so assume user will be specifying using shells */
150  radii = getRadiiByShells(input);
151  }
152 
153  return radii;
154 
155 }
156 
157 
158 vector<EGS_Float> EGS_RZ_LOCAL getZPlanesBySlabs(EGS_Input *input) {
159 
160  vector<EGS_Float> zplanes;
161 
162  EGS_Float zo = 0;
163 
164  int err = input->getInput("first plane", zo);
165  if (err) {
166  egsWarning("RZ: missing 'first plane' input. Assuming zo=0");
167  zo = 0;
168  }
169 
170  vector<int> nslabs;
171  err = input->getInput("number of slabs", nslabs);
172  if (err) {
173  return zplanes;
174  }
175 
176  vector<EGS_Float> thick;
177  err = input->getInput("slab thickness", thick);
178  if (err) {
179  return zplanes;
180  }
181 
182  EGS_Float cur_z = zo;
183  zplanes.push_back(zo);
184  for (size_t slab_group=0; slab_group < min(thick.size(), nslabs.size()); slab_group++) {
185 
186  for (int slab = 0; slab < nslabs[slab_group]; slab++) {
187  cur_z += thick[slab_group];
188  zplanes.push_back(cur_z);
189  }
190  }
191 
192  return zplanes;
193 
194 }
195 
196 vector<EGS_Float> EGS_RZ_LOCAL getZPlanes(EGS_Input *input) {
197 
198  vector<EGS_Float> zplanes;
199  int err = input->getInput("z-planes", zplanes);
200  if (err) {
201  zplanes = getZPlanesBySlabs(input);
202  }
203 
204  return zplanes;
205 
206 }
207 
208 bool allIncreasing(vector<EGS_Float> vec) {
209 
210  if (vec.size() == 0) {
211  return true;
212  }
213 
214  EGS_Float last = vec[0];
215  for (size_t i=1; i < vec.size(); i++) {
216  if (vec[i] <= last) {
217  return false;
218  }
219  last = vec[i];
220  }
221 
222  return true;
223 
224 }
225 
226 
227 };
228 
229 extern "C" {
230 
231  static void setInputs() {
232  inputSet = true;
233 
234  setBaseGeometryInputs();
235 
236  geomBlockInput->getSingleInput("library")->setValues({"egs_rz"});
237 
238  // Format: name, isRequired, description, vector string of allowed values
239  auto radPtr = geomBlockInput->addSingleInput("radii", false, "A list of radii, must be in increasing order");
240  auto planePtr = geomBlockInput->addSingleInput("z-planes", false, "Input for z-planes");
241 
242  // Or can define using slabs and shells
243  auto num_shellPtr = geomBlockInput->addSingleInput("number of shells", false, "A list of the number of shells");
244  auto shellPtr = geomBlockInput->addSingleInput("shell thickness", false, "A list of shell thicknesses");
245  auto firstPtr = geomBlockInput->addSingleInput("first plane", false, "The z position of the first plane, when listing a number of slabs");
246  auto num_slabPtr = geomBlockInput->addSingleInput("number of slabs", false, "A list of the number of slabs");
247  auto slabPtr = geomBlockInput->addSingleInput("slab thickness", false, "A list of the slab thicknesses");
248 
249  // Can only use one method
250  radPtr->addDependency(num_shellPtr, "", true);
251  radPtr->addDependency(shellPtr, "", true);
252  radPtr->addDependency(firstPtr, "", true);
253  radPtr->addDependency(num_slabPtr, "", true);
254  radPtr->addDependency(slabPtr, "", true);
255  planePtr->addDependency(num_shellPtr, "", true);
256  planePtr->addDependency(shellPtr, "", true);
257  planePtr->addDependency(firstPtr, "", true);
258  planePtr->addDependency(num_slabPtr, "", true);
259  planePtr->addDependency(slabPtr, "", true);
260  num_shellPtr->addDependency(radPtr, "", true);
261  num_shellPtr->addDependency(planePtr, "", true);
262  shellPtr->addDependency(radPtr, "", true);
263  shellPtr->addDependency(planePtr, "", true);
264  firstPtr->addDependency(radPtr, "", true);
265  firstPtr->addDependency(planePtr, "", true);
266  num_slabPtr->addDependency(radPtr, "", true);
267  num_slabPtr->addDependency(planePtr, "", true);
268  slabPtr->addDependency(radPtr, "", true);
269  slabPtr->addDependency(planePtr, "", true);
270  }
271 
272  EGS_RZ_EXPORT string getExample() {
273  string example;
274  example = {
275  R"(
276  # Example of egs_rz
277  :start geometry:
278  name = my_rz
279  library = egs_rz
280  radii = 1 2 3
281  z-planes= -4 -3 -2 -1 0 1 2 3 4
282  :start media input:
283  media = water
284  :stop media input:
285  :stop geometry:
286 )"};
287  return example;
288  }
289 
290  EGS_RZ_EXPORT shared_ptr<EGS_BlockInput> getInputs() {
291  if(!inputSet) {
292  setInputs();
293  }
294  return geomBlockInput;
295  }
296 
297  EGS_RZ_EXPORT EGS_BaseGeometry *createGeometry(EGS_Input *input) {
298 
299  if (!input) {
300  egsWarning("createGeometry(egs_rz): null input?\n");
301  return 0;
302  }
303 
304  vector<EGS_Float> radii = egs_rz::getRadii(input);
305  if (radii.size() == 0) {
306  egsWarning("createGeometry(rz): wrong/missing radii inputs\n");
307  return 0;
308  }
309  if (!egs_rz::allIncreasing(radii)) {
310  egsWarning("createGeometry(rz): radii must be monotonically increasing\n");
311  return 0;
312  }
313 
314  vector<EGS_Float> zplanes = egs_rz::getZPlanes(input);
315  if (zplanes.size() == 0) {
316  egsWarning("createGeometry(rz): wrong/missing z plane inputs\n");
317  return 0;
318  }
319 
321  EGS_PlanesZ *planes = new EGS_PlanesZ(zplanes, EGS_BaseGeometry::getUniqueName(), EGS_ZProjector("z-planes"));
322 
323  vector<EGS_BaseGeometry *> rz_geoms;
324  rz_geoms.push_back(planes);
325  rz_geoms.push_back(cyl);
326 
327  EGS_BaseGeometry *rz = new EGS_RZGeometry(rz_geoms, radii, zplanes);
328 
329  if (!rz) {
330  egsWarning("createGeometry(rz): failed to create nd geometry\n");
331  return 0;
332  }
333 
334  rz->setName(input);
335  rz->setMedia(input);
336  rz->setLabels(input);
337 
338  return rz;
339 
340  }
341 
342 }
Base geometry class. Every geometry class must be derived from EGS_BaseGeometry.
void setMedia(EGS_Input *inp)
Set the media in the geometry from the input pointed to by inp.
int nreg
Number of local regions in this geometry.
void setName(EGS_Input *inp)
Set the name of the geometry from the input inp.
static string getUniqueName()
Get a unique geometry name.
int setLabels(EGS_Input *input)
Set the labels from an input block.
A set of concentric cylinders.
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:341
A class modeling a N-dimensional geometry.
A set of parallel planes.
Definition: egs_planes.h:167
a subclass of EGS_NDGeometry for conveniently defining an RZ geometry
Definition: egs_rz.h:116
EGS_Float getBound(int idir, int ind)
get RZ boundary for a given direction and directional index
Definition: egs_rz.cpp:82
EGS_Float getVolume(int ireg)
get mass of a given region
Definition: egs_rz.cpp:103
EGS_RZGeometry(vector< EGS_BaseGeometry * > geoms, vector< EGS_Float > rads, vector< EGS_Float > zbs, const string &name="")
RZ geometry constructor.
Definition: egs_rz.cpp:56
int getNRegDir(int dir)
get number of regions in a given direction
Definition: egs_rz.cpp:93
A class representing 3D vectors.
Definition: egs_vector.h:57
A projector into the z-plane.
EGS_GLIB_EXPORT EGS_BaseGeometry * createGeometry(EGS_Input *input)
Definition: egs_glib.cpp:84
EGS_Input class header file.
An egs_nd_geometry wrapper to simplify RZ geometry creation.
EGS_InfoFunction EGS_EXPORT egsWarning
Always use this function for reporting warnings.