49#include <boost/filesystem.hpp>
51#include <boost/numeric/odeint/stepper/runge_kutta4.hpp>
64 unsigned int Nsectors,
65 unsigned int truncOrder,
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) {
139 double tmp = sx * sy;
142 double kxy = K3 *
std::abs(1.0 - f) / ((sx + sy) * sz);
144 double Kx = kxy / sx;
145 double Ky = kxy / sy;
146 double Kz = K3 * f / (tmp * sz);
148 return -0.5 * Kx *
x_m *
x_m
157 unsigned int maxitOrbit,
188 if ( !cof.findOrbit(accuracy, maxitOrbit,
E_m, denergy, rguess) ) {
190 "Closed orbit finder didn't converge.");
193 cof.computeOrbitProperties(
E_m);
196 container_t h = cof.getInverseBendingRadius(angle);
212 if (!boost::filesystem::exists(fpath)) {
213 boost::filesystem::create_directory(fpath);
216 std::pair<double,double> tunes = cof.getTunes();
217 double ravg = cof.getAverageRadius();
220 *
gmsg <<
"* ----------------------------" <<
endl
221 <<
"* Closed orbit info:" <<
endl
223 <<
"* average radius: " << ravg <<
" [m]" <<
endl
224 <<
"* initial radius: " << r[0] <<
" [m]" <<
endl
225 <<
"* initial momentum: " << peo[0] <<
" [Beta Gamma]" <<
endl
226 <<
"* frequency error: " << cof.getFrequencyError()*100 <<
" [ % ] "<<
endl
227 <<
"* horizontal tune: " << tunes.first <<
endl
228 <<
"* vertical tune: " << tunes.second <<
endl
229 <<
"* ----------------------------" <<
endl <<
endl;
235 std::ofstream writeMturn, writeMcyc, writeMsc;
244 "OneTurnMapsForEnergy" + energy +
"MeV.dat"
247 writeMturn.open(fname, std::ios::out);
252 "SpaceChargeMapPerAngleForEnergy" + energy +
"MeV_iteration_0.dat"
255 writeMsc.open(fname, std::ios::out);
260 "CyclotronMapPerAngleForEnergy" + energy +
"MeV.dat"
263 writeMcyc.open(fname, std::ios::out);
267 for (
unsigned int i = 0; i <
nSteps_m; ++i) {
268 Mcycs[i] = mapgen.generateMap(
H_m(h[i],
287 mapgen.combine(Mscs,Mcycs);
303 while (
error_m > accuracy && !stop) {
326 "SpaceChargeMapPerAngleForEnergy" + energy +
"MeV_iteration_"
331 writeMsc.open(fname, std::ios::out);
335 for (
unsigned int i = 0; i <
nSteps_m; ++i) {
349 mapgen.combine(Mscs,Mcycs);
350 Mturn = mapgen.getMap();
371 }
catch(
const std::exception&
e) {
379 "MatchedDistributions.dat"
382 std::ofstream writeSigmaMatched(fname, std::ios::out);
386 writeSigmaMatched <<
"* Converged (Ex, Ey, Ez) = (" << emit[0]
387 <<
", " << emit[1] <<
", " << emit[2]
388 <<
") pi mm mrad for E= " <<
E_m <<
" (MeV)"
391 for(
unsigned int i = 0; i <
sigma_m.size1(); ++ i) {
392 writeSigmaMatched << std::setprecision(4) << std::setw(11)
394 for(
unsigned int j = 1; j <
sigma_m.size2(); ++ j) {
395 writeSigmaMatched <<
" & " << std::setprecision(4)
396 << std::setw(11) <<
sigma_m(i,j);
398 writeSigmaMatched <<
" \\\\" <<
std::endl;
402 writeSigmaMatched.close();
439 eigen(1) = - Ms(1,0);
441 eigen(3) = - Ms(3,2);
450 matrix_t newSigma = matt_boost::gemmm<matrix_t>(Mturn,
452 boost::numeric::ublas::trans(Mturn));
499 double guessedEmittance = std::cbrt(ex * ey * ez);
502 double rcyc = ravg /
beta_m;
505 double avgInverseBendingRadius = 1.0 / ravg;
526 sig = sig0 * std::cbrt(1.0 +
alpha);
527 }
else if (
alpha >= 0) {
528 sig = sig0 * (1 +
alpha * (0.25 - 0.03125 *
alpha));
531 "Negative alpha value: " + std::to_string(
alpha) +
" < 0");
535 double K = K3 *
gamma_m / (3.0 * sig * sig * sig);
538 double a = 0.5 * kx - K;
545 "Negative value --> No real-valued frequency.");
547 double tmp =
a *
a - b;
550 "Square root of negative number.");
556 "Square root of negative number.");
558 if (
std::pow(avgInverseBendingRadius, 2) * nuz * nuz <= K)
560 "h^{2} * nu_{z}^{2} <= K (i.e. square root of negative number)");
565 double A = avgInverseBendingRadius / (Omega * Omega + K);
566 double B = avgInverseBendingRadius / (omega * omega + K);
567 double invAB = 1.0 / (B - A);
570 matrix_t sigma = boost::numeric::ublas::zero_matrix<double>(6);
573 sigma(0,0) = invAB * (B * ex / Omega + A * ez / omega);
576 sigma(0,5) = sigma(5,0) = invAB * (ex / Omega + ez / omega);
579 sigma(1,1) = invAB * (B * ex * Omega + A * ez * omega);
582 sigma(1,4) = sigma(4,1) = invAB * (ex * Omega+ez * omega) / (K *
gamma2_m);
585 sigma(2,2) = ey / (
std::sqrt(
std::pow(avgInverseBendingRadius,2) * nuz * nuz - K));
587 sigma(3,3) = (ey * ey) / sigma(2,2);
590 sigma(4,4) = invAB * (A * ex * Omega + B * ez * omega) / (K *
gamma2_m);
593 sigma(5,5) = invAB * (ex / (B * Omega) + ez / (A * omega));
607 "InitialSigmaPerAngleForEnergy" + energy +
"MeV.dat"
610 std::ofstream writeInit(fname, std::ios::out);
677 double gammax = 1.0 / betax;
682 double gammal = 1.0 / betal;
704 double cosz = 0.5 * (M(2,2) + M(3,3));
706 double sign = (std::signbit(M(2,3))) ?
double(-1) : double(1);
710 double alphaz = 0.5 * (M(2,2) - M(3,3)) * invsinz;
711 double betaz = M(2,3) * invsinz;
712 double gammaz = - M(3,2) * invsinz;
715 if (std::signbit(betaz))
719 matrix_t D = boost::numeric::ublas::zero_matrix<double>(6,6);
722 D(1,0) = - gammax * ex;
724 D(2,2) = alphaz * ey;
725 D(3,3) = - alphaz * ey;
727 D(3,2) = - gammaz * ey;
730 D(5,4) = - gammal * ez;
733 expand<sparse_matrix_t>(
R);
734 expand<sparse_matrix_t>(invR);
738 S(0,1) = S(2,3) = S(4,5) = 1;
739 S(1,0) = S(3,2) = S(5,4) = -1;
741 matrix_t sigma = matt_boost::gemmm<matrix_t>(-invR,D,
R);
750 "InitialSigmaPerAngleForEnergy" + energy +
"MeV.dat"
753 std::ofstream writeInit(fname, std::ios::app);
763 const std::vector<matrix_t>& Mcycs)
765 std::ofstream writeSigma;
773 "SigmaPerAngleForEnergy" + energy +
"MeV_iteration_"
778 writeSigma.open(fname,std::ios::out);
784 for (
unsigned int i = 1; i <
nSteps_m; ++i) {
789 boost::numeric::ublas::trans(M));
807 return std::sqrt(std::inner_product(diff.data().begin(),
815 std::ostringstream out;
816 out << std::setprecision(6) << val;
834 "PropertiesForEnergy" + energy +
"MeV.dat"
837 std::ofstream writeProperties(fname, std::ios::out);
839 writeProperties << std::left
840 << std::setw(25) <<
"orbit radius"
841 << std::setw(25) <<
"orbit momentum"
842 << std::setw(25) <<
"inverse bending radius"
843 << std::setw(25) <<
"field index"
844 << std::setw(25) <<
"path length" <<
std::endl;
846 for (
unsigned int i = 0; i < r.size(); ++i) {
847 writeProperties << std::setprecision(10) << std::left
848 << std::setw(25) << r[i]
849 << std::setw(25) << peo[i]
850 << std::setw(25) << h[i]
851 << std::setw(25) << fidx[i]
854 writeProperties.close();
862 for (
unsigned int i = 0; i < 6; ++i) {
863 for (
unsigned int j = 0; j < 6; ++j)
864 os << m(i, j) <<
" ";
Tps< T > pow(const Tps< T > &x, int y)
Integer power.
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)
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)
PETE_TUTree< FnAbs, typename T::PETE_Expr_t > abs(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.
constexpr double mrad2rad
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 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.
double mass_m
Is the mass of the particles, .
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.