Euler vs Verlet integration test leads to unexpected results
in
Programming Questions
•
3 months ago
Hi
I've been considering Verlet integration and thought I'd set up a test to see how it compared with Euler. The below code initially looked to compare the Euler calculation (the red line) to Verlet (the blue). Given how horrendously awful Euler is supposed to be I was expecting to see an immediate visible result but they tracked accurately together.
I added the println calculating the accurate offset value (referred to as "Newtonian") and compared it at regular time steps to the comparable Euler and Verlet values. When I run this sketch both Euler and Verlet show largely identical (the small differences down to float precision?) errors compared to the newtonian value until the Verlet value eventually, and inexplicably, starts to deviate more dramatically.
I thought Verlett was supposed to be more accurate? I'm guessing it's a code error but not sure where I've gone wrong on this one. Any help appreciated.
Thanks
Matt
I've been considering Verlet integration and thought I'd set up a test to see how it compared with Euler. The below code initially looked to compare the Euler calculation (the red line) to Verlet (the blue). Given how horrendously awful Euler is supposed to be I was expecting to see an immediate visible result but they tracked accurately together.
I added the println calculating the accurate offset value (referred to as "Newtonian") and compared it at regular time steps to the comparable Euler and Verlet values. When I run this sketch both Euler and Verlet show largely identical (the small differences down to float precision?) errors compared to the newtonian value until the Verlet value eventually, and inexplicably, starts to deviate more dramatically.
I thought Verlett was supposed to be more accurate? I'm guessing it's a code error but not sure where I've gone wrong on this one. Any help appreciated.
Thanks
Matt
- float deltaTime;
float cumulativeTime;
PVector globalAcceleration;
EulerMover eulerMover;
VerletMover verletMover;
void setup() {
size(1000, 600, P3D);
smooth(5);
frameRate(50);
deltaTime = 1;
cumulativeTime = 0;
globalAcceleration = new PVector(0.1, 0);
eulerMover = new EulerMover();
verletMover = new VerletMover();
}
void draw() {
translate(0, height/2);
eulerMover.update();
verletMover.update();
eulerMover.display();
verletMover.display();
cumulativeTime += deltaTime;
if (cumulativeTime%200==0) {
println("Newtonian = "+(0.5*globalAcceleration.x*sq(cumulativeTime))+", Euler = "+eulerMover.location.x+", Verlet = "+verletMover.location.x);
}
}
class EulerMover {
PVector location;
PVector velocity;
PVector acceleration;
EulerMover() {
location = new PVector(0, 0);
velocity = new PVector(0, 0);
acceleration = globalAcceleration.get();
}
void update() {
PVector deltaAcceleration = PVector.mult(acceleration, deltaTime);
velocity.add(deltaAcceleration);
PVector deltaVelocity = PVector.mult(velocity, deltaTime);
location.add(deltaVelocity);
}
void display() {
stroke(255, 0, 0);
line(location.x, location.y, location.x, location.y-20);
}
}
class VerletMover {
PVector location;
PVector previousLocation;
PVector acceleration;
VerletMover() {
location = new PVector(0, 0);
previousLocation = new PVector(0, 0);
acceleration = globalAcceleration.get();
}
void update() {
PVector deltaLocation = PVector.sub(location, previousLocation);
PVector deltaAcceleration = PVector.mult(acceleration, sq(deltaTime));
PVector increment = PVector.add(deltaLocation, deltaAcceleration);
previousLocation = location.get();
location.add(increment);
}
void display() {
stroke(0, 0, 255);
line(location.x, location.y, location.x, location.y+20);
}
}
1