module ptc_export_xml_module use madx_ptc_module ! to access the layout 'MY_RING' implicit none private public :: ptc_export_xml ! external interface contains subroutine ptc_export_xml(filenameIA) implicit none integer filenameIA(*) character(48) filename !integer I,MF,DI,nt integer i,mf type(LAYOUT), TARGET :: L type(FIBRE), pointer :: P !character*255 line !REAL(DP) D(3),ANG(3),PREC,DS !LOGICAL(LP) ENERGY_PATCH integer xml_level xml_level = 0 filename = charconv(filenameIA) write(6,*) 'Fortran: export XML document "', trim(filename),'"representing PTC machine' L = MY_RING ! my ring is global variable from madx_ptc_module ! P=>L%START ! i=1 ! nt=0 ! do while(i<=l%n) ! call count_PATCH_sixtrack(di,p) ! i=i+1+DI ! nt=nt+1 ! ENDDO !nt=0 ! PREC=1.D-10 call kanalnummer(mf) open(unit=mf,file=filename) write (MF,'(a)') '' ! format to avoid first blank character write (MF,*) '' write (MF,*) '' !... continued P=>L%START i=1 do while(i<=l%n) ! for each fibre CALL print_FIBRE_SIXTRACK(P,mf,xml_level+1) p=>p%next i=i+1 !+DI ENDDO call print_XML_beam(L,mf,xml_level+1) write (MF,*) '' close(MF) END subroutine ptc_export_xml subroutine print_FIBRE_SIXTRACK(fibre_ptr,file_handle,xml_level) implicit none integer file_handle integer xml_level type(FIBRE), pointer :: fibre_ptr character propagation*32 select case(fibre_ptr%dir) case(1) propagation = 'forward' case(-1) propagation = 'backward' case default propagation = 'undefined' end select write(file_handle,*) '' call print_XML_patches(file_handle,fibre_ptr,xml_level+1) call print_XML_misalignments(file_handle,fibre_ptr,xml_level+1) call print_XML_element(fibre_ptr%mag,file_handle,xml_level+1) write(file_handle,*) '' END subroutine print_FIBRE_SIXTRACK subroutine print_XML_patches(mf,f,xml_level) implicit none type(FIBRE), pointer :: f integer mf,i integer xml_level character padding*10 real(dp) xi,yi,zi,xo,yo,zo real(dp) rxi,ryi,rzi,rxo,ryo,rzo padding = '' do i=1,10 padding = padding//' ' end do ! input patch xi = f%patch%a_d(1) yi = f%patch%a_d(2) zi = f%patch%a_d(3) rxi = f%patch%a_ang(1) ryi = f%patch%a_ang(2) rzi = f%patch%a_ang(3) ! output patch xo = f%patch%b_d(1) yo = f%patch%b_d(2) zo = f%patch%b_d(3) rxo = f%patch%b_ang(1) ryo = f%patch%b_ang(2) rzo = f%patch%b_ang(3) write(mf,*) padding(1:xml_level), '' write(mf,*) padding(1:xml_level+1), '' write(mf,*) padding(1:xml_level+2), '' write(mf,*) padding(1:xml_level+2), '' write(mf,*) padding(1:xml_level+1), '' write(mf,*) padding(1:xml_level+1), '' write(mf,*) padding(1:xml_level+2), '' write(mf,*) padding(1:xml_level+2), '' write(mf,*) padding(1:xml_level+1), '' write(mf,*) padding(1:xml_level), '' end subroutine print_XML_patches subroutine print_XML_misalignments(mf,f,xml_level) implicit none integer mf integer xml_level,i type(FIBRE), pointer ::f character padding*10 real(dp) xi,yi,zi,xo,yo,zo real(dp) rxi,ryi,rzi,rxo,ryo,rzo padding = '' do i=1,10 padding = padding//' ' end do ! input misalignment xi = f%chart%d_in(1) yi = f%chart%d_in(2) zi = f%chart%d_in(3) rxi = f%chart%ang_in(1) ryi = f%chart%ang_in(2) rzi = f%chart%ang_in(3) ! output misalignment xo = f%chart%d_out(1) yo = f%chart%d_out(2) zo = f%chart%d_out(3) rxo = f%chart%ang_out(1) ryo = f%chart%ang_out(2) rzo = f%chart%ang_out(3) write(mf,*) padding(1:xml_level), '' write(mf,*) padding(1:xml_level+1), '' write(mf,*) padding(1:xml_level+2), '' write(mf,*) padding(1:xml_level+2), '' write(mf,*) padding(1:xml_level+1), '' write(mf,*) padding(1:xml_level+1), '' write(mf,*) padding(1:xml_level+2), '' write(mf,*) padding(1:xml_level+2), '' write(mf,*) padding(1:xml_level+1), '' write(mf,*) padding(1:xml_level), '' end subroutine print_XML_misalignments subroutine print_XML_element(m,mf,xml_level) implicit none integer mf integer xml_level,i ! type(FIBRE), pointer :: P type(element), pointer :: m real(dp) length ! for a drift or a magnet real(dp) voltage, phase, frequency ! for an RF cavity real(dp) ks ! try this for a solenoid real(dp) a1,b1 ! for a crab cavity character el_name*48 ! the name of the element character padding*10 el_name = '' padding = '' do i=1,10 padding = padding//' ' end do do i=1,len(trim(M%VORNAME)) el_name(i:i)=lowercase(M%VORNAME(i:i)) end do ! hardcode design-tilt as 0.0 for the time-being write (MF,*) padding(1:xml_level), '' write(MF,*) padding(1:xml_level+1), '' ! trim to remove trailing blanks select case (M%KIND) case (30) ! this is a marker write(MF,*) padding(1:xml_level+2), '' case (31) ! this is a drift length = M%L write(MF,*) padding(1:xml_level+2), '' case (32) ! this is a drift-kick-drift?? !write(MF,*) padding(1:xml_level+2), '' ! should ensure this is a quadrupole (do we end-up here for sextupole as well? length = M%L write(MF,*) padding(1:xml_level+2), '' ! Does it account for any kind of magnet - at least this is what we ! agreed on in the Schema if (ASSOCIATED(M%an)) then do i=1,m%p%NMUL ! write(mf,*) m%bn(i),m%an(i), " BN AN ",I write(mf,*) padding(1:xml_level+3), '' write(mf,*) padding(1:xml_level+3), '' enddo endif write(MF,*) padding(1:xml_level+2), '' case (33) ! this is a multiple block ! As far as I know let's identify it as a MAD multipole composed of a series ! of zero length thin lenses ! for the time being omit, MAD's LRAD fictitious length (synchrotron radiation) ! and TILT write(MF,*) padding(1:xml_level+2), '' if (ASSOCIATED(M%an)) then do i=1,m%p%NMUL write(MF,*) padding(1:xml_level+3), '' write(MF,*) padding(1:xml_level+3), '' enddo endif write(MF,*) padding(1:xml_level+2), '' case (34) ! this is a cavity length = M%L voltage = M%VOLT ! for an ordinary RF cavity (i.e. not a crab) frequency = M%FREQ phase = M%PHAS + M%C4%PHASE0 + M%C4%PH(1) write(MF,*) padding(1:xml_level), '' ! following should be conditionnal to the cavity being ! a crab cavity a1 = M%AN(1) b1 = M%BN(1) write(MF,*) padding(1:xml_level+3), '' write(MF,*) padding(1:xml_level+3), '' write(MF,*) padding(1:xml_level+2), '' case (35) ! found-out that this is a solenoid length = M%L ks = 0 ! as I don't know yet where to pick it up write(MF,*) padding(1:xml_level), '' case (41) ! found-out that this is monitor length = M%L write(MF,*) padding(1:xml_level), '' ! monitor actual has a type, but let's forget it for the time-being case (42) ! found-out this is an H-monitor length = M%L write(MF,*) padding(1:xml_level), '' case (43) ! found-out this is a V-monitor length = M%L write(MF,*) padding(1:xml_level), '' case (44) ! found-out this is an instrument write(MF,*) padding(1:xml_level), '' case (48) ! found-out this is a R-collimator length = M%L write(MF,*) padding(1:xml_level), '' ! and what about an E-collimator ??? case (51) ! to be confirmed that this is indeed a cavity... !voltage = M%VOLT; length = M%L write(MF,*) padding(1:xml_level), '' case default write(MF,*) padding(1:xml_level), '' end select write (MF,*) padding(1:xml_level+1), '' write (MF,*) padding(1:xml_level), '' end subroutine print_XML_element subroutine print_XML_beam(L,file_handle, xml_level) integer file_handle,xml_level integer i real(dp) charge,mass,beta0,p0c type(LAYOUT), TARGET :: L character padding*10; padding = '' do i=1,10 padding = padding//' ' end do charge = L%START%charge mass = L%START%mass beta0 = L%START%beta0 p0c = L%START%MAG%P%p0c write(file_handle,*) padding(1:xml_level), '' end subroutine print_XML_beam subroutine print_element_SIXTRACK(P,m,mf) implicit none integer mf,I type(FIBRE), pointer :: P type(element), pointer :: m character*255 line WRITE(MF,*) "$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$ ELEMENT $$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$" if(m%vorname(1:1)==' ') then WRITE(MF,*) M%KIND,M%NAME, ' NOVORNAME' ELSE WRITE(MF,*) M%KIND,M%NAME,' ',M%VORNAME ENDIF WRITE(MF,*) M%L IF(ASSOCIATED(M%FREQ)) THEN WRITE(MF,*) " CAVITY INFORMATION " !HALF*EL%P%DIR*EL%P%CHARGE*EL%volt*c_1d_3*SIN(twopi*EL%freq*x(6)/CLIGHT+EL%PHAS+EL%phase0)/EL%P%P0C WRITE(LINE,*) c_1d_3*M%VOLT, twopi*M%FREQ/CLIGHT,M%PHAS+M%C4%phase0 WRITE(MF,'(A255)') LINE ELSEIF(ASSOCIATED(M%VOLT)) THEN WRITE(MF,*) " ELECTRIC SEPTUM INFORMATION " WRITE(MF,*) M%VOLT,M%PHAS, "VOLT, PHAS(rotation angle) " ELSE WRITE(MF,*) " NO ELECTRIC ELEMENT INFORMATION " ENDIF IF(ASSOCIATED(M%B_SOL)) THEN WRITE(MF,*) M%B_SOL, " B_SOL" ELSE WRITE(MF,*) zero ENDIF CALL print_magnet_chart_SIXTRACK(P,m%P,mf) IF(ASSOCIATED(M%an)) THEN do i=1,m%p%NMUL write(mf,*) m%bn(i),m%an(i), " BN AN ",I enddo endif ! call print_specific_element(m,mf) WRITE(MF,*) "$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$ END $$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$" end subroutine print_element_SIXTRACK subroutine print_magnet_chart_SIXTRACK(P,m,mf) implicit none type(FIBRE), pointer :: P type(magnet_chart), pointer :: m integer mf character*200 line WRITE(MF,*) "MAGNET CHART MAGNET CHART MAGNET CHART MAGNET CHART MAGNET CHART MAGNET CHART " WRITE(MF,*) M%METHOD,M%NST,M%NMUL, " METHOD NST NMUL" WRITE(line,*) M%B0,M%EDGE, m%tiltd, " B0, EDGES, TILT" WRITE(MF,'(A200)') LINE WRITE(LINE,*) P%BETA0,P%GAMMA0I, P%GAMBET, " BETA0 GAMMA0I GAMBET " WRITE(MF,'(A200)') LINE write(mf,'(a68)') "END MAGNET CHART END MAGNET CHART END MAGNET CHART END MAGNET CHART " if(M%METHOD/=2.and.p%mag%l>zero) then write(6,*) " error method must be 2 ",P%mag%name stop endif if(M%exact) then write(6,*) " No exact magnet permitted ",P%mag%name stop endif end subroutine print_magnet_chart_SIXTRACK subroutine print_PATCH_MIS_SIXTRACK(m,mf) implicit none type(FIBRE), pointer :: m integer mf character*200 line write(mf,'(a30)') " PATCHING AND MISALIGNMENTS " write(mf,'(a30)') " Reversed discontinuous patches " WRITE(MF,*) M%PATCH%A_X1,M%PATCH%A_X2,M%PATCH%B_X1,M%PATCH%B_X2 write(mf,'(a30)') " Time patches " WRITE(MF,*) M%PATCH%A_T, M%PATCH%B_T write(mf,'(a30)') " Frontal geometric patches " WRITE(LINE,*) M%PATCH%A_ANG,M%PATCH%A_D WRITE(MF,'(a200)') LINE write(mf,'(a30)') " Exit geometric patches " WRITE(LINE,*) M%PATCH%B_ANG,M%PATCH%B_D WRITE(MF,'(a200)') LINE write(mf,'(a30)') " Entrance misalignments " WRITE(LINE,*) M%CHART%ANG_IN,M%CHART%D_IN WRITE(MF,'(a200)') LINE write(mf,'(a30)') " Exit misalignments " WRITE(LINE,*) M%CHART%ANG_OUT,M%CHART%D_OUT WRITE(MF,'(a200)') LINE write(mf,'(a14)') " END GEOMETRY " end subroutine print_PATCH_MIS_SIXTRACK character function lowercase(C) implicit none character C integer asciiDiff asciiDiff = iachar('a') - iachar('A') if (LGE(C,'A') .AND. LLE(C,'Z')) then lowercase = achar(iachar(C) + asciiDiff) else lowercase = C endif end function ! following copied from util.F character * 48 function charconv(tint) !----------------------------------------------------------------------* ! purpose: * ! converts integer array to string (based on ascii) * ! input: * ! tint (int array) 1 = length, rest = string * !----------------------------------------------------------------------* implicit none integer tint(*) integer i, j, m, n parameter (m = 128) character *(m) letter data letter / & &' !"#$%&''()*+,-./0123456789:;<=>?@& &ABCDEFGHIJKLMNOPQRSTUVWXYZ[ ]^_`abcdefghijklmnopqrstuvwxyz{|}~'/ charconv = ' ' n = tint(1) do i = 1, n j = tint(i+1) if (j .lt. m) charconv(i:i) = letter(j:j) enddo end function end module ptc_export_xml_module