#!/bin/sh
# The next line restarts using tclsh since sh ignores the backslash \
exec oagwish "$0" "$@"

# $Log: not supported by cvs2svn $
# Revision 1.1.1.1  1996/03/25  18:53:10  evans
# Imported files.
#
# Revision 1.2  1996/02/28  16:56:16  evans
# Added #$Log: not supported by cvs2svn $
# Revision 1.1.1.1  1996/03/25  18:53:10  evans
# Imported files.
#

set auto_path [linsert $auto_path 0 /usr/local/oag/apps/lib/$env(HOST_ARCH)]
set auto_path [linsert $auto_path 0 /usr/local/oag/lib_patch/$env(HOST_ARCH)]
APSDebugPath

#printsource

# **************************** arrow ***********************************
proc arrow {cart color tag} {
    global xpixb0 ypixb0

# Convert to pixels
    set x [xpixb [lindex $cart 0]]
    set y [ypixb [lindex $cart 1]]
# Draw arrow
    .canvasb create line $xpixb0 $ypixb0 $x $y \
      -tags $tag -arrow last -fill $color
}
# **************************** cart2polar ******************************
proc cart2polar {x y} {
    set r [expr sqrt($x*$x+$y*$y)]
    set phi [expr atan2($y,$x)]
    return [list $r $phi]
}
# **************************** clear ***********************************
proc clear {} {
    global xcanvas ycanvas

    .canvas delete line
    .canvas delete grid
    set margin 15
    set top [expr $margin] 
    set bottom [expr $ycanvas-$margin] 
    set left [expr $margin] 
    set right [expr $xcanvas-$margin] 
    set xcenter [expr $xcanvas/2]
    set ycenter [expr $ycanvas/2]
    .canvas create line $left $ycenter $right $ycenter -tags grid
    .canvas create line $xcenter $top $xcenter $bottom -tags grid
    .canvas create text [expr $xcenter+5] $top -text "P-Ps" \
      -anchor w -tags grid 
    .canvas create text $right [expr $ycenter+5] -text "Phi-Phis"\
      -anchor ne -tags grid
}
# **************************** cont ************************************
proc cont {} {
    global npoints abort beamload

    .canvas configure -cursor watch
    update idletasks
    for {set n 0} {$n < $npoints} {incr n} {
	if {![iterate]} {
	    global p0 pbounds
	    puts "p0: $p0   pbounds: $pbounds   npoints: $npoints"
	    break
	}
        update
	if {$abort} {
	    set abort 0
	    break
	}
    }
    .canvas configure -cursor crosshair
}
# **************************** errmsg **********************************
proc errmsg {string} {

    APSErrorDialog .bcerror -errorMessage $string -unique 1
}
# **************************** iterate *********************************
proc iterate {} {
    global fold sign p0 p1 pbounds kstrengthb beamload
    global phimax phimin phi0 phi1 phis sinphis delphi

# Calculate change in phi and p
    set phi1 [expr $phi0+$sign*$p0]
    set p1 [expr $p0+$kstrengthb*(sin($phi1+$phis)-$sinphis)]
    if {$fold} {
	while {$phi1 > $phimax} {set phi1 [expr $phi1-$delphi]}
	while {$phi1 < $phimin} {set phi1 [expr $phi1+$delphi]}
    }
    set p0 $p1
    set phi0 $phi1
    set x [xpix $phi1]
    set y [ypix $p1]
#    puts "x=$x y=$y phi1=$phi1 p1=$p1"
    point $x $y
# Do beam loading
    if {$beamload} iterateb
# Return
    expr "($p1 < $pbounds && $p1 > -$pbounds)?1:0"
}
# **************************** iterateb ********************************
proc iterateb {} {
    global pi phi0
    global phicav phibeam igen vcav phivcav

# Delete old lines
    .canvasb delete line
# Beam
    set phibeam [expr -$phi0]
    set cartib [polar2cart $igen $phibeam]     ;# Note $igen to make bigger
    arrow $cartib SteelBlue2 line
# Real part of cavity voltage
    set phivcib [expr $phivcav-$phibeam]
    set vcavreal [expr $vcav*cos($phivcib)]
    set cartvr [polar2cart $vcavreal [expr $phibeam]]
    arrow $cartvr Red line
}
# **************************** overviewtext ****************************
proc overviewtext {} {
    return "\
Tcl Synchtron Motion\n\
\n\
This program displays the evolution in phase space of a particle in\n\
a closed ring passing through an RF cavity.  The phase space\n\
coordinates are P-Ps in the vertical direction and Phi-Phis in the\n\
horizontal direction.  P is the momentum and Phi is the phase of the\n\
particle.  Ps and Phis are the synchronous momentum and phase (the\n\
ones for which there is no synchrotron motion about the orbit).\n\
\n\
If you click with Button-1 on the plot, it will trace out the phase\n\
space trajectory which starts at the coordinates corresponding to the\n\
point where you clicked.  Each point corresponds to a pass through the\n\
cavity.\n\
\n\
It is necessary to hit Return in an entry box after typing the new\n\
value.  Double clicking with Button-3 on any controls or the plots\n\
brings up for that object.\n\
\n\
The relative strength (K) of the cavity, the synchronous phase, the\n\
vertical axis limits (Pmax and Pmin) the number of points traced, and\n\
the number of periods of Phi shown on the horizontal axis can be\n\
changed as you like.  There is a switch to set Pmax=-Pmin when either\n\
is changed, and another switch to fold all multiples of the Phi-Phis\n\
interval into the visible part of the plot.  Without folding,\n\
particles that are not trapped are lost from the display.\n\
\n\
There are buttons to stop the trajectory, continue the trajectory for\n\
another set of points, step through the trajectory one point at a\n\
time, clear the display, print a Postscript file of the plot, and to\n\
quit.  The Postscript file is named tsm.ps and the button also brings\n\
up Ghostview for the Postscript file.  The program may also be quit\n\
from the File menu.\n\
\n\
If K=1 and Pmax=-Pmin=5, the motion is chaotic and stochastic, and the\n\
patterns are more interesting.  (However, K=1 corresponds to the RF voltage\n\
kick being the same size as the momentum, an unrealistic regime for an\n\
accelerator.)\n\
\n\
There is also the ability to simulate the effects of beam loading.\n\
Click on the beam loading plot to get more information."
}
# **************************** pixx ************************************
proc pixx {x} { global ax bx

    expr (double($x)-$bx)/$ax
}
# **************************** pixxb ***********************************
proc pixxb {x} {
    global axb bxb

    expr (double($x)-$bxb)/$axb
}
# **************************** pixy ************************************
proc pixy {y} {
    global ay by

    expr (double($y)-$by)/$ay
}
# **************************** pixyb ***********************************
proc pixyb {y} {
    global ayb byb

    expr (double($y)-$byb)/$ayb
}
# **************************** point ***********************************
proc point {x y} {
#    global dot

# Bitmap seems the nicest and is about 5% faster than line.  It needs to
# be able to find the bitmap file, though.  Line is all internal.

#    .canvas create line $x $y $x $y -tags line -fill black
#    .canvas create oval $x $y $x $y -tags line -outline {}
#    .canvas create line [expr $x-.5] $y [expr $x+.5] $y -tags line -fill black
    .canvas create image $x $y -image dot -tags line
}
# **************************** polar2cart ******************************
proc polar2cart {r phi} {
    set x [expr $r*cos($phi)]
    set y [expr $r*sin($phi)]
    return [list $x $y]
}
# **************************** print ***********************************
proc print {} {
    .canvas postscript -file tsm.ps -pagewidth 6.5i
    exec ghostview tsm.ps &
}
# **************************** resize **********************************
proc resize {} {
    global ax bx ay by xcanvas ycanvas phimax phimin pmax pmin

    set ax [expr $xcanvas/($phimax-$phimin)]
    set bx [expr -$ax*$phimin]
    set ay [expr -$ycanvas/($pmax-$pmin)]
    set by [expr $ycanvas-$ay*$pmin]
    clear
}
# **************************** resizeb *********************************
proc resizeb {} {
    global axb bxb ayb byb xcanvas ycanvas bymax bymin bxmax bxmin

    set axb [expr $xcanvas/($bxmax-$bxmin)]
    set bxb [expr -$axb*$bxmin]
    set ayb [expr -$ycanvas/($bymax-$bymin)]
    set byb [expr $ycanvas-$ayb*$bymin]
    clear
}
# **************************** setextra ********************************
proc setextra {var} {
    global phis phisn pmax pmin pmaxmin npoints nperiods fold pbounds
    global sinphis sign phimax phimin delphi twopi pi abovetransition
    global phigen phicav phicavn iratio igen vgen ibeam vbeam
    global beamload kstrength kstrengthb

    switch -exact $var {
        abovetransition {
            if {$abovetransition} {     ;# Gets here before it is reset
		set sign -1
	    } else {
		set sign 1
	    }
        }
        k {
	    setkstrength
            clear
        }
        phis {
            set phis [expr $phisn*$pi]
            set sinphis [expr sin($phis)]
	    setkstrength
            clear
        }
        pmax {
            set pbounds [expr 10.*$pmax]
            if {$pmaxmin} {set pmin [expr -$pmax]}
            resize
            clear
        }
        pmin {
            if {$pmaxmin} {
                set pmax [expr -$pmin]
                set pbounds [expr 10.*$pmax]
            }
            resize
            clear
        }
        npoints {
        }
        nperiods {
            set phimax [expr $phimin+double($nperiods)*$twopi]
            set delphi [expr $phimax-$phimin]
            resize
            clear
        }
        pmaxmin {
            set pmaxmin [expr !$pmaxmin]
            setextra pmax
        }
        fold {
        }
        phicav {
            set phicav [expr $phicavn*$pi]
	    setkstrength
        }
        iratio {
            set ibeam [expr $iratio*$igen]
            set vbeam [expr $iratio*$vgen]
	    setkstrength
        }
        beamload {
	    setkstrength
        }
    }
}
# **************************** setkstrength *****************************
proc setkstrength {} {
    global kstrength kstrengthb  beamload
    global pi phi0 phis
    global phicav phigen phibeam igen vgen vcav phivcav ibeam vbeam
    global xcanvas ycanvas xpixb0 ypixb0

# No beam loading
    if {!$beamload} {
	set kstrengthb $kstrength
	.canvasb delete line
	.canvasb delete grid
	return
    }
# Delete old lines
    .canvasb delete grid
# Legend
    set y [expr $ycanvas-10]
    set del 25
    set x 50
    .canvasb create text $x $y -text "Ig" -tags grid -fill Green -anchor w
    set x [expr $x+$del]
    .canvasb create text $x $y -text "Vg" -tags grid -fill Green3 -anchor w
    set x [expr $x+$del]
    .canvasb create text $x $y -text "Ib" -tags grid -fill LightBlue -anchor w
    set x [expr $x+$del]
    .canvasb create text $x $y -text "Vb" -tags grid -fill Blue -anchor w
    set x [expr $x+$del]
    .canvasb create text $x $y -text "Vc" -tags grid -fill Black -anchor w
    set x [expr $x+$del]
    .canvasb create text $x $y -text "Vr" -tags grid -fill Red -anchor w
    set x [expr $x+$del]
    .canvasb create text $x $y -text "Iparticle" -tags grid -fill SteelBlue2 -anchor w
# Define pixel coordinates for 0
    set xpixb0 [xpixb 0]
    set ypixb0 [ypixb 0]
# Set beam phase
    set phibeam $pi
    set cartib [polar2cart $ibeam $phibeam]
    arrow $cartib LightBlue grid
    set cartvb [polar2cart $vbeam [expr $phibeam+$phicav]]
    arrow $cartvb Blue grid
# Generator
    set theta [expr $phis-$pi/2-$phicav]
    set val $vbeam/$vgen*sin($theta)
    if {$val > 1 || $val < -1} {
	errmsg "Cannot adjust cavity with these parameters"
	return
    }
    set phigen [expr $theta-asin($val)]
    set cartig [polar2cart $igen $phigen]
    arrow $cartig Green grid
    set cartvg [polar2cart $vgen [expr $phigen+$phicav]]
    arrow $cartvg Green3 grid
# Cavity
    set cartvc [list \
		  [expr [lindex $cartvg 0]+[lindex $cartvb 0]] \
		  [expr [lindex $cartvg 1]+[lindex $cartvb 1]]]
    arrow $cartvc Black grid
    set polarvc [cart2polar [lindex $cartvc 0] [lindex $cartvc 1]]
    set vcav [lindex $polarvc 0]
    set phivcav [lindex $polarvc 1]
# Effective strength
    set kstrengthb [expr $kstrength*$vcav]
}
# **************************** start ***********************************
proc start {x y} {
    global phi0 p0

    point $x $y
    set phi0 [pixx $x]
    set p0 [pixy $y]
#    puts "x=$x y=$y phi0=$phi0 p0=$p0 (Start)"
    cont
}
# **************************** step ************************************
proc step {} {
    iterate
}
# **************************** optimize ********************************
proc optimize {} {
    global phis phicav phigen phicavn vbeam pi vcav

    set i 0
    while 1 {
	setkstrength
	if {abs($phigen-$phis+$pi/2) < .001} {
	    break
	} else {
	    set val [expr $vbeam/$vcav*sin($phis-$pi/2)]
	    if {$val > 1 || $val < -1} {
		errmsg "Cannot optimize cavity with these parameters"
		return
	    }
	    set phicav [expr -asin($val)]
	}
	incr i
	if {$i > 50} {
	    errmsg "Failed to converge"
	    break
	}
    }
    set phicavn [format "%.3f" [expr $phicav/$pi]]
}
# **************************** xpix ************************************
proc xpix {x} {
    global ax bx

    expr round($ax*$x+$bx+.5)
}
# **************************** xpixb ***********************************
proc xpixb {x} {
    global axb bxb

    expr round($axb*$x+$bxb+.5)
}
# **************************** ypix ************************************
proc ypix {y} {
    global ay by

    expr round($ay*$y+$by+.5)
}
# **************************** ypixb ***********************************
proc ypixb {y} {
    global ayb byb

    expr round($ayb*$y+$byb+.5)
}

