Fermi Acceleration-A real scientific problem James A. Rome Tennessee Governor's Academy August 2010 The problem Enrico Fermi postulated an acceleration method for cosmic rays that has a simple physical model. Imagine a ball bouncing between two massive walls, one of which oscillates back and forth. The question to be solved is whether the ball can be accelerated to very large velocities u Top View V(t) Some Web links http://www.dynamical-systems.org/fermi/info.html and you can see an animation at http://www.dynamical-systems.org/fermi/index.html http://books.google.com/books?id=a0AABe1Hve8C&lpg=PA10&dq=velocity%20 of%20ball%20bouncing%20off%20moving%20wall&pg=PA10#v=onepage&q=vel ocity%20of%20ball%20bouncing%20off%20moving%20wall&f=false http://en.wikipedia.org/wiki/Fermi_acceleration http://en.wikipedia.org/wiki/Fermi%E2%80%93Ulam_model A ball bouncing off a stationary wall u ? Wall Assumptions: The ball is a point located at its center The ball is perfectly elastic (think superball) The Wall is infinitely massive and absorbs no energy in the collision The collision is instantaneous If energy (mv2/2) is conserved, and if the wall does not move, the speed after the collision must equal the speed before the collision, but the direction is reversed. The ball bounces off the wall with velocity = -u This is in accord with your experiences. Between collisions, the ball moves at a constant velocity (with no external forces) A ball bouncing off a moving wall V u=0 Wall After u=? How do you solve this problem? First suppose the ball is sitting still, and it is hit by the wall that moves at V towards the ball If you ever played ping pong or tennis, you will know that the ball goes to the right—but how fast? Use the special theory of relativity V Wall ? Einstein said that physics must be the same when viewed from any system moving at a constant velocity. Example: You sit in your moving car and toss a ball up. To you it looks just like it would if you were not in the car. The ball goes straight up and straight down. But to someone on the ground, the ball will move in a parabola. So what do you see if you sit on the wall and solve this problem? Viewed sitting on the wall moving at V V ? Wall You see the ball approaching you with velocity V I think we have already solved this problem. . . Viewed sitting on the wall moving at V V ? Wall You see the ball approaching you with velocity V I think we have already solved this problem. . . The ball bounces off the wall with velocity V in the opposite direction But the wall is already moving to the right at V So in the Lab frame, the ball goes to the right at 2V That is why Fermi thought you could make it get faster! Viewed sitting on the wall moving at V V ? Wall If the ball is moving towards the wall with speed u, after the collision it moves right with speed u + 2V The ball gains energy because the wall is moving, and we assumed it was infinitely massive. Whatever is moving the wall puts energy into the ball. You see the ball approaching you with velocity V I think we have already solved this problem. . . The ball bounces off the wall with velocity V in the opposite direction But the wall is already moving to the right at V So in the Lab frame, the ball goes to the right at 2V That is why Fermi thought you could make it get faster! Velocity of the wall A light ball bounces in one dimension between two massive walls. One wall oscillates with a velocity given by V(t) = (V/4)[1 - 2{t}] where {t} is the fractional part of t (denoted by ft in the code). V(t) | | V/4|\ |\ |\ |\ |\ |\ | \ | \ | \ | \ | \ | \ | --|--\--|--\--|--\--|--\--|--\--|--\--|- t |0 \ |1 \ |2 \ |3 \ |4 \ |5 \ |6 | \| \| \| \| \| \| | A little calculus... (plane geometry) V(t) The velocity is the time rate of change of the distance (m/s) which means the velocity is the slope of the position of the wall. The position is the area under the velocity curve up to time t area of little triangle = (1/2)*(1/2-{t})*V({t})= (V/4)[1/2 - {t}]2 V/4 {t} -V/4 1 t distance = area of trapezoid = area of big triangle area of little triangle = (V/16) – (V/4)[1/2 - {t}]2 {t=1/2} area = base * height/2 = (1/2)*(1/2)*(V/4) = V/16 = max oscillation A little calculus... V(t) The velocity is the time rate of change of the distance (m/s) which means the velocity is the slope of the position of the wall. The position is the area under the velocity curve up to time t area of little triangle = (1/2)*(1/2-{t})*V({t})= (V/4)[1/2 - {t}]2 V/4 {t} -V/4 1 t For {t} > 1/2, the area under the curve is the area of the positive triangle – area of the dotted triangle (note that V < 0) = V/16 + (1/2)[{t} – (1/2)]*(V/4)[1 – 2{t}] = V/16 - (V/4)[{t} - (1/2)]2 distance = area of trapezoid = area of big triangle area of little triangle = (V/16) – (V/4)[1/2 - {t}]2 {t=1/2} area = base * height/2 = (1/2)*(1/2)*(V/4) = V/16 = max oscillation A little calculus... V(t) The velocity is the time rate of change of the distance (m/s) which means the velocity is the slope of the position of the wall. The position is the area under the velocity curve up to time t area of little triangle = (1/2)*(1/2-{t})*V({t})= (V/4)[1/2 - {t}]2 V/4 {t} -V/4 1 t For {t} > 1/2, the area under the curve is the area of the positive triangle – area of the dotted triangle= V/16 – (1/2)[{t} – (1/2)]*(V/4)[1 – 2{t}] = V/16 + (V/4)[{t} - (1/2)]2 distance = area of trapezoid = area of big triangle area of little triangle = (V/16) – (V/4)[1/2 - {t}]2 Sanity check: d = 0 at {t} = 0, 1 d = V/16 at {t} = ½ It is two parabolas! {t=1/2} area = base * height/2 = (1/2)*(1/2)*(V/4) = V/16 = max oscillation When do we need to “solve” this? Most of the time, the ball is bouncing from the bouncing wall to the fixed wall and back again. It will maintain its speed during this process The speed changes only when it hits the bouncing wall. The velocity of the ball just before the nth collision with the oscillating wall is (un = vball/V) The ball leaves the collision with its initial velocity (-un) + 2*Vwall({t})/V and remember that Vwall(t) = (V/4)[1 - 2{t}] speed = |un + 2*(1/4)[2{tn} – 1]| => un+1 = |un + {tn} – 1/2| How long between bounces? If we assume the distance between the walls (d) is much greater than the amplitude of the oscillation (V/16), the ball goes a distance 2d between bounces with the moving wall. distance = speed * time, so, remembering that Vun+1 i the speed just before the n+1 collision, tn+1 = tn + 2d/(Vun+1) = tn + M/un+1 where M = 2d/V, and {tn+1}= {{tn} + M/un+1} So, what do we need to plot? u vs {t} u vs iteration Can we predict the output? It is chaotic, so NO The GUI . . . PhaseCanvas TimeCanvas How do we do this using Java? Make a new Project • Make a New Java Desktop Application • Call it FermiPlot • As before, remove the status panel, the progress bar, the code after initComponents(), and the variables for the progress bar at the end of the code. • You can change the name of the project and the other information in the resources. • Save the project. Start with the physics calculation Make a new Class called FermiCalc Need calculations in separate thread to keep the GUI responsive public class FermiCalc extends Thread // Run in a separate thread { PhaseCanvas pc; // The left plot area TimeCanvas tc; // The right plot area private static final int NCURVE = 7; private float M = 10.0f; private static final Color[] colors = {Color.black, Color.blue, Color.cyan, Color.red, Color.green, Color.magenta, Color.orange}; // The constructor to instantiate the class instance public FermiCalc(PhaseCanvas pc, TimeCanvas tc) { // Get and store the two drawing canvases this.pc = pc; this.tc = tc; } // Other methods go here } FermiCalc A Thread must have a run() method that does the work public void run(){ float u[] = new float[2]; // Relative velocity before/after collision float ft[] = new float[2]; // Fractional parts of t float nstep[] = new float[2]; // Steps (need float for the plot) /* Pick interesting starting points (NCURVE=7 of them) */ double[] ustart = {M, M, .4*Math.sqrt((double)M), 1.45*M,1.5*M, 2.0*M, M}; double[] tstart = {.1, .4, .5, .5, 0.0, .5, 0.0}; int[] stepmax = {500, 500, 4000, 2000, 4000, 4000,4000, 4000}; for (int i = 0; i < NCURVE; i++) // For each curve { u[0] = (float)ustart[i]; ft[0] = (float)tstart[i]; nstep[0] = 0.0f; for (int n = 1; n < stepmax[i]; n++) // Iterate for each bounce { . . .// THE CODE THAT DOES THE WORK GOES HERE (next slide) } } } FermiCalc (continued) nstep[1] = (float)n; // The iteration number. Cast to float u[1] = Math.abs(u[0] + ft[0] - .5f); // u_n+1 = |u_n + {t_n} - 1/2| ft[1] = ft[0] + (M/u[1]); // The time of the bounce while (ft[1] > 1.0f) // Get its fractional part ft[1] -= 1.0f; // could use ft[1] - (float)Math.floor((double)ft[1]) // Phase plot pc.symbol(ft[1], u[1], colors[i]); // Plot a symbol at the new point // Time plot tc.curve(nstep, u,colors[i]); // Plot line between the points // Prepare for the next iteration u[0] = u[1]; ft[0] = ft[1]; nstep[0] = nstep[1]; // add a delay so we can watch the plot happening try { // This is new. Some methods throw an exception if a problem Thread.sleep(5); // In this case, sleep throws one when its over // 5 millisecs } catch(InterruptedException ex) { Remember that the two canvases } What happens if ft, u change before they get plotted? are Swing components and that Swing is processing many events. It is a bad idea to call methods in Swing from outside the EventQueue. See next slide for the correct way. Putting events on the EventQueue Can only pass final variables into final float u1 = u[1]; invokeLater so that the things we final float ft1 = ft[1]; pass in do not change final int i1 = i; Note that we are defining // Phase plot a new anonymous class EventQueue.invokeLater(new Runnable() { (we never need it's name) to spawn a Thread that public void run() { will sit on the Swing event pc.symbol(ft1, u1, colors[i1]); queue until Swing is } // end of run() ready to process it. } ); //end of call We must implement the run() method // Time plot final float uf[] = {u[0], u[1]}; final float nstepf[] = {nstep[0], nstep[1]}; EventQueue.invokeLater(new Runnable() { public void run() { tc.curve(nstepf, uf,colors[i1]); } There is also }); EventQueue.invokeAndWait(new Runnable()…) for when we want our call processed before continuing PhaseCanvas The strategy is to make a class that extends JPanel (one of the Java containers). It is a rectangle that we can draw in. We will add PhaseCanvas to the Swing Component palate and then we can add to to our GUI. We can do this because all Swing components are Java Beans. All we have to do is to override the paintComponent() method of the JPanel to make our plot. PhaseCanvas public class PhaseCanvas extends JPanel { symbol() is called by FermiCalc public PhaseCanvas() {} // Constructor @Override when it has some data to plot. public void paintComponent(Graphics g) { It puts the data into a DataPoint super.paintComponent(g); and adds it to the end of a // More code to come Vector } public void symbol(float x, float y, Color c ){ pts.add(new DataPoint(x, y, c)); this.repaint(); // Force JPanel to be redrawn with this point in it } private float M = 10.0f; // Data members of PhaseCanvas class private Vector<DataPoint> pts = new Vector<DataPoint>(); private int npts = 0; // Define a new internal class to hold the data of one point private class DataPoint { protected float x; // protected variables can be accessed protected float y; // by classes in this package protected Color c; private DataPoint(float x, float y, Color c) { this.x = x; this.y = y; <DataPoint> tells the compiler this.c = c; that this vector is composed } of DataPoints. If you try to add } // End of DataPoint class something else, you get a } // End of PhaseCanvas class compiler error. PhaseCanvas.paintComponent() @Override public void paintComponent(Graphics g) { super.paintComponent(g); Graphics2D g2d = (Graphics2D)g; // cast to Graphics2D which has int width = this.getWidth(); // many drawing methods int height = this.getHeight(); // Get the JPanel dimensions g2d.drawRect(0,0,width-1,height-1); // Outline the panel AffineTransform t = new AffineTransform(); // Next Slide t.translate(0, (double) height); t.scale(1.0, -1.0); t.scale((double)width, (double)height/(2.0*M)); for(int i = 0; i < pts.size(); i++) { // Draw all the points DataPoint dp = (DataPoint)pts.elementAt(i); g2d.setColor(dp.c); // We need to draw in pixel space, so must use the transform Point2D.Float inPt = new Point2D.Float(dp.x, dp.y); Point2D.Float outPt = new Point2D.Float(); t.transform(inPt, outPt); g2d.drawRect((int)outPt.x -1, (int)outPt.y -1, 1, 1); } } Affine Transforms 0, 0 width, 0 1.0, 2M 0.0, 2M PhaseCanvas FermiCalc ? 0, height width,height 0.0, 0.0 1.0, 0.0 FermiCalc calculated u in units of M , and {t} goes from 0 to 1. How do we plot this in pixel space? We use an affine transform which is some fancy matrix algebra (good reason to do more math!) But I can never remember how it works, so I always draw some pictures to help me break it down into easy-to-understand steps Affine Transforms 0, 0 1.0, 2M 0.0, 2M width, 0 PhaseCanvas FermiCalc ? 0, height 0.0, 0.0 width,height scale(width/1.0, height/2M) translate(0.0, height) 0.0, -height 1.0, 0.0 width, -height 0.0, height width, height scale(1.0, -1.0) 0.0, 0.0 We do the steps backwards in the code width, 0.0 0.0, 0.0 width, 0.0 t.translate(0, (double) height); t.scale(1.0, -1.0); t.scale((double)width, (double)height/(2.0*M)); TimeCanvas is very similar public class TimeCanvas extends JPanel { public TimeCanvas() { } @Override curve() is called from FermiCalc public void paintComponent(Graphics g) { when new iteration s are ready super.paintComponent(g); to be plotted // More code to come . . . } public void curve(float x[], float y[], Color c) { linesegs.add(new Lines(x, y, c)); this.repaint(); // Repaint TimeCanvas to display new curve } private float M = 10.0f; Vector<Lines> linesegs = new Vector<Lines>() } // Define a private class to store the plot vectors private class Lines { protected Point2D.Float[] p2d = new Point2D.Float[2]; protected Color c; protected Lines(float x[], float y[], Color c) { p2d[0] = new Point2D.Float(x[0], y[0]); p2d[1] = new Point2D.Float(x[1], y[1]); this.c = c; } } TimeCanvas.paintComponent() @Override public void paintComponent(Graphics g) { super.paintComponent(g); Graphics2D g2d = (Graphics2D)g; // cast to Graphics2D int width = this.getWidth(); int height = this.getHeight(); g2d.drawRect(0,0,width-1,height-1); // Draw a box around the plot AffineTransform t = new AffineTransform(); t.translate(0, (double) height); t.scale(1.0, -1.0); t.scale((double)width/4000.0, (double)height/(2.0*M)); for(int i = 0; i < linesegs.size(); i++) { Lines lns = (Lines)linesegs.elementAt(i); g2d.setColor(lns.c); // We need to draw in pixel space, so must use the transform Point2D.Float[] inPts = lns.p2d; Point2D.Float[] outPts = new Point2D.Float[2]; t.transform(inPts, 0, outPts, 0, 2); // Note that we have to draw in integer coordinates (pixels) g2d.drawLine((int)outPts[0].x, (int)outPts[0].y, (int)outPts[1].x, (int)outPts[1].y); } } Add the canvases to your Palette •First, right-click the FermiPlot project and pick Clean and build (otherwise this will not work) - The palette components are taken from the compiled canvases (in the jar file in the dist directory) •Click Tools, Palette, Swing/AWT Components Add components from your project Add to Palette (pick the project) Add to Palette Your components are now available PhaseCanvas TimeCanvas Labels In design view, Add the two canvases and all the labels. • Make sure that the labels are pinned to their canvases, and that the canvases are pinned to the sides and bottom of the mainPanel. • I used copy and paste to replicate the identical labels • Save, clean and build, and run your project. Make sure that the labels and windows behave properly when you resize things. FermiPlotView code These are the names you called public FermiPlotView() { the two canvases in the GUI builder initComponents(); // NetBeans code // instantiate the calculation FermiCalc fc = new FermiCalc(phaseCanvas, timeCanvas); fc.setM(10.0f); // I left these out before, setting M=10 in the code phaseCanvas.setM(10.0f); timeCanvas.setM(10.0f); disableDoubleBuffering(phaseCanvas); // So you can watch the plot disableDoubleBuffering(timeCanvas); // Otherwise it happens off screen // start the calculation fc.start(); // this starts FermiCalc in its thread by calling fc.run() } /** * * @param c - the component to have double buffering disabled */ private void disableDoubleBuffering( Component c ) { RepaintManager currentManager = RepaintManager.currentManager(c); currentManager.setDoubleBufferingEnabled(false); } // . . . the rest of the code Optionally, change the Information This will change the title of the Application window The Answer . . . Documentation: JavaDocs •Click on the FermiPlot Source Packages •Run/Generate JavaDoc •file:///Users/jar/Documents/T GA/Projects/FermiPlot/dist/ja vadoc/index.html will show you documentation for your Project •But we did not insert many JavaDoc comments…