1
+ import logging
1
2
import unittest
2
3
3
4
from ase .build import bulk
5
+ from ase .constraints import FixAtoms , FixedPlane , FixCom
4
6
import numpy as np
5
7
6
8
from pylammpsmpi import LammpsASELibrary , LammpsLibrary
9
+ from pylammpsmpi .wrapper .ase import (
10
+ cell_is_skewed ,
11
+ get_species_symbols ,
12
+ get_structure_indices ,
13
+ get_lammps_indicies_from_ase_structure ,
14
+ set_selective_dynamics ,
15
+ )
7
16
8
17
9
18
class TestLammpsASELibrary (unittest .TestCase ):
@@ -12,13 +21,13 @@ def test_static(self):
12
21
working_directory = None ,
13
22
cores = 1 ,
14
23
comm = None ,
15
- logger = None ,
24
+ logger = logging . getLogger ( "TestStaticLogger" ) ,
16
25
log_file = None ,
17
26
library = LammpsLibrary (cores = 2 , mode = 'local' ),
18
27
diable_log_file = True ,
19
28
)
20
29
structure = bulk ("Al" , cubic = True ).repeat ([2 , 2 , 2 ])
21
- lmp .interactive_lib_command (command = "units lj" )
30
+ lmp .interactive_lib_command (command = "units lj" )
22
31
lmp .interactive_lib_command (command = "atom_style atomic" )
23
32
lmp .interactive_lib_command (command = "atom_modify map array" )
24
33
lmp .interactive_structure_setter (
@@ -32,6 +41,8 @@ def test_static(self):
32
41
)
33
42
lmp .interactive_lib_command ("pair_style lj/cut 6.0" )
34
43
lmp .interactive_lib_command ("pair_coeff 1 1 1.0 1.0 4.04" )
44
+ lmp .interactive_lib_command (command = "thermo_style custom step temp pe etotal pxx pxy pxz pyy pyz pzz vol" )
45
+ lmp .interactive_lib_command (command = "thermo_modify format float %20.15g" )
35
46
lmp .interactive_lib_command ("run 0" )
36
47
self .assertTrue (np .all (np .isclose (lmp .interactive_cells_getter (), structure .cell .array )))
37
48
self .assertTrue (np .isclose (lmp .interactive_energy_pot_getter (), - 0.04342932384411341 ))
@@ -41,20 +52,26 @@ def test_static(self):
41
52
self .assertTrue (np .all (lmp .interactive_indices_getter () == [1 ] * len (structure )))
42
53
self .assertEqual (lmp .interactive_steps_getter (), 0 )
43
54
self .assertEqual (lmp .interactive_temperatures_getter (), 0 )
55
+ self .assertTrue (np .isclose (np .sum (lmp .interactive_pressures_getter ()), - 0.015661731917941832 ))
56
+ self .assertEqual (np .sum (lmp .interactive_velocities_getter ()), 0.0 )
57
+ self .assertTrue (np .isclose (np .sum (lmp .interactive_positions_getter ()), 291.6 ))
58
+ lmp .interactive_cells_setter (cell = 1.01 * structure .cell .array )
59
+ lmp .interactive_lib_command ("run 0" )
60
+ self .assertTrue (np .all (np .isclose (lmp .interactive_cells_getter (), 1.01 * structure .cell .array )))
44
61
lmp .close ()
45
62
46
63
def test_static_with_statement (self ):
47
64
structure = bulk ("Al" ).repeat ([2 , 2 , 2 ])
48
65
with LammpsASELibrary (
49
66
working_directory = None ,
50
- cores = 1 ,
67
+ cores = 2 ,
51
68
comm = None ,
52
69
logger = None ,
53
70
log_file = None ,
54
- library = LammpsLibrary ( cores = 2 , mode = 'local' ) ,
71
+ library = None ,
55
72
diable_log_file = True ,
56
73
) as lmp :
57
- lmp .interactive_lib_command (command = "units lj" )
74
+ lmp .interactive_lib_command (command = "units lj" )
58
75
lmp .interactive_lib_command (command = "atom_style atomic" )
59
76
lmp .interactive_lib_command (command = "atom_modify map array" )
60
77
lmp .interactive_structure_setter (
@@ -68,6 +85,8 @@ def test_static_with_statement(self):
68
85
)
69
86
lmp .interactive_lib_command ("pair_style lj/cut 6.0" )
70
87
lmp .interactive_lib_command ("pair_coeff 1 1 1.0 1.0 4.04" )
88
+ lmp .interactive_lib_command (command = "thermo_style custom step temp pe etotal pxx pxy pxz pyy pyz pzz vol" )
89
+ lmp .interactive_lib_command (command = "thermo_modify format float %20.15g" )
71
90
lmp .interactive_lib_command ("run 0" )
72
91
self .assertTrue (np .isclose (lmp .interactive_energy_pot_getter (), - 0.3083820387630098 ))
73
92
self .assertTrue (np .isclose (lmp .interactive_energy_tot_getter (), - 0.3083820387630098 ))
@@ -76,3 +95,98 @@ def test_static_with_statement(self):
76
95
self .assertTrue (np .all (lmp .interactive_indices_getter () == [1 ] * len (structure )))
77
96
self .assertEqual (lmp .interactive_steps_getter (), 0 )
78
97
self .assertEqual (lmp .interactive_temperatures_getter (), 0 )
98
+ self .assertTrue (np .isclose (np .sum (lmp .interactive_pressures_getter ()), - 0.00937227406237915 ))
99
+ self .assertEqual (np .sum (lmp .interactive_velocities_getter ()), 0.0 )
100
+
101
+
102
+ class TestASEHelperFunctions (unittest .TestCase ):
103
+ @classmethod
104
+ def setUpClass (cls ):
105
+ cls .structure_skewed = bulk ("Al" ).repeat ([2 , 2 , 2 ])
106
+ cls .structure_cubic = bulk ("Al" , cubic = True ).repeat ([2 , 2 , 2 ])
107
+
108
+ def test_get_species_symbols (self ):
109
+ self .assertEqual (get_species_symbols (structure = self .structure_cubic ),['Al' ])
110
+
111
+ def test_get_structure_indices (self ):
112
+ indicies = get_structure_indices (structure = self .structure_cubic )
113
+ self .assertEqual (len (indicies ), len (self .structure_cubic ))
114
+ self .assertEqual (len (set (indicies )), 1 )
115
+ self .assertEqual (set (indicies ), {0 })
116
+
117
+ def test_cell_is_skewed (self ):
118
+ self .assertTrue (cell_is_skewed (cell = self .structure_skewed .cell ))
119
+ self .assertFalse (cell_is_skewed (cell = self .structure_cubic .cell ))
120
+
121
+ def test_get_lammps_indicies_from_ase_structure (self ):
122
+ indicies = get_lammps_indicies_from_ase_structure (
123
+ structure = self .structure_cubic ,
124
+ el_eam_lst = ["Al" , "H" ]
125
+ )
126
+ self .assertEqual (len (indicies ), len (self .structure_cubic ))
127
+ self .assertEqual (len (set (indicies )), 1 )
128
+ self .assertEqual (set (indicies ), {1 })
129
+
130
+
131
+ class TestConstraints (unittest .TestCase ):
132
+ @classmethod
133
+ def setUpClass (cls ):
134
+ structure = bulk ("Cu" , cubic = True )
135
+ structure .symbols [2 :] = "Al"
136
+ cls .structure = structure
137
+
138
+ def test_selective_dynamics_mixed_calcmd (self ):
139
+ atoms = self .structure .copy ()
140
+ c1 = FixAtoms (indices = [atom .index for atom in atoms if atom .symbol == 'Cu' ])
141
+ c2 = FixedPlane (
142
+ [atom .index for atom in atoms if atom .symbol == 'Al' ],
143
+ [1 , 0 , 0 ],
144
+ )
145
+ atoms .set_constraint ([c1 , c2 ])
146
+ control_dict = set_selective_dynamics (structure = atoms , calc_md = True )
147
+ self .assertEqual (len (control_dict ), 6 )
148
+ self .assertTrue (control_dict ['group constraintxyz' ], 'id 1 2' )
149
+ self .assertTrue (control_dict ['fix constraintxyz' ], 'constraintxyz setforce 0.0 0.0 0.0' )
150
+ self .assertTrue (control_dict ['velocity constraintxyz' ], 'set 0.0 0.0 0.0' )
151
+ self .assertTrue (control_dict ['group constraintx' ], 'id 3 4' )
152
+ self .assertTrue (control_dict ['fix constraintx' ], 'constraintx setforce 0.0 NULL NULL' )
153
+ self .assertTrue (control_dict ['velocity constraintx' ], 'set 0.0 NULL NULL' )
154
+
155
+ def test_selective_dynamics_mixed (self ):
156
+ atoms = self .structure .copy ()
157
+ c1 = FixAtoms (indices = [atom .index for atom in atoms if atom .symbol == 'Cu' ])
158
+ c2 = FixedPlane (
159
+ [atom .index for atom in atoms if atom .symbol == 'Al' ],
160
+ [1 , 0 , 0 ],
161
+ )
162
+ atoms .set_constraint ([c1 , c2 ])
163
+ control_dict = set_selective_dynamics (structure = atoms , calc_md = False )
164
+ self .assertEqual (len (control_dict ), 4 )
165
+ self .assertTrue (control_dict ['group constraintxyz' ], 'id 1 2' )
166
+ self .assertTrue (control_dict ['fix constraintxyz' ], 'constraintxyz setforce 0.0 0.0 0.0' )
167
+ self .assertTrue (control_dict ['group constraintx' ], 'id 3 4' )
168
+ self .assertTrue (control_dict ['fix constraintx' ], 'constraintx setforce 0.0 NULL NULL' )
169
+
170
+ def test_selective_dynamics_single_fix (self ):
171
+ atoms = self .structure .copy ()
172
+ c1 = FixAtoms (indices = [atom .index for atom in atoms if atom .symbol == 'Cu' ])
173
+ atoms .set_constraint (c1 )
174
+ control_dict = set_selective_dynamics (structure = atoms , calc_md = False )
175
+ self .assertEqual (len (control_dict ), 2 )
176
+ self .assertTrue (control_dict ['group constraintxyz' ], 'id 1 2' )
177
+ self .assertTrue (control_dict ['fix constraintxyz' ], 'constraintxyz setforce 0.0 0.0 0.0' )
178
+
179
+ def test_selective_dynamics_errors (self ):
180
+ atoms = self .structure .copy ()
181
+ atoms .set_constraint (FixCom ())
182
+ with self .assertRaises (ValueError ):
183
+ set_selective_dynamics (structure = atoms , calc_md = False )
184
+
185
+ def test_selective_dynamics_wrong_plane (self ):
186
+ atoms = self .structure .copy ()
187
+ atoms .set_constraint (FixedPlane (
188
+ [atom .index for atom in atoms if atom .symbol == 'Al' ],
189
+ [2 , 1 , 0 ],
190
+ ))
191
+ with self .assertRaises (ValueError ):
192
+ set_selective_dynamics (structure = atoms , calc_md = False )
0 commit comments