module beam_beam_ptc ! use orbit_ptc use S_TRACKING ! use madx_ptc_module implicit none public private BBKICKP, BBKICKR,PATCH_BBR,PATCH_BBP private ccperrfP, ccperrfr ,ccperrf ! private TRACK_NODE_LAYOUT_FLAG_R,TRACK_NODE_LAYOUT_FLAG_P private imax integer ::imax=1000 INTERFACE ccperrf MODULE PROCEDURE ccperrfP MODULE PROCEDURE ccperrfr END INTERFACE INTERFACE BBKICK MODULE PROCEDURE BBKICKR MODULE PROCEDURE BBKICKP END INTERFACE INTERFACE PATCH_BB MODULE PROCEDURE PATCH_BBR MODULE PROCEDURE PATCH_BBP END INTERFACE logical(lp), target :: do_beam_beam= my_false contains SUBROUTINE PATCH_BBR(B,X,k,BETA0,exact,ENTERING) implicit none ! MISALIGNS REAL FIBRES IN PTC ORDER FOR FORWARD AND BACKWARD FIBRES TYPE(BEAM_BEAM_NODE),TARGET,INTENT(INOUT):: B real(dp), INTENT(INOUT):: X(6) logical(lp),INTENT(IN):: exact,ENTERING REAL(DP),INTENT(IN):: BETA0 REAL(DP) A(3),D(3) TYPE(INTERNAL_STATE) k !,OPTIONAL :: K IF(ENTERING) THEN X(3)=B%A_X1*X(3);X(4)=B%A_X1*X(4); CALL ROT_YZ(B%A(1),X,BETA0,exact,k%TIME) CALL ROT_XZ(B%A(2),X,BETA0,exact,k%TIME) CALL ROT_XY(B%A(3),X) !,exact) CALL TRANS(B%D,X,BETA0,exact,k%TIME) X(3)=B%A_X2*X(3);X(4)=B%A_X2*X(4); ELSE A=-B%A D=-B%D X(3)=B%A_X2*X(3);X(4)=B%A_X2*X(4); CALL TRANS(D,X,BETA0,exact,k%TIME) CALL ROT_XY(A(3),X) !,exact) CALL ROT_XZ(A(2),X,BETA0,exact,k%TIME) CALL ROT_YZ(A(1),X,BETA0,exact,k%TIME) X(3)=B%A_X1*X(3);X(4)=B%A_X1*X(4); ENDIF END SUBROUTINE PATCH_BBR SUBROUTINE PATCH_BBP(B,X,k,BETA0,exact,ENTERING) implicit none ! MISALIGNS REAL FIBRES IN PTC ORDER FOR FORWARD AND BACKWARD FIBRES TYPE(BEAM_BEAM_NODE),TARGET,INTENT(INOUT):: B TYPE(REAL_8), INTENT(INOUT):: X(6) logical(lp),INTENT(IN):: exact,ENTERING REAL(DP),INTENT(IN):: BETA0 REAL(DP) A(3),D(3) TYPE(INTERNAL_STATE) k !,OPTIONAL :: K IF(ENTERING) THEN X(3)=B%A_X1*X(3);X(4)=B%A_X1*X(4); CALL ROT_YZ(B%A(1),X,BETA0,exact,k%TIME) CALL ROT_XZ(B%A(2),X,BETA0,exact,k%TIME) CALL ROT_XY(B%A(3),X) !,exact) CALL TRANS(B%D,X,BETA0,exact,k%TIME) X(3)=B%A_X2*X(3);X(4)=B%A_X2*X(4); ELSE A=-B%A D=-B%D X(3)=B%A_X2*X(3);X(4)=B%A_X2*X(4); CALL TRANS(D,X,BETA0,exact,k%TIME) CALL ROT_XY(A(3),X) !,exact) CALL ROT_XZ(A(2),X,BETA0,exact,k%TIME) CALL ROT_YZ(A(1),X,BETA0,exact,k%TIME) X(3)=B%A_X1*X(3);X(4)=B%A_X1*X(4); ENDIF END SUBROUTINE PATCH_BBP subroutine BBKICKR(BB,X) implicit none !----------------------------------------------------------------------* ! purpose: * ! track a set of particle through a beam-beam interaction region. * ! see mad physicist's manual for the formulas used. * !input: * ! input/output: * ! b%x(:,6)(double) track coordinates: (x, px, y, py, pt,t). * ! b%n (integer) number of tracks. * !----------------------------------------------------------------------* real(dp) sx2,sy2,xs,ys,rho2,fk,tk,phix,phiy,rk,xb,yb,crx,cry,xr,yr,r,r2,& cbx,cby,ten3m,explim,sx,sy,xm,ym TYPE(BEAM_BEAM_NODE), INTENT(INOUT) ::BB REAL(DP), INTENT(INOUT) :: X(6) parameter(ten3m=1.0e-3_dp,explim=150.0_dp) SX=BB%SX SY=BB%SY XM=BB%XM YM=BB%YM FK=BB%FK ! write(6,*) "bb%FK = " ,bb%FK if (fk == 0.0_dp) return sx2 = sx*sx sy2 = sy*sy !---- limit formulae for sigma(x) = sigma(y). if (abs(sx2 - sy2) .le. ten3m * (sx2 + sy2)) then !ten3m = 1.0d-3 xs = x(1) - xm ys = x(3) - ym rho2 = xs * xs + ys * ys tk = rho2 / (sx2 + sy2) if (tk .gt. explim) then phix = xs * fk / rho2 phiy = ys * fk / rho2 else if (rho2 .ne. 0.0_dp) then phix = xs * fk / rho2 * (1.0_dp - exp(-tk) ) phiy = ys * fk / rho2 * (1.0_dp - exp(-tk) ) else phix = 0.0_dp phiy = 0.0_dp endif phix = phix - bb%bbk(1) ! subtract horizontal bb kick phiy = phiy - bb%bbk(2) ! subtract vertical co x(2) = x(2) + phix x(4) = x(4) + phiy !---- case sigma(x) > sigma(y). else if (sx2 > sy2) then r2 = 2.0_dp * (sx2 - sy2) r = sqrt(r2) rk = fk * sqrt(pi) / r xs = x(1) - xm ys = x(3) - ym xr = abs(xs) / r yr = abs(ys) / r call ccperrf(xr, yr, crx, cry) tk = (xs * xs / sx2 + ys * ys / sy2) / 2.0_dp if (tk .gt. explim) then phix = rk * cry phiy = rk * crx else xb = (sy / sx) * xr yb = (sx / sy) * yr call ccperrf(xb, yb, cbx, cby) phix = rk * (cry - exp(-tk) * cby) phiy = rk * (crx - exp(-tk) * cbx) endif x(2) = x(2) + phix * sign(1.0_dp,xs) x(4) = x(4) + phiy * sign(1.0_dp,ys) x(2) = x(2) - BB%bbk(1) x(4) = x(4) - BB%bbk(2) !---- case sigma(x) < sigma(y). else r2 = 2.0_dp * (sy2 - sx2) r = sqrt(r2) rk = fk * sqrt(pi) / r ! do itrack = 1, b%n ! IF(B%U(itrack)) CYCLE ! xs = track(1,itrack) - xm ! ys = track(3,itrack) - ym xs = x(1) - xm ys = x(3) - ym xr = abs(xs) / r yr = abs(ys) / r call ccperrf(yr, xr, cry, crx) tk = (xs * xs / sx2 + ys * ys / sy2) / 2.0_dp if (tk .gt. explim) then phix = rk * cry phiy = rk * crx else xb = (sy / sx) * xr yb = (sx / sy) * yr call ccperrf(yb, xb, cby, cbx) phix = rk * (cry - exp(-tk) * cby) phiy = rk * (crx - exp(-tk) * cbx) endif x(2) = x(2) + phix * sign(1.0_dp,xs) x(4) = x(4) + phiy * sign(1.0_dp,ys) x(2) = x(2) - BB%bbk(1) x(4) = x(4) - BB%bbk(2) endif ! IF(DZ/=ZERO) CALL DRIFT_BEAM_BACK_TO_POSITION(th,DZ,B) end subroutine BBKICKR subroutine ccperrfr(xx, yy, wx, wy) implicit none !----------------------------------------------------------------------* ! purpose: * ! modification of wwerf, double precision complex error function, * ! written at cern by K. Koelbig. * ! input: * ! xx, yy (double) real + imag argument * ! output: * ! wx, wy (double) real + imag function result * !----------------------------------------------------------------------* integer n,nc,nu real(dp), INTENT(INOUT):: xx,yy,wx,wy real(dp) x,y,q,h,xl,xh,yh,tx,ty,tn,sx,sy,saux, & rx(33),ry(33),cc,xlim,ylim,fac1,fac2,fac3 parameter(cc=1.12837916709551_dp, & xlim=5.33_dp,ylim=4.29_dp,fac1=3.2_dp,fac2=23.0_dp,fac3=21.0_dp) x = abs(xx) y = abs(yy) if (y .lt. ylim .and. x .lt. xlim) then q = (1.0_dp - y / ylim) * sqrt(1.0_dp - (x/xlim)**2) h = 1.0_dp / (fac1 * q) nc = 7 + int(fac2*q) xl = h**(1 - nc) xh = y + 0.5_dp/h yh = x nu = 10 + int(fac3*q) rx(nu+1) = 0.0_dp ry(nu+1) = 0.0_dp do n = nu, 1, -1 tx = xh + n * rx(n+1) ty = yh - n * ry(n+1) tn = tx*tx + ty*ty rx(n) = 0.5_dp * tx / tn ry(n) = 0.5_dp * ty / tn enddo sx = 0.0_dp sy = 0.0_dp do n = nc, 1, -1 saux = sx + xl sx = rx(n) * saux - ry(n) * sy sy = rx(n) * sy + ry(n) * saux xl = h * xl enddo wx = cc * sx wy = cc * sy else xh = y yh = x rx(1) = 0.0_dp ry(1) = 0.0_dp do n = 9, 1, -1 tx = xh + n * rx(1) ty = yh - n * ry(1) tn = tx*tx + ty*ty rx(1) = 0.5_dp * tx / tn ry(1) = 0.5_dp * ty / tn enddo wx = cc * rx(1) wy = cc * ry(1) endif ! if(y .eq. zero) wx = exp(-x**2) if(yy .lt. 0.0_dp) then wx = 2.0_dp * exp(y*y-x*x) * cos(2.0_dp*x*y) - wx wy = - 2.0_dp * exp(y*y-x*x) * sin(2.0_dp*x*y) - wy if(xx .gt. 0.0_dp) wy = -wy else if(xx .lt. 0.0_dp) wy = -wy endif end SUBROUTINE ccperrfr subroutine BBKICKP(BB,X) implicit none !----------------------------------------------------------------------* ! purpose: * ! track a set of particle through a beam-beam interaction region. * ! see mad physicist's manual for the formulas used. * !input: * ! input/output: * ! b%x(:,6)(double) track coordinates: (x, px, y, py, pt,t). * ! b%n (integer) number of tracks. * !----------------------------------------------------------------------* integer it TYPE(REAL_8) xs,ys,tk,phix,phiy,xb,yb,crx,cry TYPE(REAL_8) xr,yr,cbx,cby,rho2 REAL(DP) sx2,sy2,sx,sy,xm,ym,fk,ten3m,explim,xn1,xn2,xs1,xs2,arglim,rk REAL(DP) r,r2,n TYPE(BEAM_BEAM_NODE), INTENT(INOUT) ::BB TYPE(REAL_8), INTENT(INOUT) :: X(6) parameter(ten3m=1.0e-3_dp,arglim=1.0e-2_dp,explim=150.0_dp) if (BB%fk == 0.0_dp) return CALL ALLOC(xr,yr,cbx,cby,rho2) CALL ALLOC(xs,ys,tk,phix,phiy) CALL ALLOC(xb,yb,crx,cry) SX=BB%SX SY=BB%SY XM=BB%XM YM=BB%YM FK=BB%FK sx2 = sx*sx sy2 = sy*sy !---- limit formulae for sigma(x) = sigma(y). xn1=abs(sx2 - sy2) xn2= ten3m * (sx2 + sy2) xs1=sx2 xs2= sy2 if (xn1 .le.xn2 ) then !ten3m = 1.0d-3 xs = x(1) - xm ys = x(3) - ym rho2 = xs * xs + ys * ys tk = rho2 / (sx2 + sy2) if (tk .gt. explim) then phix = xs * fk / rho2 phiy = ys * fk / rho2 else if (tk > arglim) then phix = xs * fk / rho2 * (1.0_dp - exp(-tk) ) phiy = ys * fk / rho2 * (1.0_dp - exp(-tk) ) else xr=1.0_dp yr=1.0_dp n=mybig do it=1,imax xr=-xr*tk/(it+1) yr=yr+xr if(it>10)n=full_abs(xr) if(n<=puny) exit enddo if(it>imax-2) then write(6,*) it,n write(6,*) " Stopped in Beam-Beam " endif phix = xs * fk / (2.0_dp * sx2) * YR ! fudge phiY = Ys * fk / (2.0_dp * sx2) * YR ! fudge endif phix = phix - bb%bbk(1) phiy = phiy - bb%bbk(2) x(2) = x(2) + phix x(4) = x(4) + phiy !---- case sigma(x) > sigma(y). else xs = x(1) - xm ys = x(3) - ym tk = (xs * xs / sx2 + ys * ys / sy2) / 2.0_dp if(xs1 > xs2) then r2 = 2.0_dp * (sx2 - sy2) r = sqrt(r2) rk = fk * sqrt(pi) / r xr = xs / r ! yr = ys / r ! call ccperrf(xr, yr, crx, cry) if (tk .gt. explim) then phix = rk * cry phiy = rk * crx else xb = (sy / sx) * xr yb = (sx / sy) * yr call ccperrf(xb, yb, cbx, cby) phix = rk * (cry - exp(-tk) * cby) phiy = rk * (crx - exp(-tk) * cbx) endif x(2) = x(2) + phix x(4) = x(4) + phiy ! if (.NOT.bborbit) then x(2) = x(2) - BB%bbk(1) x(4) = x(4) - BB%bbk(2) ! endif ! enddo !---- case sigma(x) < sigma(y). else r2 = 2.0_dp * (sy2 - sx2) r = sqrt(r2) rk = fk * sqrt(pi) / r ! xs = x(1) - xm ! ys = x(3) - ym xr = xs / r !abs yr = ys / r !abs call ccperrf(yr, xr, cry, crx) ! tk = (xs * xs / sx2 + ys * ys / sy2) / two if (tk .gt. explim) then phix = rk * cry phiy = rk * crx else xb = (sy / sx) * xr yb = (sx / sy) * yr call ccperrf(yb, xb, cby, cbx) phix = rk * (cry - exp(-tk) * cby) phiy = rk * (crx - exp(-tk) * cbx) endif ! track(2,itrack) = track(2,itrack) + phix * sign(one,xs) ! track(4,itrack) = track(4,itrack) + phiy * sign(one,ys) x(2) = x(2) + phix x(4) = x(4) + phiy ! if (.NOT.bborbit) then !--- subtract closed orbit kick ! track(2,itrack) = track(2,itrack) - bb_kick(1,ipos) ! track(4,itrack) = track(4,itrack) - bb_kick(2,ipos) x(2) = x(2) - BB%bbk(1) x(4) = x(4) - BB%bbk(2) ! endif ! enddo endif endif CALL KILL(xr,yr,cbx,cby,rho2) CALL KILL(xs,ys,tk,phix,phiy) CALL KILL(xb,yb,crx,cry) end subroutine BBKICKP subroutine ccperrfP(xx, yy, wx, wy) implicit none !----------------------------------------------------------------------* ! purpose: * ! modification of wwerf, double precision complex error function, * ! written at cern by K. Koelbig. * ! input: * ! xx, yy (double) real + imag argument * ! output: * ! wx, wy (double) real + imag function result * !----------------------------------------------------------------------* TYPE(REAL_8),INTENT(INOUT):: xx,yy,wx,wy TYPE(double_complex) z,zt,w complex(dp) z0,w0,w1,wt0 real(dp) xx0, yy0, wx0, wy0 integer i call alloc( z,zt,w) z=xx+i_*yy z0=z z=z-z0 xx0=real(z0) yy0=aimag(z0) call ccperrf(xx0, yy0, wx0, wy0) w0=wx0+i_*wy0 w1=-2.0_dp*z0*w0+2.0_dp*i_/sqrt(pi) w=w0+w1*z zt=z do i=2,c_%no zt=z*zt wt0= -2.0_dp*(w0+z0*w1)/i w=w+wt0*zt w0=w1 w1=wt0 enddo wx=real(w) wy=aimag(w) call kill( z,zt,w) end SUBROUTINE ccperrfP end module beam_beam_ptc