Skip to content

Commit cc4b43f

Browse files
committed
continue fixing units
1 parent d0a6352 commit cc4b43f

File tree

5 files changed

+170
-142
lines changed

5 files changed

+170
-142
lines changed

docs/source/chapters/chapter1.rst

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -192,6 +192,7 @@ Within the *Measurements.py* file, copy the following lines:
192192

193193
.. code-block:: python
194194
195+
import numpy as np
195196
from InitializeSimulation import InitializeSimulation
196197
197198

docs/source/chapters/chapter6.rst

Lines changed: 17 additions & 18 deletions
Original file line numberDiff line numberDiff line change
@@ -145,21 +145,6 @@ Let us add a dump too:
145145
146146
.. label:: end_MonteCarlo_class
147147

148-
To output the density, let us add the following method to the *Utilities* class:
149-
# TOFIX: not used yet
150-
151-
.. label:: start_Utilities_class
152-
153-
.. code-block:: python
154-
155-
def calculate_density(self):
156-
"""Calculate the mass density."""
157-
volume = np.prod(self.box_size[:3]) # Unitless
158-
total_mass = np.sum(self.atoms_mass) # Unitless
159-
return total_mass/volume # Unitless
160-
161-
.. label:: end_Utilities_class
162-
163148
Test the code
164149
-------------
165150

@@ -195,9 +180,9 @@ One can use a similar test as previously. Let us use a displace distance of
195180
# Initialize the prepare object
196181
mc = MonteCarlo(
197182
ureg = ureg,
198-
maximum_steps=1000,
199-
thermo_period=100,
200-
dumping_period=100,
183+
maximum_steps=100,
184+
thermo_period=10,
185+
dumping_period=10,
201186
number_atoms=[nmb_1],
202187
epsilon=[eps_1], # kcal/mol
203188
sigma=[sig_1], # A
@@ -209,8 +194,22 @@ One can use a similar test as previously. Let us use a displace distance of
209194
neighbor=20,
210195
displace_mc = displace_mc,
211196
)
197+
198+
# Run the Monte Carlo simulation
212199
mc.run()
213200
201+
# Test function using pytest
202+
def test_output_files():
203+
assert os.path.exists("Outputs/dump.mc.lammpstrj"), "Test failed: dump file was not created"
204+
assert os.path.exists("Outputs/simulation.log"), "Test failed: log file was not created"
205+
print("Test passed")
206+
207+
# If the script is run directly, execute the tests
208+
if __name__ == "__main__":
209+
import pytest
210+
# Run pytest programmatically
211+
pytest.main(["-s", __file__])
212+
214213
.. label:: end_test_6a_class
215214

216215
The evolution of the potential energy as a function of the number of steps

docs/source/chapters/chapter7.rst

Lines changed: 59 additions & 86 deletions
Original file line numberDiff line numberDiff line change
@@ -30,31 +30,34 @@ vector direction between atoms pairs will have to be written here.
3030
Implement the Virial equation
3131
-----------------------------
3232

33-
Let us add the following method to the *Utilities* class.
33+
Let us add the following method to the *Measurements* class.
3434

35-
.. label:: start_Utilities_class
35+
.. label:: start_Measurements_class
3636

3737
.. code-block:: python
3838
3939
def calculate_pressure(self):
4040
"""Evaluate p based on the Virial equation (Eq. 4.4.2 in Frenkel-Smit,
4141
Understanding molecular simulation: from algorithms to applications, 2002)"""
4242
# Compute the ideal contribution
43-
Ndof = self.dimensions*self.total_number_atoms-self.dimensions
44-
volume = np.prod(self.box_size[:self.dimensions])
43+
Nat = np.sum(self.number_atoms) # total number of atoms
44+
dimension = 3 # 3D is the only possibility here
45+
Ndof = dimension*Nat-dimension
46+
volume = np.prod(self.box_size[:3]) # box volume
4547
try:
4648
self.calculate_temperature() # this is for later on, when velocities are computed
4749
temperature = self.temperature
4850
except:
4951
temperature = self.desired_temperature # for MC, simply use the desired temperature
50-
p_ideal = Ndof*temperature/(volume*self.dimensions)
52+
p_ideal = Ndof*temperature/(volume*dimension)
5153
# Compute the non-ideal contribution
52-
distances_forces = np.sum(self.compute_force(return_vector = False)*self.evaluate_rij_matrix())
53-
p_nonideal = distances_forces/(volume*self.dimensions)
54+
distances_forces = np.sum(self.compute_force(return_vector = False) \
55+
*self.evaluate_rij_matrix())
56+
p_nonideal = distances_forces/(volume*dimension)
5457
# Final pressure
5558
self.pressure = p_ideal+p_nonideal
5659
57-
.. label:: end_Utilities_class
60+
.. label:: end_Measurements_class
5861

