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 # Marc Chamberland
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 #include "egs_smart_envelope.h"
60 #include "egs_input.h"
61 #include "egs_functions.h"
62 
63 #include <cstdlib>
64 
65 using namespace std;
66 
67 string EGS_SMART_ENVELOPE_LOCAL EGS_SmartEnvelope::type = "EGS_SmartEnvelope";
68 
69 void EGS_SmartEnvelope::setMedia(EGS_Input *,int,const int *) {
70  egsWarning("EGS_SmartEnvelope::setMedia: don't use this method. Use the\n"
71  " setMedia() methods of the geometry objects that make up this geometry\n");
72 }
73 
74 void EGS_SmartEnvelope::setRelativeRho(int start, int end, EGS_Float rho) {
75  setRelativeRho(0);
76 }
77 
78 void EGS_SmartEnvelope::setRelativeRho(EGS_Input *) {
79  egsWarning("EGS_SmartEnvelope::setRelativeRho(): don't use this method."
80  " Use the\n setRelativeRho methods of the geometry objects that make up"
81  " this geometry\n");
82 }
83 
84 void EGS_SmartEnvelope::setBScaling(int start, int end, EGS_Float bf) {
85  setBScaling(0);
86 }
87 
88 void EGS_SmartEnvelope::setBScaling(EGS_Input *) {
89  egsWarning("EGS_SmartEnvelope::setsetBScaling(): don't use this method."
90  " Use the\n setsetBScaling methods of the geometry objects that make up"
91  " this geometry\n");
92 }
93 
94 struct EGS_SMART_ENVELOPE_LOCAL SmartEnvelopeAux {
96  int ireg;
97  int type;
98  int nreg;
99  int *regs;
100  SmartEnvelopeAux() : g(0), ireg(-1), type(0), nreg(0) {};
101  ~SmartEnvelopeAux() {
102  if (nreg>0) {
103  delete [] regs;
104  }
105  };
106 };
107 
108 EGS_SmartEnvelope::EGS_SmartEnvelope(EGS_BaseGeometry *G,
109  const vector<SmartEnvelopeAux *> &fgeoms, const string &Name) :
110  EGS_BaseGeometry(Name), geometries(0), gindex(0),
111  reg_to_inscr(0), reg_to_base(0), local_start(0), itype(0) {
112  if (!G) {
113  egsFatal("EGS_SmartEnvelope: base geometry must not be null\n");
114  }
115  g = G;
116  g->ref();
117  n_in = fgeoms.size();
118  if (!n_in) {
119  egsFatal("EGS_SmartEnvelope: no inscribed geometries!\n");
120  }
121  geometries = new EGS_BaseGeometry * [n_in];
122  nbase = g->regions();
123  gindex = new int [nbase];
124  itype = new char [fgeoms.size()];
125  int j;
126  for (j=0; j<nbase; j++) {
127  gindex[j] = -1;
128  }
129  for (j=0; j<fgeoms.size(); j++) {
130  itype[j] = 0;
131  }
132  int nreg_inscribed = 0;
133  bool ok = true;
134  for (j=0; j<fgeoms.size(); j++) {
135  geometries[j] = fgeoms[j]->g;
136  geometries[j]->ref();
137  int i = fgeoms[j]->ireg;
138  if (gindex[i] >= 0) {
139  egsWarning("EGS_SmartEnvelope:"
140  " There can only be a single geometry inscribed in a region\n");
141  egsWarning(" You are trying to inscribe %s into region %d but\n",
142  geometries[j]->getName().c_str(),i);
143  egsWarning(" geometry %s is already inscribed in this region\n",
144  geometries[gindex[i]]->getName().c_str());
145  ok = false;
146  }
147  else {
148  gindex[i] = j;
149  itype[j] = fgeoms[j]->type;
150  //egsInformation("inscribing %d into %d with type %d\n",j,i,itype[j]);
151  nreg_inscribed += geometries[j]->regions();
152  }
153  }
154  if (!ok) {
155  egsFatal("EGS_SmartEnvelope: errors during definition\n");
156  }
157  nreg = nbase + nreg_inscribed;
158  local_start = new int [fgeoms.size()];
159  reg_to_inscr = new int [nreg_inscribed];
160  reg_to_base = new int [nreg_inscribed];
161  int nr = 0;
162  for (j=0; j<fgeoms.size(); j++) {
163  local_start[j] = nbase + nr;
164  int nj = geometries[j]->regions();
165  for (int i=nr; i<nr+nj; ++i) {
166  reg_to_inscr[i] = j;
167  reg_to_base[i] = fgeoms[j]->ireg;
168  }
169  nr += nj;
170  }
171  is_convex = g->isConvex();
172  has_rho_scaling = g->hasRhoScaling();
173  if (!has_rho_scaling) {
174  for (int j=0; j<n_in; j++) {
175  if (geometries[j]->hasRhoScaling()) {
176  has_rho_scaling = true;
177  break;
178  }
179  }
180  }
181  has_B_scaling = g->hasBScaling();
182  if (!has_B_scaling) {
183  for (int j=0; j<n_in; j++) {
184  if (geometries[j]->hasBScaling()) {
185  has_B_scaling = true;
186  break;
187  }
188  }
189  }
190 }
191 
192 EGS_SmartEnvelope::~EGS_SmartEnvelope() {
193  if (!g->deref()) {
194  delete g;
195  }
196  for (int j=0; j<n_in; j++) {
197  if (!geometries[j]->deref()) {
198  delete geometries[j];
199  }
200  }
201  if (geometries) {
202  delete [] geometries;
203  }
204  if (gindex) {
205  delete [] gindex;
206  }
207  if (reg_to_inscr) {
208  delete [] reg_to_inscr;
209  }
210  if (reg_to_base) {
211  delete [] reg_to_base ;
212  }
213  if (local_start) {
214  delete [] local_start;
215  }
216  if (itype) {
217  delete itype;
218  }
219 }
220 
221 void EGS_SmartEnvelope::printInfo() const {
223  egsInformation(" base geometry = %s (type %s)\n",g->getName().c_str(),
224  g->getType().c_str());
225  egsInformation(" inscribed geometries:\n");
226  for (int j=0; j<n_in; j++) egsInformation(" %s (type %s) in region=%d, "
227  " itype=%d\n",
228  geometries[j]->getName().c_str(),geometries[j]->getType().c_str(),
229  reg_to_base[j],(int)itype[j]);
231  "=======================================================\n");
232 }
233 
234 
235 static char EGS_SMART_ENVELOPE_LOCAL eeg_message1[] =
236  "createGeometry(smart envelope): %s\n";
237 static char EGS_SMART_ENVELOPE_LOCAL eeg_message2[] =
238  "null input?";
239 static char EGS_SMART_ENVELOPE_LOCAL eeg_message3[] =
240  "no 'base geometry' input?";
241 static char EGS_SMART_ENVELOPE_LOCAL eeg_message4[] =
242  "incorrect base geometry definition";
243 static char EGS_SMART_ENVELOPE_LOCAL eeg_message5[] =
244  "missing/incorrect 'base geometry' input";
245 static char EGS_SMART_ENVELOPE_LOCAL eeg_message6[] =
246  "createGeometry(smart envelope): no geometry with name %s defined\n";
247 //static char EGS_SMART_ENVELOPE_LOCAL eeg_message7[] =
248 //"no inscirebed geometries defined?. I hope you know what you are doing";
249 //static char EGS_SMART_ENVELOPE_LOCAL eeg_message8[] =
250 //"an error occured while constructing inscibed geometries";
251 
252 static char EGS_SMART_ENVELOPE_LOCAL eeg_keyword1[] = "base geometry";
253 static char EGS_SMART_ENVELOPE_LOCAL eeg_keyword2[] = "geometry";
254 //static char EGS_SMART_ENVELOPE_LOCAL eeg_keyword3[] = "inscribed geometries";
255 
256 extern "C" {
257 
258  EGS_SMART_ENVELOPE_EXPORT EGS_BaseGeometry *createGeometry(EGS_Input *input) {
259  if (!input) {
260  egsWarning(eeg_message1,eeg_message2);
261  return 0;
262  }
263  //
264  // *** Base geometry
265  //
266  EGS_Input *i = input->takeInputItem(eeg_keyword1);
267  if (!i) {
268  egsWarning(eeg_message1,eeg_message3);
269  return 0;
270  }
271  EGS_Input *ig = i->takeInputItem(eeg_keyword2);
272  EGS_BaseGeometry *g;
273  if (ig) { // defined inline
275  delete ig;
276  if (!g) {
277  egsWarning(eeg_message1,eeg_message4);
278  delete i;
279  return 0;
280  }
281  }
282  else { // defined via a name of a previously defined geometry
283  string bgname;
284  int err = i->getInput(eeg_keyword1,bgname);
285  delete i;
286  if (err) {
287  egsWarning(eeg_message1,eeg_message5);
288  return 0;
289  }
290  g = EGS_BaseGeometry::getGeometry(bgname);
291  if (!g) {
292  egsWarning(eeg_message6,bgname.c_str());
293  return 0;
294  }
295  }
296  vector<SmartEnvelopeAux *> fgeoms;
297  int nbase = g->regions();
298  EGS_Input *ix;
299  while ((ix = input->takeInputItem("inscribe geometry")) != 0) {
300  vector<string> values;
301  ix->getInput("inscribe geometry",values);
302  if (values.size() < 2) egsWarning("createGeometry(smart envelope):"
303  " %d inputs for 'inscribe geometry'? 2 or more are needed\n",values.size());
304  else {
306  if (!gj) {
307  egsWarning(eeg_message6,values[0].c_str());
308  }
309  else {
311  aux->g = gj;
312  aux->ireg = atoi(values[1].c_str());
313  aux->type = values.size() == 3 ? atoi(values[2].c_str()) : 0;
314  //egsInformation("set geometr: %s %d %d\n",values[0].c_str(),aux->ireg,aux->type);
315  if (aux->ireg < 0 || aux->ireg >= nbase) {
316  egsWarning("createGeometry(smart envelope): wrong "
317  "region index %d for inscribed geometry %s\n",
318  aux->ireg,gj->getName().c_str());
319  delete aux;
320  }
321  else {
322  fgeoms.push_back(aux);
323  }
324  }
325  }
326  delete ix;
327  }
328  EGS_BaseGeometry *result = new EGS_SmartEnvelope(g,fgeoms,"");
329  result->setName(input);
330  result->setBoundaryTolerance(input);
331  result->setLabels(input);
332  for (int j=0; j<fgeoms.size(); j++) {
333  delete fgeoms[j];
334  }
335  return result;
336 
337  }
338 
339  void EGS_SmartEnvelope::getLabelRegions(const string &str, vector<int> &regs) {
340 
341  // label defined in the envelope geometry
342  g->getLabelRegions(str, regs);
343 
344  // label defined in the inscribed geometries
345  vector<int> gregs;
346  for (int i=0; i<n_in; i++) {
347 
348  // add regions from set geometries
349  gregs.clear();
350  if (geometries[i]) {
351  geometries[i]->getLabelRegions(str, gregs);
352  }
353 
354  // shift region numbers according to indexing style
355  for (int j=0; j<gregs.size(); j++) {
356  gregs[j] += local_start[i];
357  }
358 
359  // add regions to the list
360  regs.insert(regs.end(), gregs.begin(), gregs.end());
361 
362  }
363 
364  // label defined in self (envelope geometry input block)
366 
367  }
368 
369 }
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.
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
int n_in
Number of inscribed geometries.
void setMedia(EGS_Input *, int, const int *)
Don't set media for an envelope geometry.
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.
Global egspp functions header file.
EGS_GLIB_EXPORT EGS_BaseGeometry * createGeometry(EGS_Input *input)
Definition: egs_glib.cpp:57
EGS_Input class header file.
A smart envelope geometry: header.
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.