mirror of
https://github.com/TheAlgorithms/Java.git
synced 2025-12-19 07:00:35 +08:00
Added SimplePendulumRK4 (#6800)
* Added SimplePendulumRK4 * Fixed build issue. * Fixed build issue. * Fixed build issue.
This commit is contained in:
126
src/main/java/com/thealgorithms/physics/SimplePendulumRK4.java
Normal file
126
src/main/java/com/thealgorithms/physics/SimplePendulumRK4.java
Normal file
@@ -0,0 +1,126 @@
|
||||
package com.thealgorithms.physics;
|
||||
|
||||
/**
|
||||
* Simulates a simple pendulum using the Runge-Kutta 4th order method.
|
||||
* The pendulum is modeled with the nonlinear differential equation.
|
||||
*
|
||||
* @author [Yash Rajput](https://github.com/the-yash-rajput)
|
||||
*/
|
||||
public final class SimplePendulumRK4 {
|
||||
|
||||
private SimplePendulumRK4() {
|
||||
throw new AssertionError("No instances.");
|
||||
}
|
||||
|
||||
private final double length; // meters
|
||||
private final double g; // acceleration due to gravity (m/s^2)
|
||||
|
||||
/**
|
||||
* Constructs a simple pendulum simulator.
|
||||
*
|
||||
* @param length the length of the pendulum in meters
|
||||
* @param g the acceleration due to gravity in m/s^2
|
||||
*/
|
||||
public SimplePendulumRK4(double length, double g) {
|
||||
if (length <= 0) {
|
||||
throw new IllegalArgumentException("Length must be positive");
|
||||
}
|
||||
if (g <= 0) {
|
||||
throw new IllegalArgumentException("Gravity must be positive");
|
||||
}
|
||||
this.length = length;
|
||||
this.g = g;
|
||||
}
|
||||
|
||||
/**
|
||||
* Computes the derivatives of the state vector.
|
||||
* State: [theta, omega] where theta is angle and omega is angular velocity.
|
||||
*
|
||||
* @param state the current state [theta, omega]
|
||||
* @return the derivatives [dtheta/dt, domega/dt]
|
||||
*/
|
||||
private double[] derivatives(double[] state) {
|
||||
double theta = state[0];
|
||||
double omega = state[1];
|
||||
double dtheta = omega;
|
||||
double domega = -(g / length) * Math.sin(theta);
|
||||
return new double[] {dtheta, domega};
|
||||
}
|
||||
|
||||
/**
|
||||
* Performs one time step using the RK4 method.
|
||||
*
|
||||
* @param state the current state [theta, omega]
|
||||
* @param dt the time step size
|
||||
* @return the new state after time dt
|
||||
*/
|
||||
public double[] stepRK4(double[] state, double dt) {
|
||||
if (state == null || state.length != 2) {
|
||||
throw new IllegalArgumentException("State must be array of length 2");
|
||||
}
|
||||
if (dt <= 0) {
|
||||
throw new IllegalArgumentException("Time step must be positive");
|
||||
}
|
||||
|
||||
double[] k1 = derivatives(state);
|
||||
double[] s2 = new double[] {state[0] + 0.5 * dt * k1[0], state[1] + 0.5 * dt * k1[1]};
|
||||
|
||||
double[] k2 = derivatives(s2);
|
||||
double[] s3 = new double[] {state[0] + 0.5 * dt * k2[0], state[1] + 0.5 * dt * k2[1]};
|
||||
|
||||
double[] k3 = derivatives(s3);
|
||||
double[] s4 = new double[] {state[0] + dt * k3[0], state[1] + dt * k3[1]};
|
||||
|
||||
double[] k4 = derivatives(s4);
|
||||
|
||||
double thetaNext = state[0] + dt / 6.0 * (k1[0] + 2 * k2[0] + 2 * k3[0] + k4[0]);
|
||||
double omegaNext = state[1] + dt / 6.0 * (k1[1] + 2 * k2[1] + 2 * k3[1] + k4[1]);
|
||||
|
||||
return new double[] {thetaNext, omegaNext};
|
||||
}
|
||||
|
||||
/**
|
||||
* Simulates the pendulum for a given duration.
|
||||
*
|
||||
* @param initialState the initial state [theta, omega]
|
||||
* @param dt the time step size
|
||||
* @param steps the number of steps to simulate
|
||||
* @return array of states at each step
|
||||
*/
|
||||
public double[][] simulate(double[] initialState, double dt, int steps) {
|
||||
double[][] trajectory = new double[steps + 1][2];
|
||||
trajectory[0] = initialState.clone();
|
||||
|
||||
double[] currentState = initialState.clone();
|
||||
for (int i = 1; i <= steps; i++) {
|
||||
currentState = stepRK4(currentState, dt);
|
||||
trajectory[i] = currentState.clone();
|
||||
}
|
||||
|
||||
return trajectory;
|
||||
}
|
||||
|
||||
/**
|
||||
* Calculates the total energy of the pendulum.
|
||||
* E = (1/2) * m * L^2 * omega^2 + m * g * L * (1 - cos(theta))
|
||||
* We use m = 1 for simplicity.
|
||||
*
|
||||
* @param state the current state [theta, omega]
|
||||
* @return the total energy
|
||||
*/
|
||||
public double calculateEnergy(double[] state) {
|
||||
double theta = state[0];
|
||||
double omega = state[1];
|
||||
double kineticEnergy = 0.5 * length * length * omega * omega;
|
||||
double potentialEnergy = g * length * (1 - Math.cos(theta));
|
||||
return kineticEnergy + potentialEnergy;
|
||||
}
|
||||
|
||||
public double getLength() {
|
||||
return length;
|
||||
}
|
||||
|
||||
public double getGravity() {
|
||||
return g;
|
||||
}
|
||||
}
|
||||
Reference in New Issue
Block a user