EGSnrc C++ class library  Report PIRS-898 (2021)
Iwan Kawrakow, Ernesto Mainegra-Hing, Frederic Tessier, Reid Townson and Blake Walters
egs_conical_shell.cpp
Go to the documentation of this file.
1 /*
2 ###############################################################################
3 #
4 # EGSnrc egs++ conical shell shape
5 # Copyright (C) 2016 Randle E. P. Taylor, Rowan M. Thomson,
6 # Marc J. P. Chamberland, D. 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 # Hannah Gallop
31 #
32 ###############################################################################
33 #
34 # egs_conical_shell was developed for the Carleton Laboratory for
35 # Radiotherapy Physics.
36 #
37 ###############################################################################
38 */
39 
40 
46 #include "egs_conical_shell.h"
47 #include "egs_input.h"
48 #include "egs_functions.h"
49 #include <iostream>
50 #include <fstream>
51 
52 static bool EGS_CONICAL_SHELL_LOCAL inputSet = false;
53 static shared_ptr<EGS_BlockInput> EGS_CONICAL_SHELL_LOCAL shapeBlockInput = make_shared<EGS_BlockInput>("shape");
54 
55 CSSSLayer::CSSSLayer(EGS_Float t, EGS_Float rit, EGS_Float rot, EGS_Float rib, EGS_Float rob, EGS_Float z):
56  thick(t), ri_top(rit), ro_top(rot), ri_bot(rib), ro_bot(rob), zo(z) {
57 
58  ro_max = max(ro_top, ro_bot);
59  ro_min = min(ro_top, ro_bot);
60 
61  ri_max = max(ri_top, ri_bot);
62  ri_min = min(ri_top, ri_bot);
63 
64  o_slope = (ro_bot - ro_top)/thick;
65  i_slope = (ri_bot - ri_top)/thick;
66 
67  const_width = ((ro_bot - ri_bot) - (ro_top - ri_top)) < 1E-5;
68 
69  vout = M_PI/3.*(3*ro_max+thick*fabs(o_slope))*thick*thick*fabs(o_slope);
70  vout += M_PI*ro_min*ro_min*thick;
71 
72  vin = M_PI/3.*(3*ri_max+thick*fabs(i_slope))*thick*thick*fabs(i_slope);
73  vin += M_PI*ri_min*ri_min*thick;
74 
75  volume = vout - vin;
76 
77 }
78 
79 EGS_Vector CSSSLayer::getPoint(EGS_RandomGenerator *rndm) {
80 
81  EGS_Float r, z;
82 
83  if (const_width) {
84  getRZEqualWidth(rndm, r, z);
85  }
86  else {
87  getRZRejection(rndm, r, z);
88 
89  }
90 
91  EGS_Vector point = getPointInCircleAtZ(rndm, r, z);
92  point.z += zo;
93  return point;
94 }
95 
96 void CSSSLayer::getRZEqualWidth(EGS_RandomGenerator *rndm, EGS_Float &r, EGS_Float &z) {
97 
98  z = thick*(rndm->getUniform());
99  EGS_Float ri = getRiAtZ(z);
100  EGS_Float ro = getRoAtZ(z);
101  r = ri+(ro-ri)*sqrt(rndm->getUniform());
102 }
103 
104 void CSSSLayer::getRZRejection(EGS_RandomGenerator *rndm, EGS_Float &r, EGS_Float &z) {
105 
106  int count = 0;
107 
108  while (1) {
109  z = thick*(rndm->getUniform());
110  r = ri_min+(ro_max-ri_min)*rndm->getUniform();
111 
112  if (r <= getRoAtZ(z) && r >= getRiAtZ(z)) {
113  EGS_Vector point = getPointInCircleAtZ(rndm, r, z);
114  point.z += zo;
115  return;
116  }
117 
118  if (count++ > 1000) {
119  egsWarning("egs_conical_shell: Less than .1%% of random points are being accepted");
120  }
121 
122  }
123 
124 }
125 
126 
127 EGS_Vector CSSSLayer::getPointInCircleAtZ(EGS_RandomGenerator *rndm, EGS_Float r, EGS_Float z) {
128 
129  EGS_Float cphi, sphi;
130  rndm->getAzimuth(cphi,sphi);
131  return EGS_Vector(r*cphi, r*sphi, z);
132 
133 };
134 
135 EGS_Float CSSSLayer::getRoAtZ(EGS_Float z) {
136  return o_slope*z+ro_top;
137 }
138 
139 EGS_Float CSSSLayer::getRiAtZ(EGS_Float z) {
140  return i_slope*z+ri_top;
141 }
142 
143 
144 
147  EGS_BaseShape(Name, f), layer_sampler(0), xo(Xo) {
148  otype = "conicalShellStack";
149  total_thick = 0;
150 };
151 
154 
155  int lyr= layer_sampler->sample(rndm) ;
156  CSSSLayer *layer = layers[lyr];
157  EGS_Vector point = layer->getPoint(rndm);
158  return xo + point;
159 
160 };
161 
162 void EGS_ConicalShellStackShape::addLayer(EGS_Float thick,
163  EGS_Float ri_top, EGS_Float ro_top, EGS_Float ri_bot,EGS_Float ro_bot) {
164 
165  CSSSLayer *layer = new CSSSLayer(thick, ri_top, ro_top, ri_bot, ro_bot, total_thick);
166  layers.push_back(layer);
167  total_thick += thick;
168 
169  volumes.push_back(layer->volume);
170 
171  setLayerSampler();
172 
173 }
174 
175 
176 void EGS_ConicalShellStackShape::addLayer(EGS_Float thick, EGS_Float ri_bot,EGS_Float ro_bot) {
177 
178  EGS_Float ri_top = layers[layers.size()-1]->ri_bot;
179  EGS_Float ro_top = layers[layers.size()-1]->ro_bot;
180 
181  addLayer(thick, ri_top, ro_top, ri_bot, ro_bot);
182 
183 }
184 
185 void EGS_ConicalShellStackShape::setLayerSampler() {
186 
187  if (layer_sampler) {
188  delete layer_sampler;
189  }
190 
191  layer_sampler = new EGS_SimpleAliasTable(volumes.size(), &volumes[0]);
192 }
193 
194 
195 extern "C" {
196 
197  static void setInputs() {
198  inputSet = true;
199 
200  setShapeInputs(shapeBlockInput);
201  shapeBlockInput->getSingleInput("library")->setValues({"egs_conical_shell"});
202 
203  shapeBlockInput->addSingleInput("midpoint", false, "The midpoint of the conical shell, (x, y, z). Defaults to '0 0 0'.");
204 
205  auto blockPtr = shapeBlockInput->addBlockInput("layer");
206  blockPtr->addSingleInput("thickness", true, "The thickness of the layer");
207  blockPtr->addSingleInput("top radii", false, "1 (outer radius, inner radius assumed to be 0) or 2 (outer and inner radius) inputs, only required for top layer");
208  blockPtr->addSingleInput("bottom radii", true, "1 (outer radius, inner radius assumed to be 0) or 2 (outer and inner radius) inputs");
209  }
210 
211  EGS_CONICAL_SHELL_EXPORT string getExample() {
212  string example;
213  example = {
214  R"(
215  # Example of egs_conical_shell
216  #:start shape:
217  library = egs_conical_shell
218  midpoint = 0 0 -1
219  :start layer:
220  thickness = 0.5
221  top radii = 0 1
222  bottom radii = 0.5 2
223  :stop layer:
224  :start layer:
225  thickness = 0.5
226  bottom radii = 0.25 1
227  :stop layer:
228  :start layer:
229  thickness = 0.5
230  bottom radii = 0.5
231  :stop layer:
232  :start layer:
233  thickness = 0.5
234  bottom radii = 2
235  :stop layer:
236  :stop shape:
237 )"};
238  return example;
239  }
240 
241  EGS_CONICAL_SHELL_EXPORT shared_ptr<EGS_BlockInput> getInputs() {
242  if(!inputSet) {
243  setInputs();
244  }
245  return shapeBlockInput;
246  }
247 
248  EGS_CONICAL_SHELL_EXPORT EGS_BaseShape *createShape(EGS_Input *input, EGS_ObjectFactory *f) {
249 
250  if (!input) {
251  egsWarning("createShape(conicalShell): null input?\n");
252  return 0;
253  }
254 
255 
256  vector<EGS_Float> xo;
257  int err = input->getInput("midpoint", xo);
258  if (err || xo.size() != 3) {
259  xo.clear();
260  xo.push_back(0);
261  xo.push_back(0);
262  xo.push_back(0);
263  }
264 
265  EGS_ConicalShellStackShape *result = new EGS_ConicalShellStackShape(EGS_Vector(xo[0],xo[1],xo[2]));
266  result->setName(input);
267 
268  EGS_Input *layer;
269  int nl = 0;
270  while ((layer = input->takeInputItem("layer"))) {
271  vector<EGS_Float> rtop, rbot;
272  EGS_Float thick;
273  err = layer->getInput("thickness", thick);
274  if (err) {
275  egsWarning(
276  "createShape(EGS_ConicalShellStackShape): missing 'thickness'"
277  " input for layer %d\n --> layer ignored\n", nl
278  );
279  }
280  else {
281 
282  err = layer->getInput("top radii",rtop);
283  if (err && nl==0) {
284  egsWarning("createGeometry(EGS_ConeStack): missing 'top radii' input for 1st layer\n");
285  }
286  else {
287  err=0;
288  }
289 
290  int err1 = layer->getInput("bottom radii",rbot);
291  if (err1) {
292  egsWarning("createGeometry(EGS_ConeStack): missing 'bottom radii' input for layer %d\n",nl);
293  }
294  if (err || err1) {
295  egsWarning(" --> layer ignored\n");
296  }
297  else {
298 
299  EGS_Float rit, rot, rib, rob;
300  if (rbot.size() < 2) {
301  rib = 0;
302  rob = rbot[0];
303  }
304  else {
305  rib = rbot[0];
306  rob = rbot[1];
307  }
308 
309  if (rtop.size() == 0) {
310  result->addLayer(thick, rib, rob);
311  }
312  else if (rtop.size() < 2) {
313  rit = 0;
314  rot = rtop[0];
315  result->addLayer(thick, rit, rot, rib, rob);
316  }
317  else {
318  rit = rtop[0];
319  rot = rtop[1];
320  result->addLayer(thick, rit, rot, rib, rob);
321  }
322  }
323  }
324  delete layer;
325  ++nl;
326  }
327 
328  return result;
329  }
330 
331 }
Base shape class. All shapes in the EGSnrc C++ class library are derived from EGS_BaseShape.
Definition: egs_shapes.h:145
EGS_ConicalShellStackShape(const EGS_Vector &Xo, const string &Name="", EGS_ObjectFactory *f=0)
Construct a sphere of radius r with midpoint Xo.
EGS_Vector getPoint(EGS_RandomGenerator *rndm)
Returns a random point within the conical shell.
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
An object factory.
void setName(EGS_Input *inp)
Set the name of the object from the information provided by inp.
string otype
The object type.
Base random number generator class. All random number generators should be derived from this class.
Definition: egs_rndm.h:90
void getAzimuth(EGS_Float &cphi, EGS_Float &sphi)
Sets cphi and sphi to the cosine and sine of a random angle uniformely distributed between 0 and .
Definition: egs_rndm.h:161
EGS_Float getUniform()
Returns a random number uniformly distributed between zero (inclusive) and 1 (exclusive).
Definition: egs_rndm.h:126
A class for sampling random bins from a given probability distribution using the alias table techniqu...
int sample(EGS_RandomGenerator *rndm) const
Sample a random bin.
A class representing 3D vectors.
Definition: egs_vector.h:57
EGS_Float z
z-component
Definition: egs_vector.h:63
a conical stack shell shape
Global egspp functions header file.
EGS_Input class header file.
EGS_InfoFunction EGS_EXPORT egsWarning
Always use this function for reporting warnings.
A conical shell shape.