!The Polymorphic Tracking Code
!Copyright (C) Etienne Forest and CERN
module ptc_multiparticle
! use S_TRACKING !,FRINGE_=>FRINGE__MULTI !,FACE=>FACE_MULTI
use beam_beam_ptc
implicit none
public
CHARACTER*27 CASE_NAME(-2:3)
PRIVATE fuzzy_eq,fuzzy_neq
PRIVATE TRACK_FIBRE_FRONTR,TRACK_FIBRE_FRONTP
PRIVATE TRACK_FIBRE_BACKR,TRACK_FIBRE_BACKP
PRIVATE TRACKR_NODE_SINGLE,TRACKP_NODE_SINGLE,TRACKV_NODE_SINGLE
private DRIFTr_BACK_TO_POSITION,DRIFTp_BACK_TO_POSITION !,DRIFT_BACK_TO_POSITION
private MAKE_NODE_LAYOUT_2 !,DRIFT_TO_TIME
PRIVATE MODULATE_R,MODULATE_P
PRIVATE TRACK_MODULATION_R,TRACK_MODULATION_P
! LOGICAL :: OLD_MOD=.TRUE.
logical(lp),private, parameter :: dobb=.true.
logical(lp),private, parameter :: aperture_all_case0=.false.
type(probe) :: xsm,xsm0
!real(dp) :: unit_time =1.0e-3_dp
REAL(dp) :: x_orbit_sync(6)= 0.0_dp,dt_orbit_sync=0.0_dp
INTERFACE TRACK_NODE_SINGLE
MODULE PROCEDURE TRACKR_NODE_SINGLE !@1 t,x,state,charge
MODULE PROCEDURE TRACKP_NODE_SINGLE !@1 t,y,state,charge
MODULE PROCEDURE TRACKV_NODE_SINGLE !@1 t,v,state,charge
END INTERFACE
INTERFACE DRIFT_BACK_TO_POSITION
MODULE PROCEDURE DRIFTr_BACK_TO_POSITION
MODULE PROCEDURE DRIFTp_BACK_TO_POSITION
END INTERFACE
INTERFACE TRACK_FIBRE_FRONT
MODULE PROCEDURE TRACK_FIBRE_FRONTR
MODULE PROCEDURE TRACK_FIBRE_FRONTP
END INTERFACE
INTERFACE TRACK_FIBRE_BACK
MODULE PROCEDURE TRACK_FIBRE_BACKR
MODULE PROCEDURE TRACK_FIBRE_BACKP
END INTERFACE
INTERFACE COPY
MODULE PROCEDURE COPY_BEAM
END INTERFACE
INTERFACE OPERATOR (.feq.)
MODULE PROCEDURE fuzzy_eq
END INTERFACE
INTERFACE OPERATOR (.fne.)
MODULE PROCEDURE fuzzy_neq
END INTERFACE
INTERFACE MODULATE
MODULE PROCEDURE MODULATE_R ! PROPAGATE FAKE MODULATED (Q,P) ; 7TH AND 8TH VARIABLES
MODULE PROCEDURE MODULATE_P !
END INTERFACE
INTERFACE TRACK_MODULATION
MODULE PROCEDURE TRACK_MODULATION_R ! PROPAGATE FAKE MODULATED (Q,P) ; 7TH AND 8TH VARIABLES
MODULE PROCEDURE TRACK_MODULATION_P !
END INTERFACE
type three_d_info
! character(nlp),pointer :: name
real(dp) a(3),b(3) ! Centre of entrance and exit faces
real(dp) ent(3,3),exi(3,3) ! entrace and exit frames for drawing magnet faces
real(dp) wx,wy ! width of box for plotting purposes
real(dp) o(3),mid(3,3) ! frames at the point of tracking
real(dp) reference_ray(6) !
real(dp) x(6) ! ray tracked with reference_ray using a type(beam)
real(dp) r0(3),r(3) ! ray position global returned
real(dp) scale ! magnification using reference_ray
logical(lp) u(2) ! unstable flag for both ray and reference_ray
END type three_d_info
! real :: ttime0,ttime1,dt1=0.0,dt2=0.0;
CONTAINS
SUBROUTINE MODULATE_R(C,XS,K)
IMPLICIT NONE
type(INTEGRATION_NODE), pointer :: C
type(probe), INTENT(INOUT) :: xs
TYPE(INTERNAL_STATE) K
TYPE(ELEMENT),POINTER :: EL
TYPE(ELEMENTP),POINTER :: ELp
REAL(DP) v,dv
EL=>C%PARENT_FIBRE%MAG
ELP=>C%PARENT_FIBRE%MAGP
IF(K%MODULATION) THEN
DV=(XS%AC%X(1)*COS(EL%theta_ac)-XS%AC%X(2)*SIN(EL%theta_ac))
V=EL%DC_ac+EL%A_ac*DV
DV=el%D_ac*DV
else
V=0.0_dp
DV=0.0_dp
endif
CALL transfer_ANBN(EL,ELP,VR=V,DVR=DV)
END SUBROUTINE MODULATE_R
SUBROUTINE do_ramping_R(C,t,K)
IMPLICIT NONE
type(INTEGRATION_NODE), pointer :: C
TYPE(INTERNAL_STATE) K
TYPE(ELEMENT),POINTER :: EL
TYPE(ELEMENTP),POINTER :: ELp
REAL(DP) v,dv,t
EL=>C%PARENT_FIBRE%MAG
ELP=>C%PARENT_FIBRE%MAGP
if(.not.associated(EL%ramp)) return
V=EL%DC_ac
DV=0.0_dp
call set_ramp(C,t)
CALL transfer_ANBN(EL,ELP,VR=V,DVR=DV)
END SUBROUTINE do_ramping_R
SUBROUTINE DO_Ramping_p(C,t,K)
IMPLICIT NONE
type(INTEGRATION_NODE), pointer :: C
TYPE(INTERNAL_STATE) K
TYPE(ELEMENT),POINTER :: EL
TYPE(ELEMENTP),POINTER :: ELP
TYPE(REAL_8) V,DV
real(dp) t
EL=>C%PARENT_FIBRE%MAG
ELP=>C%PARENT_FIBRE%MAGP
if(.not.associated(EL%ramp)) return
CALL ALLOC(V)
CALL ALLOC(DV)
V=elp%DC_ac
DV=0.0_dp
call set_ramp(C,t)
CALL transfer_ANBN(EL,ELP,VP=V,DVP=DV)
CALL KILL(V)
CALL KILL(DV)
END SUBROUTINE DO_Ramping_p
SUBROUTINE set_all_ramp(R)
IMPLICIT NONE
TYPE(layout), target :: r
TYPE(fibre), POINTER :: p
integer i
REAL(DP) v,dv
v=0.0_dp
dv=0.0_dp
p=>r%start
do i=1,r%n
if(associated(p%mag%ramp)) then
call set_ramp(p%t1,x_orbit_sync(6))
CALL transfer_ANBN(p%mag,p%magp,VR=V,DVR=DV)
endif
p=>p%next
enddo
end SUBROUTINE set_all_ramp
SUBROUTINE set_ramp(t,t0)
IMPLICIT NONE
TYPE(INTEGRATION_NODE), POINTER :: T
integer i,it
real(dp) r,ti,rat,dtot
type(ramping), pointer :: a
real(dp) an,bn,t0
! if(t%pos_in_fibre==1) return
a=>t%parent_fibre%mag%ramp
dtot=(a%table(a%n)%time-a%table(1)%time) !/(a%n-1)
! ti=XSM0%ac%t/clight/a%unit_time ! time in milliseconds
ti=t0/clight !/a%unit_time ! time in milliseconds
! if(ti>a%t_max.or.tia%table(a%n)%time.or.ti=a%t_max.or.tia%table(a%n)%time.or.ti=a%t_max) then
a%table(0)%bn=0.0_dp
a%table(0)%an=0.0_dp
do i=1,size(a%table(0)%bn)
a%table(0)%bn(i)= a%table(a%n)%bn(i)*a%r
a%table(0)%an(i)= a%table(a%n)%an(i)*a%r
enddo
a%table(0)%b_t= a%table(a%n)%b_t
a=>t%parent_fibre%magp%ramp
a%table(0)%bn=0.0_dp
a%table(0)%an=0.0_dp
do i=1,size(a%table(0)%bn)
a%table(0)%bn(i)= a%table(a%n)%bn(i)*a%r
a%table(0)%an(i)= a%table(a%n)%an(i)*a%r
enddo
a%table(0)%b_t= a%table(a%n)%b_t
else
a%table(0)%bn=0.0_dp
a%table(0)%an=0.0_dp
do i=1,size(a%table(0)%bn)
a%table(0)%bn(i)= a%table(1)%bn(i)*a%r
a%table(0)%an(i)= a%table(1)%an(i)*a%r
enddo
a%table(0)%b_t= a%table(1)%b_t
a=>t%parent_fibre%magp%ramp
a%table(0)%bn=0.0_dp
a%table(0)%an=0.0_dp
do i=1,size(a%table(0)%bn)
a%table(0)%bn(i)= a%table(1)%bn(i)*a%r
a%table(0)%an(i)= a%table(1)%an(i)*a%r
enddo
a%table(0)%b_t= a%table(1)%b_t
endif
else
ti=ti-a%table(1)%time
ti=mod(ti,dtot)+a%table(1)%time
dtot=dtot/(a%n-1)
ti=(ti-a%table(1)%time)/dtot+1
it=int(ti)
! it=idint(ti)
rat=(ti-it)
a%table(0)%bn=0.0_dp
a%table(0)%an=0.0_dp
do i=1,size(a%table(0)%bn)
a%table(0)%bn(i)=((a%table(it+1)%bn(i)-a%table(it)%bn(i))*rat + a%table(it)%bn(i))*a%r
a%table(0)%an(i)= ((a%table(it+1)%an(i)-a%table(it)%an(i))*rat + a%table(it)%an(i))*a%r
enddo
a%table(0)%b_t=((a%table(it+1)%b_t-a%table(it)%b_t)*rat + a%table(it)%b_t)
a=>t%parent_fibre%magp%ramp
a%table(0)%bn=0.0_dp
a%table(0)%an=0.0_dp
do i=1,size(a%table(0)%bn)
a%table(0)%bn(i)=((a%table(it+1)%bn(i)-a%table(it)%bn(i))*rat + a%table(it)%bn(i))*a%r
a%table(0)%an(i)= ((a%table(it+1)%an(i)-a%table(it)%an(i))*rat + a%table(it)%an(i))*a%r
enddo
a%table(0)%b_t=((a%table(it+1)%b_t-a%table(it)%b_t)*rat + a%table(it)%b_t)
endif
end SUBROUTINE set_ramp
SUBROUTINE MODULATE_P(C,XS,K)
IMPLICIT NONE
type(INTEGRATION_NODE), pointer :: C
type(probe_8), INTENT(INOUT) :: xs
TYPE(INTERNAL_STATE) K
TYPE(ELEMENT),POINTER :: EL
TYPE(ELEMENTP),POINTER :: ELP
TYPE(REAL_8) V,DV
EL=>C%PARENT_FIBRE%MAG
ELP=>C%PARENT_FIBRE%MAGP
CALL ALLOC(V)
CALL ALLOC(DV)
IF(K%MODULATION) THEN
DV=(XS%AC%X(1)*COS(ELP%theta_ac)-XS%AC%X(2)*SIN(ELP%theta_ac))
V=ELP%DC_ac+ELP%A_ac*DV
DV=elp%D_ac*DV
else ! ramp
V=0.0_dp
DV=0.0_dp
endif
CALL transfer_ANBN(EL,ELP,VP=V,DVP=DV)
CALL KILL(V)
CALL KILL(DV)
END SUBROUTINE MODULATE_P
SUBROUTINE TRACK_MODULATION_R(C,XS,K)
IMPLICIT NONE
type(INTEGRATION_NODE), pointer :: C
type(probe), INTENT(INOUT) :: xs
TYPE(INTERNAL_STATE) K
real(dp) xt
real(dp),pointer :: beta0
if(k%time) then
beta0=>C%PARENT_FIBRE%beta0
xs%ac%t=c%DS_AC/beta0+xs%ac%t
xt = cos(XS%AC%om * c%DS_AC/beta0) *XS%AC%X(1) + sin(XS%AC%om * c%DS_AC/beta0) *XS%AC%X(2)
XS%AC%X(2) = -sin(XS%AC%om * c%DS_AC/beta0) *XS%AC%X(1) + cos(XS%AC%om * c%DS_AC/beta0) *XS%AC%X(2)
XS%AC%X(1) = xt
else
xt = cos(XS%AC%om * c%DS_AC) *XS%AC%X(1) + sin(XS%AC%om * c%DS_AC) *XS%AC%X(2)
XS%AC%X(2) = -sin(XS%AC%om * c%DS_AC) *XS%AC%X(1) + cos(XS%AC%om * c%DS_AC) *XS%AC%X(2)
XS%AC%X(1) = xt
xs%ac%t=c%DS_AC+xs%ac%t
endif
END SUBROUTINE TRACK_MODULATION_R
SUBROUTINE TRACK_MODULATION_P(C,XS,K)
IMPLICIT NONE
type(INTEGRATION_NODE), pointer :: C
type(probe_8), INTENT(INOUT) :: xs
TYPE(INTERNAL_STATE) K
TYPE(REAL_8) xt
real(dp),pointer :: beta0
CALL ALLOC(XT)
if(k%time) then
beta0=>C%PARENT_FIBRE%beta0
xs%ac%t=c%DS_AC/beta0+xs%ac%t
xt = cos(XS%AC%om * c%DS_AC/beta0) *XS%AC%X(1) + sin(XS%AC%om * c%DS_AC/beta0) *XS%AC%X(2)
XS%AC%X(2) = -sin(XS%AC%om * c%DS_AC/beta0) *XS%AC%X(1) + cos(XS%AC%om * c%DS_AC/beta0) *XS%AC%X(2)
XS%AC%X(1) = xt
else
xt = cos(XS%AC%om * c%DS_AC) *XS%AC%X(1) + sin(XS%AC%om * c%DS_AC) *XS%AC%X(2)
XS%AC%X(2) = -sin(XS%AC%om * c%DS_AC) *XS%AC%X(1) + cos(XS%AC%om * c%DS_AC) *XS%AC%X(2)
XS%AC%X(1) = xt
xs%ac%t=c%DS_AC+xs%ac%t
endif
CALL KILL(XT)
END SUBROUTINE TRACK_MODULATION_P
FUNCTION fuzzy_eq( S1, S2 )
implicit none
logical(lp) fuzzy_eq
real(dp), INTENT (IN) :: S1,S2
fuzzy_eq=.false.
if(abs(s1-s2)<=c_%eps_pos) fuzzy_eq=.true.
end FUNCTION fuzzy_eq
FUNCTION fuzzy_neq( S1, S2 )
implicit none
logical(lp) fuzzy_neq
real(dp), INTENT (IN) :: S1,S2
fuzzy_neq=.false.
if(abs(s1-s2)>c_%eps_pos) fuzzy_neq=.true.
end FUNCTION fuzzy_neq
SUBROUTINE move_to_s( L,s,current,i,ds ) ! Moves position s
implicit none
TYPE (INTEGRATION_NODE), POINTER :: Current
TYPE (NODE_LAYOUT) L
real(dp) s,sp,ds
integer i,k
logical(lp) DOIT !,track_it
! track_it=.false.
sp=mod(s,L%END%S(3))
if(sp==0.0_dp.and.s/=0.0_dp) then
current=>l%end
i=l%n+1
ds=0.0_dp
! track_it=.true.
return
endif
if(sp==0.0_dp) then
current=>l%start
i=1
ds=0.0_dp
return
endif
nullify(current);
Current => L%LAST
k=L%LASTPOS
I=K
ds=0.0_dp
IF(SP>CURRENT%S(3) ) then
do i=k,l%n-1
if(current%next%s(3)>=sp) exit
current=>current%next
enddo
if(current%next%s(3)/=sp) ds=sp-current%s(3)
if(current%next%s(3)==sp) THEN
ds=0.0_dp
CURRENT=>current%next
I=I+1
ENDIF
elseif(SPcurrent%previous
if(current%s(3)<=sp) exit
enddo
ds=sp-current%s(3)
endif
L%LASTPOS=I; L%LAST => Current;
if(ds>0.0_dp) then
if(CURRENT%S(4)-ds.feq.0.0_dp) then
ds=0.0_dp
current=>Current%next
i=i+1
L%LAST => Current;
ELSEIF(ds.feq.0.0_dp) THEN
DS=0.0_dp
ENDIF
endif
DOIT=.TRUE.
!DOIT=.FALSE.
if(iabs(CURRENT%cas)==0.OR.iabs(CURRENT%cas)==1) then
do while(DS==0.0_dp.AND.DOIT) ! PUTS AT BEGINNING IF DS=ZERO
CURRENT=>CURRENT%PREVIOUS
IF(ASSOCIATED(CURRENT)) THEN
IF((SP.FNE.CURRENT%S(3)).or.CURRENT%cas==-2) THEN
CURRENT=>CURRENT%NEXT
DOIT=.FALSE.
ELSE
I=I-1
ENDIF
ELSE
CURRENT=>CURRENT%NEXT
DOIT=.FALSE.
ENDIF
enddo
elseif(iabs(CURRENT%cas)==2) then
do while(DS==0.0_dp.AND.DOIT) ! PUTS AT BEGINNING IF DS=ZERO
CURRENT=>CURRENT%next
IF(ASSOCIATED(CURRENT)) THEN
IF((SP.FNE.CURRENT%S(3)).or.CURRENT%cas==1) THEN
CURRENT=>CURRENT%previous
DOIT=.FALSE.
ELSE
I=I+1
ENDIF
ELSE
CURRENT=>CURRENT%previous
DOIT=.FALSE.
ENDIF
enddo
endif
L%LASTPOS=I; L%LAST => Current;
IF(I/=L%LAST%POS) THEN
WRITE(6,*) " ERROR IN move_to_s ",I,L%LAST%POS
STOP 999
ENDIF
END SUBROUTINE move_to_s
! tracking one steps in the body
! MULTIPARTICLE AT THE FIBRE LEVEL
! front patch/misaglinments/tilt
SUBROUTINE TRACK_FIBRE_FRONTR(C,X,K)
implicit none
logical(lp) :: doneitt=.true.
TYPE(FIBRE),TARGET,INTENT(INOUT):: C
! TYPE(BEAM),TARGET,INTENT(INOUT):: B
real(dp), INTENT(INOUT) :: X(6)
TYPE(INTERNAL_STATE) K
! TYPE(INTERNAL_STATE), INTENT(IN) :: K
logical(lp) ou,patch
INTEGER(2) PATCHT,PATCHG,PATCHE
TYPE (fibre), POINTER :: CN
real(dp), POINTER :: P0,B0
!FRONTAL PATCH
! IF(ASSOCIATED(C%PATCH)) THEN
PATCHT=C%PATCH%TIME ;PATCHE=C%PATCH%ENERGY ;PATCHG=C%PATCH%PATCH;
! ELSE
! PATCHT=0 ; PATCHE=0 ;PATCHG=0;
! ENDIF
! PUSHING BEAM
!
IF(PATCHE/=0.AND.PATCHE/=2) THEN
NULLIFY(P0);NULLIFY(B0);
CN=>C%PREVIOUS
IF(ASSOCIATED(CN)) THEN ! ASSOCIATED
! IF(.NOT.CN%PATCH%ENERGY) THEN ! No need to patch IF PATCHED BEFORE
IF(CN%PATCH%ENERGY==0) THEN ! No need to patch IF PATCHED BEFORE
P0=>CN%MAG%P%P0C
B0=>CN%MAG%P%BETA0
X(2)=X(2)*P0/C%MAG%P%P0C
X(4)=X(4)*P0/C%MAG%P%P0C
IF(k%TIME.or.recirculator_cheat)THEN
X(5)=root(1.0_dp+2.0_dp*X(5)/B0+X(5)**2) !X(5) = 1+DP/P0C_OLD
X(5)=X(5)*P0/C%MAG%P%P0C-1.0_dp !X(5) = DP/P0C_NEW
X(5)=(2.0_dp*X(5)+X(5)**2)/(root(1.0_dp/C%MAG%P%BETA0**2+2.0_dp*X(5)+X(5)**2)+1.0_dp/C%MAG%P%BETA0)
ELSE
X(5)=(1.0_dp+X(5))*P0/C%MAG%P%P0C-1.0_dp
ENDIF
ENDIF ! No need to patch
ENDIF ! ASSOCIATED
ENDIF
! The chart frame of reference is located here implicitely
IF(PATCHG==1.or.PATCHG==3) THEN
patch=ALWAYS_EXACT_PATCHING.or.C%MAG%P%EXACT
CALL PATCH_FIB(C,X,k,PATCH,MY_TRUE)
ENDIF
IF(PATCHT/=0.AND.PATCHT/=2.AND.(K%TOTALPATH==0)) THEN
if(K%time) then
X(6)=X(6)-C%PATCH%a_T/c%beta0
else
X(6)=X(6)-C%PATCH%a_T
endif
ENDIF
CALL DTILTD(C%DIR,C%MAG%P%TILTD,1,X)
! The magnet frame of reference is located here implicitely before misalignments
! CALL TRACK(C,X,EXACTMIS=K%EXACTMIS)
IF(C%MAG%MIS) THEN
ou = ALWAYS_EXACTMIS !K%EXACTMIS.or.
CALL MIS_FIB(C,X,k,OU,DONEITT)
ENDIF
END SUBROUTINE TRACK_FIBRE_FRONTR
SUBROUTINE TRACK_FIBRE_FRONTP(C,X,K)
implicit none
logical(lp) :: doneitt=.true.
TYPE(FIBRE),TARGET,INTENT(INOUT):: C
! TYPE(BEAM),TARGET,INTENT(INOUT):: B
TYPE(REAL_8), INTENT(INOUT) :: X(6)
TYPE(INTERNAL_STATE) K
! TYPE(INTERNAL_STATE), INTENT(IN) :: K
logical(lp) ou,patch
INTEGER(2) PATCHT,PATCHG,PATCHE
TYPE (fibre), POINTER :: CN
real(dp), POINTER :: P0,B0
!FRONTAL PATCH
! IF(ASSOCIATED(C%PATCH)) THEN
PATCHT=C%PATCH%TIME ;PATCHE=C%PATCH%ENERGY ;PATCHG=C%PATCH%PATCH;
! ELSE
! PATCHT=0 ; PATCHE=0 ;PATCHG=0;
! ENDIF
! PUSHING BEAM
!
IF(PATCHE/=0.AND.PATCHE/=2) THEN
NULLIFY(P0);NULLIFY(B0);
CN=>C%PREVIOUS
IF(ASSOCIATED(CN)) THEN ! ASSOCIATED
! IF(.NOT.CN%PATCH%ENERGY) THEN ! No need to patch IF PATCHED BEFORE
IF(CN%PATCH%ENERGY==0) THEN ! No need to patch IF PATCHED BEFORE
P0=>CN%MAGP%P%P0C
B0=>CN%MAGP%P%BETA0
X(2)=X(2)*P0/C%MAGP%P%P0C
X(4)=X(4)*P0/C%MAGP%P%P0C
IF(k%TIME.or.recirculator_cheat)THEN
X(5)=SQRT(1.0_dp+2.0_dp*X(5)/B0+X(5)**2) !X(5) = 1+DP/P0C_OLD
X(5)=X(5)*P0/C%MAGP%P%P0C-1.0_dp !X(5) = DP/P0C_NEW
X(5)=(2.0_dp*X(5)+X(5)**2)/(SQRT(1.0_dp/C%MAGP%P%BETA0**2+2.0_dp*X(5)+X(5)**2)+1.0_dp/C%MAGP%P%BETA0)
ELSE
X(5)=(1.0_dp+X(5))*P0/C%MAGP%P%P0C-1.0_dp
ENDIF
ENDIF ! No need to patch
ENDIF ! ASSOCIATED
ENDIF
! The chart frame of reference is located here implicitely
IF(PATCHG==1.or.PATCHG==3) THEN
patch=ALWAYS_EXACT_PATCHING.or.C%MAGP%P%EXACT
CALL PATCH_FIB(C,X,k,PATCH,MY_TRUE)
ENDIF
IF(PATCHT/=0.AND.PATCHT/=2.AND.(K%TOTALPATH==0)) THEN
if(K%time) then
X(6)=X(6)-C%PATCH%a_T/c%beta0
else
X(6)=X(6)-C%PATCH%a_T
endif
ENDIF
CALL DTILTD(C%DIR,C%MAGP%P%TILTD,1,X)
! The magnet frame of reference is located here implicitely before misalignments
! CALL TRACK(C,X,EXACTMIS=K%EXACTMIS)
IF(C%MAGP%MIS) THEN
ou = ALWAYS_EXACTMIS !K%EXACTMIS.or.
CALL MIS_FIB(C,X,k,OU,DONEITT)
ENDIF
END SUBROUTINE TRACK_FIBRE_FRONTP
! back patch/misaglinments/tilt
SUBROUTINE TRACK_FIBRE_BACKR(C,X,K)
implicit none
logical(lp) :: doneitf=.false.
TYPE(FIBRE),TARGET,INTENT(INOUT):: C
! TYPE(BEAM),TARGET,INTENT(INOUT):: B
real(dp), INTENT(INOUT) :: X(6)
TYPE(INTERNAL_STATE) K
! TYPE(INTERNAL_STATE), INTENT(IN) :: K
logical(lp) ou,patch
INTEGER(2) PATCHT,PATCHG,PATCHE
TYPE (fibre), POINTER :: CN
real(dp), POINTER :: P0,B0
IF(ASSOCIATED(C%PATCH)) THEN
PATCHT=C%PATCH%TIME ;PATCHE=C%PATCH%ENERGY ;PATCHG=C%PATCH%PATCH;
ELSE
PATCHT=0 ; PATCHE=0 ;PATCHG=0;
ENDIF
IF(C%MAG%MIS) THEN
ou = ALWAYS_EXACTMIS !K%EXACTMIS.or.
CALL MIS_FIB(C,X,k,OU,DONEITF)
ENDIF
! The magnet frame of reference is located here implicitely before misalignments
CALL DTILTD(C%DIR,C%MAG%P%TILTD,2,X)
IF(PATCHT/=0.AND.PATCHT/=1.AND.(K%TOTALPATH==0)) THEN
if(K%time) then
X(6)=X(6)-C%PATCH%b_T/c%beta0
else
X(6)=X(6)-C%PATCH%b_T
endif
ENDIF
IF(PATCHG==2.or.PATCHG==3) THEN
patch=ALWAYS_EXACT_PATCHING.or.C%MAG%P%EXACT
CALL PATCH_FIB(C,X,k,PATCH,MY_FALSE)
ENDIF
! The CHART frame of reference is located here implicitely
IF(PATCHE/=0.AND.PATCHE/=1) THEN
NULLIFY(P0);NULLIFY(B0);
CN=>C%NEXT
IF(.NOT.ASSOCIATED(CN)) CN=>C
! P0=>CN%MAG%P%P0C
! B0=>CN%MAG%P%BETA0
P0=>CN%MAG%P%P0C
B0=>CN%BETA0
X(2)=X(2)*C%MAG%P%P0C/P0
X(4)=X(4)*C%MAG%P%P0C/P0
IF(k%TIME.or.recirculator_cheat)THEN
X(5)=root(1.0_dp+2.0_dp*X(5)/C%MAG%P%BETA0+X(5)**2) !X(5) = 1+DP/P0C_OLD
X(5)=X(5)*C%MAG%P%P0C/P0-1.0_dp !X(5) = DP/P0C_NEW
X(5)=(2.0_dp*X(5)+X(5)**2)/(root(1.0_dp/B0**2+2.0_dp*X(5)+X(5)**2)+1.0_dp/B0)
ELSE
X(5)=(1.0_dp+X(5))*C%MAG%P%P0C/P0-1.0_dp
ENDIF
ENDIF
END SUBROUTINE TRACK_FIBRE_BACKR
SUBROUTINE TRACK_FIBRE_BACKP(C,X,K)
implicit none
logical(lp) :: doneitf=.false.
TYPE(FIBRE),TARGET,INTENT(INOUT):: C
! TYPE(BEAM),TARGET,INTENT(INOUT):: B
type(real_8), INTENT(INOUT) :: X(6)
TYPE(INTERNAL_STATE) K
! TYPE(INTERNAL_STATE), INTENT(IN) :: K
logical(lp) ou,patch
INTEGER(2) PATCHT,PATCHG,PATCHE
TYPE (fibre), POINTER :: CN
real(dp), POINTER :: P0,B0
IF(ASSOCIATED(C%PATCH)) THEN
PATCHT=C%PATCH%TIME ;PATCHE=C%PATCH%ENERGY ;PATCHG=C%PATCH%PATCH;
ELSE
PATCHT=0 ; PATCHE=0 ;PATCHG=0;
ENDIF
IF(C%MAGP%MIS) THEN
ou = ALWAYS_EXACTMIS !K%EXACTMIS.or.
CALL MIS_FIB(C,X,k,OU,DONEITF)
ENDIF
! The magnet frame of reference is located here implicitely before misalignments
CALL DTILTD(C%DIR,C%MAGP%P%TILTD,2,X)
IF(PATCHT/=0.AND.PATCHT/=1.AND.(K%TOTALPATH==0)) THEN
if(K%time) then
X(6)=X(6)-C%PATCH%b_T/c%beta0
else
X(6)=X(6)-C%PATCH%b_T
endif
ENDIF
IF(PATCHG==2.or.PATCHG==3) THEN
patch=ALWAYS_EXACT_PATCHING.or.C%MAGP%P%EXACT
CALL PATCH_FIB(C,X,k,PATCH,MY_FALSE)
ENDIF
! The CHART frame of reference is located here implicitely
IF(PATCHE/=0.AND.PATCHE/=1) THEN
NULLIFY(P0);NULLIFY(B0);
CN=>C%NEXT
IF(.NOT.ASSOCIATED(CN)) CN=>C
! P0=>CN%MAGP%P%P0C
! B0=>CN%MAGP%P%BETA0
P0=>CN%MAGP%P%P0C
B0=>CN%BETA0
X(2)=X(2)*C%MAGP%P%P0C/P0
X(4)=X(4)*C%MAGP%P%P0C/P0
IF(k%TIME.or.recirculator_cheat)THEN
X(5)=sqrt(1.0_dp+2.0_dp*X(5)/C%BETA0+X(5)**2) !X(5) = 1+DP/P0C_OLD
X(5)=X(5)*C%MAGP%P%P0C/P0-1.0_dp !X(5) = DP/P0C_NEW
X(5)=(2.0_dp*X(5)+X(5)**2)/(sqrt(1.0_dp/B0**2+2.0_dp*X(5)+X(5)**2)+1.0_dp/B0)
ELSE
X(5)=(1.0_dp+X(5))*C%MAGP%P%P0C/P0-1.0_dp
ENDIF
ENDIF
END SUBROUTINE TRACK_FIBRE_BACKP
! thin lens tracking
SUBROUTINE TRACKV_NODE_SINGLE(T,V,K) !!
implicit none
TYPE(INTEGRATION_NODE),POINTER :: T
TYPE(INTERNAL_STATE) K
REAL(DP) SC,reference_ray(6),x(6)
type(three_d_info),intent(INOUT) :: v
TYPE(INTEGRATION_NODE),POINTER:: mag_in,mag_out
IF(.NOT.CHECK_STABLE) return
! CALL RESET_APERTURE_FLAG
! endif
if(abs(x(1))+abs(x(3))>absolute_aperture) then
messageLOST="exceed absolute_aperture in TRACKV_NODE_SINGLE"
lost_node=>t
lost_fibre=>t%parent_fibre
xlost=x
CHECK_STABLE=.false.
endif
x=V%X
reference_ray=V%reference_ray
CALL TRACK_NODE_SINGLE(T,V%X,K)
IF(.NOT.CHECK_STABLE) V%U(1)=.TRUE.
CALL TRACK_NODE_SINGLE(T,V%reference_ray,K)
IF(.NOT.CHECK_STABLE) V%U(2)=.TRUE.
IF(V%U(1).OR.V%U(2)) then
write(6,*) " Unstable in TRACKV_NODE_SINGLE ", V%U
RETURN
endif
IF(.NOT.ASSOCIATED(T%B)) THEN
WRITE(6,*) " NO FRAMES IN INTEGRATION NODES "
STOP 101
ENDIF
SC=1.0_dp
IF(v%SCALE/=0.0_dp) SC=v%SCALE
! t=>B%POS(1)%NODE%previous
V%r0=t%A+(reference_ray(1)-SC*reference_ray(1))*t%ENT(1,1:3)+ SC*X(1)*t%ENT(1,1:3)
V%r0=v%r0+(reference_ray(3)-SC*reference_ray(3))*t%ENT(2,1:3)+ SC*X(3)*t%ENT(2,1:3)
V%r=t%B+(V%reference_ray(1)-SC*V%reference_ray(1))*t%EXI(1,1:3)+ SC*V%X(1)*t%EXI(1,1:3)
V%r=v%r+(V%reference_ray(3)-SC*V%reference_ray(3))*t%EXI(2,1:3)+ SC*V%X(3)*t%EXI(2,1:3)
mag_in=>t%parent_fibre%t1%next%next
mag_out=>t%parent_fibre%t2%previous%previous
v%a=mag_in%a
v%ent=mag_in%ent
v%b=mag_in%b
v%exi=mag_in%exi
v%o=t%B
v%mid=t%exi
IF(MAG_IN%PREVIOUS%CAS/=CASE1) STOP 201
IF(MAG_OUT%NEXT%CAS/=CASE2) STOP 202
END SUBROUTINE TRACKV_NODE_SINGLE
SUBROUTINE TRACKR_NODE_SINGLE(T,X,K) !!
! This routines tracks a single thin lens
! it is supposed to reproduce plain PTC
implicit none
TYPE(INTEGRATION_NODE), TARGET, INTENT(INOUT):: T
REAL(DP),INTENT(INOUT):: X(6)
TYPE(INTERNAL_STATE) K
! TYPE(INTERNAL_STATE), INTENT(IN) :: K
type(element),pointer :: el
IF(.NOT.CHECK_STABLE) return
! CALL RESET_APERTURE_FLAG
! endif
if(abs(x(1))+abs(x(3))>absolute_aperture) then !.or.(.not.CHECK_MADX_APERTURE)) then
messageLOST="exceed absolute_aperture in TRACKR_NODE_SINGLE"
lost_node=>t
lost_fibre=>t%parent_fibre
xlost=x
CHECK_STABLE=.false.
endif
! T%PARENT_FIBRE%MAG=K
T%PARENT_FIBRE%MAG%P%DIR=>T%PARENT_FIBRE%DIR
T%PARENT_FIBRE%MAG%P%beta0=>T%PARENT_FIBRE%beta0
T%PARENT_FIBRE%MAG%P%GAMMA0I=>T%PARENT_FIBRE%GAMMA0I
T%PARENT_FIBRE%MAG%P%GAMBET=>T%PARENT_FIBRE%GAMBET
T%PARENT_FIBRE%MAG%P%MASS=>T%PARENT_FIBRE%MASS
T%PARENT_FIBRE%MAG%P%CHARGE=>T%PARENT_FIBRE%CHARGE
!call cpu_time(ttime1)
!dt1=ttime1-ttime0+dt1
SELECT CASE(T%CAS)
CASE(CASEP1)
CALL TRACK_FIBRE_FRONT(T%PARENT_FIBRE,X,K)
if(associated(T%PARENT_FIBRE%MAG%p%aperture)) call CHECK_APERTURE(T%PARENT_FIBRE%MAG%p%aperture,X)
CASE(CASEP2)
CALL TRACK_FIBRE_BACK(T%PARENT_FIBRE,X,K)
CASE(CASE1,CASE2)
el=>T%PARENT_FIBRE%MAG
if(s_aperture_CHECK.and.associated(el%p%A).AND.CHECK_MADX_APERTURE.and.t%cas==case2) &
call check_S_APERTURE_out(el%p,t%POS_IN_FIBRE-2,x)
SELECT CASE(EL%KIND)
CASE(KIND0:KIND1,KIND3,KIND8:KIND9,KIND11:KIND15,KIND18:KIND19,kind22)
case(KIND2)
CALL TRACK_FRINGE(EL=EL%K2,X=X,k=k,J=T%CAS)
case(KIND4)
IF(T%CAS==CASE1) THEN
CALL ADJUST_TIME_CAV4(EL%C4,X,k,1)
CALL FRINGECAV(EL%C4,X,k=k,J=1)
ELSE
CALL FRINGECAV(EL%C4,X,k=k,J=2)
CALL ADJUST_TIME_CAV4(EL%C4,X,k,2)
ENDIF
case(KIND5)
CALL TRACK_FRINGE(EL5=EL%S5,X=X,k=k,J=T%CAS)
case(KIND6)
CALL TRACK_FRINGE(EL6=EL%T6,X=X,k=k,J=T%CAS)
case(KIND7)
CALL TRACK_FRINGE(EL7=EL%T7,X=X,k=k,J=T%CAS)
case(KIND10)
CALL FRINGE_teapot(EL%TP10,X,k=k,j=T%CAS)
case(KIND16,KIND20)
CALL fringe_STREX(EL%K16,X,k,T%CAS)
case(KIND17)
STOP 317
case(KIND21)
CALL FRINGE_CAV_TRAV(EL%CAV21,X=X,k=k,J=T%CAS)
CALL ADJUST_TIME_CAV_TRAV_OUT(EL%CAV21,X,k,T%CAS) ! ONLY DOES SOMETHING IF J==2
case(KINDWIGGLER)
CALL ADJUST_WI(EL%WI,X,T%CAS) ! ONLY DOES SOMETHING IF J==2
case(KINDPA)
CALL ADJUST_PANCAKE(EL%PA,X,k,T%CAS)
CASE DEFAULT
WRITE(6,*) "NOT IMPLEMENTED ",EL%KIND
stop 666
END SELECT
CASE(CASE0)
el=>T%PARENT_FIBRE%MAG
if(s_aperture_CHECK.and.associated(el%p%A).AND.CHECK_MADX_APERTURE) &
call check_S_APERTURE(el%p,t%POS_IN_FIBRE-2,x)
if(associated(t%bb).and.dobb.and.do_beam_beam) then
if(t%bb%patch) call PATCH_BB(t%bb,X,k,EL%p%BETA0,ALWAYS_EXACT_PATCHING.or.EL%P%EXACT,my_true)
call BBKICK(t%bb,X)
if(t%bb%patch)call PATCH_BB(t%bb,X,k,EL%p%BETA0,ALWAYS_EXACT_PATCHING.or.EL%P%EXACT,my_false)
endif
SELECT CASE(EL%KIND)
CASE(KIND0)
case(KIND1)
CALL TRACK_SLICE(EL%D0,X,K)
case(KIND2)
CALL TRACK_SLICE(EL%K2,X,K,t%POS_IN_FIBRE-2)
case(KIND3)
CALL TRACK(EL%K3,X,K)
case(KIND4)
CALL TRACK_SLICE(EL%C4,X,K,t%POS_IN_FIBRE-2)
case(KIND5)
CALL TRACK_SLICE(EL%S5,X,K)
case(KIND6)
CALL TRACK_SLICE(EL%T6,X,K)
case(KIND7)
CALL TRACK_SLICE(EL%T7,X,K,t%POS_IN_FIBRE-2)
case(KIND8)
CALL TRACK(EL%S8,X,K)
case(KIND9)
CALL TRACK(EL%S9,X,K)
case(KIND10)
CALL TRACK_SLICE(EL%TP10,X,K,t%POS_IN_FIBRE-2)
case(KIND11:KIND14)
CALL MONTI(EL%MON14,X,k,t%POS_IN_FIBRE-2)
! CALL TRACK_SLICE(EL%MON14,X,K)
case(KIND15)
call SEPTTRACK(EL%SEP15,X,k,t%POS_IN_FIBRE-2)
! CALL TRACK_SLICE(EL%SEP15,X,K)
case(KIND16,KIND20)
CALL TRACK_SLICE(EL%K16,X,K,t%POS_IN_FIBRE-2)
case(KIND17)
STOP 317
case(KIND18)
call RCOLLIMATORI(EL%RCOL18,X,k,t%POS_IN_FIBRE-2)
case(KIND19)
CALL ECOLLIMATORI(EL%ECOL19,X,k,t%POS_IN_FIBRE-2)
! CALL TRACK_SLICE(EL%ECOL19,X,K)
case(KIND21)
CALL TRACK_SLICE(EL%CAV21,X,k,t%POS_IN_FIBRE-2)
case(KIND22)
CALL TRACK_SLICE(EL%he22,X,k,t%POS_IN_FIBRE-2)
case(KINDWIGGLER)
CALL TRACK_SLICE(EL%WI,X,k,t%POS_IN_FIBRE-2)
case(KINDPA)
CALL TRACK_SLICE(EL%PA,X,k,T%POS_IN_FIBRE-2)
CASE DEFAULT
WRITE(6,*) "NOT IMPLEMENTED ",EL%KIND
stop 999
END SELECT
if(associated(T%PARENT_FIBRE%MAG%p%aperture).and.aperture_all_case0) &
call CHECK_APERTURE(T%PARENT_FIBRE%MAG%p%aperture,X)
case(CASET)
if(associated(t%bb).and.dobb.and.do_beam_beam) then
if(t%bb%patch) call PATCH_BB(t%bb,X,k,EL%p%BETA0,ALWAYS_EXACT_PATCHING.or.EL%P%EXACT,my_true)
call BBKICK(t%bb,X)
if(t%bb%patch)call PATCH_BB(t%bb,X,k,EL%p%BETA0,ALWAYS_EXACT_PATCHING.or.EL%P%EXACT,my_false)
endif
IF(ASSOCIATED(T%T)) CALL TRACK(T%T,X)
case(CASETF1,CASETF2)
IF(ASSOCIATED(T%T)) CALL TRACK(T%T,X)
END SELECT
! CASE(CASE100) ! FAKE BEAM BEAM CAKE AT SOME S
! T%PARENT_FIBRE%MAG=DEFAULT
if(wherelost==2.and.(.not.check_stable)) then
t%lost=t%lost+1
endif
END SUBROUTINE TRACKR_NODE_SINGLE
SUBROUTINE TRACKP_NODE_SINGLE(T,X,K) !!
! This routines tracks a single thin lens
! it is supposed to reproduce plain PTC
implicit none
TYPE(INTEGRATION_NODE), TARGET, INTENT(INOUT):: T
TYPE(REAL_8),INTENT(INOUT):: X(6)
TYPE(INTERNAL_STATE) K
! TYPE(INTERNAL_STATE), INTENT(IN) :: K
type(elementp),pointer :: el
logical(lp) BN2,L
logical(lp) CHECK_KNOB
integer(2), pointer,dimension(:)::AN,BN
IF(.NOT.CHECK_STABLE) return
! CALL RESET_APERTURE_FLAG
! endif
if(abs(x(1))+abs(x(3))>absolute_aperture) then
messageLOST="exceed absolute_aperture in TRACKP_NODE_SINGLE"
lost_node=>t
lost_fibre=>t%parent_fibre
xlost=x
CHECK_STABLE=.false.
endif
! T%PARENT_FIBRE%MAGP=K
IF(K%PARA_IN ) KNOB=.TRUE.
T%PARENT_FIBRE%MAGP%P%DIR=>T%PARENT_FIBRE%DIR
T%PARENT_FIBRE%MAGP%P%beta0=>T%PARENT_FIBRE%beta0
T%PARENT_FIBRE%MAGP%P%GAMMA0I=>T%PARENT_FIBRE%GAMMA0I
T%PARENT_FIBRE%MAGP%P%GAMBET=>T%PARENT_FIBRE%GAMBET
T%PARENT_FIBRE%MAGP%P%MASS=>T%PARENT_FIBRE%MASS
T%PARENT_FIBRE%MAGP%P%CHARGE=>T%PARENT_FIBRE%CHARGE
SELECT CASE(T%CAS)
CASE(CASEP1)
CALL TRACK_FIBRE_FRONT(T%PARENT_FIBRE,X,K)
if(associated(T%PARENT_FIBRE%MAGP%p%aperture)) call CHECK_APERTURE(T%PARENT_FIBRE%MAGP%p%aperture,X)
CASE(CASEP2)
! if(abs(x(1))+abs(x(3))>absolute_aperture.or.(.not.CHECK_MADX_APERTURE)) then ! new 2010
! CHECK_STABLE=.false.
! endif
CALL TRACK_FIBRE_BACK(T%PARENT_FIBRE,X,K)
CASE(CASE1,CASE2)
el=>T%PARENT_FIBRE%MAGP
if(s_aperture_CHECK.and.associated(el%p%A).AND.CHECK_MADX_APERTURE.and.t%cas==case2) &
call check_S_APERTURE_out(el%p,t%POS_IN_FIBRE-2,x)
SELECT CASE(EL%KIND)
CASE(KIND0:KIND1,KIND3,KIND8:KIND9,KIND11:KIND15,KIND18:KIND19,kind22)
case(KIND2)
CALL TRACK_FRINGE(EL=EL%K2,X=X,k=k,J=T%CAS)
case(KIND4)
IF(T%CAS==CASE1) THEN
CALL ADJUST_TIME_CAV4(EL%C4,X,k,1)
CALL FRINGECAV(EL%C4,X,k=k,J=1)
ELSE
CALL FRINGECAV(EL%C4,X,k=k,J=2)
CALL ADJUST_TIME_CAV4(EL%C4,X,k,2)
ENDIF
case(KIND5)
CALL TRACK_FRINGE(EL5=EL%S5,X=X,k=k,J=T%CAS)
case(KIND6)
CALL TRACK_FRINGE(EL6=EL%T6,X=X,k=k,J=T%CAS)
case(KIND7)
CALL TRACK_FRINGE(EL7=EL%T7,X=X,k=k,J=T%CAS)
case(KIND10)
CALL FRINGE_teapot(EL%TP10,X,k,T%CAS)
case(KIND16,KIND20)
CALL fringe_STREX(EL%K16,X,k,T%CAS)
case(KIND17)
STOP 317
case(KIND21)
CALL FRINGE_CAV_TRAV(EL%CAV21,X=X,k=k,J=T%CAS)
CALL ADJUST_TIME_CAV_TRAV_OUT(EL%CAV21,X,k,T%CAS) ! ONLY DOES SOMETHING IF J==2
case(KINDWIGGLER)
CALL ADJUST_WI(EL%WI,X,T%CAS) ! ONLY DOES SOMETHING IF J==2
case(KINDPA)
CALL ADJUST_PANCAKE(EL%PA,X,k,T%CAS) ! ONLY DOES SOMETHING IF J==2
CASE DEFAULT
WRITE(6,*) "NOT IMPLEMENTED ",EL%KIND
stop 666
END SELECT
CASE(CASE0)
el=>T%PARENT_FIBRE%MAGP
if(s_aperture_CHECK.and.associated(el%p%A).AND.CHECK_MADX_APERTURE) &
call check_S_APERTURE(el%p,t%POS_IN_FIBRE-2,x)
if(associated(t%bb).and.dobb.and.do_beam_beam) then
if(t%bb%patch) call PATCH_BB(t%bb,X,k,EL%p%BETA0,ALWAYS_EXACT_PATCHING.or.EL%P%EXACT,my_true)
call BBKICK(t%bb,X)
if(t%bb%patch)call PATCH_BB(t%bb,X,k,EL%p%BETA0,ALWAYS_EXACT_PATCHING.or.EL%P%EXACT,my_false)
endif
SELECT CASE(EL%KIND)
CASE(KIND0)
case(KIND1)
CALL TRACK_SLICE(EL%D0,X,K)
case(KIND2)
CALL TRACK_SLICE(EL%K2,X,K,t%POS_IN_FIBRE-2)
case(KIND3)
CALL TRACK(EL%K3,X,K)
case(KIND4)
CALL TRACK_SLICE(EL%C4,X,K,t%POS_IN_FIBRE-2)
case(KIND5)
CALL TRACK_SLICE(EL%S5,X,K)
case(KIND6)
CALL TRACK_SLICE(EL%T6,X,K)
case(KIND7)
IF((EL%T7%BN(2)%KIND==3.OR.EL%T7%L%KIND==3).AND.KNOB) THEN
CALL GETMAT7(EL%T7) ! RECOMPUTES ONLY IF KNOB (SPEED)
ENDIF
CALL TRACK_SLICE(EL%T7,X,K,t%POS_IN_FIBRE-2)
IF(KNOB) THEN
BN2=.FALSE.
L=.FALSE.
IF(EL%T7%BN(2)%KIND==3) THEN
BN2=.TRUE.
ENDIF
IF(EL%T7%L%KIND==3) THEN
L=.TRUE.
ENDIF
IF(BN2.OR.L) THEN
EL%T7%BN(2)%KIND=1
EL%T7%L%KIND=1
CALL KILL(EL%T7) ! RECOMPUTES ONLY IF KNOB (SPEED)
CALL ALLOC(EL%T7) ! KNOB IS REMOVED THE SLOW WAY(SPEED)
CALL GETMAT7(EL%T7)
IF(BN2) EL%T7%BN(2)%KIND=3
IF(L) EL%T7%L%KIND=3
ENDIF
ENDIF
case(KIND8)
CALL TRACK(EL%S8,X,K)
case(KIND9)
CALL TRACK(EL%S9,X,K)
case(KIND10)
CALL MAKEPOTKNOB(EL%TP10,CHECK_KNOB,AN,BN)
CALL TRACK_SLICE(EL%TP10,X,K,t%POS_IN_FIBRE-2)
CALL UNMAKEPOTKNOB(EL%TP10,CHECK_KNOB,AN,BN)
case(KIND11:KIND14)
CALL MONTI(EL%MON14,X,k,t%POS_IN_FIBRE-2)
! CALL TRACK_SLICE(EL%MON14,X,K)
case(KIND15)
call SEPTTRACK(EL%SEP15,X,k,t%POS_IN_FIBRE-2)
! CALL TRACK_SLICE(EL%SEP15,X,K)
case(KIND16,KIND20)
CALL TRACK_SLICE(EL%K16,X,K,t%POS_IN_FIBRE-2)
case(KIND17)
STOP 317
case(KIND18)
call RCOLLIMATORI(EL%RCOL18,X,k,t%POS_IN_FIBRE-2)
! CALL TRACK_SLICE(EL%RCOL18,X,K)
case(KIND19)
CALL ECOLLIMATORI(EL%ECOL19,X,k,t%POS_IN_FIBRE-2)
! CALL TRACK_SLICE(EL%ECOL19,X,K)
case(KIND21)
CALL TRACK_SLICE(EL%CAV21,X,k,t%POS_IN_FIBRE-2)
case(KINDWIGGLER)
CALL TRACK_SLICE(EL%WI,X,k,t%POS_IN_FIBRE-2)
case(KIND22)
CALL TRACK_SLICE(EL%he22,X,k,t%POS_IN_FIBRE-2)
case(KINDPA)
CALL TRACK_SLICE(EL%PA,X,k,T%POS_IN_FIBRE-2)
CASE DEFAULT
WRITE(6,*) "NOT IMPLEMENTED ",EL%KIND
stop 999
END SELECT
if(associated(T%PARENT_FIBRE%MAG%p%aperture).and.aperture_all_case0) &
call CHECK_APERTURE(T%PARENT_FIBRE%MAG%p%aperture,X)
case(CASET)
if(associated(t%bb).and.dobb.and.do_beam_beam) then
if(t%bb%patch) call PATCH_BB(t%bb,X,k,EL%p%BETA0,ALWAYS_EXACT_PATCHING.or.EL%P%EXACT,my_true)
call BBKICK(t%bb,X)
if(t%bb%patch)call PATCH_BB(t%bb,X,k,EL%p%BETA0,ALWAYS_EXACT_PATCHING.or.EL%P%EXACT,my_false)
endif
IF(ASSOCIATED(T%T)) CALL TRACK(T%T,X)
case(CASETF1,CASETF2)
IF(ASSOCIATED(T%T)) CALL TRACK(T%T,X)
END SELECT
! CASE(CASE100) ! FAKE BEAM BEAM CAKE AT SOME S
! T%PARENT_FIBRE%MAGP=DEFAULT
! KNOB IS RETURNED TO THE PTC DEFAULT
! NEW STUFF WITH KIND=3
KNOB=.FALSE.
! END NEW STUFF WITH KIND=3
END SUBROUTINE TRACKP_NODE_SINGLE
! STUFF ABOUT LIST AND STRUCTURES
SUBROUTINE MAKE_NODE_LAYOUT( R) !
! Creates the thin layout and puts in R%T by calling MAKE_NODE_LAYOUT_2
! At this point large patches would be problematic; i.e. |d(3)|>>>0 .
implicit none
TYPE (LAYOUT), TARGET :: R
call MAKE_NODE_LAYOUT_2( R,R%T )
end SUBROUTINE MAKE_NODE_LAYOUT
SUBROUTINE sum_ds_ac( R,ds_ac_tot) !
! computes the total length for AC-modulation
implicit none
TYPE (LAYOUT), TARGET :: R
TYPE (NODE_LAYOUT), pointer :: L
INTEGER I
TYPE(INTEGRATION_NODE), POINTER :: T
REAL(DP), intent(inout) :: ds_ac_tot
t=>r%t%start
ds_ac_tot=0.0_dp
do i=1,r%t%n
ds_ac_tot=ds_ac_tot+t%ds_ac
t=>t%next
enddo
end SUBROUTINE sum_ds_ac
SUBROUTINE MAKE_NODE_LAYOUT_2( R,L ) !
! Creates a thin layout.
! At this point large patches would be problematic; i.e. |d(3)|>>>0 .
implicit none
TYPE (LAYOUT), TARGET :: R
TYPE (NODE_LAYOUT), pointer :: L
TYPE(FIBRE), POINTER :: P
INTEGER I,J,k,TEAPOT_LIKE
REAL(DP) S,DLD,DL,LI,SL
LOGICAL(LP) CIRCULAR
TYPE(INTEGRATION_NODE), POINTER :: T1,T2,TM
CASE_NAME(CASEP1)="THE ENTRANCE PATCH"
CASE_NAME(CASEP2)="THE EXIT PATCH "
CASE_NAME(CASE1)= "THE ENTRANCE FRINGE"
CASE_NAME(CASE2)="THE EXIT FRINGE"
CASE_NAME(CASE0)="A STEP OF INTEGRATION BODY"
! CASE_NAME(CASE3)="BEAM BEAM PANCAKE"
if(associated(L)) then
CALL kill_NODE_LAYOUT(L)
NULLIFY(L);
endif
allocate(L)
CALL Set_Up_NODE_LAYOUT( L )
S=0.0_dp
SL=0.0_dp ! INTEGRATION LENGTH
P=>R%START
k=1
DO I=1,R%N
TEAPOT_LIKE=0
IF(P%MAG%P%B0/=0.0_dp) TEAPOT_LIKE=1
IF(P%MAG%KIND==KIND16.OR.P%MAG%KIND==KIND16)TEAPOT_LIKE=0
IF(P%MAG%KIND==KIND0.AND.P%MAG%P%NST/=1) THEN
WRITE(6,*) "MARKER SHOULD HAVE NST=1 OTHERWISE PROBLEMS "
WRITE(6,*) "WILL OCCUR WITH THE WORM AND THE NODE_LAYOUT SURVEY "
STOP 500
ENDIF
IF(P%DIR==1) THEN
LI=0.0_dp;
ELSE
LI=P%MAG%L;
ENDIF
DL=P%DIR*P%MAG%L/P%MAG%P%NST
DLD=P%MAG%P%LD/P%MAG%P%NST
CALL APPEND_EMPTY_THIN( L )
L%END%TEAPOT_LIKE=TEAPOT_LIKE
L%END%S(1)=S;L%END%S(2)=LI;L%END%S(3)=SL;L%END%S(4)=0.0_dp; ! s(1) total ld
L%END%S(5)=0.0_dp;L%END%DS_AC=0.0_dp;
T1=>L%END ! s(2) local integration distance
! s(3) total integration distance
L%END%CAS=CASEP1 ! s(4) end of step = DL
L%END%pos_in_fibre=1
L%END%pos=k;k=k+1;
L%END%PARENT_NODE_LAYOUT=>L
L%END%PARENT_FIBRE=>P
CALL APPEND_EMPTY_THIN( L )
L%END%TEAPOT_LIKE=TEAPOT_LIKE
L%END%S(1)=S;L%END%S(2)=LI;L%END%S(3)=SL;L%END%S(4)=0.0_dp;L%END%S(5)=0.0_dp;L%END%DS_AC=0.0_dp;
L%END%CAS=CASE1
L%END%pos_in_fibre=2
L%END%pos=k;k=k+1;
L%END%PARENT_NODE_LAYOUT=>L
L%END%PARENT_FIBRE=>P
DO J=1,P%MAG%P%NST
CALL APPEND_EMPTY_THIN( L )
L%END%TEAPOT_LIKE=TEAPOT_LIKE
L%END%S(1)=S;L%END%S(2)=LI;L%END%S(3)=SL;L%END%S(4)=DL;L%END%S(5)=DLD;L%END%ds_ac=DLD;
L%END%CAS=CASE0
L%END%pos_in_fibre=J+2
L%END%pos=k;k=k+1;
L%END%PARENT_NODE_LAYOUT=>L
L%END%PARENT_FIBRE=>P
S=S+DLD
LI=LI+DL
SL=SL+P%DIR*DL
IF(MOD(P%MAG%P%NST,2)==0) THEN
IF(J==P%MAG%P%NST/2) TM=>L%END !+1
ELSE
IF(J==1) TM=>T1
ENDIF
ENDDO
CALL APPEND_EMPTY_THIN( L )
L%END%TEAPOT_LIKE=TEAPOT_LIKE
L%END%S(1)=S;L%END%S(2)=LI;L%END%S(3)=SL;L%END%S(4)=0.0_dp;L%END%S(5)=0.0_dp;L%END%DS_AC=0.0_dp;
L%END%CAS=CASE2
L%END%pos_in_fibre=P%MAG%P%NST+3
L%END%pos=k;k=k+1;
L%END%PARENT_FIBRE=>P
CALL APPEND_EMPTY_THIN( L )
L%END%TEAPOT_LIKE=TEAPOT_LIKE
L%END%S(1)=S;L%END%S(2)=LI;L%END%S(3)=SL;L%END%S(4)=0.0_dp;L%END%S(5)=0.0_dp;L%END%DS_AC=0.0_dp;
L%END%CAS=CASEP2
L%END%pos_in_fibre=P%MAG%P%NST+4
L%END%pos=k;k=k+1;
L%END%PARENT_NODE_LAYOUT=>L
L%END%PARENT_FIBRE=>P
T2=>L%END
P%T1=>T1
P%T2=>T2
P%TM=>TM
P=>P%NEXT
ENDDO
L%N=k-1
L%PARENT_LAYOUT=>R
IF(R%CLOSED) THEN
l%closed=.true.
CIRCULAR=.TRUE.
CALL RING_L_THIN(L,CIRCULAR)
ENDIF
if(lielib_print(12)==1) call stat_NODE_LAYOUT(l)
END SUBROUTINE MAKE_NODE_LAYOUT_2
SUBROUTINE stat_NODE_LAYOUT( L )
implicit none
TYPE (NODE_LAYOUT), pointer :: L
WRITE(6,*) " PARENT LAYOUT NAME :", L%PARENT_LAYOUT%NAME(1:len_trim(L%PARENT_LAYOUT%NAME))
WRITE(6,*) " NUMBER OF ORIGINAL LAYOUT ELEMENTS :", L%PARENT_LAYOUT%N
WRITE(6,*) " NUMBER OF THIN OBJECTS :", L%N
WRITE(6,*) " TOTAL IDEAL LENGTH OF STRUCTURE :", L%END%S(1)
WRITE(6,*) " TOTAL INTEGRATION LENGTH OF STRUCTURE (mad8 style survey) :", L%END%S(3)
end SUBROUTINE stat_NODE_LAYOUT
SUBROUTINE DRIFT_TO_TIME(T,YL,DT,X,k)
! Drifts to a given time using either a regular or TEAPOT drift. (Cylindrical coordinate drift)
! The amount of the drift YL is computed to achieve a time DT.
IMPLICIT NONE
real(dp),INTENT(INOUT):: X(6)
real(dp),INTENT(INOUT):: YL
real(dp),INTENT(IN):: DT
TYPE(INTEGRATION_NODE), pointer :: T
TYPE(magnet_chart), pointer :: p
real(dp) PZ
real(dp) b
TYPE(INTERNAL_STATE) k !,OPTIONAL :: K
P=>T%PARENT_FIBRE%MAG%P
IF(k%TIME) then
B=P%BETA0
ELSE
B=1.0_dp
ENDIF
! if(P%B0/=zero.AND.T%TEAPOT_LIKE==1) then
!
! PZ=ROOT(one+two*x(5)/b+X(5)**2-X(2)**2-X(4)**2)
! R=one/P%B0
! A=(X(1)+R)*(one/b+x(5))/PZ
! A=ATAN(DT/(A+DT*X(2)/PZ) )
! YL=A/P%B0
! PT=one-X(2)*TAN(A)/PZ
! XN(1)=(X(1)+R)/COS(A)/PT-R
! XN(2)=X(2)*COS(A)+SIN(A)*PZ
! XN(3)=X(3)+X(4)*(X(1)+R)*TAN(A)/PZ/PT
! XN(6)=X(6)+(X(1)+R)*TAN(A)/PZ/PT*(one/b+x(5))
! X(1)=XN(1)
! X(2)=XN(2)
! X(3)=XN(3)
! X(6)=XN(6)
! else
PZ=ROOT(1.0_dp+2.0_dp*X(5)/b+x(5)**2-X(2)**2-X(4)**2)
YL=DT/(1.0_dp/b+X(5))*PZ
X(1)=X(1)+YL*X(2)/PZ
X(3)=X(3)+YL*X(4)/PZ
X(6)=X(6)+YL*(1.0_dp/b+X(5))/PZ
! endif
END SUBROUTINE DRIFT_TO_TIME
SUBROUTINE DRIFTr_BACK_TO_POSITION(T,YL,X,k)
! This is a regular drift
! It is used in time tracking to project back to the beginning of the thin lens
! and it is used in S tracking to drift in the middle of a step.
IMPLICIT NONE
real(dp),INTENT(INOUT):: X(6)
real(dp),INTENT(IN):: YL
TYPE(INTEGRATION_NODE), pointer :: T
! TYPE(magnet_chart), pointer :: p
! TYPE(magnet_chart), pointer :: p
real(dp) PZ
real(dp) b
TYPE(INTERNAL_STATE) k !,OPTIONAL :: K
! P=>T%PARENT_FIBRE%MAG%P
IF(k%TIME) then
B=T%PARENT_FIBRE%BETA0
ELSE
B=1.0_dp
ENDIF
! if(P%B0/=zero.AND.T%TEAPOT_LIKE==1) then
! PZ=ROOT(one+two*x(5)/b+X(5)**2-X(2)**2-X(4)**2)
! R=one/P%B0
! A=-YL*P%B0
! PT=one-X(2)*TAN(A)/PZ
! XN(1)=(X(1)+R*(two*sin(a/two)**2+X(2)*sin(A)/PZ))/COS(A)/PT
! XN(2)=X(2)*COS(A)+SIN(A)*PZ
! XN(3)=X(3)+X(4)*(X(1)+R)*TAN(A)/PZ/PT
! XN(6)=X(6)+(X(1)+R)*TAN(A)/PZ/PT*(one/b+x(5))
! WRITE(6,*) "XN(6)-X(6)-DT , DT",DT,XN(6)-X(6)-DT
! X(1)=XN(1)
! X(2)=XN(2)
! X(3)=XN(3)
! X(6)=XN(6)
! else
! CALL DRIFT(YL,DL,P%beta0,1,P%EXACT,P%TIME,X)
PZ=ROOT(1.0_dp+2.0_dp*X(5)/b+x(5)**2-X(2)**2-X(4)**2)
X(1)=X(1)-YL*X(2)/PZ
X(3)=X(3)-YL*X(4)/PZ
X(6)=X(6)-YL*(1.0_dp/b+X(5))/PZ
! endif
END SUBROUTINE DRIFTr_BACK_TO_POSITION
SUBROUTINE DRIFTp_BACK_TO_POSITION(T,YL,X,k)
! This is a regular drift
! It is used in time tracking to project back to the beginning of the thin lens
! and it is used in S tracking to drift in the middle of an step.
IMPLICIT NONE
type(real_8),INTENT(INOUT):: X(6)
real(dp),INTENT(IN):: YL
TYPE(INTEGRATION_NODE), pointer :: T
TYPE(magnet_chart), pointer :: p
type(real_8) XN(6),PZ,PT
real(dp) b
TYPE(INTERNAL_STATE) k !,OPTIONAL :: K
P=>T%PARENT_FIBRE%MAG%P
IF(k%TIME) then
B=P%BETA0
ELSE
B=1.0_dp
ENDIF
call alloc(xn,6); call alloc(pz,pt);
! if(P%B0/=zero.AND.T%TEAPOT_LIKE==1) then
! PZ=sqrt(one+two*x(5)/b+X(5)**2-X(2)**2-X(4)**2)
! R=one/P%B0
! A=-YL*P%B0
! PT=one-X(2)*TAN(A)/PZ
! XN(1)=(X(1)+R*(two*sin(a/two)**2+X(2)*sin(A)/PZ))/COS(A)/PT
! XN(2)=X(2)*COS(A)+SIN(A)*PZ
! XN(3)=X(3)+X(4)*(X(1)+R)*TAN(A)/PZ/PT
! XN(6)=X(6)+(X(1)+R)*TAN(A)/PZ/PT*(one/b+x(5))
! WRITE(6,*) "XN(6)-X(6)-DT , DT",DT,XN(6)-X(6)-DT
! X(1)=XN(1)
! X(2)=XN(2)
! X(3)=XN(3)
! X(6)=XN(6)
! else
! CALL DRIFT(YL,DL,P%beta0,1,P%EXACT,P%TIME,X)
PZ=sqrt(1.0_dp+2.0_dp*X(5)/b+x(5)**2-X(2)**2-X(4)**2)
X(1)=X(1)-YL*X(2)/PZ
X(3)=X(3)-YL*X(4)/PZ
X(6)=X(6)-YL*(1.0_dp/b+X(5))/PZ
! endif
call kill(xn,6); call kill(pz,pt);
END SUBROUTINE DRIFTp_BACK_TO_POSITION
! Survey still worm like
SUBROUTINE FILL_SURVEY_DATA_IN_NODE_LAYOUT(R)
! THIS SUBROUTINE ALLOCATES NODE FRAMES IF NEEDED
! IT SURVEYS THE NODES USING THE OLD REAL WORMS
! SHOULD BE CALLED AFTER MISALIGNMENTS OR MOVING PART OF LATTICE
IMPLICIT NONE
type(layout),target:: r
type(fibre), pointer ::c
type(INTEGRATION_NODE), pointer ::t
type(worm) vers
integer k,ic,j
real(dp) x(6),ent(3,3),a(3)
LOGICAL(LP) APER
aper=APERTURE_FLAG
APERTURE_FLAG=.FALSE.
if(.not.associated(r%t)) call MAKE_NODE_LAYOUT(r)
CALL allocate_node_frame( R)
call survey(r)
CALL ALLOC(vers,r)
C=>r%START
CALL XFRAME(vers%E,C%chart%f%ent,C%chart%f%A,-7) ! initializes the survey part of worm
vers%E%L(-1)=0.d0 !Starts beam line at z=0 fake distance along ld for cheap work
do k=1,r%n
x=0.0_dp
CALL TRACK(r,x,k,k+1,default,vers)
if(.not.check_stable) then
Write(6,*) " fake instability at ",c%mag%name, " ",k
check_stable=.true.
CALL RESET_APERTURE_FLAG
endif
t=>c%t1
j=-6
call gMID(vers,x,j)
call G_FRAME(vers%e,ENT,A,j)
t%ent=ent
t%a=a
t=>t%next
if(t%cas/=case1) then
write(6,*)" error in fill_survey_data_in_NODE_LAYOUT",j,t%cas
stop 665
endif
j=vers%POS(2)
call gMID(vers,x,j)
call G_FRAME(vers%e,ENT,A,j)
t%ent=ent
t%a=a
t%previous%exi=ent
t%previous%b=a
t=>t%next
ic=0
DO J=vers%POS(2)+1,vers%POS(3)-1 ! pos(2)+1 to pos(3)-1 inside the magnet
ic=ic+1
call gMID(vers,x,j)
call G_FRAME(vers%e,ENT,A,j)
if(j/=vers%POS(2)+1) then
t%previous%exi=ent
t%previous%b=a
if(t%previous%cas/=case0) then
write(6,*)" error in fill_survey_data_in_NODE_LAYOUT",j,t%previous%cas
stop 666
endif
else
t%previous%exi=ent
t%previous%b=a
if(t%previous%cas/=case1) then
write(6,*)" error in fill_survey_data_in_NODE_LAYOUT",j,t%previous%cas
stop 664
endif
endif
if(j/=vers%POS(3)-1) then
t%ent=ent
t%a=a
if(t%cas/=case0) then
write(6,*)" error in fill_survey_data_in_NODE_LAYOUT",j,t%cas
stop 666
endif
else
t%ent=ent
t%a=a
if(t%cas/=case2) then
write(6,*)" error in fill_survey_data_in_NODE_LAYOUT",j,t%cas
write(6,*)t%POS,T%PARENT_FIBRE%MAG%NAME
write(6,*)T%PARENT_FIBRE%T1%POS,T%PARENT_FIBRE%T2%POS
stop 668
endif
endif
! omega(1)= a(1)+scale*(xr(1)*ent(1,1)+xr(3)*ent(2,1))
! omega(2)= a(2)+scale*(xr(1)*ent(1,2)+xr(3)*ent(2,2))
! omega(3)= a(3)+scale*(xr(1)*ent(1,3)+xr(3)*ent(2,3))
! r1(1)=omega0(3)
! r1(2)=omega0(1)
! r2(1)=omega(3)
! r2(2)=omega(1)
! if(abs(r1(1))>1.d6) r1=r2
! call gMoveTo2D(r1(1),r1(2))
! call gDrawLineTo2D(r2(1),r2(2))
! omega0=omega
t=>t%next
enddo
j=vers%POS(3)
call gMID(vers,x,j)
call G_FRAME(vers%e,ENT,A,j)
t%previous%exi=ent
t%previous%b=a
t%ent=ent
t%a=a
if(t%previous%cas/=case2) then
write(6,*)" error in fill_survey_data_in_NODE_LAYOUT",j,t%cas
stop 669
endif
! t=>t%next
j=vers%nst
call gMID(vers,x,j)
call G_FRAME(vers%e,ENT,A,j)
t%exi=ent
t%b=a
if(t%cas/=casep2) then
write(6,*)" error in fill_survey_data_in_NODE_LAYOUT",j,t%cas
stop 670
endif
if(ic/=c%mag%p%nst+1) then
write(6,*)" error in fill_survey_data_in_NODE_LAYOUT"
write(6,*)k, ic,c%mag%name,c%mag%p%nst
stop 888
endif
c=>c%next
enddo
CALL kill(vers)
APERTURE_FLAG=aper
end subroutine fill_survey_data_in_NODE_LAYOUT
! BEAM STUFF
subroutine create_beam(B,N,CUT,SIG,A,C,T)
USE gauss_dis
implicit none
INTEGER N,I,J,K
REAL(DP) CUT,SIG(6),X
TYPE(BEAM) B
REAL(DP), OPTIONAL :: A(6,6),C(6)
REAL(DP) AS(6,6),CL(6),XT(6)
TYPE (INTEGRATION_NODE),optional,target:: T
IF(.NOT.ASSOCIATED(B%N)) THEN
CALL ALLOCATE_BEAM(B,N)
ELSEIF(B%N/=N) THEN
CALL KILL_BEAM(B)
CALL ALLOCATE_BEAM(B,N)
ENDIF
CL=0.0_dp; AS=0.0_dp;
DO I=1,6
AS(I,I)=1.0_dp
ENDDO
IF(PRESENT(A)) AS=A
IF(PRESENT(C)) CL=C
DO I=1,N
DO J=1,6
CALL GRNF(X,cut)
XT(J)=X*SIG(J)
ENDDO
B%X(I,1:6)=CL(:)
DO J=1,6
DO K=1,6
B%X(I,J)=AS(J,K)*XT(K)+B%X(I,J)
ENDDO
ENDDO
ENDDO
if(present(t)) then
DO I=1,N
! if(associated(B%POS(I)%NODE))then
B%POS(I)%NODE=>T
! endif
ENDDO
endif
end subroutine create_beam
subroutine create_PANCAKE(B,N,CUT,SIG,T,A)
USE gauss_dis
implicit none
INTEGER N,I,J
REAL(DP) CUT,SIG(6),X,Y(LNV),beta(2)
TYPE(BEAM) B
TYPE (INTEGRATION_NODE),optional,target:: T
TYPE (DAMAP),OPTIONAL :: A
TYPE (tree) monkey
IF(.NOT.ASSOCIATED(B%N)) THEN
CALL ALLOCATE_BEAM(B,N)
ELSEIF(B%N/=N) THEN
CALL KILL_BEAM(B)
CALL ALLOCATE_BEAM(B,N)
ENDIF
write(6,*) n," particles created"
Y=0.0_dp
IF(.not.PRESENT(A)) THEN
DO I=1,N
DO J=1,6
CALL GRNF(X,cut)
B%X(I,J)=X*SIG(J)
ENDDO
B%X(I,7)=0.0_dp
enddo
ELSE
call alloc(monkey)
beta(1)=(a%v(1).sub.'1')**2+(a%v(1).sub.'01')**2
beta(2)=(a%v(3).sub.'001')**2+(a%v(3).sub.'0001')**2
write(6,*) " Betas in create_PANCAKE ",beta
monkey=A
DO I=1,N
DO J=1,C_%ND
CALL GRNF(X,cut)
Y(2*j-1)=X*sqrt(SIG(j)/2.0_dp)
CALL GRNF(X,cut)
Y(2*j)=X*sqrt(SIG(j)/2.0_dp)
ENDDO
y=monkey*Y
B%X(I,1:C_%ND2)=y(1:c_%nd2)
DO J=C_%ND2+1,6
CALL GRNF(X,cut)
B%X(I,J)=X*SIG(J)
ENDDO
B%X(I,7)=0.0_dp
enddo
CALL KILL(MONKEY)
ENDIF
if(present(t)) then
DO I=1,N
if(associated(B%POS(I)%NODE))then
B%POS(I)%NODE=>T
endif
ENDDO
endif
end subroutine create_PANCAKE
subroutine copy_beam(B1,B2)
implicit none
INTEGER I
TYPE(BEAM), INTENT(INOUT) :: B1,B2
IF(.NOT.ASSOCIATED(B2%N)) THEN
CALL ALLOCATE_BEAM(B2,B1%N)
ELSEIF(B1%N/=B2%N) THEN
CALL KILL_BEAM(B2)
CALL ALLOCATE_BEAM(B2,B1%N)
ENDIF
B2%X=B1%X
B2%U=B1%U
B2%N=B1%N
! B2%CHARGE=B1%CHARGE
B2%LOST=B1%LOST
DO I=0,B1%N
if(associated(B1%POS(I)%NODE))then
B2%POS(I)%NODE=>B1%POS(I)%NODE
endif
ENDDO
END subroutine copy_beam
subroutine READ_beam_raw(B,MF)
implicit none
INTEGER k,mf
TYPE(BEAM), INTENT(IN):: B
DO K=1,b%n
IF(.not.B%U(K)) THEN
if(associated(b%pos(k)%NODE)) then
WRITE(MF,100) B%X(K,1:6),b%pos(k)%NODE%s(3)+B%X(K,7)
else
WRITE(MF,100) B%X(K,1:6),B%X(K,7)
endif
ENDIF
ENDDO
100 FORMAT(7(1x,e13.6))
END subroutine READ_beam_raw
subroutine PRINT_beam_raw(B,MF)
implicit none
INTEGER k,mf
TYPE(BEAM), INTENT(IN):: B
DO K=1,b%n
IF(.not.B%U(K)) THEN
if(associated(b%pos(k)%NODE)) then
WRITE(MF,100) B%X(K,1:6),b%pos(k)%NODE%s(3)+B%X(K,7)
else
WRITE(MF,100) B%X(K,1:6),B%X(K,7)
endif
ENDIF
ENDDO
100 FORMAT(7(1x,e13.6))
END subroutine PRINT_beam_raw
subroutine stat_beam_raw(B,n,MF,xm)
implicit none
INTEGER i,j,k,mf,NOTlost,N
TYPE(BEAM), INTENT(IN):: B
real(dp), optional :: xm(6)
real(dp), allocatable :: av(:,:)
real(dp) em(2),beta(2),xma(6)
allocate(av(n,n))
av=0.0_dp
notlost=0
xma(:)=-1.0_dp
DO K=1,b%n
IF(.not.B%U(K)) THEN
do i=1,6
if(abs(b%x(k,i))>xma(i)) xma(i)=abs(b%x(k,i))
enddo
do i=1,n
do j=i,n
av(i,j)= b%x(k,i)*b%x(k,j)+av(i,j)
enddo
enddo
notlost=notlost+1
ENDIF
ENDDO
IF(NOTLOST==0) THEN
if(mf/=6) then
WRITE(mf,*) " ALL PARTICLES ARE LOST "
WRITE(mf,*) " NO STATISTICS "
else
WRITE(6,*) " ALL PARTICLES ARE LOST "
WRITE(6,*) " NO STATISTICS "
endif
deallocate(av)
RETURN
ENDIF
if(notlost/=b%n-b%lost) then
Write(6,*) " Error keeping track of lost particles "
stop 999
endif
WRITE(MF,*) " NUMBER LEFT ",B%N-B%LOST
if(mf/=6)WRITE(6,*) " NUMBER LEFT ",B%N-B%LOST
WRITE(MF,*) " LOST ",B%LOST
if(mf/=6)WRITE(6,*) " LOST ",B%LOST
av=av/notlost
em(1)=2.0_dp*sqrt(av(1,1)*av(2,2)-av(1,2)**2)
em(2)=2.0_dp*sqrt(av(3,3)*av(4,4)-av(3,4)**2)
beta(1)=2.0_dp*av(1,1)/em(1)
beta(2)=2.0_dp*av(3,3)/em(2)
write(mf,*) " average arrays "
write(mf,*) "betas ",beta
write(mf,*) "emittances ",em
if(mf/=6) then
write(6,*) " average arrays "
write(6,*) "betas ",beta
write(6,*) "emittances ",em
endif
write(6,*) " limits "
write(6,*) xma(1:2)
write(6,*) xma(3:4)
write(6,*) xma(5:6)
if(present(xm)) xm=xma
100 FORMAT(7(1x,e13.6))
deallocate(av)
END subroutine stat_beam_raw
subroutine PRINT_beam(B,MF,I)
implicit none
INTEGER K,MF,I1,I2
INTEGER,OPTIONAL:: I
TYPE(BEAM), INTENT(IN):: B
TYPE(INTEGRATION_NODE),POINTER::T
TYPE(FIBRE),POINTER::F
I1=1
I2=B%N
IF(PRESENT(I)) THEN
I1=I
I2=I
ENDIF
! IF(B%TIME_INSTEAD_OF_S) THEN
! WRITE(MF,*) "____________________________ TIME TRACKED BEAM __________________________________"
! ELSE
WRITE(MF,*) "_________________ POSITION TRACKED BEAM (AS IN PTC PROPER)_______________________"
! ENDIF
DO K=I1,I2
IF(B%U(K)) THEN
WRITE(MF,*) " PARTICLE # ",K, " IS LOST "
ELSE
T=>B%POS(K)%NODE
F=>T%PARENT_FIBRE
WRITE(MF,*) "_________________________________________________________________________"
WRITE(MF,*) " PARTICLE # ",K, " IS LOCATED AT SLICE # ",T%POS," IN FIBRE ",F%MAG%NAME
WRITE(MF,*) " IN THE FIBRE POSITION ",T%pos_in_fibre
WRITE(MF,*) " IN ",CASE_NAME(T%CAS)
IF(T%CAS==CASE0)WRITE(MF,*) " AT THE STEP NUMBER ",T%pos_in_fibre-2
WRITE(MF,*) "........................................................................."
! IF(B%TIME_INSTEAD_OF_S) THEN
! WRITE(MF,*) " TIME AND POSITION AFTER THIN SLICE = ",B%X(K,6:7)
! ELSE
WRITE(MF,*) " TIME AND POSITION = ",B%X(K,6:7)
! ENDIF
WRITE(MF,*) " X,Y = ",B%X(K,1),B%X(K,3)
WRITE(MF,*) " PX,PY = ",B%X(K,2),B%X(K,4)
WRITE(MF,*) " ENERGY VARIABLE = ",B%X(K,5)
ENDIF
WRITE(MF,*) "_________________________________________________________________________"
ENDDO
END subroutine PRINT_beam
SUBROUTINE NULLIFY_BEAM(B)
IMPLICIT NONE
TYPE(BEAM) , INTENT (INOUT) :: B
NULLIFY(B%N,B%LOST)
! NULLIFY(B%Y)
NULLIFY(B%X)
NULLIFY(B%U)
NULLIFY(B%POS)
! NULLIFY(B%CHARGE)
! NULLIFY(B%TIME_INSTEAD_OF_S)
! NULLIFY(B%SIGMA)
! NULLIFY(B%DX,B%ORBIT)
! NULLIFY(B%BBPAR,B%BEAM_BEAM,B%BBORBIT)
END SUBROUTINE NULLIFY_BEAM
SUBROUTINE NULLIFY_BEAMS(B)
IMPLICIT NONE
TYPE(BEAM) , INTENT (INOUT) :: B(:)
INTEGER I
DO I=1,SIZE(B)
CALL NULLIFY_BEAM(B(i))
ENDDO
END SUBROUTINE NULLIFY_BEAMS
subroutine alloc_three_d_info(v)
IMPLICIT NONE
TYPE(three_d_info) , INTENT (INOUT) :: V
v%a=0.0_dp
v%b=0.0_dp
v%o=0.0_dp
v%ent=global_frame
v%exi=global_frame
v%mid=global_frame
v%reference_ray=0.0_dp
v%r0=0.0_dp
v%r=0.0_dp
v%x=0.0_dp
v%scale=1.0_dp
v%u=my_false
v%wx=0.1_dp
v%wy=0.1_dp
end subroutine alloc_three_d_info
SUBROUTINE ALLOCATE_BEAM(B,N)
IMPLICIT NONE
TYPE(BEAM) , INTENT (INOUT) :: B
INTEGER , INTENT (IN) :: N
INTEGER I
ALLOCATE(B%N,B%LOST)
B%N=N
B%LOST=0
! NULLIFY(B%Y)
! IF(PRESENT(POLYMORPH)) THEN
! IF(POLYMORPH) then
! ALLOCATE(B%Y(6))
! CALL ALLOC(B%Y)
! endif
! ENDIF
ALLOCATE(B%X(N,7))
ALLOCATE(B%U(0:N))
ALLOCATE(B%POS(0:N))
! ALLOCATE(B%SIGMA(6))
! ALLOCATE(B%DX(3))
! ALLOCATE(B%ORBIT(6))
! ALLOCATE(B%BBPAR,B%BEAM_BEAM,B%BBORBIT)
DO I=0,N
NULLIFY(B%POS(i)%NODE)
ENDDO
! ALLOCATE(B%CHARGE)
! ALLOCATE(B%TIME_INSTEAD_OF_S)
B%X = 0.0_dp
B%U = .FALSE.
! B%CHARGE=1
! B%TIME_INSTEAD_OF_S=.FALSE.
! B%SIGMA=ZERO
! B%DX=ZERO
! B%BBPAR=ZERO
! B%ORBIT=ZERO
! B%BEAM_BEAM=MY_FALSE
! B%BBORBIT=MY_FALSE
END SUBROUTINE ALLOCATE_BEAM
SUBROUTINE KILL_BEAM(B)
IMPLICIT NONE
TYPE(BEAM) , INTENT (INOUT) :: B
! IF(ASSOCIATED(B%Y)) THEN
! CALL KILL(B%Y)
! DEALLOCATE(B%Y)
! ENDIF
IF(ASSOCIATED(B%N)) THEN
DEALLOCATE(B%N,B%LOST,B%X,B%U,B%POS)
! DEALLOCATE(B%N,B%LOST,B%X,B%U,B%POS,B%CHARGE,B%TIME_INSTEAD_OF_S)
! DEALLOCATE(B%SIGMA,B%DX,B%BBPAR,B%ORBIT,B%BEAM_BEAM,B%BBORBIT)
ENDIF
END SUBROUTINE KILL_BEAM
SUBROUTINE KILL_BEAMS(B)
IMPLICIT NONE
TYPE(BEAM) , INTENT (INOUT) :: B(:)
INTEGER I
DO I=1,SIZE(B)
CALL KILL_BEAM(B(i))
ENDDO
END SUBROUTINE KILL_BEAMS
FUNCTION BEAM_IN_X(B,I)
IMPLICIT NONE
REAL(DP) BEAM_IN_X(6)
TYPE(BEAM), INTENT(INOUT) ::B
INTEGER, INTENT(IN) :: I
BEAM_IN_X=B%X(I,1:6)
END FUNCTION BEAM_IN_X
SUBROUTINE X_IN_BEAM(B,X,I,DL,T)
IMPLICIT NONE
REAL(DP),OPTIONAL:: X(6)
REAL(DP),OPTIONAL:: DL
TYPE(BEAM), INTENT(INOUT) ::B
TYPE(INTEGRATION_NODE),OPTIONAL,POINTER :: T
INTEGER, INTENT(IN) :: I
if(PRESENT(X)) B%X(I,1:6)=X(1:6)
IF(PRESENT(DL)) B%X(I,7)=DL
IF(PRESENT(T)) B%POS(I)%NODE=>T
if(.not.CHECK_STABLE) then
! write(6,*) "unstable "
CALL RESET_APERTURE_FLAG
b%u(I)=.true.
B%LOST=B%LOST+1
endif
END SUBROUTINE X_IN_BEAM
! Beam Beam stuff
subroutine s_locate_beam_beam(my_ering,sc,pos,tl,b_b)
implicit none
type(layout), target :: my_ering
type(integration_node), pointer :: tl
real(dp) sc
integer pos,j
logical(lp) b_b
IF(.NOT.ASSOCIATED(my_ering%T)) THEN
CALL MAKE_NODE_LAYOUT(my_ering)
ENDIF
! s(1) total ld
! s(2) local integration distance
! SC=MOD(SC,MY_RING%T%END%S(1))
b_b=.false.
TL=>my_ering%T%START
DO j=1,my_ering%T%N
if(pos<1) then
IF(TL%S(1)<=SC.AND.TL%NEXT%S(1)>SC) then
b_b=.true.
exit
endif
else
if(j==pos) then
b_b=.true.
exit
endif
endif
TL=>TL%NEXT
ENDDO
if(b_b.and.(tl%cas==case0.or.tl%cas==caset)) then
write(6,*) " Beam-Beam position at ",tl%parent_fibre%mag%name
if(.not.associated(tl%BB)) call alloc(tl%BB)
write(6,*) tl%pos,tl%parent_fibre%mag%name,' created'
b_b=my_true
else
b_b=my_false
write(6,*) " Beam-Beam position not found "
endif
end subroutine s_locate_beam_beam
subroutine locate_beam_beam(my_ering,a,ent,tl,b_b)
implicit none
type(layout), target :: my_ering
type(integration_node), pointer :: tl,tmin,tp
real(dp) dmin,a(3),ent(3,3),d,cos
integer pos,j
logical(lp) b_b
dmin=mybig
IF(.NOT.ASSOCIATED(my_ering%T)) THEN
CALL MAKE_NODE_LAYOUT(my_ering)
call FILL_SURVEY_DATA_IN_NODE_LAYOUT(my_ering)
ENDIF
IF(.NOT.ASSOCIATED(my_ering%T%start%B)) THEN
call FILL_SURVEY_DATA_IN_NODE_LAYOUT(my_ering)
ENDIF
b_b=.false.
TL=>my_ering%T%START
tmin=>tl
tp=>tl
DO j=1,my_ering%T%N
if(tl%cas==case0.or.tl%cas==caset) then
d=sqrt((a(1)-tl%a(1))**2+(a(2)-tl%a(2))**2+(a(3)-tl%a(3))**2)
if(d<=dmin) then
dmin=d
tmin=>tl
tp=>tl%parent_fibre%previous%t2%previous%previous
endif
endif
TL=>TL%NEXT
ENDDO
if((tmin%cas==case0.or.tmin%cas==caset)) then
write(6,*) " Tentative Beam-Beam position at ",tl%parent_fibre%mag%name
write(6,*) tmin%pos,tmin%parent_fibre%mag%name,' created'
b_b=my_true
cos=0.0_dp
do j=1,3
cos=cos+ (a(j)-tmin%a(j))*tmin%ent(1,j)
enddo
tl=>tp
if(cos<0.0_dp) then
write(6,*) " Beam-Beam position replaced at ",tl%parent_fibre%mag%name,tl%cas
write(6,*) tl%pos,tl%parent_fibre%mag%name,' created'
endif
else
b_b=my_false
write(6,*) " Beam-Beam position not found "
endif
if(b_b.and.(.not.associated(tl%BB))) call alloc(tl%BB)
end subroutine locate_beam_beam
end module ptc_multiparticle