EGSnrc C++ class library  Report PIRS-898 (2021)
Iwan Kawrakow, Ernesto Mainegra-Hing, Frederic Tessier, Reid Townson and Blake Walters
egs_envelope_geometry.cpp
Go to the documentation of this file.
1 /*
2 ###############################################################################
3 #
4 # EGSnrc egs++ envelope 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 # Ernesto Mainegra-Hing
28 # Marc Chamberland
29 #
30 ###############################################################################
31 */
32 
33 
39 #include "egs_envelope_geometry.h"
40 #include "egs_input.h"
41 #include "egs_functions.h"
42 
43 #include <cstdlib>
44 
45 using namespace std;
46 
47 string EGS_ENVELOPEG_LOCAL EGS_EnvelopeGeometry::type = "EGS_EnvelopeGeometry";
48 string EGS_ENVELOPEG_LOCAL EGS_FastEnvelope::type = "EGS_FastEnvelope";
49 
50 void EGS_EnvelopeGeometry::setMedia(EGS_Input *,int,const int *) {
51  egsWarning("EGS_EnvelopeGeometry::setMedia: don't use this method. Use the\n"
52  " setMedia() methods of the geometry objects that make up this geometry\n");
53 }
54 
55 void EGS_EnvelopeGeometry::setRelativeRho(int start, int end, EGS_Float rho) {
56  setRelativeRho(0);
57 }
58 
59 void EGS_EnvelopeGeometry::setRelativeRho(EGS_Input *) {
60  egsWarning("EGS_EnvelopeGeometry::setRelativeRho(): don't use this method."
61  " Use the\n setRelativeRho methods of the geometry objects that make up"
62  " this geometry\n");
63 }
64 
65 void EGS_EnvelopeGeometry::setBScaling(int start, int end, EGS_Float bf) {
66  setBScaling(0);
67 }
68 
69 void EGS_EnvelopeGeometry::setBScaling(EGS_Input *) {
70  egsWarning("EGS_EnvelopeGeometry::setBScaling(): don't use this method."
71  " Use the\n setBScaling methods of the geometry objects that make up"
72  " this geometry\n");
73 }
74 
75 void EGS_FastEnvelope::setMedia(EGS_Input *,int,const int *) {
76  egsWarning("EGS_FastEnvelope::setMedia: don't use this method. Use the\n"
77  " setMedia() methods of the geometry objects that make up this geometry\n");
78 }
79 
80 void EGS_FastEnvelope::setRelativeRho(int start, int end, EGS_Float rho) {
81  setRelativeRho(0);
82 }
83 
84 void EGS_FastEnvelope::setRelativeRho(EGS_Input *) {
85  egsWarning("EGS_FastEnvelope::setRelativeRho(): don't use this method."
86  " Use the\n setRelativeRho methods of the geometry objects that make up"
87  " this geometry\n");
88 }
89 
90 void EGS_FastEnvelope::setBScaling(int start, int end, EGS_Float bf) {
91  setBScaling(0);
92 }
93 
94 void EGS_FastEnvelope::setBScaling(EGS_Input *) {
95  egsWarning("EGS_FastEnvelope::setBScaling(): don't use this method."
96  " Use the\n setBScaling methods of the geometry objects that make up"
97  " this geometry\n");
98 }
99 
100 struct EGS_ENVELOPEG_LOCAL EnvelopeAux {
101  EGS_BaseGeometry *g;
102  int nreg;
103  int *regs;
104  EnvelopeAux() : nreg(0) {};
105  ~EnvelopeAux() {
106  if (nreg>0) {
107  delete [] regs;
108  }
109  };
110 };
111 
112 EGS_EnvelopeGeometry::EGS_EnvelopeGeometry(EGS_BaseGeometry *G,
113  const vector<EGS_BaseGeometry *> &geoms, const string &Name,
114  bool newindexing) :
115  EGS_BaseGeometry(Name), reg_to_inscr(0), local_start(0) {
116  if (!G) {
117  egsFatal("EGS_EnvelopeGeometry: base geometry must not be null\n");
118  }
119  g = G;
120  g->ref();
121  new_indexing = false;
122  nbase = g->regions();
123  n_in = geoms.size();
124  nmax = 1;
125  int nreg_inscribed = 0;
126  if (n_in > 0) {
127  geometries = new EGS_BaseGeometry * [n_in];
128  for (int j=0; j<n_in; j++) {
129  geometries[j] = geoms[j];
130  geometries[j]->ref();
131  int nj = geometries[j]->regions();
132  if (nj > nmax) {
133  nmax = nj;
134  }
135  nreg_inscribed += nj;
136  }
137  }
138  nreg = nbase + n_in*nmax;
139  is_convex = g->isConvex();
140 
141  has_rho_scaling = g->hasRhoScaling();
142  if (!has_rho_scaling) {
143  for (int j=0; j<n_in; j++) {
144  if (geometries[j]->hasRhoScaling()) {
145  has_rho_scaling = true;
146  break;
147  }
148  }
149  }
150  has_B_scaling = g->hasBScaling();
151  if (!has_B_scaling) {
152  for (int j=0; j<n_in; j++) {
153  if (geometries[j]->hasBScaling()) {
154  has_B_scaling = true;
155  break;
156  }
157  }
158  }
159 
160  if (!n_in) {
161  return;
162  }
163  if (newindexing) {
164  new_indexing = true;
165  local_start = new int [n_in];
166  reg_to_inscr = new int [nreg_inscribed];
167  int ir=0;
168  for (int j=0; j<n_in; j++) {
169  int n = geometries[j]->regions();
170  local_start[j] = nbase + ir;
171  for (int i=0; i<n; i++) {
172  reg_to_inscr[ir++] = j;
173  }
174  }
175  nreg = nbase + ir;
176  }
177 }
178 
179 EGS_FastEnvelope::EGS_FastEnvelope(EGS_BaseGeometry *G,
180  const vector<EnvelopeAux *> &fgeoms, const string &Name,
181  int newindexing) :
182  EGS_BaseGeometry(Name), reg_to_inscr(0), local_start(0) {
183  if (!G) {
184  egsFatal("EGS_FastEnvelope: base geometry must not be null\n");
185  }
186  g = G;
187  g->ref();
188  n_in = fgeoms.size();
189  nmax = 1;
190  new_indexing = false;
191  if (!n_in) {
192  egsFatal("EGS_FastEnvelope: no inscribed geometries!\n");
193  }
194  geometries = new EGS_BaseGeometry * [n_in];
195  nbase = g->regions();
196  int *iaux = new int [nbase];
197  int j;
198  for (j=0; j<nbase; j++) {
199  iaux[j] = 0;
200  }
201  int nlist = 0;
202  int nreg_inscribed = 0;
203  for (j=0; j<fgeoms.size(); j++) {
204  geometries[j] = fgeoms[j]->g;
205  geometries[j]->ref();
206  int nj = geometries[j]->regions();
207  nreg_inscribed += nj;
208  if (nj > nmax) {
209  nmax = nj;
210  }
211  for (int i=0; i<fgeoms[j]->nreg; i++) {
212  int k = fgeoms[j]->regs[i];
213  if (k >= 0 && k < nbase) {
214  ++iaux[k];
215  ++nlist;
216  }
217  }
218  }
219  n_start = new int [nbase+1];
220  glist = new int [nlist];
221  int ilist=0;
222  for (j=0; j<nbase; j++) {
223  n_start[j] = ilist;
224  if (iaux[j] > 0) {
225  for (int l=0; l<fgeoms.size(); l++) {
226  for (int i=0; i<fgeoms[l]->nreg; i++) {
227  int k = fgeoms[l]->regs[i];
228  if (k == j) {
229  glist[ilist++] = l;
230  }
231  }
232  }
233  }
234  }
235  n_start[nbase] = ilist;
236  nreg = nbase + n_in*nmax;
237  is_convex = g->isConvex();
238  has_rho_scaling = g->hasRhoScaling();
239  if (!has_rho_scaling) {
240  for (int j=0; j<n_in; j++) {
241  if (geometries[j]->hasRhoScaling()) {
242  has_rho_scaling = true;
243  break;
244  }
245  }
246  }
247 
248  has_B_scaling = g->hasBScaling();
249  if (!has_B_scaling) {
250  for (int j=0; j<n_in; j++) {
251  if (geometries[j]->hasBScaling()) {
252  has_B_scaling = true;
253  break;
254  }
255  }
256  }
257 
258  delete [] iaux;
259  if (newindexing) {
260  new_indexing = true;
261  local_start = new int [n_in];
262  reg_to_inscr = new int [nreg_inscribed];
263  int ir=0;
264  for (int j=0; j<n_in; j++) {
265  int n = geometries[j]->regions();
266  local_start[j] = nbase + ir;
267  for (int i=0; i<n; i++) {
268  reg_to_inscr[ir++] = j;
269  }
270  }
271  nreg = nbase + ir;
272  }
273 }
274 
275 EGS_EnvelopeGeometry::~EGS_EnvelopeGeometry() {
276  if (!g->deref()) {
277  delete g;
278  }
279  for (int j=0; j<n_in; j++) {
280  if (!geometries[j]->deref()) {
281  delete geometries[j];
282  }
283  }
284  delete [] geometries;
285  if (new_indexing) {
286  if (local_start) {
287  delete [] local_start;
288  }
289  if (reg_to_inscr) {
290  delete [] reg_to_inscr;
291  }
292  }
293 }
294 
295 EGS_FastEnvelope::~EGS_FastEnvelope() {
296  if (!g->deref()) {
297  delete g;
298  }
299  for (int j=0; j<n_in; j++) {
300  if (!geometries[j]->deref()) {
301  delete geometries[j];
302  }
303  }
304  delete [] geometries;
305  delete [] n_start;
306  delete [] glist;
307  if (new_indexing) {
308  if (local_start) {
309  delete [] local_start;
310  }
311  if (reg_to_inscr) {
312  delete [] reg_to_inscr;
313  }
314  }
315 }
316 
317 void EGS_EnvelopeGeometry::printInfo() const {
319  egsInformation(" base geometry = %s (type %s)\n",g->getName().c_str(),
320  g->getType().c_str());
321  egsInformation(" inscribed geometries:\n");
322  for (int j=0; j<n_in; j++) egsInformation(" %s (type %s)\n",
323  geometries[j]->getName().c_str(),geometries[j]->getType().c_str());
325  "=======================================================\n");
326 }
327 
328 void EGS_FastEnvelope::printInfo() const {
330  egsInformation(" base geometry = %s (type %s)\n",g->getName().c_str(),
331  g->getType().c_str());
332  egsInformation(" inscribed geometries:\n");
333  for (int j=0; j<n_in; j++) egsInformation(" %s (type %s)\n",
334  geometries[j]->getName().c_str(),geometries[j]->getType().c_str());
336  "=======================================================\n");
337 }
338 
339 
340 static char EGS_ENVELOPEG_LOCAL eeg_message1[] =
341  "createGeometry(envelope geometry): %s\n";
342 static char EGS_ENVELOPEG_LOCAL eeg_message2[] =
343  "null input?";
344 static char EGS_ENVELOPEG_LOCAL eeg_message3[] =
345  "no 'base geometry' input?";
346 static char EGS_ENVELOPEG_LOCAL eeg_message4[] =
347  "incorrect base geometry definition";
348 static char EGS_ENVELOPEG_LOCAL eeg_message5[] =
349  "missing/incorrect 'base geometry' input";
350 static char EGS_ENVELOPEG_LOCAL eeg_message6[] =
351  "createGeometry(envelope geometry): no geometry with name %s defined\n";
352 static char EGS_ENVELOPEG_LOCAL eeg_message7[] =
353  "no inscirebed geometries defined?. I hope you know what you are doing";
354 static char EGS_ENVELOPEG_LOCAL eeg_message8[] =
355  "an error occured while constructing inscibed geometries";
356 
357 static char EGS_ENVELOPEG_LOCAL eeg_keyword1[] = "base geometry";
358 static char EGS_ENVELOPEG_LOCAL eeg_keyword2[] = "geometry";
359 static char EGS_ENVELOPEG_LOCAL eeg_keyword3[] = "inscribed geometries";
360 
361 extern "C" {
362 
363  EGS_ENVELOPEG_EXPORT EGS_BaseGeometry *createGeometry(EGS_Input *input) {
364  if (!input) {
365  egsWarning(eeg_message1,eeg_message2);
366  return 0;
367  }
368  //
369  // *** new indexing style
370  //
371  int indexing = 0;
372  input->getInput("new indexing style",indexing);
373  //
374  // *** Base geometry
375  //
376  EGS_Input *i = input->takeInputItem(eeg_keyword1);
377  if (!i) {
378  egsWarning(eeg_message1,eeg_message3);
379  return 0;
380  }
381  EGS_Input *ig = i->takeInputItem(eeg_keyword2);
382  EGS_BaseGeometry *g;
383  if (ig) { // defined inline
385  delete ig;
386  if (!g) {
387  egsWarning(eeg_message1,eeg_message4);
388  delete i;
389  return 0;
390  }
391  }
392  else { // defined via a name of a previously defined geometry
393  string bgname;
394  int err = i->getInput(eeg_keyword1,bgname);
395  delete i;
396  if (err) {
397  egsWarning(eeg_message1,eeg_message5);
398  return 0;
399  }
400  g = EGS_BaseGeometry::getGeometry(bgname);
401  if (!g) {
402  egsWarning(eeg_message6,bgname.c_str());
403  return 0;
404  }
405  }
406  vector<EnvelopeAux *> fgeoms;
407  EGS_Input *ix;
408  while ((ix = input->takeInputItem("inscribe in regions")) != 0) {
409  vector<string> values;
410  ix->getInput("inscribe in regions",values);
411  if (values.size() < 2) egsWarning("createGeometry(envelope geometry):"
412  " %d inputs for 'inscribe in regions'? 2 or more are needed\n",values.size());
413  else {
415  if (!gj) {
416  egsWarning(eeg_message6,values[0].c_str());
417  }
418  else {
419  EnvelopeAux *aux = new EnvelopeAux;
420  aux->g = gj;
421  aux->nreg = values.size()-1;
422  aux->regs = new int [aux->nreg];
423  for (int j=0; j<aux->nreg; j++) {
424  aux->regs[j] = atoi(values[j+1].c_str());
425  }
426  fgeoms.push_back(aux);
427  }
428  }
429  delete ix;
430  }
431  if (fgeoms.size() > 0) {
432  EGS_BaseGeometry *result = new EGS_FastEnvelope(g,fgeoms,"",indexing);
433  result->setName(input);
434  result->setBoundaryTolerance(input);
435  for (int j=0; j<fgeoms.size(); j++) {
436  delete fgeoms[j];
437  }
438  return result;
439  }
440 
441  //
442  // *** Inscribed geometries
443  //
444  i = input->takeInputItem(eeg_keyword3);
445  vector<EGS_BaseGeometry *> geoms;
446  if (!i) {
447  if (fgeoms.size()) {
448  egsWarning(eeg_message1,eeg_message7);
449  }
450  }
451  else {
452  // first try for inscribed geometries defined inline
453  while ((ig = i->takeInputItem(eeg_keyword2)) != 0) {
455  delete ig;
456  if (!gj) {
457  egsWarning(eeg_message1,eeg_message8);
458  }
459  else {
460  geoms.push_back(gj);
461  }
462  }
463  // if geoms.size() is 0, check if inscribed geometries are defined
464  // via names of previously defined geometries.
465  if (!geoms.size()) {
466  vector<string> igeoms;
467  int err = i->getInput(eeg_keyword3,igeoms);
468  if (err || !igeoms.size()) {
469  egsWarning(eeg_message1,eeg_message7);
470  }
471  else {
472  for (unsigned int j=0; j<igeoms.size(); j++) {
473  EGS_BaseGeometry *gj =
475  if (!gj) {
476  egsWarning(eeg_message6,igeoms[j].c_str());
477  }
478  else {
479  geoms.push_back(gj);
480  }
481  }
482  }
483  }
484  delete i;
485  }
486  /*
487  EGS_BaseGeometry *result = fgeoms.size() ?
488  new EGS_EnvelopeGeometry(g,fgeoms,geoms) :
489  new EGS_EnvelopeGeometry(g,geoms);
490  */
491  EGS_BaseGeometry *result = new EGS_EnvelopeGeometry(g,geoms,"",indexing);
492  result->setName(input);
493  result->setLabels(input);
494  return result;
495 
496  }
497 
498 
499  void EGS_EnvelopeGeometry::getLabelRegions(const string &str, vector<int> &regs) {
500 
501  // label defined in the envelope geometry
502  g->getLabelRegions(str, regs);
503 
504  // label defined in the inscribed geometries
505  vector<int> gregs;
506  int shift=0;
507  for (int i=0; i<n_in; i++) {
508 
509  // add regions from set geometries
510  gregs.clear();
511  if (geometries[i]) {
512  geometries[i]->getLabelRegions(str, gregs);
513  }
514 
515  // shift region numbers according to indexing style
516  if (new_indexing) {
517  shift = local_start[i];
518  }
519  else {
520  shift = nbase+i*nmax;
521  }
522  for (int j=0; j<gregs.size(); j++) {
523  gregs[j] += shift;
524  }
525 
526  // add regions to the list
527  regs.insert(regs.end(), gregs.begin(), gregs.end());
528 
529  }
530 
531  // label defined in self (envelope geometry input block)
533 
534  }
535 
536  void EGS_FastEnvelope::getLabelRegions(const string &str, vector<int> &regs) {
537 
538  // label defined in the envelope geometry
539  g->getLabelRegions(str, regs);
540 
541  // label defined in the inscribed geometries
542  vector<int> gregs;
543  int shift=0;
544  for (int i=0; i<n_in; i++) {
545 
546  // add regions from set geometries
547  gregs.clear();
548  if (geometries[i]) {
549  geometries[i]->getLabelRegions(str, gregs);
550  }
551 
552  // shift region numbers according to indexing style
553  if (new_indexing) {
554  shift = local_start[i];
555  }
556  else {
557  shift = nmax;
558  }
559  for (int j=0; j<gregs.size(); j++) {
560  gregs[j] += shift;
561  }
562 
563  // add regions to the list
564  regs.insert(regs.end(), gregs.begin(), gregs.end());
565 
566  }
567 
568  // label defined in self (envelope geometry input block)
570 
571  }
572 
573 }
Base geometry class. Every geometry class must be derived from EGS_BaseGeometry.
int deref()
Decrease the reference count to this geometry.
static EGS_BaseGeometry * createSingleGeometry(EGS_Input *inp)
Create a single geometry from the input 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.
bool hasBScaling() const
Does this geometry object have a B field scaling feature?
void setName(EGS_Input *inp)
Set the name of the geometry from the input inp.
const string & getName() const
Get the name of this geometry.
bool isConvex() const
Is the geometry convex?
bool hasRhoScaling() const
Does this geometry object have a mass density scaling feature?
int regions() const
Returns the number of local regions in this geometry.
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.
static EGS_BaseGeometry * getGeometry(const string &Name)
Get a pointer to the geometry named Name.
void setBoundaryTolerance(EGS_Input *inp)
Set the value of the boundary tolerance from the input inp.
An envelope geometry class.
EGS_BaseGeometry * g
The envelope geometry.
int n_in
Number of inscribed geometries.
static string type
Geometry type.
int * local_start
First region for each inscribed geometry.
void setMedia(EGS_Input *, int, const int *)
Don't set media for an envelope geometry.
int nbase
Number of regions in the base geometry.
bool new_indexing
If true, use new indexing style.
EGS_BaseGeometry ** geometries
The inscribed geometries.
int * reg_to_inscr
Region to inscribed geometry conversion.
An envelope geometry class.
EGS_BaseGeometry ** geometries
The inscribed geometries.
int * local_start
First region for each inscribed geometry.
int n_in
Number of inscribed geometries.
int * reg_to_inscr
Region to inscribed geometry conversion.
EGS_BaseGeometry * g
The envelope geometry.
static string type
Geometry type.
void setMedia(EGS_Input *, int, const int *)
Don't set media for an envelope geometry.
bool new_indexing
If true, use new indexing style.
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
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
An envelope geometry: header.
Global egspp functions header file.
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 egsFatal
Always use this function for reporting fatal errors.
EGS_InfoFunction EGS_EXPORT egsWarning
Always use this function for reporting warnings.