5962
To evaluate all the vectors between all the particles, let us also add the
6063
*evaluate_rij_matrix* method to the *Utilities* class:
@@ -65,95 +68,75 @@ To evaluate all the vectors between all the particles, let us also add the
6568
6669
def evaluate_rij_matrix(self):
6770
"""Matrix of vectors between all particles."""
68-
box_size = self.box_size[:3]
69-
half_box_size = self.box_size[:3]/2.0
70-
rij_matrix = np.zeros((self.total_number_atoms,self.total_number_atoms,3))
71-
positions_j = self.atoms_positions
72-
for Ni in range(self.total_number_atoms-1):
73-
position_i = self.atoms_positions[Ni]
74-
rij_xyz = (np.remainder(position_i - positions_j + half_box_size, box_size) - half_box_size)
71+
Nat = np.sum(self.number_atoms)
72+
Box = self.box_size[:3]
73+
rij_matrix = np.zeros((Nat, Nat,3))
74+
pos_j = self.atoms_positions
75+
for Ni in range(Nat-1):
76+
pos_i = self.atoms_positions[Ni]
77+
rij_xyz = (np.remainder(pos_i - pos_j + Box/2.0, Box) - Box/2.0)
7578
rij_matrix[Ni] = rij_xyz
76-
# use nan_to_num to avoid "nan" values in 2D
77-
return np.nan_to_num(rij_matrix)
79+
return rij_matrix
7880
7981
.. label:: end_Utilities_class
8082

8183
Test the code
8284
-------------
8385

84-
Let us test the outputed pressure. An interesting test is to contront the output from
85-
our code with some data from the litterature. Let us used the same parameters
86-
as in Ref. :cite:`woodMonteCarloEquation1957`, where Monte Carlo simulations
87-
are used to simulate argon bulk phase. All we have to do is to apply our current
88-
code using their parameters, i.e. :math:`\sigma = 3.405~\text{Å}`, :math:`\epsilon = 0.238~\text{kcal/mol}`,
89-
and :math:`T = 55~^\circ\text{C}`. More details are given in the first illustration, :ref:`project1-label`.
90-
91-
On the side note, a relatively small cut-off as well as a small number of atoms were
92-
chosen to make the calculation faster.
86+
Let us test the outputed pressure.
9387

9488
.. label:: start_test_7a_class
9589

