OPAL (Object Oriented Parallel Accelerator Library) 2024.2
OPAL
Cyclotron.cpp
Go to the documentation of this file.
1//
2// Class Cyclotron
3// Defines the abstract interface for a cyclotron.
4//
5// Copyright (c) 2007 - 2012, Jianjun Yang and Andreas Adelmann, Paul Scherrer Institut, Villigen PSI, Switzerland
6// Copyright (c) 2013 - 2021, Paul Scherrer Institut, Villigen PSI, Switzerland
7// All rights reserved
8//
9// Implemented as part of the PhD thesis
10// "Beam dynamics in high intensity cyclotrons including neighboring bunch effects"
11// and the paper
12// "Beam dynamics in high intensity cyclotrons including neighboring bunch effects:
13// Model, implementation, and application"
14// (https://journals.aps.org/prab/pdf/10.1103/PhysRevSTAB.13.064201)
15//
16// This file is part of OPAL.
17//
18// OPAL is free software: you can redistribute it and/or modify
19// it under the terms of the GNU General Public License as published by
20// the Free Software Foundation, either version 3 of the License, or
21// (at your option) any later version.
22//
23// You should have received a copy of the GNU General Public License
24// along with OPAL. If not, see <https://www.gnu.org/licenses/>.
25//
27
31#include "Fields/Fieldmap.h"
32#include "Physics/Physics.h"
33#include "Physics/Units.h"
35#include "TrimCoils/TrimCoil.h"
36#include "Utilities/Options.h"
38#include "Utilities/Util.h"
39
40#include <cmath>
41#include <cstring>
42#include <cstdio>
43#include <filesystem>
44#include <fstream>
45#include <map>
46
47#define CHECK_CYC_FSCANF_EOF(arg) if (arg == EOF)\
48throw GeneralClassicException("Cyclotron::getFieldFromFile",\
49 "fscanf returned EOF at " #arg);
50
51extern Inform* gmsg;
52extern Inform *gmsgALL;
53
57
59 Component(right),
61 fmapfn_m(right.fmapfn_m),
62 rffrequ_m(right.rffrequ_m),
63 rfphi_m(right.rfphi_m),
64 escale_m(right.escale_m),
67 rinit_m(right.rinit_m),
68 prinit_m(right.prinit_m),
69 phiinit_m(right.phiinit_m),
70 zinit_m(right.zinit_m),
71 pzinit_m(right.pzinit_m),
75 harm_m(right.harm_m),
76 bscale_m(right.bscale_m),
78 minr_m(right.minr_m),
79 maxr_m(right.maxr_m),
80 minz_m(right.minz_m),
81 maxz_m(right.maxz_m),
82 fmLowE_m(right.fmLowE_m),
83 fmHighE_m(right.fmHighE_m),
87}
88
89Cyclotron::Cyclotron(const std::string& name):
91}
92
95
96
97void Cyclotron::applyTrimCoil_m(const double r, const double z,
98 const double tet_rad,
99 double* br, double* bz) {
100 for (auto trimcoil : trimcoils_m) {
101 trimcoil->applyField(r, z, tet_rad, br, bz);
102 }
103}
104
105void Cyclotron::applyTrimCoil(const double r, const double z,
106 const double tet_rad,
107 double& br, double& bz) {
108 //Changed from > to >= to include case where bz == 0 and trimCoilThreshold_m == 0 -DW
109 if (std::abs(bz) >= trimCoilThreshold_m) {
110 applyTrimCoil_m(r, z, tet_rad, &br, &bz);
111 } else {
112 // make sure to have a smooth transition
113 double tmp_bz = 0.0;
114 applyTrimCoil_m(r, z, tet_rad, &br, &tmp_bz);
115 bz += tmp_bz * std::abs(bz) / trimCoilThreshold_m;
116 }
117}
118
119void Cyclotron::accept(BeamlineVisitor &visitor) const {
120 visitor.visitCyclotron(*this);
121}
122
123void Cyclotron::setRinit(double rinit) {
124 rinit_m = rinit;
125}
126
127double Cyclotron::getRinit() const {
128 return rinit_m;
129}
130
131void Cyclotron::setPRinit(double prinit) {
132 prinit_m = prinit;
133}
134
135double Cyclotron::getPRinit() const {
136 return prinit_m;
137}
138
139void Cyclotron::setPHIinit(double phiinit) {
140 phiinit_m = phiinit;
141}
142
143double Cyclotron::getPHIinit() const {
144 return phiinit_m;
145}
146
147void Cyclotron::setZinit(double zinit){
148 zinit_m = zinit;
149}
150
151double Cyclotron::getZinit() const {
152 return zinit_m;
153}
154
155void Cyclotron::setPZinit(double pzinit){
156 pzinit_m = pzinit;
157}
158
159double Cyclotron::getPZinit() const {
160 return pzinit_m;
161}
162
163void Cyclotron::setTrimCoilThreshold(double trimCoilThreshold) {
164 trimCoilThreshold_m = trimCoilThreshold;
165}
166
168 return trimCoilThreshold_m;
169}
170
171void Cyclotron::setSpiralFlag(bool spiral_flag) {
172 spiralFlag_m = spiral_flag;
173}
174
176 return spiralFlag_m;
177}
178
179void Cyclotron::setFieldMapFN(const std::string& f) {
180 fmapfn_m = f;
181}
182
183std::string Cyclotron::getFieldMapFN() const {
184 if (fmapfn_m.empty()) {
186 "Cyclotron::getFieldMapFN",
187 "The attribute FMAPFN isn't set for the CYCLOTRON element");
188 } else if (std::filesystem::exists(fmapfn_m)) {
189 return fmapfn_m;
190 } else {
191 throw GeneralClassicException("Cyclotron::getFieldMapFN",
192 "Failed to open file '" + fmapfn_m +
193 "', please check if it exists");
194 }
195}
196
197void Cyclotron::setRfFieldMapFN(std::vector<std::string> f) {
198 RFfilename_m = f;
199}
200
201void Cyclotron::setRFFCoeffFN(std::vector<std::string> f) {
202 RFFCoeff_fn_m = f;
203}
204
205void Cyclotron::setRFVCoeffFN(std::vector<std::string> f) {
206 RFVCoeff_fn_m = f;
207}
208
209void Cyclotron::setRfPhi(std::vector<double> f) {
210 rfphi_m = f;
211}
212
213std::vector<double> Cyclotron::getRfPhi() const {
214 if (!rfphi_m.empty()) {
215 return rfphi_m;
216 } else {
217 throw GeneralClassicException("Cyclotron::getRfPhi",
218 "RFPHI not defined for CYCLOTRON");
219 }
220}
221
222void Cyclotron::setRfFrequ(std::vector<double> f) {
223 rffrequ_m = f;
224}
225
226std::vector<double> Cyclotron::getRfFrequ() const {
227 if (!rffrequ_m.empty()) {
228 return rffrequ_m;
229 } else {
230 throw GeneralClassicException("Cyclotron::getRfFrequ",
231 "RFFREQ not defined for CYCLOTRON");
232 }
233}
234
235void Cyclotron::setSuperpose(std::vector<bool> flag) {
236 superpose_m = flag;
237}
238
239std::vector<bool> Cyclotron::getSuperpose() const {
240 if (!superpose_m.empty()) {
241 return superpose_m;
242 } else {
243 throw GeneralClassicException("Cyclotron::getSuperpose",
244 "SUPERPOSE not defined for CYCLOTRON");
245 }
246}
247
249 symmetry_m = s;
250}
251
253 return symmetry_m;
254}
255
256void Cyclotron::setCyclotronType(const std::string& type) {
258 if (!typeName_m.empty()) {
260 }
261}
262
263const std::string& Cyclotron::getCyclotronType() const {
264 return typeName_m;
265}
266
270
272 harm_m = h;
273}
274
275void Cyclotron::setBScale(double s) {
276 bscale_m = s;
277}
278
279double Cyclotron::getBScale() const {
280 return bscale_m;
281}
282
283void Cyclotron::setEScale(std::vector<double> s) {
284 escale_m = s;
285}
286
287std::vector<double> Cyclotron::getEScale() const {
288 if (!escale_m.empty()) {
289 return escale_m;
290 } else {
291 throw GeneralClassicException("Cyclotron::getEScale",
292 "ESCALE not defined for CYCLOTRON");
293 }
294}
295
297 return trimcoils_m.size();
298}
299
301 return harm_m;
302}
303
304double Cyclotron::getRmin() const {
305 return BP_m.rmin_m;
306}
307
308double Cyclotron::getRmax() const {
309 return BP_m.rmin_m + (Bfield_m.nrad_m - 1) * BP_m.delr_m;
310}
311
312void Cyclotron::setMinR(double r) {
313 minr_m = r;
314}
315
316void Cyclotron::setMaxR(double r) {
317 maxr_m = r;
318}
319
320double Cyclotron::getMinR() const {
321 if (minr_m >= 0.0) {
322 return minr_m;
323 } else {
324 throw GeneralClassicException("Cyclotron::getMinR",
325 "MINR must be positive");
326 }
327}
328
329double Cyclotron::getMaxR() const {
330 if (maxr_m > minr_m) {
331 return maxr_m;
332 } else {
333 throw GeneralClassicException("Cyclotron::getMaxR",
334 "The attribute MAXR has to be higher than MINR");
335 }
336}
337
338void Cyclotron::setMinZ(double z) {
339 minz_m = z;
340}
341
342double Cyclotron::getMinZ() const {
343 return minz_m;
344}
345
346void Cyclotron::setMaxZ(double z) {
347 maxz_m = z;
348}
349
350double Cyclotron::getMaxZ() const {
351 if (maxz_m > minz_m) {
352 return maxz_m;
353 } else {
354 throw GeneralClassicException("Cyclotron::getMaxZ",
355 "The attribute MAXZ has to be higher than MINZ");
356 }
357}
358
359void Cyclotron::setTrimCoils(const std::vector<TrimCoil*>& trimcoils) {
360 trimcoils_m = trimcoils;
361}
362
363void Cyclotron::setFMLowE(double e) {
364 fmLowE_m = e;
365}
366
367double Cyclotron::getFMLowE() const {
368 return fmLowE_m;
369}
370
371void Cyclotron::setFMHighE(double e) {
372 fmHighE_m = e;
373}
374
375double Cyclotron::getFMHighE() const {
376 return fmHighE_m;
377}
378
380 static const std::map<std::string, BFieldType> typeStringToBFieldType_s = {
381 {"RING", BFieldType::PSIBF},
382 {"CARBONCYCL", BFieldType::CARBONBF},
383 {"CYCIAE", BFieldType::ANSYSBF},
384 {"AVFEQ", BFieldType::AVFEQBF},
385 {"FFA", BFieldType::FFABF},
386 {"BANDRF", BFieldType::BANDRF},
387 {"SYNCHROCYCLOTRON", BFieldType::SYNCHRO}
388 };
389
390 fieldType_m = typeStringToBFieldType_s.at(typeName_m);
391}
392
396
398 double refTheta,
399 double refZ) {
400 if ( (refZ < minz_m || refZ > maxz_m) ||
401 (refR < minr_m || refR > maxr_m) ) {
403 "Cyclotron::checkInitialReferenceParticle",
404 "The initial position of the reference particle (RINIT, ZINIT) "
405 "must be in the range of (MINR, MAXR) and (MINZ, MAXZ)");
406 }
407
409 throw GeneralClassicException("Cyclotron::checkInitialReferenceParticle",
410 "PHIINIT is out of [-180, 180)");
411 }
412}
413
414bool Cyclotron::apply(const size_t& id, const double& t, Vector_t& E, Vector_t& B) {
415
416 bool flagNeedUpdate = false;
417
418 const double rpos = std::hypot(RefPartBunch_m->R[id](0), RefPartBunch_m->R[id](1));
419 const double zpos = RefPartBunch_m->R[id](2);
420
421 if (zpos > maxz_m || zpos < minz_m || rpos > maxr_m || rpos < minr_m) {
422 flagNeedUpdate = true;
423 *gmsgALL << level4 << getName() << ": Particle " << id
424 << " out of the global aperture of cyclotron!" << endl;
425 *gmsgALL << level4 << getName()
426 << ": Coords: "<< RefPartBunch_m->R[id] << " m" << endl;
427
428 } else {
429 flagNeedUpdate = apply(RefPartBunch_m->R[id], RefPartBunch_m->P[id], t, E, B);
430 if (flagNeedUpdate) {
431 *gmsgALL << level4 << getName() << ": Particle "<< id
432 << " out of the field map boundary!" << endl;
433 *gmsgALL << level4 << getName()
434 << ": Coords: "<< RefPartBunch_m->R[id] << " m" << endl;
435 }
436 }
437
438 if (flagNeedUpdate) {
439 lossDs_m->addParticle(OpalParticle(id, RefPartBunch_m->R[id], RefPartBunch_m->P[id],
440 t, RefPartBunch_m->Q[id], RefPartBunch_m->M[id]),
441 std::make_pair(0, RefPartBunch_m->bunchNum[id]));
442 RefPartBunch_m->Bin[id] = -1;
443 }
444
445 return flagNeedUpdate;
446}
447
448bool Cyclotron::apply(const Vector_t& R, const Vector_t& /*P*/,
449 const double& t, Vector_t& E, Vector_t& B) {
450
451 double tet = 0.0;
452 if (std::abs(R[0]) < 1.0E-10) {
453 if (R[1] >= 0.0) {
454 tet = Physics::pi / 2.0;
455 } else {
456 tet = 1.5 * Physics::pi;
457 }
458 } else if (R[0] < 0.0) {
459 tet = Physics::pi + std::atan(R[1] / R[0]);
460 } else {
461 if (R[1] > 0.0) { // R[0] > 0.0 && R[1] > 0.0
462 tet = std::atan(R[1] / R[0]);
463 } else { // R[0] > 0.0 && R[1] <= 0.0
464 tet = Physics::two_pi + std::atan(R[1] / R[0]);
465 }
466 }
467
468 // Necessary for gap phase output -DW
469 if ( 0 <= tet && tet <= (Physics::pi / 4) ) waitingGap_m = 1;
470
471 // dB_{z}/dr, dB_{z}/dtheta, B_{z}
472 double brint = 0.0, btint = 0.0, bzint = 0.0;
473
474 const double rad = std::hypot(R[0],R[1]);
475 if ( this->interpolate(rad, tet, brint, btint, bzint) ) {
476
477 /* Br */
478 double br = - brint * R[2];
479
480 /* Btheta */
481 double bt = - btint / rad * R[2];
482
483 /* Bz */
484 double bz = - bzint;
485
486 this->applyTrimCoil(rad, R[2], tet, br, bz);
487
488 /* Br Btheta -> Bx By */
489 B[0] = br * std::cos(tet) - bt * std::sin(tet);
490 B[1] = br * std::sin(tet) + bt * std::cos(tet);
491 B[2] = bz;
492 } else {
493 return true;
494 }
495
497 return false;
498 }
499
500 //The RF field is supposed to be sampled on a cartesian grid
501 std::vector<Fieldmap>::const_iterator fi = RFfields_m.begin();
502 std::vector<double>::const_iterator rffi = rffrequ_m.begin();
503 std::vector<double>::const_iterator rfphii = rfphi_m.begin();
504 std::vector<double>::const_iterator escali = escale_m.begin();
505 std::vector<bool>::const_iterator superposei = superpose_m.begin();
506 std::vector<std::vector<double>>::const_iterator rffci = rffc_m.begin();
507 std::vector<std::vector<double>>::const_iterator rfvci = rfvc_m.begin();
508
509 double xBegin(0), xEnd(0), yBegin(0), yEnd(0), zBegin(0), zEnd(0);
510 int fcount = 0;
511
512 for (; fi != RFfields_m.end(); ++fi, ++rffi, ++rfphii, ++escali, ++superposei) {
513 (*fi)->getFieldDimensions(xBegin, xEnd, yBegin, yEnd, zBegin, zEnd);
514 if (fcount > 0 && *superposei == false) continue;
515
516 // Ok, this is a total patch job, but now that the internal cyclotron units are in m, we have to
517 // change stuff here to match with the input units of mm in the fieldmaps. -DW
518 const Vector_t temp_R = R * Vector_t(Units::m2mm); //Keep this until we have transitioned fully to m -DW
519
520 if (temp_R(0) < xBegin || temp_R(0) > xEnd ||
521 temp_R(1) < yBegin || temp_R(1) > yEnd ||
522 temp_R(2) < zBegin || temp_R(2) > zEnd) continue;
523
524 Vector_t tmpE(0.0, 0.0, 0.0), tmpB(0.0, 0.0, 0.0);
525 // out of bounds?
526 if ((*fi)->getFieldstrength(temp_R, tmpE, tmpB)) continue;
527
528 ++fcount;
529
530 double frequency = (*rffi); // frequency in [MHz]
531 double ebscale = (*escali); // E and B field scaling
532
534 double powert = 1;
535 for (const double fcoef : (*rffci)) {
536 powert *= t;
537 frequency += fcoef * powert; // Add frequency ramp [MHz/s^n]
538 }
539 powert = 1;
540 for (const double vcoef : (*rfvci)) {
541 powert *= t;
542 ebscale += vcoef * powert; // Add frequency ramp [MHz/s^n]
543 }
544 }
545
546 double phase = Physics::two_pi * Units::MHz2Hz * frequency * t + (*rfphii);
547
548 E += ebscale * std::cos(phase) * tmpE;
549 B -= ebscale * std::sin(phase) * tmpB;
550
552 continue;
553
554 // Some phase output -DW
555 double phase_print = phase * Units::rad2deg;
556 if (tet >= 90.0 && waitingGap_m == 1) {
557 phase_print = std::fmod(phase_print, 360) - 360.0;
558
559 *gmsg << endl << "Gap 1 phase = " << phase_print << " Deg" << endl;
560 *gmsg << "Gap 1 E-Field = (" << E[0] << "/" << E[1] << "/" << E[2] << ")" << endl;
561 *gmsg << "Gap 1 B-Field = (" << B[0] << "/" << B[1] << "/" << B[2] << ")" << endl;
562 *gmsg << "RF Frequency = " << frequency << " MHz" << endl;
563
564 waitingGap_m = 2;
565 } else if (tet >= 270.0 && waitingGap_m == 2) {
566 phase_print = std::fmod(phase_print, 360) - 360.0;
567
568 *gmsg << endl << "Gap 2 phase = " << phase_print << " Deg" << endl;
569 *gmsg << "Gap 2 E-Field = (" << E[0] << "/" << E[1] << "/" << E[2] << ")" << endl;
570 *gmsg << "Gap 2 B-Field = (" << B[0] << "/" << B[1] << "/" << B[2] << ")" << endl;
571 *gmsg << "RF Frequency = " << frequency << " MHz" << endl;
572 waitingGap_m = 0;
573 }
575 ++rffci, ++rfvci;
576 }
577 }
578 return false;
579}
580
581void Cyclotron::apply(const double& rad, const double& z,
582 const double& tet_rad, double& br,
583 double& bt, double& bz) {
584 this->interpolate(rad, tet_rad, br, bt, bz);
585 this->applyTrimCoil(rad, z, tet_rad, br, bz);
586}
587
589 online_m = false;
590 lossDs_m->save();
591 *gmsg << "* Finalize cyclotron " << getName() << endl;
592}
593
594bool Cyclotron::bends() const {
595 return true;
596}
597
598// calculate derivatives with 5-point lagrange's formula.
599double Cyclotron::gutdf5d(double* f, double dx, const int kor,
600 const int krl, const int lpr) {
601
602 double C[5][5][3], FAC[3];
603 double result;
604 int j;
605 /* CALCULATE DERIVATIVES WITH 5-POINT LAGRANGE FORMULA
606 * PARAMETERS:
607 * F STARTADDRESS FOR THE 5 SUPPORT POINTS
608 * DX STEPWIDTH FOR ARGUMENT
609 * KOR ORDER OF DERIVATIVE (KOR=1,2,3).
610 * KRL NUMBER OF SUPPORT POINT, WHERE THE DERIVATIVE IS TO BE CALCULATED
611 * (USUALLY 3, USE FOR BOUNDARY 1 ,2, RESP. 4, 5)
612 * LPR DISTANCE OF THE 5 STORAGE POSITIONS (=1 IF THEY ARE NEIGHBORS OR LENGTH
613 * OF COLUMNLENGTH OF A MATRIX, IF THE SUPPORT POINTS ARE ON A LINE).
614 * ATTENTION! THE INDICES ARE NOW IN C-FORMAT AND NOT IN FORTRAN-FORMAT.*/
615
616 /* COEFFICIENTS FOR THE 1ST DERIVATIVE: */
617 C[0][0][0] = -50.0;
618 C[1][0][0] = 96.0;
619 C[2][0][0] = -72.0;
620 C[3][0][0] = 32.0;
621 C[4][0][0] = -6.0;
622 C[0][1][0] = -6.0;
623 C[1][1][0] = -20.0;
624 C[2][1][0] = 36.0;
625 C[3][1][0] = -12.0;
626 C[4][1][0] = 2.0;
627 C[0][2][0] = 2.0;
628 C[1][2][0] = -16.0;
629 C[2][2][0] = 0.0;
630 C[3][2][0] = 16.0;
631 C[4][2][0] = -2.0;
632 C[0][3][0] = -2.0;
633 C[1][3][0] = 12.0;
634 C[2][3][0] = -36.0;
635 C[3][3][0] = 20.0;
636 C[4][3][0] = 6.0;
637 C[0][4][0] = 6.0;
638 C[1][4][0] = -32.0;
639 C[2][4][0] = 72.0;
640 C[3][4][0] = -96.0;
641 C[4][4][0] = 50.0;
642
643 /* COEFFICIENTS FOR THE 2ND DERIVATIVE: */
644 C[0][0][1] = 35.0;
645 C[1][0][1] = -104;
646 C[2][0][1] = 114.0;
647 C[3][0][1] = -56.0;
648 C[4][0][1] = 11.0;
649 C[0][1][1] = 11.0;
650 C[1][1][1] = -20.0;
651 C[2][1][1] = 6.0;
652 C[3][1][1] = 4.0;
653 C[4][1][1] = -1.0;
654 C[0][2][1] = -1.0;
655 C[1][2][1] = 16.0;
656 C[2][2][1] = -30.0;
657 C[3][2][1] = 16.0;
658 C[4][2][1] = -1.0;
659 C[0][3][1] = -1.0;
660 C[1][3][1] = 4.0;
661 C[2][3][1] = 6.0;
662 C[3][3][1] = -20.0;
663 C[4][3][1] = 11.0;
664 C[0][4][1] = 11.0;
665 C[1][4][1] = -56.0;
666 C[2][4][1] = 114.0;
667 C[3][4][1] = -104;
668 C[4][4][1] = 35.0;
669
670 /* COEFFICIENTS FOR THE 3RD DERIVATIVE: */
671 C[0][0][2] = -10.0;
672 C[1][0][2] = 36.0;
673 C[2][0][2] = -48.0;
674 C[3][0][2] = 28.0;
675 C[4][0][2] = -6.0;
676 C[0][1][2] = -6.0;
677 C[1][1][2] = 20.0;
678 C[2][1][2] = -24.0;
679 C[3][1][2] = 12.0;
680 C[4][1][2] = -2.0;
681 C[0][2][2] = -2.0;
682 C[1][2][2] = 4.0;
683 C[2][2][2] = 0.0;
684 C[3][2][2] = -4.0;
685 C[4][2][2] = 2.0;
686 C[0][3][2] = 2.0;
687 C[1][3][2] = -12.0;
688 C[2][3][2] = 24.0;
689 C[3][3][2] = -20.0;
690 C[4][3][2] = 6.0;
691 C[0][4][2] = 6.0;
692 C[1][4][2] = -28.0;
693 C[2][4][2] = 48.0;
694 C[3][4][2] = -36.0;
695 C[4][4][2] = 10.0;
696
697 /* FACTOR: */
698 FAC[0] = 24.0;
699 FAC[1] = 12.0;
700 FAC[2] = 4.0;
701
702 result = 0.0;
703 for (j = 0; j < 5; j++) {
704 result += C[j][krl][kor] * *(f + j * lpr);
705 }
706
707 return result / (FAC[kor] * std::pow(dx, (kor + 1)));
708}
709
710
711bool Cyclotron::interpolate(const double& rad,
712 const double& tet_rad,
713 double& brint,
714 double& btint,
715 double& bzint) {
716
717 const double xir = (rad - BP_m.rmin_m) / BP_m.delr_m;
718
719 // ir : the number of path whose radius is less than the 4 points of cell which surround the particle.
720 const int ir = (int)xir;
721
722 // wr1 : the relative distance to the inner path radius
723 const double wr1 = xir - (double)ir;
724 // wr2 : the relative distance to the outer path radius
725 const double wr2 = 1.0 - wr1;
726
727 // the corresponding angle on the field map
728 // Note: this does not work if the start point of field map does not equal zero.
729 double tet_map = std::fmod(tet_rad * Units::rad2deg, 360.0 / symmetry_m);
730
731 double xit = tet_map / BP_m.dtet_m;
732 int it = (int) xit;
733
734 const double wt1 = xit - (double)it;
735 const double wt2 = 1.0 - wt1;
736
737 // it : the number of point on the inner path whose angle is less than
738 // the particle' corresponding angle.
739 // include zero degree point
740 it++;
741
742 int r1t1, r2t1, r1t2, r2t2;
743 int ntetS = Bfield_m.ntet_m + 1;
744
745 // r1t1 : the index of the "min angle, min radius" point in the 2D field array.
746 // considering the array start with index of zero, minus 1.
747
749 /*
750 For FFA this does not work
751 */
752 r1t1 = it + ntetS * ir - 1;
753 r1t2 = r1t1 + 1;
754 r2t1 = r1t1 + ntetS;
755 r2t2 = r2t1 + 1 ;
756
757 } else {
758 /*
759 With this we have B-field AND this is far more
760 intuitive for me ....
761 */
762 r1t1 = idx(ir , it);
763 r2t1 = idx(ir + 1, it);
764 r1t2 = idx(ir , it + 1);
765 r2t2 = idx(ir + 1, it + 1);
766 }
767
768 if ((r1t1 >= 0) && (r2t2 < Bfield_m.ntot_m)) {
769 // B_{z}
770 double bzf = Bfield_m.bfld_m[r1t1] * wr2 * wt2 +
771 Bfield_m.bfld_m[r2t1] * wr1 * wt2 +
772 Bfield_m.bfld_m[r1t2] * wr2 * wt1 +
773 Bfield_m.bfld_m[r2t2] * wr1 * wt1;
774 bzint = /*- */bzf ;
775
776 // dB_{z}/dr
777 brint = Bfield_m.dbr_m[r1t1] * wr2 * wt2 +
778 Bfield_m.dbr_m[r2t1] * wr1 * wt2 +
779 Bfield_m.dbr_m[r1t2] * wr2 * wt1 +
780 Bfield_m.dbr_m[r2t2] * wr1 * wt1;
781
782 // dB_{z}/dtheta
783 btint = Bfield_m.dbt_m[r1t1] * wr2 * wt2 +
784 Bfield_m.dbt_m[r2t1] * wr1 * wt2 +
785 Bfield_m.dbt_m[r1t2] * wr2 * wt1 +
786 Bfield_m.dbt_m[r2t2] * wr1 * wt1;
787
788 return true;
789 }
790 return false;
791}
792
793
794void Cyclotron::read(const double& scaleFactor) {
795 if (typeName_m.empty()) {
796 throw GeneralClassicException("Cyclotron::read",
797 "The attribute TYPE isn't set for the CYCLOTRON element");
798 }
799 switch (fieldType_m) {
800 case BFieldType::PSIBF: {
801 *gmsg << "* Read field data from PSI format field map file" << endl;
802 getFieldFromFile_Ring(scaleFactor);
803 break;
804 }
806 *gmsg << "* Read data from 450MeV Carbon cyclotron field file" << endl;
807 getFieldFromFile_Carbon(scaleFactor);
808 break;
809 }
810 case BFieldType::ANSYSBF: {
811 *gmsg << "* Read data from 100MeV H- cyclotron CYCIAE-100 field file" << endl;
812 getFieldFromFile_CYCIAE(scaleFactor);
813 break;
814 }
815 case BFieldType::AVFEQBF: {
816 *gmsg << "* Read AVFEQ data (Riken)" << endl;
817 getFieldFromFile_AVFEQ(scaleFactor);
818 break;
819 }
820 case BFieldType::FFABF: {
821 *gmsg << "* Read FFA data MSU/FNAL" << endl;
822 getFieldFromFile_FFA(scaleFactor);
823 break;
824 }
825 case BFieldType::BANDRF: {
826 *gmsg << "* Read both median plane B field map and 3D E field map of RF cavity for compact cyclotron" << endl;
827 getFieldFromFile_BandRF(scaleFactor);
828 break;
829 }
830 case BFieldType::SYNCHRO: {
831 *gmsg << "* Read midplane B-field, 3D RF fieldmaps, and text files with RF frequency/Voltage coefficients for Synchrocyclotron" << endl;
833 break;
834 }
835 default: {
836 throw GeneralClassicException("Cyclotron::read",
837 "Unknown TYPE for the CYCLOTRON element");
838 }
839 }
840
841 // calculate the radii of initial grid.
842 initR(BP_m.rmin_m, BP_m.delr_m, Bfield_m.nrad_m);
843
844 // calculate the remaining derivatives
845 getdiffs();
846}
847
848// evaluate other derivative of magnetic field.
850
851 Bfield_m.dbr_m.resize(Bfield_m.ntot_m);
852 Bfield_m.dbrr_m.resize(Bfield_m.ntot_m);
853 Bfield_m.dbrrr_m.resize(Bfield_m.ntot_m);
854
855 Bfield_m.dbrt_m.resize(Bfield_m.ntot_m);
856 Bfield_m.dbrrt_m.resize(Bfield_m.ntot_m);
857 Bfield_m.dbrtt_m.resize(Bfield_m.ntot_m);
858
859 Bfield_m.f2_m.resize(Bfield_m.ntot_m);
860 Bfield_m.f3_m.resize(Bfield_m.ntot_m);
861 Bfield_m.g3_m.resize(Bfield_m.ntot_m);
862
863 for (int i = 0; i < Bfield_m.nrad_m; i++) {
864 for (int k = 0; k < Bfield_m.ntet_m; k++) {
865
866 double dtheta = Units::deg2rad * BP_m.dtet_m;
867
868 int kEdge;
869
870 kEdge = std::max(k - 2, 0);
871 kEdge = std::min(kEdge, Bfield_m.ntet_m - 5);
872
873 int dkFromEdge = k - kEdge;
874 int index = idx(i, k);
875 int indexkEdge = idx(i, kEdge);
876
877 Bfield_m.dbt_m[index] = gutdf5d(&Bfield_m.bfld_m[indexkEdge], dtheta, 0, dkFromEdge, 1);
878 Bfield_m.dbtt_m[index] = gutdf5d(&Bfield_m.bfld_m[indexkEdge], dtheta, 1, dkFromEdge, 1);
879 Bfield_m.dbttt_m[index] = gutdf5d(&Bfield_m.bfld_m[indexkEdge], dtheta, 2, dkFromEdge, 1);
880 }
881 }
882
883 for (int k = 0; k < Bfield_m.ntet_m; k++) {
884 // inner loop varies R
885 for (int i = 0; i < Bfield_m.nrad_m; i++) {
886 double rac = BP_m.rarr_m[i];
887 // define iredg, the reference index for radial interpolation
888 // standard: i-2 minimal: 0 (not negative!) maximal: nrad-4
889 int iredg = std::max(i - 2, 0);
890 iredg = std::min(iredg, Bfield_m.nrad_m - 5);
891 int irtak = i - iredg;
892 int index = idx(i, k);
893 int indexredg = idx(iredg, k);
894
895 Bfield_m.dbr_m[index] = gutdf5d(&Bfield_m.bfld_m[indexredg], BP_m.delr_m, 0, irtak, Bfield_m.ntetS_m);
896 Bfield_m.dbrr_m[index] = gutdf5d(&Bfield_m.bfld_m[indexredg], BP_m.delr_m, 1, irtak, Bfield_m.ntetS_m);
897 Bfield_m.dbrrr_m[index] = gutdf5d(&Bfield_m.bfld_m[indexredg], BP_m.delr_m, 2, irtak, Bfield_m.ntetS_m);
898
899 Bfield_m.dbrt_m[index] = gutdf5d(&Bfield_m.dbt_m[indexredg], BP_m.delr_m, 0, irtak, Bfield_m.ntetS_m);
900 Bfield_m.dbrrt_m[index] = gutdf5d(&Bfield_m.dbt_m[indexredg], BP_m.delr_m, 1, irtak, Bfield_m.ntetS_m);
901 Bfield_m.dbrtt_m[index] = gutdf5d(&Bfield_m.dbtt_m[indexredg], BP_m.delr_m, 0, irtak, Bfield_m.ntetS_m);
902
903 // fehlt noch!! f2,f3,g3,
904 Bfield_m.f2_m[index] = (Bfield_m.dbrr_m[index]
905 + Bfield_m.dbr_m[index] / rac
906 + Bfield_m.dbtt_m[index] / rac / rac) / 2.0;
907
908 Bfield_m.f3_m[index] = (Bfield_m.dbrrr_m[index]
909 + Bfield_m.dbrr_m[index] / rac
910 + (Bfield_m.dbrtt_m[index] - Bfield_m.dbr_m[index]) / rac / rac
911 - 2.0 * Bfield_m.dbtt_m[index] / rac / rac / rac) / 6.0;
912
913 Bfield_m.g3_m[index] = (Bfield_m.dbrrt_m[index]
914 + Bfield_m.dbrt_m[index] / rac
915 + Bfield_m.dbttt_m[index] / rac / rac) / 6.0;
916 } // Radius Loop
917 } // Azimuth loop
918
919 // copy 1st azimuth to last + 1 to always yield an interval
920 for (int i = 0; i < Bfield_m.nrad_m; i++) {
921 int iend = idx(i, Bfield_m.ntet_m);
922 int istart = idx(i, 0);
923
924 Bfield_m.bfld_m[iend] = Bfield_m.bfld_m[istart];
925 Bfield_m.dbt_m[iend] = Bfield_m.dbt_m[istart];
926 Bfield_m.dbtt_m[iend] = Bfield_m.dbtt_m[istart];
927 Bfield_m.dbttt_m[iend] = Bfield_m.dbttt_m[istart];
928
929 Bfield_m.dbr_m[iend] = Bfield_m.dbr_m[istart];
930 Bfield_m.dbrr_m[iend] = Bfield_m.dbrr_m[istart];
931 Bfield_m.dbrrr_m[iend] = Bfield_m.dbrrr_m[istart];
932
933 Bfield_m.dbrt_m[iend] = Bfield_m.dbrt_m[istart];
934 Bfield_m.dbrtt_m[iend] = Bfield_m.dbrtt_m[istart];
935 Bfield_m.dbrrt_m[iend] = Bfield_m.dbrrt_m[istart];
936
937 Bfield_m.f2_m[iend] = Bfield_m.f2_m[istart];
938 Bfield_m.f3_m[iend] = Bfield_m.f3_m[istart];
939 Bfield_m.g3_m[iend] = Bfield_m.g3_m[istart];
940 }
941
942 /* debug
943
944 for (int i = 0; i< Bfield_m.nrad_m; i++){
945 for (int j = 0; j< Bfield_m.ntetS_m; j++){
946 int index = idx(i,j);
947 double x = (BP_m.rmin_m+i*BP_m.delr_m) * std::sin(j*BP_m.dtet_m*pi/180.0);
948 double y = (BP_m.rmin_m+i*BP_m.delr_m) * std::cos(j*BP_m.dtet_m*pi/180.0);
949 *gmsg<<"x= "<<x<<" y= "<<y<<" B= "<<Bfield_m.bfld_m[index]<<endl;
950 }
951 }
952 */
953}
954
955
956// Calculates Radii of initial grid.
957// dimensions in [m]!
958void Cyclotron::initR(double rmin, double dr, int nrad) {
959 BP_m.rarr_m.resize(nrad);
960 for (int i = 0; i < nrad; i++) {
961 BP_m.rarr_m[i] = rmin + i * dr;
962 }
963 BP_m.delr_m = dr;
964}
965
966void Cyclotron::initialise(PartBunchBase<double, 3>* bunch, double& /*startField*/, double& /*endField*/) {
967 RefPartBunch_m = bunch;
968 online_m = true;
969}
970
971void Cyclotron::initialise(PartBunchBase<double, 3>* bunch, const double& scaleFactor) {
972 RefPartBunch_m = bunch;
973 lossDs_m = std::unique_ptr<LossDataSink>(new LossDataSink(getOutputFN(), !Options::asciidump));
974
975 this->read(scaleFactor);
976}
977
978
979// Read field map from external file.
980void Cyclotron::getFieldFromFile_Ring(const double& scaleFactor) {
981
982 FILE *f = nullptr;
983 int lpar;
984 char fout[100];
985 double dtmp;
986
987 *gmsg << "* ----------------------------------------------" << endl;
988 *gmsg << "* READ IN RING FIELD MAP " << endl;
989 *gmsg << "* (The first data block is useless) " << endl;
990 *gmsg << "* ----------------------------------------------" << endl;
991
992 BP_m.Bfact_m = scaleFactor;
993
994 f = std::fopen(fmapfn_m.c_str(), "r");
995
996 CHECK_CYC_FSCANF_EOF(std::fscanf(f, "%lf", &BP_m.rmin_m));
997 *gmsg << "* Minimal radius of measured field map: " << BP_m.rmin_m << " [mm]" << endl;
998 BP_m.rmin_m *= Units::mm2m;
999
1000 CHECK_CYC_FSCANF_EOF(std::fscanf(f, "%lf", &BP_m.delr_m));
1001 //if the value is negative, the actual value is its reciprocal.
1002 if (BP_m.delr_m < 0.0) BP_m.delr_m = 1.0 / (-BP_m.delr_m);
1003 *gmsg << "* Stepsize in radial direction: " << BP_m.delr_m << " [mm]" << endl;
1004 BP_m.delr_m *= Units::mm2m;
1005
1006 CHECK_CYC_FSCANF_EOF(std::fscanf(f, "%lf", &BP_m.tetmin_m));
1007 *gmsg << "* Minimal angle of measured field map: " << BP_m.tetmin_m << " [deg]" << endl;
1008
1009 CHECK_CYC_FSCANF_EOF(std::fscanf(f, "%lf", &BP_m.dtet_m));
1010 //if the value is negative, the actual value is its reciprocal.
1011 if (BP_m.dtet_m < 0.0) BP_m.dtet_m = 1.0 / (-BP_m.dtet_m);
1012 *gmsg << "* Stepsize in azimuth direction: " << BP_m.dtet_m << " [deg]" << endl;
1013
1014 for (int i = 0; i < 13; i++) {
1015 CHECK_CYC_FSCANF_EOF(std::fscanf(f, "%s", fout));
1016 }
1017
1018 CHECK_CYC_FSCANF_EOF(std::fscanf(f, "%d", &Bfield_m.nrad_m));
1019 *gmsg << "* Index in radial direction: " << Bfield_m.nrad_m << endl;
1020
1021 CHECK_CYC_FSCANF_EOF(std::fscanf(f, "%d", &Bfield_m.ntet_m));
1022 *gmsg << "* Index in azimuthal direction: " << Bfield_m.ntet_m << endl;
1023
1024 Bfield_m.ntetS_m = Bfield_m.ntet_m + 1;
1025 *gmsg << "* Accordingly, total grid point along azimuth: " << Bfield_m.ntetS_m << endl;
1026
1027 for (int i = 0; i < 5; i++) {
1028 CHECK_CYC_FSCANF_EOF(std::fscanf(f, "%s", fout));
1029 }
1030 CHECK_CYC_FSCANF_EOF(std::fscanf(f, "%d", &lpar));
1031 // msg<< "READ"<<lpar<<" DATA ENTRIES"<<endl;
1032
1033 for (int i = 0; i < 4; i++) {
1034 CHECK_CYC_FSCANF_EOF(std::fscanf(f, "%s", fout));
1035 }
1036
1037 for (int i = 0; i < lpar; i++) {
1038 CHECK_CYC_FSCANF_EOF(std::fscanf(f, "%16lE", &dtmp));
1039 }
1040 for (int i = 0; i < 6; i++) {
1041 CHECK_CYC_FSCANF_EOF(std::fscanf(f, "%s", fout));
1042 }
1043 //*gmsg << "* READ FILE DESCRIPTION..." <<endl;
1044 for (int i = 0; i < 10000; i++) {
1045 CHECK_CYC_FSCANF_EOF(std::fscanf(f, "%s", fout));
1046 if (std::strcmp(fout, "LREC=") == 0)break;
1047 }
1048
1049 for (int i = 0; i < 5; i++) {
1050 CHECK_CYC_FSCANF_EOF(std::fscanf(f, "%s", fout));
1051 }
1052 Bfield_m.ntot_m = idx(Bfield_m.nrad_m - 1, Bfield_m.ntet_m) + 1;
1053 *gmsg << "* Total stored grid point number ( ntetS * nrad ): " << Bfield_m.ntot_m << endl;
1054
1055 Bfield_m.bfld_m.resize(Bfield_m.ntot_m);
1056 Bfield_m.dbt_m.resize(Bfield_m.ntot_m);
1057 Bfield_m.dbtt_m.resize(Bfield_m.ntot_m);
1058 Bfield_m.dbttt_m.resize(Bfield_m.ntot_m);
1059
1060 *gmsg << "* Read-in loop one block per radius" << endl;
1061 *gmsg << "* Rescaling of the magnetic fields with factor: " << BP_m.Bfact_m << endl;
1062 for (int i = 0; i < Bfield_m.nrad_m; i++) {
1063 if (i > 0) {
1064 for (int dummy = 0; dummy < 6; dummy++) {
1065 CHECK_CYC_FSCANF_EOF(std::fscanf(f, "%s", fout)); // INFO-LINE
1066 }
1067 }
1068 for (int k = 0; k < Bfield_m.ntet_m; k++) {
1069 CHECK_CYC_FSCANF_EOF(std::fscanf(f, "%16lE", &(Bfield_m.bfld_m[idx(i, k)])));
1070 Bfield_m.bfld_m[idx(i, k)] *= BP_m.Bfact_m;
1071 }
1072 for (int k = 0; k < Bfield_m.ntet_m; k++) {
1073 CHECK_CYC_FSCANF_EOF(std::fscanf(f, "%16lE", &(Bfield_m.dbt_m[idx(i, k)])));
1074 Bfield_m.dbt_m[idx(i, k)] *= BP_m.Bfact_m;
1075 }
1076 for (int k = 0; k < Bfield_m.ntet_m; k++) {
1077 CHECK_CYC_FSCANF_EOF(std::fscanf(f, "%16lE", &(Bfield_m.dbtt_m[idx(i, k)])));
1078 Bfield_m.dbtt_m[idx(i, k)] *= BP_m.Bfact_m;
1079 }
1080 for (int k = 0; k < Bfield_m.ntet_m; k++) {
1081 CHECK_CYC_FSCANF_EOF(std::fscanf(f, "%16lE", &(Bfield_m.dbttt_m[idx(i, k)])));
1082 Bfield_m.dbttt_m[idx(i, k)] *= BP_m.Bfact_m;
1083 }
1084 }
1085 std::fclose(f);
1086
1087 *gmsg << "* Field Map read successfully!" << endl << endl;
1088}
1089
1090
1091void Cyclotron::getFieldFromFile_FFA(const double& /*scaleFactor*/) {
1092
1093 /*
1094 Field is read in from ascii file (COSY output) in the order:
1095 R(m) theta(Deg) x(m) y(m) Bz(T).
1096
1097 Theta is the fast varying variable
1098
1099 2.0000 0.0 2.0000 0.0000 0.0000000000000000
1100 2.0000 1.0 1.9997 0.0349 0.0000000000000000
1101 2.0000 2.0 1.9988 0.0698 0.0000000000000000
1102 2.0000 3.0 1.9973 0.1047 0.0000000000000000
1103
1104 ......
1105 <blank line>
1106
1107 2.1000 0.0 2.1000 0.0000 0.0000000000000000
1108 2.1000 1.0 2.0997 0.0367 0.0000000000000000
1109 2.1000 2.0 2.0987 0.0733 0.0000000000000000
1110 */
1111
1112 std::vector<double> rv;
1113 std::vector<double> thv;
1114 std::vector<double> xv;
1115 std::vector<double> yv;
1116 std::vector<double> bzv;
1117 std::vector<double>::iterator vit;
1118
1119 *gmsg << "* ----------------------------------------------" << endl;
1120 *gmsg << "* READ IN FFA FIELD MAP " << endl;
1121 *gmsg << "* ----------------------------------------------" << endl;
1122
1123 BP_m.Bfact_m = Units::T2kG * -1; // T->kG and H- for the current FNAL FFA
1124
1125 std::ifstream file_to_read(fmapfn_m.c_str());
1126 const int max_num_of_char_in_a_line = 128;
1127 const int num_of_header_lines = 1;
1128
1129 // STEP2: SKIP ALL THE HEADER LINES
1130 for (int i = 0; i < num_of_header_lines; ++i)
1131 file_to_read.ignore(max_num_of_char_in_a_line, '\n');
1132
1133 while(!file_to_read.eof()) {
1134 double r, th, x, y, bz;
1135 file_to_read >> r >> th >> x >> y >> bz;
1136 if ((int)th != 360) {
1137 rv.push_back(r);
1138 thv.push_back(th);
1139 xv.push_back(x);
1140 yv.push_back(y);
1141 bzv.push_back(bz);
1142 }
1143 }
1144
1145 double maxtheta = 360.0;
1146 BP_m.dtet_m = thv[1] - thv[0];
1147 BP_m.rmin_m = *(rv.begin());
1148 double rmax = rv.back();
1149
1150 // find out dR
1151 for (vit = rv.begin(); *vit <= BP_m.rmin_m; ++vit) {}
1152 BP_m.delr_m = *vit - BP_m.rmin_m;
1153
1154 BP_m.tetmin_m = thv[0];
1155
1156 Bfield_m.ntet_m = (int)((maxtheta - thv[0]) / BP_m.dtet_m);
1157 Bfield_m.nrad_m = (int)(rmax - BP_m.rmin_m) / BP_m.delr_m + 1;
1158 Bfield_m.ntetS_m = Bfield_m.ntet_m + 1;
1159 *gmsg << "* Minimal radius of measured field map: " << Units::m2mm * BP_m.rmin_m << " [mm]" << endl;
1160 *gmsg << "* Maximal radius of measured field map: " << Units::m2mm * rmax << " [mm]" << endl;
1161 *gmsg << "* Stepsize in radial direction: " << Units::m2mm * BP_m.delr_m << " [mm]" << endl;
1162 *gmsg << "* Minimal angle of measured field map: " << BP_m.tetmin_m << " [deg]" << endl;
1163 *gmsg << "* Maximal angle of measured field map: " << maxtheta << " [deg]" << endl;
1164
1165 //if the value is negtive, the actual value is its reciprocal.
1166 if (BP_m.dtet_m < 0.0) BP_m.dtet_m = 1.0 / (-BP_m.dtet_m);
1167 *gmsg << "* Stepsize in azimuth direction: " << BP_m.dtet_m << " [deg]" << endl;
1168 *gmsg << "* Total grid point along azimuth: " << Bfield_m.ntetS_m << endl;
1169 *gmsg << "* Total grid point along radius: " << Bfield_m.nrad_m << endl;
1170
1171 Bfield_m.ntot_m = Bfield_m.ntetS_m * Bfield_m.nrad_m;
1172 *gmsg << "* Total stored grid point number ( ntetS * nrad ): " << Bfield_m.ntot_m << endl;
1173
1174 Bfield_m.bfld_m.resize(Bfield_m.ntot_m);
1175 Bfield_m.dbt_m.resize(Bfield_m.ntot_m);
1176 Bfield_m.dbtt_m.resize(Bfield_m.ntot_m);
1177 Bfield_m.dbttt_m.resize(Bfield_m.ntot_m);
1178
1179 *gmsg << "* Rescaling of the magnetic fields with factor: " << BP_m.Bfact_m << endl;
1180
1181 int count = 0;
1182 for (int r = 0; r < Bfield_m.nrad_m; r++) {
1183 for (int k = 0; k < Bfield_m.ntet_m; k++) {
1184 Bfield_m.bfld_m[idx(r, k)] = bzv[count] * BP_m.Bfact_m;
1185 count++;
1186 }
1187 }
1188
1189 if ((Ippl::getNodes()) == 1 && Options::info) {
1191 }
1192 *gmsg << "* Number of elements read: " << count << endl;
1193 *gmsg << "* Field Map read successfully!" << endl << endl;
1194}
1195
1196
1197void Cyclotron::getFieldFromFile_AVFEQ(const double& scaleFactor) {
1198
1199 FILE *f = nullptr;
1200 *gmsg << "* ----------------------------------------------" << endl;
1201 *gmsg << "* READ IN AVFEQ CYCLOTRON FIELD MAP " << endl;
1202 *gmsg << "* ----------------------------------------------" << endl;
1203
1204 /* From Hiroki-san
1205 The first line tells r minimum (500mm),
1206 r maximum(4150mm),
1207 r step(50mm),
1208 theta minimum(0deg),
1209 theta maximum(90deg)
1210 theta step(0.5deg).
1211
1212 From the next line data repeat the block for a given r which the
1213 first line of the block tells. Each block consists of the data Bz
1214 from theta minimum (0deg) to theta maximum(90deg) with theta
1215 step(0.5deg).
1216 */
1217
1218 BP_m.Bfact_m = scaleFactor / 1000.;
1219
1220 f = std::fopen(fmapfn_m.c_str(), "r");
1221
1222 CHECK_CYC_FSCANF_EOF(std::fscanf(f, "%lf", &BP_m.rmin_m));
1223 *gmsg << "* Minimal radius of measured field map: " << BP_m.rmin_m << " [mm]" << endl;
1224 BP_m.rmin_m *= Units::mm2m;
1225
1226 double rmax;
1227 CHECK_CYC_FSCANF_EOF(std::fscanf(f, "%lf", &rmax));
1228 *gmsg << "* Maximal radius of measured field map: " << rmax << " [mm]" << endl;
1229 rmax *= Units::mm2m;
1230
1231 CHECK_CYC_FSCANF_EOF(std::fscanf(f, "%lf", &BP_m.delr_m));
1232 *gmsg << "* Stepsize in radial direction: " << BP_m.delr_m << " [mm]" << endl;
1233 BP_m.delr_m *= Units::mm2m;
1234
1235 CHECK_CYC_FSCANF_EOF(std::fscanf(f, "%lf", &BP_m.tetmin_m));
1236 *gmsg << "* Minimal angle of measured field map: " << BP_m.tetmin_m << " [deg]" << endl;
1237
1238 double tetmax;
1239 CHECK_CYC_FSCANF_EOF(std::fscanf(f, "%lf", &tetmax));
1240 *gmsg << "* Maximal angle of measured field map: " << tetmax << " [deg]" << endl;
1241
1242 CHECK_CYC_FSCANF_EOF(std::fscanf(f, "%lf", &BP_m.dtet_m));
1243 //if the value is nagtive, the actual value is its reciprocal.
1244
1245 if (BP_m.dtet_m < 0.0) BP_m.dtet_m = 1.0 / (-BP_m.dtet_m);
1246 *gmsg << "* Stepsize in azimuth direction: " << BP_m.dtet_m << " [deg]" << endl;
1247
1248 Bfield_m.ntetS_m = (int)((tetmax - BP_m.tetmin_m) / BP_m.dtet_m + 1);
1249 *gmsg << "* Total grid point along azimuth: " << Bfield_m.ntetS_m << endl;
1250
1251 Bfield_m.nrad_m = (int)(rmax - BP_m.rmin_m) / BP_m.delr_m;
1252
1253 int ntotidx = idx(Bfield_m.nrad_m, Bfield_m.ntetS_m) + 1;
1254
1255 Bfield_m.ntot_m = Bfield_m.ntetS_m * Bfield_m.nrad_m;
1256 *gmsg << "* Total stored grid point number ( ntetS * nrad ): "
1257 << Bfield_m.ntot_m << " ntot-idx= " << ntotidx << endl;
1258
1259 Bfield_m.bfld_m.resize(Bfield_m.ntot_m);
1260 Bfield_m.dbt_m.resize(Bfield_m.ntot_m);
1261 Bfield_m.dbtt_m.resize(Bfield_m.ntot_m);
1262 Bfield_m.dbttt_m.resize(Bfield_m.ntot_m);
1263
1264 *gmsg << "* Rescaling of the magnetic fields with factor: " << BP_m.Bfact_m << endl;
1265
1266 double tmp;
1267 int count = 0;
1268 for (int r = 0; r < Bfield_m.nrad_m; r++) {
1269 CHECK_CYC_FSCANF_EOF(std::fscanf(f, "%16lE", &tmp)); // over read
1270 for (int k = 0; k < Bfield_m.ntetS_m; k++) {
1271 CHECK_CYC_FSCANF_EOF(std::fscanf(f, "%16lE", &(Bfield_m.bfld_m[idx(r, k)])));
1272 Bfield_m.bfld_m[idx(r, k)] *= BP_m.Bfact_m;
1273 count++;
1274 }
1275 }
1276
1277 if ((Ippl::getNodes()) == 1 && Options::info) {
1279 }
1280
1281 std::fclose(f);
1282 *gmsg << "* Number of elements read: " << count << endl;
1283 *gmsg << "* Field Map read successfully!" << endl << endl;
1284}
1285
1286
1287void Cyclotron::getFieldFromFile_Carbon(const double& scaleFactor) {
1288
1289 FILE *f = nullptr;
1290 *gmsg << "* ----------------------------------------------" << endl;
1291 *gmsg << "* READ IN CARBON CYCLOTRON FIELD MAP " << endl;
1292 *gmsg << "* ----------------------------------------------" << endl;
1293
1294 BP_m.Bfact_m = scaleFactor;
1295
1296 f = std::fopen(fmapfn_m.c_str(), "r");
1297
1298 CHECK_CYC_FSCANF_EOF(std::fscanf(f, "%lf", &BP_m.rmin_m));
1299 *gmsg << "* Minimal radius of measured field map: " << BP_m.rmin_m << " [mm]" << endl;
1300 BP_m.rmin_m *= Units::mm2m;
1301
1302 CHECK_CYC_FSCANF_EOF(std::fscanf(f, "%lf", &BP_m.delr_m));
1303 //if the value is negative, the actual value is its reciprocal.
1304 if (BP_m.delr_m < 0.0) BP_m.delr_m = 1.0 / (-BP_m.delr_m);
1305 *gmsg << "* Stepsize in radial direction: " << BP_m.delr_m << " [mm]" << endl;
1306 BP_m.delr_m *= Units::mm2m;
1307
1308 CHECK_CYC_FSCANF_EOF(std::fscanf(f, "%lf", &BP_m.tetmin_m));
1309 *gmsg << "* Minimal angle of measured field map: " << BP_m.tetmin_m << " [deg]" << endl;
1310
1311 CHECK_CYC_FSCANF_EOF(std::fscanf(f, "%lf", &BP_m.dtet_m));
1312 //if the value is negative, the actual value is its reciprocal.
1313 if (BP_m.dtet_m < 0.0) BP_m.dtet_m = 1.0 / (-BP_m.dtet_m);
1314 *gmsg << "* Stepsize in azimuthal direction: " << BP_m.dtet_m << " [deg]" << endl;
1315
1316 CHECK_CYC_FSCANF_EOF(std::fscanf(f, "%d", &Bfield_m.ntet_m));
1317 *gmsg << "* Grid points along azimuth (ntet): " << Bfield_m.ntet_m << endl;
1318
1319 CHECK_CYC_FSCANF_EOF(std::fscanf(f, "%d", &Bfield_m.nrad_m));
1320 *gmsg << "* Grid points along radius (nrad): " << Bfield_m.nrad_m << endl;
1321
1322 //Bfield_m.ntetS = Bfield_m.ntet;
1323 Bfield_m.ntetS_m = Bfield_m.ntet_m + 1;
1324 //*gmsg << "* Accordingly, total grid point along azimuth: " << Bfield_m.ntetS << endl;
1325
1326 //Bfield_m.ntot = idx(Bfield_m.nrad - 1, Bfield_m.ntet) + 1;
1327 Bfield_m.ntot_m = Bfield_m.nrad_m * Bfield_m.ntetS_m;
1328
1329 *gmsg << "* Adding a guard cell along azimuth" << endl;
1330 *gmsg << "* Total stored grid point number ((ntet+1) * nrad): " << Bfield_m.ntot_m << endl;
1331 Bfield_m.bfld_m.resize(Bfield_m.ntot_m);
1332 Bfield_m.dbt_m.resize(Bfield_m.ntot_m);
1333 Bfield_m.dbtt_m.resize(Bfield_m.ntot_m);
1334 Bfield_m.dbttt_m.resize(Bfield_m.ntot_m);
1335
1336 *gmsg << "* Rescaling of the magnetic fields with factor: " << BP_m.Bfact_m << endl;
1337
1338 for (int i = 0; i < Bfield_m.nrad_m; i++) {
1339 for (int k = 0; k < Bfield_m.ntet_m; k++) {
1340 CHECK_CYC_FSCANF_EOF(std::fscanf(f, "%16lE", &(Bfield_m.bfld_m[idx(i, k)])));
1341 Bfield_m.bfld_m[idx(i, k)] *= BP_m.Bfact_m;
1342 }
1343 }
1344
1345 if ((Ippl::getNodes()) == 1 && Options::info) {
1347 }
1348
1349 std::fclose(f);
1350 *gmsg << "* Field Map read successfully!" << endl << endl;
1351}
1352
1353
1354void Cyclotron::getFieldFromFile_CYCIAE(const double& scaleFactor) {
1355
1356 FILE *f = nullptr;
1357 char fout[100];
1358 int dtmp;
1359
1360 *gmsg << "* ----------------------------------------------" << endl;
1361 *gmsg << "* READ IN CYCIAE-100 CYCLOTRON FIELD MAP " << endl;
1362 *gmsg << "* ----------------------------------------------" << endl;
1363
1364 BP_m.Bfact_m = scaleFactor;
1365
1366 f = std::fopen(fmapfn_m.c_str(), "r");
1367
1368 CHECK_CYC_FSCANF_EOF(std::fscanf(f, "%lf", &BP_m.rmin_m));
1369 *gmsg << "* Minimal radius of measured field map: " << BP_m.rmin_m << " [mm]" << endl;
1370 BP_m.rmin_m *= Units::mm2m;
1371
1372 CHECK_CYC_FSCANF_EOF(std::fscanf(f, "%lf", &BP_m.delr_m));
1373 *gmsg << "* Stepsize in radial direction: " << BP_m.delr_m << " [mm]" << endl;
1374 BP_m.delr_m *= Units::mm2m;
1375
1376 CHECK_CYC_FSCANF_EOF(std::fscanf(f, "%lf", &BP_m.tetmin_m));
1377 *gmsg << "* Minimal angle of measured field map: " << BP_m.tetmin_m << " [deg]" << endl;
1378
1379 CHECK_CYC_FSCANF_EOF(std::fscanf(f, "%lf", &BP_m.dtet_m));
1380 //if the value is nagtive, the actual value is its reciprocal.
1381 if (BP_m.dtet_m < 0.0) BP_m.dtet_m = 1.0 / (-BP_m.dtet_m);
1382 *gmsg << "* Stepsize in azimuth direction: " << BP_m.dtet_m << " [deg]" << endl;
1383
1384 CHECK_CYC_FSCANF_EOF(std::fscanf(f, "%d", &Bfield_m.ntet_m));
1385 *gmsg << "* Index in azimuthal direction: " << Bfield_m.ntet_m << endl;
1386
1387 CHECK_CYC_FSCANF_EOF(std::fscanf(f, "%d", &Bfield_m.nrad_m));
1388 *gmsg << "* Index in radial direction: " << Bfield_m.nrad_m << endl;
1389
1390 Bfield_m.ntetS_m = Bfield_m.ntet_m + 1;
1391 *gmsg << "* Accordingly, total grid point along azimuth: " << Bfield_m.ntetS_m << endl;
1392
1393 Bfield_m.ntot_m = idx(Bfield_m.nrad_m - 1, Bfield_m.ntet_m) + 1;
1394
1395 *gmsg << "* Total stored grid point number ( ntetS * nrad ): " << Bfield_m.ntot_m << endl;
1396 Bfield_m.bfld_m.resize(Bfield_m.ntot_m);
1397 Bfield_m.dbt_m.resize(Bfield_m.ntot_m);
1398 Bfield_m.dbtt_m.resize(Bfield_m.ntot_m);
1399 Bfield_m.dbttt_m.resize(Bfield_m.ntot_m);
1400
1401 *gmsg << "* Rescaling of the magnetic fields with factor: " << BP_m.Bfact_m << endl;
1402
1403 int nHalfPoints = Bfield_m.ntet_m / 2.0 + 1;
1404
1405 for (int i = 0; i < Bfield_m.nrad_m; i++) {
1406 for (int ii = 0; ii < 13; ii++) {
1407 CHECK_CYC_FSCANF_EOF(std::fscanf(f, "%s", fout));
1408 }
1409 for (int k = 0; k < nHalfPoints; k++) {
1410 CHECK_CYC_FSCANF_EOF(std::fscanf(f, "%d", &dtmp));
1411 CHECK_CYC_FSCANF_EOF(std::fscanf(f, "%d", &dtmp));
1412 CHECK_CYC_FSCANF_EOF(std::fscanf(f, "%d", &dtmp));
1413 CHECK_CYC_FSCANF_EOF(std::fscanf(f, "%lf", &(Bfield_m.bfld_m[idx(i, k)])));
1414 // T --> kGs, minus for minus hydrogen
1415 Bfield_m.bfld_m[idx(i, k)] = Bfield_m.bfld_m[idx(i, k)] * ( Units::T2kG * -1);
1416 }
1417 for (int k = nHalfPoints; k < Bfield_m.ntet_m; k++) {
1418 Bfield_m.bfld_m[idx(i, k)] = Bfield_m.bfld_m[idx(i, Bfield_m.ntet_m-k)];
1419 }
1420 }
1421
1422 std::fclose(f);
1423 *gmsg << "* Field Map read successfully!" << endl << endl;
1424}
1425
1426
1427void Cyclotron::getFieldFromFile_BandRF(const double& scaleFactor) {
1428 // read 3D E&B field data file
1429 // loop over all field maps and superpose fields
1430 for (auto& fm: RFfilename_m) {
1431 Fieldmap f = _Fieldmap::getFieldmap(fm, false);
1432 *gmsg << "* Reading '" << fm << "'" << endl;
1433 f->readMap();
1434 RFfields_m.push_back(f);
1435 }
1436 // read CARBON type B field
1437 getFieldFromFile_Carbon(scaleFactor);
1438}
1439
1440
1441void Cyclotron::getFieldFromFile_Synchrocyclotron(const double& scaleFactor) {
1442
1443 // read 3D E&B field data file
1444 std::vector<std::string>::const_iterator fm = RFfilename_m.begin();
1445 std::vector<std::string>::const_iterator rffcfni = RFFCoeff_fn_m.begin();
1446 std::vector<std::string>::const_iterator rfvcfni = RFVCoeff_fn_m.begin();
1447 // loop over all field maps and superpose fields
1448 int fcount = 0;
1449 FILE *rffcf = nullptr;
1450 FILE *rfvcf = nullptr;
1451
1452 *gmsg << endl;
1453 *gmsg << "* ------------------------------------------------------------" << endl;
1454 *gmsg << "* READ IN 3D RF Fields and Frequency Coefficients " << endl;
1455 *gmsg << "* ------------------------------------------------------------" << endl;
1456
1457 for (; fm != RFfilename_m.end(); ++fm, ++rffcfni, ++rfvcfni, ++fcount) {
1458 Fieldmap f = _Fieldmap::getFieldmap(*fm, false);
1459 f->readMap();
1460 // if (IPPL::Comm->getOutputLevel() != 0) f->getInfo(gmsg);
1461 RFfields_m.push_back(f);
1462
1463 // Read RF Frequency Coefficients from file
1464 *gmsg << "RF Frequency Coefficient Filename: " << (*rffcfni) << endl;
1465
1466 rffcf = std::fopen((*rffcfni).c_str(), "r");
1467
1468 if (rffcf == nullptr) {
1470 "Cyclotron::getFieldFromFile_Synchrocyclotron",
1471 "failed to open file '" + *rffcfni + "', please check if it exists");
1472 }
1473
1474 std::vector<double> fcoeff;
1475 int nc; //Number of coefficients
1476 double value;
1477
1478 CHECK_CYC_FSCANF_EOF(std::fscanf(rffcf, "%d", &nc));
1479 *gmsg << "* Number of coefficients in file: " << nc << endl;
1480 for (int k = 0; k < nc; k++) {
1481 CHECK_CYC_FSCANF_EOF(std::fscanf(rffcf, "%16lE", &value));
1482 fcoeff.push_back(value);
1483 //*gmsg << "* Coefficient " << k << ": " << value << endl;
1484 }
1485 rffc_m.push_back(fcoeff);
1486
1487 std::fclose(rffcf);
1488
1489 // Read RF Voltage Coefficients from file
1490 *gmsg << "RF Voltage Coefficient Filename: " << (*rfvcfni) << endl;
1491
1492 rfvcf = std::fopen((*rfvcfni).c_str(), "r");
1493 if (rfvcf == nullptr) {
1495 "Cyclotron::getFieldFromFile_Synchrocyclotron",
1496 "failed to open file '" + *rfvcfni + "', please check if it exists");
1497 }
1498
1499 std::vector<double> vcoeff;
1500
1501 CHECK_CYC_FSCANF_EOF(std::fscanf(rfvcf, "%d", &nc));
1502 *gmsg << "* Number of coefficients in file: " << nc << endl;
1503 for (int k = 0; k < nc; k++) {
1504 CHECK_CYC_FSCANF_EOF(std::fscanf(rfvcf, "%16lE", &value));
1505 vcoeff.push_back(value);
1506 //*gmsg << "* Coefficient " << k << ": " << value << endl;
1507 }
1508 rfvc_m.push_back(vcoeff);
1509
1510 std::fclose(rfvcf);
1511 }
1512
1513 // read CARBON type B field for mid-plane field
1514 getFieldFromFile_Carbon(scaleFactor);
1515}
1516
1517void Cyclotron::getDimensions(double& /*zBegin*/, double& /*zEnd*/) const
1518{ }
1519
1520
1522 std::fstream fp1;
1523 std::string fname = Util::combineFilePath({
1525 "gnu.out"
1526 });
1527 fp1.open(fname, std::ios::out);
1528 for (int i = 0; i < Bfield_m.nrad_m; i++) {
1529 for (int k = 0; k < Bfield_m.ntet_m; k++) {
1530 fp1 << BP_m.rmin_m + (i * BP_m.delr_m) << " \t "
1531 << k * (BP_m.tetmin_m + BP_m.dtet_m) << " \t "
1532 << Bfield_m.bfld_m[idx(i, k)] << std::endl;
1533 }
1534 }
1535 fp1.close();
1536
1540 std::fstream fp2;
1541 fname = Util::combineFilePath({
1543 "eb.out"
1544 });
1545 fp2.open(fname, std::ios::out);
1546 for (int i = 0; i < Bfield_m.nrad_m; i++) {
1547 for (int k = 0; k < Bfield_m.ntet_m; k++) {
1548 Vector_t tmpR = Vector_t (BP_m.rmin_m + (i * BP_m.delr_m), 0.0, k * (BP_m.tetmin_m + BP_m.dtet_m));
1549 Vector_t tmpE(0.0, 0.0, 0.0), tmpB(0.0, 0.0, 0.0);
1550 for (auto& fi: RFfields_m) {
1551 Vector_t E(0.0, 0.0, 0.0), B(0.0, 0.0, 0.0);
1552 if (!fi->getFieldstrength(tmpR, tmpE, tmpB)) {
1553 tmpE += E;
1554 tmpB -= B;
1555 }
1556 }
1557 fp2 << tmpR << " \t E= " << tmpE << "\t B= " << tmpB << std::endl;
1558 }
1559 }
1560 *gmsg << "\n* Writing 'gnu.out' and 'eb.out' files of cyclotron field maps\n" << endl;
1561 fp2.close();
1562 } else {
1563 *gmsg << "\n* Writing 'gnu.out' file of cyclotron field map\n" << endl;
1564 }
1565}
1566
1567#undef CHECK_CYC_FSCANF_EOF
#define CHECK_CYC_FSCANF_EOF(arg)
Definition Cyclotron.cpp:47
ElementType
Definition ElementBase.h:88
std::shared_ptr< _Fieldmap > Fieldmap
Definition Definitions.h:24
Inform * gmsgALL
Definition Main.cpp:71
Inform * gmsg
Definition Main.cpp:70
void fp2(BareField< T, 2U > &field, bool docomm=true)
void fp1(BareField< T, 1U > &field, bool docomm=true)
Inform & level4(Inform &inf)
Definition Inform.cpp:48
Inform & endl(Inform &inf)
Definition Inform.cpp:42
const std::string name
constexpr double two_pi
The value of.
Definition Physics.h:33
constexpr double pi
The value of.
Definition Physics.h:30
constexpr double mm2m
Definition Units.h:29
constexpr double m2mm
Definition Units.h:26
constexpr double MHz2Hz
Definition Units.h:113
constexpr double T2kG
Definition Units.h:56
constexpr double rad2deg
Definition Units.h:146
constexpr double deg2rad
Definition Units.h:143
bool asciidump
Definition Options.cpp:85
bool info
Info flag.
Definition Options.cpp:28
std::string combineFilePath(std::initializer_list< std::string > ilist)
Definition Util.cpp:197
bool angleBetweenAngles(const double angle, const double min, const double max)
check if angle (in rad and in range [0,2pi]) is within [min, max]
Definition Util.h:206
static OpalData * getInstance()
Definition OpalData.cpp:196
std::string getAuxiliaryOutputDirectory() const
get the name of the the additional data directory
Definition OpalData.cpp:666
virtual void visitCyclotron(const Cyclotron &)=0
Apply the algorithm to a cyclotron.
bool online_m
Definition Component.h:192
Component(const std::string &name)
Constructor with given name.
Definition Component.cpp:53
PartBunchBase< double, 3 > * RefPartBunch_m
Definition Component.h:191
virtual std::vector< double > getEScale() const
void setTrimCoilThreshold(double)
void setZinit(double zinit)
double minr_m
Definition Cyclotron.h:277
virtual double getCyclHarm() const
double rinit_m
Definition Cyclotron.h:260
void setBFieldType()
virtual void getDimensions(double &zBegin, double &zEnd) const
std::vector< std::string > RFfilename_m
Definition Cyclotron.h:291
virtual bool getSpiralFlag() const
virtual bool bends() const
void getFieldFromFile_CYCIAE(const double &scaleFactor)
void setSpiralFlag(bool spiral_flag)
virtual ElementType getType() const
Get element type std::string.
virtual double getPRinit() const
void getFieldFromFile_BandRF(const double &scaleFactor)
double harm_m
Definition Cyclotron.h:271
void setSuperpose(std::vector< bool > flag)
double fmHighE_m
Definition Cyclotron.h:283
void setMinR(double r)
virtual double getTrimCoilThreshold() const
double prinit_m
Definition Cyclotron.h:261
void checkInitialReferenceParticle(double refR, double refTheta, double refZ)
void setRfPhi(std::vector< double > f)
void setRFVCoeffFN(std::vector< std::string > rfv_coeff_fn)
bool spiralFlag_m
Definition Cyclotron.h:266
void setPZinit(double zinit)
void setCyclotronType(const std::string &type)
virtual void accept(BeamlineVisitor &) const
Apply visitor to Cyclotron.
virtual double getPZinit() const
double symmetry_m
Definition Cyclotron.h:258
std::string typeName_m
Definition Cyclotron.h:269
virtual std::string getFieldMapFN() const
virtual double getRmin() const
void read(const double &scaleFactor)
int idx(int irad, int ktet)
Definition Cyclotron.h:243
double phiinit_m
Definition Cyclotron.h:262
virtual double getMaxR() const
void setEScale(std::vector< double > bs)
double zinit_m
Definition Cyclotron.h:263
void setSymmetry(double symmetry)
std::vector< bool > superpose_m
Definition Cyclotron.h:256
virtual void finalise()
virtual std::vector< double > getRfFrequ() const
std::vector< double > escale_m
Definition Cyclotron.h:255
std::vector< std::string > RFVCoeff_fn_m
Definition Cyclotron.h:293
std::vector< double > rffrequ_m
Definition Cyclotron.h:250
double maxz_m
Definition Cyclotron.h:280
void getFieldFromFile_AVFEQ(const double &scaleFactor)
void setMaxR(double r)
virtual double getRmax() const
virtual double getFMHighE() const
double gutdf5d(double *f, double dx, const int kor, const int krl, const int lpr)
void setFieldMapFN(const std::string &fmapfn)
double trimCoilThreshold_m
Definition Cyclotron.h:267
virtual double getMaxZ() const
void getdiffs()
void setMaxZ(double z)
virtual double getBScale() const
virtual double getZinit() const
void getFieldFromFile_Carbon(const double &scaleFactor)
void writeOutputFieldFiles()
virtual double getPHIinit() const
std::vector< TrimCoil * > trimcoils_m
Definition Cyclotron.h:275
std::vector< std::string > RFFCoeff_fn_m
Definition Cyclotron.h:292
void setTrimCoils(const std::vector< TrimCoil * > &trimcoils)
virtual double getSymmetry() const
void setCyclHarm(double h)
virtual double getMinZ() const
void getFieldFromFile_Synchrocyclotron(const double &scaleFactor)
virtual std::vector< double > getRfPhi() const
void applyTrimCoil_m(const double r, const double z, const double tet_rad, double *br, double *bz)
Apply trim coils (calculate field contributions).
Definition Cyclotron.cpp:97
virtual ~Cyclotron()
Definition Cyclotron.cpp:93
BFieldType getBFieldType() const
double minz_m
Definition Cyclotron.h:279
virtual void initialise(PartBunchBase< double, 3 > *bunch, double &startField, double &endField)
Cyclotron(const std::string &name)
Constructor with given name.
Definition Cyclotron.cpp:89
double fmLowE_m
Definition Cyclotron.h:282
void getFieldFromFile_FFA(const double &scaleFactor)
std::string fmapfn_m
Definition Cyclotron.h:249
void initR(double rmin, double dr, int nrad)
void setPHIinit(double phiinit)
void setRfFrequ(std::vector< double > f)
void setPRinit(double prinit)
void applyTrimCoil(const double r, const double z, const double tet_rad, double &br, double &bz)
Apply trim coils (calculate field contributions) with smooth field transition.
BFieldType fieldType_m
Definition Cyclotron.h:247
double bscale_m
Definition Cyclotron.h:273
virtual bool apply(const size_t &id, const double &t, Vector_t &E, Vector_t &B)
void setRfFieldMapFN(std::vector< std::string > rffmapfn)
bool interpolate(const double &rad, const double &tet_rad, double &br, double &bt, double &bz)
void setFMHighE(double e)
std::vector< double > rfphi_m
Definition Cyclotron.h:254
void setMinZ(double z)
void setRinit(double rinit)
int waitingGap_m
Definition Cyclotron.h:298
double pzinit_m
Definition Cyclotron.h:264
virtual std::vector< bool > getSuperpose() const
double maxr_m
Definition Cyclotron.h:278
BfieldData Bfield_m
Definition Cyclotron.h:302
std::vector< std::vector< double > > rfvc_m
Definition Cyclotron.h:253
std::vector< std::vector< double > > rffc_m
Definition Cyclotron.h:251
BPositions BP_m
Definition Cyclotron.h:305
std::vector< Fieldmap > RFfields_m
Definition Cyclotron.h:290
virtual double getFMLowE() const
std::unique_ptr< LossDataSink > lossDs_m
Definition Cyclotron.h:295
unsigned int getNumberOfTrimcoils() const
virtual double getRinit() const
void getFieldFromFile_Ring(const double &scaleFactor)
virtual double getMinR() const
const std::string & getCyclotronType() const
void setRFFCoeffFN(std::vector< std::string > rff_coeff_fn)
void setFMLowE(double e)
void setBScale(double bs)
virtual const std::string & getName() const
Get element name.
std::string getOutputFN() const
Get output filename.
static void readMap(std::string Filename)
Definition Fieldmap.cpp:422
static Fieldmap getFieldmap(std::string Filename, bool fast=false)
Definition Fieldmap.cpp:48
static int getNodes()
Definition IpplInfo.cpp:670
Vektor< double, 3 > Vector_t