@@ -15,9 +15,9 @@ Initialize the simulation
1515 :align: right
1616 :class: only-light
1717
18- Here, the *InitializeSimulation * class is created . This class is used to
19- prepare the simulation box and populate the box randomly with atoms.
20- Let us improve the previously created *InitializeSimulation * class:
18+ Here, the *InitializeSimulation * class is completed . This class is used to
19+ prepare the simulation box and populate it randomly with atoms. Improve the
20+ previously created *InitializeSimulation * class as follows :
2121
2222.. label :: start_InitializeSimulation_class
2323
@@ -43,30 +43,20 @@ Let us improve the previously created *InitializeSimulation* class:
4343
4444Several parameters are provided to the *InitializeSimulation * class:
4545
46- - The first parameter is the box dimensions, which is a list with a length
47- corresponding to the dimension of the system. Each element of the list
48- corresponds to a dimension of the box in Ångström in the x, y, and z
49- directions, respectively.
50- - Optionally, a seed can be provided as an integer. If the seed is given
51- by the user, the random number generator will always produce the same
52- displacements.
46+ - The box dimensions, which is a list with 3 elements. Each element of
47+ the list corresponds to a dimension of the box in Ångström in the :math: `x`,
48+ :math: `y`, and :math: `z`` directions, respectively.
49+ - The cutoff :math: `r_\text {c}` for the potential interaction.
5350- Optionally, initial positions for the atoms can be provided as an array
5451 of length corresponding to the number of atoms. If *initial_positions *
55- is left equal to *None *, positions will be randomly assigned to the
56- atoms (see below).
57- - A cut off value with a default of 10 Ångströms is defined.
58- - The *neighbor * parameter determines the interval between recalculations of
59- the neighbor lists. By default, a value of 1 is used, meaning that neighbor
60- list will be reconstructed every steps. In certain cases, the number will be
61- increased to recude the computation time.
62-
63- ..
64- - Optionally, a thermo period and a dumping_period can be provided to # TOFIX to be added later
65- control the outputs from the simulation (it will be implemented # TOFIX to be added later
66- in :ref:`chapter5-label`). # TOFIX to be added later
67-
68- Finally, the *dimensions * of the system are calculated as the length of
69- *box_dimensions *.
52+ is set to *None *, positions will be randomly assigned to the atoms (see
53+ below).
54+ - The *neighbor * parameter determines the interval between recalculations
55+ of the neighbor lists. By default, a value of 1 is used, meaning that the
56+ neighbor list will be reconstructed every step. In certain cases, this
57+ number may be increased to reduce computation time.
58+
59+ Note that the simulation step is initialized to 0.
7060
7161Nondimensionalize units
7262-----------------------
@@ -89,8 +79,8 @@ parameters, here the *box_dimensions*, the *cut_off*, as well as the *initial_po
8979Define the box
9080--------------
9181
92- Let us define the simulation box using the values from *box_dimensions *. Add the following
93- method to the *InitializeSimulation * class:
82+ Let us define the simulation box using the values from *box_dimensions *. Add the
83+ following method to the *InitializeSimulation * class:
9484
9585.. label :: start_InitializeSimulation_class
9686
@@ -99,10 +89,8 @@ method to the *InitializeSimulation* class:
9989 def define_box (self ):
10090 """ Define the simulation box. Only 3D boxes are supported."""
10191 box_boundaries = np.zeros((3 , 2 ))
102- dim = 0
103- for L in self .box_dimensions:
92+ for dim, L in enumerate (self .box_dimensions):
10493 box_boundaries[dim] = - L/ 2 , L/ 2
105- dim += 1
10694 self .box_boundaries = box_boundaries
10795 box_size = np.diff(self .box_boundaries).reshape(3 )
10896 box_geometry = np.array([90 , 90 , 90 ])
@@ -113,12 +101,16 @@ method to the *InitializeSimulation* class:
113101The *box_boundaries * are calculated from the *box_dimensions *. They
114102represent the lowest and highest coordinates in all directions. By symmetry,
115103the box is centered at 0 along all axes. A *box_size * is also defined,
116- following the MDAnalysis conventions: Lx, Ly, Lz, 90, 90, 90, where the
117- last three numbers are angles in degrees. Values different from *90 * for
118- the angles would define a triclinic (non-orthogonal) box, which is not
119- currently supported by the existing code.
104+ following the MDAnalysis |mdanalysis_box |: Lx, Ly, Lz, 90, 90, 90, where
105+ the last three numbers are angles in degrees :cite: `michaud2011mdanalysis `.
106+ Values different from *90 * for the angles would define a triclinic (non-orthogonal)
107+ box, which is not currently supported by the existing code.
108+
109+ .. |mdanalysis_box | raw :: html
110+
111+ <a href="https://docs.mdanalysis.org/stable/documentation_pages/transformations/boxdimensions.html" target="_blank">conventions</a>
120112
121- Let us call the *define_box * method from the *__init__ * class :
113+ Let us call *define_box() * from the *__init__() * method :
122114
123115.. label :: start_InitializeSimulation_class
124116
@@ -132,40 +124,41 @@ Let us call the *define_box* method from the *__init__* class:
132124
133125 .. label :: end_InitializeSimulation_class
134126
135- Populate the box
127+ Populate the Box
136128----------------
137129
138130Here, the atoms are placed within the simulation box. If initial
139131positions were not provided (i.e., *initial_positions = None *), atoms
140- are placed randomly within the box. If *initial_positions * was provided
141- as an array, the provided positions are used instead. Note that, in this
132+ are placed randomly within the box. If *initial_positions * is provided
133+ as an array, the provided positions are used instead. Note that in this
142134case, the array must be of size 'number of atoms' times 'number of dimensions'.
143135
144136.. label :: start_InitializeSimulation_class
145137
146138.. code-block :: python
147139
148140 def populate_box (self ):
141+ Nat = np.sum(self .number_atoms) # total number of atoms
149142 if self .initial_positions is None :
150- atoms_positions = np.zeros((np.sum( self .number_atoms) , 3 ))
143+ atoms_positions = np.zeros((Nat , 3 ))
151144 for dim in np.arange(3 ):
152145 diff_box = np.diff(self .box_boundaries[dim])
153- random_pos = np.random.random(np.sum( self .number_atoms) )
146+ random_pos = np.random.random(Nat )
154147 atoms_positions[:, dim] = random_pos* diff_box- diff_box/ 2
155148 self .atoms_positions = atoms_positions
156149 else :
157150 self .atoms_positions = self .initial_positions
158151
159152 .. label :: end_InitializeSimulation_class
160153
161- In case *initial_positions is None *, and array is first created. Then, random
162- positions that are constrained within the box boundaries are defined using the
163- random function of NumPy. Note that, here, the newly added atoms are added
164- randomly within the box, without taking care of avoiding overlaps with
165- existing atoms. Overlaps will be dealt with using energy minimization,
166- see :ref: `chapter4-label `.
154+ In case *initial_positions * is None, an array is first created. Then,
155+ random positions constrained within the box boundaries are defined using
156+ the random function from NumPy. Note that newly added atoms are placed
157+ randomly within the box, without considering overlaps with existing
158+ atoms. Overlaps will be addressed using energy minimization (see
159+ the :ref: `chapter4-label ` chapter) .
167160
168- Let us call the *populate_box * method from the *__init__ * class :
161+ Let us call *populate_box * from the *__init__ * method :
169162
170163.. label :: start_InitializeSimulation_class
171164
@@ -178,7 +171,7 @@ Let us call the *populate_box* method from the *__init__* class:
178171
179172 .. label :: end_InitializeSimulation_class
180173
181- Build neighbor lists
174+ Build Neighbor Lists
182175--------------------
183176
184177In molecular simulations, it is common practice to identify neighboring atoms
@@ -210,12 +203,16 @@ atom, ensuring that only relevant interactions are considered in the
210203calculations. These lists will be recalculated at intervals specified by
211204the *neighbor * input parameter.
212205
213- Update cross coefficients
206+ For efficiency, the *contact_matrix * function from MDAnalysis is
207+ used :cite: `michaud2011mdanalysis `. The *contact_matrix * function returns
208+ information about atoms located at a distance less than the cutoff from one another.
209+
210+ Update Cross Coefficients
214211-------------------------
215212
216- At the same time as the neighbor lists are getting build up , let us also
217- pre-calculate the cross coefficients. This will make the force calculation
218- more practical (see below).
213+ As the neighbor lists are being built , let us also pre-calculate the cross
214+ coefficients. This will make the force calculation more efficient (see
215+ below).
219216
220217.. label :: start_Utilities_class
221218
@@ -250,7 +247,7 @@ Here, the values of the cross coefficients between atom of type 1 and 2,
250247 \sigma _{12 } = (\sigma _{11 }+\sigma _{22 })/2 \\
251248 \epsilon _{12 } = (\epsilon _{11 }+\epsilon _{22 })/2
252249
253- Finally, import the following library in the *Utilities.py * file:
250+ Finally, import the following libraries in the *Utilities.py * file:
254251
255252.. label :: start_Utilities_class
256253
@@ -261,8 +258,8 @@ Finally, import the following library in the *Utilities.py* file:
261258
262259 .. label :: end_Utilities_class
263260
264- Let us call the *update_neighbor_lists * and *update_cross_coefficients *
265- methods from the *__init__ * class :
261+ Let us call *update_neighbor_lists * and *update_cross_coefficients *
262+ from the *__init__ * method :
266263
267264.. label :: start_InitializeSimulation_class
268265
@@ -276,12 +273,11 @@ methods from the *__init__* class:
276273
277274 .. label :: end_InitializeSimulation_class
278275
279- Test the code
276+ Test the Code
280277-------------
281278
282- Let us test the *InitializeSimulation * class to make sure that it does what
283- is expected, i.e. that it does create atoms that are located within the box
284- boundaries along all 3 dimensions of space:
279+ Let us test the *InitializeSimulation * class to ensure that it behaves as
280+ expected, i.e., that it creates atoms located within the box boundaries:
285281
286282.. label :: start_test_3a_class
287283
@@ -333,3 +329,6 @@ boundaries along all 3 dimensions of space:
333329 pytest.main([" -s" , __file__ ])
334330
335331 .. label :: end_test_3a_class
332+
333+ The value of the cutoff, chosen as :math: `2.5 \sigma _{11 }`, is relatively
334+ common for Lennard-Jones fluids and will often be the default choice for us.
0 commit comments