EGSnrc C++ class library  Report PIRS-898 (2021)
Iwan Kawrakow, Ernesto Mainegra-Hing, Frederic Tessier, Reid Townson and Blake Walters
egs_union_geometry.cpp
Go to the documentation of this file.
1 /*
2 ###############################################################################
3 #
4 # EGSnrc egs++ union 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 # Hubert Ho
29 # Marc Chamberland
30 # Hannah Gallop
31 #
32 ###############################################################################
33 */
34 
35 
41 #include "egs_union_geometry.h"
42 #include "egs_input.h"
43 #include "egs_functions.h"
44 
45 using namespace std;
46 
47 string EGS_UNIONG_LOCAL EGS_UnionGeometry::type = "EGS_UnionGeometry";
48 
49 static bool EGS_UNIONG_LOCAL inputSet = false;
50 
51 void EGS_UnionGeometry::setMedia(EGS_Input *,int,const int *) {
52  egsWarning("EGS_UnionGeometry::setMedia: don't use this method. Use the\n"
53  " setMedia() methods of the geometry objects that make up this geometry\n");
54 }
55 
56 void EGS_UnionGeometry::setRelativeRho(int start, int end, EGS_Float rho) {
57  setRelativeRho(0);
58 }
59 
60 void EGS_UnionGeometry::setRelativeRho(EGS_Input *) {
61  egsWarning("EGS_UnionGeometry::setRelativeRho(): don't use this method. "
62  "Use the\n setRelativeRho() methods of the geometry objects that make "
63  "up this geometry\n");
64 }
65 
66 void EGS_UnionGeometry::setBScaling(int start, int end, EGS_Float bf) {
67  setBScaling(0);
68 }
69 
70 void EGS_UnionGeometry::setBScaling(EGS_Input *) {
71  egsWarning("EGS_UnionGeometry::setBScaling(): don't use this method. "
72  "Use the\n setBScaling() methods of the geometry objects that make "
73  "up this geometry\n");
74 }
75 
76 EGS_UnionGeometry::EGS_UnionGeometry(const vector<EGS_BaseGeometry *> &geoms,
77  const int *priorities, const string &Name) :
78  EGS_BaseGeometry(Name) {
79  ng = geoms.size();
80  if (ng <= 0) egsFatal("EGS_UnionGeometry::EGS_UnionGeometry: attempt "
81  " to construct a union geometry from zero geometries\n");
82  is_convex = false;
83  if (ng == 1) egsWarning("EGS_UnionGeometry::EGS_UnionGeometry: why "
84  "do you want to make a union out of a single geometry?\n");
85  g = new EGS_BaseGeometry* [ng];
86  nmax = 0;
87  int j;
88  int *order = new int [ng];
89  if (priorities) {
90  // user has definied priorities
91  // order them using a very simplistic algorithm
92  bool *is_used = new bool [ng];
93  for (j=0; j<ng; j++) {
94  is_used[j] = false;
95  }
96  for (j=0; j<ng; j++) {
97  int imax;
98  for (imax=0; imax<ng-1; imax++) if (!is_used[imax]) {
99  break;
100  }
101  int pmax = priorities[imax];
102  for (int i=0; i<ng; i++) {
103  if (!is_used[i] && priorities[i] > pmax) {
104  imax = i;
105  pmax = priorities[i];
106  }
107  }
108  order[j] = imax;
109  is_used[imax] = true;
110  }
111  delete [] is_used;
112  }
113  else {
114  // user has not definied priorities
115  for (j=0; j<ng; j++) {
116  order[j] = j;
117  }
118  }
119  has_rho_scaling = false;
120  // now put the geometries into the array of geometries in
121  // decreasing priority order.
122  for (j=0; j<ng; j++) {
123  int i = order[j];
124  g[i] = geoms[j];
125  g[i]->ref();
126  int n = g[i]->regions();
127  if (n > nmax) {
128  nmax = n;
129  }
130  if (!has_rho_scaling) {
132  }
133  }
134  has_B_scaling = false;
135  // now put the geometries into the array of geometries in
136  // decreasing priority order.
137  for (j=0; j<ng; j++) {
138  int i = order[j];
139  g[i] = geoms[j];
140  g[i]->ref();
141  int n = g[i]->regions();
142  if (n > nmax) {
143  nmax = n;
144  }
145  if (!has_B_scaling) {
146  has_B_scaling = g[i]->hasBScaling();
147  }
148  }
149  delete [] order;
150  if (!nmax) egsFatal("EGS_UnionGeometry::EGS_UnionGeometry: all geometries"
151  " have zero regions?\n");
152  nreg = nmax*ng;
153 }
154 
155 EGS_UnionGeometry::~EGS_UnionGeometry() {
156  for (int j=0; j<ng; j++) {
157  if (!g[j]->deref()) {
158  delete g[j];
159  }
160  }
161  delete [] g;
162 }
163 
164 void EGS_UnionGeometry::printInfo() const {
166  egsInformation(" geometries:\n");
167  for (int j=0; j<ng; j++) egsInformation(" %s (type %s)\n",
168  g[j]->getName().c_str(),g[j]->getType().c_str());
170  "=======================================================\n");
171 }
172 
173 extern "C" {
174  static void setInputs() {
175  inputSet = true;
176 
177  setBaseGeometryInputs(false);
178 
179  geomBlockInput->getSingleInput("library")->setValues({"egs_gunion"});
180 
181  // Format: name, isRequired, description, vector string of allowed values
182  geomBlockInput->addSingleInput("geometries", true, "A list of names of previously defined geometries");
183  geomBlockInput->addSingleInput("priorities", false, "A list of integers defining the geometry priorities. If neglected, the priority decreases when moving from the first to the last of the geometry list.");
184  }
185 
186  EGS_UNIONG_EXPORT string getExample() {
187  string example;
188  example = {
189  R"(
190  # Example of egs_gunion
191  #:start geometry:
192  name = my_union
193  library = egs_union
194  geometries = my_box my_sphere
195  :stop geometry:
196 )"};
197  return example;
198  }
199 
200  EGS_UNIONG_EXPORT shared_ptr<EGS_BlockInput> getInputs() {
201  if(!inputSet) {
202  setInputs();
203  }
204  return geomBlockInput;
205  }
206 
207  EGS_UNIONG_EXPORT EGS_BaseGeometry *createGeometry(EGS_Input *input) {
208  if (!input) {
209  egsWarning("createGeometry(union): null input?\n");
210  return 0;
211  }
212  vector<EGS_BaseGeometry *> geoms;
213  vector<string> gnames;
214  int err = input->getInput("geometries",gnames);
215  if (err || gnames.size() < 1) {
216  egsWarning("createGeometry(union): missing/wrong 'geometries' input\n");
217  return 0;
218  }
219  for (unsigned int j=0; j<gnames.size(); j++) {
221  if (!gj) egsWarning("createGeometry(union): no geometry named %s "
222  "defined\n",gnames[j].c_str());
223  else {
224  geoms.push_back(gj);
225  }
226  }
227  if (geoms.size() < 1) {
228  egsWarning("createGeometry(union): must have at least one geometry\n");
229  return 0;
230  }
231  vector<int> pri;
232  err = input->getInput("priorities",pri);
233  int *p = 0;
234  if (!err) {
235  if (pri.size() == geoms.size()) {
236  p = new int [pri.size()];
237  for (int i=0; i<pri.size(); i++) {
238  p[i] = pri[i];
239  }
240  }
241  else egsWarning("createGeometry(union): the number of priorities (%d)"
242  " is not the same as the number of geometries (%d) => ignoring\n",
243  pri.size(),geoms.size());
244  }
245  EGS_BaseGeometry *result = new EGS_UnionGeometry(geoms,p);
246  result->setName(input);
247  result->setBoundaryTolerance(input);
248  result->setLabels(input);
249  if (p) {
250  delete [] p;
251  }
252  return result;
253  }
254 
255  int EGS_UnionGeometry::getGlobalRegionOffset(const string geomName) {
256  // Look for the named geometry in the inscribed geometries
257  for (int i=0; i<ng; i++) {
258  if (g[i] && g[i]->getName() == geomName) {
259  return i*nmax;
260  }
261  }
262 
263  // If it's not found above, search through the inscribed geometries in case they are composite geometries
264  for (int i=0; i<ng; i++) {
265  int shift = g[i]->getGlobalRegionOffset(geomName);
266  if (shift >= 0) {
267  shift += i*nmax;
268  return shift;
269  }
270  }
271 
272  // Return -1 for not found
273  return -1;
274  }
275 
276  void EGS_UnionGeometry::getLabelRegions(const string &str, vector<int> &regs, bool sanitize) {
277 
278  // label defined in the sub-geometries
279  vector<int> gregs;
280  for (int i=0; i<ng; i++) {
281 
282  // add regions from set geometries
283  gregs.clear();
284  if (g[i]) {
285  g[i]->getLabelRegions(str, gregs, sanitize);
286  }
287 
288  // shift region numbers according to indexing style
289  for (int j=0; j<gregs.size(); j++) {
290  gregs[j] += i*nmax;
291  }
292 
293  // add regions to the list
294  regs.insert(regs.end(), gregs.begin(), gregs.end());
295 
296  }
297 
298  // label defined in self (union geometry input block)
299  EGS_BaseGeometry::getLabelRegions(str, regs, sanitize);
300 
301  }
302 
303 }
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.
int nreg
Number of local regions in this geometry.
bool has_B_scaling
Does this geometry has B field scaling factor?
bool is_convex
Is this geometry convex?
bool has_rho_scaling
Does this geometry have relative mass density scvaling?
bool hasBScaling() const
Does this geometry object have a B field scaling feature?
virtual bool hasRhoScaling()
Does this geometry object have a mass density 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.
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.
virtual void getLabelRegions(const string &str, vector< int > &regs, bool sanitize=true)
Get the list of all regions labeled with str.
A class for storing information in a tree-like structure of key-value pairs. This class is used throu...
Definition: egs_input.h:182
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 geometry constructed as the union of other geometries.
void setMedia(EGS_Input *, int, const int *)
Don't set media when defining the union.
int nmax
max. number of regions in all of the geoms.
int ng
number of geometries.
static string type
the geometry type
EGS_BaseGeometry ** g
the geometries that form the union.
EGS_UnionGeometry(const vector< EGS_BaseGeometry * > &geoms, const int *priorities=0, const string &Name="")
Construct a geometry union from the vector of geometries geom.
Global egspp functions header file.
EGS_GLIB_EXPORT EGS_BaseGeometry * createGeometry(EGS_Input *input)
Definition: egs_glib.cpp:84
EGS_Input class header file.
A geometry union.
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.