# **********************************************************************
# **************************** main ************************************
# **********************************************************************
set name "Synchrotron Motion"
set overview [overviewtext]
set version "Version 1.0"

#APSResetDefaultFont -adobe-courier-bold-r-normal-*-*-120-75-75-*-*-*-*

APSApplication . -name $name -version $version -overview $overview \
  -contextHelp "Sorry, there is no context help available for this widget."

set framepad 2
set tcl_precision 17
#set tk_strictMotif 1
set pi [expr acos(-1.)]
set twopi [expr 2*$pi]
set npoints 1000
set nperiods 1
#set kstrength .2
set kstrength .001
set phimin -$pi
set phimax [expr $phimin+$nperiods*$twopi]
set delphi [expr $phimax-$phimin]
set phisn 1
set phis [expr $phisn*$pi]
set abovetransition 1
set sign 1
#set sign [expr (cos($phis)<0.)?1:-1]
set phi0 0
set p0 0
set sinphis [expr sin($phis)]
set pmax .1
set pmin -$pmax
set pmaxmin 1
set pbounds [expr 10.0*$pmax]
set bxmax 1.4
set bxmin -$bxmax
set bymax 1.4
set bymin -$bymax
set xcanvas 400
set ycanvas 300
set fold 1
set beamload 1
set abort 0
#set dot "@/home/phoebus/EVANS/src/tcl/dot.bmp"
image create bitmap dot \
  -data "#define dot_width 1 #define dot_height 1 \
         static unsigned char dot_bits[] = { 0x01};"

