Skip to content

Commit 97df881

Browse files
authored
Merge pull request #193 from CCPBioSim/192-force-partitioning
Force partitioning
2 parents f3d3920 + 04499b9 commit 97df881

File tree

4 files changed

+72
-16
lines changed

4 files changed

+72
-16
lines changed

CodeEntropy/config/arg_config_manager.py

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -268,5 +268,5 @@ def _check_input_force_partitioning(self, args):
268268
if args.force_partitioning != default_value:
269269
logger.warning(
270270
f"'force_partitioning' is set to {args.force_partitioning},"
271-
" which differs from the default ({default_value})."
271+
f" which differs from the default {default_value}."
272272
)

CodeEntropy/entropy.py

Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -118,6 +118,7 @@ def execute(self):
118118
end,
119119
step,
120120
number_frames,
121+
self._args.force_partitioning,
121122
)
122123
)
123124

@@ -548,6 +549,7 @@ def _process_vibrational_entropy(
548549
"""
549550
# Find the relevant force and torque matrices and tidy them up
550551
# by removing rows and columns that are all zeros
552+
551553
force_matrix = self._level_manager.filter_zero_rows_columns(force_matrix)
552554

553555
torque_matrix = self._level_manager.filter_zero_rows_columns(torque_matrix)

CodeEntropy/levels.py

Lines changed: 21 additions & 7 deletions
Original file line numberDiff line numberDiff line change
@@ -83,6 +83,7 @@ def get_matrices(
8383
highest_level,
8484
force_matrix,
8585
torque_matrix,
86+
force_partitioning,
8687
):
8788
"""
8889
Compute and accumulate force/torque covariance matrices for a given level.
@@ -94,6 +95,8 @@ def get_matrices(
9495
highest_level (bool): Whether this is the top (largest bead size) level.
9596
force_matrix, torque_matrix (np.ndarray or None): Accumulated matrices to add
9697
to.
98+
force_partitioning (float): Factor to adjust force contributions,
99+
default is 0.5.
97100
98101
Returns:
99102
force_matrix (np.ndarray): Accumulated force covariance matrix.
@@ -119,10 +122,14 @@ def get_matrices(
119122

120123
# Sort out coordinates, forces, and torques for each atom in the bead
121124
weighted_forces[bead_index] = self.get_weighted_forces(
122-
data_container, list_of_beads[bead_index], trans_axes, highest_level
125+
data_container,
126+
list_of_beads[bead_index],
127+
trans_axes,
128+
highest_level,
129+
force_partitioning,
123130
)
124131
weighted_torques[bead_index] = self.get_weighted_torques(
125-
data_container, list_of_beads[bead_index], rot_axes
132+
data_container, list_of_beads[bead_index], rot_axes, force_partitioning
126133
)
127134

128135
# Create covariance submatrices
@@ -571,7 +578,7 @@ def get_sphCoord_axes(self, arg_r):
571578
return spherical_basis
572579

573580
def get_weighted_forces(
574-
self, data_container, bead, trans_axes, highest_level, force_partitioning=0.5
581+
self, data_container, bead, trans_axes, highest_level, force_partitioning
575582
):
576583
"""
577584
Function to calculate the mass weighted forces for a given bead.
@@ -620,9 +627,7 @@ def get_weighted_forces(
620627

621628
return weighted_force
622629

623-
def get_weighted_torques(
624-
self, data_container, bead, rot_axes, force_partitioning=0.5
625-
):
630+
def get_weighted_torques(self, data_container, bead, rot_axes, force_partitioning):
626631
"""
627632
Function to calculate the moment of inertia weighted torques for a given bead.
628633
@@ -747,6 +752,7 @@ def build_covariance_matrices(
747752
end,
748753
step,
749754
number_frames,
755+
force_partitioning,
750756
):
751757
"""
752758
Construct average force and torque covariance matrices for all molecules and
@@ -770,6 +776,9 @@ def build_covariance_matrices(
770776
Step size for frame iteration.
771777
number_frames : int
772778
Total number of frames to process.
779+
force_partitioning : float
780+
Factor to adjust force contributions, default is 0.5.
781+
773782
774783
Returns
775784
-------
@@ -855,6 +864,7 @@ def build_covariance_matrices(
855864
force_avg,
856865
torque_avg,
857866
frame_counts,
867+
force_partitioning,
858868
)
859869

860870
progress.advance(task)
@@ -873,6 +883,7 @@ def update_force_torque_matrices(
873883
force_avg,
874884
torque_avg,
875885
frame_counts,
886+
force_partitioning,
876887
):
877888
"""
878889
Update the running averages of force and torque covariance matrices
@@ -913,7 +924,8 @@ def update_force_torque_matrices(
913924
frame_counts : dict
914925
Dictionary holding the count of frames processed for each molecule/level
915926
combination.
916-
927+
force_partitioning : float
928+
Factor to adjust force contributions, default is 0.5.
917929
Returns
918930
-------
919931
None
@@ -946,6 +958,7 @@ def update_force_torque_matrices(
946958
highest,
947959
None if key not in force_avg["ua"] else force_avg["ua"][key],
948960
None if key not in torque_avg["ua"] else torque_avg["ua"][key],
961+
force_partitioning,
949962
)
950963

951964
if key not in force_avg["ua"]:
@@ -979,6 +992,7 @@ def update_force_torque_matrices(
979992
if torque_avg[key][group_id] is None
980993
else torque_avg[key][group_id]
981994
),
995+
force_partitioning,
982996
)
983997

984998
if force_avg[key][group_id] is None:

tests/test_CodeEntropy/test_levels.py

Lines changed: 48 additions & 8 deletions
Original file line numberDiff line numberDiff line change
@@ -92,6 +92,7 @@ def test_get_matrices(self):
9292
highest_level=True,
9393
force_matrix=None,
9494
torque_matrix=None,
95+
force_partitioning=0.5,
9596
)
9697

9798
# Assertions
@@ -139,6 +140,7 @@ def test_get_matrices_force_shape_mismatch(self):
139140
highest_level=True,
140141
force_matrix=bad_force_matrix,
141142
torque_matrix=correct_torque_matrix,
143+
force_partitioning=0.5,
142144
)
143145

144146
self.assertIn("Inconsistent force matrix shape", str(context.exception))
@@ -174,6 +176,7 @@ def test_get_matrices_torque_shape_mismatch(self):
174176
highest_level=True,
175177
force_matrix=correct_force_matrix,
176178
torque_matrix=bad_torque_matrix,
179+
force_partitioning=0.5,
177180
)
178181

