Skip to content

Commit a612c41

Browse files
committed
continue simplifying unit conversion system
1 parent ff5a598 commit a612c41

File tree

4 files changed

+103
-78
lines changed

4 files changed

+103
-78
lines changed

docs/source/chapters/chapter3.rst

Lines changed: 1 addition & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -23,7 +23,7 @@ Let us improve the previously created *InitializeSimulation* class:
2323

2424
.. code-block:: python
2525
26-
class InitializeSimulation(Prepare):
26+
class InitializeSimulation(Prepare, Utilities):
2727
def __init__(self,
2828
box_dimensions, # List - Angstroms
2929
cut_off, # Angstroms
@@ -192,7 +192,6 @@ neighboring atoms, the simulation becomes more efficient. Add the following
192192
193193
def update_neighbor_lists(self):
194194
if (self.step % self.neighbor == 0):
195-
print(self.cut_off)
196195
matrix = distances.contact_matrix(self.atoms_positions,
197196
cutoff=self.cut_off, #+2,
198197
returntype="numpy",

docs/source/chapters/chapter4.rst

Lines changed: 35 additions & 53 deletions
Original file line numberDiff line numberDiff line change
@@ -68,22 +68,17 @@ Then, let us fill the *__init__()* method:
6868
class MinimizeEnergy(Measurements):
6969
def __init__(self,
7070
maximum_steps,
71-
cut_off=9,
72-
neighbor=1,
73-
displacement=0.01,
7471
thermo_outputs="MaxF",
75-
data_folder=None,
72+
data_folder="Outputs/",
7673
*args,
7774
**kwargs):
78-
self.displacement = displacement
7975
self.maximum_steps = maximum_steps
8076
self.thermo_outputs = thermo_outputs
8177
self.data_folder = data_folder
82-
if self.data_folder is not None:
83-
if os.path.exists(self.data_folder) is False:
84-
os.mkdir(self.data_folder)
78+
if os.path.exists(self.data_folder) is False:
79+
os.mkdir(self.data_folder)
8580
super().__init__(*args, **kwargs)
86-
81+
8782
.. label:: end_MinimizeEnergy_class
8883

8984
An important parameter is *maximum_steps*, which sets the maximum number
@@ -94,37 +89,6 @@ displacement value.
9489
The *thermo_outputs* and *data_folder* parameters are used for printing data
9590
to files. These two parameters will be useful in the next chapter, :ref:`chapter5-label`.
9691

97-
Nondimensionalize units
98-
-----------------------
99-
100-
As was done previously, some parameters from the *MinimizeEnergy* class
101-
must be non-dimensionalized: *cut_off* and *displacement*. Add the following
102-
method to the *MinimizeEnergy* class:
103-
104-
.. label:: start_MinimizeEnergy_class
105-
106-
.. code-block:: python
107-
108-
def nondimensionalize_units_2(self):
109-
"""Use LJ prefactors to convert units into non-dimensional."""
110-
self.displacement = self.displacement/self.reference_distance
111-
112-
.. label:: end_MinimizeEnergy_class
113-
114-
Let us call the *nondimensionalize_units_2()* method from the *__init__()*
115-
method:
116-
117-
.. label:: start_MinimizeEnergy_class
118-
119-
.. code-block:: python
120-
121-
def __init__(self,
122-
(...)
123-
super().__init__(*args, **kwargs)
124-
self.nondimensionalize_units_2()
125-
126-
.. label:: end_MinimizeEnergy_class
127-
12892
Energy minimizer
12993
----------------
13094

@@ -136,6 +100,7 @@ following *run()* method to the *MinimizeEnergy* class:
136100
.. code-block:: python
137101
138102
def run(self):
103+
self.displacement = 0.01 # pick a random initial displacement (dimentionless)
139104
# *step* loops for 0 to *maximum_steps*+1
140105
for self.step in range(0, self.maximum_steps+1):
141106
# First, meevaluate the initial energy and max force
@@ -185,7 +150,7 @@ class:
185150
def compute_potential(self):
186151
"""Compute the potential energy by summing up all pair contributions."""
187152
energy_potential = 0
188-
for Ni in np.arange(self.total_number_atoms-1):
153+
for Ni in np.arange(np.sum(self.number_atoms)-1):
189154
# Read neighbor list
190155
neighbor_of_i = self.neighbor_lists[Ni]
191156
# Measure distance
@@ -234,11 +199,11 @@ let us create a new method that is dedicated solely to measuring forces:
234199
235200
def compute_force(self, return_vector = True):
236201
if return_vector: # return a N-size vector
237-
force_vector = np.zeros((self.total_number_atoms,3))
202+
force_vector = np.zeros((np.sum(self.number_atoms),3))
238203
else: # return a N x N matrix
239-
force_matrix = np.zeros((self.total_number_atoms,
240-
self.total_number_atoms,3))
241-
for Ni in np.arange(self.total_number_atoms-1):
204+
force_matrix = np.zeros((np.sum(self.number_atoms),
205+
np.sum(self.number_atoms),3))
206+
for Ni in np.arange(np.sum(self.number_atoms)-1):
242207
# Read neighbor list
243208
neighbor_of_i = self.neighbor_lists[Ni]
244209
# Measure distance
@@ -282,7 +247,7 @@ within the *Utilities* class:
282247
.. code-block:: python
283248
284249
def wrap_in_box(self):
285-
for dim in np.arange(self.dimensions):
250+
for dim in np.arange(3):
286251
out_ids = self.atoms_positions[:, dim] \
287252
> self.box_boundaries[dim][1]
288253
self.atoms_positions[:, dim][out_ids] \
@@ -306,15 +271,32 @@ typically negative.
306271
.. code-block:: python
307272
308273
from MinimizeEnergy import MinimizeEnergy
309-
310-
# Initialize the MinimizeEnergy object and run the minimization
274+
from pint import UnitRegistry
275+
ureg = UnitRegistry()
276+
277+
# Define atom number of each group
278+
nmb_1, nmb_2= [2, 3]
279+
# Define LJ parameters (sigma)
280+
sig_1, sig_2 = [3, 4]*ureg.angstrom
281+
# Define LJ parameters (epsilon)
282+
eps_1, eps_2 = [0.2, 0.4]*ureg.kcal/ureg.mol
283+
# Define atom mass
284+
mss_1, mss_2 = [10, 20]*ureg.gram/ureg.mol
285+
# Define box size
286+
L = 20*ureg.angstrom
287+
# Define a cut off
288+
rc = 2.5*sig_1
289+
290+
# Initialize the prepare object
311291
minimizer = MinimizeEnergy(
292+
ureg = ureg,
312293
maximum_steps=100,
313-
number_atoms=[2, 3],
314-
epsilon=[0.2, 0.4], # kcal/mol
315-
sigma=[3, 4], # A
316-
atom_mass=[10, 20], # g/mol
317-
box_dimensions=[20, 20, 20], # A
294+
number_atoms=[nmb_1, nmb_2],
295+
epsilon=[eps_1, eps_2], # kcal/mol
296+
sigma=[sig_1, sig_2], # A
297+
atom_mass=[mss_1, mss_2], # g/mol
298+
box_dimensions=[L, L, L], # A
299+
cut_off=rc,
318300
)
319301
minimizer.run()
320302

docs/source/chapters/chapter5.rst

Lines changed: 66 additions & 22 deletions
Original file line numberDiff line numberDiff line change
@@ -85,9 +85,9 @@ All quantities are re-dimensionalized before getting outputed.
8585
if code.step % code.thermo_period == 0:
8686
if code.step == 0:
8787
Epot = code.compute_potential() \
88-
* code.reference_energy # kcal/mol
88+
* code.ref_energy # kcal/mol
8989
else:
90-
Epot = code.Epot * code.reference_energy # kcal/mol
90+
Epot = code.Epot * code.ref_energy # kcal/mol
9191
if code.step == 0:
9292
if code.thermo_outputs == "Epot":
9393
logger.info(f"step Epot")
@@ -101,7 +101,7 @@ All quantities are re-dimensionalized before getting outputed.
101101
logger.info(f"{code.step} {Epot:.2f} {code.MaxF:.2f}")
102102
elif code.thermo_outputs == "Epot-press":
103103
code.calculate_pressure()
104-
press = code.pressure * code.reference_pressure # Atm
104+
press = code.pressure * code.ref_pressure # Atm
105105
logger.info(f"{code.step} {Epot:.2f} {press:.2f}")
106106
107107
.. label:: end_logger_class
@@ -125,14 +125,12 @@ a LAMMPS dump format, and can be read by molecular dynamics softwares like VMD.
125125
if code.dumping_period is not None:
126126
if code.step % code.dumping_period == 0:
127127
# Convert units to the *real* dimensions
128-
box_boundaries = code.box_boundaries\
129-
* code.reference_distance # Angstrom
130-
atoms_positions = code.atoms_positions\
131-
* code.reference_distance # Angstrom
128+
box_boundaries = code.box_boundaries*code.ref_length # Angstrom
129+
atoms_positions = code.atoms_positions*code.ref_length # Angstrom
132130
atoms_types = code.atoms_type
133131
if velocity:
134132
atoms_velocities = code.atoms_velocities \
135-
* code.reference_distance/code.reference_time # Angstrom/femtosecond
133+
* code.ref_length/code.ref_time # Angstrom/femtosecond
136134
# Start writting the file
137135
if code.step == 0: # Create new file
138136
f = open(code.data_folder + filename, "w")
@@ -141,18 +139,18 @@ a LAMMPS dump format, and can be read by molecular dynamics softwares like VMD.
141139
f.write("ITEM: TIMESTEP\n")
142140
f.write(str(code.step) + "\n")
143141
f.write("ITEM: NUMBER OF ATOMS\n")
144-
f.write(str(code.total_number_atoms) + "\n")
142+
f.write(str(np.sum(code.number_atoms)) + "\n")
145143
f.write("ITEM: BOX BOUNDS pp pp pp\n")
146144
for dim in np.arange(3):
147-
f.write(str(box_boundaries[dim][0]) + " "
148-
+ str(box_boundaries[dim][1]) + "\n")
145+
f.write(str(box_boundaries[dim][0].magnitude) + " "
146+
+ str(box_boundaries[dim][1].magnitude) + "\n")
149147
cpt = 1
150148
if velocity:
151149
f.write("ITEM: ATOMS id type x y z vx vy vz\n")
152150
characters = "%d %d %.3f %.3f %.3f %.3f %.3f %.3f %s"
153151
for type, xyz, vxyz in zip(atoms_types,
154-
atoms_positions,
155-
atoms_velocities):
152+
atoms_positions.magnitude,
153+
atoms_velocities.magnitude):
156154
v = [cpt, type, xyz[0], xyz[1], xyz[2],
157155
vxyz[0], vxyz[1], vxyz[2]]
158156
f.write(characters % (v[0], v[1], v[2], v[3], v[4],
@@ -162,7 +160,7 @@ a LAMMPS dump format, and can be read by molecular dynamics softwares like VMD.
162160
f.write("ITEM: ATOMS id type x y z\n")
163161
characters = "%d %d %.3f %.3f %.3f %s"
164162
for type, xyz in zip(atoms_types,
165-
atoms_positions):
163+
atoms_positions.magnitude):
166164
v = [cpt, type, xyz[0], xyz[1], xyz[2]]
167165
f.write(characters % (v[0], v[1], v[2],
168166
v[3], v[4], '\n'))
@@ -197,6 +195,35 @@ Add the same lines at the top of the *MinimizeEnergy.py* file:
197195
198196
.. label:: end_MinimizeEnergy_class
199197

198+
Finally, let us make sure that *thermo_period*, *dumping_period*, and *thermo_outputs*
199+
parameters are passed the InitializeSimulation method:
200+
201+
.. label:: start_InitializeSimulation_class
202+
203+
.. code-block:: python
204+
205+
def __init__(self,
206+
(...)
207+
neighbor=1, # Integer
208+
thermo_period = None,
209+
dumping_period = None,
210+
thermo_outputs = None,
211+
212+
.. label:: end_InitializeSimulation_class
213+
214+
.. label:: start_InitializeSimulation_class
215+
216+
.. code-block:: python
217+
218+
def __init__(self,
219+
(...)
220+
self.initial_positions = initial_positions
221+
self.thermo_period = thermo_period
222+
self.dumping_period = dumping_period
223+
self.thermo_outputs = thermo_outputs
224+
225+
.. label:: end_InitializeSimulation_class
226+
200227
Test the code
201228
-------------
202229

@@ -208,21 +235,38 @@ files were indeed created without the *Outputs/* folder:
208235

209236
.. code-block:: python
210237
211-
import os
212238
from MinimizeEnergy import MinimizeEnergy
239+
from pint import UnitRegistry
240+
ureg = UnitRegistry()
241+
import os
213242
214-
# Initialize the MinimizeEnergy object and run the minimization
243+
# Define atom number of each group
244+
nmb_1, nmb_2= [2, 3]
245+
# Define LJ parameters (sigma)
246+
sig_1, sig_2 = [3, 4]*ureg.angstrom
247+
# Define LJ parameters (epsilon)
248+
eps_1, eps_2 = [0.2, 0.4]*ureg.kcal/ureg.mol
249+
# Define atom mass
250+
mss_1, mss_2 = [10, 20]*ureg.gram/ureg.mol
251+
# Define box size
252+
L = 20*ureg.angstrom
253+
# Define a cut off
254+
rc = 2.5*sig_1
255+
256+
# Initialize the prepare object
215257
minimizer = MinimizeEnergy(
258+
ureg = ureg,
216259
maximum_steps=100,
217260
thermo_period=25,
218261
dumping_period=25,
219-
thermo_outputs="Epot-MaxF",
220-
number_atoms=[2, 3],
221-
epsilon=[0.1, 1.0], # kcal/mol
222-
sigma=[3, 4], # A
223-
atom_mass=[10, 20], # g/mol
224-
box_dimensions=[20, 20, 20], # A
262+
number_atoms=[nmb_1, nmb_2],
263+
epsilon=[eps_1, eps_2], # kcal/mol
264+
sigma=[sig_1, sig_2], # A
265+
atom_mass=[mss_1, mss_2], # g/mol
266+
box_dimensions=[L, L, L], # A
267+
cut_off=rc,
225268
data_folder="Outputs/",
269+
thermo_outputs="Epot-MaxF",
226270
)
227271
minimizer.run()
228272

tests/build-documentation.py

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -18,7 +18,7 @@
1818
os.mkdir("generated-codes/")
1919

2020
# loop on the different chapter
21-
for chapter_id in [1, 2, 3]:
21+
for chapter_id in [1, 2, 3, 4, 5]:
2222
# for each chapter, create the corresponding code
2323
RST_EXISTS, created_tests, folder = sphinx_to_python(path_to_docs, chapter_id)
2424
if RST_EXISTS:

0 commit comments

Comments
 (0)