11.. _chapter1-label :
22
3- Start coding
3+ Start Coding
44============
55
6+ Let's start with the Python script. During this first chapter, some Python
7+ files will be created and filled in a minimal fashion. At the end of this
8+ chapter, a small test will be set up to ensure that the files were correctly
9+ created.
10+
611Presentation
712------------
813
@@ -34,94 +39,89 @@ containing either Python functions or classes:
3439
3540 * - File Name
3641 - Content
37- * - * Prepare.py *
42+ * - Prepare.py
3843 - *Prepare * class: Methods for preparing the non-dimensionalization of the
3944 units
40- * - *Utilities.py *
41- - *Utilities * class: General-purpose methods, inherited by all other classes
42- * - *InitializeSimulation.py *
45+ * - Utilities.py
46+ - *Utilities * class: General-purpose methods, inherited by all other
47+ classes
48+ * - InitializeSimulation.py
4349 - *InitializeSimulation * class: Methods necessary to set up the system and
4450 prepare the simulation, inherited by all the classes below
45- * - * MinimizeEnergy.py *
51+ * - MinimizeEnergy.py
4652 - *MinimizeEnergy * class: Methods for performing energy minimization
47- * - * MonteCarlo.py *
53+ * - MonteCarlo.py
4854 - *MonteCarlo * class: Methods for performing Monte Carlo simulations in
4955 different ensembles (e.g., Grand Canonical, Canonical)
50- * - * MolecularDynamics.py *
56+ * - MolecularDynamics.py
5157 - *MolecularDynamics * class: Methods for performing molecular dynamics in
5258 different ensembles (NVE, NPT, NVT)
53- * - * measurements .py*
54- - Functions for performing specific measurements on the system
59+ * - Measurements .py
60+ - * Measurements * class: Methods for for performing specific measurements on the system
5561 * - *potentials.py *
5662 - Functions for calculating the potentials and forces between atoms
57- * - * tools .py*
63+ * - logger .py
5864 - Functions for outputting data into text files
65+ * - dumper.py
66+ - Functions for outputting data into trajectory files for visualization
67+ * - reader.py
68+ - Functions for importing data from text files
5969
70+ Some of these files are created in this chapter; others will be created later
71+ on. All of these files must be created within the same folder.
6072
61- Potential for inter-atomic interaction
73+ Potential for Inter-Atomic Interaction
6274--------------------------------------
6375
64- In molecular simulations, potential functions are used to mimic the interaction
65- between atoms. Although more complicated options exist, potentials are usually
76+ In molecular simulations, potential functions are used to model the interaction
77+ between atoms. Although more complex options exist, potentials are usually
6678defined as functions of the distance :math: `r` between two atoms.
6779
68- Within a dedicated folder, create the first file named *potentials.py *. This
69- file will contain a function called *potentials *. Two types of potential can
70- be returned by this function: the Lennard-Jones potential (LJ), and the
71- hard-sphere potential.
80+ Create a file named *potentials.py *. This file will contain a function called
81+ *potentials *. For now, the only potential that can be returned by this function
82+ is the Lennard-Jones (LJ) potential, but this may change in the future.
7283
7384Copy the following lines into *potentials.py *:
7485
7586.. label :: start_potentials_class
7687
7788.. code-block :: python
7889
79- import numpy as np
80-
81- def potentials (potential_type , epsilon , sigma , r , derivative = False ):
82- if potential_type == " Lennard-Jones" :
83- if derivative:
84- return 48 * epsilon * ((sigma / r) ** 12 - 0.5 * (sigma / r) ** 6 ) / r
85- else :
86- return 4 * epsilon * ((sigma / r) ** 12 - (sigma / r) ** 6 )
87- elif potential_type == " Hard-Sphere" :
88- if derivative:
89- # Derivative is not defined for Hard-Sphere potential.
90- # --> return 0
91- return np.zeros(len (r))
92- else :
93- return np.where(r > sigma, 0 , 1000 )
90+ def potentials (epsilon , sigma , r , derivative = False ):
91+ if derivative:
92+ return 48 * epsilon * ((sigma / r) ** 12 - 0.5 * (sigma / r) ** 6 ) / r
9493 else :
95- raise ValueError ( f " Unknown potential type: { potential_type } " )
94+ return 4 * epsilon * ((sigma / r) ** 12 - (sigma / r) ** 6 )
9695
9796 .. label :: end_potentials_class
9897
99- The hard-sphere potential either returns a value of 0 when the distance between
100- the two particles is larger than the parameter, :math: `r > \sigma `, or 1000 when
101- :math: `r < \sigma `. The value of *1000 * was chosen to be large enough to ensure
102- that any Monte Carlo move that would lead to the two particles to overlap will
103- be rejected.
104-
105- In the case of the LJ potential, depending on the value of the optional
106- argument *derivative *, which can be either *False * or *True *, the *LJ_potential *
107- function will return the force:
98+ Depending on the value of the optional argument *derivative *, which can be
99+ either *False * or *True *, this function returns the derivative of the potential,
100+ i.e., the force, :math: `F_\text {LJ} = - \mathrm {d} U_\text {LJ} / \mathrm {d} r`:
108101
109102.. math ::
110103
111- F_\text {LJ} = 48 \dfrac {\epsilon }{r} \left [ \left ( \frac {\sigma }{r} \right )^{12 } - \frac {1 }{2 } \left ( \frac {\sigma }{r} \right )^6 \right ],
104+ F_\text {LJ} = 48 \dfrac {\epsilon }{r} \left [ \left ( \frac {\sigma }{r} \right )^{12 }
105+ - \frac {1 }{2 } \left ( \frac {\sigma }{r} \right )^6 \right ], ~ \text {for} ~ r < r_\text {c},
112106
113107 or the potential energy:
114108
115109.. math ::
116110
117- U_\text {LJ} = 4 \epsilon \left [ \left ( \frac {\sigma }{r} \right )^{12 } - \left ( \frac {\sigma }{r} \right )^6 \right ].
111+ U_\text {LJ} = 4 \epsilon \left [ \left ( \frac {\sigma }{r} \right )^{12 }
112+ - \left ( \frac {\sigma }{r} \right )^6 \right ], ~ \text {for} ~ r < r_\text {c}.
113+
114+ Here, :math: `\sigma ` is the distance at which the potential :math: `U_\text {LJ}`
115+ is zero, :math: `\epsilon ` is the depth of the potential well, and
116+ :math: `r_\text {c}` is a cutoff distance. For :math: `r > r_\text {c}`,
117+ :math: `U_\text {LJ} = 0 ` and :math: `F_\text {LJ} = 0 `.
118118
119119Create the Classes
120120------------------
121121
122- Let's create the files with the minimal information about the classes and
123- their inheritance. The classes will be developed progressively in the
124- following chapters.
122+ Let's create the files with some minimal details about the classes and their
123+ inheritance. The classes will be developed progressively in the following
124+ chapters.
125125
126126The first class is the *Prepare * class, which will be used for the
127127nondimensionalization of the parameters. In the same folder as *potentials.py *,
@@ -157,20 +157,22 @@ copy the following lines:
157157
158158 .. label :: end_Utilities_class
159159
160- The line *from potentials import LJ_potential * is used to import the
161- * LJ_potential * function.
160+ The line *from potentials import potentials * is used to import the
161+ previously created * potentials * function.
162162
163163Within the *InitializeSimulation.py * file, copy the following lines:
164164
165165.. label :: start_InitializeSimulation_class
166166
167167.. code-block :: python
168168
169+ import os
169170 import numpy as np
170171 from Prepare import Prepare
172+ from Utilities import Utilities
171173
172174
173- class InitializeSimulation (Prepare ):
175+ class InitializeSimulation (Prepare , Utilities ):
174176 def __init__ (self ,
175177 * args ,
176178 ** kwargs ,
@@ -180,39 +182,50 @@ Within the *InitializeSimulation.py* file, copy the following lines:
180182 .. label :: end_InitializeSimulation_class
181183
182184The *InitializeSimulation * class inherits from the previously created
183- *Prepare * class. Additionally, we anticipate that *NumPy * will be required.
185+ *Prepare * and *Utilities * classes. Additionally, we anticipate that |NumPy |
186+ will be required :cite: `harris2020array `. We also anticipate that the *os *
187+ module, which provides a way to interact with the operating system, will
188+ be required :cite: `Rossum2009Python3 `.
189+
190+ .. |NumPy | raw :: html
191+
192+ <a href="https://numpy.org/" target="_blank">NumPy</a>
184193
185194Within the *Measurements.py * file, copy the following lines:
186195
187196.. label :: start_Measurements_class
188197
189198.. code-block :: python
190199
200+ import numpy as np
191201 from InitializeSimulation import InitializeSimulation
192- from Utilities import Utilities
193202
194203
195- class Measurements (InitializeSimulation , Utilities ):
204+ class Measurements (InitializeSimulation ):
196205 def __init__ (self ,
197206 * args ,
198207 ** kwargs ):
199208 super ().__init__ (* args, ** kwargs)
200209
201210 .. label :: end_Measurements_class
202211
203- The *Measurements * class inherits both the *InitializeSimulation * and
204- *Utilities * classes.
212+ The *Measurements * class inherits from *InitializeSimulation * (and thus
213+ also inherits from the *Prepare * and *Utilities * classes).
214+
215+ Finally, let us create the three remaining classes: *MinimizeEnergy *,
216+ *MonteCarlo *, and *MolecularDynamics *. Each of these classes inherits
217+ from the *Measurements * class (and thus also from the *Prepare *, *Utilities *,
218+ and *InitializeSimulation * classes).
205219
206- Finally, let us create the three remaining classes, named *MinimizeEnergy *,
207- *MonteCarlo *, and *MolecularDynamics *. Each of these three classes inherits
208- from the *Measurements * class, and thus from the classes inherited by
209- *Measurements *. Within the *MinimizeEnergy.py * file, copy the following lines:
220+ Within the *MinimizeEnergy.py * file, copy the following lines:
210221
211222.. label :: start_MinimizeEnergy_class
212223
213224.. code-block :: python
214225
215226 from Measurements import Measurements
227+ import numpy as np
228+ import copy
216229 import os
217230
218231
@@ -224,19 +237,17 @@ from the *Measurements* class, and thus from the classes inherited by
224237
225238 .. label :: end_MinimizeEnergy_class
226239
227- We anticipate that the * os * module , which provides a way to interact with the
228- operating system, will be required :cite: ` Rossum2009Python3 ` .
240+ The * copy * library , which provides functions to create shallow or deep copies of
241+ objects, is imported, along with * NumPy * and * os * .
229242
230243Within the *MonteCarlo.py * file, copy the following lines:
231244
232245.. label :: start_MonteCarlo_class
233246
234247.. code-block :: python
235248
236- from scipy import constants as cst
237249 import numpy as np
238250 import copy
239- import os
240251 from Measurements import Measurements
241252
242253 import warnings
@@ -251,12 +262,10 @@ Within the *MonteCarlo.py* file, copy the following lines:
251262
252263 .. label :: end_MonteCarlo_class
253264
254- Several libraries were imported, namely *Constants * from *SciPy *, *NumPy *, *copy *
255- and *os *.
256-
257- The *warnings * was placed to avoid the anoying message "*RuntimeWarning: overflow
258- encountered in exp *" that is sometimes triggered by the exponential of the
259- *acceptation_probability * (see :ref: `chapter6-label `).
265+ The *ignore warnings * commands are optional; they were added to avoid the
266+ annoying message "*RuntimeWarning: overflow encountered in exp *" that is sometimes
267+ triggered by the exponential function of *acceptation_probability * (see the
268+ :ref: `chapter6-label ` chapter).
260269
261270Finally, within the *MolecularDynamics.py * file, copy the following lines:
262271
@@ -294,12 +303,14 @@ and copy the following lines into it:
294303
295304 # Make sure that MonteCarlo correctly inherits from Utilities
296305 def test_montecarlo_inherits_from_utilities ():
297- assert issubclass (MonteCarlo, Utilities), " MonteCarlo should inherit from Utilities"
306+ assert issubclass (MonteCarlo, Utilities), \
307+ " MonteCarlo should inherit from Utilities"
298308 print (" MonteCarlo correctly inherits from Utilities" )
299309
300310 # Make sure that Utilities does not inherit from MonteCarlo
301311 def test_utilities_does_not_inherit_from_montecarlo ():
302- assert not issubclass (Utilities, MonteCarlo), " Utilities should not inherit from MonteCarlo"
312+ assert not issubclass (Utilities, MonteCarlo), \
313+ " Utilities should not inherit from MonteCarlo"
303314 print (" Utilities does not inherit from MonteCarlo, as expected" )
304315
305316 # In the script is launched with Python, call Pytest
@@ -317,15 +328,15 @@ any *AssertionError*:
317328 Utilities does not inherit from MonteCarlo, as expected
318329 MonteCarlo correctly inherits from Utilities
319330
320- Alternatively, this test can also be launched using Pytest by typing in a terminal:
331+ Alternatively, this test can also be launched using * Pytest * by typing in a terminal:
321332
322333.. code-block :: bash
323334
324335 pytest .
325336
326- We can also test that calling the *__init__ *
327- method of the * MonteCarlo * class does not return any error. In new Python file
328- called * test_1b.py *, copy the following lines:
337+ We can also test that calling the *__init__ * method of the * MonteCarlo * class
338+ does not return any error. In new Python file called * test_1b.py *, copy the
339+ following lines:
329340
330341.. label :: start_test_1b_class
331342
0 commit comments