Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
Original file line number Diff line number Diff line change
Expand Up @@ -43,7 +43,7 @@ public static void jugglerSequence(int inputNumber) {
seq.add(n + "");
}
String res = String.join(",", seq);
System.out.println(res);
System.out.print(res + "\n");
}

// Driver code
Expand Down
80 changes: 80 additions & 0 deletions src/main/java/com/thealgorithms/physics/CoulombsLaw.java
Original file line number Diff line number Diff line change
@@ -0,0 +1,80 @@
package com.thealgorithms.physics;

/**
* Implements Coulomb's Law for electrostatics.
* Provides simple static methods to calculate electrostatic force and circular orbit velocity.
*
* @author [Priyanshu Singh](https://github.com/Priyanshu1303d)
* @see <a href="https://en.wikipedia.org/wiki/Coulomb%27s_law">Wikipedia</a>
*/
public final class CoulombsLaw {

/** Coulomb's constant in N·m²/C² */
public static final double COULOMBS_CONSTANT = 8.9875517923e9;

/**
* Private constructor to prevent instantiation of this utility class.
*/
private CoulombsLaw() {
}

/**
* Calculates the electrostatic force vector exerted by one charge on another.
* The returned vector is the force *on* the second charge (q2).
*
* @param q1 Charge of the first particle (in Coulombs).
* @param x1 X-position of the first particle (m).
* @param y1 Y-position of the first particle (m).
* @param q2 Charge of the second particle (in Coulombs).
* @param x2 X-position of the second particle (m).
* @param y2 Y-position of the second particle (m).
* @return A double array `[fx, fy]` representing the force vector on the second charge.
*/
public static double[] calculateForceVector(double q1, double x1, double y1, double q2, double x2, double y2) {
// Vector from 1 to 2
double dx = x2 - x1;
double dy = y2 - y1;
double distanceSq = dx * dx + dy * dy;

// If particles are at the same position, force is zero to avoid division by zero.
if (distanceSq == 0) {
return new double[] {0, 0};
}

double distance = Math.sqrt(distanceSq);
// Force magnitude: k * (q1 * q2) / r^2
// A positive result is repulsive (pushes q2 away from q1).
// A negative result is attractive (pulls q2 toward q1).
double forceMagnitude = COULOMBS_CONSTANT * q1 * q2 / distanceSq;

// Calculate the components of the force vector
// (dx / distance) is the unit vector pointing from 1 to 2.
double fx = forceMagnitude * (dx / distance);
double fy = forceMagnitude * (dy / distance);

return new double[] {fx, fy};
}

/**
* Calculates the speed required for a stable circular orbit of a charged particle
* around a central charge (e.g., an electron orbiting a nucleus).
*
* @param centralCharge The charge of the central body (in Coulombs).
* @param orbitingCharge The charge of the orbiting body (in Coulombs).
* @param orbitingMass The mass of the orbiting body (in kg).
* @param radius The radius of the orbit (in m).
* @return The orbital speed (in m/s).
* @throws IllegalArgumentException if mass or radius are not positive.
*/
public static double calculateCircularOrbitVelocity(double centralCharge, double orbitingCharge, double orbitingMass, double radius) {
if (orbitingMass <= 0 || radius <= 0) {
throw new IllegalArgumentException("Orbiting mass and radius must be positive.");
}

// We only need the magnitude of the force, which is always positive.
double forceMagnitude = Math.abs(COULOMBS_CONSTANT * centralCharge * orbitingCharge) / (radius * radius);

// F_c = m * v^2 / r => v = sqrt(F_c * r / m)
return Math.sqrt(forceMagnitude * radius / orbitingMass);
}
}
100 changes: 100 additions & 0 deletions src/test/java/com/thealgorithms/physics/CoulombsLawTest.java
Original file line number Diff line number Diff line change
@@ -0,0 +1,100 @@
package com.thealgorithms.physics;

import static org.junit.jupiter.api.Assertions.assertArrayEquals;
import static org.junit.jupiter.api.Assertions.assertEquals;
import static org.junit.jupiter.api.Assertions.assertThrows;

import org.junit.jupiter.api.DisplayName;
import org.junit.jupiter.api.Test;

