50 #include <boost/numeric/odeint/stepper/runge_kutta4.hpp>
63 unsigned int Nsectors,
64 unsigned int truncOrder,
67 , wo_m(cycl->getRfFrequ()[0]*Units::
MHz2Hz/cycl->getCyclHarm()*2.0*Physics::
pi)
70 , gamma2_m(gamma_m*gamma_m)
71 , nh_m(cycl->getCyclHarm())
72 , beta_m(std::
sqrt(1.0-1.0/gamma2_m))
77 , Emin_m(cycl->getFMLowE())
78 , Emax_m(cycl->getFMHighE())
80 , nSectors_m(Nsectors)
81 , nStepsPerSector_m(N/cycl->getSymmetry())
83 , error_m(std::numeric_limits<double>::
max())
84 , truncOrder_m(truncOrder)
86 , sigmas_m(nStepsPerSector_m)
111 H_m = [&](
double h,
double kx,
double ky) {
117 Hsc_m = [&](
double sigx,
double sigy,
double sigz) {
138 double tmp = sx * sy;
141 double kxy = K3 *
std::abs(1.0 - f) / ((sx + sy) * sz);
143 double Kx = kxy / sx;
144 double Ky = kxy / sy;
145 double Kz = K3 * f / (tmp * sz);
147 return -0.5 * Kx *
x_m *
x_m
156 unsigned int maxitOrbit,
187 if ( !cof.findOrbit(accuracy, maxitOrbit,
E_m, denergy, rguess) ) {
189 "Closed orbit finder didn't converge.");
192 cof.computeOrbitProperties(
E_m);
195 container_t h = cof.getInverseBendingRadius(angle);
211 if (!std::filesystem::exists(fpath)) {
212 std::filesystem::create_directory(fpath);
215 std::pair<double,double> tunes = cof.getTunes();
216 double ravg = cof.getAverageRadius();
219 *gmsg <<
"* ----------------------------" <<
endl
220 <<
"* Closed orbit info:" <<
endl
222 <<
"* average radius: " << ravg <<
" [m]" <<
endl
223 <<
"* initial radius: " << r[0] <<
" [m]" <<
endl
224 <<
"* initial momentum: " << peo[0] <<
" [Beta Gamma]" <<
endl
225 <<
"* frequency error: " << cof.getFrequencyError()*100 <<
" [ % ] "<<
endl
226 <<
"* horizontal tune: " << tunes.first <<
endl
227 <<
"* vertical tune: " << tunes.second <<
endl
228 <<
"* ----------------------------" <<
endl <<
endl;
234 std::ofstream writeMturn, writeMcyc, writeMsc;
243 "OneTurnMapsForEnergy" + energy +
"MeV.dat"
246 writeMturn.open(fname, std::ios::out);
251 "SpaceChargeMapPerAngleForEnergy" + energy +
"MeV_iteration_0.dat"
254 writeMsc.open(fname, std::ios::out);
259 "CyclotronMapPerAngleForEnergy" + energy +
"MeV.dat"
262 writeMcyc.open(fname, std::ios::out);
266 for (
unsigned int i = 0; i <
nSteps_m; ++i) {
267 Mcycs[i] = mapgen.generateMap(
H_m(h[i],
286 mapgen.combine(Mscs,Mcycs);
302 while (
error_m > accuracy && !stop) {
325 "SpaceChargeMapPerAngleForEnergy" + energy +
"MeV_iteration_"
330 writeMsc.open(fname, std::ios::out);
334 for (
unsigned int i = 0; i <
nSteps_m; ++i) {
348 mapgen.combine(Mscs,Mcycs);
349 Mturn = mapgen.getMap();
378 "MatchedDistributions.dat"
381 std::ofstream writeSigmaMatched(fname, std::ios::out);
385 writeSigmaMatched <<
"* Converged (Ex, Ey, Ez) = (" << emit[0]
386 <<
", " << emit[1] <<
", " << emit[2]
387 <<
") pi mm mrad for E= " <<
E_m <<
" (MeV)"
390 for(
unsigned int i = 0; i <
sigma_m.size1(); ++ i) {
391 writeSigmaMatched << std::setprecision(4) << std::setw(11)
393 for(
unsigned int j = 1; j < sigma_m.size2(); ++ j) {
394 writeSigmaMatched <<
" & " << std::setprecision(4)
395 << std::setw(11) <<
sigma_m(i,j);
397 writeSigmaMatched <<
" \\\\" <<
std::endl;
401 writeSigmaMatched.close();
438 eigen(1) = - Ms(1,0);
440 eigen(3) = - Ms(3,2);
449 matrix_t newSigma = matt_boost::gemmm<matrix_t>(Mturn,
451 boost::numeric::ublas::trans(Mturn));
498 double guessedEmittance = std::cbrt(ex * ey * ez);
501 double rcyc = ravg /
beta_m;
504 double avgInverseBendingRadius = 1.0 / ravg;
525 sig = sig0 * std::cbrt(1.0 + alpha);
526 }
else if (alpha >= 0) {
527 sig = sig0 * (1 + alpha * (0.25 - 0.03125 *
alpha));
530 "Negative alpha value: " + std::to_string(alpha) +
" < 0");
534 double K = K3 *
gamma_m / (3.0 * sig * sig * sig);
537 double a = 0.5 * kx - K;
544 "Negative value --> No real-valued frequency.");
546 double tmp = a * a - b;
549 "Square root of negative number.");
555 "Square root of negative number.");
557 if (
std::pow(avgInverseBendingRadius, 2) * nuz * nuz <= K)
559 "h^{2} * nu_{z}^{2} <= K (i.e. square root of negative number)");
564 double A = avgInverseBendingRadius / (Omega * Omega + K);
565 double B = avgInverseBendingRadius / (omega * omega + K);
566 double invAB = 1.0 / (B - A);
569 matrix_t sigma = boost::numeric::ublas::zero_matrix<double>(6);
572 sigma(0,0) = invAB * (B * ex / Omega + A * ez / omega);
575 sigma(0,5) = sigma(5,0) = invAB * (ex / Omega + ez / omega);
578 sigma(1,1) = invAB * (B * ex * Omega + A * ez * omega);
581 sigma(1,4) = sigma(4,1) = invAB * (ex * Omega+ez * omega) / (K *
gamma2_m);
584 sigma(2,2) = ey / (
std::sqrt(
std::pow(avgInverseBendingRadius,2) * nuz * nuz - K));
586 sigma(3,3) = (ey * ey) / sigma(2,2);
589 sigma(4,4) = invAB * (A * ex * Omega + B * ez * omega) / (K * gamma2_m);
592 sigma(5,5) = invAB * (ex / (B * Omega) + ez / (A * omega));
606 "InitialSigmaPerAngleForEnergy" + energy +
"MeV.dat"
609 std::ofstream writeInit(fname, std::ios::out);
676 double gammax = 1.0 / betax;
681 double gammal = 1.0 / betal;
703 double cosz = 0.5 * (M(2,2) + M(3,3));
705 double sign = (std::signbit(M(2,3))) ?
double(-1) : double(1);
709 double alphaz = 0.5 * (M(2,2) - M(3,3)) * invsinz;
710 double betaz = M(2,3) * invsinz;
711 double gammaz = - M(3,2) * invsinz;
714 if (std::signbit(betaz))
718 matrix_t D = boost::numeric::ublas::zero_matrix<double>(6,6);
721 D(1,0) = - gammax * ex;
723 D(2,2) = alphaz * ey;
724 D(3,3) = - alphaz * ey;
726 D(3,2) = - gammaz * ey;
729 D(5,4) = - gammal * ez;
732 expand<sparse_matrix_t>(
R);
733 expand<sparse_matrix_t>(invR);
737 S(0,1) = S(2,3) = S(4,5) = 1;
738 S(1,0) = S(3,2) = S(5,4) = -1;
740 matrix_t sigma = matt_boost::gemmm<matrix_t>(-invR,D,
R);
749 "InitialSigmaPerAngleForEnergy" + energy +
"MeV.dat"
752 std::ofstream writeInit(fname, std::ios::app);
762 const std::vector<matrix_t>& Mcycs)
764 std::ofstream writeSigma;
772 "SigmaPerAngleForEnergy" + energy +
"MeV_iteration_"
777 writeSigma.open(fname,std::ios::out);
783 for (
unsigned int i = 1; i <
nSteps_m; ++i) {
788 boost::numeric::ublas::trans(M));
806 return std::sqrt(std::inner_product(diff.data().begin(),
814 std::ostringstream out;
815 out << std::setprecision(6) << val;
833 "PropertiesForEnergy" + energy +
"MeV.dat"
836 std::ofstream writeProperties(fname, std::ios::out);
838 writeProperties << std::left
839 << std::setw(25) <<
"orbit radius"
840 << std::setw(25) <<
"orbit momentum"
841 << std::setw(25) <<
"inverse bending radius"
842 << std::setw(25) <<
"field index"
843 << std::setw(25) <<
"path length" <<
std::endl;
845 for (
unsigned int i = 0; i < r.size(); ++i) {
846 writeProperties << std::setprecision(10) << std::left
847 << std::setw(25) << r[i]
848 << std::setw(25) << peo[i]
849 << std::setw(25) << h[i]
850 << std::setw(25) << fidx[i]
853 writeProperties.close();
861 for (
unsigned int i = 0; i < 6; ++i) {
862 for (
unsigned int j = 0; j < 6; ++j)
863 os << m(i, j) <<
" ";
static OpalData * getInstance()
Tps< T > sqrt(const Tps< T > &x)
Square root.
constexpr double c
The velocity of light in m/s.
item[EANGLE] Entrance edge angle(radians).\item[ROTATION] Rotation of the magnet about its central axis(radians
and that you know you can do these things To protect your we need to make restrictions that forbid anyone to deny you these rights or to ask you to surrender the rights These restrictions translate to certain responsibilities for you if you distribute copies of the or if you modify it For if you distribute copies of such a whether gratis or for a you must give the recipients all the rights that you have You must make sure that receive or can get the source code And you must show them these terms so they know their rights We protect your rights with two distribute and or modify the software for each author s protection and we want to make certain that everyone understands that there is no warranty for this free software If the software is modified by someone else and passed we want its recipients to know that what they have is not the so that any problems introduced by others will not reflect on the original authors reputations any free program is threatened constantly by software patents We wish to avoid the danger that redistributors of a free program will individually obtain patent in effect making the program proprietary To prevent we have made it clear that any patent must be licensed for everyone s free use or not licensed at all The precise terms and conditions for distribution and modification follow GNU GENERAL PUBLIC LICENSE TERMS AND CONDITIONS FOR DISTRIBUTION AND MODIFICATION This License applies to any program or other work which contains a notice placed by the copyright holder saying it may be distributed under the terms of this General Public License The refers to any such program or and a work based on the Program means either the Program or any derivative work under copyright a work containing the Program or a portion of it
constexpr double two_pi
The value of .
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)
void initialize(double, double)
double I_m
Stores the value of the current, .
PETE_TUTree< FnAbs, typename T::PETE_Expr_t > abs(const PETE_Expr< T > &l)
constexpr double epsilon_0
The permittivity of vacuum in As/Vm.
void writeMatrix(std::ofstream &, const matrix_t &)
RealDiracMatrix::matrix_t matrix_t
Type for storing maps.
void diagonalize(matrix_t &, sparse_matrix_t &, sparse_matrix_t &)
matrix_t symplex(const matrix_t &)
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.
unsigned int nSectors_m
Number of (symmetric) sectors the field is averaged over.
constexpr double pi
The value of .
This class generates the matrices for the one turn matrix of a cyclotron.
Inform & endl(Inform &inf)
double L2ErrorNorm(const matrix_t &, const matrix_t &)
Returns the L2-error norm between the old and new sigma-matrix.
T::PETE_Expr_t::PETE_Return_t max(const PETE_Expr< T > &expr, NDIndex< D > &loc)
RealDiracMatrix::sparse_matrix_t sparse_matrix_t
Type for storing the sparse maps.
PETE_TUTree< FnFabs, typename T::PETE_Expr_t > fabs(const PETE_Expr< T > &l)
SpaceCharge Hsc_m
Stores the Hamiltonian for the space charge.
matrix_t updateInitialSigma(const matrix_t &, const vector_t &, sparse_matrix_t &, sparse_matrix_t &)
Computes the new initial sigma matrix.
std::function< Series(double, double, double)> Hamiltonian
Type of the Hamiltonian for the cyclotron.
std::string::iterator iterator
double gamma2_m
Relativistic factor squared.
bool match(double accuracy, unsigned int maxit, unsigned int maxitOrbit, Cyclotron *cycl, double denergy, double rguess, bool full)
Searches for a matched distribution.
Series x_m
All variables x, px, z, pz, l, delta.
The base class for all OPAL exceptions.
constexpr double mu_0
The permeability of vacuum in Vs/Am.
std::string getAuxiliaryOutputDirectory() const
get the name of the the additional data directory
RealDiracMatrix rdm_m
RealDiracMatrix-class member used for decoupling
T::PETE_Expr_t::PETE_Return_t prod(const PETE_Expr< T > &expr)
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.
constexpr double mrad2rad
RealDiracMatrix::vector_t vector_t
Type for storing vectors.
double isEigenEllipse(const matrix_t &Mturn, const matrix_t &sigma)
Checks if the sigma-matrix is an eigenellipse and returns the L2 error.
double E_m
Stores the user-define energy, .
bool converged_m
Is true if converged, false otherwise.
double beta_m
Velocity (c/v), .
FTps< double, 2 *3 > Series
Type of the truncated power series.
unsigned int niterations_m
Is the number of iterations needed for convergence.
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().
double error_m
Error of computation.
std::vector< double > container_t
Container for storing the properties for each angle.
std::array< double, 3 > getEmittances() const
Hamiltonian H_m
Stores the Hamiltonian of the cyclotron.
constexpr double alpha
The fine structure constant, no dimension.
c Accompany it with the information you received as to the offer to distribute corresponding source complete source code means all the source code for all modules it plus any associated interface definition plus the scripts used to control compilation and installation of the executable as a special exception
std::string combineFilePath(std::initializer_list< std::string > ilist)
std::string float2string(double val)
Transforms a floating point value to a string.
double Emin_m
Minimum energy needed in cyclotron, .
static void setGlobalTruncOrder(int order)
Set the global truncation order.
std::array< double, 3 > emittance_m
std::function< Series(double, double, double)> SpaceCharge
Type of the Hamiltonian for the space charge.
double q_m
Is the particle charge [e].
virtual double getPHIinit() const
constexpr double e
The value of .
double nh_m
Harmonic number, .
void updateSigma(const std::vector< matrix_t > &, const std::vector< matrix_t > &)
Computes new sigma matrices (one for each angle)
unsigned int nSteps_m
Number of integration steps in total.
Tps< T > pow(const Tps< T > &x, int y)
Integer power.
bool write_m
Decides for writing output (default: true)
unsigned int truncOrder_m
Truncation order of the power series for the Hamiltonian (cyclotron and space charge) ...
unsigned int nStepsPerSector_m
Number of integration steps per sector (–> also: number of maps per sector)
unsigned int N_m
Number of integration steps for closed orbit computation.
double wo_m
Is the orbital frequency, .
FVps< double, 2 *3 > Map
Type of a map.
static FTps makeVariable(int var)
Make variable.
double mass_m
Is the mass of the particles, .
double getBetaGamma(double Ekin, double mass)