package org.openpixi.pixi.ui;
import java.awt.event.ActionEvent;
import java.awt.event.ActionListener;
import java.io.FileNotFoundException;
import java.io.IOException;
import java.util.ArrayList;
import java.util.logging.Level;
import java.util.logging.Logger;
import javax.swing.Timer;
import org.openpixi.pixi.physics.InitialConditions;
import org.openpixi.pixi.physics.Settings;
import org.openpixi.pixi.physics.Simulation;
import org.openpixi.pixi.physics.collision.algorithms.CollisionAlgorithm;
import org.openpixi.pixi.physics.collision.algorithms.MatrixTransformation;
import org.openpixi.pixi.physics.collision.algorithms.SimpleCollision;
import org.openpixi.pixi.physics.collision.algorithms.VectorTransformation;
import org.openpixi.pixi.physics.collision.detectors.AllParticles;
import org.openpixi.pixi.physics.collision.detectors.Detector;
import org.openpixi.pixi.physics.collision.detectors.SweepAndPrune;
import org.openpixi.pixi.physics.force.CombinedForce;
import org.openpixi.pixi.physics.force.ConstantForce;
import org.openpixi.pixi.physics.force.Force;
import org.openpixi.pixi.physics.force.SimpleGridForce;
import org.openpixi.pixi.physics.force.relativistic.ConstantForceRelativistic;
import org.openpixi.pixi.physics.force.relativistic.SimpleGridForceRelativistic;
import org.openpixi.pixi.physics.movement.boundary.ParticleBoundaryType;
import org.openpixi.pixi.physics.solver.Boris;
import org.openpixi.pixi.physics.solver.BorisDamped;
import org.openpixi.pixi.physics.solver.Euler;
import org.openpixi.pixi.physics.solver.EulerRichardson;
import org.openpixi.pixi.physics.solver.LeapFrog;
import org.openpixi.pixi.physics.solver.LeapFrogDamped;
import org.openpixi.pixi.physics.solver.LeapFrogHalfStep;
import org.openpixi.pixi.physics.solver.SemiImplicitEuler;
import org.openpixi.pixi.physics.solver.relativistic.BorisRelativistic;
import org.openpixi.pixi.physics.solver.relativistic.LeapFrogRelativistic;
import org.openpixi.pixi.physics.solver.relativistic.SemiImplicitEulerRelativistic;
import org.openpixi.pixi.ui.panel.Particle2DPanel;
import org.openpixi.pixi.ui.util.FrameRateDetector;
/**
* Wrapper for the simulation class in GUI applications.
*/
public class SimulationAnimation {
private Simulation s;
private boolean relativistic = false;
private boolean calculateFields = false;
/** Milliseconds between updates */
private int interval = 30;
/** Timer for animation */
private Timer timer;
private FrameRateDetector frameratedetector;
private ArrayList<SimulationAnimationListener> listeners = new ArrayList<SimulationAnimationListener>();
/** Constructor */
public SimulationAnimation() {
timer = new Timer(interval, new TimerListener());
frameratedetector = new FrameRateDetector(500);
s = InitialConditions.initRandomParticles(10, 2);
}
/** Listener for timer */
public class TimerListener implements ActionListener {
public void actionPerformed(ActionEvent eve) {
try {
s.step();
} catch (FileNotFoundException ex) {
Logger.getLogger(Particle2DPanel.class.getName()).log(Level.SEVERE, null, ex);
} catch (IOException ex2) {
Logger.getLogger(Particle2DPanel.class.getName()).log(Level.SEVERE, null, ex2);
}
frameratedetector.update();
repaint();
}
}
public void startAnimation() {
timer.start();
}
public void stopAnimation() {
timer.stop();
//test = false;
}
public Simulation getSimulation() {
return s;
}
public FrameRateDetector getFrameRateDetector() {
return frameratedetector;
}
public Timer getTimer() {
return timer;
}
/**
* Add Listener for repaint() event.
* @param listener
*/
public void addListener(SimulationAnimationListener listener) {
listeners.add(listener);
}
/**
* Removes Listener for repaint() event.
* @param listener
*/
public void removeListener(SimulationAnimationListener listener) {
listeners.remove(listener);
}
private void repaint() {
// Let all listeners know
for (SimulationAnimationListener l : listeners) {
l.repaint();
}
}
private void clear() {
// Let all listeners know
for (SimulationAnimationListener l : listeners) {
l.clear();
}
}
public void resetAnimation(int id) {
// timer.restart();
timer.stop();
clear();
switch(id) {
case 0:
s = InitialConditions.initRandomParticles(10, 2);
break;
case 1:
s = InitialConditions.initRandomParticles(100, 1);
break;
case 2:
s = InitialConditions.initRandomParticles(1000, 0.5);
break;
case 3:
s = InitialConditions.initRandomParticles(10000, 0.01);
break;
case 4:
s = InitialConditions.initGravity(1, 2);
break;
case 5:
s = InitialConditions.initElectric(1, 2);
break;
case 6:
s = InitialConditions.initMagnetic(3, 2);
break;
case 7:
s = InitialConditions.initPair(0.1,1);
break;
case 8:
s = InitialConditions.initTwoStream(0.1,1,1000);
break;
case 9:
s = InitialConditions.initWeibel(0.01,1,2000,4,0.9);
break;
case 10:
s = InitialConditions.initOneTest(0.01,1);
break;
case 11:
s = InitialConditions.initWaveTest(0.2);
break;
}
updateFieldForce();
s.prepareAllParticles();
s.turnGridForceOn();
timer.start();
}
/**
* Reset animation according to settings
*
* @param settings New settings for animation.
*/
public void resetAnimation(Settings settings) {
// timer.restart();
timer.stop();
clear();
s = new Simulation(settings);
//updateFieldForce();
s.prepareAllParticles();
//s.turnGridForceOn();
timer.start();
}
public void calculateFields() {
calculateFields =! calculateFields;
updateFieldForce();
}
private void updateFieldForce() {
if(calculateFields) {
s.turnGridForceOn();
}
else {
s.turnGridForceOff();
}
}
public void algorithmChange(int id)
{
s.completeAllParticles();
switch(id) {
case 0:
s.getParticleMover().setSolver(new EulerRichardson());
break;
case 1:
s.getParticleMover().setSolver(new LeapFrog());
break;
case 2:
s.getParticleMover().setSolver(new LeapFrogDamped());
break;
case 3:
s.getParticleMover().setSolver(new LeapFrogHalfStep());
break;
case 4:
s.getParticleMover().setSolver(new Boris());
break;
case 5:
s.getParticleMover().setSolver(new BorisDamped());
break;
case 6:
s.getParticleMover().setSolver(new SemiImplicitEuler());
break;
case 7:
s.getParticleMover().setSolver(new Euler());
break;
}
s.prepareAllParticles();
}
public void relativisticEffects(int i) {
relativistic =! relativistic;
if(relativistic == false) {
s.relativistic = false;
if (s.f instanceof CombinedForce) {
ArrayList<Force> forces = ((CombinedForce) s.f).forces;
for (int j = 0; j < forces.size(); j++) {
if (forces.get(j) instanceof ConstantForceRelativistic){
forces.set(j, new ConstantForce());
}
if (forces.get(j) instanceof SimpleGridForceRelativistic){
forces.set(j, new SimpleGridForce());
}
}
}
switch(i) {
case 1:
s.getParticleMover().setSolver(new LeapFrog());
case 4:
s.getParticleMover().setSolver(new Boris());
break;
case 6:
s.getParticleMover().setSolver(new SemiImplicitEuler());
break;
}
}
if(relativistic == true) {
s.relativistic = true;
//System.out.println("relativistic version on");
if (s.f instanceof CombinedForce) {
ArrayList<Force> forces = ((CombinedForce) s.f).forces;
for (int j = 0; j < forces.size(); j++) {
if (forces.get(j) instanceof ConstantForce){
forces.set(j, new ConstantForceRelativistic(s.getSpeedOfLight()));
}
if (forces.get(j) instanceof SimpleGridForce){
forces.set(j, new SimpleGridForceRelativistic(s));
}
}
}
switch(i) {
case 1:
s.getParticleMover().setSolver(new LeapFrogRelativistic(s.getSpeedOfLight()));
case 4:
s.getParticleMover().setSolver(new BorisRelativistic(s.getSpeedOfLight()));
break;
case 6:
s.getParticleMover().setSolver(new SemiImplicitEulerRelativistic(s.getSpeedOfLight()));
break;
}
}
}
public void collisionChange(int i) {
switch(i) {
case 0:
s.detector = new Detector();
s.collisionalgorithm = new CollisionAlgorithm();
break;
case 1:
s.detector = new AllParticles(s.particles);
break;
case 2:
s.detector = new SweepAndPrune(s.particles);
break;
}
}
public void algorithmCollisionChange(int i) {
switch(i) {
case 0:
s.collisionalgorithm = new SimpleCollision();
break;
case 1:
s.collisionalgorithm = new VectorTransformation();
break;
case 2:
s.collisionalgorithm = new MatrixTransformation();
break;
}
}
public void boundariesChange(int i) {
switch(i) {
case 0:
s.getParticleMover().changeBoundaryType(ParticleBoundaryType.Hardwall);
break;
case 1:
s.getParticleMover().changeBoundaryType(ParticleBoundaryType.Periodic);
}
}
}