/**
* Unit tests for the CoulombsLaw utility class.
*/
final class CoulombsLawTest {

// A small tolerance (delta) for comparing floating-point numbers
private static final double DELTA = 1e-9;
private static final double K = CoulombsLaw.COULOMBS_CONSTANT;

@Test
@DisplayName("Test repulsive force between two charges on the x-axis")
void testSimpleRepulsiveForce() {
// Two positive 1C charges, 1 meter apart.
// Force on q2 should be F = K*1*1 / 1^2 = K, directed away from q1 (positive x)
double[] forceOnB = CoulombsLaw.calculateForceVector(1.0, 0, 0, 1.0, 1, 0);
assertArrayEquals(new double[] {K, 0.0}, forceOnB, DELTA);

// Force on q1 should be equal and opposite (negative x)
double[] forceOnA = CoulombsLaw.calculateForceVector(1.0, 1, 0, 1.0, 0, 0);
assertArrayEquals(new double[] {-K, 0.0}, forceOnA, DELTA);
}

@Test
@DisplayName("Test attractive force between two charges on the x-axis")
void testSimpleAttractiveForce() {
// One positive 1C, one negative -1C, 1 meter apart.
// Force on q2 should be F = K*1*(-1) / 1^2 = -K, directed toward q1 (negative x)
double[] forceOnB = CoulombsLaw.calculateForceVector(1.0, 0, 0, -1.0, 1, 0);
assertArrayEquals(new double[] {-K, 0.0}, forceOnB, DELTA);
}

@Test
@DisplayName("Test electrostatic force in a 2D plane (repulsive)")
void test2DRepulsiveForce() {
// q1 at (0,0) with charge +2C
// q2 at (3,4) with charge +1C
// Distance is 5 meters.
double magnitude = K * 2.0 * 1.0 / 25.0; // 2K/25
// Unit vector from 1 to 2 is (3/5, 4/5)
double expectedFx = magnitude * (3.0 / 5.0); // 6K / 125
double expectedFy = magnitude * (4.0 / 5.0); // 8K / 125

double[] forceOnB = CoulombsLaw.calculateForceVector(2.0, 0, 0, 1.0, 3, 4);
assertArrayEquals(new double[] {expectedFx, expectedFy}, forceOnB, DELTA);
}

@Test
@DisplayName("Test overlapping charges should result in zero force")
void testOverlappingCharges() {
double[] force = CoulombsLaw.calculateForceVector(1.0, 1.5, -2.5, -1.0, 1.5, -2.5);
assertArrayEquals(new double[] {0.0, 0.0}, force, DELTA);
}

@Test
@DisplayName("Test circular orbit velocity with simple values")
void testCircularOrbitVelocity() {
// v = sqrt( (K*1*1 / 1^2) * 1 / 1 ) = sqrt(K)
double velocity = CoulombsLaw.calculateCircularOrbitVelocity(1.0, 1.0, 1.0, 1.0);
assertEquals(Math.sqrt(K), velocity, DELTA);
}

@Test
@DisplayName("Test orbital velocity for a Hydrogen atom (Bohr model)")
void testHydrogenAtomVelocity() {
// Charge of a proton
double protonCharge = 1.602176634e-19;
// Charge of an electron
double electronCharge = -1.602176634e-19;
// Mass of an electron
double electronMass = 9.1093837e-31;
// Bohr radius (avg distance)
double bohrRadius = 5.29177e-11;

double expectedVelocity = 2.1876917e6;

double velocity = CoulombsLaw.calculateCircularOrbitVelocity(protonCharge, electronCharge, electronMass, bohrRadius);
// Use a wider delta for this real-world calculation
assertEquals(expectedVelocity, velocity, 1.0);
}

@Test
@DisplayName("Test invalid inputs for orbital velocity throw exception")
void testInvalidOrbitalVelocityInputs() {
// Non-positive mass
assertThrows(IllegalArgumentException.class, () -> CoulombsLaw.calculateCircularOrbitVelocity(1, 1, 0, 100));
assertThrows(IllegalArgumentException.class, () -> CoulombsLaw.calculateCircularOrbitVelocity(1, 1, -1, 100));
// Non-positive radius
assertThrows(IllegalArgumentException.class, () -> CoulombsLaw.calculateCircularOrbitVelocity(1, 1, 1, 0));
assertThrows(IllegalArgumentException.class, () -> CoulombsLaw.calculateCircularOrbitVelocity(1, 1, 1, -100));
}
}