Skip to content

Commit cbec920

Browse files
committed
Tests: Linear TS Job Adapter
1 parent 87b4175 commit cbec920

1 file changed

Lines changed: 250 additions & 0 deletions

File tree

arc/job/adapters/ts/linear_test.py

Lines changed: 250 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,250 @@
1+
#!/usr/bin/env python3
2+
# encoding: utf-8
3+
4+
"""
5+
This module contains unit tests of the arc.job.adapters.ts.heuristics module
6+
"""
7+
8+
import os
9+
import shutil
10+
import unittest
11+
12+
from arc.common import ARC_PATH, almost_equal_coords
13+
from arc.job.adapters.ts.linear import (LinearAdapter,
14+
average_zmat_params,
15+
get_rxn_weight,
16+
get_weight,
17+
interpolate_isomerization,
18+
)
19+
from arc.reaction import ARCReaction
20+
from arc.rmgdb import make_rmg_database_object, load_families_only
21+
from arc.species.converter import str_to_xyz
22+
from arc.species.species import ARCSpecies
23+
from arc.species.zmat import _compare_zmats
24+
25+
26+
class TestHeuristicsAdapter(unittest.TestCase):
27+
"""
28+
Contains unit tests for the HeuristicsAdapter class.
29+
"""
30+
31+
@classmethod
32+
def setUpClass(cls):
33+
"""
34+
A method that is run before all unit tests in this class.
35+
"""
36+
cls.maxDiff = None
37+
cls.rmgdb = make_rmg_database_object()
38+
load_families_only(cls.rmgdb)
39+
40+
cls.rxn_1 = ARCReaction(r_species=[ARCSpecies(label='CPD', smiles='C1C=CC=C1',
41+
xyz="""C -1.11689933 -0.16076292 -0.17157587
42+
C -0.34122713 1.12302797 -0.12498608
43+
C 0.95393962 0.86179733 0.10168911
44+
C 1.14045506 -0.56033684 0.22004768
45+
C -0.03946631 -1.17782376 0.06650470
46+
H -1.58827673 -0.30386166 -1.14815401
47+
H -1.87502410 -0.19463481 0.61612857
48+
H -0.77193310 2.10401684 -0.25572143
49+
H 1.74801386 1.58807889 0.18578522
50+
H 2.09208098 -1.03534789 0.40412258
51+
H -0.20166282 -2.24415315 0.10615953""")],
52+
p_species=[ARCSpecies(label='C5_carbene', adjlist="""1 C u0 p1 c0 {2,S} {6,S}
53+
2 C u0 p0 c0 {1,S} {3,D} {7,S}
54+
3 C u0 p0 c0 {2,D} {4,S} {8,S}
55+
4 C u0 p0 c0 {3,S} {5,D} {9,S}
56+
5 C u0 p0 c0 {4,D} {10,S} {11,S}
57+
6 H u0 p0 c0 {1,S}
58+
7 H u0 p0 c0 {2,S}
59+
8 H u0 p0 c0 {3,S}
60+
9 H u0 p0 c0 {4,S}
61+
10 H u0 p0 c0 {5,S}
62+
11 H u0 p0 c0 {5,S}""",
63+
xyz="""C 2.62023459 0.49362130 -0.23013873
64+
C 1.48006570 -0.33866786 -0.38699247
65+
C 1.53457595 -1.45115429 -1.13132450
66+
C 0.40179762 -2.32741928 -1.31937443
67+
C 0.45595744 -3.43865596 -2.06277224
68+
H 3.47507694 1.11901971 -0.11163109
69+
H 0.56454036 -0.04212124 0.11659958
70+
H 2.46516705 -1.72493574 -1.62516589
71+
H -0.53390611 -2.06386676 -0.83047533
72+
H -0.42088759 -4.06846526 -2.17670487
73+
H 1.36205133 -3.75009763 -2.57288841""")])
74+
cls.rxn_1.determine_family(rmg_database=cls.rmgdb)
75+
76+
def test_average_zmat_params(self):
77+
"""Test the average_zmat_params() function."""
78+
zmat_1 = {'symbols': ('H', 'H'),
79+
'coords': ((None, None, None),
80+
('R_1_0', None, None)),
81+
'vars': {'R_1_0': 0.7},
82+
'map': {0: 0, 1: 1}}
83+
zmat_2 = {'symbols': ('H', 'H'),
84+
'coords': ((None, None, None),
85+
('R_1_0', None, None)),
86+
'vars': {'R_1_0': 1.3},
87+
'map': {0: 0, 1: 1}}
88+
expected_zmat = {'symbols': ('H', 'H'),
89+
'coords': ((None, None, None),
90+
('R_1_0', None, None)),
91+
'vars': {'R_1_0': 1.0},
92+
'map': {0: 0, 1: 1}}
93+
zmat = average_zmat_params(zmat_1, zmat_2)
94+
self.assertTrue(_compare_zmats(zmat, expected_zmat))
95+
96+
expected_zmat = {'symbols': ('H', 'H'),
97+
'coords': ((None, None, None),
98+
('R_1_0', None, None)),
99+
'vars': {'R_1_0': 0.85},
100+
'map': {0: 0, 1: 1}}
101+
zmat = average_zmat_params(zmat_1, zmat_2, weight=0.25)
102+
self.assertTrue(_compare_zmats(zmat, expected_zmat))
103+
zmat = average_zmat_params(zmat_2, zmat_1, weight=0.75)
104+
self.assertTrue(_compare_zmats(zmat, expected_zmat))
105+
106+
zmat_1 = {'symbols': ('C', 'N', 'H', 'H', 'H', 'H', 'H'),
107+
'coords': ((None, None, None), ('R_1_0', None, None), ('R_2|4_0|0', 'A_2|4_0|0_1|1', None),
108+
('R_3|6_1|1', 'A_3|6_1|1_0|0', 'D_3_1_0_2'),
109+
('R_2|4_0|0', 'A_2|4_0|0_1|1', 'D_4_0_1_3'), ('R_5_0', 'A_5_0_1', 'D_5_0_1_4'),
110+
('R_3|6_1|1', 'A_3|6_1|1_0|0', 'D_6_1_0_5')),
111+
'vars': {'R_1_0': 1.451965854148702, 'D_3_1_0_2': 60.83821034525936,
112+
'D_4_0_1_3': 301.30263742432356, 'R_5_0': 1.0936965384360282,
113+
'A_5_0_1': 110.59878027260544, 'D_5_0_1_4': 239.76779188408136,
114+
'D_6_1_0_5': 65.17113681053117, 'R_2|4_0|0': 1.0935188594180785,
115+
'R_3|6_1|1': 1.019169330302324, 'A_2|4_0|0_1|1': 110.20495980110817,
116+
'A_3|6_1|1_0|0': 109.41187648524644},
117+
'map': {0: 0, 1: 1, 2: 2, 3: 5, 4: 3, 5: 4, 6: 6}}
118+
zmat_2 = {'symbols': ('C', 'N', 'H', 'H', 'H', 'H', 'H'),
119+
'coords': ((None, None, None), ('R_1_0', None, None), ('R_2|4_0|0', 'A_2|4_0|0_1|1', None),
120+
('R_3|6_1|1', 'A_3|6_1|1_0|0', 'D_3_1_0_2'),
121+
('R_2|4_0|0', 'A_2|4_0|0_1|1', 'D_4_0_1_3'), ('R_5_0', 'A_5_0_1', 'D_5_0_1_4'),
122+
('R_3|6_1|1', 'A_3|6_1|1_0|0', 'D_6_1_0_5')),
123+
'vars': {'R_1_0': 1.2, 'D_3_1_0_2': 50,
124+
'D_4_0_1_3': 250, 'R_5_0': 1.0936965384360282,
125+
'A_5_0_1': 110.59878027260544, 'D_5_0_1_4': 239.76779188408136,
126+
'D_6_1_0_5': 120, 'R_2|4_0|0': 1.0935188594180785,
127+
'R_3|6_1|1': 1.6, 'A_2|4_0|0_1|1': 110.20495980110817,
128+
'A_3|6_1|1_0|0': 109.41187648524644},
129+
'map': {0: 0, 1: 1, 2: 2, 3: 5, 4: 3, 5: 4, 6: 6}}
130+
expected_zmat = {'symbols': ('C', 'N', 'H', 'H', 'H', 'H', 'H'),
131+
'coords': ((None, None, None), ('R_1_0', None, None), ('R_2|4_0|0', 'A_2|4_0|0_1|1', None),
132+
('R_3|6_1|1', 'A_3|6_1|1_0|0', 'D_3_1_0_2'), ('R_2|4_0|0', 'A_2|4_0|0_1|1', 'D_4_0_1_3'),
133+
('R_5_0', 'A_5_0_1', 'D_5_0_1_4'), ('R_3|6_1|1', 'A_3|6_1|1_0|0', 'D_6_1_0_5')),
134+
'vars': {'R_1_0': 1.3259829270743508, 'D_3_1_0_2': 55.419105172629685,
135+
'D_4_0_1_3': 275.6513187121618, 'R_5_0': 1.0936965384360282,
136+
'A_5_0_1': 110.59878027260544, 'D_5_0_1_4': 239.76779188408136,
137+
'D_6_1_0_5': 92.58556840526558, 'R_2|4_0|0': 1.0935188594180785,
138+
'R_3|6_1|1': 1.309584665151162, 'A_2|4_0|0_1|1': 110.20495980110817,
139+
'A_3|6_1|1_0|0': 109.41187648524644},
140+
'map': {0: 0, 1: 1, 2: 2, 3: 5, 4: 3, 5: 4, 6: 6}}
141+
zmat = average_zmat_params(zmat_1, zmat_2)
142+
self.assertTrue(_compare_zmats(zmat, expected_zmat))
143+
144+
def test_get_weight(self):
145+
"""Test the get_weight() function."""
146+
self.assertEqual(get_weight([0], [0], 4), 0.5) # 4 / 8
147+
self.assertEqual(get_weight([0], [8], 12), 0.75) # 12 / 20
148+
self.assertEqual(get_weight([0], [2], 6), 0.6) # 6 / 10
149+
self.assertEqual(get_weight([10], [0], 30), 0.4) # 20 / 50
150+
self.assertEqual(get_weight([20], [10], 40), 0.4) # 20 / 50
151+
self.assertIsNone(get_weight([20], [None], 40), 0.4) # 20 / 50
152+
self.assertEqual(get_weight([8, 2], [0], 30), 0.4) # 20 / 50
153+
self.assertEqual(get_weight([4, 1], [5.5, 1.5], 11), 0.6) # 6 / 10
154+
155+
def test_get_rxn_weight(self):
156+
"""Test the get_rxn_weight() function."""
157+
rxn_1 = ARCReaction(r_species=[ARCSpecies(label='HO2', smiles='[O]O'),
158+
ARCSpecies(label='NH', smiles='[NH]')],
159+
p_species=[ARCSpecies(label='N', smiles='[N]'),
160+
ARCSpecies(label='H2O2', smiles='OO')])
161+
rxn_1.r_species[0].e0 = 252.0
162+
rxn_1.r_species[1].e0 = 100.5
163+
rxn_1.p_species[0].e0 = 116.0
164+
rxn_1.p_species[1].e0 = 200.3
165+
rxn_1.ts_species = ARCSpecies(label='TS', is_ts=True)
166+
rxn_1.ts_species.e0 = 391.6
167+
self.assertAlmostEquals(get_rxn_weight(rxn_1), 0.3417832)
168+
169+
def test_interpolate_isomerization(self):
170+
"""Test the interpolate_isomerization() function."""
171+
nc3h7_xyz = """C 0.00375165 -0.48895802 -1.20586379
172+
C 0.00375165 -0.48895802 0.28487510
173+
C 0.00375165 0.91997987 0.85403684
174+
H 0.41748586 -1.33492098 -1.74315104
175+
H -0.57506729 0.24145491 -1.76006154
176+
H -0.87717095 -1.03203740 0.64280162
177+
H 0.88948616 -1.02465371 0.64296621
178+
H 0.88512433 1.48038223 0.52412379
179+
H 0.01450405 0.88584135 1.94817394
180+
H -0.88837301 1.47376959 0.54233121"""
181+
ic3h7_xyz = """C -0.40735690 -0.74240205 -0.34312948
182+
C 0.38155377 -0.25604705 0.82450968
183+
C 0.54634593 1.25448345 0.81064511
184+
H 0.00637731 -1.58836501 -0.88041673
185+
H -0.98617584 -0.01198912 -0.89732723
186+
H -1.29710684 -1.29092340 0.08598983
187+
H 1.36955428 -0.72869684 0.81102246
188+
H 1.06044877 1.58846788 -0.09702437
189+
H 1.13774084 1.57830484 1.67308862
190+
H -0.42424546 1.75989927 0.85794283"""
191+
nc3h7 = ARCSpecies(label='nC3H7', smiles='[CH2]CC', xyz=nc3h7_xyz)
192+
ic3h7 = ARCSpecies(label='iC3H7', smiles='C[CH]C', xyz=ic3h7_xyz)
193+
rxn = ARCReaction(r_species=[nc3h7], p_species=[ic3h7])
194+
expected_ts_xyz = str_to_xyz("""C 0.01099731 -0.46789926 -1.15958911
195+
C 0.01099731 -0.46789926 0.33114978
196+
C 0.01099731 0.94103865 0.90031155
197+
H 0.57795661 -1.24174248 -1.65467180
198+
H -0.39690222 0.34527841 -1.69240298
199+
H -1.19440431 -1.28933062 -0.47327539
200+
H 0.89689057 -1.16420498 0.45967951
201+
H 0.76979130 1.33747945 0.33815513
202+
H -0.04544494 0.70455273 1.77835334
203+
H -1.00071642 1.24557408 0.38839197""")
204+
ts_xyz = interpolate_isomerization(rxn, use_weights=False)
205+
self.assertTrue(almost_equal_coords(ts_xyz, expected_ts_xyz))
206+
207+
nc3h7.e0 = 101.55
208+
ic3h7.e0 = 88.91
209+
ts = ARCSpecies(label='TS', is_ts=True, multiplicity=2, xyz=expected_ts_xyz)
210+
ts.e0 = 105
211+
rxn.ts_species = ts
212+
expected_ts_xyz = str_to_xyz("""C 0.01224420 -0.47400672 -1.18787451
213+
C 0.01224420 -0.47400672 0.30286438
214+
C 0.01224420 0.93493122 0.87202615
215+
H 0.47981756 -1.29923732 -1.70742021
216+
H -0.50470551 0.28201158 -1.73526026
217+
H -1.06475721 -1.18141451 0.26785378
218+
H 0.86736552 -1.12118386 0.54383845
219+
H 0.79813573 1.38347069 0.43772483
220+
H -0.03897336 0.76031233 1.86961141
221+
H -0.97425159 1.33180895 0.47825005""")
222+
ts_xyz = interpolate_isomerization(rxn, use_weights=True)
223+
self.assertTrue(almost_equal_coords(ts_xyz, expected_ts_xyz))
224+
225+
def test_linear_adapter(self):
226+
"""Test the LinearAdapter class."""
227+
self.assertEqual(self.rxn_1.family.label, 'Cyclopentadiene_scission')
228+
linear_1 = LinearAdapter(job_type='tsg',
229+
reactions=[self.rxn_1],
230+
testing=True,
231+
project='test',
232+
project_directory=os.path.join(ARC_PATH, 'arc', 'testing', 'test_linear', 'tst1'),
233+
)
234+
self.assertIsNone(self.rxn_1.ts_species)
235+
linear_1.execute()
236+
self.assertEqual(len(self.rxn_1.ts_species.ts_guesses), 1)
237+
self.assertEqual(self.rxn_1.ts_species.ts_guesses[0].initial_xyz['symbols'],
238+
('C', 'C', 'C', 'C', 'C', 'H', 'H', 'H', 'H', 'H', 'H'))
239+
240+
@classmethod
241+
def tearDownClass(cls):
242+
"""
243+
A function that is run ONCE after all unit tests in this class.
244+
Delete all project directories created during these unit tests.
245+
"""
246+
shutil.rmtree(os.path.join(ARC_PATH, 'arc', 'testing', 'test_linear'), ignore_errors=True)
247+
248+
249+
if __name__ == '__main__':
250+
unittest.main(testRunner=unittest.TextTestRunner(verbosity=2))

0 commit comments

Comments
 (0)