EGSnrc C++ class library  Report PIRS-898 (2021)
Iwan Kawrakow, Ernesto Mainegra-Hing, Frederic Tessier, Reid Townson and Blake Walters
egs_cd_geometry.cpp
Go to the documentation of this file.
1 /*
2 ###############################################################################
3 #
4 # EGSnrc egs++ cd 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 # Reid Townson
30 #
31 ###############################################################################
32 */
33 
34 
40 #include "egs_cd_geometry.h"
41 #include "egs_input.h"
42 
43 #ifdef NO_SSTREAM
44  #include <strstream>
45  #define S_STREAM std::istrstream
46 #else
47  #include <sstream>
48  #define S_STREAM std::istringstream
49 #endif
50 
51 static string EGS_CDGEOMETRY_LOCAL typeStr("egs_cdgeometry");
52 string EGS_CDGeometry::type(typeStr);
53 
54 static bool EGS_CDGEOMETRY_LOCAL inputSet = false;
55 
56 void EGS_CDGeometry::setMedia(EGS_Input *,int,const int *) {
57  egsWarning("EGS_CDGeometry::setMedia: don't use this method. Use the\n"
58  " setMedia() methods of the geometry objects that make up this geometry\n");
59 }
60 
61 void EGS_CDGeometry::setRelativeRho(int start, int end, EGS_Float rho) {
62  egsWarning("EGS_CDGeometry::setRelativeRho(): don't use this method\n"
63  " Use the setRelativeRho() methods of the geometry objects that make"
64  " up this geometry\n");
65 }
66 
67 void EGS_CDGeometry::setRelativeRho(EGS_Input *) {
68  egsWarning("EGS_CDGeometry::setRelativeRho(): don't use this method\n"
69  " Use the setRelativeRho() methods of the geometry objects that make"
70  " up this geometry\n");
71 }
72 
73 void EGS_CDGeometry::setBScaling(int start, int end, EGS_Float bf) {
74  egsWarning("EGS_CDGeometry::setBScaling(): don't use this method\n"
75  " Use the setBScaling() methods of the geometry objects that make"
76  " up this geometry\n");
77 }
78 
79 void EGS_CDGeometry::setBScaling(EGS_Input *) {
80  egsWarning("EGS_CDGeometry::setBScaling(): don't use this method\n"
81  " Use the setBScaling() methods of the geometry objects that make"
82  " up this geometry\n");
83 }
84 
85 void EGS_CDGeometry::setUpIndexing() {
86  int nr = 0;
87  int j;
88  for (j=0; j<nbase; j++) {
89  if (g[j]) {
90  nr += g[j]->regions();
91  }
92  else {
93  ++nr;
94  }
95  }
96  reg_to_base = new int [nr];
97  local_start = new int [nbase];
98  int ir=0;
99  for (j=0; j<nbase; j++) {
100  local_start[j] = ir;
101  if (g[j]) {
102  int n = g[j]->regions();
103  for (int i=0; i<n; i++) {
104  reg_to_base[ir++] = j;
105  }
106  }
107  else {
108  reg_to_base[ir++] = j;
109  }
110  }
111  new_indexing = true;
112  nreg = nr;
113 }
114 
115 
116 extern "C" {
117 
118  static void setInputs() {
119  inputSet = true;
120 
121  setBaseGeometryInputs(false);
122 
123  geomBlockInput->getSingleInput("library")->setValues(vector<string>(1, typeStr));
124 
125  // Format: name, isRequired, description, vector string of allowed values
126  geomBlockInput->addSingleInput("base geometry", true, "The name of the geometry that defines regions for this 'cutting device'. It is within these regions that other geometries will be placed to create a composite geometry.");
127  geomBlockInput->addSingleInput("set geometry", true, "The local region number in the base geometry, followed by the name of the geometry to place in that region. If this geometry extends beyond the region boundaries, it will be cut to size.");
128  geomBlockInput->addSingleInput("new indexing style", false, "Set to 1 to use a new region numbering algorithm. Defaults to 0, to use the original indexing style.");
129  }
130 
131  EGS_CDGEOMETRY_EXPORT string getExample() {
132  string example {
133  R"(
134  :start geometry:
135  library = EGS_CDGeometry
136  name = my_cd
137  base geometry = my_regions
138  # set geometry = 1 geom means:
139  # in region 1 of the basegeometry, use geometry named "geom"
140  set geometry = 0 my_geom1
141  set geometry = 1 my_geom2
142  :stop geometry:
143 )"};
144  return example;
145  }
146 
147  EGS_CDGEOMETRY_EXPORT shared_ptr<EGS_BlockInput> getInputs() {
148  if(!inputSet) {
149  setInputs();
150  }
151  return geomBlockInput;
152  }
153 
154  EGS_CDGEOMETRY_EXPORT EGS_BaseGeometry *createGeometry(EGS_Input *input) {
155  if (!input) {
156  egsWarning("createGeometry(CD_Geometry): null input?\n");
157  return 0;
158  }
159  EGS_Input *ij;
160  while ((ij = input->takeInputItem("geometry",false)) != 0) {
162  delete ij;
163  }
164 
165  string bg_name;
166  int err = input->getInput("base geometry", bg_name);
167  if (err) {
168  egsWarning("createGeometry(CD_Geometry): no 'base geometry' input\n");
169  return 0;
170  }
172  if (!g) {
173  egsWarning("createGeometry(CD_Geometry): no geometry named %s is"
174  " defined\n",bg_name.c_str());
175  return 0;
176  }
177  int nreg = g->regions();
178  if (nreg < 1) {
179  egsWarning("createGeometry(CD_Geometry): the base geometry has %d"
180  " regions?\n",nreg);
181  return 0;
182  }
183  EGS_BaseGeometry **G = new EGS_BaseGeometry* [nreg];
184  int j;
185  for (j=0; j<nreg; j++) {
186  G[j] = 0;
187  }
188  int ng = 0;
189  string aux;
190  err = 0;
191  while ((ij = input->takeInputItem("set geometry")) != 0) {
192  vector<string> aux;
193  ij->getInput("set geometry",aux);
194  int istart, iend;
195  string name;
196  bool is_ok = true;
197  if (aux.size() == 2) {
198  string auxx = aux[0];
199  auxx += ' ';
200  auxx += aux[1];
201  auxx += ' ';
202  S_STREAM in(auxx.c_str());
203  in >> istart >> name;
204  if (in.fail() || !in.good()) {
205  egsWarning("createGeometry(CD_Geometry): parse error in\n"
206  " set geometry = %s\n",auxx.c_str());
207  err++;
208  is_ok = false;
209  }
210  else {
211  if (istart < 0 || istart > nreg-1) {
212  istart = -1;
213  iend = -2;
214  }
215  else {
216  iend = istart+1;
217  }
218  }
219  }
220  else if (aux.size() == 3) {
221  string auxx = aux[0];
222  auxx += ' ';
223  auxx += aux[1];
224  auxx += ' ';
225  auxx += aux[2];
226  auxx += ' ';
227  S_STREAM in(auxx.c_str());
228  in >> istart >> iend >> name;
229  if (in.fail() || !in.good()) {
230  egsWarning("createGeometry(CD_Geometry): parse error in\n"
231  " set geometry = %s\n",auxx.c_str());
232  err++;
233  is_ok = false;
234  }
235  else {
236  if (istart < 0) {
237  istart = 0;
238  }
239  if (iend > nreg) {
240  iend = nreg;
241  }
242  }
243  }
244  else {
245  err++;
246  is_ok = false;
247  }
248  if (is_ok) {
250  if (!gj) {
251  egsWarning("createGeometry(CD_Geometry): no geometry named %s"
252  " is defined\n",name.c_str());
253  err++;
254  }
255  else {
256  for (int j=istart; j<iend; j++) {
257  if (G[j] && G[j] != gj) {
258  G[j]->deref();
259  }
260  /*
261  if( !G[j] ) gj->ref();
262  else {
263  if( G[j] != gj ) G[j]->deref();
264  }
265  */
266  G[j] = gj;
267  gj->ref();
268  ng++;
269  }
270  }
271  }
272  delete ij;
273  }
274  if (err) {
275  egsWarning("createGeometry(CD_Geometry): %d errors\n",err);
276  for (j=0; j<nreg; j++) {
277  if (G[j]) {
278  if (!G[j]->deref()) {
279  delete G[j];
280  }
281  }
282  }
283  delete [] G[j];
284  return 0;
285  }
286  if (!ng)
287  egsWarning("createGeometry(CD_Geometry): no geometries in addition to"
288  " the base geometry defined?\n"
289  " Hope you know what you are doing\n");
290  g->ref();
291  int indexing = 0;
292  input->getInput("new indexing style",indexing);
293  EGS_BaseGeometry *result = new EGS_CDGeometry(g,G,"",indexing);
294  delete [] G;
295  result->setName(input);
296  result->setBoundaryTolerance(input);
297  result->setLabels(input);
298  return result;
299 
300  }
301 
302  int EGS_CDGeometry::getGlobalRegionOffset(const string geomName) {
303  // Look for the named geometry in the set geometries
304  for (int i=0; i<nbase; i++) {
305  if (g[i] && g[i]->getName() == geomName) {
306  int shift = 0;
307  if (new_indexing) {
308  shift = local_start[i];
309  }
310  else {
311  shift = i*nmax;
312  }
313  return shift;
314  }
315  }
316 
317  // If it's not found above, search through the set geometries in case they are composite geometries
318  for (int i=0; i<nbase; i++) {
319  int shift = g[i]->getGlobalRegionOffset(geomName);
320  if (shift >= 0) {
321  if (new_indexing) {
322  shift += local_start[i];
323  }
324  else {
325  shift += i*nmax;
326  }
327  return shift;
328  }
329  }
330 
331  return -1;
332  }
333 
334  void EGS_CDGeometry::getLabelRegions(const string &str, vector<int> &regs, bool sanitize) {
335 
336  // label defined in the base geometry
337  vector<int> bgregs;
338  bg->getLabelRegions(str, bgregs);
339 
340  // expand base regions to global region lists
341  int rstart = 0;
342  int rend = 0;
343  for (int i=0; i<bgregs.size(); i++) {
344  if (new_indexing) {
345  rstart = local_start[bgregs[i]];
346  if (bgregs[i] < nbase-1) {
347  rend = local_start[bgregs[i]+1];
348  }
349  else {
350  rend = nreg;
351  }
352  }
353  else {
354  rstart = bgregs[i]*nmax;
355  rend = (bgregs[i]+1)*nmax;
356  }
357  for (int j=rstart; j<rend; j++) {
358  regs.push_back(j);
359  }
360  }
361 
362  // label defined in the set geometries
363  vector<int> gregs;
364  int shift=0;
365  for (int i=0; i<nbase; i++) {
366 
367  // add regions from set geometries
368  gregs.clear();
369  if (g[i]) {
370  g[i]->getLabelRegions(str, gregs, sanitize);
371  }
372 
373  // shift region numbers according to indexing style
374  if (new_indexing) {
375  shift = local_start[i];
376  }
377  else {
378  shift = i*nmax;
379  }
380  for (int j=0; j<gregs.size(); j++) {
381  gregs[j] += shift;
382  }
383 
384  // add regions to the list
385  regs.insert(regs.end(), gregs.begin(), gregs.end());
386 
387  }
388 
389  // label defined in self (cd input block)
390  EGS_BaseGeometry::getLabelRegions(str, regs, sanitize);
391 
392  }
393 
394 }
Base geometry class. Every geometry class must be derived from EGS_BaseGeometry.
virtual int getGlobalRegionOffset(const string geomName)
Get the global region number for the first region in the geometry.
int deref()
Decrease the reference count to this geometry.
static EGS_BaseGeometry * createSingleGeometry(EGS_Input *inp)
Create a single geometry from the input inp.
int nreg
Number of local regions in this geometry.
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.
int regions() const
Returns the number of local regions in this geometry.
int setLabels(EGS_Input *input)
Set the labels from an input block.
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.
virtual void getLabelRegions(const string &str, vector< int > &regs, bool sanitize=true)
Get the list of all regions labeled with str.
A "combinatorial dimension" geometry.
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:229
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:341
A CD-geometry: header.
EGS_GLIB_EXPORT EGS_BaseGeometry * createGeometry(EGS_Input *input)
Definition: egs_glib.cpp:84
EGS_Input class header file.
EGS_InfoFunction EGS_EXPORT egsWarning
Always use this function for reporting warnings.