Skip to content

Commit 1c1dd5a

Browse files
authored
Merge pull request #64 from CCPBioSim/55-weighted-torque-bug
Weighted Torque Bug
2 parents 478280f + 456b9e3 commit 1c1dd5a

File tree

1 file changed

+43
-15
lines changed

1 file changed

+43
-15
lines changed

CodeEntropy/GeometricFunctions.py

Lines changed: 43 additions & 15 deletions
Original file line numberDiff line numberDiff line change
@@ -298,15 +298,30 @@ def get_weighted_torques(data_container, bead, rot_axes, force_partitioning=0.5)
298298
"""
299299
Function to calculate the moment of inertia weighted torques for a given bead.
300300
301-
Input
302-
-----
303-
bead : the part of the molecule to be considered
304-
rot_axes : the axes relative to which the forces and coordinates are located
305-
frame : the frame number from the trajectory
306-
307-
Output
308-
------
309-
weighted_torque : the mass weighted sum of the torques in the bead
301+
This function computes torques in a rotated frame and then weights them using
302+
the moment of inertia tensor. To prevent numerical instability, it treats
303+
extremely small diagonal elements of the moment of inertia tensor as zero
304+
(since values below machine precision are effectively zero). This avoids
305+
unnecessary use of extended precision (e.g., float128).
306+
307+
Additionally, if the computed torque is already zero, the function skips
308+
the division step, reducing unnecessary computations and potential errors.
309+
310+
Parameters
311+
----------
312+
data_container : object
313+
Contains atomic positions and forces.
314+
bead : object
315+
The part of the molecule to be considered.
316+
rot_axes : np.ndarray
317+
The axes relative to which the forces and coordinates are located.
318+
force_partitioning : float, optional
319+
Factor to adjust force contributions, default is 0.5.
320+
321+
Returns
322+
-------
323+
np.ndarray
324+
The mass-weighted sum of the torques in the bead.
310325
"""
311326

312327
torques = np.zeros((3,))
@@ -336,17 +351,30 @@ def get_weighted_torques(data_container, bead, rot_axes, force_partitioning=0.5)
336351
moment_of_inertia = bead.moment_of_inertia()
337352

338353
for dimension in range(3):
339-
# Check if the moment of inertia is valid for square root calculation
340-
inertia_value = moment_of_inertia[dimension, dimension]
354+
# Skip calculation if torque is already zero
355+
if np.isclose(torques[dimension], 0):
356+
weighted_torque[dimension] = 0
357+
continue
358+
359+
# Check for zero moment of inertia
360+
if np.isclose(moment_of_inertia[dimension, dimension], 0):
361+
raise ZeroDivisionError(
362+
f"Attempted to divide by zero moment of inertia in dimension "
363+
f"{dimension}."
364+
)
341365

342-
if np.isclose(inertia_value, 0):
366+
# Check for negative moment of inertia
367+
if moment_of_inertia[dimension, dimension] < 0:
343368
raise ValueError(
344-
f"Invalid moment of inertia value: {inertia_value}. "
369+
f"Negative value encountered for moment of inertia: "
370+
f"{moment_of_inertia[dimension, dimension]} "
345371
f"Cannot compute weighted torque."
346372
)
347373

348-
# compute weighted torque if moment of inertia is valid
349-
weighted_torque[dimension] = torques[dimension] / np.sqrt(inertia_value)
374+
# Compute weighted torque
375+
weighted_torque[dimension] = torques[dimension] / np.sqrt(
376+
moment_of_inertia[dimension, dimension]
377+
)
350378

351379
return weighted_torque
352380

0 commit comments

Comments
 (0)