EGSnrc C++ class library  Report PIRS-898 (2021)
Iwan Kawrakow, Ernesto Mainegra-Hing, Frederic Tessier, Reid Townson and Blake Walters
egs_smart_envelope.h
Go to the documentation of this file.
1 /*
2 ###############################################################################
3 #
4 # EGSnrc egs++ smart envelope geometry headers
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, 2008
25 #
26 # Contributors: Frederic Tessier
27 # Ernesto Mainegra-Hing
28 # Alexandre Demelo
29 #
30 ###############################################################################
31 #
32 # A "smart" envelope geometry. The smartness is due to the fact that there
33 # can be only zero or one inscribed geometry per base geometry region, which
34 # makes many of the checks faster.
35 #
36 # In addition, unlike the regular envelope geometry where all inscribed
37 # geometries always must completely fit inside the base geometry, here
38 # geometries can be inscribed using logic 0 or 1.
39 #
40 # Logic 0 is as before, i.e., geometry must completely fit into the region
41 # where it is being inscribed.
42 #
43 # Logic 1 means that the inscribed geometry extends beyond the region and
44 # therefore the smart envelope also checks the base geometry in this case.
45 # This is very similar to a CD geometry except that now the space outside
46 # the inscribed geometry is still part of the geometry.
47 #
48 # Warning: not completely tested, so don't use for production runs yet.
49 #
50 ###############################################################################
51 */
52 
53 
59 #ifndef EGS_SMART_ENVELOPE_
60 #define EGS_SMART_ENVELOPE_
61 
62 #ifdef WIN32
63 
64  #ifdef BUILD_SMART_ENVELOPE_DLL
65  #define EGS_SMART_ENVELOPE_EXPORT __declspec(dllexport)
66  #else
67  #define EGS_SMART_ENVELOPE_EXPORT __declspec(dllimport)
68  #endif
69  #define EGS_SMART_ENVELOPE_LOCAL
70 
71 #else
72 
73  #ifdef HAVE_VISIBILITY
74  #define EGS_SMART_ENVELOPE_EXPORT __attribute__ ((visibility ("default")))
75  #define EGS_SMART_ENVELOPE_LOCAL __attribute__ ((visibility ("hidden")))
76  #else
77  #define EGS_SMART_ENVELOPE_EXPORT
78  #define EGS_SMART_ENVELOPE_LOCAL
79  #endif
80 
81 #endif
82 
83 
84 #include "egs_base_geometry.h"
85 #include "egs_functions.h"
86 
87 #include<vector>
88 using std::vector;
89 
135 //#include "egs_functions.h"
136 
137 struct SmartEnvelopeAux;
138 
139 class EGS_SMART_ENVELOPE_EXPORT EGS_SmartEnvelope : public EGS_BaseGeometry {
140 
141 public:
142 
144  const vector<SmartEnvelopeAux *> &fgeoms, const string &Name = "");
145 
147 
148  bool isInside(const EGS_Vector &x) {
149  return g->isInside(x);
150  };
151 
152  int isWhere(const EGS_Vector &x) {
153  int ibase = g->isWhere(x);
154  if (ibase < 0) {
155  return ibase;
156  }
157  int j = gindex[ibase];
158  if (j >= 0) {
159  int i = geometries[j]->isWhere(x);
160  if (i >= 0) {
161  ibase = local_start[j] + i;
162  }
163  }
164  return ibase;
165  };
166 
167  int inside(const EGS_Vector &x) {
168  return isWhere(x);
169  };
170 
171  bool isRealRegion(int ireg) const {
172  if (ireg < nbase) {
173  return g->isRealRegion(ireg);
174  }
175  int i = ireg - nbase;
176  int j = reg_to_inscr[i];
177  return geometries[j]->isRealRegion(ireg-local_start[j]);
178  };
179 
180  int medium(int ireg) const {
181  if (ireg < nbase) {
182  return g->medium(ireg);
183  }
184  int i = ireg - nbase;
185  int j = reg_to_inscr[i];
186  return geometries[j]->medium(ireg-local_start[j]);
187  };
188 
189  EGS_Float howfarToOutside(int ireg, const EGS_Vector &x,
190  const EGS_Vector &u) {
191  if (ireg < 0) {
192  return 0;
193  }
194  int ibase = ireg < nbase ? ireg : reg_to_base[ireg-nbase];
195  return g->howfarToOutside(ibase,x,u);
196  };
197 
198  int howfar(int ireg, const EGS_Vector &x, const EGS_Vector &u,
199  EGS_Float &t, int *newmed = 0, EGS_Vector *normal = 0) {
200  if (ireg >= 0) {
201  // inside.
202  if (ireg < nbase) {
203  // in one of the regions of the base geometry
204  // check if we hit a boundary in the base geometry.
205  // if we do, newmed and normal get set accordingly.
206  int ibase = g->howfar(ireg,x,u,t,newmed,normal);
207  int j = gindex[ireg];
208  if (j >= 0) {
209  // there is an inscribed geometry in this region
210  // => check if we will enter
211  int inscr = geometries[j]->howfar(-1,x,u,t,newmed,normal);
212  if (inscr >= 0)
213  // yes, we do.
214  {
215  return local_start[j] + inscr;
216  }
217  }
218  if (ibase == ireg || ibase < 0) {
219  return ibase;
220  }
221  // if here, we enter a new base geometry region.
222  j = gindex[ibase];
223  if (j >= 0 && itype[j]) {
224  // geometry inscribed in the new base region
225  // using inscription type 1 => check if already
226  // inside the inscribed
227  int inscr = geometries[j]->isWhere(x+u*t);
228  if (inscr >= 0) {
229  if (newmed) {
230  *newmed = geometries[j]->medium(inscr);
231  }
232  return local_start[j] + inscr;
233  }
234  }
235  return ibase;
236  }
237  // if here, we are in an inscribed geometry.
238  int i = ireg-nbase;
239  int ibase = reg_to_base[i];
240  int j = reg_to_inscr[i];
241  int ilocal = ireg-local_start[j];
242  int inew = geometries[j]->howfar(ilocal,x,u,t,newmed,normal);
243  if (itype[j]) {
244  int ibase_new = g->howfar(ibase,x,u,t,newmed,normal);
245  if (ibase_new != ibase) {
246  if (ibase_new < 0) {
247  return ibase_new;
248  }
249  j = gindex[ibase_new];
250  if (j >= 0 && itype[j]) {
251  int inscr = geometries[j]->isWhere(x+u*t);
252  if (inscr >= 0) {
253  if (newmed) {
254  *newmed = geometries[j]->medium(inscr);
255  }
256  return local_start[j] + inscr;
257  }
258  }
259  return ibase_new;
260  }
261  }
262  if (inew < 0) {
263  if (newmed) {
264  *newmed = g->medium(ibase);
265  }
266  return ibase;
267  }
268  return local_start[j] + inew;
269  }
270  // if here, we are outside the base geometry.
271  // check to see if we will enter.
272  int ibase = g->howfar(ireg,x,u,t,newmed,normal);
273  if (ibase >= 0) {
274  int j = gindex[ibase];
275  if (j >= 0 && itype[j]) {
276  int inscr = geometries[j]->isWhere(x+u*t);
277  if (inscr >= 0) {
278  if (newmed) {
279  *newmed = geometries[j]->medium(inscr);
280  }
281  return local_start[j] + inscr;
282  }
283  }
284  }
285  return ibase;
286  };
287 
288  EGS_Float hownear(int ireg, const EGS_Vector &x) {
289  if (ireg >= 0) {
290  EGS_Float tmin;
291  if (ireg < nbase) { // in one of the regions of the base geom.
292  tmin = g->hownear(ireg,x);
293  if (tmin <= 0) {
294  return tmin;
295  }
296  int j = gindex[ireg];
297  if (j >= 0) {
298  EGS_Float ti = geometries[j]->hownear(-1,x);
299  if (ti < tmin) {
300  tmin = ti;
301  }
302  }
303  return tmin;
304  }
305  int i = ireg-nbase;
306  int j = reg_to_inscr[i];
307  int ilocal = ireg-local_start[j];
308  tmin = geometries[j]->hownear(ilocal,x);
309  if (itype[j]) {
310  int ibase = reg_to_base[i];
311  EGS_Float tbase = g->hownear(ibase,x);
312  if (tbase < tmin) {
313  tmin = tbase;
314  }
315  }
316  return tmin;
317  }
318  return g->hownear(ireg,x);
319  };
320 
321  void getNextGeom(EGS_RandomGenerator *rndm) {
322  // calls getNextGeom on its component geometries to update dynamic
323  // geometries in the simulation
324  for (int j=0; j<n_in; j++) {
325  geometries[j]->getNextGeom(rndm);
326  }
327  g->getNextGeom(rndm);
328  };
329 
330  void updatePosition(EGS_Float time) {
331  // calls updatePosition on its component geometries to update dynamic
332  // geometries in the simulation
333  for (int j=0; j<n_in; j++) {
334  geometries[j]->updatePosition(time);
335  }
336  g->updatePosition(time);
337  };
338 
339  void containsDynamic(bool &hasdynamic) {
340  // calls containsDynamic on its component geometries (only calls if
341  // hasDynamic is false, as if it is true we already found one)
342  for (int j=0; j<n_in; j++) {
343  if (!hasdynamic) {
344  geometries[j]->containsDynamic(hasdynamic);
345  }
346  }
347  if (!hasdynamic) {
348  g->containsDynamic(hasdynamic);
349  }
350  };
351 
352  int getMaxStep() const {
353  int nstep = g->getMaxStep() + n_in;
354  for (int j=0; j<n_in; ++j) {
355  nstep += geometries[j]->getMaxStep();
356  }
357  return nstep;
358  };
359 
360  bool hasBooleanProperty(int ireg, EGS_BPType prop) const {
361  if (ireg >= 0 && ireg < nreg) {
362  if (ireg < nbase) {
363  return g->hasBooleanProperty(ireg,prop);
364  }
365  int i = ireg-nbase, j = reg_to_inscr[i];
366  return geometries[j]->hasBooleanProperty(ireg-local_start[j],prop);
367  }
368  return false;
369  };
370  void setBooleanProperty(EGS_BPType) {
371  setPropertyError("setBooleanProperty()");
372  };
373  void addBooleanProperty(int) {
374  setPropertyError("addBooleanProperty()");
375  };
376  void setBooleanProperty(EGS_BPType,int,int,int step=1) {
377  setPropertyError("setBooleanProperty()");
378  };
379  void addBooleanProperty(int,int,int,int step=1) {
380  setPropertyError("addBooleanProperty()");
381  };
382 
383  const string &getType() const {
384  return type;
385  };
386 
387  void printInfo() const;
388 
389  void setRelativeRho(int start, int end, EGS_Float rho);
390  void setRelativeRho(EGS_Input *);
391  EGS_Float getRelativeRho(int ireg) const {
392  if (ireg < 0 || ireg >= nreg) {
393  return 1;
394  }
395  if (ireg < nbase) {
396  return g->getRelativeRho(ireg);
397  }
398  int i = ireg-nbase;
399  int j = reg_to_inscr[i];
400  return geometries[j]->getRelativeRho(ireg-local_start[j]);
401  };
402 
403  void setBScaling(int start, int end, EGS_Float bf);
404  void setBScaling(EGS_Input *);
405  EGS_Float getBScaling(int ireg) const {
406  if (ireg < 0 || ireg >= nreg) {
407  return 1;
408  }
409  if (ireg < nbase) {
410  return g->getBScaling(ireg);
411  }
412  int i = ireg-nbase;
413  int j = reg_to_inscr[i];
414  return geometries[j]->getBScaling(ireg-local_start[j]);
415  };
416 
417  virtual void getLabelRegions(const string &str, vector<int> &regs);
418 
419 protected:
420 
423  int *gindex;
425  int *reg_to_base;
426  int *local_start;
427  char *itype;
428  int n_in;
429  int nbase;
430 
431  static string type;
432 
439  void setMedia(EGS_Input *,int,const int *);
440 
441 private:
442 
443  void setPropertyError(const char *funcname) {
444  egsFatal("EGS_SmartEnvelope::%s: don't use this method\n Define "
445  "properties in the constituent geometries instead\n",
446  funcname);
447  };
448 
449 
450 };
451 
452 #endif
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.
virtual int inside(const EGS_Vector &x)=0
Returns the region index, if inside, or -1 if outside (obsolete)
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 EGS_Float getBScaling(int ireg) const
Get the B field scaling factor in region ireg.
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.
virtual const string & getType() const =0
Get the geometry type.
virtual void getLabelRegions(const string &str, vector< int > &regs)
Get the list of all regions labeled with str.
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.
virtual bool isRealRegion(int ireg) const
Returnes true if ireg is a real region, false otherwise.
virtual bool isInside(const EGS_Vector &x)=0
Is the position x inside the geometry?
virtual EGS_Float getRelativeRho(int ireg) const
Get the relative mass density in region ireg.
virtual void setBooleanProperty(EGS_BPType prop)
Set the boolean properties of the entire geometry to prop.
virtual int getMaxStep() const
Returns the maximum number of steps through the geometry.
virtual int medium(int ireg) const
Returns the medium index in region ireg.
virtual void setRelativeRho(int start, int end, EGS_Float rho)
Set the relative mass density in regions.
virtual void printInfo() const
Print information about this geometry.
virtual void addBooleanProperty(int bit)
Add a boolean property for the entire geometry by setting the bit'th bit.
virtual int isWhere(const EGS_Vector &x)=0
In which region is poisition x?
A class for storing information in a tree-like structure of key-value pairs. This class is used throu...
Definition: egs_input.h:182
Base random number generator class. All random number generators should be derived from this class.
Definition: egs_rndm.h:67
int n_in
Number of inscribed geometries.
int * gindex
Index of inscribed geometries.
EGS_BaseGeometry * g
The envelope geometry.
int * local_start
First region for each inscribed geometry.
int * reg_to_inscr
Region to inscribed geometry conversion.
static string type
Geometry type.
int * reg_to_base
Region to base region conversion.
EGS_BaseGeometry ** geometries
The inscribed geometries.
int nbase
Number of regions in the base geometry.
A class representing 3D vectors.
Definition: egs_vector.h:57
EGS_BaseGeometry class header file.
Global egspp functions header file.
EGS_InfoFunction EGS_EXPORT egsFatal
Always use this function for reporting fatal errors.