FLAME  devel
 All Classes Functions Variables Typedefs Enumerations Pages
linear.cpp
1 
2 #include <string>
3 #include <algorithm>
4 
5 #include "flame/linear.h"
6 #include "flame/state/vector.h"
7 #include "flame/state/matrix.h"
8 
9 
10 #define sqr(x) ((x)*(x))
11 #define cube(x) ((x)*(x)*(x))
12 
13 // Phase-space units.
14 #if false
15  // Use [m, rad, m, rad, rad, eV/u].
16  #define MtoMM 1e0
17 #else
18  // Use [mm, rad, mm, rad, rad, MeV/u].
19  #define MtoMM 1e3
20 #endif
21 
22 MatrixState::MatrixState(const Config& c)
23  :StateBase(c)
24  ,state(boost::numeric::ublas::identity_matrix<double>(maxsize))
25 {
26  try{
27  const std::vector<double>& I = c.get<std::vector<double> >("initial");
28  if(I.size()>state.data().size())
29  throw std::invalid_argument("Initial state size too big");
30  std::copy(I.begin(), I.end(), state.data().begin());
31  }catch(key_error&){
32  // default to identity
33  }catch(boost::bad_any_cast&){
34  throw std::invalid_argument("'initial' has wrong type (must be vector)");
35  }
36 }
37 
38 MatrixState::~MatrixState() {}
39 
40 MatrixState::MatrixState(const MatrixState& o, clone_tag t)
41  :StateBase(o, t)
42  ,state(o.state)
43 {}
44 
45 void MatrixState::assign(const StateBase& other)
46 {
47  const MatrixState *O = dynamic_cast<const MatrixState*>(&other);
48  if(!O)
49  throw std::invalid_argument("Can't assign State: incompatible types");
50  state = O->state;
51  StateBase::assign(other);
52 }
53 
54 void MatrixState::show(std::ostream& strm, int level) const
55 {
56  strm<<"State: "<<state<<"\n";
57 }
58 
59 bool MatrixState::getArray(unsigned idx, ArrayInfo& Info) {
60  if(idx==0) {
61  Info.name = "state";
62  Info.ptr = &state(0,0);
63  Info.type = ArrayInfo::Double;
64  Info.ndim = 2;
65  Info.dim[0] = state.size1();
66  Info.dim[1] = state.size2();
67  Info.stride[0] = sizeof(double)*state.size1();
68  Info.stride[1] = sizeof(double);
69  return true;
70  }
71  return StateBase::getArray(idx-1, Info);
72 }
73 
74 VectorState::VectorState(const Config& c)
75  :StateBase(c)
76  ,state(maxsize, 0.0)
77 {
78  try{
79  const std::vector<double>& I = c.get<std::vector<double> >("initial");
80  if(I.size()>state.size())
81  throw std::invalid_argument("Initial state size too big");
82  std::copy(I.begin(), I.end(), state.begin());
83  }catch(key_error&){
84  }catch(boost::bad_any_cast&){
85  }
86 }
87 
88 VectorState::~VectorState() {}
89 
90 VectorState::VectorState(const VectorState& o, clone_tag t)
91  :StateBase(o, t)
92  ,state(o.state)
93 {}
94 
95 void VectorState::assign(const StateBase& other)
96 {
97  const VectorState *O = dynamic_cast<const VectorState*>(&other);
98  if(!O)
99  throw std::invalid_argument("Can't assign State: incompatible types");
100  state = O->state;
101  StateBase::assign(other);
102 }
103 
104 void VectorState::show(std::ostream& strm) const
105 {
106  strm<<"State: "<<state<<"\n";
107 }
108 
109 bool VectorState::getArray(unsigned idx, ArrayInfo& Info) {
110  if(idx==0) {
111  Info.name = "state";
112  Info.ptr = &state(0);
113  Info.type = ArrayInfo::Double;
114  Info.ndim = 1;
115  Info.dim[0] = state.size();
116  Info.stride[0] = sizeof(double);
117  return true;
118  }
119  return StateBase::getArray(idx-1, Info);
120 }
121 
122 namespace {
123 
124 template<typename Base>
125 void Get2by2Matrix(const double L, const double K, const unsigned ind, typename Base::value_t &M)
126 {
127  // Transport matrix for one plane for a Quadrupole.
128  double sqrtK,
129  psi,
130  cs,
131  sn;
132 
133  if (K > 0e0) {
134  // Focusing.
135  sqrtK = sqrt(K);
136  psi = sqrtK*L;
137  cs = ::cos(psi);
138  sn = ::sin(psi);
139 
140  M(ind, ind) = M(ind+1, ind+1) = cs;
141  if (sqrtK != 0e0)
142  M(ind, ind+1) = sn/sqrtK;
143  else
144  M(ind, ind+1) = L;
145  if (sqrtK != 0e0)
146  M(ind+1, ind) = -sqrtK*sn;
147  else
148  M(ind+1, ind) = 0e0;
149  } else {
150  // Defocusing.
151  sqrtK = sqrt(-K);
152  psi = sqrtK*L;
153  cs = ::cosh(psi);
154  sn = ::sinh(psi);
155 
156  M(ind, ind) = M(ind+1, ind+1) = cs;
157  if (sqrtK != 0e0)
158  M(ind, ind+1) = sn/sqrtK;
159  else
160  M(ind, ind+1) = L;
161  if (sqrtK != 0e0)
162  M(ind+1, ind) = sqrtK*sn;
163  else
164  M(ind+1, ind) = 0e0;
165  }
166 }
167 
168 template<typename Base>
169 struct ElementSource : public Base
170 {
171  typedef Base base_t;
172  typedef typename base_t::state_t state_t;
173  ElementSource(const Config& c)
174  :base_t(c), istate(c)
175  {}
176 
177  virtual void advance(StateBase& s)
178  {
179  state_t& ST = static_cast<state_t&>(s);
180  // Replace state with our initial values
181  ST.assign(istate);
182  }
183 
184  virtual void show(std::ostream& strm, int level) const
185  {
186  ElementVoid::show(strm, level);
187  strm<<"Initial: "<<istate.state<<"\n";
188  }
189 
190  state_t istate;
191  // note that 'transfer' is not used by this element type
192 
193  virtual ~ElementSource() {}
194 
195  virtual const char* type_name() const {return "source";}
196 };
197 
198 template<typename Base>
199 struct ElementMark : public Base
200 {
201  // Transport (identity) matrix for a Marker.
202  typedef Base base_t;
203  typedef typename base_t::state_t state_t;
204  ElementMark(const Config& c)
205  :base_t(c)
206  {
207 // double L = c.get<double>("L", 0e0);
208 
209  // Identity matrix.
210  }
211  virtual ~ElementMark() {}
212 
213  virtual const char* type_name() const {return "marker";}
214 };
215 
216 template<typename Base>
217 struct ElementDrift : public Base
218 {
219  // Transport matrix for a Drift.
220  typedef Base base_t;
221  typedef typename base_t::state_t state_t;
222  ElementDrift(const Config& c)
223  :base_t(c)
224  {
225  double L = this->length*MtoMM; // Convert from [m] to [mm].
226 
227  this->transfer(state_t::PS_X, state_t::PS_PX) = L;
228  this->transfer(state_t::PS_Y, state_t::PS_PY) = L;
229  // For total path length.
230 // this->transfer(state_t::PS_S, state_t::PS_S) = L;
231  }
232  virtual ~ElementDrift() {}
233 
234  virtual const char* type_name() const {return "drift";}
235 };
236 
237 template<typename Base>
238 struct ElementSBend : public Base
239 {
240  // Transport matrix for a Gradient Sector Bend (cylindrical coordinates).
241  typedef Base base_t;
242  typedef typename base_t::state_t state_t;
243  ElementSBend(const Config& c)
244  :base_t(c)
245  {
246  double L = this->length*MtoMM,
247  phi = c.get<double>("phi"), // [rad].
248  rho = L/phi,
249  K = c.get<double>("K", 0e0)/sqr(MtoMM), // [1/m^2].
250  Kx = K + 1e0/sqr(rho),
251  Ky = -K;
252 
253  // Horizontal plane.
254  Get2by2Matrix<Base>(L, Kx, (unsigned)state_t::PS_X, this->transfer);
255  // Vertical plane.
256  Get2by2Matrix<Base>(L, Ky, (unsigned)state_t::PS_Y, this->transfer);
257  // Longitudinal plane.
258 // this->transfer(state_t::PS_S, state_t::PS_S) = L;
259  }
260  virtual ~ElementSBend() {}
261 
262  virtual const char* type_name() const {return "sbend";}
263 };
264 
265 template<typename Base>
266 struct ElementQuad : public Base
267 {
268  // Transport matrix for a Quadrupole; K = B2/Brho.
269  typedef Base base_t;
270  typedef typename base_t::state_t state_t;
271  ElementQuad(const Config& c)
272  :base_t(c)
273  {
274  double L = this->length*MtoMM,
275  //B2 = c.get<double>("B2"),
276  K = c.get<double>("K", 0e0)/sqr(MtoMM);
277 
278  // Horizontal plane.
279  Get2by2Matrix<Base>(L, K, (unsigned)state_t::PS_X, this->transfer);
280  // Vertical plane.
281  Get2by2Matrix<Base>(L, -K, (unsigned)state_t::PS_Y, this->transfer);
282  // Longitudinal plane.
283  // For total path length.
284 // this->transfer(state_t::PS_S, state_t::PS_S) = L;
285  }
286  virtual ~ElementQuad() {}
287 
288  virtual const char* type_name() const {return "quadrupole";}
289 };
290 
291 template<typename Base>
292 struct ElementSolenoid : public Base
293 {
294  // Transport (identity) matrix for a Solenoid; K = B0/(2 Brho).
295  typedef Base base_t;
296  typedef typename base_t::state_t state_t;
297  ElementSolenoid(const Config& c)
298  :base_t(c)
299  {
300  double L = this->length*MtoMM, // Convert from [m] to [mm].
301 // B = c.get<double>("B"),
302  K = c.get<double>("K", 0e0)/MtoMM, // Convert from [m] to [mm].
303  C = ::cos(K*L),
304  S = ::sin(K*L);
305 
306  this->transfer(state_t::PS_X, state_t::PS_X)
307  = this->transfer(state_t::PS_PX, state_t::PS_PX)
308  = this->transfer(state_t::PS_Y, state_t::PS_Y)
309  = this->transfer(state_t::PS_PY, state_t::PS_PY)
310  = sqr(C);
311 
312  if (K != 0e0)
313  this->transfer(state_t::PS_X, state_t::PS_PX) = S*C/K;
314  else
315  this->transfer(state_t::PS_X, state_t::PS_PX) = L;
316  this->transfer(state_t::PS_X, state_t::PS_Y) = S*C;
317  if (K != 0e0)
318  this->transfer(state_t::PS_X, state_t::PS_PY) = sqr(S)/K;
319  else
320  this->transfer(state_t::PS_X, state_t::PS_PY) = 0e0;
321 
322  this->transfer(state_t::PS_PX, state_t::PS_X) = -K*S*C;
323  this->transfer(state_t::PS_PX, state_t::PS_Y) = -K*sqr(S);
324  this->transfer(state_t::PS_PX, state_t::PS_PY) = S*C;
325 
326  this->transfer(state_t::PS_Y, state_t::PS_X) = -S*C;
327  if (K != 0e0)
328  this->transfer(state_t::PS_Y, state_t::PS_PX) = -sqr(S)/K;
329  else
330  this->transfer(state_t::PS_Y, state_t::PS_PX) = 0e0;
331  if (K != 0e0)
332  this->transfer(state_t::PS_Y, state_t::PS_PY) = S*C/K;
333  else
334  this->transfer(state_t::PS_Y, state_t::PS_PY) = L;
335 
336  this->transfer(state_t::PS_PY, state_t::PS_X) = K*sqr(S);
337  this->transfer(state_t::PS_PY, state_t::PS_PX) = -S*C;
338  this->transfer(state_t::PS_PY, state_t::PS_Y) = -K*S*C;
339 
340  // Longitudinal plane.
341  // For total path length.
342 // this->transfer(state_t::PS_S, state_t::PS_S) = L;
343  }
344  virtual ~ElementSolenoid() {}
345 
346  virtual const char* type_name() const {return "solenoid";}
347 };
348 
349 template<typename Base>
350 struct ElementGeneric : public Base
351 {
352  typedef Base base_t;
353  typedef typename base_t::state_t state_t;
354  ElementGeneric(const Config& c)
355  :base_t(c)
356  {
357  std::vector<double> I = c.get<std::vector<double> >("transfer");
358  if(I.size()>this->transfer.data().size())
359  throw std::invalid_argument("Initial transfer size too big");
360  std::copy(I.begin(), I.end(), this->transfer.data().begin());
361  }
362  virtual ~ElementGeneric() {}
363 
364  virtual const char* type_name() const {return "generic";}
365 };
366 
367 } // namespace
368 
369 void registerLinear()
370 {
371  Machine::registerState<VectorState>("Vector");
372  Machine::registerState<MatrixState>("TransferMatrix");
373 
374  Machine::registerElement<ElementSource<LinearElementBase<VectorState> > >("Vector", "source");
375  Machine::registerElement<ElementSource<LinearElementBase<MatrixState> > >("TransferMatrix", "source");
376 
377  Machine::registerElement<ElementMark<LinearElementBase<VectorState> > >("Vector", "marker");
378  Machine::registerElement<ElementMark<LinearElementBase<MatrixState> > >("TransferMatrix", "marker");
379 
380  Machine::registerElement<ElementDrift<LinearElementBase<VectorState> > >("Vector", "drift");
381  Machine::registerElement<ElementDrift<LinearElementBase<MatrixState> > >("TransferMatrix", "drift");
382 
383  Machine::registerElement<ElementSBend<LinearElementBase<VectorState> > >("Vector", "sbend");
384  Machine::registerElement<ElementSBend<LinearElementBase<MatrixState> > >("TransferMatrix", "sbend");
385 
386  Machine::registerElement<ElementQuad<LinearElementBase<VectorState> > >("Vector", "quadrupole");
387  Machine::registerElement<ElementQuad<LinearElementBase<MatrixState> > >("TransferMatrix", "quadrupole");
388 
389  Machine::registerElement<ElementSolenoid<LinearElementBase<VectorState> > >("Vector", "solenoid");
390  Machine::registerElement<ElementSolenoid<LinearElementBase<MatrixState> > >("TransferMatrix", "solenoid");
391 
392  Machine::registerElement<ElementGeneric<LinearElementBase<VectorState> > >("Vector", "generic");
393  Machine::registerElement<ElementGeneric<LinearElementBase<MatrixState> > >("TransferMatrix", "generic");
394 }
virtual void assign(const StateBase &other)
Definition: linear.cpp:95
Simulation state which include only a matrix.
Definition: matrix.h:13
void assign(const StateBase &other)
Definition: linear.cpp:45
Simulation state which include only a vector.
Definition: vector.h:13
virtual void show(std::ostream &strm, int level) const
Definition: linear.cpp:54
The abstract base class for all simulation state objects.
Definition: base.h:28
Associative configuration container.
Definition: config.h:66
Used with StateBase::getArray() to describe a single parameter.
Definition: base.h:48
virtual void assign(const StateBase &other)=0
Definition: base.cpp:30
virtual void assign(const StateBase &other)
Definition: moment.cpp:233
size_t dim[maxdims]
Array dimensions in elements.
Definition: base.h:66
size_t stride[maxdims]
Array strides in bytes.
Definition: base.h:68
virtual bool getArray(unsigned index, ArrayInfo &Info)
Introspect named parameter of the derived class.
Definition: base.cpp:35
detail::RT< T >::type get(const std::string &name) const
Definition: config.h:123
virtual void show(std::ostream &, int level) const
Definition: base.cpp:67
virtual bool getArray(unsigned idx, ArrayInfo &Info)
Introspect named parameter of the derived class.
Definition: linear.cpp:109
virtual bool getArray(unsigned idx, ArrayInfo &Info)
Introspect named parameter of the derived class.
Definition: linear.cpp:59
const char * name
The parameter name.
Definition: base.h:52
unsigned ndim
Definition: base.h:64