EGSnrc C++ class library  Report PIRS-898 (2021)
Iwan Kawrakow, Ernesto Mainegra-Hing, Frederic Tessier, Reid Townson and Blake Walters
egs_cones.cpp
Go to the documentation of this file.
1 /*
2 ###############################################################################
3 #
4 # EGSnrc egs++ cones geometry
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: Frederic Tessier
27 # Marc Chamberland
28 # Randle Taylor
29 # Ernesto Mainegra-Hing
30 #
31 ###############################################################################
32 */
33 
34 
40 #include "egs_cones.h"
41 #include "egs_input.h"
42 
43 #include <vector>
44 using std::vector;
45 
46 #ifndef M_PI
47  #define M_PI 3.14159265358979323846
48 #endif
49 
50 string EGS_SimpleCone::type = "EGS_SimpleCone";
51 string EGS_ParallelCones::type = "EGS_ParallelCones";
52 string EGS_ConeSet::type = "EGS_ConeSet";
53 string EGS_ConeStack::type = "EGS_ConeStack";
54 
55 void EGS_ConeStack::clear(bool all) {
56  if (nltot > 0) {
57  if (all) {
58  for (int j=0; j<nl; j++) {
59  for (int i=0; i<nr[j]; i++)
60  if (!cones[j][i]->deref()) {
61  delete cones[j][i];
62  }
63  delete [] cones[j];
64  }
65  nl = 0;
66  }
67  delete [] cones;
68  delete [] pos;
69  delete [] nr;
70  delete [] flag;
71  nltot = 0;
72  }
73 }
74 
75 #define N_CS_GROW 50
76 void EGS_ConeStack::resize() {
77  int nnew = nltot + N_CS_GROW;
78  int *new_nr = new int [nnew], *new_flag = new int [nnew];
79  EGS_Float *new_pos = new EGS_Float [nnew+1];
80  EGS_SimpleCone ***new_cones = new EGS_SimpleCone **[nnew];
81  for (int j=0; j<nl; j++) {
82  new_nr[j] = nr[j];
83  new_flag[j] = flag[j];
84  new_pos[j] = pos[j];
85  new_cones[j] = cones[j];
86  }
87  if (nl > 0) {
88  new_pos[nl] = pos[nl];
89  }
90  clear(false);
91  nr = new_nr;
92  pos = new_pos;
93  flag = new_flag;
94  cones = new_cones;
95  nltot = nnew;
96 }
97 
98 void EGS_ConeStack::addLayer(EGS_Float thick, const vector<EGS_Float> &rtop,
99  const vector<EGS_Float> &rbottom,
100  const vector<string> &med_names) {
101  int this_nr = rbottom.size();
102  if (!this_nr) {
103  egsWarning("EGS_ConeStack::addLayer: no bottom radii?\n");
104  egsWarning(" --> ignoring layer\n");
105  return;
106  }
107  if ((int)med_names.size() != this_nr) {
108  egsWarning("EGS_ConeStack::addLayer: number of cone radii (%d) is"
109  " different from number of media (%d)\n",this_nr,med_names.size());
110  egsWarning(" --> ignoting layer\n");
111  return;
112  }
113  bool same_radii = false;
114  if (rtop.size() != rbottom.size()) {
115  if (!rtop.size()) {
116  if (!nl) {
117  egsWarning("EGS_ConeStack::addLayer: zero top radii does not"
118  " work for the first layer\n");
119  egsWarning(" --> ignoting layer\n");
120  return;
121  }
122  same_radii = true;
123  }
124  else {
125  egsWarning("EGS_ConeStack::addLayer: number of bottom radii (%d)"
126  " is different from number of top radii (%d)\n",this_nr,
127  rtop.size());
128  egsWarning(" --> ignoting layer\n");
129  return;
130  }
131  }
132  if (nl >= nltot) {
133  resize();
134  }
135  if (!nl) {
136  pos[nl] = xo*a;
137  Rout = rbottom[this_nr-1];
138  Rout2 = Rout*Rout;
139  if (fabs(rtop[this_nr-1]-Rout) > boundaryTolerance) {
140  same_Rout = false;
141  is_convex = false;
142  }
143  }
144 
145  cones[nl] = new EGS_SimpleCone * [this_nr];
146  nr[nl] = this_nr;
147  pos[nl+1] = pos[nl] + thick;
148  EGS_Vector x(xo+a*(pos[nl]-pos[0]));
149  //egsInformation(" layer %d x = (%g,%g,%g)\n",nl,x.x,x.y,x.z);
150  for (int ir=0; ir<this_nr; ir++) {
151  EGS_Float Rtop = same_radii ? cones[nl-1][ir]->getRadius(x) : rtop[ir];
152  cones[nl][ir] = new EGS_SimpleCone(x,a,thick,Rtop,rbottom[ir]);
153  cones[nl][ir]->setMedium(med_names[ir]);
154  cones[nl][ir]->ref();
155  if (ir == this_nr-1) {
156  if (fabs(rbottom[this_nr-1]-Rout) > boundaryTolerance) {
157  same_Rout = false;
158  is_convex = false;
159  }
160  if (fabs(Rtop-Rout) > boundaryTolerance) {
161  same_Rout = false;
162  is_convex = false;
163  }
164  }
165  }
166  if (same_radii) {
167  flag[nl-1] += 2;
168  flag[nl] = 1;
169  }
170  else {
171  flag[nl] = 0;
172  }
173  if (this_nr > nmax) {
174  nmax = this_nr;
175  }
176  ++nl;
177  nreg = nl*nmax;
178  //egsInformation("addLayer: the following layers are defined:\n");
179  //for(int j=0; j<nl; j++) egsInformation(" %g %g %d %d\n",pos[j],pos[j+1],
180  // nr[j],flag[j]);
181 }
182 
183 void EGS_ConeStack::printInfo() const {
185  egsInformation("number of layers: %d\n",nl);
186  for (int il=0; il<nl; il++) {
187  egsInformation("*** layer %d: top = %g bottom = %g\n",il,
188  pos[il],pos[il+1]);
189  egsInformation(" top radii: ");
190  int i;
191  EGS_Vector x(xo+a*(pos[il]-pos[0]));
192  for (i=0; i<nr[il]; i++) {
193  egsInformation("%g ",cones[il][i]->getRadius(x));
194  }
195  egsInformation("\n bottom radii: ");
196  x = xo + a*(pos[il+1]-pos[0]);
197  for (i=0; i<nr[il]; i++) {
198  egsInformation("%g ",cones[il][i]->getRadius(x));
199  }
200  egsInformation("\n media: ");
201  for (i=0; i<nr[il]; i++) {
202  egsInformation("%d ",cones[il][i]->medium(0));
203  }
204  egsInformation("\n");
205  }
206  egsInformation("=====================================================\n");
207 }
208 
209 void EGS_SimpleCone::printInfo() const {
211  egsInformation(" cone apex = (%g,%g,%g)\n",xo.x,xo.y,xo.z);
212  egsInformation(" cone axis = (%g,%g,%g)\n",a.x,a.y,a.z);
213  egsInformation(" opening angle = %g degrees\n",180*atan(gamma)/M_PI);
214  if (open) {
215  egsInformation(" cone is open\n");
216  }
217  else {
218  egsInformation(" cone height %g\n",-d1);
219  }
220  egsInformation("=====================================================\n");
221 }
222 
223 void EGS_ParallelCones::printInfo() const {
225  egsInformation(" cone axis = (%g,%g,%g)\n",a.x,a.y,a.z);
226  egsInformation(" opening angle = %g degrees\n",180*atan(gamma)/M_PI);
227  egsInformation(" number of cones = %d\n",nc);
228  egsInformation(" cone apexes:\n ");
229  for (int j=0; j<nc; j++) {
230  egsInformation("(%g,%g,%g) ",xo[j].x,xo[j].y,xo[j].z);
231  }
232  egsInformation("\n=====================================================\n");
233 }
234 
235 void EGS_ConeSet::printInfo() const {
237  egsInformation(" cone apex = (%g,%g,%g)\n",xo.x,xo.y,xo.z);
238  egsInformation(" cone axis = (%g,%g,%g)\n",a.x,a.y,a.z);
239  egsInformation(" flag = %d\n",flag);
240  egsInformation(" opening angles (degrees)=\n ");
241  for (int j=0; j<nc; j++) {
242  egsInformation("%g ",180*atan(gamma[j])/M_PI);
243  }
244  egsInformation("\n=====================================================\n");
245 }
246 
247 
248 extern "C" {
249 
250  EGS_CONES_EXPORT EGS_BaseGeometry *createGeometry(EGS_Input *input) {
251 
252  if (!input) {
253  egsWarning("createGeometry(cones): null input?\n");
254  return 0;
255  }
256  string type;
257  int err = input->getInput("type",type);
258  if (err) {
259  egsWarning("createGeometry(cones): object type not specified\n");
260  return 0;
261  }
262  if (type == "EGS_ConeStack") {
263  vector<EGS_Float> axis;
264  err = input->getInput("axis",axis);
265  if (err) {
266  egsWarning("createGeometry(EGS_ConeStack): no axis input\n");
267  return 0;
268  }
269  if (axis.size() != 6) {
270  egsWarning("createGeometry(EGS_ConeStack): wrong axis input"
271  " (expecting 6 instead of %d inputs)\n",axis.size());
272  return 0;
273  }
274  EGS_ConeStack *g = new EGS_ConeStack(
275  EGS_Vector(axis[0],axis[1],axis[2]),
276  EGS_Vector(axis[3],axis[4],axis[5]),"");
277  EGS_Input *layer;
278  int nl = 0;
279  vector<int> layerLabels;
280  while ((layer = input->takeInputItem("layer"))) {
281  vector<EGS_Float> rtop, rbottom;
282  vector<string> media;
283  EGS_Float thickness;
284  err = layer->getInput("thickness",thickness);
285  if (err)
286  egsWarning("createGeometry(EGS_ConeStack): missing 'thickness'"
287  " input for layer %d\n --> layer ignored\n",nl);
288  else {
289  err = layer->getInput("top radii",rtop);
290  err = layer->getInput("bottom radii",rbottom);
291  if (err) egsWarning("createGeometry(EGS_ConeStack): missing "
292  "'bottom radii' input for layer %d\n",nl);
293  int err1 = layer->getInput("media",media);
294  if (err1) egsWarning("createGeometry(EGS_ConeStack): missing "
295  "'media' input for layer %d\n",nl);
296  if (err || err1) {
297  egsWarning(" --> layer ignored\n");
298  }
299  else {
300  g->addLayer(thickness,rtop,rbottom,media);
301  }
302  }
303  layerLabels.push_back(g->setLabels(layer));
304  delete layer;
305  ++nl;
306  }
307  if (!g->nLayer()) {
308  egsWarning("createGeometry(EGS_ConeStack): zero layers\n");
309  delete g;
310  return 0;
311  }
312 
313  // adjust lable region numbering in each layer
314  int count=0;
315  for (size_t i=0; i<layerLabels.size(); i++) {
316  for (int j=0; j<layerLabels[i]; j++) {
317  g->shiftLabelRegions(count,i);
318  count++;
319  }
320  }
321 
322  g->setName(input);
323  g->setBoundaryTolerance(input);
324  g->setLabels(input);
325  g->setBScaling(input); // Perhaps add density scaling as well?
326  return g;
327  }
328 
329  // get cone apex position
330  vector<EGS_Float> tmp;
331  EGS_Vector Xo;
332  err = input->getInput("apex",tmp);
333  if (err || tmp.size() != 3)
334  egsWarning("createGeometry(cones): no 'apex' input, "
335  "assuming (0,0,0)\n");
336  else {
337  Xo.x = tmp[0];
338  Xo.y = tmp[1];
339  Xo.z = tmp[2];
340  }
341  tmp.clear();
342 
343  // get cone axis
344  EGS_Vector axis(0,0,1);
345  err = input->getInput("axis",tmp);
346  if (err || tmp.size() != 3)
347  egsWarning("createGeometry(cones): no 'axis' input, assuming "
348  "(0,0,1)\n");
349  else {
350  axis.x = tmp[0];
351  axis.y = tmp[1];
352  axis.z = tmp[2];
353  }
354 
355  EGS_BaseGeometry *g;
356  if (input->compare(type,"EGS_ConeSet")) {
357  vector<EGS_Float> angles;
358  err = input->getInput("opening angles",angles);
359  bool is_radian = false;
360  if (err) {
361  angles.clear();
362  err = input->getInput("opening angles in radian",angles);
363  if (err) {
364  egsWarning("createGeometry(cones): no 'opening angles' or "
365  "'opening angles in radian' input\n");
366  return 0;
367  }
368  is_radian = true;
369  }
370  int flag = 0;
371  err = input->getInput("flag",flag);
372  int nc = angles.size();
373  EGS_Float *gamma = new EGS_Float [nc];
374  for (int j=0; j<nc; j++) {
375  if (angles[j] <= 0) {
376  egsWarning("createGeometry(cones): opening angles must be"
377  " positive\n");
378  delete [] gamma;
379  return 0;
380  }
381  EGS_Float a = angles[j];
382  if (!is_radian) {
383  a *= (M_PI/180);
384  }
385  if (a >= M_PI/2) {
386  egsWarning("createGeometry(cones): opening angles can not be"
387  " greater than Pi/2\n");
388  delete [] gamma;
389  return 0;
390  }
391  if (j > 0) {
392  if (angles[j] <= angles[j-1]) {
393  egsWarning("createGeometry(cones): opening angles must be"
394  " in increasing order\n");
395  delete [] gamma;
396  return 0;
397  }
398  }
399  gamma[j] = tan(a);
400  }
401  g = new EGS_ConeSet(Xo,axis,nc,gamma,flag);
402  delete [] gamma;
403  }
404 
405  else {
406  // get opening angle
407  EGS_Float angle;
408  err = input->getInput("opening angle",angle);
409  if (err) {
410  err = input->getInput("opening angle in radian",angle);
411  if (err) {
412  egsWarning("createGeometry(cones): no 'opening angle' or "
413  "'opening angle in radian' input\n");
414  return 0;
415  }
416  }
417  else {
418  angle *= (M_PI/180);
419  }
420  if (angle >= M_PI/2) {
421  egsWarning("createGeometry(cones): it is not allowed to have"
422  " an opening angle greater than Pi/2, your input was %g\n",angle);
423  return 0;
424  }
425  EGS_Float gamma = tan(angle);
426  if (input->compare(type,"EGS_SimpleCone")) {
427  EGS_Float height;
428  EGS_Float *h = 0;
429  err = input->getInput("height",height);
430  if (!err) {
431  if (height <= 0)
432  egsWarning("createGeometry(cones): the cone height"
433  " must be greater than zero, your input was %g\n",height);
434  else {
435  h = &height;
436  }
437  }
438  g = new EGS_SimpleCone(Xo,axis,gamma,h,"");
439  }
440  else if (input->compare(type,"EGS_ParallelCones")) {
441  vector<EGS_Float> d;
442  err = input->getInput("apex distances",d);
443  EGS_Float *dist=0;
444  int nc=1;
445  if (!err && d.size() > 0) {
446  dist = new EGS_Float [d.size()];
447  for (size_t j=0; j<d.size(); j++) {
448  dist[j] = d[j];
449  }
450  nc = 1 + d.size();
451  }
452  g = new EGS_ParallelCones(nc,Xo,axis,gamma,dist);
453  if (dist) {
454  delete [] dist;
455  }
456  }
457  else {
458  egsWarning("createGeometry(cones): unknown object type %s\n",
459  type.c_str());
460  return 0;
461  }
462  }
463 
464  g->setName(input);
465  g->setMedia(input);
466  g->setLabels(input);
467  return g;
468  }
469 
470 }
Base geometry class. Every geometry class must be derived from EGS_BaseGeometry.
int deref()
Decrease the reference count to this geometry.
virtual void setBScaling(int start, int end, EGS_Float bf)
Set the B field scaling factor in regions.
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.
bool is_convex
Is this geometry convex?
EGS_Float boundaryTolerance
Boundary tolerance for geometries that need it.
void setName(EGS_Input *inp)
Set the name of the geometry from the input inp.
void setMedium(const string &Name)
Set all regions to a medium with name Name.
int setLabels(EGS_Input *input)
Set the labels from an input block.
virtual void printInfo() const
Print information about this geometry.
int ref()
Increase the reference count to this geometry.
void setBoundaryTolerance(EGS_Input *inp)
Set the value of the boundary tolerance from the input inp.
A set of cones with different opening angles but the same axis and apexes.
Definition: egs_cones.h:1061
A cone stack.
Definition: egs_cones.h:1463
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:226
static bool compare(const string &s1, const string &s2)
Definition: egs_input.cpp:1170
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
A set of "parallel cones" (i.e. cones with the same axis and opening angles but different apexes)
Definition: egs_cones.h:741
A single cone that may be open (i.e. extends to infinity or closed by a plane perpendicular to the co...
Definition: egs_cones.h:126
A class representing 3D vectors.
Definition: egs_vector.h:57
EGS_Float y
y-component
Definition: egs_vector.h:62
EGS_Float z
z-component
Definition: egs_vector.h:63
EGS_Float x
x-component
Definition: egs_vector.h:61
Various cone geometries: header.
EGS_GLIB_EXPORT EGS_BaseGeometry * createGeometry(EGS_Input *input)
Definition: egs_glib.cpp:57
EGS_Input class header file.
EGS_InfoFunction EGS_EXPORT egsInformation
Always use this function for reporting the progress of a simulation and any other type of information...
EGS_InfoFunction EGS_EXPORT egsWarning
Always use this function for reporting warnings.