set phicavn 0
set phicav [expr $phicavn*$pi]
set phibeam $pi
set igen 1.2
set vgen 1
set iratio .5
set ibeam [expr $iratio*$igen]
set vbeam [expr $iratio*$vgen]

# Frame0
frame .frame0 -relief flat -bd 2
pack .frame0 -in .userFrame -side top -fill x

# Parameters
frame .pframe -relief flat -bd 2
pack .pframe -in .frame0 -side left -fill x

frame .pframe1 -relief flat -bd 2
pack .pframe1 -in .pframe -side top -fill x

frame .pframe11
pack .pframe11 -in .pframe1 -side left
set w .pframe11

APSLabeledEntry .kframe -parent $w -label "K:" \
-textVariable kstrength  -width 6 -contextHelp \
"Relative strength (eV/E).  A value of .001 is typical of real electron\
 machines.  A value of .2 (and Pmax = 1) makes things\
 happen faster.  A value of 1 or greater (and Pmax >= 5)\
 with Fold enabled gives interesting chatotic behavior."
bind $w.kframe.entry <Return> {setextra k}

APSLabeledEntry .phisframe -parent $w -label "Phis/Pi:" \
-textVariable phisn  -width 6 -contextHelp \
"Synchronous phase in units of pi.   If above transition the\
 sychronous phase should be between Pi/2 and 3Pi/2 for stability.  If below\
 transition, the synchronous phase should be between -Pi/2 and Pi/2.  The\
 generator voltage is assumed to be a sine wave, and the synchronous phase\
 is measured from the start of the sine wave."
