6 #include <boost/lexical_cast.hpp>
8 #include <boost/numeric/ublas/vector_proxy.hpp>
9 #include <boost/numeric/ublas/matrix_proxy.hpp>
11 #include "flame/constants.h"
13 #include "flame/moment.h"
14 #include "flame/moment_sup.h"
15 #include "flame/rf_cavity.h"
16 #include "flame/chg_stripper.h"
18 #include "flame/h5loader.h"
20 #define sqr(x) ((x)*(x))
21 #define cube(x) ((x)*(x)*(x))
23 namespace ub = boost::numeric::ublas;
30 template<
typename ARR>
31 bool load_storage(ARR& to,
const Config& conf,
const std::string& name,
bool T=
true)
34 const std::vector<double>& val(conf.
get<std::vector<double> >(name));
35 if(to.size()!=val.size()) {
36 throw std::invalid_argument(SB()<<
"Array "<<name<<
" must have "<<to.size()<<
" elements, not "<<val.size());
38 std::copy(val.begin(), val.end(), to.begin());
41 }
catch(std::exception&){
43 throw std::invalid_argument(name+
" not defined or has wrong type (must be vector)");
52 std::ostream& operator<<(std::ostream& strm,
const Particle& P)
55 <<
"IonZ="<<std::scientific << std::setprecision(10)<<P.
IonZ
69 MomentState::MomentState(
const Config& c)
73 ,moment0_env(maxsize, 0e0)
74 ,moment0_rms(maxsize, 0e0)
75 ,moment1_env(boost::numeric::ublas::identity_matrix<double>(maxsize))
83 double icstate_f = 0.0;
84 bool have_cstate = c.
tryGet<
double>(
"cstate", icstate_f);
85 size_t icstate = (size_t)icstate_f;
87 std::string vectorname(c.
get<std::string>(
"vector_variable",
"moment0"));
88 std::string matrixname(c.
get<std::string>(
"matrix_variable",
"initial"));
90 std::vector<double> ics, nchg;
91 bool have_ics = c.
tryGet<std::vector<double> >(
"IonChargeStates", ics);
93 ref.IonEs = c.
get<
double>(
"IonEs", 0e0),
94 ref.IonEk = c.
get<
double>(
"IonEk", 0e0);
98 ref.IonZ = c.
get<
double>(
"IonZ", 0e0);
99 ref.IonQ = c.
get<
double>(
"IonQ", 1e0);
101 ics.push_back(ref.IonZ);
102 nchg.push_back(ref.IonQ);
106 throw std::invalid_argument(
"IonChargeStates w/ length 0");
107 if(icstate>=ics.size())
108 throw std::invalid_argument(
"IonChargeStates[cstate] is out of bounds");
110 nchg = c.
get<std::vector<double> >(
"NCharge");
111 if(nchg.size()!=ics.size())
112 throw std::invalid_argument(
"NCharge[] and IonChargeStates[] must have equal length");
126 if(!have_cstate && !have_ics) {
128 }
else if(!have_cstate && have_ics) {
132 }
else if(have_cstate && have_ics) {
136 ics[0] = ics[icstate];
137 nchg[0] = nchg[icstate];
142 throw std::invalid_argument(
"MomentState: must define IonChargeStates and NCharge when cstate is set");
146 real.resize(ics.size());
147 moment0.resize(ics.size());
148 moment1.resize(ics.size());
150 for(
size_t i=0; i<ics.size(); i++) {
151 std::string num(boost::lexical_cast<std::string>(icstate+i));
153 moment0[i].resize(maxsize);
154 moment1[i].resize(maxsize, maxsize);
155 moment1[i] = boost::numeric::ublas::identity_matrix<double>(maxsize);
157 load_storage(moment0[i].data(), c, vectorname+num);
158 load_storage(moment1[i].data(), c, matrixname+num);
162 real[i].IonZ = ics[i];
163 real[i].IonQ = nchg[i];
165 real[i].phis = moment0[i][PS_S];
166 real[i].IonEk += moment0[i][PS_PS]*MeVtoeV;
176 moment0[0].resize(maxsize);
177 moment1[0].resize(maxsize, maxsize);
179 load_storage(moment0[0].data(), c, vectorname,
false);
180 load_storage(moment1[0].data(), c, matrixname,
false);
186 MomentState::~MomentState() {}
188 void MomentState::calc_rms()
190 assert(real.size()>0);
191 assert(moment0_env.size()==maxsize);
192 assert(moment0_rms.size()==maxsize);
193 assert(moment1_env.size1()==maxsize);
194 assert(moment1_env.size2()==maxsize);
197 for(
size_t n=0; n<real.size(); n++) {
198 totQ += real[n].IonQ;
200 noalias(moment0_env) = moment0[n]*real[n].IonQ;
202 noalias(moment0_env) += moment0[n]*real[n].IonQ;
207 moment1_env = ub::zero_matrix<double>(state_t::maxsize);
208 boost::numeric::ublas::slice S(0, 1, 6);
209 for(
size_t n=0; n<real.size(); n++) {
210 const double Q = real[n].IonQ;
211 state_t::vector_t m0diff(moment0[n]-moment0_env);
213 ub::project(moment1_env, S, S) += ub::project(Q*(moment1[n]+ub::outer_prod(m0diff, m0diff)), S, S);
217 for(
size_t j=0; j<maxsize; j++) {
218 moment0_rms[j] = sqrt(moment1_env(j,j));
222 MomentState::MomentState(
const MomentState& o, clone_tag t)
228 ,moment0_env(o.moment0_env)
229 ,moment0_rms(o.moment0_rms)
230 ,moment1_env(o.moment1_env)
237 throw std::invalid_argument(
"Can't assign State: incompatible types");
240 moment0 = O->moment0;
241 moment1 = O->moment1;
242 moment0_env = O->moment0_env;
243 moment0_rms = O->moment0_rms;
244 moment1_env = O->moment1_env;
251 strm<<
"State: empty";
256 strm<<
"State: moment0 mean="<<moment0_env;
259 strm << std::scientific << std::setprecision(8)
260 <<
"\nState:\n energy [eV] =\n" << std::setw(20) << real[0].IonEk <<
"\n moment0 mean =\n ";
261 for (
size_t k = 0; k < MomentState::maxsize; k++)
262 strm << std::scientific << std::setprecision(10) << std::setw(18) << moment0_env(k) <<
",";
263 strm << std::scientific << std::setprecision(10)
264 <<
"\n moment0 rms =\n ";
265 for (
size_t k = 0; k < MomentState::maxsize; k++)
266 strm << std::scientific << std::setprecision(10) << std::setw(18) << moment0_rms(k) <<
",";
267 strm <<
"\n moment1 mean =\n";
268 for (
size_t j = 0; j < MomentState::maxsize; j++) {
270 for (
size_t k = 0; k < MomentState::maxsize; k++) {
271 strm << std::scientific << std::setprecision(10) << std::setw(18) << moment1_env(j, k) <<
",";
273 if (j < MomentState::maxsize-1) strm <<
"\n";
277 strm<<
"\n Reference state:\n "<<ref<<
"\n";
278 for(
size_t k=0; k<
size(); k++) {
279 strm<<
" Charge state "<<k<<
"\n"
281 " moment0 "<<moment0[k]<<
"\n";
284 " moment1 "<<moment1[k]<<
"\n";
292 Info.
name =
"moment1_env";
293 Info.
ptr = &moment1_env(0,0);
294 Info.type = ArrayInfo::Double;
296 Info.
dim[0] = moment1_env.size1();
297 Info.
dim[1] = moment1_env.size2();
298 Info.
stride[0] =
sizeof(double)*moment1_env.size2();
299 Info.
stride[1] =
sizeof(double);
301 }
else if(idx==I++) {
309 static_assert(
sizeof(moment1[0])>=
sizeof(
double)*maxsize*maxsize,
310 "storage assumption violated");
311 Info.
name =
"moment1";
312 Info.
ptr = &moment1[0](0,0);
313 Info.type = ArrayInfo::Double;
315 Info.
dim[0] = moment1[0].size1();
316 Info.
dim[1] = moment1[0].size2();
317 Info.
dim[2] = moment1.size();
318 Info.
stride[0] =
sizeof(double)*moment1_env.size2();
319 Info.
stride[1] =
sizeof(double);
320 Info.
stride[2] =
sizeof(moment1[0]);
322 }
else if(idx==I++) {
323 Info.
name =
"moment0_env";
324 Info.
ptr = &moment0_env(0);
325 Info.type = ArrayInfo::Double;
327 Info.
dim[0] = moment0_env.size();
328 Info.
stride[0] =
sizeof(double);
330 }
else if(idx==I++) {
331 Info.
name =
"moment0_rms";
332 Info.
ptr = &moment0_rms(0);
333 Info.type = ArrayInfo::Double;
335 Info.
dim[0] = moment0_rms.size();
336 Info.
stride[0] =
sizeof(double);
338 }
else if(idx==I++) {
340 static_assert(
sizeof(moment0[0])>=
sizeof(
double)*maxsize,
341 "storage assumption violated");
342 Info.
name =
"moment0";
343 Info.
ptr = &moment0[0][0];
344 Info.type = ArrayInfo::Double;
346 Info.
dim[0] = moment0[0].size();
347 Info.
dim[1] = moment0.size();
348 Info.
stride[0] =
sizeof(double);
349 Info.
stride[1] =
sizeof(moment0[0]);
351 }
else if(idx==I++) {
352 Info.
name =
"ref_IonZ";
354 Info.type = ArrayInfo::Double;
357 }
else if(idx==I++) {
358 Info.
name =
"ref_IonQ";
360 Info.type = ArrayInfo::Double;
363 }
else if(idx==I++) {
364 Info.
name =
"ref_IonEs";
366 Info.type = ArrayInfo::Double;
369 }
else if(idx==I++) {
370 Info.
name =
"ref_IonW";
372 Info.type = ArrayInfo::Double;
375 }
else if(idx==I++) {
376 Info.
name =
"ref_gamma";
378 Info.type = ArrayInfo::Double;
381 }
else if(idx==I++) {
382 Info.
name =
"ref_beta";
384 Info.type = ArrayInfo::Double;
387 }
else if(idx==I++) {
388 Info.
name =
"ref_bg";
390 Info.type = ArrayInfo::Double;
393 }
else if(idx==I++) {
394 Info.
name =
"ref_SampleIonK";
396 Info.type = ArrayInfo::Double;
399 }
else if(idx==I++) {
400 Info.
name =
"ref_phis";
402 Info.type = ArrayInfo::Double;
405 }
else if(idx==I++) {
406 Info.
name =
"ref_IonEk";
408 Info.type = ArrayInfo::Double;
411 }
else if(idx==I++) {
413 Info.
ptr = &real[0].IonZ;
414 Info.type = ArrayInfo::Double;
416 Info.
dim [0] = real.size();
417 Info.
stride[0] =
sizeof(real[0]);
420 }
else if(idx==I++) {
422 Info.
ptr = &real[0].IonEs;
423 Info.type = ArrayInfo::Double;
425 Info.
dim [0] = real.size();
426 Info.
stride[0] =
sizeof(real[0]);
428 }
else if(idx==I++) {
430 Info.
ptr = &real[0].IonW;
431 Info.type = ArrayInfo::Double;
433 Info.
dim [0] = real.size();
434 Info.
stride[0] =
sizeof(real[0]);
436 }
else if(idx==I++) {
438 Info.
ptr = &real[0].gamma;
439 Info.type = ArrayInfo::Double;
441 Info.
dim [0] = real.size();
442 Info.
stride[0] =
sizeof(real[0]);
444 }
else if(idx==I++) {
446 Info.
ptr = &real[0].beta;
447 Info.type = ArrayInfo::Double;
449 Info.
dim [0] = real.size();
450 Info.
stride[0] =
sizeof(real[0]);
452 }
else if(idx==I++) {
454 Info.
ptr = &real[0].bg;
455 Info.type = ArrayInfo::Double;
457 Info.
dim [0] = real.size();
458 Info.
stride[0] =
sizeof(real[0]);
460 }
else if(idx==I++) {
461 Info.
name =
"SampleIonK";
462 Info.
ptr = &real[0].SampleIonK;
463 Info.type = ArrayInfo::Double;
465 Info.
dim [0] = real.size();
466 Info.
stride[0] =
sizeof(real[0]);
468 }
else if(idx==I++) {
470 Info.
ptr = &real[0].phis;
471 Info.type = ArrayInfo::Double;
473 Info.
dim [0] = real.size();
474 Info.
stride[0] =
sizeof(real[0]);
476 }
else if(idx==I++) {
478 Info.
ptr = &real[0].IonEk;
479 Info.type = ArrayInfo::Double;
481 Info.
dim [0] = real.size();
482 Info.
stride[0] =
sizeof(real[0]);
484 }
else if(idx==I++) {
486 Info.
ptr = &real[0].IonQ;
487 Info.type = ArrayInfo::Double;
489 Info.
dim [0] = real.size();
490 Info.
stride[0] =
sizeof(real[0]);
497 MomentElementBase::MomentElementBase(
const Config& c)
499 ,dx (c.get<double>(
"dx", 0e0)*MtoMM)
500 ,dy (c.get<double>(
"dy", 0e0)*MtoMM)
501 ,pitch(c.get<double>(
"pitch", 0e0))
502 ,yaw (c.get<double>(
"yaw", 0e0))
503 ,roll (c.get<double>(
"roll", 0e0))
504 ,skipcache(c.get<double>(
"skipcache", 0.0)!=0.0)
509 MomentElementBase::~MomentElementBase() {}
514 last_real_in = O->last_real_in;
515 last_real_out= O->last_real_out;
516 last_ref_in = O->last_ref_in;
517 last_ref_out = O->last_ref_out;
519 misalign = O->misalign;
520 misalign_inv = O->misalign_inv;
532 using namespace boost::numeric::ublas;
541 void MomentElementBase::get_misalign(
const state_t &ST,
const Particle &real, value_t &M, value_t &IM)
const
544 scl = boost::numeric::ublas::identity_matrix<double>(state_t::maxsize),
550 scl(state_t::PS_S, state_t::PS_S) /= -real.
SampleIonK;
551 scl(state_t::PS_PS, state_t::PS_PS) /= sqr(real.
beta)*real.
gamma*ST.ref.
IonEs/MeVtoeV;
553 inverse(scl_inv, scl);
556 T(state_t::PS_S, 6) = -
length/2e0*MtoMM;
557 T(state_t::PS_PS, 6) = 1e0;
560 RotMat(
dx, dy, pitch, yaw, roll, R);
565 M = prod(scl_inv, M);
570 T(state_t::PS_S, 6) =
length/2e0*MtoMM;
571 T(state_t::PS_PS, 6) = 1e0;
575 IM = prod(R_inv, IM);
576 IM = prod(T_inv, IM);
577 IM = prod(scl_inv, IM);
583 using namespace boost::numeric::ublas;
592 last_ref_in = ST.ref;
593 last_real_in = ST.real;
600 for(
size_t k=0; k<last_real_in.size(); k++)
601 ST.real[k].phis += ST.real[k].SampleIonK*
length*MtoMM;
604 last_ref_out = ST.ref;
605 last_real_out = ST.real;
607 ST.ref = last_ref_out;
608 assert(last_real_out.size()==ST.real.size());
609 std::copy(last_real_out.begin(),
616 for(
size_t k=0; k<last_real_in.size(); k++) {
618 ST.moment0[k] = prod(
transfer[k], ST.moment0[k]);
620 scratch = prod(
transfer[k], ST.moment1[k]);
621 ST.moment1[k] = prod(scratch, trans(
transfer[k]));
630 && last_real_in.size()==ST.
size()
631 && last_ref_in==ST.ref
632 && std::equal(last_real_in.begin(),
639 transfer.resize(ST.real.size(), boost::numeric::ublas::identity_matrix<double>(state_t::maxsize));
640 misalign.resize(ST.real.size(), boost::numeric::ublas::identity_matrix<double>(state_t::maxsize));
641 misalign_inv.resize(ST.real.size(), boost::numeric::ublas::identity_matrix<double>(state_t::maxsize));
648 for(
size_t k=0; k<last_real_in.size(); k++) {
649 transfer[k] = boost::numeric::ublas::identity_matrix<double>(state_t::maxsize);
657 typedef ElementSource self_t;
659 typedef typename base_t::state_t
state_t;
661 ElementSource(
const Config& c): base_t(c), istate(c) {}
665 state_t& ST =
static_cast<state_t&
>(s);
670 virtual void show(std::ostream& strm,
int level)
const
673 strm<<
"Initial: "<<istate.moment0_env<<
"\n";
679 virtual ~ElementSource() {}
681 virtual const char*
type_name()
const {
return "source";}
684 base_t::assign(other);
685 const self_t* O=
static_cast<const self_t*
>(other);
693 typedef ElementMark self_t;
695 typedef typename base_t::state_t state_t;
698 virtual ~ElementMark() {}
699 virtual const char*
type_name()
const {
return "marker";}
707 typedef ElementBPM self_t;
709 typedef typename base_t::state_t state_t;
712 virtual ~ElementBPM() {}
713 virtual const char*
type_name()
const {
return "bpm";}
721 typedef ElementDrift self_t;
723 typedef typename base_t::state_t state_t;
725 ElementDrift(
const Config& c) : base_t(c) {}
726 virtual ~ElementDrift() {}
727 virtual const char*
type_name()
const {
return "drift";}
735 const double L =
length*MtoMM;
737 for(
size_t i=0; i<last_real_in.size(); i++) {
738 transfer[i] = boost::numeric::ublas::identity_matrix<double>(state_t::maxsize);
739 transfer[i](state_t::PS_X, state_t::PS_PX) = L;
740 transfer[i](state_t::PS_Y, state_t::PS_PY) = L;
741 transfer[i](state_t::PS_S, state_t::PS_PS) =
742 -2e0*M_PI/(SampleLambda*ST.real[i].IonEs/MeVtoeV*cube(ST.real[i].bg))*L;
750 typedef ElementOrbTrim self_t;
752 typedef typename base_t::state_t state_t;
754 ElementOrbTrim(
const Config& c) : base_t(c) {
length = 0e0;}
755 virtual ~ElementOrbTrim() {}
756 virtual const char*
type_name()
const {
return "orbtrim";}
763 double theta_x =
conf().
get<
double>(
"theta_x", 0e0),
764 theta_y =
conf().
get<
double>(
"theta_y", 0e0);
766 for(
size_t i=0; i<last_real_in.size(); i++) {
767 transfer[i] = boost::numeric::ublas::identity_matrix<double>(state_t::maxsize);
768 transfer[i](state_t::PS_PX, 6) = theta_x*ST.real[i].IonZ/ST.ref.
IonZ;
769 transfer[i](state_t::PS_PY, 6) = theta_y*ST.real[i].IonZ/ST.ref.
IonZ;
771 get_misalign(ST, ST.real[i], misalign[i], misalign_inv[i]);
773 noalias(scratch) = prod(
transfer[i], misalign[i]);
774 noalias(
transfer[i]) = prod(misalign_inv[i], scratch);
784 typedef ElementSBend self_t;
786 typedef typename base_t::state_t state_t;
788 unsigned HdipoleFitMode;
790 ElementSBend(
const Config& c) : base_t(c), HdipoleFitMode(0) {
792 std::istringstream strm(c.
get<std::string>(
"HdipoleFitMode",
"1"));
793 strm>>HdipoleFitMode;
794 if(!strm.eof() && strm.fail())
795 throw std::runtime_error(
"HdipoleFitMode must be an integer");
797 virtual ~ElementSBend() {}
798 virtual const char*
type_name()
const {
return "sbend";}
801 base_t::assign(other);
802 const self_t* O=
static_cast<const self_t*
>(other);
803 HdipoleFitMode = O->HdipoleFitMode;
808 state_t& ST =
static_cast<state_t&
>(s);
809 using namespace boost::numeric::ublas;
816 last_ref_in = ST.ref;
817 last_real_in = ST.real;
823 last_ref_out = ST.ref;
824 last_real_out = ST.real;
826 ST.ref = last_ref_out;
827 assert(last_real_out.size()==ST.real.size());
828 std::copy(last_real_out.begin(),
837 for(
size_t i=0; i<last_real_in.size(); i++) {
838 double phis_temp = ST.moment0[i][state_t::PS_S];
840 ST.moment0[i] = prod(
transfer[i], ST.moment0[i]);
842 noalias(scratch) = prod(
transfer[i], ST.moment1[i]);
843 noalias(ST.moment1[i]) = prod(scratch, trans(
transfer[i]));
845 double dphis_temp = ST.moment0[i][state_t::PS_S] - phis_temp;
847 if (HdipoleFitMode != 1) {
860 ST.real[i].phis += ST.real[i].SampleIonK*
length*MtoMM + dphis_temp;
862 ST.real[i].phis += ST.real[i].SampleIonK*
length*MtoMM + dphis_temp;
872 double L =
conf().
get<
double>(
"L")*MtoMM,
873 phi =
conf().
get<
double>(
"phi")*M_PI/180e0,
874 phi1 =
conf().
get<
double>(
"phi1")*M_PI/180e0,
875 phi2 =
conf().
get<
double>(
"phi2")*M_PI/180e0,
876 K =
conf().
get<
double>(
"K", 0e0)/sqr(MtoMM);
878 for(
size_t i=0; i<last_real_in.size(); i++) {
879 double qmrel = (ST.real[i].IonZ-ST.ref.
IonZ)/ST.ref.
IonZ;
881 transfer[i] = boost::numeric::ublas::identity_matrix<double>(state_t::maxsize);
883 if (HdipoleFitMode != 1) {
884 double dip_bg =
conf().
get<
double>(
"bg"),
886 dip_Ek = (sqrt(sqr(dip_bg)+1e0)-1e0)*ST.ref.
IonEs,
887 dip_gamma = (dip_Ek+ST.ref.
IonEs)/ST.ref.
IonEs,
888 dip_beta = sqrt(1e0-1e0/sqr(dip_gamma)),
889 d = (ST.ref.
gamma-dip_gamma)/(sqr(dip_beta)*dip_gamma) - qmrel,
890 dip_IonK = 2e0*M_PI/(dip_beta*SampleLambda);
892 GetSBendMatrix(L, phi, phi1, phi2, K, ST.ref.
IonEs, ST.ref.
gamma, qmrel,
893 dip_beta, dip_gamma, d, dip_IonK,
transfer[i]);
895 GetSBendMatrix(L, phi, phi1, phi2, K, ST.ref.
IonEs, ST.ref.
gamma, qmrel,
898 get_misalign(ST, ST.real[i], misalign[i], misalign_inv[i]);
900 noalias(scratch) = prod(
transfer[i], misalign[i]);
901 noalias(
transfer[i]) = prod(misalign_inv[i], scratch);
909 typedef ElementQuad self_t;
911 typedef typename base_t::state_t state_t;
913 ElementQuad(
const Config& c) : base_t(c) {}
914 virtual ~ElementQuad() {}
915 virtual const char*
type_name()
const {
return "quadrupole";}
921 const double B2=
conf().
get<
double>(
"B2"),
922 L =
conf().
get<
double>(
"L")*MtoMM;
924 for(
size_t i=0; i<last_real_in.size(); i++) {
926 transfer[i] = boost::numeric::ublas::identity_matrix<double>(state_t::maxsize);
928 double Brho = ST.real[i].beta*(ST.real[i].IonEk+ST.real[i].IonEs)/(C0*ST.real[i].IonZ),
929 K = B2/Brho/sqr(MtoMM);
932 GetQuadMatrix(L, K, (
unsigned)state_t::PS_X,
transfer[i]);
934 GetQuadMatrix(L, -K, (
unsigned)state_t::PS_Y,
transfer[i]);
938 transfer[i](state_t::PS_S, state_t::PS_PS) =
939 -2e0*M_PI/(SampleLambda*ST.real[i].IonEs/MeVtoeV*cube(ST.real[i].bg))*L;
941 get_misalign(ST, ST.real[i], misalign[i], misalign_inv[i]);
943 noalias(scratch) = prod(
transfer[i], misalign[i]);
944 noalias(
transfer[i]) = prod(misalign_inv[i], scratch);
952 typedef ElementSolenoid self_t;
954 typedef typename base_t::state_t state_t;
956 ElementSolenoid(
const Config& c) : base_t(c) {}
957 virtual ~ElementSolenoid() {}
958 virtual const char*
type_name()
const {
return "solenoid";}
964 const double B =
conf().
get<
double>(
"B"),
965 L =
conf().
get<
double>(
"L")*MtoMM;
967 for(
size_t i=0; i<last_real_in.size(); i++) {
969 transfer[i] = boost::numeric::ublas::identity_matrix<double>(state_t::maxsize);
971 double Brho = ST.real[i].beta*(ST.real[i].IonEk+ST.real[i].IonEs)/(C0*ST.real[i].IonZ),
972 K = B/(2e0*Brho)/MtoMM;
976 transfer[i](state_t::PS_S, state_t::PS_PS) =
977 -2e0*M_PI/(SampleLambda*ST.real[i].IonEs/MeVtoeV*cube(ST.real[i].bg))*L;
979 get_misalign(ST, ST.real[i], misalign[i], misalign_inv[i]);
981 noalias(scratch) = prod(
transfer[i], misalign[i]);
982 noalias(
transfer[i]) = prod(misalign_inv[i], scratch);
990 typedef ElementEDipole self_t;
992 typedef typename base_t::state_t state_t;
994 ElementEDipole(
const Config& c) : base_t(c) {}
995 virtual ~ElementEDipole() {}
996 virtual const char*
type_name()
const {
return "edipole";}
1006 bool ver =
conf().
get<
double>(
"ver") == 1.0;
1007 double L =
conf().
get<
double>(
"L")*MtoMM,
1008 phi =
conf().
get<
double>(
"phi")*M_PI/180e0,
1010 fringe_x =
conf().
get<
double>(
"fringe_x", 0e0)/MtoMM,
1011 fringe_y =
conf().
get<
double>(
"fringe_y", 0e0)/MtoMM,
1012 kappa =
conf().
get<
double>(
"asym_fac", 0e0),
1014 spher =
conf().
get<
double>(
"spher"),
1018 Ky = spher/sqr(rho),
1019 dip_beta =
conf().
get<
double>(
"beta"),
1020 dip_gamma = 1e0/sqrt(1e0-sqr(dip_beta));
1022 for(
size_t i=0; i<last_real_in.size(); i++) {
1023 double eta0 = (ST.real[i].gamma-1e0)/2e0,
1024 Kx = (1e0-spher+sqr(1e0+2e0*eta0))/sqr(rho),
1025 delta_KZ = ST.real[i].IonZ/ST.ref.
IonZ - 1e0,
1026 SampleIonK = 2e0*M_PI/(ST.real[i].beta*SampleLambda);
1028 transfer[i] = boost::numeric::ublas::identity_matrix<double>(state_t::maxsize);
1030 GetEBendMatrix(L, phi, fringe_x, fringe_y, kappa, Kx, Ky, ST.ref.
IonEs, ST.ref.
beta, ST.real[i].gamma,
1031 eta0, h, dip_beta, dip_gamma, delta_KZ, SampleIonK,
transfer[i]);
1036 R = boost::numeric::ublas::identity_matrix<double>(state_t::maxsize);
1037 R(state_t::PS_X, state_t::PS_X) = 0e0;
1038 R(state_t::PS_PX, state_t::PS_PX) = 0e0;
1039 R(state_t::PS_Y, state_t::PS_Y) = 0e0;
1040 R(state_t::PS_PY, state_t::PS_PY) = 0e0;
1041 R(state_t::PS_X, state_t::PS_Y) = -1e0;
1042 R(state_t::PS_PX, state_t::PS_PY) = -1e0;
1043 R(state_t::PS_Y, state_t::PS_X) = 1e0;
1044 R(state_t::PS_PY, state_t::PS_PX) = 1e0;
1046 noalias(scratch) = prod(R,
transfer[i]);
1047 noalias(
transfer[i]) = prod(scratch, trans(R));
1051 get_misalign(ST, ST.real[i], misalign[i], misalign_inv[i]);
1053 noalias(scratch) = prod(
transfer[i], misalign[i]);
1054 noalias(
transfer[i]) = prod(misalign_inv[i], scratch);
1062 typedef ElementEQuad self_t;
1064 typedef typename base_t::state_t state_t;
1066 ElementEQuad(
const Config& c) : base_t(c) {}
1067 virtual ~ElementEQuad() {}
1068 virtual const char*
type_name()
const {
return "equad";}
1074 const double V0 =
conf().
get<
double>(
"V"),
1075 R =
conf().
get<
double>(
"radius"),
1076 L =
conf().
get<
double>(
"L")*MtoMM;
1078 for(
size_t i=0; i<last_real_in.size(); i++) {
1081 transfer[i] = boost::numeric::ublas::identity_matrix<double>(state_t::maxsize);
1083 double Brho = ST.real[i].beta*(ST.real[i].IonEk+ST.real[i].IonEs)/(C0*ST.real[i].IonZ),
1084 K = 2e0*V0/(C0*ST.real[i].beta*sqr(R))/Brho/sqr(MtoMM);
1087 GetQuadMatrix(L, K, (
unsigned)state_t::PS_X,
transfer[i]);
1089 GetQuadMatrix(L, -K, (
unsigned)state_t::PS_Y,
transfer[i]);
1093 transfer[i](state_t::PS_S, state_t::PS_PS) =
1094 -2e0*M_PI/(SampleLambda*ST.real[i].IonEs/MeVtoeV*cube(ST.real[i].bg))*L;
1096 get_misalign(ST, ST.real[i], misalign[i], misalign_inv[i]);
1098 noalias(scratch) = prod(
transfer[i], misalign[i]);
1099 noalias(
transfer[i]) = prod(misalign_inv[i], scratch);
1106 void registerMoment()
1108 Machine::registerState<MomentState>(
"MomentMatrix");
1110 Machine::registerElement<ElementSource >(
"MomentMatrix",
"source");
1112 Machine::registerElement<ElementMark >(
"MomentMatrix",
"marker");
1114 Machine::registerElement<ElementBPM >(
"MomentMatrix",
"bpm");
1116 Machine::registerElement<ElementDrift >(
"MomentMatrix",
"drift");
1118 Machine::registerElement<ElementOrbTrim >(
"MomentMatrix",
"orbtrim");
1120 Machine::registerElement<ElementSBend >(
"MomentMatrix",
"sbend");
1122 Machine::registerElement<ElementQuad >(
"MomentMatrix",
"quadrupole");
1124 Machine::registerElement<ElementSolenoid >(
"MomentMatrix",
"solenoid");
1126 Machine::registerElement<ElementRFCavity >(
"MomentMatrix",
"rfcavity");
1128 Machine::registerElement<ElementStripper >(
"MomentMatrix",
"stripper");
1130 Machine::registerElement<ElementEDipole >(
"MomentMatrix",
"edipole");
1132 Machine::registerElement<ElementEQuad >(
"MomentMatrix",
"equad");
double gamma
Gamma for ion. (dependent)
virtual bool check_cache(const state_t &S) const
virtual bool getArray(unsigned idx, ArrayInfo &Info)
Introspect named parameter of the derived class.
Base class for all simulated elements.
double length
Longitudual length of this element (added to StateBase::pos)
double IonW
Total energy. (dependent)
double IonEk
Kinetic energy.
virtual void show(std::ostream &strm, int level) const
virtual const char * type_name() const =0
The abstract base class for all simulation state objects.
virtual void advance(StateBase &s)
Propogate the given State through this Element.
double phis
Absolute synchrotron phase [rad].
virtual void assign(const ElementVoid *other)=0
Associative configuration container.
virtual void recompute_matrix(state_t &ST)
recalculate 'transfer' taking into consideration the provided input state
Used with StateBase::getArray() to describe a single parameter.
virtual void assign(const StateBase &other)=0
double pos
absolute longitudinal position at end of Element
virtual void assign(const ElementVoid *other)=0
virtual void assign(const StateBase &other)
size_t dim[maxdims]
Array dimensions in elements.
const Config & conf() const
The Config used to construct this element.
double dx
constituents of misalign
bool skipcache
If set, check_cache() will always return false.
size_t size() const
of charge states
size_t stride[maxdims]
Array strides in bytes.
std::vector< value_t > transfer
final transfer matricies
double beta
Beta for ion. (dependent)
double bg
Beta*gamma. (dependent)
virtual void show(std::ostream &strm, int level) const
bool tryGet(const std::string &name, T &val) const
virtual bool getArray(unsigned index, ArrayInfo &Info)
Introspect named parameter of the derived class.
detail::RT< T >::type get(const std::string &name) const
double SampleIonK
Sample rate; different RF Cavity due to RF frequenies. (dependent)
virtual void show(std::ostream &, int level) const
void resize_cache(const state_t &ST)
const char * name
The parameter name.
An Element which propagates the statistical moments of a bunch.