179182
self.assertIn("Inconsistent torque matrix shape", str(context.exception))
@@ -207,6 +210,7 @@ def test_get_matrices_torque_consistency(self):
207210
highest_level=True,
208211
force_matrix=initial_force_matrix.copy(),
209212
torque_matrix=initial_torque_matrix.copy(),
213+
force_partitioning=0.5,
210214
)
211215

212216
force_matrix_2, torque_matrix_2 = level_manager.get_matrices(
@@ -216,6 +220,7 @@ def test_get_matrices_torque_consistency(self):
216220
highest_level=True,
217221
force_matrix=initial_force_matrix.copy(),
218222
torque_matrix=initial_torque_matrix.copy(),
223+
force_partitioning=0.5,
219224
)
220225

221226
# Check that repeated calls produce the same output
@@ -692,7 +697,7 @@ def test_get_weighted_force_with_partitioning(self):
692697
trans_axes = np.identity(3)
693698

694699
result = level_manager.get_weighted_forces(
695-
data_container, bead, trans_axes, highest_level=True
700+
data_container, bead, trans_axes, highest_level=True, force_partitioning=0.5
696701
)
697702

698703
expected = (0.5 * np.array([2.0, 0.0, 0.0])) / np.sqrt(4.0)
@@ -717,7 +722,11 @@ def test_get_weighted_force_without_partitioning(self):
717722
trans_axes = np.identity(3)
718723

719724
result = level_manager.get_weighted_forces(
720-
data_container, bead, trans_axes, highest_level=False
725+
data_container,
726+
bead,
727+
trans_axes,
728+
highest_level=False,
729+
force_partitioning=0.5,
721730
)
722731

723732
expected = np.array([3.0, 0.0, 0.0]) / np.sqrt(1.0)
@@ -743,7 +752,11 @@ def test_get_weighted_forces_zero_mass_raises_value_error(self):
743752

744753
with self.assertRaises(ValueError):
745754
level_manager.get_weighted_forces(
746-
data_container, bead, trans_axes, highest_level=True
755+
data_container,
756+
bead,
757+
trans_axes,
758+
highest_level=True,
759+
force_partitioning=0.5,
747760
)
748761

749762
def test_get_weighted_forces_negative_mass_raises_value_error(self):
@@ -766,7 +779,11 @@ def test_get_weighted_forces_negative_mass_raises_value_error(self):
766779

767780
with self.assertRaises(ValueError):
768781
level_manager.get_weighted_forces(
769-
data_container, bead, trans_axes, highest_level=True
782+
data_container,
783+
bead,
784+
trans_axes,
785+
highest_level=True,
786+
force_partitioning=0.5,
770787
)
771788