bind $w.phisframe.entry <Return> {setextra phis}

APSLabeledEntry .pmaxframe -parent $w -label "Pmax:" \
-textVariable pmax  -width 6 -contextHelp \
"Vertical axis upper limit.  Needs to increase as K increases."
bind $w.pmaxframe.entry <Return> {setextra pmax}

APSLabeledEntry .pminframe -parent $w -label "Pmin:" \
-textVariable pmin  -width 6 -contextHelp \
"Vertical axis lower limit.  Needs to decrease as K increases."
bind $w.pminframe.entry <Return> {setextra pmin}

frame .pframe12
pack .pframe12 -in .pframe1 -side right
set w .pframe12

APSLabeledEntry .npointsframe -parent $w -label "Points per Trajectory:" \
-textVariable npoints  -width 6 -contextHelp \
"Number of points to calculate each time Button-1 or Continue is pressed."
bind $w.npointsframe.entry <Return> {setextra npoints}

APSLabeledEntry .nperiodsframe -parent $w -label "Periods:" \
-textVariable nperiods  -width 6 -contextHelp \
"Number of periods of Phi-Phis on the horizontal axis, centered about zero."
bind $w.nperiodsframe.entry <Return> {setextra nperiods}

APSCheckButtonFrame .optionsframe -parent $w \
  -label "" -buttonList {"Set Pmin=-Pmax" "Fold Angles" "Above Transition"} \
  -variableList {pmaxmin fold abovetransition} \
  -commandList {{setextra pmaxmin} {} {setextra abovetransition}}