9690
.. code-block:: python
9791
98-
import numpy as np
9992
from MonteCarlo import MonteCarlo
100-
from scipy import constants as cst
10193
from pint import UnitRegistry
102-
from reader import import_data
103-
104-
# Initialize the unit registry
10594
ureg = UnitRegistry()
106-
107-
# Constants
108-
kB = cst.Boltzmann * ureg.J / ureg.kelvin # Boltzmann constant
109-
Na = cst.Avogadro / ureg.mole # Avogadro's number
110-
R = kB * Na # Gas constant
111-
112-
# Parameters taken from Wood1957
113-
tau = 2 # Ratio between volume / reduced volume
114-
epsilon = (119.76 * ureg.kelvin * kB * Na).to(ureg.kcal / ureg.mol) # kcal/mol
115-
r_star = 3.822 * ureg.angstrom # Angstrom
116-
sigma = r_star / 2**(1/6) # Angstrom
117-
N_atom = 50 # Number of atoms
118-
m_argon = 39.948 * ureg.gram / ureg.mol # g/mol
119-
T = 328.15 * ureg.degK # 328 K or 55°C
120-
volume_star = r_star**3 * Na * 2**(-0.5)
121-
cut_off = sigma * 2.5 # Angstrom
122-
displace_mc = sigma / 5 # Angstrom
123-
volume = N_atom * volume_star * tau / Na # Angstrom^3
124-
box_size = volume**(1/3) # Angstrom
125-
126-
# Initialize and run the Monte Carlo simulation
95+
import os
96+
97+
# Define atom number of each group
98+
nmb_1= 50
99+
# Define LJ parameters (sigma)
100+
sig_1 = 3*ureg.angstrom
101+
# Define LJ parameters (epsilon)
102+
eps_1 = 0.1*ureg.kcal/ureg.mol
103+
# Define atom mass
104+
mss_1 = 10*ureg.gram/ureg.mol
105+
# Define box size
106+
L = 20*ureg.angstrom
107+
# Define a cut off
108+
rc = 2.5*sig_1
109+
# Pick the desired temperature
110+
T = 300*ureg.kelvin
111+
# choose the displace_mc
112+
displace_mc = sig_1/4
113+
114+
# Initialize the prepare object
127115
mc = MonteCarlo(
128-
maximum_steps=15000,
129-
dumping_period=1000,
130-
thermo_period=1000,
116+
ureg = ureg,
117+
maximum_steps=100,
118+
thermo_period=10,
119+
dumping_period=10,
120+
number_atoms=[nmb_1],
121+
epsilon=[eps_1], # kcal/mol
122+
sigma=[sig_1], # A
123+
atom_mass=[mss_1], # g/mol
124+
box_dimensions=[L, L, L], # A
125+
cut_off=rc,
131126
thermo_outputs="Epot-press",
132-
neighbor=50,
133-
number_atoms=[N_atom],
134-
epsilon=[epsilon.magnitude],
135-
sigma=[sigma.magnitude],
136-
atom_mass=[m_argon.magnitude],
137-
box_dimensions=[box_size.magnitude, box_size.magnitude, box_size.magnitude],
138-
displace_mc=displace_mc.magnitude,
139-
desired_temperature=T.magnitude,
140-
cut_off=cut_off.magnitude,
141-
data_folder="Outputs/",
127+
desired_temperature=T, # K
128+
neighbor=20,
129+
displace_mc = displace_mc,
142130
)
131+
132+
# Run the Monte Carlo simulation
143133
mc.run()
144134
145135
# Test function using pytest
146-
def test_pV_over_RT():
147-
# Import the data and calculate pV / RT
148-
pressure_data = np.array(import_data("Outputs/simulation.log")[1:])[0][:,2][10:] # Skip initial values
149-
pressure_atm = np.mean(pressure_data) # atm
150-
pressure_Pa = (pressure_atm * ureg.atm).to(ureg.pascal) # Pa
151-
volume = (volume_star * tau / Na).to(ureg.meter**3) # m3
152-
pV_over_RT = (pressure_Pa * volume / (R * T) * Na).magnitude
153-
154-
# Assert that pV_over_RT is close to 1.5
155-
assert np.isclose(pV_over_RT, 1.5, atol=1.0), f"Test failed: pV/Rt = {pV_over_RT}, expected close to 1.5"
156-
print(f"pV/RT = {pV_over_RT:.2f} --- (The expected value from Wood1957 is 1.5)")
136+
def test_output_files():
137+
assert os.path.exists("Outputs/dump.mc.lammpstrj"), "Test failed: dump file was not created"
138+
assert os.path.exists("Outputs/simulation.log"), "Test failed: log file was not created"
139+
print("Test passed")
157140
158141
# If the script is run directly, execute the tests
159142
if __name__ == "__main__":
@@ -162,13 +145,3 @@ chosen to make the calculation faster.
162145
pytest.main(["-s", __file__])
163146
164147
.. label:: end_test_7a_class
165-
166-
Which should return a value for :math:`p V / R T` that is close to the expected value
167-
of 1.5 by Wood and Parker for :math:`\tau = V/V^* = 2` (see Fig. 4 in Ref. :cite:`woodMonteCarloEquation1957`):
168-
169-
.. code-block:: bw
170-
171-
(...)
172-
p v / R T = 1.56 --- (The expected value from Wood1957 is 1.5)
173-
174-
The exact value will vary from one simulation to the other due to noise.

0 commit comments

Comments
 (0)