1 | module madx_ptc_setcavs_module |
---|
2 | USE madx_keywords |
---|
3 | USE madx_ptc_intstate_module |
---|
4 | implicit none |
---|
5 | public |
---|
6 | |
---|
7 | ! flag for debugging ranges from 0 (no debug printout) to 10 (the most detailed) |
---|
8 | logical(lp), public :: cavsareset = .false. |
---|
9 | ! flag that indicates if cavities were already set for the current setup |
---|
10 | |
---|
11 | !******************************************************************************************** |
---|
12 | !******************************************************************************************** |
---|
13 | !******************************************************************************************** |
---|
14 | |
---|
15 | contains |
---|
16 | subroutine setcavities(my_ring, maxaccel) |
---|
17 | implicit none |
---|
18 | type(layout),target :: my_ring |
---|
19 | type(internal_state) :: localis ! internal state to be use in this routine = intstate+totalpath+time |
---|
20 | logical(lp) :: maxaccel |
---|
21 | real(dp) :: charge ! charge of an accelerated particle |
---|
22 | ! use madx_keywords |
---|
23 | integer :: i,j!,currentelement=1 !iterators |
---|
24 | integer :: mf1,mf2 |
---|
25 | type(fibre), pointer :: p ! skowron: temporary variable: current fibre |
---|
26 | type(work) :: startfen |
---|
27 | type(work) :: nfen ! New Fibre ENergy |
---|
28 | integer, pointer :: poscav(:) !array keeping indexes of cavities |
---|
29 | real(dp),allocatable :: phasecav(:) !array keeping phases of cavities |
---|
30 | real(dp) :: patchprecision=c_1d_8 |
---|
31 | logical(lp) :: patchenergy=.true. |
---|
32 | logical(lp) :: patchnext=.true. |
---|
33 | real(dp) :: prevbeta0 !just a temporary real variable |
---|
34 | real (dp) :: x(1:6) ! track vector - |
---|
35 | ! here we always use closed orbit track, that is all its relative coordinates are 0 |
---|
36 | real(dp) :: position=zero !synchronous particle position |
---|
37 | real(kind(1d0)) :: get_value |
---|
38 | !------------------------------------------------------ |
---|
39 | 100 format (a20, f10.4, a10, f10.4, a10, f10.4) |
---|
40 | 110 format (8f10.4, l2, i3) |
---|
41 | 120 format (i16, f16.3, f16.4, e16.3, e16.3, f16.3) |
---|
42 | 130 format (a12, i5, a6, a30, a6, f10.4, a20, f10.4) |
---|
43 | !------------------------------------------------------ |
---|
44 | |
---|
45 | |
---|
46 | !Below we enforce that x(6) is cT, and it is time of flight from the start |
---|
47 | !we use time T=x(6)/ctime to find the time of arrival to a cavity so we can adjust its phase optimally |
---|
48 | |
---|
49 | !This is not needed, and even to contrary, it creates a bug: |
---|
50 | !if the tracking is done without totalpath, cavities should be tuned to such x(6)=0 gives max acceleration |
---|
51 | |
---|
52 | localis = getintstate() |
---|
53 | |
---|
54 | ! localis = localis - nocavity0 + totalpath0 |
---|
55 | localis = localis - nocavity0 |
---|
56 | if (getdebug() > 1) then |
---|
57 | print *, "I am in setcavities " |
---|
58 | call print(localis,6) |
---|
59 | endif |
---|
60 | |
---|
61 | patchnext=.true. |
---|
62 | |
---|
63 | charge = get_value('beam ', "charge ") |
---|
64 | |
---|
65 | if (getdebug() > 1) then |
---|
66 | call kanalnummer(mf1) |
---|
67 | open(unit=mf1,file='sychrpart.txt') |
---|
68 | call kanalnummer(mf2) |
---|
69 | open(unit=mf2,file='twcavsettings.txt') |
---|
70 | write(mf2,'(6a16)') "!ElNo ","Ref.Momentum","Phase","Frequency [Hz]","Voltage","DeltaE" |
---|
71 | endif |
---|
72 | |
---|
73 | nfen = 0 |
---|
74 | startfen = 0 |
---|
75 | x(:)=zero |
---|
76 | |
---|
77 | call locate_all_twcav(my_ring,poscav) |
---|
78 | if ( getdebug() > 2 ) write(6,*) "There are ", size(poscav), " Cavities in the line." |
---|
79 | if ( size(poscav) == 0) then |
---|
80 | if (getdebug() > 1) then |
---|
81 | close(mf1);close(mf2); |
---|
82 | endif |
---|
83 | return |
---|
84 | endif |
---|
85 | |
---|
86 | allocate(phasecav(size(poscav))) |
---|
87 | |
---|
88 | ! Here is tracking element by element |
---|
89 | p=>my_ring%start |
---|
90 | |
---|
91 | startfen=p !setting up start energy for record |
---|
92 | nfen=p ! current fibre energy |
---|
93 | |
---|
94 | if ( getdebug() > 1 ) then |
---|
95 | print *, 'c_%feed_p0c = ', c_%feed_p0c |
---|
96 | endif |
---|
97 | |
---|
98 | if ( getdebug() > 2 ) write (*,*) 'START TRACKING TILL THE FIRST CAVITY' |
---|
99 | |
---|
100 | i = 1 |
---|
101 | |
---|
102 | do j=1,size(poscav) |
---|
103 | |
---|
104 | if ( getdebug() > 2 ) then |
---|
105 | write (*,*) 'Current cavity no is j=',j |
---|
106 | write (*,*) 'Setting beam momentum AND tracking ', nfen%p0c,' till the cavity (',poscav(j),')' |
---|
107 | endif |
---|
108 | |
---|
109 | |
---|
110 | do i=i,poscav(j)-1 !from the current element i to the current cavity j |
---|
111 | |
---|
112 | p = nfen ! set current reference energy |
---|
113 | call track(my_ring,x,i,i+1,localis) |
---|
114 | |
---|
115 | if ( .not. c_%stable_da) then |
---|
116 | call fort_warn('setcavities: ','DA got unstable') |
---|
117 | call seterrorflag(10,"setcavities ","DA got unstable"); |
---|
118 | |
---|
119 | deallocate(poscav); |
---|
120 | deallocate(phasecav); |
---|
121 | if (getdebug() > 1) then |
---|
122 | close(mf1);close(mf2); |
---|
123 | endif |
---|
124 | return |
---|
125 | endif |
---|
126 | |
---|
127 | if ( getdebug()>1 ) then |
---|
128 | write (6,*) ' i=',i,' name=',p%mag%name, & |
---|
129 | ' beta0 ', nfen%beta0, & |
---|
130 | ' newpos ', x(6), & |
---|
131 | ' Current energy ',nfen%energy |
---|
132 | write(6,'(6f8.4)') x |
---|
133 | endif |
---|
134 | |
---|
135 | if (getdebug() > 1) then |
---|
136 | write (mf1,*) ' ' |
---|
137 | write (mf1,130) 'i=',i,' name=',p%mag%name,' p0c=',p%mag%p%p0c, ' Current energy ',nfen%energy |
---|
138 | write (mf1,'(6f8.4)') x |
---|
139 | endif |
---|
140 | |
---|
141 | p=>p%next |
---|
142 | enddo |
---|
143 | |
---|
144 | if (associated(p%next)) then |
---|
145 | if ( (p%next%mag%kind==kind21) .or. (p%next%mag%kind==kind4) ) then |
---|
146 | write(6,*) "!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!" |
---|
147 | write(6,*) "!!! !!!" |
---|
148 | write(6,*) "!!! CONESCUTIVE CAVITIES !!!" |
---|
149 | write(6,*) "!!! !!!" |
---|
150 | write(6,*) "!!! Currently it is forbiden !!!" |
---|
151 | write(6,*) "!!! to place one cavity after another. !!!" |
---|
152 | write(6,*) "!!! Plese insert a marker between them. !!!" |
---|
153 | write(6,*) "!!! !!!" |
---|
154 | write(6,*) "!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!" |
---|
155 | stop |
---|
156 | endif |
---|
157 | endif |
---|
158 | |
---|
159 | !AT THIS POINT WE HAVE ARRIVED TO A CAVITY |
---|
160 | ! p point to this cavity |
---|
161 | |
---|
162 | ! set the reference energy in this cavity |
---|
163 | |
---|
164 | p = nfen |
---|
165 | |
---|
166 | if ( getdebug() > 1 ) then |
---|
167 | write (6,130) 'i=',i,' name=',p%mag%name,' p0c=',p%mag%p%p0c, ' Current energy ',nfen%energy |
---|
168 | write (6,'(6f8.4)') x |
---|
169 | endif |
---|
170 | |
---|
171 | !TUNE CAVITY |
---|
172 | call setcavity(p,x,phasecav(j),charge,maxaccel) |
---|
173 | |
---|
174 | if (getdebug() > 1) then |
---|
175 | write(mf2,120) poscav(j), p%mag%p%p0c, p%mag%phas*c_360/twopi, p%mag%freq, p%mag%volt, p%mag%delta_e |
---|
176 | endif |
---|
177 | |
---|
178 | !TRACK CAVITY |
---|
179 | call track(my_ring,x,poscav(j),poscav(j)+1,localis) |
---|
180 | |
---|
181 | if ( .not. c_%stable_da) then |
---|
182 | call fort_warn('setcavities: ','DA got unstable') |
---|
183 | call seterrorflag(10,"setcavities ","DA got unstable"); |
---|
184 | |
---|
185 | deallocate(poscav); |
---|
186 | deallocate(phasecav); |
---|
187 | if (getdebug() > 1) then |
---|
188 | close(mf1);close(mf2); |
---|
189 | endif |
---|
190 | return |
---|
191 | endif |
---|
192 | |
---|
193 | if (getdebug() > 1) then |
---|
194 | write (mf1,*) ' ' |
---|
195 | write (mf1,130) 'poscav(j)=',poscav(j),' name=',p%mag%name,' p0c=',p%mag%p%p0c, ' Current energy ',nfen%energy |
---|
196 | write (mf1,'(6f8.4)') x |
---|
197 | endif |
---|
198 | |
---|
199 | if ( getdebug() > 2 ) then |
---|
200 | write(6,'(a, 6f12.8)') ' Track parameters after cavity ',x |
---|
201 | write(*,100) 'Old Fibre: energy=',nfen%energy,' momentum=',nfen%p0c,' kinetic=',nfen%kinetic |
---|
202 | endif |
---|
203 | |
---|
204 | ! GET NEW ENERGY AFTER THE CAVITY |
---|
205 | prevbeta0 = nfen%beta0 |
---|
206 | |
---|
207 | nfen= x(5)*nfen%p0c |
---|
208 | |
---|
209 | if ( getdebug() > 2 ) then |
---|
210 | write(6,100) 'New Fibre: energy=',nfen%energy,' momentum=',nfen%p0c,' kinetic=',nfen%kinetic |
---|
211 | write(6,110) nfen |
---|
212 | write(6,'(a10, f8.4)') 'Relative E increase', (nfen%energy-startfen%energy)/startfen%kinetic |
---|
213 | endif |
---|
214 | |
---|
215 | if (getdebug()>1) write (6,*) 'beta0 ', prevbeta0, ' oldpos ', position, ' newpos ', x(6), ' Current energy ',nfen%energy |
---|
216 | position = x(6) |
---|
217 | |
---|
218 | !PATCH THE NEXT ELEMENT ON ENTRANCE |
---|
219 | p%next = nfen |
---|
220 | |
---|
221 | if ( getdebug() > 2 ) write (*,*) 'Finding patch for j=',j,' ',p%mag%name |
---|
222 | call find_patch(p,next=patchnext,ENERGY_PATCH=patchenergy,PREC=patchprecision) |
---|
223 | |
---|
224 | i=poscav(j)+1 |
---|
225 | p=>p%next |
---|
226 | |
---|
227 | !from this point on we do not need to calculate TOF cause there is no further cavs to set |
---|
228 | enddo |
---|
229 | |
---|
230 | if ( getdebug() > 2 ) then |
---|
231 | write (*,*) 'Loop over cavities done' |
---|
232 | write (*,*) 'Current element is ', p%mag%name |
---|
233 | write (*,*) 'Doing loop from the first element after the last cavity to the END' |
---|
234 | endif |
---|
235 | |
---|
236 | do i=i,my_ring%n !setting beam energies to the end of line |
---|
237 | p = nfen |
---|
238 | call track(my_ring,x,i,i+1,localis) |
---|
239 | |
---|
240 | if ( .not. c_%stable_da) then |
---|
241 | call fort_warn('setcavities: ','DA got unstable') |
---|
242 | call seterrorflag(10,"setcavities ","DA got unstable"); |
---|
243 | |
---|
244 | deallocate(poscav); |
---|
245 | deallocate(phasecav); |
---|
246 | if (getdebug() > 1) then |
---|
247 | close(mf1);close(mf2); |
---|
248 | endif |
---|
249 | return |
---|
250 | endif |
---|
251 | |
---|
252 | if (getdebug() > 1) then |
---|
253 | write (mf1,*) ' ' |
---|
254 | write (mf1,130) 'i=',i,' name=',p%mag%name,' p0c=',p%mag%p%p0c, ' Current energy ',nfen%energy |
---|
255 | write (mf1,'(6f8.4)') x |
---|
256 | endif |
---|
257 | |
---|
258 | if ( getdebug() > 1 ) then |
---|
259 | write(6,*) ' i=',i,' name=',p%mag%name, & |
---|
260 | ' beta0 ', nfen%beta0, & |
---|
261 | ' newpos ', x(6), & |
---|
262 | ' Current energy ',nfen%energy |
---|
263 | write(6,'(6f8.4)') x |
---|
264 | endif |
---|
265 | |
---|
266 | p=>p%next |
---|
267 | enddo |
---|
268 | |
---|
269 | |
---|
270 | if (getdebug() > 1) then |
---|
271 | write (mf1,*) ' ' |
---|
272 | write (mf1,*) 'END' |
---|
273 | write (mf1,'(6f8.4)') x |
---|
274 | |
---|
275 | write(6,*) 'PARAMETERS AT THE END OF LINE:' |
---|
276 | write(6,'(a, 6f8.4)') ' Track parameters ',x |
---|
277 | write(*,100) 'START energy=',startfen%energy,' momentum=',startfen%p0c,' kinetic=',startfen%kinetic |
---|
278 | write(6,100) 'END energy=',nfen%energy,' momentum=',nfen%p0c,' kinetic=',nfen%kinetic |
---|
279 | write(6,110) nfen |
---|
280 | write(6,'(a10, f8.4)') 'Relative E increase', (nfen%energy-startfen%energy)/startfen%kinetic |
---|
281 | endif |
---|
282 | |
---|
283 | ! FINISHED HERE |
---|
284 | |
---|
285 | patchnext=.false. |
---|
286 | p=>my_ring%start |
---|
287 | |
---|
288 | do i=1,my_ring%n |
---|
289 | if ( associated(p%mag) .eqv. .false.) then |
---|
290 | if (getdebug() > 1 ) then |
---|
291 | print *, 'Fibre no. ',i,' has no mag assigned to it' |
---|
292 | endif |
---|
293 | cycle |
---|
294 | endif |
---|
295 | if ( getdebug() > 2 ) then |
---|
296 | write(6,*) 'Name: ', p%mag%name, ' Kind: ', p%mag%kind |
---|
297 | endif |
---|
298 | |
---|
299 | if( (p%mag%kind == kind21) .or. (p%mag%kind == kind4)) then |
---|
300 | |
---|
301 | if(p%next%patch%energy==1) then |
---|
302 | p%patch%energy=2 |
---|
303 | p%next%patch%energy=0 |
---|
304 | endif |
---|
305 | |
---|
306 | if ( getdebug() > 1 ) then |
---|
307 | write (6,*) 'Cavity ',i,' name ',p%mag%name,' phase ', p%mag%phas,' Volt ',p%mag%volt, & |
---|
308 | & ' length ', p%mag%l |
---|
309 | write(6,*) 'DELTAE ', p%mag%DELTA_E |
---|
310 | endif |
---|
311 | |
---|
312 | |
---|
313 | endif |
---|
314 | p=>p%next |
---|
315 | enddo |
---|
316 | |
---|
317 | cavsareset = .true. !module field indicating that cavities were set appriopriately |
---|
318 | deallocate(poscav); |
---|
319 | deallocate(phasecav); |
---|
320 | |
---|
321 | if (getdebug() > 1) then |
---|
322 | close(mf1);close(mf2); |
---|
323 | endif |
---|
324 | |
---|
325 | !**************************************************************************************** |
---|
326 | !********* E N D O F PTC_TRACKCAVS ************************************************ |
---|
327 | !**************************************************************************************** |
---|
328 | !________________________________________________________________________________________ |
---|
329 | |
---|
330 | contains ! what follows are internal subroutines of ptc_trackline |
---|
331 | !____________________________________________________________________________________________ |
---|
332 | |
---|
333 | subroutine setcavity(f, x, phase_rel, charge, ene) |
---|
334 | implicit none |
---|
335 | type(fibre),intent(inout):: f ! fiber -> here must be a cavity, i.e. kind21 (tw) or kind4 (rf) |
---|
336 | real(dp) :: x(6) ! reference particle coordinates (closed orbit for a circular machine) |
---|
337 | real(dp) :: phase_rel ! final relative phase |
---|
338 | real(dp) :: phase_old ! for printing old phase |
---|
339 | real(dp) :: charge ! charge of an particle |
---|
340 | logical(lp) :: ene ! switches if cavity should always maximally accelerate |
---|
341 | ! the reference track; lag is calculated |
---|
342 | ! logical(lp) :: givendene = .false. ! makes cavity always accelerate about a given value; |
---|
343 | ! integer(4) :: tmp |
---|
344 | ! volt is calculated; lag and freq is preserved |
---|
345 | real(dp) :: de_mev ! delta energy |
---|
346 | real(dp) :: arrivtime !time of arrival |
---|
347 | ! type(internal_state) :: globalis ! internal state to be use in the tracking |
---|
348 | |
---|
349 | arrivtime = x(6)/clight |
---|
350 | if (getdebug()>2) then |
---|
351 | print *, 'arrivtime = ', arrivtime |
---|
352 | endif |
---|
353 | |
---|
354 | if( (f%mag%kind/=kind21) .and. (f%mag%kind/=kind4) ) then |
---|
355 | write(6,*) " fatal error: not a Cavity " |
---|
356 | stop |
---|
357 | endif |
---|
358 | |
---|
359 | if ( f%mag%kind==kind21) then |
---|
360 | if(f%mag%cav21%psi/=zero) then |
---|
361 | write(6,*) " warning: backwards wave present ",f%mag%cav21%psi |
---|
362 | f%mag%cav21%psi=zero ! removing backward waves |
---|
363 | f%magp%cav21%psi=zero ! removing backward waves |
---|
364 | endif |
---|
365 | endif |
---|
366 | |
---|
367 | ! globalis = getintstate() |
---|
368 | ! print*, "Total path is ", globalis%totalpath |
---|
369 | ! chargesign = charge/abs(charge) |
---|
370 | |
---|
371 | phase_old = f%mag%phas |
---|
372 | |
---|
373 | if(ene) then |
---|
374 | |
---|
375 | if ( getdebug() > 2 ) then |
---|
376 | de_mev=f%mag%volt*f%mag%l |
---|
377 | write(*,*) ' Max Energy to gain: ', de_mev, ' MeV, x(6)', x(6) |
---|
378 | endif |
---|
379 | |
---|
380 | f%mag%phas = pi/two - twopi*f%mag%freq*arrivtime - f%mag%lag ! here we tune to be on the crest and then we add the lag |
---|
381 | f%magp%phas= f%mag%phas |
---|
382 | phase_rel=f%mag%phas |
---|
383 | |
---|
384 | else |
---|
385 | |
---|
386 | f%mag%phas = - f%mag%lag |
---|
387 | f%magp%phas= f%mag%phas |
---|
388 | phase_rel=f%mag%phas |
---|
389 | |
---|
390 | endif |
---|
391 | |
---|
392 | |
---|
393 | ! write (*,*) 'energy (t/f)? :',ene, 'charge: ', charge |
---|
394 | if ( getdebug() > 1 ) then |
---|
395 | write(6,*) 'Cavity settings:' |
---|
396 | write(6,*) ' Name ', f%mag%name |
---|
397 | write(6,'(a12,f12.5,a10,l1)') ' Charge ', charge,' max ene? : ',ene |
---|
398 | write(6,'(a12,f12.5,a10)') ' Volt ', f%mag%volt,' MV ' |
---|
399 | write(6,'(a12,f12.5,a10)') ' DELTAE ', f%mag%delta_e, ' GeV ' |
---|
400 | write(6,'(a12,f12.5,a10)') ' Length ', f%mag%l,' m' |
---|
401 | write(6,'(a12,f12.3,a10)') ' Phase ', f%mag%phas, ' rad ' |
---|
402 | write(6,'(a12,f12.3,a10)') ' Old Ph ', phase_old, ' rad ' |
---|
403 | write(6,'(a12,f12.0,a10)') ' Freq ', f%mag%freq, ' Hz ' |
---|
404 | write(6,'(a12,f12.5,a10,f12.4,a10)') ' Lag ', f%mag%lag/twopi*c_360,' deg ', f%mag%lag,' rad ' |
---|
405 | write(6,'(a12,f12.5,a10)') ' P0c ', f%mag%p%p0c, 'GeV/c' |
---|
406 | endif |
---|
407 | |
---|
408 | end subroutine setcavity |
---|
409 | !____________________________________________________________________________________________ |
---|
410 | |
---|
411 | subroutine locate_all_twcav(r,pos) |
---|
412 | implicit none |
---|
413 | type(layout), target, intent(inout) :: r |
---|
414 | type(fibre), pointer:: p |
---|
415 | integer, pointer :: pos(:) |
---|
416 | integer i,ic |
---|
417 | ic=0 |
---|
418 | p=>r%start |
---|
419 | do i=1,r%n |
---|
420 | if( (p%mag%kind==kind21) .or. (p%mag%kind==kind4) ) then |
---|
421 | if(p%mag%freq/=zero) then |
---|
422 | ic=ic+1 |
---|
423 | endif |
---|
424 | endif |
---|
425 | p=>p%next |
---|
426 | enddo |
---|
427 | allocate(pos(ic)) |
---|
428 | pos=0 |
---|
429 | ic=0 |
---|
430 | p=>r%start |
---|
431 | do i=1,r%n |
---|
432 | if( (p%mag%kind==kind21) .or. (p%mag%kind==kind4) ) then |
---|
433 | if(p%mag%freq/=zero) then |
---|
434 | ic=ic+1 |
---|
435 | pos(ic)=i |
---|
436 | endif |
---|
437 | endif |
---|
438 | p=>p%next |
---|
439 | enddo |
---|
440 | |
---|
441 | end subroutine locate_all_twcav |
---|
442 | |
---|
443 | end subroutine setcavities |
---|
444 | |
---|
445 | end module madx_ptc_setcavs_module |
---|
446 | |
---|
447 | |
---|
448 | !!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!! |
---|
449 | ! |
---|
450 | ! if (f%mag%delta_e > 0) then |
---|
451 | ! kf= -f%mag%delta_e/f%mag%l/f%dir/charge |
---|
452 | ! if(givendene) then |
---|
453 | ! !push about given energy, calculates the needed voltage keeping lag and freq |
---|
454 | ! f%mag%volt=kf |
---|
455 | ! f%magp%volt=kf |
---|
456 | ! else |
---|
457 | ! !uses simply the peak voltage and phase |
---|
458 | ! f%mag%volt=sign(one,kf*f%mag%volt) * f%mag%volt |
---|
459 | ! f%magp%volt=f%mag%volt |
---|
460 | ! endif |
---|
461 | ! f%mag%phas=pi/two-twopi*f%mag%freq*arrivtime-c_%phase0 |
---|
462 | ! f%magp%phas=f%mag%phas |
---|
463 | ! endif |
---|
464 | ! phase_rel=f%mag%phas+twopi*f%mag%freq*arrivtime |
---|
465 | |
---|
466 | ! tmp = f%mag%phas/twopi |
---|
467 | ! print *, tmp, f%mag%phas/twopi |
---|
468 | ! f%mag%phas = f%mag%phas - twopi*dble(tmp) |
---|
469 | ! f%magp%phas=f%mag%phas |
---|
470 | ! print *, f%mag%phas |
---|