49 #include "../egs_gtransformed/egs_gtransformed.h"
65 const string EGS_AENVELOPE_LOCAL EGS_AEnvelope::allowed_base_geom_types[] = {
"EGS_cSpheres",
"EGS_cSphericalShell",
"EGS_XYZGeometry",
"EGS_RZ"};
67 static char EGS_AENVELOPE_LOCAL geom_class_msg[] =
"createGeometry(AEnvelope): %s\n";
68 static char EGS_AENVELOPE_LOCAL base_geom_keyword[] =
"base geometry";
69 static char EGS_AENVELOPE_LOCAL inscribed_geom_keyword[] =
"inscribed geometry";
70 static char EGS_AENVELOPE_LOCAL inscribed_geom_name_keyword[] =
"inscribed geometry name";
71 static char EGS_AENVELOPE_LOCAL transformations_keyword[] =
"transformations";
72 static char EGS_AENVELOPE_LOCAL type_keyword[] =
"type";
73 static char EGS_AENVELOPE_LOCAL transformation_keyword[] =
"transformation";
77 const vector<AEnvelopeAux> inscribed,
const string &Name,
bool debug,
string output_vc_file) :
78 EGS_BaseGeometry(Name), base_geom(base_geom), debug_info(debug), output_vc(output_vc_file) {
80 bool volcor_available = allowedBaseGeomType(base_geom->
getType());
81 bool volcor_requested = inscribed.size() > 0 && inscribed[0].vcopts->mode ==
CORRECT_VOLUME;
83 if (!volcor_available && volcor_requested) {
86 "EGS_AEnvelope:: Volume correction is not available for geometry type '%s (%s)'. "
87 "Geometry types must implement getVolume. Valid choices are:\n\t"
90 int end = (int)(
sizeof(allowed_base_geom_types)/
sizeof(string));
91 for (
int i=0; i < end; i++) {
92 msg += allowed_base_geom_types[i] +
" ";
94 msg +=
"\nPlease set `action = discover -or- correct and zero volume` or use a different base geometry type.\n";
100 nregbase = base_geom->
regions();
102 has_rho_scaling = getHasRhoScaling();
104 ninscribed = inscribed.size();
105 if (ninscribed == 0) {
106 egsFatal(
"EGS_AEnvelope: no inscribed geometries!\n");
114 for (
int geom_idx=0; geom_idx < ninscribed; geom_idx++) {
118 VCOptions *vcopt = inscribed[geom_idx].vcopts;
121 inscribed_geoms.push_back(transformed);
122 transforms.push_back(transform);
123 opts.push_back(vcopt);
125 int ninscribed_reg= transformed->
regions();
126 nreg += ninscribed_reg;
128 for (
int lreg = 0; lreg < ninscribed_reg; lreg++) {
130 local_to_global_reg[local] = global;
131 global_reg_to_local[global] = local;
136 geoms_in_region =
new vector<EGS_BaseGeometry *>[nregbase];
138 if (inscribed[0].vcopts->vc_file !=
"") {
139 vc_results =
loadFileResults(inscribed[0].vcopts, base_geom, inscribed_geoms, transforms);
140 egsInformation(
"loaded from %s\n", inscribed[0].vcopts->vc_file.c_str());
148 nreg_with_inscribed = 0;
149 for (volcor::RegionGeomSetT::iterator it=vc_results.regions_with_inscribed.begin();
150 it!=vc_results.regions_with_inscribed.end(); it++) {
151 nreg_with_inscribed++;
152 copy(it->second.begin(), it->second.end(), back_inserter(geoms_in_region[it->first]));
155 if (getNRegWithInscribed() == 0) {
156 egsFatal(
"EGS_AEnvelope:: Failed to find any regions with inscribed geometries\n");
159 if (output_vc==
"yes" || output_vc==
"text" || output_vc==
"gzip") {
160 writeVolumeCorrection();
170 EGS_AEnvelope::~EGS_AEnvelope() {
179 int end = (int)(
sizeof(allowed_base_geom_types)/
sizeof(string));
181 for (
int i=0; i<end; i++) {
182 if (allowed_base_geom_types[i] == geom_type) {
190 int EGS_AEnvelope::getGlobalRegFromLocalReg(
EGS_BaseGeometry *g,
int local_reg) {
196 map<volcor::GeomRegPairT, int>::const_iterator glob_it = local_to_global_reg.find(local);
197 if (glob_it != local_to_global_reg.end()) {
198 return (*glob_it).second;
205 map<int, volcor::GeomRegPairT>::const_iterator glob_it = global_reg_to_local.find(ireg);
206 if (glob_it != global_reg_to_local.end()) {
207 return (*glob_it).second;
212 int EGS_AEnvelope::getNRegWithInscribed()
const {
213 return nreg_with_inscribed;
216 bool EGS_AEnvelope::isRealRegion(
int ireg)
const {
218 bool is_outside = ireg < 0 || ireg >=
nreg;
223 bool in_base_geom = ireg <
nregbase;
229 local = getLocalFromGlobalReg(ireg);
230 return local.first->isRealRegion(local.second);
235 bool EGS_AEnvelope::isInside(
const EGS_Vector &x) {
240 int EGS_AEnvelope::isWhere(
const EGS_Vector &x) {
245 vector<EGS_BaseGeometry *> geoms_in_reg = getGeomsInRegion(base_reg);
247 if (base_reg < 0 || geoms_in_reg.size()==0) {
253 for (vector<EGS_BaseGeometry *>::iterator geom=geoms_in_reg.begin(); geom!= geoms_in_reg.end(); ++geom) {
254 int inscribed_reg = (*geom)->isWhere(x);
255 if (inscribed_reg >= 0) {
256 return getGlobalRegFromLocalReg(*geom, inscribed_reg);
264 int EGS_AEnvelope::inside(
const EGS_Vector &x) {
268 int EGS_AEnvelope::medium(
int ireg)
const {
276 return local.first->medium(local.second);
279 vector<EGS_BaseGeometry *> EGS_AEnvelope::getGeomsInRegion(
int ireg) {
281 vector<EGS_BaseGeometry *> empty;
284 return geoms_in_region[ireg];
287 int EGS_AEnvelope::computeIntersections(
int ireg,
int n,
const EGS_Vector &X,
311 bool outside_envelope = ireg < 0;
312 bool in_base_geom = ireg >= 0 && ireg <
nregbase;
314 if (outside_envelope) {
318 ireg = howfar(ireg,x,u,t,&imed);
319 bool would_not_intersect = ireg < 0;
321 if (would_not_intersect) {
326 isections[0].
rhof = 1;
327 isections[0].
ireg = -1;
328 isections[0].
imed = -1;
353 isections[isec_idx].
imed = imed;
354 isections[isec_idx].
ireg = ireg;
355 isections[isec_idx].
rhof = getRelativeRho(ireg);
365 vector<EGS_BaseGeometry *> geoms_in_reg = getGeomsInRegion(ireg);
366 for (vector<EGS_BaseGeometry *>::iterator geom=geoms_in_reg.begin(); geom!= geoms_in_reg.end(); ++geom) {
368 int inscribed_reg = (*geom)->howfar(-1, x, u, t, &imed);
370 bool hits_inscribed = inscribed_reg >= 0;
372 if (hits_inscribed) {
373 ireg = getGlobalRegFromLocalReg(*geom, inscribed_reg);
378 isections[isec_idx++].
t = ttot;
400 int max_isec = n - isec_idx;
402 int ninter_sec = local.first->computeIntersections(local.second, max_isec,
403 x, u, &isections[isec_idx]);
406 int nmax = ninter_sec >= 0 ? ninter_sec + isec_idx : n;
407 for (
int i=isec_idx; i < nmax; i++) {
408 isections[i].
ireg = getGlobalRegFromLocalReg(local.first, isections[i].ireg);
409 isections[i].
t += ttot;
413 if (ninter_sec < 0) {
417 isec_idx += ninter_sec;
423 t = isections[isec_idx-1].
t - ttot;
425 ttot = isections[isec_idx-1].
t;
447 bool in_base_geom = ireg <
nregbase;
463 EGS_Float &t,
int *newmed,
EGS_Vector *normal) {
465 bool inside_geom = ireg >= 0;
468 bool inside_base_geom = ireg <
nregbase;
470 if (inside_base_geom) {
473 vector<EGS_BaseGeometry *> geoms_in_reg = getGeomsInRegion(ireg);
475 bool no_inscribed_in_reg = geoms_in_reg.size() == 0;
476 if (no_inscribed_in_reg) {
480 int inscribed_global = -1;
481 for (vector<EGS_BaseGeometry *>::iterator geom=geoms_in_reg.begin(); geom!= geoms_in_reg.end(); ++geom) {
482 int local_reg = (*geom)->howfar(-1, x, u, t, newmed, normal);
483 bool hits_inscribed = local_reg >= 0;
484 if (hits_inscribed) {
485 inscribed_global = getGlobalRegFromLocalReg(*geom, local_reg);
489 bool hit_inscribed_first = inscribed_global >= 0;
491 if (hit_inscribed_first) {
492 return inscribed_global;
503 int new_local = local.first->howfar(local.second, x, u, t, newmed, normal);
504 bool hit_boundary_in_inscribed = new_local >=0;
505 if (hit_boundary_in_inscribed) {
506 return getGlobalRegFromLocalReg(local.first, new_local);
512 if (inew >= 0 && newmed) {
522 vector<EGS_BaseGeometry *> geoms_in_reg = getGeomsInRegion(new_base_reg);
523 bool has_geoms_in_reg = geoms_in_reg.size() > 0;
526 if (new_base_reg >= 0 && has_geoms_in_reg) {
529 for (vector<EGS_BaseGeometry *>::iterator geom=geoms_in_reg.begin(); geom!= geoms_in_reg.end(); ++geom) {
530 int new_local_reg = (*geom)->isWhere(x+u*t);
531 bool landed_in_inscribed = new_local_reg >= 0;
532 if (landed_in_inscribed) {
534 *newmed = (*geom)->medium(new_local_reg);
536 return getGlobalRegFromLocalReg(*geom, new_local_reg);
546 EGS_Float EGS_AEnvelope::hownear(
int ireg,
const EGS_Vector &x) {
547 bool inside_envelope = ireg >= 0;
549 if (!inside_envelope) {
553 bool in_base_geom = ireg <
nregbase ;
556 return local.first->hownear(local.second, x);
563 vector<EGS_BaseGeometry *> geoms_in_reg = getGeomsInRegion(ireg);
564 for (vector<EGS_BaseGeometry *>::iterator geom=geoms_in_reg.begin(); geom!= geoms_in_reg.end(); ++geom) {
565 EGS_Float local_t = (*geom)->hownear(-1, x);
566 if (local_t < tmin) {
576 bool EGS_AEnvelope::hasBooleanProperty(
int ireg, EGS_BPType prop)
const {
577 if (ireg >= 0 && ireg <
nreg) {
582 return local.first->hasBooleanProperty(local.second, prop);
587 void EGS_AEnvelope::setBooleanProperty(EGS_BPType prop) {
588 setPropertyError(
"setBooleanProperty()");
591 void EGS_AEnvelope::addBooleanProperty(
int bit) {
592 setPropertyError(
"addBooleanProperty()");
595 void EGS_AEnvelope::setBooleanProperty(EGS_BPType prop,
int start,
int end,
int step) {
596 setPropertyError(
"setBooleanProperty()");
599 void EGS_AEnvelope::addBooleanProperty(
int bit,
int start,
int end,
int step) {
600 setPropertyError(
"addBooleanProperty()");
603 int EGS_AEnvelope::getMaxStep()
const {
620 void EGS_AEnvelope::updatePosition(EGS_Float time) {
629 void EGS_AEnvelope::containsDynamic(
bool &hasdynamic) {
643 EGS_Float EGS_AEnvelope::getVolume(
int ireg) {
654 return local.first->getVolume(local.second);
657 EGS_Float EGS_AEnvelope::getCorrectionRatio(
int ireg) {
671 void EGS_AEnvelope::printInfo()
const {
677 for (
int ir=0; ir <
nregbase; ir++) {
679 egsInformation(
" volume of region %d was corrected from %.5E g to %.5E g\n",
684 for (
int ir=0; ir <
nregbase; ir++) {
685 if (geoms_in_region[ir].size() > 0) {
686 egsInformation(
" region %d has %d inscribed geometries\n", ir, geoms_in_region[ir].size());
698 egsInformation(
"=======================================================\n");
701 void EGS_AEnvelope::writeVCToFile(ostream &out) {
703 vector<int> to_write;
708 bool has_correction = fabs(cor-uncor) > 1E-8;
709 if (has_correction) {
710 to_write.push_back(i);
714 size_t nrecords = to_write.size();
715 out << nrecords << endl;
717 for (
size_t i=0; i<to_write.size(); i++) {
718 int ir = to_write[i];
722 vector<EGS_BaseGeometry *> geoms_in_reg = getGeomsInRegion(ir);
723 vector<int> geom_idxs_in_reg;
724 for (
size_t i=0; i<geoms_in_reg.size(); i++) {
727 geom_idxs_in_reg.push_back(pos);
731 int ninscribed = (int)geom_idxs_in_reg.size();
733 out << ir <<
" " << cor;
736 for (
size_t gidx = 0; gidx < geom_idxs_in_reg.size(); gidx++) {
737 out <<
" " <<geom_idxs_in_reg[gidx];
744 void EGS_AEnvelope::writeVolumeCorrection() {
746 egsInformation(
"\nVolume Correction Output File \n%s\n",
string(80,
'=').c_str());
749 string fname = gname+
".autoenv.volcor";
750 fname += (output_vc ==
"gzip" ?
".gz" :
"");
751 string mode = (output_vc ==
"gzip" ?
"gzip" :
"text");
754 "Writing volume correction file for %s to %s file %s\n",
755 gname.c_str(), mode.c_str(), fname.c_str());
757 if (output_vc ==
"gzip") {
759 ogzstream outgz(fname.c_str());
760 writeVCToFile(outgz);
765 ofstream out(fname.c_str());
774 bool EGS_AEnvelope::getHasRhoScaling() {
781 for (
size_t geom_idx=0; geom_idx <
inscribed_geoms.size(); geom_idx++) {
792 egsWarning(
"EGS_AEnvelope::setMedia: don't use this method. Use the\n"
793 " setMedia() methods of the geometry objects that make up this geometry\n");
797 void EGS_AEnvelope::setRelativeRho(
int start,
int end, EGS_Float rho) {
802 void EGS_AEnvelope::setRelativeRho(
EGS_Input *) {
803 egsWarning(
"EGS_AEnvelope::setRelativeRho(): don't use this method."
804 " Use the\n setRelativeRho methods of the geometry objects that make up"
809 EGS_Float EGS_AEnvelope::getRelativeRho(
int ireg)
const {
810 if (ireg < 0 || ireg >=
nreg) {
819 return local.first->getRelativeRho(local.second);
830 const vector<AEnvelopeAux> inscribed,
const string &Name,
bool debug,
string output_vc_file):
831 EGS_AEnvelope(base_geom, inscribed, Name, debug, output_vc_file) {
843 vector<EGS_BaseGeometry *> EGS_ASwitchedEnvelope::getGeomsInRegion(
int ireg) {
845 vector<EGS_BaseGeometry *> active_in_reg;
846 if ((0 <= ireg) && (ireg <
nregbase)) {
848 geoms_in_region[ireg].begin(), geoms_in_region[ireg].end(),
849 active_inscribed.begin(), active_inscribed.end(),
850 back_inserter(active_in_reg)
854 return active_in_reg;
860 active_inscribed.clear();
861 active_inscribed = geoms;
863 if (geoms.size() <= 0) {
878 active_inscribed.clear();
880 for (
size_t i = 0; i < geom_indexes.size(); i++) {
881 int idx = geom_indexes[i];
883 egsFatal(
"EGS_ASwitchedEnvelope:: %d is not a valid geometry index\n", idx);
888 cur_ptr = geom_indexes[0];
895 if ((0 <= ireg) && (ireg <
nregbase)) {
896 size_t nactive = getGeomsInRegion(ireg).size();
906 if ((0 <= ireg) && (ireg <
nregbase)) {
907 size_t nactive = getGeomsInRegion(ireg).size();
908 size_t ntotal = EGS_AEnvelope::getGeomsInRegion(ireg).size();
909 return nactive < ntotal;
917 vector<EGS_BaseGeometry *> to_activate;
920 cur_ptr = inscribed_index;
928 vector<EGS_BaseGeometry *>::iterator loc = find(
929 active_inscribed.begin(), active_inscribed.end(),
932 if (loc != active_inscribed.end()) {
933 active_inscribed.erase(loc);
938 cur_ptr = cur_ptr ==
ninscribed -1 ? 0 : cur_ptr + 1;
939 vector<EGS_BaseGeometry *> to_activate;
954 egsWarning(
"Invalid transform input given\n");
978 vector<string> debug_choices;
979 debug_choices.push_back(
"no");
980 debug_choices.push_back(
"yes");
981 debug = input->
getInput(
"print debug info", debug_choices, 0);
983 int output_vc_file_choice;
984 vector<string> vc_file_choices;
985 vc_file_choices.push_back(
"no");
986 vc_file_choices.push_back(
"yes");
987 vc_file_choices.push_back(
"text");
988 vc_file_choices.push_back(
"gzip");
989 output_vc_file_choice = input->
getInput(
"output volume correction file", vc_file_choices, 0);
990 string output_vc_file = vc_file_choices[output_vc_file_choice];
993 if (output_vc_file ==
"gzip") {
995 "GZip file output requested but not compiled with gzstream.\n"
996 "Please recompile with gzstream support.\n"
1004 string base_geom_name;
1005 int err = input->
getInput(base_geom_keyword, base_geom_name);
1007 egsWarning(geom_class_msg, (
"'"+
string(base_geom_keyword)+
"' input not found").c_str());
1012 err = input->
getInput(type_keyword, type);
1019 egsWarning(geom_class_msg, (
"Unable to find geometry '"+base_geom_name+
"'").c_str());
1024 if (!inscribed_input) {
1025 egsWarning(geom_class_msg, (
"Missing '"+
string(inscribed_geom_keyword)+
"' input item").c_str());
1029 string inscribed_geom_name;
1030 err = inscribed_input->
getInput(inscribed_geom_name_keyword, inscribed_geom_name);
1032 egsWarning(geom_class_msg, (
"'"+
string(inscribed_geom_name_keyword)+
"' input not found").c_str());
1037 if (!inscribed_geom) {
1038 egsWarning(geom_class_msg, (
"Unable to find geometry '"+inscribed_geom_name+
"'").c_str());
1042 vector<EGS_AffineTransform *> transforms;
1052 if (!vcopts->
valid) {
1053 egsWarning(geom_class_msg,
"Missing or invalid 'region discovery' input item");
1057 delete inscribed_input;
1060 vector<AEnvelopeAux> inscribed;
1061 if (transforms.size()>0) {
1062 for (
size_t i=0; i < transforms.size(); i++) {
1063 inscribed.push_back(
AEnvelopeAux(inscribed_geom, transforms[i], vcopts));
1068 inscribed.push_back(
AEnvelopeAux(inscribed_geom, unityt, vcopts));
1072 if (type ==
"EGS_ASwitchedEnvelope") {
1076 result =
new EGS_AEnvelope(base_geom, inscribed,
"", (
bool)debug, output_vc_file);
A fast envelope geometry with automatic region detection.
vector< EGS_BaseGeometry * > inscribed_geoms
The inscribed geometries.
static string type
Geometry type.
vector< EGS_AffineTransform * > transforms
The inscribed geometries.
EGS_BaseGeometry * base_geom
The envelope geometry.
static vector< EGS_AffineTransform * > createTransforms(EGS_Input *inpt)
Take a block of transformations and return vector of EGS_AffineTransforms.
static bool allowedBaseGeomType(const string &geom_type)
function for checking whether a given geometry type is allowed to be used as a base geometry
int nregbase
Number of regions in the base geometry.
void setMedia(EGS_Input *, int, const int *)
Don't set media for an envelope geometry.
int ninscribed
Number of regions in the base geometry.
This geometry type allows you to activate and deactivate inscribed geometries in custom egspp user co...
void deactivateByIndex(int inscribed_index)
bool hasInactiveGeom(int ireg)
void activateByIndex(int inscribed_index)
void setActiveGeometries(vector< EGS_BaseGeometry * > geoms)
void setActiveByIndex(int inscribed_index)
static string type
Geometry type.
bool hasActiveGeom(int ireg)
Base geometry class. Every geometry class must be derived from EGS_BaseGeometry.
virtual EGS_Float hownear(int ireg, const EGS_Vector &x)=0
Calculate the distance to a boundary for position x in any direction.
int deref()
Decrease the reference count to this geometry.
virtual bool hasBooleanProperty(int ireg, EGS_BPType prop) const
Is the boolean property prop set for region ireg ?
virtual EGS_Float howfarToOutside(int ireg, const EGS_Vector &x, const EGS_Vector &u)
virtual const string & getType() const =0
Get the geometry type.
int nreg
Number of local regions in this geometry.
virtual int howfar(int ireg, const EGS_Vector &x, const EGS_Vector &u, EGS_Float &t, int *newmed=0, EGS_Vector *normal=0)=0
Calculate the distance to a boundary from x along the direction u.
bool has_rho_scaling
Does this geometry have relative mass density scvaling?
virtual bool isRealRegion(int ireg) const
Returnes true if ireg is a real region, false otherwise.
void setName(EGS_Input *inp)
Set the name of the geometry from the input inp.
virtual bool isInside(const EGS_Vector &x)=0
Is the position x inside the geometry?
const string & getName() const
Get the name of this geometry.
virtual EGS_Float getRelativeRho(int ireg) const
Get the relative mass density in region ireg.
bool isConvex() const
Is the geometry convex?
virtual int getMaxStep() const
Returns the maximum number of steps through the geometry.
bool hasRhoScaling() const
Does this geometry object have a mass density scaling feature?
virtual int medium(int ireg) const
Returns the medium index in region ireg.
int regions() const
Returns the number of local regions in this geometry.
virtual void printInfo() const
Print information about this geometry.
int ref()
Increase the reference count to this geometry.
static EGS_BaseGeometry * getGeometry(const string &Name)
Get a pointer to the geometry named Name.
virtual int isWhere(const EGS_Vector &x)=0
In which region is poisition x?
Base random number generator class. All random number generators should be derived from this class.
A class representing 3D vectors.
Volume correction initialization helper class.
An envelope geometry with automatic inscribed region detection (inspired by EGS_FastEnvelope)
EGS_GLIB_EXPORT EGS_BaseGeometry * createGeometry(EGS_Input *input)
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 egsFatal
Always use this function for reporting fatal errors.
EGS_InfoFunction EGS_EXPORT egsWarning
Always use this function for reporting warnings.
VCResults findRegionsWithInscribed(VCOptions *opts, EGS_BaseGeometry *base, vector< EGS_BaseGeometry * > inscribed, vector< EGS_AffineTransform * > transforms)
Run the MC simulation.
VCResults loadFileResults(VCOptions *opts, EGS_BaseGeometry *base, vector< EGS_BaseGeometry * > inscribed, vector< EGS_AffineTransform * > transforms)
Load volume corrections from external file.
pair< EGS_BaseGeometry *, int > GeomRegPairT
A helper class for initializing auto envelopes.
EGS_Float t
distance to next region boundary
EGS_Float rhof
relative mass density in that region
vector< EGS_Float > corrected_volumes
void outputResults() const
vector< EGS_Float > uncorrected_volumes