"""Tern: re-derive Cavendish's 'attraction of the weight on the arm' (his 128 + 29 = 157 grains placed at the ball) by numerical integration.
Model (my reading of his geometry): arm point at distance s from the centre (0..l, l = 36.65 in); deal rod + wire weight per inch rho(s) = (3490 - 1848 s/l)/73.3 grains
(his; 47.6 at the centre, 22.4 at the end). The weight's centre w is level with the ball, 8.85 in to the side of the arm's vertical plane and 5.5 in below the arm,
opposite the end piece, so the displacement from the point to w is ((l - s) along the arm, 8.85 perpendicular, -5.5 vertical). The part of the force that turns the arm is the perpendicular
component, F*8.85/r with F ~ 1/r^2, times the lever s/l; the ball (s = l, perpendicular, r = 8.85) is the unit. So effective grains at the ball = integral rho(s) (s/l) 8.85^3 / r^3 ds."""
import math
l, b, v = 36.65, 8.85, 5.5
rho = lambda s: (3490 - 1848 * s / l) / 73.3
def r(s): return math.sqrt((l - s) ** 2 + b ** 2 + v ** 2)
n = 200000; h = l / n
rod = sum(rho((i + .5) * h) * ((i + .5) * h / l) * b ** 3 / r((i + .5) * h) ** 3 for i in range(n)) * h
end = 47 * (b / math.hypot(b, v)) ** 3
print(f'rod+wire, near half: {rod:.1f} grains at the ball (his 128)')
print(f'end piece (47 grains at the end, lever 1): {end:.1f} (his 29)')
print(f'total {rod+end:.1f} (his 157); / 11260 = {(rod+end)/11260:.4f} (his .0139)')
# the farther half pulls the other way (his remark that it can be disregarded): size
far = sum(rho((i + .5) * h) * ((i + .5) * h / l) * b ** 3 / (math.sqrt((l + (i + .5) * h) ** 2 + b ** 2 + v ** 2)) ** 3 for i in range(n)) * h
print(f'far half (opposite sense): {far:.2f} grains-equivalent ({far/(rod+end)*100:.2f} % of the near half)')
# bonus: his first correction's integral: mass placed at the end with the same moment of inertia as each half of rod+wire = integral rho(s) (s/l)^2 ds  (his 350 grains)
inert = sum(rho((i + .5) * h) * ((i + .5) * h / l) ** 2 for i in range(n)) * h
print(f'inertia of each half of rod+wire as grains at the end: {inert:.1f} (his 350)')
print(f'arm total with end pieces 2x(48): {inert+48:.0f} grains at each end (his 398); balls 11262 -> {(11262+inert+48):.0f} (his 11660); ratio {(11262+inert+48)/11262:.4f} (his 1.0353)')