772789
def test_get_weighted_torques_weighted_torque_basic(self):
@@ -795,7 +812,11 @@ def test_get_weighted_torques_weighted_torque_basic(self):
795812
# Rotation axes (identity matrix)
796813
rot_axes = np.identity(3)
797814

798-
result = level_manager.get_weighted_torques(data_container, bead, rot_axes)
815+
force_partitioning = 0.5
816+
817+
result = level_manager.get_weighted_torques(
818+
data_container, bead, rot_axes, force_partitioning
819+
)
799820

800821
np.testing.assert_array_almost_equal(result, np.array([0.0, 0.0, 0.5]))
801822

@@ -821,7 +842,11 @@ def test_get_weighted_torques_zero_torque_skips_division(self):
821842

822843
rot_axes = np.identity(3)
823844

824-
result = level_manager.get_weighted_torques(data_container, bead, rot_axes)
845+
force_partitioning = 0.5
846+
847+
result = level_manager.get_weighted_torques(
848+
data_container, bead, rot_axes, force_partitioning
849+
)
825850
np.testing.assert_array_almost_equal(result, np.zeros(3))
826851

827852
def test_get_weighted_torques_zero_moi_raises(self):
@@ -852,8 +877,12 @@ def test_get_weighted_torques_zero_moi_raises(self):
852877

853878
rot_axes = np.identity(3)
854879

880+
force_partitioning = 0.5
881+
855882
with self.assertRaises(ZeroDivisionError):
856-
level_manager.get_weighted_torques(data_container, bead, rot_axes)
883+
level_manager.get_weighted_torques(
884+
data_container, bead, rot_axes, force_partitioning
885+
)
857886

858887
def test_get_weighted_torques_negative_moi_raises(self):
859888
"""
@@ -883,8 +912,12 @@ def test_get_weighted_torques_negative_moi_raises(self):
883912

884913
rot_axes = np.identity(3)
885914

915+
foce_partitioning = 0.5
916+
886917
with self.assertRaises(ValueError) as context:
887-
level_manager.get_weighted_torques(data_container, bead, rot_axes)
918+
level_manager.get_weighted_torques(
919+
data_container, bead, rot_axes, foce_partitioning
920+
)
888921

889922
self.assertIn(
890923
"Negative value encountered for moment of inertia", str(context.exception)
@@ -995,6 +1028,7 @@ def test_build_covariance_matrices_atomic(self):
9951028
end=2,
9961029
step=1,
9971030
number_frames=2,
1031+
force_partitioning=0.5,
9981032
)
9991033

10001034
# Assert returned matrices are dictionaries with correct keys
@@ -1057,6 +1091,7 @@ def test_update_force_torque_matrices_united_atom(self):
10571091
force_avg=force_avg,
10581092
torque_avg=torque_avg,
10591093
frame_counts=frame_counts,
1094+
force_partitioning=0.5,
10601095
)
10611096

10621097
expected_keys = [(0, 0), (0, 1)]
@@ -1107,6 +1142,7 @@ def test_update_force_torque_matrices_united_atom_increment(self):
11071142
force_avg=force_avg,
11081143
torque_avg=torque_avg,
11091144
frame_counts=frame_counts,
1145+
force_partitioning=0.5,
11101146
)
11111147

11121148
# Second call: update
@@ -1123,6 +1159,7 @@ def test_update_force_torque_matrices_united_atom_increment(self):
11231159
force_avg=force_avg,
11241160
torque_avg=torque_avg,
11251161
frame_counts=frame_counts,
1162+
force_partitioning=0.5,
11261163
)
11271164

11281165
expected_force = f_mat_1 + (f_mat_2 - f_mat_1) / 2
@@ -1162,6 +1199,7 @@ def test_update_force_torque_matrices_residue(self):
11621199
force_avg=force_avg,
11631200
torque_avg=torque_avg,
11641201
frame_counts=frame_counts,
1202+
force_partitioning=0.5,
11651203
)
11661204

11671205
np.testing.assert_array_equal(force_avg["res"][0], f_mat_mock)
@@ -1206,6 +1244,7 @@ def test_update_force_torque_matrices_incremental_average(self):
12061244
force_avg=force_avg,
12071245
torque_avg=torque_avg,
12081246
frame_counts=frame_counts,
1247+
force_partitioning=0.5,
12091248
)
12101249

12111250
# Second update
@@ -1220,6 +1259,7 @@ def test_update_force_torque_matrices_incremental_average(self):
12201259
force_avg=force_avg,
12211260
torque_avg=torque_avg,
12221261
frame_counts=frame_counts,
1262+
force_partitioning=0.5,
12231263
)
12241264

12251265
expected_force = f_mat_1 + (f_mat_2 - f_mat_1) / 2

0 commit comments

Comments
 (0)