Skip to content

Commit 7b3dc8e

Browse files
Merge branch 'master' into my-mergeaccounts-branch
2 parents 490c540 + 8930369 commit 7b3dc8e

File tree

3 files changed

+389
-2
lines changed

3 files changed

+389
-2
lines changed

pom.xml

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -112,14 +112,14 @@
112112
<dependency>
113113
<groupId>com.puppycrawl.tools</groupId>
114114
<artifactId>checkstyle</artifactId>
115-
<version>12.0.1</version>
115+
<version>12.1.0</version>
116116
</dependency>
117117
</dependencies>
118118
</plugin>
119119
<plugin>
120120
<groupId>com.github.spotbugs</groupId>
121121
<artifactId>spotbugs-maven-plugin</artifactId>
122-
<version>4.9.7.0</version>
122+
<version>4.9.8.1</version>
123123
<configuration>
124124
<excludeFilterFile>spotbugs-exclude.xml</excludeFilterFile>
125125
<includeTests>true</includeTests>
Lines changed: 126 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,126 @@
1+
package com.thealgorithms.physics;
2+
3+
/**
4+
* Simulates a simple pendulum using the Runge-Kutta 4th order method.
5+
* The pendulum is modeled with the nonlinear differential equation.
6+
*
7+
* @author [Yash Rajput](https://github.com/the-yash-rajput)
8+
*/
9+
public final class SimplePendulumRK4 {
10+
11+
private SimplePendulumRK4() {
12+
throw new AssertionError("No instances.");
13+
}
14+
15+
private final double length; // meters
16+
private final double g; // acceleration due to gravity (m/s^2)
17+
18+
/**
19+
* Constructs a simple pendulum simulator.
20+
*
21+
* @param length the length of the pendulum in meters
22+
* @param g the acceleration due to gravity in m/s^2
23+
*/
24+
public SimplePendulumRK4(double length, double g) {
25+
if (length <= 0) {
26+
throw new IllegalArgumentException("Length must be positive");
27+
}
28+
if (g <= 0) {
29+
throw new IllegalArgumentException("Gravity must be positive");
30+
}
31+
this.length = length;
32+
this.g = g;
33+
}
34+
35+
/**
36+
* Computes the derivatives of the state vector.
37+
* State: [theta, omega] where theta is angle and omega is angular velocity.
38+
*
39+
* @param state the current state [theta, omega]
40+
* @return the derivatives [dtheta/dt, domega/dt]
41+
*/
42+
private double[] derivatives(double[] state) {
43+
double theta = state[0];
44+
double omega = state[1];
45+
double dtheta = omega;
46+
double domega = -(g / length) * Math.sin(theta);
47+
return new double[] {dtheta, domega};
48+
}
49+
50+
/**
51+
* Performs one time step using the RK4 method.
52+
*
53+
* @param state the current state [theta, omega]
54+
* @param dt the time step size
55+
* @return the new state after time dt
56+
*/
57+
public double[] stepRK4(double[] state, double dt) {
58+
if (state == null || state.length != 2) {
59+
throw new IllegalArgumentException("State must be array of length 2");
60+
}
61+
if (dt <= 0) {
62+
throw new IllegalArgumentException("Time step must be positive");
63+
}
64+
65+
double[] k1 = derivatives(state);
66+
double[] s2 = new double[] {state[0] + 0.5 * dt * k1[0], state[1] + 0.5 * dt * k1[1]};
67+
68+
double[] k2 = derivatives(s2);
69+
double[] s3 = new double[] {state[0] + 0.5 * dt * k2[0], state[1] + 0.5 * dt * k2[1]};
70+
71+
double[] k3 = derivatives(s3);
72+
double[] s4 = new double[] {state[0] + dt * k3[0], state[1] + dt * k3[1]};
73+
74+
double[] k4 = derivatives(s4);
75+
76+
double thetaNext = state[0] + dt / 6.0 * (k1[0] + 2 * k2[0] + 2 * k3[0] + k4[0]);
77+
double omegaNext = state[1] + dt / 6.0 * (k1[1] + 2 * k2[1] + 2 * k3[1] + k4[1]);
78+
79+
return new double[] {thetaNext, omegaNext};
80+
}
81+
82+
/**
83+
* Simulates the pendulum for a given duration.
84+
*
85+
* @param initialState the initial state [theta, omega]
86+
* @param dt the time step size
87+
* @param steps the number of steps to simulate
88+
* @return array of states at each step
89+
*/
90+
public double[][] simulate(double[] initialState, double dt, int steps) {
91+
double[][] trajectory = new double[steps + 1][2];
92+
trajectory[0] = initialState.clone();
93+
94+
double[] currentState = initialState.clone();
95+
for (int i = 1; i <= steps; i++) {
96+
currentState = stepRK4(currentState, dt);
97+
trajectory[i] = currentState.clone();
98+
}
99+
100+
return trajectory;
101+
}
102+
103+
/**
104+
* Calculates the total energy of the pendulum.
105+
* E = (1/2) * m * L^2 * omega^2 + m * g * L * (1 - cos(theta))
106+
* We use m = 1 for simplicity.
107+
*
108+
* @param state the current state [theta, omega]
109+
* @return the total energy
110+
*/
111+
public double calculateEnergy(double[] state) {
112+
double theta = state[0];
113+
double omega = state[1];
114+
double kineticEnergy = 0.5 * length * length * omega * omega;
115+
double potentialEnergy = g * length * (1 - Math.cos(theta));
116+
return kineticEnergy + potentialEnergy;
117+
}
118+
119+
public double getLength() {
120+
return length;
121+
}
122+
123+
public double getGravity() {
124+
return g;
125+
}
126+
}

0 commit comments

Comments
 (0)