EGSnrc C++ class library  Report PIRS-898 (2021)
Iwan Kawrakow, Ernesto Mainegra-Hing, Frederic Tessier, Reid Townson and Blake Walters
egs_dynamic_source.cpp
Go to the documentation of this file.
1 /*
2 ###############################################################################
3 #
4 # EGSnrc egs++ dynamic source
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: Blake Walters, 2017
25 #
26 # Contributors: Alexandre Demelo
27 # Hannah Gallop
28 #
29 ###############################################################################
30 */
31 
32 
38 #include "egs_dynamic_source.h"
39 #include "egs_input.h"
40 
41 static bool EGS_DYNAMIC_SOURCE_LOCAL inputSet = false;
42 
44  EGS_ObjectFactory *f) : EGS_BaseSource(input,f), source(0), valid(true) {
45  EGS_Input *isource = input->takeInputItem("source",false);
46  if (isource) {
48  delete isource;
49  }
50  if (!source) {
51  string sname;
52  int err = input->getInput("base source",sname);
53  if (err) {
54  err = input->getInput("source name",sname);
55  if (err) {
56  egsWarning("EGS_DynamicSource: missing/wrong inline source "
57  "definition and missing wrong 'base source' input\n");
58  return;
59  }
60  }
61 
63  if (!source) egsWarning("EGS_DynamicSource: base source %s"
64  " does not exist\n",sname.c_str());
65  }
66  //now read inputs relevant to dynamic source
67  //see if user wants to synchronize source with time read from
68  //iaea phsp or beam simulation source
69  vector<string> sync_options;
70  sync_options.push_back("no");
71  sync_options.push_back("yes");
72  sync = input->getInput("synchronize motion",sync_options,0);
73  if (sync && source->getObjectType()!="IAEA_PhspSource" &&
74  source->getObjectType()!="EGS_BeamSource") {
75  egsWarning("EGS_DynamicSource: source motion can only be synchronized with a source of type iaea_phsp_source or egs_beam_source.\n Will not synchronize.\n");
76  sync = false;
77  }
78 
79  //get control points
80  EGS_Input *dyninp = input->takeInputItem("motion");
81  if (dyninp) {
82  //get control points
83  ncpts=0;
84  vector<EGS_Float> point;
85  EGS_ControlPoint cpt;
86  stringstream itos;
87  int err;
88  int icpts=1;
89  itos << icpts;
90 
91  string inputTag = "control point";
92  string inputTag_backCompat = "control point " + itos.str();
93  EGS_Input *currentInput;
94 
95  while (true) {
96  currentInput = dyninp->takeInputItem(inputTag);
97  if (!currentInput || currentInput->getInput(inputTag, point)) {
98  currentInput = dyninp->takeInputItem(inputTag_backCompat);
99  if (!currentInput || currentInput->getInput(inputTag_backCompat, point)) {
100  delete currentInput;
101  break;
102  }
103  }
104  delete currentInput;
105 
106  if (point.size()!=8) {
107  egsWarning("EGS_DynamicSource: control point %i does not specify 8 values.\n",icpts);
108  valid = false;
109  }
110  else {
111  if (ncpts>0 && point[7] < cpts[ncpts-1].time) {
112  egsWarning("EGS_DynamicSource: time index of control point %i < time index of control point %i\n",icpts,ncpts);
113  valid = false;
114  }
115  else if (point[7] < 0.) {
116  egsWarning("EGS_DynamicSource: time index of control point %i < 0.0\n",icpts);
117  valid = false;
118  }
119  else {
120  ncpts++;
121  if (ncpts ==1 && point[7] > 0.0) {
122  egsWarning("EGS_DynamicSource: time index of control point 1 > 0.0. This will generate many warning messages.\n");
123  }
124  //set cpt values
125  cpt.iso = EGS_Vector(point[0],point[1],point[2]);
126  cpt.dsource = point[3];
127  cpt.theta = point[4];
128  cpt.phi = point[5];
129  cpt.phicol = point[6];
130  cpt.time = point[7];
131  //add it to the vector of control points
132  cpts.push_back(cpt);
133  icpts++;
134  itos.str("");
135  itos << icpts;
136  inputTag_backCompat = "control point " + itos.str();
137  }
138  }
139  }
140  if (ncpts<=1) {
141  egsWarning("EGS_DynamicSource: not enough or missing control points.\n");
142  valid = false;
143  }
144  if (cpts[ncpts-1].time == 0.0) {
145  egsWarning("EGS_DynamicSource: time index of last control point = 0. Something's wrong.\n");
146  valid = false;
147  }
148  else {
149  //normalize time index to max. value
150  for (int i=0; i<=ncpts-1; i++) {
151  cpts[i].time /= cpts[ncpts-1].time;
152  }
153  }
154  }
155  else {
156  egsWarning("EGS_DynamicSource: no control points input.\n");
157  valid = false;
158  }
159  setUp();
160 }
161 
162 void EGS_DynamicSource::setUp() {
163  //most setup done in constructor
164  otype="EGS_DynamicSource";
165  if (!isValid()) {
166  description = "Invalid dynamic source";
167  }
168  else {
169  description = "Dynamic source based on\n";
171  if (sync) {
172  description += "\n Source will be synched with time values read in (if available).";
173  }
174  }
175 }
176 
177 //actually select the rotation coordinates for the incident particle
178 int EGS_DynamicSource::getCoord(EGS_Float rand, EGS_ControlPoint &ipt) {
179  int iindex=0;
180  int i;
181  for (i=0; i<ncpts; i++) {
182  if (rand < cpts[i].time-epsilon) {
183  iindex =i;
184  break;
185  }
186  }
187  if (i==ncpts) {
188  egsWarning("EGS_DynamicSource: could not locate control point.\n");
189  return 1;
190  }
191  EGS_Float factor = (rand-cpts[iindex-1].time)/(cpts[iindex].time-cpts[iindex-1].time);
192  ipt.iso.x=cpts[iindex-1].iso.x+ (cpts[iindex].iso.x-cpts[iindex-1].iso.x)*factor;
193  ipt.iso.y=cpts[iindex-1].iso.y+ (cpts[iindex].iso.y-cpts[iindex-1].iso.y)*factor;
194  ipt.iso.z=cpts[iindex-1].iso.z+ (cpts[iindex].iso.z-cpts[iindex-1].iso.z)*factor;
195  ipt.dsource=cpts[iindex-1].dsource+ (cpts[iindex].dsource-cpts[iindex-1].dsource)*factor;
196  ipt.theta=cpts[iindex-1].theta+ (cpts[iindex].theta-cpts[iindex-1].theta)*factor;
197  ipt.phi=cpts[iindex-1].phi+ (cpts[iindex].phi-cpts[iindex-1].phi)*factor;
198  ipt.phicol=cpts[iindex-1].phicol+ (cpts[iindex].phicol-cpts[iindex-1].phicol)*factor;
199  return 0;
200 };
201 
207 void EGS_DynamicSource::containsDynamic(bool &hasdynamic) {
208  hasdynamic = true;
209 }
210 
211 extern "C" {
212 
213  static void setInputs() {
214  inputSet = true;
215 
216  setBaseSourceInputs(false, false);
217 
218  srcBlockInput->getSingleInput("library")->setValues({"egs_dynamic_source"});
219 
220  // Format:name, isRequired, description, vector string of allowed
221  srcBlockInput->addSingleInput("base source", true, "The name of a previously defined source");
222  srcBlockInput->addSingleInput("synchronize motion", false, "Whether or not to synchronize with time indices in original 'base source'. Does not impact egs_dynamic_geometry.", {"yes", "no"});
223 
224  auto motionPtr = srcBlockInput->addBlockInput("motion");
225  motionPtr->addSingleInput("control point", false, "xiso(1) yiso(1) ziso(1) dsource(1) theta(1) phi(1) phicol(1) mu(1)");
226  }
227 
228  EGS_DYNAMIC_SOURCE_EXPORT string getExample() {
229  string example;
230  example = {
231  R"(
232  # Example of egs_dynamic_source
233  #:start source:
234  library = egs_dynamic_source
235  name = my_source
236  base source = orig_source
237  # Source orig_source must already be defined
238  # Units in cm and degrees
239  :start motion:
240  control point = 0 0 0 100 0 0 0 0
241  control point = 0 0 0 100 360 0 0 0.5
242  control point = 0 0 0 100 90 0 0 0.5
243  control point = 0 0 0 100 90 360 0 1.0
244  :stop motion:
245  :stop source:
246 )"};
247  return example;
248  }
249 
250  EGS_DYNAMIC_SOURCE_EXPORT shared_ptr<EGS_BlockInput> getInputs() {
251  if(!inputSet) {
252  setInputs();
253  }
254  return srcBlockInput;
255  }
256 
257  EGS_DYNAMIC_SOURCE_EXPORT EGS_BaseSource *createSource(EGS_Input *input,
258  EGS_ObjectFactory *f) {
259  return
260  createSourceTemplate<EGS_DynamicSource>(input,f,"dynamic source");
261  }
262 
263 }
Base source class. All particle sources must be derived from this class.
const char * getSourceDescription() const
Get a short description of this source.
static EGS_BaseSource * getSource(const string &Name)
Get a pointer to the source named Name.
string description
A short source description.
static EGS_BaseSource * createSource(EGS_Input *)
Create sources from the information pointed to by input.
EGS_BaseSource * source
The source being rotated.
EGS_DynamicSource(EGS_BaseSource *Source, vector< EGS_ControlPoint > cpts, const string &Name="", EGS_ObjectFactory *f=0)
Construct a dynamic source using Source as the source and cpts as the control points....
void containsDynamic(bool &hasdynamic)
Check if the simulation source contains time indices.
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
An object factory.
string otype
The object type.
const string & getObjectType() const
Get the object type.
A class representing 3D vectors.
Definition: egs_vector.h:57
A source with simulated time-varying rotations/translations.
EGS_Input class header file.
const EGS_Float epsilon
The epsilon constant for floating point comparisons.
Definition: egs_functions.h:62
EGS_InfoFunction EGS_EXPORT egsWarning
Always use this function for reporting warnings.