set apsContextHelp($w.optionsframe.frame.button1) \
"Pmin will automatically be set to the negative of what you enter for Pmax."
set apsContextHelp($w.optionsframe.frame.button2) \
"If Fold is enabled, then points that are outside the displayed interval\
 will be mapped into the displayed interval."
set apsContextHelp($w.optionsframe.frame.button3) \
"Sets whether the ring is above transition or not.  If above transition the\
 sychronous phase should be between Pi/2 and 3Pi/2 for stability.  If below\
 transition, the synchronous phase should be between -Pi/2 and Pi/2.  The\
 generator voltage is assumed to be a sine wave, and the synchronous phase\
 is measured from the start of the sine wave."

# Plot Canvas
frame .canvasframe -relief sunken -bd 2
pack .canvasframe -in .pframe -side top -padx 20 -pady 10
canvas .canvas -cursor crosshair -width ${xcanvas} -height ${ycanvas} -bg white
pack .canvas -in .canvasframe -side top
bind .canvas <Button-1> "start %x %y"
set apsContextHelp(.canvas) \
"This plot shows the longitudinal phase space in terms of the coordinates\
 Phi-Phis and P-Ps, where s stands for the synchronous particle.  Clicking\
 Button-1 on the plot will show Npoints successive\
 values of these quantities starting with the point where the Button was\
 clicked.  Each value is the value when the particle passes through the cavity."

# Beam loading
frame .lframe -relief flat -bd 2
pack .lframe -in .frame0 -side left -fill x

frame .lframe1 -relief flat -bd 2
pack .lframe1 -in .lframe -side top -fill x

frame .lframe11
pack .lframe11 -in .lframe1 -side left
set w .lframe11

