From dee81f618ef4afadc11b881bb826996f15ae52b0 Mon Sep 17 00:00:00 2001 From: Chinmay Bhardwaj Date: Fri, 20 Feb 2026 22:09:12 +0530 Subject: [PATCH] Added monopole electrostatic potential and field with unit tests --- ffprime/electrostatics/__init__.py | 0 .../__pycache__/__init__.cpython-310.pyc | Bin 0 -> 160 bytes .../__pycache__/multipole.cpython-310.pyc | Bin 0 -> 632 bytes ffprime/electrostatics/multipole.py | 20 +++++++++++++ tests/test_electrostatics.py | 28 ++++++++++++++++++ 5 files changed, 48 insertions(+) create mode 100644 ffprime/electrostatics/__init__.py create mode 100644 ffprime/electrostatics/__pycache__/__init__.cpython-310.pyc create mode 100644 ffprime/electrostatics/__pycache__/multipole.cpython-310.pyc create mode 100644 ffprime/electrostatics/multipole.py create mode 100644 tests/test_electrostatics.py diff --git a/ffprime/electrostatics/__init__.py b/ffprime/electrostatics/__init__.py new file mode 100644 index 0000000..e69de29 diff --git a/ffprime/electrostatics/__pycache__/__init__.cpython-310.pyc b/ffprime/electrostatics/__pycache__/__init__.cpython-310.pyc new file mode 100644 index 0000000000000000000000000000000000000000..92e328cf1a1928771ef3b4943734cf17d2a48f77 GIT binary patch literal 160 zcmd1j<>g`k0@2PHnIQTxh(HF6K#l_t7qb9~6oz01O-8?!3`HPe1o6w+*(xTqIJKxa zCOIQBFE_>|zdSD|KQW~^CM~U?C^I(|PN(LiCYKcD7ndZKWF{BK#K&jmWtPOp>lIYq V;;_lhPbtkwwF4Pm%mgG@7y#ppCuaZv literal 0 HcmV?d00001 diff --git a/ffprime/electrostatics/__pycache__/multipole.cpython-310.pyc b/ffprime/electrostatics/__pycache__/multipole.cpython-310.pyc new file mode 100644 index 0000000000000000000000000000000000000000..3c50ddf7ae80587c075f1e3fff9329718375736e GIT binary patch literal 632 zcmZ`%y=ojW5FTlNZtrrJI6p@KY&S$!LCifq%jM}veG)TwbFW|i#c;C3~urS zNjj(WE2&KpoJUBN(Z(D$*aI`#nNRv=zLo4`G6J#>U%xBI0Di^fuH}^Mkh^UP0tC}= z$OM;MB$6E`B9*+!MJDpg^f0|wCzOzZC;!Nu_yH_o$=88+ll|Y%|7=|R_;&jKi1zn3O#(Mv z$h9(+J_@O^*j^_X8)0M*46gy7(AVF+-L3MYljzF&lQM0&XU~kbm2hR#bf{XnTBVk? zN9%m$Rqe`luD$B4mYdxoylAblF`0GNOXF3gQ(|`og)u95N{$ms9v8bw=mTP(dALfV z{9ZD9MY08d3AfTQqf<9g(lo_*TR4azwhg0mNz=}>I*~Yx)u{J>7)Si+YUV~sE#h>m zc}HxG;~G__dC1JX?G`NYDBiVJ%(dL6w*@YaSHSD! G&F~*phKe`< literal 0 HcmV?d00001 diff --git a/ffprime/electrostatics/multipole.py b/ffprime/electrostatics/multipole.py new file mode 100644 index 0000000..13311d3 --- /dev/null +++ b/ffprime/electrostatics/multipole.py @@ -0,0 +1,20 @@ +import numpy as np + + +def monopole_potential(q: float, r_vec: np.ndarray) -> float: + r = np.linalg.norm(r_vec) + + if r < 1e-12: + return 0.0 + + return q / r + + +def monopole_field(q: float, r_vec: np.ndarray) -> np.ndarray: + r = np.linalg.norm(r_vec) + + if r < 1e-12: + return np.zeros_like(r_vec) + + return q * r_vec / r**3 + \ No newline at end of file diff --git a/tests/test_electrostatics.py b/tests/test_electrostatics.py new file mode 100644 index 0000000..7a6130d --- /dev/null +++ b/tests/test_electrostatics.py @@ -0,0 +1,28 @@ +import numpy as np +from ffprime.electrostatics.multipole import ( + monopole_potential, + monopole_field, +) + + +def test_monopole_potential_unit_distance(): + q = 1.0 + r_vec = np.array([1.0, 0.0, 0.0]) + V = monopole_potential(q, r_vec) + assert np.isclose(V, 1.0) + + +def test_monopole_field_direction(): + q = 1.0 + r_vec = np.array([1.0, 0.0, 0.0]) + E = monopole_field(q, r_vec) + assert np.allclose(E, np.array([1.0, 0.0, 0.0])) + + +def test_zero_distance_safe(): + q = 1.0 + r_vec = np.array([0.0, 0.0, 0.0]) + V = monopole_potential(q, r_vec) + E = monopole_field(q, r_vec) + assert V == 0.0 + assert np.allclose(E, np.zeros(3)) \ No newline at end of file