2222import numpy as np
2323import pytest
2424
25- from tinyff .forcefield import CutOffWrapper , LennardJones , PairwiseForceField
25+ from tinyff .atomsmithy import PushPotential
26+ from tinyff .forcefield import CutOffWrapper , ForceField , LennardJones
2627from tinyff .neighborlist import NBuildCellLists , NBuildSimple
2728
2829
2930def test_lennard_jones_derivative ():
3031 lj = LennardJones (2.5 , 0.5 )
3132 dist = np .linspace (0.4 , 3.0 , 50 )
32- gdist1 = lj (dist )[1 ]
33- gdist2 = nd .Derivative (lambda dist : lj (dist )[0 ])(dist )
33+ gdist1 = lj . compute (dist )[1 ]
34+ gdist2 = nd .Derivative (lambda dist : lj . compute (dist )[0 ])(dist )
3435 assert gdist1 == pytest .approx (gdist2 )
3536
3637
3738def test_lennard_jones_cut_derivative ():
3839 lj = CutOffWrapper (LennardJones (2.5 , 0.5 ), 3.5 )
3940 dist = np .linspace (0.4 , 5.0 , 50 )
40- gdist1 = lj (dist )[1 ]
41- gdist2 = nd .Derivative (lambda x : lj (x )[0 ])(dist )
41+ gdist1 = lj . compute (dist )[1 ]
42+ gdist2 = nd .Derivative (lambda x : lj . compute (x )[0 ])(dist )
4243 assert gdist1 == pytest .approx (gdist2 )
4344
4445
4546def test_lennard_jones_cut_zero_array ():
4647 lj = CutOffWrapper (LennardJones (2.5 , 0.5 ), 3.5 )
47- e , g = lj ([5.0 , 3.6 ])
48+ e , g = lj . compute ([5.0 , 3.6 ])
4849 assert (e == 0.0 ).all ()
4950 assert (g == 0.0 ).all ()
5051
5152
5253def test_lennard_jones_cut_zero_scalar ():
5354 lj = CutOffWrapper (LennardJones (2.5 , 0.5 ), 3.5 )
54- e , g = lj (5.0 )
55+ e , g = lj . compute (5.0 )
5556 assert e == 0.0
5657 assert g == 0.0
5758
@@ -65,13 +66,12 @@ def test_pairwise_force_field_two(nbuild_class):
6566 # Define the force field.
6667 rcut = 8.0
6768 lj = CutOffWrapper (LennardJones (2.5 , 1.3 ), rcut )
68- nbuild = nbuild_class (rcut )
69- pwff = PairwiseForceField (lj , nbuild )
69+ ff = ForceField ([lj ], nbuild_class (rcut ))
7070
7171 # Compute and check against manual result
72- energy , forces , frc_press = pwff (atpos , cell_length )
72+ energy , forces , frc_press = ff (atpos , cell_length )
7373 d = np .linalg .norm (atpos [0 ] - atpos [1 ])
74- e , g = lj (d )
74+ e , g = lj . compute (d )
7575 assert energy == pytest .approx (e )
7676 assert forces == pytest .approx (np .array ([[g , 0.0 , 0.0 ], [- g , 0.0 , 0.0 ]]))
7777 assert frc_press == pytest .approx (- g * d / (3 * cell_length ** 3 ))
@@ -86,31 +86,30 @@ def test_pairwise_force_field_three(nbuild_class):
8686 # Define the force field.
8787 rcut = 8.0
8888 lj = CutOffWrapper (LennardJones (2.5 , 1.3 ), rcut )
89- nbuild = nbuild_class (rcut )
90- pwff = PairwiseForceField (lj , nbuild )
89+ ff = ForceField ([lj ], nbuild_class (rcut ))
9190
9291 # Compute the energy, the forces and the force contribution pressure.
93- energy1 , forces1 , frc_press1 = pwff (atpos , cell_length )
92+ energy1 , forces1 , frc_press1 = ff (atpos , cell_length )
9493
9594 # Compute the energy manually and compare.
9695 dists = [
9796 np .linalg .norm (atpos [1 ] - atpos [2 ]),
9897 np .linalg .norm (atpos [2 ] - atpos [0 ]),
9998 np .linalg .norm (atpos [0 ] - atpos [1 ]),
10099 ]
101- energy2 = lj (dists )[0 ].sum ()
100+ energy2 = lj . compute (dists )[0 ].sum ()
102101 assert energy1 == pytest .approx (energy2 )
103102
104103 # Test forces with numdifftool
105- forces2 = - nd .Gradient (lambda x : pwff (x .reshape (- 1 , 3 ), cell_length )[0 ])(atpos )
104+ forces2 = - nd .Gradient (lambda x : ff (x .reshape (- 1 , 3 ), cell_length )[0 ])(atpos )
106105 forces2 .shape = (- 1 , 3 )
107106 assert forces1 == pytest .approx (forces2 .reshape (- 1 , 3 ))
108107
109108 # Test pressure with numdifftool
110109 def energy_volume (volume ):
111110 my_cell_length = volume ** (1.0 / 3.0 )
112111 scale = my_cell_length / cell_length
113- return pwff (atpos * scale , my_cell_length )[0 ]
112+ return ff (atpos * scale , my_cell_length )[0 ]
114113
115114 frc_press2 = - nd .Derivative (energy_volume )(cell_length ** 3 )
116115 assert frc_press1 == pytest .approx (frc_press2 )
@@ -143,23 +142,43 @@ def test_pairwise_force_field_fifteen(nbuild_class):
143142 # Define the force field.
144143 rcut = 8.0
145144 lj = CutOffWrapper (LennardJones (2.5 , 1.3 ), rcut )
146- nbuild = nbuild_class (rcut )
147- pwff = PairwiseForceField (lj , nbuild )
145+ ff = ForceField ([lj ], nbuild_class (rcut ))
148146
149147 # Compute the energy, the forces and the force contribution to the pressure.
150- energy , forces1 , frc_press1 = pwff (atpos , cell_length )
148+ energy , forces1 , frc_press1 = ff (atpos , cell_length )
151149 assert energy < 0
152150
153151 # Test forces with numdifftool
154- forces2 = - nd .Gradient (lambda x : pwff (x .reshape (- 1 , 3 ), cell_length )[0 ])(atpos )
152+ forces2 = - nd .Gradient (lambda x : ff (x .reshape (- 1 , 3 ), cell_length )[0 ])(atpos )
155153 forces2 .shape = (- 1 , 3 )
156154 assert forces1 == pytest .approx (forces2 .reshape (- 1 , 3 ))
157155
158156 # Test pressure with numdifftool
159157 def energy_volume (volume ):
160158 my_cell_length = volume ** (1.0 / 3.0 )
161159 scale = my_cell_length / cell_length
162- return pwff (atpos * scale , my_cell_length )[0 ]
160+ return ff (atpos * scale , my_cell_length )[0 ]
163161
164162 frc_press2 = - nd .Derivative (energy_volume )(cell_length ** 3 )
165163 assert frc_press1 == pytest .approx (frc_press2 )
164+
165+
166+ @pytest .mark .parametrize ("nbuild_class" , [NBuildSimple , NBuildCellLists ])
167+ def test_superposition (nbuild_class ):
168+ atpos = np .array ([[0.0 , 0.0 , 5.0 ], [0.0 , 0.0 , 0.0 ], [0.0 , 3.0 , 0.0 ]])
169+ cell_length = 10.0
170+
171+ # Define the force field.
172+ rcut = 4.9
173+ lj = CutOffWrapper (LennardJones (2.5 , 1.3 ), rcut )
174+ pp = PushPotential (rcut )
175+ ff_lj = ForceField ([lj ], nbuild_class (rcut ))
176+ ff_pp = ForceField ([pp ], nbuild_class (rcut ))
177+ ff_su = ForceField ([lj , pp ], nbuild_class (rcut ))
178+
179+ energy_lj , forces_lj , frc_press_lj = ff_lj (atpos , cell_length )
180+ energy_pp , forces_pp , frc_press_pp = ff_pp (atpos , cell_length )
181+ energy_su , forces_su , frc_press_su = ff_su (atpos , cell_length )
182+ assert energy_lj + energy_pp == pytest .approx (energy_su )
183+ assert forces_lj + forces_pp == pytest .approx (forces_su )
184+ assert frc_press_lj + frc_press_pp == pytest .approx (frc_press_su )
0 commit comments