EGSnrc C++ class library  Report PIRS-898 (2021)
Iwan Kawrakow, Ernesto Mainegra-Hing, Frederic Tessier, Reid Townson and Blake Walters
egs_smart_envelope.cpp
Go to the documentation of this file.
1 /*
2 ###############################################################################
3 #
4 # EGSnrc egs++ smart 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, 2008
25 #
26 # Contributors: Frederic Tessier
27 # Ernesto Mainegra-Hing
28 #
29 ###############################################################################
30 #
31 # A "smart" envelope geometry. The smartness is due to the fact that there
32 # can be only zero or one inscribed geometry per base geometry region, which
33 # makes many of the checks faster.
34 #
35 # In addition, unlike the regular envelope geometry where all inscribed
36 # geometries always must completely fit inside the base geometry, here
37 # geometries can be inscribed using logic 0 or 1.
38 #
39 # Logic 0 is as before, i.e., geometry must completely fit into the region
40 # where it is being inscribed.
41 #
42 # Logic 1 means that the inscribed geometry extends beyond the region and
43 # therefore the smart envelope also checks the base geometry in this case.
44 # This is very similar to a CD geometry except that now the space outside
45 # the inscribed geometry is still part of the geometry.
46 #
47 # Warning: not completely tested, so don't use for production runs yet.
48 #
49 ###############################################################################
50 */
51 
52 
58 #include "egs_smart_envelope.h"
59 #include "egs_input.h"
60 #include "egs_functions.h"
61 
62 #include <cstdlib>
63 
64 using namespace std;
65 
66 string EGS_SMART_ENVELOPE_LOCAL EGS_SmartEnvelope::type = "EGS_SmartEnvelope";
67 
68 void EGS_SmartEnvelope::setMedia(EGS_Input *,int,const int *) {
69  egsWarning("EGS_SmartEnvelope::setMedia: don't use this method. Use the\n"
70  " setMedia() methods of the geometry objects that make up this geometry\n");
71 }
72 
73 void EGS_SmartEnvelope::setRelativeRho(int start, int end, EGS_Float rho) {
74  setRelativeRho(0);
75 }
76 
77 void EGS_SmartEnvelope::setRelativeRho(EGS_Input *) {
78  egsWarning("EGS_SmartEnvelope::setRelativeRho(): don't use this method."
79  " Use the\n setRelativeRho methods of the geometry objects that make up"
80  " this geometry\n");
81 }
82 
83 void EGS_SmartEnvelope::setBScaling(int start, int end, EGS_Float bf) {
84  setBScaling(0);
85 }
86 
87 void EGS_SmartEnvelope::setBScaling(EGS_Input *) {
88  egsWarning("EGS_SmartEnvelope::setsetBScaling(): don't use this method."
89  " Use the\n setsetBScaling methods of the geometry objects that make up"
90  " this geometry\n");
91 }
92 
93 struct EGS_SMART_ENVELOPE_LOCAL SmartEnvelopeAux {
95  int ireg;
96  int type;
97  int nreg;
98  int *regs;
99  SmartEnvelopeAux() : g(0), ireg(-1), type(0), nreg(0) {};
100  ~SmartEnvelopeAux() {
101  if (nreg>0) {
102  delete [] regs;
103  }
104  };
105 };
106 
107 EGS_SmartEnvelope::EGS_SmartEnvelope(EGS_BaseGeometry *G,
108  const vector<SmartEnvelopeAux *> &fgeoms, const string &Name) :
109  EGS_BaseGeometry(Name), geometries(0), gindex(0),
110  reg_to_inscr(0), reg_to_base(0), local_start(0), itype(0) {
111  if (!G) {
112  egsFatal("EGS_SmartEnvelope: base geometry must not be null\n");
113  }
114  g = G;
115  g->ref();
116  n_in = fgeoms.size();
117  if (!n_in) {
118  egsFatal("EGS_SmartEnvelope: no inscribed geometries!\n");
119  }
120  geometries = new EGS_BaseGeometry * [n_in];
121  nbase = g->regions();
122  gindex = new int [nbase];
123  itype = new char [fgeoms.size()];
124  int j;
125  for (j=0; j<nbase; j++) {
126  gindex[j] = -1;
127  }
128  for (j=0; j<fgeoms.size(); j++) {
129  itype[j] = 0;
130  }
131  int nreg_inscribed = 0;
132  bool ok = true;
133  for (j=0; j<fgeoms.size(); j++) {
134  geometries[j] = fgeoms[j]->g;
135  geometries[j]->ref();
136  int i = fgeoms[j]->ireg;
137  if (gindex[i] >= 0) {
138  egsWarning("EGS_SmartEnvelope:"
139  " There can only be a single geometry inscribed in a region\n");
140  egsWarning(" You are trying to inscribe %s into region %d but\n",
141  geometries[j]->getName().c_str(),i);
142  egsWarning(" geometry %s is already inscribed in this region\n",
143  geometries[gindex[i]]->getName().c_str());
144  ok = false;
145  }
146  else {
147  gindex[i] = j;
148  itype[j] = fgeoms[j]->type;
149  //egsInformation("inscribing %d into %d with type %d\n",j,i,itype[j]);
150  nreg_inscribed += geometries[j]->regions();
151  }
152  }
153  if (!ok) {
154  egsFatal("EGS_SmartEnvelope: errors during definition\n");
155  }
156  nreg = nbase + nreg_inscribed;
157  local_start = new int [fgeoms.size()];
158  reg_to_inscr = new int [nreg_inscribed];
159  reg_to_base = new int [nreg_inscribed];
160  int nr = 0;
161  for (j=0; j<fgeoms.size(); j++) {
162  local_start[j] = nbase + nr;
163  int nj = geometries[j]->regions();
164  for (int i=nr; i<nr+nj; ++i) {
165  reg_to_inscr[i] = j;
166  reg_to_base[i] = fgeoms[j]->ireg;
167  }
168  nr += nj;
169  }
170  is_convex = g->isConvex();
171  has_rho_scaling = g->hasRhoScaling();
172  if (!has_rho_scaling) {
173  for (int j=0; j<n_in; j++) {
174  if (geometries[j]->hasRhoScaling()) {
175  has_rho_scaling = true;
176  break;
177  }
178  }
179  }
180  has_B_scaling = g->hasBScaling();
181  if (!has_B_scaling) {
182  for (int j=0; j<n_in; j++) {
183  if (geometries[j]->hasBScaling()) {
184  has_B_scaling = true;
185  break;
186  }
187  }
188  }
189 }
190 
191 EGS_SmartEnvelope::~EGS_SmartEnvelope() {
192  if (!g->deref()) {
193  delete g;
194  }
195  for (int j=0; j<n_in; j++) {
196  if (!geometries[j]->deref()) {
197  delete geometries[j];
198  }
199  }
200  if (geometries) {
201  delete [] geometries;
202  }
203  if (gindex) {
204  delete [] gindex;
205  }
206  if (reg_to_inscr) {
207  delete [] reg_to_inscr;
208  }
209  if (reg_to_base) {
210  delete [] reg_to_base ;
211  }
212  if (local_start) {
213  delete [] local_start;
214  }
215  if (itype) {
216  delete itype;
217  }
218 }
219 
220 void EGS_SmartEnvelope::printInfo() const {
222  egsInformation(" base geometry = %s (type %s)\n",g->getName().c_str(),
223  g->getType().c_str());
224  egsInformation(" inscribed geometries:\n");
225  for (int j=0; j<n_in; j++) egsInformation(" %s (type %s) in region=%d, "
226  " itype=%d\n",
227  geometries[j]->getName().c_str(),geometries[j]->getType().c_str(),
228  reg_to_base[j],(int)itype[j]);
230  "=======================================================\n");
231 }
232 
233 
234 static char EGS_SMART_ENVELOPE_LOCAL eeg_message1[] =
235  "createGeometry(smart envelope): %s\n";
236 static char EGS_SMART_ENVELOPE_LOCAL eeg_message2[] =
237  "null input?";
238 static char EGS_SMART_ENVELOPE_LOCAL eeg_message3[] =
239  "no 'base geometry' input?";
240 static char EGS_SMART_ENVELOPE_LOCAL eeg_message4[] =
241  "incorrect base geometry definition";
242 static char EGS_SMART_ENVELOPE_LOCAL eeg_message5[] =
243  "missing/incorrect 'base geometry' input";
244 static char EGS_SMART_ENVELOPE_LOCAL eeg_message6[] =
245  "createGeometry(smart envelope): no geometry with name %s defined\n";
246 //static char EGS_SMART_ENVELOPE_LOCAL eeg_message7[] =
247 //"no inscirebed geometries defined?. I hope you know what you are doing";
248 //static char EGS_SMART_ENVELOPE_LOCAL eeg_message8[] =
249 //"an error occured while constructing inscibed geometries";
250 
251 static char EGS_SMART_ENVELOPE_LOCAL eeg_keyword1[] = "base geometry";
252 static char EGS_SMART_ENVELOPE_LOCAL eeg_keyword2[] = "geometry";
253 //static char EGS_SMART_ENVELOPE_LOCAL eeg_keyword3[] = "inscribed geometries";
254 
255 extern "C" {
256 
257  EGS_SMART_ENVELOPE_EXPORT EGS_BaseGeometry *createGeometry(EGS_Input *input) {
258  if (!input) {
259  egsWarning(eeg_message1,eeg_message2);
260  return 0;
261  }
262  //
263  // *** Base geometry
264  //
265  EGS_Input *i = input->takeInputItem(eeg_keyword1);
266  if (!i) {
267  egsWarning(eeg_message1,eeg_message3);
268  return 0;
269  }
270  EGS_Input *ig = i->takeInputItem(eeg_keyword2);
271  EGS_BaseGeometry *g;
272  if (ig) { // defined inline
274  delete ig;
275  if (!g) {
276  egsWarning(eeg_message1,eeg_message4);
277  delete i;
278  return 0;
279  }
280  }
281  else { // defined via a name of a previously defined geometry
282  string bgname;
283  int err = i->getInput(eeg_keyword1,bgname);
284  delete i;
285  if (err) {
286  egsWarning(eeg_message1,eeg_message5);
287  return 0;
288  }
289  g = EGS_BaseGeometry::getGeometry(bgname);
290  if (!g) {
291  egsWarning(eeg_message6,bgname.c_str());
292  return 0;
293  }
294  }
295  vector<SmartEnvelopeAux *> fgeoms;
296  int nbase = g->regions();
297  EGS_Input *ix;
298  while ((ix = input->takeInputItem("inscribe geometry")) != 0) {
299  vector<string> values;
300  ix->getInput("inscribe geometry",values);
301  if (values.size() < 2) egsWarning("createGeometry(smart envelope):"
302  " %d inputs for 'inscribe geometry'? 2 or more are needed\n",values.size());
303  else {
305  if (!gj) {
306  egsWarning(eeg_message6,values[0].c_str());
307  }
308  else {
310  aux->g = gj;
311  aux->ireg = atoi(values[1].c_str());
312  aux->type = values.size() == 3 ? atoi(values[2].c_str()) : 0;
313  //egsInformation("set geometr: %s %d %d\n",values[0].c_str(),aux->ireg,aux->type);
314  if (aux->ireg < 0 || aux->ireg >= nbase) {
315  egsWarning("createGeometry(smart envelope): wrong "
316  "region index %d for inscribed geometry %s\n",
317  aux->ireg,gj->getName().c_str());
318  delete aux;
319  }
320  else {
321  fgeoms.push_back(aux);
322  }
323  }
324  }
325  delete ix;
326  }
327  EGS_BaseGeometry *result = new EGS_SmartEnvelope(g,fgeoms,"");
328  result->setName(input);
329  result->setBoundaryTolerance(input);
330  result->setLabels(input);
331  for (int j=0; j<fgeoms.size(); j++) {
332  delete fgeoms[j];
333  }
334  return result;
335 
336  }
337 
338  void EGS_SmartEnvelope::getLabelRegions(const string &str, vector<int> &regs) {
339 
340  // label defined in the envelope geometry
341  g->getLabelRegions(str, regs);
342 
343  // label defined in the inscribed geometries
344  vector<int> gregs;
345  for (int i=0; i<n_in; i++) {
346 
347  // add regions from set geometries
348  gregs.clear();
349  if (geometries[i]) {
350  geometries[i]->getLabelRegions(str, gregs);
351  }
352 
353  // shift region numbers according to indexing style
354  for (int j=0; j<gregs.size(); j++) {
355  gregs[j] += local_start[i];
356  }
357 
358  // add regions to the list
359  regs.insert(regs.end(), gregs.begin(), gregs.end());
360 
361  }
362 
363  // label defined in self (envelope geometry input block)
365 
366  }
367 
368 }
void setMedia(EGS_Input *, int, const int *)
Don&#39;t set media for an envelope geometry.
virtual const string & getType() const =0
Get the geometry type.
int regions() const
Returns the number of local regions in this geometry.
int deref()
Decrease the reference count to this geometry.
virtual void printInfo() const
Print information about this geometry.
int * gindex
Index of inscribed geometries.
A smart envelope geometry: header.
EGS_Input class header file.
int setLabels(EGS_Input *input)
Set the labels from an input block.
bool hasRhoScaling() const
Does this geometry object have a mass density scaling feature?
int * reg_to_base
Region to base region conversion.
Global egspp functions header file.
EGS_GLIB_EXPORT EGS_BaseGeometry * createGeometry(EGS_Input *input)
Definition: egs_glib.cpp:57
Base geometry class. Every geometry class must be derived from EGS_BaseGeometry.
void setBoundaryTolerance(EGS_Input *inp)
Set the value of the boundary tolerance from the input inp.
bool isConvex() const
Is the geometry convex?
static EGS_BaseGeometry * getGeometry(const string &Name)
Get a pointer to the geometry named Name.
EGS_InfoFunction EGS_EXPORT egsFatal
Always use this function for reporting fatal errors.
virtual void getLabelRegions(const string &str, vector< int > &regs)
Get the list of all regions labeled with str.
EGS_InfoFunction EGS_EXPORT egsInformation
Always use this function for reporting the progress of a simulation and any other type of information...
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.
int n_in
Number of inscribed geometries.
int * reg_to_inscr
Region to inscribed geometry conversion.
EGS_BaseGeometry * g
The envelope geometry.
int * local_start
First region for each inscribed geometry.
EGS_BaseGeometry ** geometries
The inscribed geometries.
int ref()
Increase the reference count to this geometry.
static string type
Geometry type.
static EGS_BaseGeometry * createSingleGeometry(EGS_Input *inp)
Create a single geometry from the input inp.
A class for storing information in a tree-like structure of key-value pairs. This class is used throu...
Definition: egs_input.h:182
const string & getName() const
Get the name of this geometry.
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
EGS_InfoFunction EGS_EXPORT egsWarning
Always use this function for reporting warnings.