EGSnrc C++ class library  Report PIRS-898 (2021)
Iwan Kawrakow, Ernesto Mainegra-Hing, Frederic Tessier, Reid Townson and Blake Walters
egs_spheres.cpp
Go to the documentation of this file.
1 /*
2 ###############################################################################
3 #
4 # EGSnrc egs++ spheres 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: Ernesto Mainegra-Hing
27 # Frederic Tessier
28 # Reid Townson
29 # Randle Taylor
30 #
31 ###############################################################################
32 */
33 
34 
40 #include "egs_spheres.h"
41 #include "egs_input.h"
42 #include "egs_functions.h"
43 
44 #include <vector>
45 using std::vector;
46 
47 string EGS_cSpheres::type = "EGS_cSpheres";
48 
49 // generate the concentric spheres
50 EGS_cSpheres::EGS_cSpheres(int ns, const EGS_Float *radius,
51  const EGS_Vector &position, const string &Name) :
52  EGS_BaseGeometry(Name), xo(position) {
53 
54  if (ns>0) {
55 
56  R2=new EGS_Float [ns];
57  R=new EGS_Float [ns];
58 
59  // ... and sphere radii
60  for (int i=0; i<ns; i++) {
61  R2[i]=radius[i]*radius[i];
62  R[i]=radius[i];
63  }
64 
65  // for n-concentric spheres, we have n separate regions
66  nreg=ns;
67  }
68 
69  for (int ireg=0; ireg < ns; ireg++) {
70  rbounds.push_back(radius[ireg]);
71  EGS_Float router = rbounds[ireg];
72  EGS_Float rinner = ireg > 0 ? rbounds[ireg-1] : 0;
73  vol.push_back((4./3.)*M_PI*(router*router*router - rinner*rinner*rinner));
74  }
75 }
76 
77 bool EGS_cSpheres::isInside(const EGS_Vector &x) {
78  EGS_Vector tmp(x-xo);
79  EGS_Float r_sq=tmp.length2();
80  if (r_sq>R2[nreg-1]) {
81  return false;
82  }
83  return true;
84 }
85 
86 int EGS_cSpheres::isWhere(const EGS_Vector &x) {
87  EGS_Vector tmp(x-xo);
88  EGS_Float r_sq=tmp.length2();
89  if (r_sq>R2[nreg-1]) {
90  return -1;
91  }
92  if (r_sq<R2[0]) {
93  return 0;
94  }
95  return findRegion(r_sq,nreg-1,R2)+1;
96 }
97 
98 // method to determine which spheres we are in(between)
99 int EGS_cSpheres::inside(const EGS_Vector &x) {
100 
101  EGS_Vector tmp(x-xo);
102  EGS_Float r_sq=tmp.length2();
103 
104  // are we outside off all spheres? If so return that region number
105  if (r_sq>R2[nreg-1]) {
106  return -1;
107  }
108 
109  /*
110  * algorithm below fails for particle in central sphere ...ugh!
111  */if (r_sq<R2[0]) {
112  return 0;
113  }
114 
115  // search for region containing particle
116  int is=0,os=nreg,ms;
117  while (os-is>1) {
118  ms=(is+os)/2;
119  if (r_sq<=R2[ms]) {
120  os=ms;
121  }
122  else {
123  is=ms;
124  }
125  }
126  return os;
127 }
128 
129 // howfar is particle trajectory from sphere boundary
130 /* note that in general we will be between two spheres (if inside a sphere at
131  * all... so we need to check if the flight path will intersect the inner or
132  * outer sphere
133  */
134 
135 #ifdef SPHERES_DEBUG
136  EGS_Vector last_x, last_u;
137  int last_ireg;
138  EGS_Float last_d,last_t,last_aa,last_bb2,last_R2b2,last_tmp;
139 #endif
140 
141 EGS_Float EGS_cSpheres::howfarToOutside(int ireg, const EGS_Vector &x,
142  const EGS_Vector &u) {
143  if (ireg < 0) {
144  return 0;
145  }
146  EGS_Vector xp(x - xo);
147  EGS_Float aa = xp*u, aa2 = aa*aa;
148  EGS_Float bb2 = xp.length2();
149  EGS_Float R2b2 = R2[nreg-1] - bb2;
150  if (R2b2 <= 0) {
151  return 0; // outside within precision
152  }
153  EGS_Float tmp = sqrt(aa2 + R2b2);
154  return aa > 0 ? R2b2/(tmp + aa) : tmp - aa;
155 }
156 
157 int EGS_cSpheres::howfar(int ireg, const EGS_Vector &x,
158  const EGS_Vector &u, EGS_Float &t, int *newmed, EGS_Vector *normal) {
159  int direction_flag=-1; /* keep track of direction entering or exiting a
160  sphere boundary */
161  double d=veryFar*1e5; // set a maximum distance from a boundary
162 
163  EGS_Vector xp(x - xo);
164  double aa = xp*u, aa2 = aa*aa;
165  double bb2 = xp.length2();
166 
167  double rad=0, R2b2, tmp;
168 
169  // check if we are inside of any regions at all? ...
170  if (ireg>=0) {
171 
172  /* check if particle is moving towards or away from the sphere(s) centre.
173  * we loose here if the particle is in the centre sphere as we don't need
174  * to check this condition. see next 'if' statement
175  */
176  if (aa >= 0 || !ireg) {
177 
178  /* ie. particle moving away from center of
179  spheres, OR it is IN the innermost sphere
180  => we must check the outer sphere only
181  */
182  R2b2 = R2[ireg] - bb2;
183  if (R2b2 <= 0 && aa > 0) {
184  d = halfBoundaryTolerance; // hopefully a truncation problem
185  }
186  else {
187  tmp = aa2 + R2b2;
188  if (tmp > 0) {
189  tmp = sqrt(tmp);
190  }
191  else {
192  if (tmp < -boundaryTolerance) {
193  egsWarning("EGS_cSpheres::howfar: something is wrong\n");
194  egsWarning(" we think we are in region %d, but R2b2=%g",
195  ireg,R2b2);
196  }
197  tmp = 0;
198  }
199  d = aa > 0 ? R2b2/(tmp + aa) : tmp - aa;
200  // the above reduces roundoff, which is significant
201  // when aa2 is large compared to R2b2 and aa>0
202  }
203  rad = -R[ireg];
204  direction_flag=ireg+1;
205  if (direction_flag >= nreg) {
206  direction_flag = -1;
207  }
208  }
209  else {
210 
211  /* so now we know the particle is moving towards the centre of the
212  * spheres. check to see if its trajectory will intersect the nested
213  * sphere - we are guaranteed there is one - we checked that already!
214  */
215  R2b2 = R2[ireg-1] - bb2;
216  tmp = aa2 + R2b2;
217  if (tmp <= 0) { // we will not intersect the nested sphere
218  R2b2 = R2[ireg] - bb2;
219  tmp = aa2 + R2b2;
220  if (tmp > 0) {
221  d = sqrt(tmp) - aa;
222  }
223  else {
224  d = -aa;
225  }
226  rad = -R[ireg];
227  direction_flag=ireg+1;
228  if (direction_flag >= nreg) {
229  direction_flag = -1;
230  }
231  }
232  else {
233  // we're hitting the inner sphere (from the outside)
234  tmp = sqrt(tmp);
235  d = -R2b2/(tmp - aa);
236  direction_flag=ireg-1;
237  rad = R[direction_flag];
238  }
239  }
240  }
241  else {
242  // we are not inside any of the spherical regions of interest
243  if (aa<0) { // we _might_ intersect the largest sphere
244  R2b2 = R2[nreg-1] - bb2;
245  tmp = aa2 + R2b2;
246  if (tmp > 0) { // we *will* intersect the largest sphere
247  d = -R2b2/(sqrt(tmp) - aa);
248  direction_flag=nreg-1;
249  rad = R[direction_flag];
250  }
251  }
252  }
253 
254 #ifdef SPHERES_DEBUG
255  if (isnan(d)) {
256  egsWarning("\nGot nan\n");
257  }
258 
259  if (d < -boundaryTolerance) {
260  egsWarning("\nNegative step?: %g\n",d);
261  egsWarning("ireg=%d inew=%d aa=%g bb2=%g\n",ireg,direction_flag,aa,bb2);
262  //exit(1);
263  }
264 
265  last_x = x;
266  last_u = u;
267  last_ireg = ireg;
268  last_d = d;
269  last_t = t;
270  last_aa = aa;
271  last_bb2 = bb2;
272  last_R2b2 = R2b2;
273  last_tmp = tmp;
274 #endif
275 
276  // check desired step size against this d
277  if (d<=t) {
278  t=d;
279  if (newmed) {
280  if (direction_flag >= 0) {
281  *newmed = medium(direction_flag);
282  }
283  else {
284  *newmed = -1;
285  }
286  }
287  if (normal) {
288  EGS_Vector n(xp + u*d);
289  *normal = n*(1/rad);
290  }
291  return direction_flag;
292  }
293  return ireg;
294 }
295 
296 // hownear - closest perpendicular distance to sphere surface
297 EGS_Float EGS_cSpheres::hownear(int ireg, const EGS_Vector &x) {
298  EGS_Vector xp(x-xo);
299  EGS_Float r=xp.length();
300  //EGS_Float r_sq=x.x*x.x+x.y*x.y+x.z*x.z;
301  EGS_Float d;
302 
303  if (ireg>=0) {
304  d=R[ireg]-r;
305  if (ireg) {
306  EGS_Float dd=r-R[ireg-1];
307  if (dd<d) {
308  d=dd;
309  }
310  }
311  }
312  else {
313  d=r-R[nreg-1];
314  }
315 
316  return d;
317 }
318 
319 void EGS_cSpheres::printInfo() const {
321  egsInformation(" midpoint of spheres = (%g,%g,%g)\n",xo.x,xo.y,xo.z);
322  egsInformation(" sphere radii = ");
323  for (int j=0; j<nreg; j++) {
324  egsInformation("%g ",R[j]);
325  }
327  "\n=======================================================\n");
328 }
329 
330 EGS_Float EGS_cSpheres::getBound(int idir, int ind) {
331  if (idir == RDIR && ind ==0) {
332  return 0.;
333  }
334  else if (idir == RDIR && ind>0 && ind <= nreg) {
335  return rbounds[ind-1];
336  }
337  return EGS_BaseGeometry::getBound(idir, ind);
338 }
339 
340 
342  if (dir == RDIR) {
343  return nreg;
344  }
345  return EGS_BaseGeometry::getNRegDir(dir);
346 }
347 
348 
349 EGS_Float EGS_cSpheres::getVolume(int ireg) {
350  if (ireg >= 0 && ireg < nreg) {
351  return vol[ireg];
352  }
353  return 1;
354 }
355 
356 /********************** Shell *************************************/
357 
358 string EGS_cSphericalShell::type = "EGS_cSphericalShell";
359 
360 // generate the concentric spheres
361 EGS_cSphericalShell::EGS_cSphericalShell(int ns, const EGS_Float *radius,
362  const EGS_Vector &position, const string &Name) :
363  EGS_BaseGeometry(Name), xo(position) {
364 
365  is_convex = false;
366 
367  if (ns>0) {
368 
369  R2 = new EGS_Float [ns];
370  R = new EGS_Float [ns];
371 
372  for (int i=0; i<ns; i++) {
373  R2[i] = radius[i]*radius[i];
374  R[i] = radius[i];
375  }
376 
377  // for n-concentric spheres (with hollow centre), we have n - 1 separate regions
378  nreg = ns - 1;
379  }
380 
381  for (int ireg=0; ireg < nreg; ireg++) {
382  EGS_Float rinner = R[ireg];
383  EGS_Float router = R[ireg + 1];
384  vol.push_back((4./3.)*M_PI*(router*router*router - rinner*rinner*rinner));
385  }
386 }
387 
388 bool EGS_cSphericalShell::isInside(const EGS_Vector &x) {
389  EGS_Float r_sq = (x - xo).length2();
390  return (r_sq >= R2[0]) && (r_sq <= R2[nreg]);
391 }
392 
393 int EGS_cSphericalShell::isWhere(const EGS_Vector &x) {
394 
395  EGS_Float r_sq = (x - xo).length2();
396 
397  if ((r_sq < R2[0]) || (r_sq > R2[nreg])) {
398  return -1;
399  }
400  return findRegion(r_sq, nreg, R2);
401 }
402 
403 // method to determine which spheres we are in(between)
404 int EGS_cSphericalShell::inside(const EGS_Vector &x) {
405 
406  EGS_Vector tmp(x-xo);
407  EGS_Float r_sq=tmp.length2();
408 
409  // are we outside off all spheres? If so return that region number
410  if (r_sq > R2[nreg] || r_sq < R2[0]) {
411  return -1;
412  }
413 
414  for (int shell = 1; shell < nreg + 1; shell++) {
415  if (r_sq <= R2[shell]) {
416  return shell - 1;
417  }
418  }
419 
420  return -1;
421 
422 }
423 
424 EGS_Float EGS_cSphericalShell::howfarToOutside(int ireg, const EGS_Vector &x,
425  const EGS_Vector &u) {
426  if (ireg < 0) {
427  return 0;
428  }
429  EGS_Vector xp(x - xo);
430  EGS_Float aa = xp*u;
431  EGS_Float aa2 = aa*aa;
432  EGS_Float bb2 = xp.length2();
433  EGS_Float R2b2 = R2[nreg] - bb2;
434  EGS_Float R2b2in = R2[0] - bb2;
435  if (R2b2in <= 0 || R2b2 <= 0) {
436  return 0; // outside within precision
437  }
438 
439  EGS_Float d, tmp;
440  if (aa >= 0) {
441 
442  /* ie. particle moving away from center of
443  spheres we must check the outer sphere only
444  */
445  if (R2b2 <= 0 && aa > 0) {
446  d = 1e-15; // hopefully a truncation problem
447  }
448  else {
449  tmp = aa2 + R2b2;
450  if (tmp > 0) {
451  tmp = sqrt(tmp);
452  }
453  else {
454  if (tmp < -1e-2) {
455  egsWarning("EGS_cSphericalShell::howfarToOutside: something is wrong\n");
456  egsWarning(" we think we are in region %d, but R2b2=%g", ireg,R2b2);
457  }
458  tmp = 0;
459  }
460  d = aa > 0 ? R2b2/(tmp + aa) : tmp - aa;
461  }
462  }
463  else {
464 
465  R2b2 = R2[0] - bb2;
466  tmp = aa2 + R2b2;
467  if (tmp <= 0) { // we will not intersect the nested sphere
468  R2b2 = R2[nreg] - bb2;
469  tmp = aa2 + R2b2;
470  if (tmp > 0) {
471  d = sqrt(tmp) - aa;
472  }
473  else {
474  d = -aa;
475  }
476  }
477  else {
478  // we're hitting the inner sphere (from the outside)
479  tmp = sqrt(tmp);
480  d = -R2b2/(tmp - aa);
481  }
482 
483  }
484  return d;
485 
486 }
487 
488 
489 // howfar is particle trajectory from sphere boundary
490 /* note that in general we will be between two spheres (if inside a sphere at
491  * all... so we need to check if the flight path will intersect the inner or
492  * outer sphere
493  */
494 int EGS_cSphericalShell::howfar(int ireg, const EGS_Vector &x,
495  const EGS_Vector &u, EGS_Float &t, int *newmed, EGS_Vector *normal) {
496  int direction_flag=-1; /* keep track of direction entering or exiting a
497  sphere boundary */
498  double d=1e35; // set a maximum distance from a boundary
499 
500  EGS_Vector xp(x - xo);
501  double aa = xp*u, aa2 = aa*aa;
502  double bb2 = xp.length2();
503 
504  double rad=0, R2b2, tmp;
505 
506  // check if we are inside of any regions at all? ...
507  if (ireg >= 0) {
508 
509  /* check if particle is moving towards or away from the sphere(s) centre.
510  * we loose here if the particle is in the centre sphere as we don't need
511  * to check this condition. see next 'if' statement
512  */
513  if (aa >= 0) {
514 
515  /* ie. particle moving away from center of
516  spheres we must check the outer sphere only
517  */
518  R2b2 = R2[ireg + 1] - bb2;
519  if (R2b2 <= 0 && aa > 0) {
520  d = 1e-15; // hopefully a truncation problem
521  }
522  else {
523  tmp = aa2 + R2b2;
524  if (tmp > 0) {
525  tmp = sqrt(tmp);
526  }
527  else {
528  if (tmp < -1e-2) {
529  egsWarning("EGS_cSphericalShell::howfar: something is wrong\n");
530  egsWarning(" we think we are in region %d, but R2b2=%g",
531  ireg,R2b2);
532  }
533  tmp = 0;
534  }
535  d = aa > 0 ? R2b2/(tmp + aa) : tmp - aa;
536  // the above reduces roundoff, which is significant
537  // when aa2 is large compared to R2b2 and aa>0
538  }
539  rad = -R[ireg + 1];
540  direction_flag = ireg + 1;
541  if (direction_flag >= nreg) {
542  direction_flag = -1;
543  }
544  }
545  else {
546 
547  /* so now we know the particle is moving towards the centre of the
548  * spheres. check to see if its trajectory will intersect the nested
549  * sphere - we are guaranteed there is one - we checked that already!
550  */
551  R2b2 = R2[ireg] - bb2;
552  tmp = aa2 + R2b2;
553  if (tmp <= 0) { // we will not intersect the nested sphere
554  R2b2 = R2[ireg+1] - bb2;
555  tmp = aa2 + R2b2;
556  if (tmp > 0) {
557  d = sqrt(tmp) - aa;
558  }
559  else {
560  d = -aa;
561  }
562  rad = -R[ireg + 1];
563  direction_flag= ireg + 1;
564  if (direction_flag >= nreg) {
565  direction_flag = -1;
566  }
567  }
568  else {
569  // we're hitting the inner sphere (from the outside)
570  tmp = sqrt(tmp);
571  d = -R2b2/(tmp - aa);
572  direction_flag= ireg - 1;
573  rad = R[ireg];
574  }
575  }
576  }
577  else {
578  // if we're in here, we know we're not in the shell, so bb2
579  // can be equal to R2[0], it just means we're sitting at the
580  // boundary
581  if (bb2 <= R2[0] + epsilon) { //epsilon needed for round off errors
582  // we are in the hollow center
583  R2b2 = R2[0] - bb2;
584  tmp = sqrt(aa2 + R2b2);
585  d = aa > 0 ? R2b2/(tmp + aa) : tmp - aa;
586  direction_flag = 0;
587  rad = -R[direction_flag];
588  }
589  else {
590  // we are not inside any of the spherical regions of interest
591  if (aa<0) { // we _might_ intersect the largest sphere
592  R2b2 = R2[nreg] - bb2;
593  tmp = aa2 + R2b2;
594  if (tmp > 0) { // we *will* intersect the largest sphere
595  d = -R2b2/(sqrt(tmp) - aa);
596  direction_flag=nreg-1;
597  rad = R[nreg];
598  }
599  }
600  }
601  }
602 
603  // check desired step size against this d
604  if (d <= t) {
605  t=d;
606  if (newmed) {
607  if (direction_flag >= 0) {
608  *newmed = medium(direction_flag);
609  }
610  else {
611  *newmed = -1;
612  }
613  }
614  if (normal) {
615  EGS_Vector n(xp + u*d);
616  *normal = n*(1/rad);
617  }
618  return direction_flag;
619  }
620  return ireg;
621 }
622 
623 // hownear - closest perpendicular distance to sphere surface
624 EGS_Float EGS_cSphericalShell::hownear(int ireg, const EGS_Vector &x) {
625 
626  EGS_Vector xp(x-xo);
627  EGS_Float r = xp.length();
628  EGS_Float d, dout,din;
629 
630  if (ireg >= 0) {
631  dout = R[ireg+1] - r;
632  din = r - R[ireg];
633  d = min(dout, din);
634  }
635  else if (r <= R[0] + epsilon) { //epsilon needed for round off errors
636  d = R[0] - r;
637  }
638  else {
639  d = r - R[nreg];
640  }
641 
642  return d;
643 }
644 
645 EGS_Float EGS_cSphericalShell::getBound(int idir, int ind) {
646  if (idir == RDIR && ind >= 0 && ind <= nreg) {
647  return R[ind];
648  }
649  return EGS_BaseGeometry::getBound(idir, ind);
650 }
651 
652 
653 int EGS_cSphericalShell::getNRegDir(int dir) {
654  if (dir == RDIR) {
655  return nreg;
656  }
657  return EGS_BaseGeometry::getNRegDir(dir);
658 }
659 
660 
661 EGS_Float EGS_cSphericalShell::getVolume(int ireg) {
662  if (ireg >= 0 && ireg < nreg) {
663  return vol[ireg];
664  }
665  return 1;
666 }
667 
668 
669 void EGS_cSphericalShell::printInfo() const {
671  egsInformation(" midpoint of spheres = (%g,%g,%g)\n",xo.x,xo.y,xo.z);
672  egsInformation(" sphere radii = ");
673  for (int j=0; j<nreg+1; j++) {
674  egsInformation("%g ",R[j]);
675  }
677  "\n=======================================================\n");
678 }
679 
680 extern "C" {
681 
682  EGS_SPHERES_EXPORT EGS_BaseGeometry *createGeometry(EGS_Input *input) {
683  if (!input) {
684  egsWarning("createGeometry(spheres): null input?\n");
685  return 0;
686  }
687  EGS_Vector xo;
688  vector<EGS_Float> Xo;
689  int err = input->getInput("midpoint",Xo);
690  if (!err && Xo.size() == 3) {
691  xo = EGS_Vector(Xo[0],Xo[1],Xo[2]);
692  }
693 
694  string type= "";
695  input->getInput("type", type);
696 
697  vector<EGS_Float> radii;
698  err = input->getInput("radii",radii);
699  if (err) {
700  egsWarning("createGeometry(spheres): wrong/missing 'radii' input\n");
701  return 0;
702  }
703  else if ((type == "shell") && (radii.size() < 2)) {
704  egsWarning("createGeometry(spheres): You must specify at least two radii for a spherical shell\n");
705  return 0;
706  }
707 
708  EGS_Float *r = new EGS_Float [radii.size()];
709  for (int j=0; j<radii.size(); j++) {
710  r[j] = radii[j];
711  }
712 
713  EGS_BaseGeometry *result;
714  if (type != "shell") {
715  result = new EGS_cSpheres(radii.size(),r,xo);
716  }
717  else {
718  result = new EGS_cSphericalShell(radii.size(), r, xo);
719  }
720  result->setName(input);
721  result->setBoundaryTolerance(input);
722  result->setMedia(input);
723  result->setLabels(input);
724  return result;
725  }
726 
727 }
virtual int getNRegDir(int idir)
virtual int medium(int ireg) const
Returns the medium index in region ireg.
virtual void printInfo() const
Print information about this geometry.
EGS_Float getVolume(int ireg)
Implement getVolume for spherical regions.
EGS_Input class header file.
EGS_Float y
y-component
Definition: egs_vector.h:61
A class representing 3D vectors.
Definition: egs_vector.h:56
int setLabels(EGS_Input *input)
Set the labels from an input block.
int getNRegDir(int dir)
Implement geNRegDir for spherical regions.
Global egspp functions header file.
static int findRegion(EGS_Float xp, int np, const EGS_Float *p)
Find the bin to which xp belongs, given np bin edges p.
const EGS_Float veryFar
A very large float.
EGS_GLIB_EXPORT EGS_BaseGeometry * createGeometry(EGS_Input *input)
Definition: egs_glib.cpp:57
EGS_Float getBound(int idir, int ind)
Implement getBound for spherical regions.
Base geometry class. Every geometry class must be derived from EGS_BaseGeometry.
virtual EGS_Float getBound(int idir, int ind)
Returns region boundaries in direction determined by idir.
void setBoundaryTolerance(EGS_Input *inp)
Set the value of the boundary tolerance from the input inp.
EGS_Float z
z-component
Definition: egs_vector.h:62
void setMedia(EGS_Input *inp)
Set the media in the geometry from the input pointed to by inp.
EGS_InfoFunction EGS_EXPORT egsInformation
Always use this function for reporting the progress of a simulation and any other type of information...
bool is_convex
Is this geometry convex?
A set of concentric spheres.
Implements a spherical shell geometry with a hollow centre.
Definition: egs_spheres.h:207
void setName(EGS_Input *inp)
Set the name of the geometry from the input inp.
EGS_Float boundaryTolerance
Boundary tolerance for geometries that need it.
EGS_Float x
x-component
Definition: egs_vector.h:60
A set of concentric spheres.
Definition: egs_spheres.h:137
const EGS_Float epsilon
The epsilon constant for floating point comparisons.
Definition: egs_functions.h:61
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 nreg
Number of local regions in this geometry.
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
EGS_InfoFunction EGS_EXPORT egsWarning
Always use this function for reporting warnings.