EGSnrc C++ class library  Report PIRS-898 (2021)
Iwan Kawrakow, Ernesto Mainegra-Hing, Frederic Tessier, Reid Townson and Blake Walters
egs_lattice.cpp
Go to the documentation of this file.
1 /*
2 ###############################################################################
3 #
4 # EGSnrc egs++ lattice geometry
5 # Copyright (C) 2019 Rowan Thomson and Martin Martinov
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: Martin Martinov, 2019
25 #
26 # Contributors:
27 #
28 ###############################################################################
29 #
30 # When egs_lattice is used for publications, please cite the following paper:
31 #
32 # Martinov, Martin P., and Rowan M. Thomson. Taking EGSnrc to new lows:
33 # Development of egs++ lattice geometry and testing with microscopic
34 # geometries. Medical Physics 47, 3225-3232 (2020).
35 #
36 ###############################################################################
37 */
38 
39 
44 #include "egs_lattice.h"
45 #include "egs_input.h"
46 #include "egs_functions.h"
47 
48 using namespace std;
49 
50 static bool EGS_LATTICE_LOCAL inputSet = false;
51 
52 void EGS_Lattice::setMedia(EGS_Input *,int,const int *) {
53  egsWarning("EGS_Lattice::setMedia: don't use this method. Use the\n"
54  " setMedia() methods of the geometry objects that make up this geometry\n");
55 }
56 
57 void EGS_Lattice::setRelativeRho(int start, int end, EGS_Float rho) {
58  setRelativeRho(0);
59 }
60 
61 void EGS_Lattice::setRelativeRho(EGS_Input *) {
62  egsWarning("EGS_Lattice::setRelativeRho(): don't use this method."
63  " Use the\n setRelativeRho methods of the geometry objects that make up"
64  " this geometry\n");
65 }
66 
67 void EGS_Lattice::setBScaling(int start, int end, EGS_Float bf) {
68  setBScaling(0);
69 }
70 
71 void EGS_Lattice::setBScaling(EGS_Input *) {
72  egsWarning("EGS_Lattice::setBScaling(): don't use this method. "
73  "Use the\n setBScaling() methods of the geometry objects that make "
74  "up this geometry\n");
75 }
76 
77 EGS_Lattice::EGS_Lattice(EGS_BaseGeometry *B, EGS_BaseGeometry *S, int i, EGS_Float x,
78  EGS_Float y, EGS_Float z, const string &Name)
79  : EGS_BaseGeometry(Name), base(B),
80  sub(new EGS_TransformedGeometry(S,EGS_Vector(0,0,0))),
81  ind(i), a(x), b(y), c(z) {
82  type = base->getType();
83  type += " with a lattice of ";
84  type += sub->getType();
85  nreg = base->regions() + sub->regions();
86  has_rho_scaling = base->hasRhoScaling();
87  maxStep = base->regions()+1000000*sub->regions(); // Arbitrary step-length because I can't
88 }; // think of an elegant way to do this
89 
90 EGS_Lattice::~EGS_Lattice() {
91  if (!sub->deref()) {
92  delete sub;
93  }
94  if (!base->deref()) {
95  delete base;
96  }
97 };
98 
99 void EGS_Lattice::printInfo() const {
101  egsInformation(" base geometry = %s (type %s)\n",base->getName().c_str(),
102  base->getType().c_str());
103  egsInformation(" lattice subgeometry = %s (type %s)\n",sub->getName().c_str(),
104  sub->getType().c_str());
105  egsInformation(" lattice region %d with an (x,y,z) spacing of (%d,%d,%d)",
106  ind,a,b,c);
107  egsInformation("=======================================================\n");
108 }
109 
110 void EGS_Hexagonal_Lattice::setMedia(EGS_Input *,int,const int *) {
111  egsWarning("EGS_Hexagonal_Lattice::setMedia: don't use this method. Use the\n"
112  " setMedia() methods of the geometry objects that make up this geometry\n");
113 }
114 
115 void EGS_Hexagonal_Lattice::setRelativeRho(int start, int end, EGS_Float rho) {
116  setRelativeRho(0);
117 }
118 
119 void EGS_Hexagonal_Lattice::setRelativeRho(EGS_Input *) {
120  egsWarning("EGS_Hexagonal_Lattice::setRelativeRho(): don't use this method."
121  " Use the\n setRelativeRho methods of the geometry objects that make up"
122  " this geometry\n");
123 }
124 
125 void EGS_Hexagonal_Lattice::setBScaling(int start, int end, EGS_Float bf) {
126  setBScaling(0);
127 }
128 
129 void EGS_Hexagonal_Lattice::setBScaling(EGS_Input *) {
130  egsWarning("EGS_Hexagonal_Lattice::setBScaling(): don't use this method. "
131  "Use the\n setBScaling() methods of the geometry objects that make "
132  "up this geometry\n");
133 }
134 
135 EGS_Hexagonal_Lattice::EGS_Hexagonal_Lattice(EGS_BaseGeometry *B, EGS_BaseGeometry *S, int i, EGS_Float x,
136  const string &Name)
137  : EGS_BaseGeometry(Name), base(B),
138  sub(new EGS_TransformedGeometry(S,EGS_Vector(0,0,0))),
139  ind(i), a(x), d(4,0.0) {
140  type = base->getType();
141  type += " with a hexagonal lattice of ";
142  type += sub->getType();
143  gap = a*sqrt(3.0)/2.0;
144  nreg = base->regions() + sub->regions();
145  has_rho_scaling = base->hasRhoScaling();
146  maxStep = base->regions()+1000000*sub->regions(); // Arbitrary step-length because I can't
147 }; // think of an elegant way to do this
148 
149 EGS_Hexagonal_Lattice::~EGS_Hexagonal_Lattice() {
150  if (!sub->deref()) {
151  delete sub;
152  }
153  if (!base->deref()) {
154  delete base;
155  }
156 };
157 
158 void EGS_Hexagonal_Lattice::printInfo() const {
160  egsInformation(" base geometry = %s (type %s)\n",base->getName().c_str(),
161  base->getType().c_str());
162  egsInformation(" hexagonal lattice subgeometry = %s (type %s)\n",sub->getName().c_str(),
163  sub->getType().c_str());
164  egsInformation(" hexagonal lattice region %d with a spacing of %d",ind,a);
165  egsInformation("=======================================================\n");
166 }
167 extern "C" {
168 
169  static void setInputs() {
170  inputSet = true;
171 
172  setBaseGeometryInputs(false);
173 
174  geomBlockInput->getSingleInput("library")->setValues({"egs_lattice"});
175 
176  // Format: name, isRequired, description, vector string of allowed values
177  geomBlockInput->addSingleInput("base geometry", true, "The name of a previously defined geometry, into which the lattice will be enveloped.");
178  geomBlockInput->addSingleInput("subgeometry", true, "The name of a geometry to place at each lattice position.");
179  geomBlockInput->addSingleInput("subgeometry index", true, "The region or list of regions that contain the lattice.");
180  geomBlockInput->addSingleInput("spacing", true, "The spacing as defined for Bravais (x, y, z), Cubic (x), or Hexagonal modes (s, close-packed distance). ");
181  geomBlockInput->addSingleInput("type", false, "The type of lattice. Currently just used for hexagonal lattices.", {"hexagonal"});
182  }
183 
184  EGS_LATTICE_EXPORT string getExample() {
185  string example;
186  example = {
187  R"(
188  # Example Bravais lattice with spacings 1, 2 and 3
189  #:start geometry:
190  library = egs_lattice
191  name = phantom_w_microcavity
192  base geometry = phantom
193  subgeometry = microcavity
194  subgeometry index = 0
195  spacing = 1 2 3
196  :stop geometry:
197 )"};
198  return example;
199  }
200 
201  EGS_LATTICE_EXPORT shared_ptr<EGS_BlockInput> getInputs() {
202  if(!inputSet) {
203  setInputs();
204  }
205  return geomBlockInput;
206  }
207 
208  EGS_LATTICE_EXPORT EGS_BaseGeometry *createGeometry(EGS_Input *input) {
209  int err = 0;
210 
211  // Get base geometry
212  EGS_Input *i = input->getInputItem("base geometry");
213  if (!i) {
214  egsWarning("createGeometry(lattice): base geometry must be defined\n"
215  " using 'base geometry = some_geom'?\n");
216  return 0;
217  }
218  EGS_Input *ig = i->getInputItem("geometry");
219  EGS_BaseGeometry *b;
220  if (ig) {
222  delete ig;
223  if (!b) {
224  egsWarning("createGeometry(lattice): incorrect base geometry definition\n");
225  delete i;
226  return 0;
227  }
228  }
229  else {
230  string bgname;
231  err = i->getInput("base geometry",bgname);
232  delete i;
233  if (err) {
234  egsWarning("createGeometry(lattice): missing/incorrect 'base geometry' input\n");
235  return 0;
236  }
237  b = EGS_BaseGeometry::getGeometry(bgname);
238  if (!b) {
239  egsWarning("createGeometry(lattice): no geometry with name %s defined\n",
240  bgname.c_str());
241  return 0;
242  }
243  }
244 
245  // Get subgeometry
246  i = input->getInputItem("subgeometry");
247  if (!i) {
248  egsWarning("createGeometry(lattice): subgeometry must be defined\n"
249  " using 'subgeometry = some_geom'?\n");
250  return 0;
251  }
252  ig = i->getInputItem("geometry");
253  EGS_BaseGeometry *s;
254  if (ig) {
256  delete ig;
257  if (!s) {
258  egsWarning("createGeometry(lattice): incorrect subgeometry definition\n");
259  delete i;
260  return 0;
261  }
262  }
263  else {
264  string bgname;
265  err = i->getInput("subgeometry",bgname);
266  delete i;
267  if (err) {
268  egsWarning("createGeometry(lattice): missing/incorrect 'subgeometry' input\n");
269  return 0;
270  }
271  s = EGS_BaseGeometry::getGeometry(bgname);
272  if (!s) {
273  egsWarning("createGeometry(lattice): no geometry with name %s defined\n",
274  bgname.c_str());
275  return 0;
276  }
277  }
278 
279  // Get base region in which to place subgeometries
280  int ind = -1;
281  i = input->getInputItem("subgeometry index");
282  if (!i) {
283  egsWarning("createGeometry(lattice): subgeometry index must be defined\n"
284  " using 'subgeometry index = some_index'\n");
285  return 0;
286  }
287  else {
288  err = i->getInput("subgeometry index",ind);
289  delete i;
290  if (err) {
291  egsWarning("createGeometry(lattice): missing/incorrect 'subgeometry index' input\n");
292  return 0;
293  }
294  else if (ind < 0 || ind >= b->regions()) { // Not a real index
295  egsWarning("createGeometry(lattice): subgeometry index %d"
296  " is not valid, must be a region in base geometry\n",ind);
297  return 0;
298  }
299  }
300 
301  // Get one subgeometry spacing (hexagonal or cubic) or three (Bravais)
302  vector<EGS_Float> space;
303  err = input->getInput("spacing",space);
304  if (!err) {
305  for (int i=0; i < space.size(); i++) {
306  if (space[i] <= 0) {
307  egsWarning("createGeometry(lattice): spacing"
308  " is not valid, spacings must be greater than zero\n");
309  return 0;
310  }
311  }
312  if (space.size() != 1 && space.size() != 3) {
313  egsWarning("createGeometry(lattice): spacing"
314  " is not valid, input either one or three"
315  "x, y, and z spacings\n");
316  return 0;
317  }
318  }
319 
320  // Check for hexagonal lattice
321  string type;
322  input->getInput("type",type);
323 
324  // Final build
325  EGS_BaseGeometry *result;
326  if (space.size() == 3) {
327  result = new EGS_Lattice(b, s, ind, space[0], space[1], space[2]);
328  }
329  else if (input->compare("hexagonal",type)) {
330  result = new EGS_Hexagonal_Lattice(b, s, ind, space[0]);
331  }
332  else {
333  result = new EGS_Lattice(b, s, ind, space[0], space[0], space[0]);
334  }
335  result->setName(input);
336  return result;
337  }
338 
339  void EGS_Lattice::getLabelRegions(const string &str, vector<int> &regs, bool sanitize) {
340  // labels defined in base geometry (matching indices)
341  base->getLabelRegions(str, regs, sanitize);
342  int index = regs.size();
343 
344  // labels defined in sub geometries (shifting by base nreg)
345  EGS_BaseGeometry::getLabelRegions(str, regs, sanitize);
346  for (; index<regs.size(); index++) {
347  regs[index] += base->regions();
348  }
349  }
350 
351  void EGS_Hexagonal_Lattice::getLabelRegions(const string &str, vector<int> &regs, bool sanitize) {
352  // labels defined in base geometry (matching indices)
353  base->getLabelRegions(str, regs, sanitize);
354  int index = regs.size();
355 
356  // labels defined in sub geometries (shifting by base nreg)
357  EGS_BaseGeometry::getLabelRegions(str, regs, sanitize);
358  for (; index<regs.size(); index++) {
359  regs[index] += base->regions();
360  }
361  }
362 }
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.
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.
virtual void printInfo() const
Print information about this geometry.
static EGS_BaseGeometry * getGeometry(const string &Name)
Get a pointer to the geometry named Name.
virtual void getLabelRegions(const string &str, vector< int > &regs, bool sanitize=true)
Get the list of all regions labeled with str.
EGS_Float a
The center-to-center distance to the nearest 12 neighbours.
Definition: egs_lattice.h:538
EGS_BaseGeometry * base
The geometry within which the sub geometry appears.
Definition: egs_lattice.h:534
EGS_TransformedGeometry * sub
The sub geometry that could appear within base.
Definition: egs_lattice.h:535
int ind
The region in base geom where we could encounter sub geom.
Definition: egs_lattice.h:536
A class for storing information in a tree-like structure of key-value pairs. This class is used throu...
Definition: egs_input.h:182
static bool compare(const string &s1, const string &s2)
Definition: egs_input.cpp:1173
EGS_Input * getInputItem(const string &key) const
Same as the previous function but now ownership remains with the EGS_Input object.
Definition: egs_input.cpp:248
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 Bravais, cubic, and hexagonal lattice geometry.
Definition: egs_lattice.h:146
EGS_TransformedGeometry * sub
The sub geometry that could appear within base.
Definition: egs_lattice.h:150
EGS_BaseGeometry * base
The geometry within which the sub geometry appears.
Definition: egs_lattice.h:149
EGS_Float c
The center-to-center distance along x, y, and z.
Definition: egs_lattice.h:153
int ind
The region in base geom where we could encounter sub geom.
Definition: egs_lattice.h:151
A transformed geometry.
A class representing 3D vectors.
Definition: egs_vector.h:57
Global egspp functions header file.
EGS_GLIB_EXPORT EGS_BaseGeometry * createGeometry(EGS_Input *input)
Definition: egs_glib.cpp:84
EGS_Input class header file.
Lattice geometries: 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 egsWarning
Always use this function for reporting warnings.