Skip to content

Commit 23b110e

Browse files
committed
started to simplify potential functions
1 parent 939501c commit 23b110e

File tree

3 files changed

+87
-121
lines changed

3 files changed

+87
-121
lines changed

docs/source/chapters/chapter2.rst

Lines changed: 0 additions & 80 deletions
Original file line numberDiff line numberDiff line change
@@ -293,86 +293,6 @@ Let us call the *identify_atom_properties* from the *__init__()* method:
293293
294294
.. label:: end_Prepare_class
295295

296-
..
297-
Calculate cross coefficients
298-
----------------------------
299-
300-
Let us calculate all cross coefficients that are required to calculate the interactions
301-
between atom :math:`i` and atom :math:`j`. From the example described previously,
302-
where:
303-
304-
.. math::
305-
306-
\text{atoms_sigma} = [\sigma_{11}, \sigma_{11}, \sigma_{22}, \sigma_{22}, \sigma_{22}]
307-
308-
one expects all direct and cross coefficients to be:
309-
310-
.. math::
311-
312-
\text{array_sigma_ij} = \begin{bmatrix}
313-
\sigma_{11} & \sigma_{11} & \sigma_{12} & \sigma_{12} & \sigma_{12} \\
314-
\sigma_{11} & \sigma_{11} & \sigma_{12} & \sigma_{12} & \sigma_{12} \\
315-
\sigma_{12} & \sigma_{12} & \sigma_{22} & \sigma_{22} & \sigma_{22} \\
316-
\sigma_{12} & \sigma_{12} & \sigma_{22} & \sigma_{22} & \sigma_{22} \\
317-
\sigma_{12} & \sigma_{12} & \sigma_{22} & \sigma_{22} & \sigma_{22} \\
318-
\end{bmatrix}
319-
320-
321-
The matrix is symmetric, so the coefficients in the bottom left corner are
322-
the same as the coefficient in the top right corner. The first value in the top left corner of the matrix,
323-
:math:`\sigma_{11}`, indicates that the :math:`\sigma` value for the interaction
324-
between the atom 1 and itself is is :math:`\sigma_{11}`. A similar matrix can
325-
be written for epsilon_sigma_ij.
326-
327-
Here, the values of the cross coefficients :math:`\sigma_{12}` and :math:`\epsilon_{12}`
328-
are assumed to follow the arithmetic mean :
329-
330-
.. math::
331-
332-
\sigma_{12} = (\sigma_{11}+\sigma_{22})/2 \\
333-
\epsilon_{12} = (\epsilon_{11}+\epsilon_{22})/2
334-
335-
Create the following method called *calculate_cross_coefficients* within the
336-
*Prepare* class:
337-
338-
. . label:: start_Prepare_class
339-
340-
.. code-block:: python
341-
342-
def calculate_cross_coefficients(self):
343-
"""Calculate all the cross-coefficients for the LJ interations."""
344-
self.identify_atom_properties() # TOFIX: this was left because of GCMC. Remove? Move?
345-
matrix_epsilon_ij = []
346-
matrix_sigma_ij = []
347-
for i in range(self.total_number_atoms):
348-
matrix_epsilon_ij.append([])
349-
matrix_sigma_ij.append([])
350-
for j in range(self.total_number_atoms):
351-
matrix_epsilon_ij[-1].append((self.atoms_epsilon[i]+self.atoms_epsilon[j])/2)
352-
matrix_sigma_ij[-1].append((self.atoms_sigma[i]+self.atoms_sigma[j])/2)
353-
self.matrix_sigma_ij = matrix_sigma_ij
354-
self.matrix_epsilon_ij = matrix_epsilon_ij
355-
356-
. . label:: end_Prepare_class
357-
358-
After calling for the *identify_atom_properties()* method, a double loop
359-
is performed over all direct coefficients, and the cross coefficients
360-
are stored within *matrix_sigma_ij* and *matrix_epsilon_ij*, two matrices.
361-
362-
Finally, let us call the *calculate_cross_coefficients* method from the
363-
*__init__()* method.
364-
365-
. . label:: start_Prepare_class
366-
367-
.. code-block:: python
368-
369-
def __init__(self,
370-
(...)
371-
self.identify_atom_properties()
372-
self.calculate_cross_coefficients()
373-
374-
. . label:: end_Prepare_class
375-
376296
Test the code
377297
-------------
378298

docs/source/chapters/chapter4.rst

Lines changed: 86 additions & 40 deletions
Original file line numberDiff line numberDiff line change
@@ -146,25 +146,21 @@ following *run()* method to the *MinimizeEnergy* class:
146146
# First, meevaluate the initial energy and max force
147147
self.update_neighbor_lists() # Rebuild neighbor list, if necessary
148148
self.update_cross_coefficients() # Recalculate the cross coefficients, if necessary
149-
try: # try using the last saved Epot and MaxF, if it exists
150-
init_Epot = self.Epot
151-
init_MaxF = self.MaxF
152-
except: # If Epot/MaxF do not exists yet, calculate them both
153-
init_Epot = self.compute_potential(output="potential")
154-
forces = self.compute_potential(output="force-vector")
155-
init_MaxF = np.max(np.abs(forces))
149+
if self.step == 0: # At the first step, Epot/MaxF do not exists yet, calculate them both
150+
init_Epot = self.compute_potential()
151+
forces, init_MaxF = self.compute_vector_force()
156152
# Save the current atom positions
157153
init_positions = copy.deepcopy(self.atoms_positions)
158154
# Move the atoms in the opposite direction of the maximum force
159155
self.atoms_positions = self.atoms_positions \
160156
+ forces/init_MaxF*self.displacement
161157
# Recalculate the energy
162-
trial_Epot = self.compute_potential(output="potential")
158+
trial_Epot = self.compute_potential()
163159
# Keep the more favorable energy
164160
if trial_Epot < init_Epot: # accept new position
165161
self.Epot = trial_Epot
166162
# calculate the new max force and save it
167-
forces = self.compute_potential(output="force-vector")
163+
forces, init_MaxF = self.compute_vector_force()
168164
self.MaxF = np.max(np.abs(forces))
169165
self.wrap_in_box() # Wrap atoms in the box, if necessary
170166
self.displacement *= 1.2 # Multiply the displacement by a factor 1.2
@@ -274,42 +270,92 @@ class.
274270

275271
.. code-block:: python
276272
277-
def compute_potential(self, output):
278-
if output == "force-vector":
279-
forces = np.zeros((self.total_number_atoms,3))
280-
elif output == "force-matrix":
281-
forces = np.zeros((self.total_number_atoms,self.total_number_atoms,3))
273+
def compute_potential(self):
274+
"""Compute the potential energy by summing up all pair contributions."""
282275
energy_potential = 0
283-
box_size = self.box_size[:3]
284-
half_box_size = self.box_size[:3]/2.0
285276
for Ni in np.arange(self.total_number_atoms-1):
286-
# Read information about atom i
287-
position_i = self.atoms_positions[Ni]
277+
# Read neighbor list
288278
neighbor_of_i = self.neighbor_lists[Ni]
289-
# Read information about neighbors j and cross coefficient
290-
positions_j = self.atoms_positions[neighbor_of_i]
279+
# Measure distance
280+
rij = self.compute_distance(self.atoms_positions[Ni],
281+
self.atoms_positions[neighbor_of_i],
282+
self.box_size[:3])
283+
# Measure potential using information about cross coefficients
291284
sigma_ij = self.sigma_ij_list[Ni]
292285
epsilon_ij = self.epsilon_ij_list[Ni]
293-
# Measure distances
294-
# Measure distances
295-
# The nan_to_num is crutial in 2D to avoid nan value along third dimension
296-
rij_xyz = np.nan_to_num(np.remainder(position_i - positions_j
297-
+ half_box_size, box_size) - half_box_size)
298-
rij = np.linalg.norm(rij_xyz, axis=1)
299-
# Measure potential
300-
if output == "potential":
301-
energy_potential += np.sum(potentials(self.potential_type, epsilon_ij, sigma_ij, rij))
302-
else:
303-
derivative_potential = potentials(self.potential_type, epsilon_ij, sigma_ij, rij, derivative = True)
304-
if output == "force-vector":
305-
forces[Ni] += np.sum((derivative_potential*rij_xyz.T/rij).T, axis=0)
306-
forces[neighbor_of_i] -= (derivative_potential*rij_xyz.T/rij).T
307-
elif output == "force-matrix":
308-
forces[Ni][neighbor_of_i] += (derivative_potential*rij_xyz.T/rij).T
309-
if output=="potential":
310-
return energy_potential
311-
elif (output == "force-vector") | (output == "force-matrix"):
312-
return forces
286+
energy_potential += np.sum(potentials(self.potential_type,
287+
epsilon_ij, sigma_ij, rij))
288+
return energy_potential
289+
290+
.. label:: end_Utilities_class
291+
292+
.. label:: start_Utilities_class
293+
294+
.. code-block:: python
295+
296+
def compute_distance(self,position_i, positions_j, box_size, only_norm = True):
297+
"""
298+
Measure the distances between two particles.
299+
The nan_to_num is crutial in 2D to avoid nan value along third dimension.
300+
# TOFIX: Move as function instead of a method?
301+
"""
302+
rij_xyz = np.nan_to_num(np.remainder(position_i - positions_j
303+
+ box_size[:3]/2.0, box_size) - box_size[:3]/2.0)
304+
if only_norm:
305+
return np.linalg.norm(rij_xyz, axis=1)
306+
else:
307+
return np.linalg.norm(rij_xyz, axis=1), rij_xyz
308+
309+
.. label:: end_Utilities_class
310+
311+
.. label:: start_Utilities_class
312+
313+
.. code-block:: python
314+
315+
def compute_vector_force(self):
316+
force_vector = np.zeros((self.total_number_atoms,3))
317+
for Ni in np.arange(self.total_number_atoms-1):
318+
# Read neighbor list
319+
neighbor_of_i = self.neighbor_lists[Ni]
320+
# Measure distance
321+
rij, rij_xyz = self.compute_distance(self.atoms_positions[Ni],
322+
self.atoms_positions[neighbor_of_i],
323+
self.box_size[:3], only_norm = False)
324+
# Measure force using information about cross coefficients
325+
sigma_ij = self.sigma_ij_list[Ni]
326+
epsilon_ij = self.epsilon_ij_list[Ni]
327+
fij_xyz = potentials(self.potential_type, epsilon_ij,
328+
sigma_ij, rij, derivative = True)
329+
# Add the contribution to both Ni and its neighbors
330+
force_vector[Ni] += np.sum((fij_xyz*rij_xyz.T/rij).T, axis=0)
331+
force_vector[neighbor_of_i] -= (fij_xyz*rij_xyz.T/rij).T
332+
max_force = np.max(np.abs(force_vector))
333+
return force_vector, max_force
334+
335+
.. label:: end_Utilities_class
336+
337+
.. label:: start_Utilities_class
338+
339+
.. code-block:: python
340+
341+
def compute_vector_matrix(self):
342+
force_matrix = np.zeros((self.total_number_atoms,
343+
self.total_number_atoms,3))
344+
for Ni in np.arange(self.total_number_atoms-1):
345+
# Read neighbor list
346+
neighbor_of_i = self.neighbor_lists[Ni]
347+
# Measure distance
348+
rij, rij_xyz = self.compute_distance(self.atoms_positions[Ni],
349+
self.atoms_positions[neighbor_of_i],
350+
self.box_size[:3], only_norm = False)
351+
# Measure force using information about cross coefficients
352+
sigma_ij = self.sigma_ij_list[Ni]
353+
epsilon_ij = self.epsilon_ij_list[Ni]
354+
fij_xyz = potentials(self.potential_type, epsilon_ij,
355+
sigma_ij, rij, derivative = True)
356+
# Add the contribution to the force matrix
357+
force_matrix[Ni][neighbor_of_i] += (fij_xyz*rij_xyz.T/rij).T
358+
return force_matrix
313359
314360
.. label:: end_Utilities_class
315361

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, 4, 5, 6, 7]:
21+
for chapter_id in [1, 2, 3, 4]: #, 5, 6, 7]:
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)