# Beam loading entries
APSLabeledEntry .phicavframe -parent $w -label "Phic/Pi:" \
-textVariable phicavn  -width 8 -contextHelp \
"Cavity phase in units of pi.  (Phase of beam voltage relative to beam current\
 or phase of generator voltage relative to generator current.)  This phase\
 may be used to tune the cavity off resonance.  Negative values are stabilizing\
 and positive values are destabilizing.  The effect is known as Robinson\
 instability."
bind $w.phicavframe.entry <Return> {setextra phicav}

APSLabeledEntry .ibeamframe -parent $w -label "Ib/Ig:" \
-textVariable iratio  -width 8 -contextHelp \
"Beam current relative to generator current or beam voltage relative to\
 generator voltage.  Larger values correspond to more beam loading.)"
bind $w.ibeamframe.entry <Return> {setextra iratio}

frame .lframe12
pack .lframe12 -in .lframe1 -side right
set w .lframe12

# Beam loading options
APSCheckButtonFrame .boptionsframe -parent $w \
  -label "" -buttonList {"Simulate Beam Loading"} \
  -variableList {beamload} -commandList {{setextra beamload}}
set apsContextHelp($w.optionsframe.frame.button1) \
"Simulate beam loading effects."

frame .separator -height 15
pack .separator -in $w

APSButton .optimizebutton -parent $w -text "Optimize Cavity" -command optimize \
  -packOption "-side top" \
  -contextHelp "Optimize the cavity by trying to line up the generator current\
   and the cavity voltage for the synchronous particle.  This minimizes the\
   input power."

# Beam Loading Canvas
frame .canvasbframe -relief sunken -bd 2
pack .canvasbframe -in .lframe -side top -padx 20 -pady 10
canvas .canvasb -cursor crosshair -width ${xcanvas} -height ${ycanvas} \
  -bg white
pack .canvasb -in .canvasbframe -side top
set apsContextHelp(.canvasb) \
"This plot shows the phasor diagram of the cavity.  All of the particles\
 together contribute to the beam loading and they will adjust so\
 that Vc makes an angle Phis-Pi/2 with the total beam current.  (The voltage\
 peak is ahead of the current peak by this angle.  Phis is defined assuming\
 the voltage is a sine wave and is measured from the zero, not the peak.)  The\
 total beam current of all the particles is taken to point to the right.\
 Since the average phase of the bunch is the synchronous phase, this direction\
 corresponds to the synchronous phase.  The induced beam\
 current, Ib, is directly opposite the real beam current of all the\
 particles.  The induced beam\
 voltage, Vb, is ahead of the induced beam current by the cavity\
 phase, Phic.  The generator voltage, Vg, is ahead of the generator\
 current, Ig, by the same amount, Phic.  (Phic is the angle of the\
 impedance, Zc, of the cavity and Vb = Ib Zc.)  The cavity voltage, Vc, is\
 the sum of Vb and Vg.  The projection of Vc on the real particle\
 current, Iparticle, is the accelerating voltage of the particle.  These\
 two quantities change depending on the phase of the particle.  The\
 other quantities are fixed in the phasor diagram."

# Buttons
frame .buttonframe
pack .buttonframe -in .userFrame -side top -fill x -fill y \
  -padx $framepad -pady $framepad
set w .buttonframe

APSButton .abortbutton -parent $w -text Stop -command {global abort; set abort 1} \
  -contextHelp "Stop the current set of iterations."
APSButton .contbutton -parent $w -text Continue -command cont \
  -contextHelp "Do the next set of iterations."
APSButton .stepbutton -parent $w -text Step -command step \
  -contextHelp "Do one iteration."
APSButton .clearbutton -parent $w -text Clear -command clear \
  -contextHelp "Clear the graph area."
APSButton .printbutton -parent $w -text Print -command print \
  -contextHelp "Save the graph area as a Postscript file named tsm.ps and\
   show it in Ghostview"
APSButton .done -parent $w -text Done -command exit \
  -contextHelp "Terminate the program."
pack $w.contbutton $w.stepbutton $w.clearbutton $w.printbutton $w.done \
  -in $w -side left -pady 5 -padx 5 -expand 1

resizeb
resize
setkstrength

# **************************** Emacs Editing Sequences *****************
# Local Variables:
# mode: tcl
# End:
