FLAME  devel
 All Classes Functions Variables Typedefs Enumerations Pages
chg_stripper.cpp
1 #include "flame/constants.h"
2 #include "flame/moment.h"
3 #include "flame/moment_sup.h"
4 #include "flame/chg_stripper.h"
5 
6 #define sqr(x) ((x)*(x))
7 #define cube(x) ((x)*(x)*(x))
8 
9 static
10 double Gaussian(double in, const double Q_ave, const double d)
11 {
12  // Gaussian distribution.
13  return 1e0/sqrt(2e0*M_PI)/d*exp(-0.5e0*sqr(in-Q_ave)/sqr(d));
14 }
15 
16 
17 void ElementStripper::StripperCharge(const double beta, double &Q_ave, double &d)
18 {
19  // Baron's formula for carbon foil.
20  double Q_ave1, Y;
21 
22  Q_ave1 = Stripper_IonProton*(1e0-exp(-83.275*(beta/pow(Stripper_IonProton, 0.447))));
23  Q_ave = Q_ave1*(1e0-exp(-12.905+0.2124*Stripper_IonProton-0.00122*sqr(Stripper_IonProton)));
24  Y = Q_ave1/Stripper_IonProton;
25  d = sqrt(Q_ave1*(0.07535+0.19*Y-0.2654*sqr(Y)));
26 }
27 
28 
29 void ElementStripper::ChargeStripper(const double beta, const std::vector<double>& ChgState, std::vector<double>& chargeAmount_Baron)
30 {
31  unsigned k;
32  double Q_ave, d;
33 
34  StripperCharge(beta, Q_ave, d);
35  for (k = 0; k < ChgState.size(); k++)
36  chargeAmount_Baron.push_back(Gaussian(ChgState[k]*Stripper_IonMass, Q_ave, d));
37 }
38 
39 
40 void ElementStripper::Stripper_Propagate_ref(Particle &ref)
41 {
42 
43  // Change reference particle charge state.
44  ref.IonZ = Stripper_IonZ;
45 
46 // ChargeStripper(ref.beta, ChgState, chargeAmount_Baron);
47 
48  // Evaluate change in reference particle energy due to stripper model energy straggling.
49  ref.IonEk = (ref.IonEk-Stripper_Para[2])*Stripper_E0Para[1] + Stripper_E0Para[0];
50 
51  ref.recalc();
52 }
53 
54 void ElementStripper::Stripper_GetMat(const Config &conf,
55  MomentState &ST)
56 {
57  unsigned k, n;
58  double tmptotCharge, Fy_abs_recomb, Ek_recomb, stdEkFoilVariation, ZpAfStr, growthRate;
59  double stdXYp, XpAfStr, growthRateXp, YpAfStr, growthRateYp, s;
60  Particle ref;
61  state_t *StatePtr = &ST;
62  MomentState::matrix_t tmpmat;
63  std::vector<double> chargeAmount_Set;
64 
65  //std::cout<<"In "<<__FUNCTION__<<"\n";
66 
67  // Get new charge states and stripper parameters.
68  const std::vector<double>& ChgState = conf.get<std::vector<double> >("IonChargeStates");
69  const std::vector<double>& NChg = conf.get<std::vector<double> >("NCharge");
70  const std::string chrgmdl = conf.get<std::string>("charge_model", "baron");
71 
72  if(chrgmdl=="off" && ChgState.size()!=NChg.size())
73  throw std::runtime_error("charge stripper requires that IonChargeStates[] and NCharge[] have the same length");
74  if(chrgmdl!="off" && chrgmdl!="baron")
75  throw std::runtime_error("charge_model key word unknown, only \"baron\" and \"off\" supported by now");
76 
77  Stripper_IonZ = conf.get<double>("Stripper_IonZ", Stripper_IonZ_default);
78  Stripper_IonMass = conf.get<double>("Stripper_IonMass", Stripper_IonMass_default);
79  Stripper_IonProton = conf.get<double>("Stripper_IonProton", Stripper_IonProton_default);
80  Stripper_E1Para = conf.get<double>("Stripper_E1Para", Stripper_E1Para_default);
81  Stripper_lambda = conf.get<double>("Stripper_lambda", Stripper_lambda_default);
82  Stripper_upara = conf.get<double>("Stripper_upara", Stripper_upara_default);
83 
84  const std::vector<double> p1_default(Stripper_Para_default, Stripper_Para_default+3),
85  p2_default(Stripper_E0Para_default, Stripper_E0Para_default+3);
86 
87  Stripper_Para = conf.get<std::vector<double> >("Stripper_Para", p1_default);
88  Stripper_E0Para = conf.get<std::vector<double> >("Stripper_E0Para", p2_default);
89 
90  n = ChgState.size();
91 
92  if(chrgmdl=="off" )
93  if (ChgState.size()!=NChg.size())
94  throw std::runtime_error("charge stripper requires that IonChargeStates[] and NCharge[] have the same length");
95  else{
96  for (k = 0; k < n; k++) chargeAmount_Set.push_back(NChg[k]);
97  }
98  else
99  ChargeStripper(StatePtr->real[0].beta, ChgState, chargeAmount_Set);
100 
101 
102  // Evaluate beam parameter recombination.
103 
104  tmptotCharge = 0e0;
105  Fy_abs_recomb = 0e0;
106  Ek_recomb = 0e0;
107  tmpmat = boost::numeric::ublas::zero_matrix<double>(PS_Dim);
108  for (k = 0; k < ST.size(); k++) {
109  const double Q = ST.real[k].IonQ;
110  tmptotCharge += Q;
111  Fy_abs_recomb += Q*StatePtr->real[k].phis;
112  Ek_recomb += Q*StatePtr->real[k].IonEk;
113  tmpmat +=
114  Q*(StatePtr->moment1[k]+outer_prod(StatePtr->moment0[k]-ST.moment0_env, StatePtr->moment0[k]-ST.moment0_env));
115  }
116 
117  Fy_abs_recomb /= tmptotCharge;
118  Ek_recomb /= tmptotCharge;
119 
120  // Stripper model energy straggling.
121  Ek_recomb = (Ek_recomb-Stripper_Para[2])*Stripper_E0Para[1] + Stripper_E0Para[0];
122  tmpmat /= tmptotCharge;
123 
124  // Estimate Zp stripper caused envelope increase.
125  stdEkFoilVariation = sqrt(1e0/3e0)*Stripper_Para[1]/100e0*Stripper_Para[0]*Stripper_E0Para[2];
126  ZpAfStr = tmpmat(5, 5) + sqr(Stripper_E1Para) + sqr(stdEkFoilVariation);
127  if (tmpmat(5, 5) != 0e0) {
128  growthRate = sqrt(ZpAfStr/tmpmat(5, 5));
129  } else {
130  growthRate = 1e0;
131  }
132 
133  for (k = 0; k < 6; k++) {
134  tmpmat(k, 5) = tmpmat(k, 5)*growthRate;
135  // This trick allows two times growthRate for <Zp, Zp>.
136  tmpmat(5, k) = tmpmat(5, k)*growthRate;
137  }
138 
139  // Estimate Xp, Yp stripper caused envelope increase.
140  stdXYp = sqrt(Stripper_upara/sqr(Stripper_lambda))*1e-3;// mrad to rad
141  XpAfStr = tmpmat(1, 1) + sqr(stdXYp);
142  growthRateXp = sqrt(XpAfStr/tmpmat(1, 1));
143  YpAfStr = tmpmat(3, 3) + sqr(stdXYp);
144  growthRateYp = sqrt(YpAfStr/tmpmat(3, 3));
145 
146  for (k = 0; k < 6; k++) {
147  tmpmat(k, 1) = tmpmat(k, 1)*growthRateXp;
148  // This trick allows two times growthRate for <Zp, Zp>.
149  tmpmat(1, k) = tmpmat(1, k)*growthRateXp;
150  tmpmat(k, 3) = tmpmat(k, 3)*growthRateYp;
151  tmpmat(3, k) = tmpmat(3, k)*growthRateYp;
152  }
153 
154  // Get new charge states.
155 
156 
157  // Propagate reference particle.
158  ref = ST.ref;
159  Stripper_Propagate_ref(ref);
160 
161  s = StatePtr->pos;
162 
163  ST.real.resize(n);
164  ST.moment0.resize(n);
165  ST.moment1.resize(n);
166  ST.transmat.resize(n);
167 
168  // Length is zero.
169  StatePtr->pos = s;
170 
171  StatePtr->ref = ref;
172 
173 
174  for (k = 0; k < n; k++) {
175  StatePtr->real[k].IonZ = ChgState[k];
176  StatePtr->real[k].IonQ = chargeAmount_Set[k];
177  StatePtr->real[k].SampleFreq = ref.SampleFreq;
178  StatePtr->real[k].IonEs = ref.IonEs;
179  StatePtr->real[k].IonEk = Ek_recomb;
180  StatePtr->real[k].recalc();
181  StatePtr->real[k].phis = Fy_abs_recomb;
182  StatePtr->moment0[k] = ST.moment0_env;
183  StatePtr->moment1[k] = tmpmat;
184  StatePtr->transmat[k] = boost::numeric::ublas::identity_matrix<double>(PS_Dim);
185  }
186 
187  ST.calc_rms();
188 }
189 
190 void ElementStripper::advance(StateBase &s)
191 {
192  state_t& ST = static_cast<state_t&>(s);
193 
194  ST.recalc();
195  ST.calc_rms(); // paranoia in case someone (python) has made moment0_env inconsistent
196 
197  if(ST.retreat) throw std::runtime_error(SB()<<
198  "Backward propagation error: Backward propagation does not support charge stripper.");
199 
200 
201  Stripper_GetMat(conf(), ST);
202 }
bool retreat
retreat (backward) simulation flag
Definition: base.h:39
double IonEk
Kinetic energy.
Definition: moment.h:22
double IonZ
Charge state.
Definition: moment.h:22
The abstract base class for all simulation state objects.
Definition: base.h:29
double IonEs
Rest energy.
Definition: moment.h:22
void recalc()
Definition: moment.h:47
double SampleFreq
Sampling frequency [Hz].
Definition: moment.h:22
Associative configuration container.
Definition: config.h:66
double pos
absolute longitudinal position at end of Element
Definition: base.h:37
size_t size() const
of charge states
Definition: moment.h:138
detail::RT< T >::type get(const std::string &name) const
Definition: config.h:123