Skip to content

Commit 5bd1c6f

Browse files
Merge pull request #10 from mdcourse/some-improvements
Some improvements
2 parents 8c464e0 + a88b569 commit 5bd1c6f

6 files changed

Lines changed: 76 additions & 8 deletions

File tree

integration_tests/test_monte_carlo_move.py

Lines changed: 44 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -1,5 +1,8 @@
11
import sys
22
import os
3+
import time
4+
import pstats
5+
import cProfile
36
import unittest
47
import numpy as np
58
from pint import UnitRegistry
@@ -30,7 +33,7 @@ def setUp(self):
3033
# Initialize the MonteCarlo object
3134
self.mc = MonteCarlo(
3235
ureg = ureg,
33-
maximum_steps = 10000,
36+
maximum_steps = 100000,
3437
thermo_period = 1000,
3538
dumping_period = 1000,
3639
number_atoms = [nmb_1],
@@ -41,20 +44,58 @@ def setUp(self):
4144
cut_off = rc,
4245
thermo_outputs = "Epot-press",
4346
desired_temperature = T,
44-
neighbor = 20,
47+
neighbor = 50,
4548
displace_mc = displace_mc,
4649
)
4750

51+
"""
4852
def test_monte_carlo_run(self):
49-
"""Test if the Monte Carlo simulation runs without errors."""
53+
# Test if the Monte Carlo simulation runs without errors.
5054
try:
5155
# Run the Monte Carlo simulation (this should not raise an exception)
56+
ti = time.time()
57+
58+
# Profile the run() method
5259
self.mc.run()
60+
# self.mc.run()
5361
# If it runs successfully, assert True
62+
tf = time.time()
63+
64+
print("Duration:", np.round(tf-ti, 2), "s")
5465
self.assertTrue(True)
5566
except Exception as e:
5667
# If any exception occurs, fail the test and print the error
5768
self.fail(f"Monte Carlo simulation failed with error: {e}")
69+
"""
70+
71+
def test_monte_carlo_run(self):
72+
"""Test if the Monte Carlo simulation runs without errors."""
73+
profiler = cProfile.Profile()
74+
try:
75+
# Start profiling before running the Monte Carlo simulation
76+
profiler.enable()
77+
78+
# Run the Monte Carlo simulation
79+
ti = time.time()
80+
self.mc.run() # Assuming self.mc is your Monte Carlo simulation object
81+
82+
# Stop profiling after the run
83+
profiler.disable()
84+
85+
tf = time.time()
86+
print("Duration:", np.round(tf - ti, 2), "s")
87+
88+
# Convert the profiler stats into a readable format
89+
stats = pstats.Stats(profiler)
90+
stats.strip_dirs() # Remove extraneous directory information
91+
stats.sort_stats('time') # Sort by time spent in function
92+
stats.print_stats(10) # Print top 10 slowest functions
93+
94+
self.assertTrue(True)
95+
except Exception as e:
96+
# If any exception occurs, fail the test and print the error
97+
self.fail(f"Monte Carlo simulation failed with error: {e}")
98+
5899

59100
if __name__ == "__main__":
60101
unittest.main()

molecular_simulation_code/measurements_utilities.py

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -1,6 +1,6 @@
11
from numba import njit
22
import numpy as np
3-
from typing import List
3+
from numba.typed import List
44

55
from distances_utilities import compute_vector_matrix
66
from forces_utilities import compute_force_matrix

molecular_simulation_code/monte_carlo.py

Lines changed: 9 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -6,6 +6,7 @@
66
from initialize_simulation import InitializeSimulation
77
from measurements_utilities import compute_epot
88
from monte_carlo_utilities import calculate_Lambda
9+
# from numba_test import numba_copy
910

1011
import warnings
1112
warnings.filterwarnings('ignore')
@@ -52,7 +53,9 @@ def monte_carlo_move(self):
5253
self.Epot = compute_epot(self.neighbor_lists, self.atoms_positions, self.box_mda, self.cross_coefficients)
5354
# Make a copy of the initial atom positions and initial energy
5455
initial_Epot = self.Epot
55-
initial_positions = copy.deepcopy(self.atoms_positions)
56+
# initial_positions = copy.deepcopy(self.atoms_positions)
57+
# initial_positions = np.copy(self.atoms_positions)
58+
# initial_positions = numba_copy(self.atoms_positions)
5659
# Pick an atom id randomly
5760
atom_id = np.random.randint(np.sum(self.number_atoms))
5861
# Move the chosen atom in a random direction
@@ -62,9 +65,12 @@ def monte_carlo_move(self):
6265
move = np.append(move, 0.0) # Pad with zero for the z-component
6366
else: # 3D case
6467
move = (np.random.random(3) - 0.5) * self.displace_mc
68+
initial_position_atom = np.copy(self.atoms_positions[atom_id])
6569
self.atoms_positions[atom_id] += move
70+
6671
# Measure the potential energy of the new configuration
6772
trial_Epot = compute_epot(self.neighbor_lists, self.atoms_positions, self.box_mda, self.cross_coefficients)
73+
6874
# Evaluate whether the new configuration should be kept or not
6975
beta = 1/self.desired_temperature
7076
delta_E = trial_Epot-initial_Epot
@@ -81,7 +87,8 @@ def monte_carlo_move(self):
8187
self.Epot = trial_Epot
8288
self.successful_move += 1
8389
else: # Reject new position
84-
self.atoms_positions = initial_positions # Revert to initial positions
90+
self.atoms_positions[atom_id] = initial_position_atom
91+
# self.atoms_positions = initial_positions # Revert to initial positions
8592
self.failed_move += 1
8693

8794
def monte_carlo_swap(self):
Lines changed: 12 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,12 @@
1+
import numpy as np
2+
from numba import njit
3+
4+
@njit
5+
def numba_copy(array):
6+
# Create an empty array of the same shape and type
7+
new_array = np.empty_like(array)
8+
# Copy elements manually
9+
for i in range(array.shape[0]):
10+
for j in range(array.shape[1]):
11+
new_array[i, j] = array[i, j]
12+
return new_array

molecular_simulation_code/simulation_handler.py

Lines changed: 7 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -1,4 +1,5 @@
11
import numpy as np
2+
from numba.typed import List
23

34
from contacts_utilities import contact_matrix, compute_neighbor_lists
45

@@ -18,7 +19,12 @@ def update_neighbor_lists(self, force_update=False):
1819
box=self.box_mda)
1920

2021
# Compute the neighbor lists from the contact matrix
21-
self.neighbor_lists = compute_neighbor_lists(matrix)
22+
python_neighbor_lists = compute_neighbor_lists(matrix)
23+
24+
# Convert Python list to numba.typed.List
25+
self.neighbor_lists = List()
26+
for neighbors in python_neighbor_lists:
27+
self.neighbor_lists.append(neighbors)
2228

2329
def update_cross_coefficients(self, force_update=False):
2430
"""Update the Lennard-Jones cross-coefficients for all atom pairs."""

molecular_simulation_code/simulation_logger.py

Lines changed: 3 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -9,8 +9,10 @@ def setup_logger(folder_name, overwrite=False):
99
logger.setLevel(logging.INFO)
1010
logger.propagate = False # Disable propagation to prevent double logging
1111

12-
# Clear any existing handlers if this function is called again
12+
# Close and clear existing handlers, if any
1313
if logger.hasHandlers():
14+
for handler in logger.handlers:
15+
handler.close() # Ensure handlers are properly closed
1416
logger.handlers.clear()
1517

1618
# Create handlers for console and file

0 commit comments

Comments
 (0)