50 string EGS_cSpheres::type =
"EGS_cSpheres";
52 static bool EGS_SPHERES_LOCAL inputSet =
false;
55 EGS_cSpheres::EGS_cSpheres(
int ns,
const EGS_Float *radius,
56 const EGS_Vector &position,
const string &Name) :
61 R2=
new EGS_Float [ns];
65 for (
int i=0; i<ns; i++) {
66 R2[i]=radius[i]*radius[i];
74 for (
int ireg=0; ireg < ns; ireg++) {
75 rbounds.push_back(radius[ireg]);
76 EGS_Float router = rbounds[ireg];
77 EGS_Float rinner = ireg > 0 ? rbounds[ireg-1] : 0;
78 vol.push_back((4./3.)*M_PI*(router*router*router - rinner*rinner*rinner));
82 bool EGS_cSpheres::isInside(
const EGS_Vector &x) {
84 EGS_Float r_sq=tmp.length2();
85 if (r_sq>R2[
nreg-1]) {
91 int EGS_cSpheres::isWhere(
const EGS_Vector &x) {
93 EGS_Float r_sq=tmp.length2();
94 if (r_sq>R2[
nreg-1]) {
104 int EGS_cSpheres::inside(
const EGS_Vector &x) {
107 EGS_Float r_sq=tmp.length2();
110 if (r_sq>R2[
nreg-1]) {
143 EGS_Float last_d,last_t,last_aa,last_bb2,last_R2b2,last_tmp;
146 EGS_Float EGS_cSpheres::howfarToOutside(
int ireg,
const EGS_Vector &x,
152 EGS_Float aa = xp*u, aa2 = aa*aa;
153 EGS_Float bb2 = xp.length2();
154 EGS_Float R2b2 = R2[
nreg-1] - bb2;
158 EGS_Float tmp = sqrt(aa2 + R2b2);
159 return aa > 0 ? R2b2/(tmp + aa) : tmp - aa;
162 int EGS_cSpheres::howfar(
int ireg,
const EGS_Vector &x,
164 int direction_flag=-1;
169 double aa = xp*u, aa2 = aa*aa;
170 double bb2 = xp.length2();
172 double rad=0, R2b2, tmp;
181 if (aa >= 0 || !ireg) {
187 R2b2 = R2[ireg] - bb2;
188 if (R2b2 <= 0 && aa > 0) {
189 d = halfBoundaryTolerance;
198 egsWarning(
"EGS_cSpheres::howfar: something is wrong\n");
199 egsWarning(
" we think we are in region %d, but R2b2=%g",
204 d = aa > 0 ? R2b2/(tmp + aa) : tmp - aa;
209 direction_flag=ireg+1;
210 if (direction_flag >=
nreg) {
220 R2b2 = R2[ireg-1] - bb2;
223 R2b2 = R2[ireg] - bb2;
232 direction_flag=ireg+1;
233 if (direction_flag >=
nreg) {
240 d = -R2b2/(tmp - aa);
241 direction_flag=ireg-1;
242 rad = R[direction_flag];
249 R2b2 = R2[
nreg-1] - bb2;
252 d = -R2b2/(sqrt(tmp) - aa);
253 direction_flag=
nreg-1;
254 rad = R[direction_flag];
266 egsWarning(
"ireg=%d inew=%d aa=%g bb2=%g\n",ireg,direction_flag,aa,bb2);
285 if (direction_flag >= 0) {
286 *newmed =
medium(direction_flag);
296 return direction_flag;
302 EGS_Float EGS_cSpheres::hownear(
int ireg,
const EGS_Vector &x) {
304 EGS_Float r=xp.length();
311 EGS_Float dd=r-R[ireg-1];
323 void EGS_cSpheres::printInfo()
const {
327 for (
int j=0; j<
nreg; j++) {
331 "\n=======================================================\n");
335 if (idir == RDIR && ind ==0) {
338 else if (idir == RDIR && ind>0 && ind <=
nreg) {
339 return rbounds[ind-1];
354 if (ireg >= 0 && ireg <
nreg) {
362 string EGS_cSphericalShell::type =
"EGS_cSphericalShell";
365 EGS_cSphericalShell::EGS_cSphericalShell(
int ns,
const EGS_Float *radius,
366 const EGS_Vector &position,
const string &Name) :
373 R2 =
new EGS_Float [ns];
374 R =
new EGS_Float [ns];
376 for (
int i=0; i<ns; i++) {
377 R2[i] = radius[i]*radius[i];
385 for (
int ireg=0; ireg <
nreg; ireg++) {
386 EGS_Float rinner = R[ireg];
387 EGS_Float router = R[ireg + 1];
388 vol.push_back((4./3.)*M_PI*(router*router*router - rinner*rinner*rinner));
392 bool EGS_cSphericalShell::isInside(
const EGS_Vector &x) {
393 EGS_Float r_sq = (x - xo).length2();
394 return (r_sq >= R2[0]) && (r_sq <= R2[
nreg]);
397 int EGS_cSphericalShell::isWhere(
const EGS_Vector &x) {
399 EGS_Float r_sq = (x - xo).length2();
401 if ((r_sq < R2[0]) || (r_sq > R2[
nreg])) {
408 int EGS_cSphericalShell::inside(
const EGS_Vector &x) {
411 EGS_Float r_sq=tmp.length2();
414 if (r_sq > R2[
nreg] || r_sq < R2[0]) {
418 for (
int shell = 1; shell <
nreg + 1; shell++) {
419 if (r_sq <= R2[shell]) {
428 EGS_Float EGS_cSphericalShell::howfarToOutside(
int ireg,
const EGS_Vector &x,
435 EGS_Float aa2 = aa*aa;
436 EGS_Float bb2 = xp.length2();
437 EGS_Float R2b2 = R2[
nreg] - bb2;
438 EGS_Float R2b2in = R2[0] - bb2;
439 if (R2b2in <= 0 || R2b2 <= 0) {
449 if (R2b2 <= 0 && aa > 0) {
459 egsWarning(
"EGS_cSphericalShell::howfarToOutside: something is wrong\n");
460 egsWarning(
" we think we are in region %d, but R2b2=%g", ireg,R2b2);
464 d = aa > 0 ? R2b2/(tmp + aa) : tmp - aa;
472 R2b2 = R2[
nreg] - bb2;
484 d = -R2b2/(tmp - aa);
498 int EGS_cSphericalShell::howfar(
int ireg,
const EGS_Vector &x,
500 int direction_flag=-1;
505 double aa = xp*u, aa2 = aa*aa;
506 double bb2 = xp.length2();
508 double rad=0, R2b2, tmp;
522 R2b2 = R2[ireg + 1] - bb2;
523 if (R2b2 <= 0 && aa > 0) {
533 egsWarning(
"EGS_cSphericalShell::howfar: something is wrong\n");
534 egsWarning(
" we think we are in region %d, but R2b2=%g",
539 d = aa > 0 ? R2b2/(tmp + aa) : tmp - aa;
544 direction_flag = ireg + 1;
545 if (direction_flag >=
nreg) {
555 R2b2 = R2[ireg] - bb2;
558 R2b2 = R2[ireg+1] - bb2;
567 direction_flag= ireg + 1;
568 if (direction_flag >=
nreg) {
575 d = -R2b2/(tmp - aa);
576 direction_flag= ireg - 1;
588 tmp = sqrt(aa2 + R2b2);
589 d = aa > 0 ? R2b2/(tmp + aa) : tmp - aa;
591 rad = -R[direction_flag];
596 R2b2 = R2[
nreg] - bb2;
599 d = -R2b2/(sqrt(tmp) - aa);
600 direction_flag=
nreg-1;
611 if (direction_flag >= 0) {
612 *newmed =
medium(direction_flag);
622 return direction_flag;
628 EGS_Float EGS_cSphericalShell::hownear(
int ireg,
const EGS_Vector &x) {
631 EGS_Float r = xp.length();
632 EGS_Float d, dout,din;
635 dout = R[ireg+1] - r;
639 else if (r <= R[0] +
epsilon) {
649 EGS_Float EGS_cSphericalShell::getBound(
int idir,
int ind) {
650 if (idir == RDIR && ind >= 0 && ind <=
nreg) {
657 int EGS_cSphericalShell::getNRegDir(
int dir) {
665 EGS_Float EGS_cSphericalShell::getVolume(
int ireg) {
666 if (ireg >= 0 && ireg <
nreg) {
673 void EGS_cSphericalShell::printInfo()
const {
677 for (
int j=0; j<
nreg+1; j++) {
681 "\n=======================================================\n");
686 static void setInputs() {
689 setBaseGeometryInputs();
691 geomBlockInput->getSingleInput(
"library")->setValues({
"egs_spheres"});
694 geomBlockInput->addSingleInput(
"radii",
true,
"A list of sphere radii, in increasing order.");
695 geomBlockInput->addSingleInput(
"midpoint",
false,
"The position of the middle of the spheres (x, y, z)");
698 EGS_SPHERES_EXPORT
string getExample() {
702 # Example of egs_spheres
705 library = egs_spheres
709 media = air water air
713 :stop geometry input:
718 EGS_SPHERES_EXPORT shared_ptr<EGS_BlockInput> getInputs() {
722 return geomBlockInput;
727 egsWarning(
"createGeometry(spheres): null input?\n");
731 vector<EGS_Float> Xo;
732 int err = input->
getInput(
"midpoint",Xo);
733 if (!err && Xo.size() == 3) {
740 vector<EGS_Float> radii;
741 err = input->
getInput(
"radii",radii);
743 egsWarning(
"createGeometry(spheres): wrong/missing 'radii' input\n");
746 else if ((type ==
"shell") && (radii.size() < 2)) {
747 egsWarning(
"createGeometry(spheres): You must specify at least two radii for a spherical shell\n");
751 EGS_Float *r =
new EGS_Float [radii.size()];
752 for (
int j=0; j<radii.size(); j++) {
757 if (type !=
"shell") {
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.
static int findRegion(EGS_Float xp, int np, const EGS_Float *p)
Find the bin to which xp belongs, given np bin edges p.
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.
virtual int getNRegDir(int idir)
virtual int medium(int ireg) const
Returns the medium index in region ireg.
int setLabels(EGS_Input *input)
Set the labels from an input block.
virtual EGS_Float getBound(int idir, int ind)
Returns region boundaries in direction determined by idir.
virtual void printInfo() const
Print information about this geometry.
void setBoundaryTolerance(EGS_Input *inp)
Set the value of the boundary tolerance from the input inp.
A class representing 3D vectors.
A set of concentric spheres.
EGS_Float getBound(int idir, int ind)
Implement getBound for spherical regions.
int getNRegDir(int dir)
Implement geNRegDir for spherical regions.
EGS_Float getVolume(int ireg)
Implement getVolume for spherical regions.
Implements a spherical shell geometry with a hollow centre.
Global egspp functions header file.
EGS_GLIB_EXPORT EGS_BaseGeometry * createGeometry(EGS_Input *input)
A set of concentric spheres.
EGS_InfoFunction EGS_EXPORT egsInformation
Always use this function for reporting the progress of a simulation and any other type of information...
const EGS_Float epsilon
The epsilon constant for floating point comparisons.
EGS_InfoFunction EGS_EXPORT egsWarning
Always use this function for reporting warnings.
const EGS_Float veryFar
A very large float.