49 #include <boost/filesystem.hpp>
51 #include <boost/numeric/odeint/stepper/runge_kutta4.hpp>
64 unsigned int Nsectors,
65 unsigned int truncOrder,
68 , wo_m(cycl->getRfFrequ(0)*1E6/cycl->getCyclHarm()*2.0*
Physics::
pi)
71 , gamma2_m(gamma_m*gamma_m)
72 , nh_m(cycl->getCyclHarm())
73 , beta_m(
std::
sqrt(1.0-1.0/gamma2_m))
78 , Emin_m(cycl->getFMLowE())
79 , Emax_m(cycl->getFMHighE())
81 , nSectors_m(Nsectors)
82 , nStepsPerSector_m(N/cycl->getSymmetry())
84 , error_m(
std::numeric_limits<double>::
max())
85 , truncOrder_m(truncOrder)
87 , sigmas_m(nStepsPerSector_m)
112 H_m = [&](
double h,
double kx,
double ky) {
118 Hsc_m = [&](
double sigx,
double sigy,
double sigz) {
120 double m =
m_m * 1.0e6;
140 double tmp = sx * sy;
143 double kxy = K3 *
std::abs(1.0 - f) / ((sx + sy) * sz);
145 double Kx = kxy / sx;
146 double Ky = kxy / sy;
147 double Kz = K3 * f / (tmp * sz);
149 return -0.5 * Kx *
x_m *
x_m
158 unsigned int maxitOrbit,
187 boost::numeric::odeint::runge_kutta4<container_t> > cof(
m_m,
q_m,
N_m, cycl,
false,
nSectors_m);
189 if ( !cof.findOrbit(accuracy, maxitOrbit,
E_m, denergy, rguess) ) {
191 "Closed orbit finder didn't converge.");
194 cof.computeOrbitProperties(
E_m);
197 container_t h = cof.getInverseBendingRadius(angle);
213 if (!boost::filesystem::exists(fpath)) {
214 boost::filesystem::create_directory(fpath);
217 std::pair<double,double> tunes = cof.getTunes();
218 double ravg = cof.getAverageRadius();
221 *
gmsg <<
"* ----------------------------" <<
endl
222 <<
"* Closed orbit info:" <<
endl
224 <<
"* average radius: " << ravg <<
" [m]" <<
endl
225 <<
"* initial radius: " << r[0] <<
" [m]" <<
endl
226 <<
"* initial momentum: " << peo[0] <<
" [Beta Gamma]" <<
endl
227 <<
"* frequency error: " << cof.getFrequencyError()*100 <<
" [ % ] "<<
endl
228 <<
"* horizontal tune: " << tunes.first <<
endl
229 <<
"* vertical tune: " << tunes.second <<
endl
230 <<
"* ----------------------------" <<
endl <<
endl;
236 std::ofstream writeMturn, writeMcyc, writeMsc;
245 "OneTurnMapsForEnergy" + energy +
"MeV.dat"
248 writeMturn.open(fname, std::ios::out);
253 "SpaceChargeMapPerAngleForEnergy" + energy +
"MeV_iteration_0.dat"
256 writeMsc.open(fname, std::ios::out);
261 "CyclotronMapPerAngleForEnergy" + energy +
"MeV.dat"
264 writeMcyc.open(fname, std::ios::out);
268 for (
unsigned int i = 0; i <
nSteps_m; ++i) {
269 Mcycs[i] = mapgen.generateMap(
H_m(h[i],
288 mapgen.combine(Mscs,Mcycs);
304 while (
error_m > accuracy && !stop) {
327 "SpaceChargeMapPerAngleForEnergy" + energy +
"MeV_iteration_"
332 writeMsc.open(fname, std::ios::out);
336 for (
unsigned int i = 0; i <
nSteps_m; ++i) {
350 mapgen.combine(Mscs,Mcycs);
351 Mturn = mapgen.getMap();
372 }
catch(
const std::exception&
e) {
380 "MatchedDistributions.dat"
383 std::ofstream writeSigmaMatched(fname, std::ios::out);
387 writeSigmaMatched <<
"* Converged (Ex, Ey, Ez) = (" << emit[0]
388 <<
", " << emit[1] <<
", " << emit[2]
389 <<
") pi mm mrad for E= " <<
E_m <<
" (MeV)"
392 for(
unsigned int i = 0; i <
sigma_m.size1(); ++ i) {
393 writeSigmaMatched << std::setprecision(4) << std::setw(11)
395 for(
unsigned int j = 1; j <
sigma_m.size2(); ++ j) {
396 writeSigmaMatched <<
" & " << std::setprecision(4)
397 << std::setw(11) <<
sigma_m(i,j);
399 writeSigmaMatched <<
" \\\\" <<
std::endl;
403 writeSigmaMatched.close();
440 eigen(1) = - Ms(1,0);
442 eigen(3) = - Ms(3,2);
451 matrix_t newSigma = matt_boost::gemmm<matrix_t>(Mturn,
453 boost::numeric::ublas::trans(Mturn));
493 double m =
m_m * 1.0e6;
501 double e = std::cbrt(ex * ey * ez);
504 double rcyc = ravg /
beta_m;
507 double h = 1.0 / ravg;
527 sig = sig0 * std::cbrt(1.0 +
alpha);
528 }
else if (
alpha >= 0) {
529 sig = sig0 * (1 +
alpha * (0.25 - 0.03125 *
alpha));
532 "Negative alpha value: " + std::to_string(
alpha) +
" < 0");
536 double K = K3 *
gamma_m / (3.0 * sig * sig * sig);
539 double a = 0.5 * kx - K;
546 "Negative value --> No real-valued frequency.");
548 double tmp =
a *
a - b;
551 "Square root of negative number.");
557 "Square root of negative number.");
559 if (h * h * nuz * nuz <= K)
561 "h^{2} * nu_{z}^{2} <= K (i.e. square root of negative number)");
566 double A = h / (Omega * Omega + K);
567 double B = h / (omega * omega + K);
568 double invAB = 1.0 / (B - A);
571 matrix_t sigma = boost::numeric::ublas::zero_matrix<double>(6);
574 sigma(0,0) = invAB * (B * ex / Omega + A * ez / omega);
577 sigma(0,5) = sigma(5,0) = invAB * (ex / Omega + ez / omega);
580 sigma(1,1) = invAB * (B * ex * Omega + A * ez * omega);
583 sigma(1,4) = sigma(4,1) = invAB * (ex * Omega+ez * omega) / (K *
gamma2_m);
586 sigma(2,2) = ey / (
std::sqrt(h * h * nuz * nuz - K));
588 sigma(3,3) = (ey * ey) / sigma(2,2);
591 sigma(4,4) = invAB * (A * ex * Omega + B * ez * omega) / (K *
gamma2_m);
594 sigma(5,5) = invAB * (ex / (B * Omega) + ez / (A * omega));
608 "InitialSigmaPerAngleForEnergy" + energy +
"MeV.dat"
611 std::ofstream writeInit(fname, std::ios::out);
678 double gammax = 1.0 / betax;
683 double gammal = 1.0 / betal;
705 double cosz = 0.5 * (M(2,2) + M(3,3));
707 double sign = (std::signbit(M(2,3))) ?
double(-1) : double(1);
711 double alphaz = 0.5 * (M(2,2) - M(3,3)) * invsinz;
712 double betaz = M(2,3) * invsinz;
713 double gammaz = - M(3,2) * invsinz;
716 if (std::signbit(betaz))
720 matrix_t D = boost::numeric::ublas::zero_matrix<double>(6,6);
723 D(1,0) = - gammax * ex;
725 D(2,2) = alphaz * ey;
726 D(3,3) = - alphaz * ey;
728 D(3,2) = - gammaz * ey;
731 D(5,4) = - gammal * ez;
734 expand<sparse_matrix_t>(
R);
735 expand<sparse_matrix_t>(invR);
739 S(0,1) = S(2,3) = S(4,5) = 1;
740 S(1,0) = S(3,2) = S(5,4) = -1;
742 matrix_t sigma = matt_boost::gemmm<matrix_t>(-invR,D,
R);
751 "InitialSigmaPerAngleForEnergy" + energy +
"MeV.dat"
754 std::ofstream writeInit(fname, std::ios::app);
764 const std::vector<matrix_t>& Mcycs)
766 std::ofstream writeSigma;
774 "SigmaPerAngleForEnergy" + energy +
"MeV_iteration_"
779 writeSigma.open(fname,std::ios::out);
785 for (
unsigned int i = 1; i <
nSteps_m; ++i) {
790 boost::numeric::ublas::trans(M));
808 return std::sqrt(std::inner_product(diff.data().begin(),
816 std::ostringstream out;
817 out << std::setprecision(6) << val;
835 "PropertiesForEnergy" + energy +
"MeV.dat"
838 std::ofstream writeProperties(fname, std::ios::out);
840 writeProperties << std::left
841 << std::setw(25) <<
"orbit radius"
842 << std::setw(25) <<
"orbit momentum"
843 << std::setw(25) <<
"inverse bending radius"
844 << std::setw(25) <<
"field index"
845 << std::setw(25) <<
"path length" <<
std::endl;
847 for (
unsigned int i = 0; i < r.size(); ++i) {
848 writeProperties << std::setprecision(10) << std::left
849 << std::setw(25) << r[i]
850 << std::setw(25) << peo[i]
851 << std::setw(25) << h[i]
852 << std::setw(25) << fidx[i]
855 writeProperties.close();
863 for (
unsigned int i = 0; i < 6; ++i) {
864 for (
unsigned int j = 0; j < 6; ++j)
865 os << m(i, j) <<
" ";
Tps< T > sqrt(const Tps< T > &x)
Square root.
T::PETE_Expr_t::PETE_Return_t max(const PETE_Expr< T > &expr, NDIndex< D > &loc)
PETE_TUTree< FnAbs, typename T::PETE_Expr_t > abs(const PETE_Expr< T > &l)
T::PETE_Expr_t::PETE_Return_t prod(const PETE_Expr< T > &expr)
PETE_TUTree< FnFabs, typename T::PETE_Expr_t > fabs(const PETE_Expr< T > &l)
Inform & endl(Inform &inf)
constexpr double two_pi
The value of.
constexpr double epsilon_0
The permittivity of vacuum in As/Vm.
constexpr double alpha
The fine structure constant, no dimension.
constexpr double e
The value of.
constexpr double mu_0
The permeability of vacuum in Vs/Am.
constexpr double c
The velocity of light in m/s.
constexpr double pi
The value of.
std::string::iterator iterator
std::string combineFilePath(std::initializer_list< std::string > ilist)
double getBetaGamma(double Ekin, double mass)
static OpalData * getInstance()
std::string getAuxiliaryOutputDirectory() const
get the name of the the additional data directory
virtual double getPHIinit() const
static FTps makeVariable(int var)
Make variable.
static void setGlobalTruncOrder(int order)
Set the global truncation order.
This class generates the matrices for the one turn matrix of a cyclotron.
matrix_t symplex(const matrix_t &)
void diagonalize(matrix_t &, sparse_matrix_t &, sparse_matrix_t &)
unsigned int niterations_m
Is the number of iterations needed for convergence.
double E_m
Stores the user-define energy, .
bool write_m
Decides for writing output (default: true)
void writeMatrix(std::ofstream &, const matrix_t &)
double isEigenEllipse(const matrix_t &Mturn, const matrix_t &sigma)
Checks if the sigma-matrix is an eigenellipse and returns the L2 error.
std::vector< double > container_t
Container for storing the properties for each angle.
std::array< double, 3 > getEmittances() const
double gamma2_m
Relativistic factor squared.
FTps< double, 2 *3 > Series
Type of the truncated power series.
Hamiltonian H_m
Stores the Hamiltonian of the cyclotron.
double m_m
Is the mass of the particles, .
double error_m
Error of computation.
matrix_t updateInitialSigma(const matrix_t &, const vector_t &, sparse_matrix_t &, sparse_matrix_t &)
Computes the new initial sigma matrix.
unsigned int nSteps_m
Number of integration steps in total.
RealDiracMatrix::sparse_matrix_t sparse_matrix_t
Type for storing the sparse maps.
unsigned int nSectors_m
Number of (symmetric) sectors the field is averaged over.
unsigned int nStepsPerSector_m
Number of integration steps per sector (--> also: number of maps per sector)
double I_m
Stores the value of the current, .
std::function< Series(double, double, double)> SpaceCharge
Type of the Hamiltonian for the space charge.
double Emin_m
Minimum energy needed in cyclotron, .
unsigned int truncOrder_m
Truncation order of the power series for the Hamiltonian (cyclotron and space charge)
SigmaGenerator(double I, double ex, double ey, double ez, double E, double m, double q, const Cyclotron *cycl, unsigned int N, unsigned int Nsectors, unsigned int truncOrder, bool write=true)
Constructs an object of type SigmaGenerator.
double L2ErrorNorm(const matrix_t &, const matrix_t &)
Returns the L2-error norm between the old and new sigma-matrix.
RealDiracMatrix rdm_m
RealDiracMatrix-class member used for decoupling
FVps< double, 2 *3 > Map
Type of a map.
Series x_m
All variables x, px, z, pz, l, delta.
SpaceCharge Hsc_m
Stores the Hamiltonian for the space charge.
double q_m
Is the particle charge [e].
RealDiracMatrix::matrix_t matrix_t
Type for storing maps.
std::vector< matrix_t > sigmas_m
Vector storing the second moment matrix for each angle.
matrix_t sigma_m
Stores the stationary distribution (sigma matrix)
double nh_m
Harmonic number, .
vector_t decouple(const matrix_t &Mturn, sparse_matrix_t &R, sparse_matrix_t &invR)
Block diagonalizes the symplex part of the one turn transfer matrix.
double wo_m
Is the orbital frequency, .
std::function< Series(double, double, double)> Hamiltonian
Type of the Hamiltonian for the cyclotron.
unsigned int N_m
Number of integration steps for closed orbit computation.
void initialize(double, double)
bool converged_m
Is true if converged, false otherwise.
void writeOrbitOutput_m(const container_t &r_turn, const container_t &peo, const container_t &h_turn, const container_t &fidx_turn, const container_t &ds_turn)
Called within SigmaGenerator::match().
void updateSigma(const std::vector< matrix_t > &, const std::vector< matrix_t > &)
Computes new sigma matrices (one for each angle)
std::string float2string(double val)
Transforms a floating point value to a string.
RealDiracMatrix::vector_t vector_t
Type for storing vectors.
double beta_m
Velocity (c/v), .
std::array< double, 3 > emittance_m
bool match(double accuracy, unsigned int maxit, unsigned int maxitOrbit, Cyclotron *cycl, double denergy, double rguess, bool full)
Searches for a matched distribution.
The base class for all OPAL exceptions.