• Home
  • Features
  • Pricing
  • Docs
  • Announcements
  • Sign In

materialsproject / pymatgen / 4075885785

pending completion
4075885785

push

github

Shyue Ping Ong
Merge branch 'master' of github.com:materialsproject/pymatgen

96 of 96 new or added lines in 27 files covered. (100.0%)

81013 of 102710 relevant lines covered (78.88%)

0.79 hits per line

Source File
Press 'n' to go to next uncovered line, 'b' for previous

99.65
/pymatgen/io/qchem/tests/test_inputs.py
1
# Copyright (c) Pymatgen Development Team.
2
# Distributed under the terms of the MIT License.
3

4

5
from __future__ import annotations
1✔
6

7
import logging
1✔
8
import os
1✔
9
import unittest
1✔
10

11
import pytest
1✔
12
from monty.serialization import loadfn
1✔
13

14
from pymatgen.core.structure import Molecule
1✔
15
from pymatgen.io.qchem.inputs import QCInput
1✔
16
from pymatgen.util.testing import PymatgenTest
1✔
17

18
__author__ = "Brandon Wood, Samuel Blau, Shyam Dwaraknath, Julian Self, Evan Spotte-Smith, Ryan Kingsbury"
1✔
19
__copyright__ = "Copyright 2018-2022, The Materials Project"
1✔
20
__version__ = "0.1"
1✔
21
__maintainer__ = "Samuel Blau"
1✔
22
__email__ = "samblau1@gmail.com"
1✔
23
__credits__ = "Xiaohui Qu"
1✔
24

25
logger = logging.getLogger(__name__)
1✔
26

27

28
class TestQCInput(PymatgenTest):
1✔
29
    # ef setUpClass(cls):
30
    # add things that show up over and over again
31

32
    def test_molecule_template(self):
1✔
33
        species = ["C", "O"]
1✔
34
        coords = [
1✔
35
            [-9.5782000000, 0.6241500000, 0.0000000000],
36
            [-7.5827400000, 0.5127000000, -0.0000000000],
37
        ]
38
        mol = Molecule(species=species, coords=coords)
1✔
39
        molecule_test = QCInput.molecule_template(mol)
1✔
40
        molecule_actual = """$molecule
1✔
41
 0 1
42
 C     -9.5782000000      0.6241500000      0.0000000000
43
 O     -7.5827400000      0.5127000000     -0.0000000000
44
$end"""
45

46
        assert molecule_actual == molecule_test
1✔
47

48
    # TODO improve this test maybe add ordered dicts
49
    def test_rem_template(self):
1✔
50
        rem_params = {
1✔
51
            "job_type": "opt",
52
            "method": "wb97m-v",
53
            "basis": "def2-qzvppd",
54
            "max_scf_cycles": 300,
55
            "gen_scfman": "true",
56
        }
57
        rem_test = QCInput.rem_template(rem_params).split("\n")
1✔
58
        rem_actual_list = [
1✔
59
            "$rem",
60
            "   job_type = opt",
61
            "   method = wb97m-v",
62
            "   basis = def2-qzvppd",
63
            "   max_scf_cycles = 300",
64
            "   gen_scfman = true",
65
            "$end",
66
        ]
67

68
        for i_rem in rem_actual_list:
1✔
69
            assert i_rem in rem_test
1✔
70

71
    def test_opt_template(self):
1✔
72
        opt_params = {
1✔
73
            "CONSTRAINT": ["tors 2 3 4 5 25.0", "bend 2 1 4 110.0"],
74
            "FIXED": ["x y 2 4 5"],
75
            "DUMMY": ["M 2 3 4 5"],
76
            "CONNECT": ["4 3 2 3 5 6"],
77
        }
78
        opt_test = QCInput.opt_template(opt_params).split("\n")
1✔
79
        opt_actual_list = [
1✔
80
            "$opt",
81
            "CONSTRAINT",
82
            "   tors 2 3 4 5 25.0",
83
            "   bend 2 1 4 110.0",
84
            "ENDCONSTRAINT",
85
            "FIXED",
86
            "   x y 2 4 5",
87
            "ENDFIXED",
88
            "DUMMY",
89
            "   M 2 3 4 5",
90
            "ENDDUMMY",
91
            "CONNECT",
92
            "   4 3 2 3 5 6",
93
            "ENDCONNECT",
94
            "$end",
95
        ]
96

97
        for i_opt in opt_actual_list:
1✔
98
            assert i_opt in opt_test
1✔
99

100
    def test_pcm_template(self):
1✔
101
        pcm_params = {"theory": "cpcm"}
1✔
102
        pcm_test = QCInput.pcm_template(pcm_params)
1✔
103
        pcm_actual = """$pcm
1✔
104
   theory cpcm
105
$end"""
106
        assert pcm_actual == pcm_test
1✔
107

108
    def test_pcm_nonels_template(self):
1✔
109
        # make sure values that are None get skipped in the output
110
        pcm_nonels = {
1✔
111
            "A": "-0.006736",
112
            "B": "0.032698",
113
            "C": "-1249.6",
114
            "D": None,
115
            "Delta": "7.0",
116
            "Gamma": "3.7",
117
            "SolvRho": "0.05",
118
            "GauLag_N": "40",
119
        }
120
        pcm_nonels_test = QCInput.pcm_nonels_template(pcm_nonels)
1✔
121
        pcm_nonels_actual = """$pcm_nonels
1✔
122
   A -0.006736
123
   B 0.032698
124
   C -1249.6
125
   Delta 7.0
126
   Gamma 3.7
127
   SolvRho 0.05
128
   GauLag_N 40
129
$end"""
130
        assert pcm_nonels_actual == pcm_nonels_test
1✔
131

132
    def test_solvent_template(self):
1✔
133
        solvent_params = {"dielectric": "5.0"}
1✔
134
        solvent_test = QCInput.solvent_template(solvent_params)
1✔
135
        solvent_actual = """$solvent
1✔
136
   dielectric 5.0
137
$end"""
138
        assert solvent_actual == solvent_test
1✔
139

140
    def test_smx_template(self):
1✔
141
        smx_params = {"solvent": "water"}
1✔
142
        smx_test = QCInput.smx_template(smx_params)
1✔
143
        smx_actual = """$smx
1✔
144
   solvent water
145
$end"""
146
        assert smx_actual == smx_test
1✔
147

148
        smx_params = {"solvent": "dimethyl sulfoxide"}
1✔
149
        smx_test = QCInput.smx_template(smx_params)
1✔
150
        smx_actual = """$smx
1✔
151
   solvent dmso
152
$end"""
153
        assert smx_actual == smx_test
1✔
154

155
    def test_svp_template(self):
1✔
156
        svp_params = {
1✔
157
            "RHOISO": 0.001,
158
            "DIELST": 78.36,
159
            "NPTLEB": 1202,
160
            "ITRNGR": 2,
161
            "IROTGR": 2,
162
            "IPNRF": 1,
163
            "IDEFESR": 1,
164
        }
165
        # svp_params = lower_and_check_unique(svp_params)
166
        svp_test = QCInput.svp_template(svp_params)
1✔
167
        svp_actual = """$svp
1✔
168
RHOISO=0.001, DIELST=78.36, NPTLEB=1202, ITRNGR=2, IROTGR=2, IPNRF=1, IDEFESR=1
169
$end"""
170
        assert svp_actual == svp_test
1✔
171

172
    def test_scan_template(self):
1✔
173
        scan_params = {"stre": ["3 6 1.5 1.9 0.01"], "tors": ["1 2 3 4 -180 180 30"]}
1✔
174
        scan_test = QCInput.scan_template(scan_params)
1✔
175
        scan_actual = """$scan
1✔
176
   stre 3 6 1.5 1.9 0.01
177
   tors 1 2 3 4 -180 180 30
178
$end"""
179
        assert scan_test == scan_actual
1✔
180

181
        bad_scan = {"stre": ["1 2 1.0 2.0 0.05", "3 4 1.5 2.0 0.05"], "bend": ["7 8 9 90 120 10"]}
1✔
182
        with pytest.raises(ValueError):
1✔
183
            QCInput.scan_template(bad_scan)
1✔
184

185
    def test_van_der_waals_template(self):
1✔
186
        vdw_params = {1: 1.20, 12: 1.72}
1✔
187
        vdw_test_atomic = QCInput.van_der_waals_template(vdw_params, mode="atomic")
1✔
188
        vdw_actual_atomic = """$van_der_waals
1✔
189
1
190
   1 1.2
191
   12 1.72
192
$end"""
193
        assert vdw_test_atomic == vdw_actual_atomic
1✔
194

195
        vdw_test_sequential = QCInput.van_der_waals_template(vdw_params, mode="sequential")
1✔
196
        vdw_actual_sequential = """$van_der_waals
1✔
197
2
198
   1 1.2
199
   12 1.72
200
$end"""
201
        assert vdw_test_sequential == vdw_actual_sequential
1✔
202

203
        with pytest.raises(ValueError):  # bad vdw test
1✔
204
            QCInput.van_der_waals_template(vdw_params, mode="mymode")
1✔
205

206
    def test_find_sections(self):
1✔
207
        str_single_job_input = """$molecule
1✔
208
 0  1
209
 S          -0.00250959       -0.05817469       -0.02921636
210
 C           1.70755408       -0.03033788       -0.01382912
211
 H           2.24317221       -0.05215019        0.92026728
212
 C           2.21976393        0.01718014       -1.27293235
213
 H           3.27786220        0.04082146       -1.48539646
214
 C           1.20867399        0.04478540       -2.27007793
215
 H           1.40292257        0.10591684       -3.33110912
216
 C          -0.05341046        0.01577217       -1.74839343
217
 C          -1.32843436        0.03545064       -2.45531187
218
 C          -1.55195156        0.08743920       -3.80184635
219
 H          -0.75245172        0.10267657       -4.52817967
220
 C          -2.93293778        0.08408786       -4.13352169
221
 H          -3.31125108        0.11340328       -5.14405819
222
 C          -3.73173288        0.02741365       -3.03412864
223
 H          -4.80776535        0.00535688       -2.99564645
224
 S          -2.81590978       -0.00516172       -1.58990580
225
$end
226

227

228
$rem
229
             job_type = opt
230
               method = wb97m-v
231
                basis = def2-tzvppd
232
           gen_scfman = true
233
  geom_opt_max_cycles = 75
234
       max_scf_cycles = 300
235
        scf_algorithm = diis
236
            scf_guess = sad
237
           sym_ignore = true
238
             symmetry = false
239
               thresh = 14
240
$end
241

242

243
$opt
244
CONSTRAINT
245
tors 6 8 9 10 0.0
246
ENDCONSTRAINT
247
$end
248
"""
249
        sections_test = QCInput.find_sections(str_single_job_input)
1✔
250
        section_actual = ["molecule", "rem", "opt"]
1✔
251
        assert section_actual == sections_test
1✔
252

253
    def test_read_molecule(self):
1✔
254
        str_molecule = """$molecule
1✔
255
 0 1
256
 C     -9.5782000000      0.6241500000      0.0000000000
257
 O     -7.5827400000      0.5127000000     -0.0000000000
258
$end"""
259
        molecule_test = QCInput.read_molecule(str_molecule)
1✔
260
        species = ["C", "O"]
1✔
261
        coords = [
1✔
262
            [-9.5782000000, 0.6241500000, 0.0000000000],
263
            [-7.5827400000, 0.5127000000, -0.0000000000],
264
        ]
265
        molecule_actual = Molecule(species, coords)
1✔
266
        assert molecule_actual == molecule_test
1✔
267

268
    def test_read_rem(self):
1✔
269
        str_rem = """Trying to break you!
1✔
270

271
$rem
272
   job_type  opt
273
  method  wb97m-v
274
   basis  def2-qzvppd
275
   max_scf_cycles  300
276
  gen_scfman = true
277
$end"""
278
        rem_test = QCInput.read_rem(str_rem)
1✔
279
        rem_actual = {
1✔
280
            "job_type": "opt",
281
            "method": "wb97m-v",
282
            "basis": "def2-qzvppd",
283
            "max_scf_cycles": "300",
284
            "gen_scfman": "true",
285
        }
286
        assert rem_actual == rem_test
1✔
287

288
    def test_read_only_rem(self):
1✔
289
        str_rem = """Trying to break you!
1✔
290

291
$rem
292
   job_type  opt
293
  method  wb97m-v
294
   basis  def2-qzvppd
295
   max_scf_cycles  300
296
  gen_scfman = true
297
$end
298

299
$pcm
300
heavypoints   194
301
hpoints   194
302
radii   uff
303
theory   cpcm
304
vdwscale   1.1
305
$end
306

307

308
$solvent
309
dielectric   10.0
310
$end
311

312

313
"""
314
        rem_test = QCInput.read_rem(str_rem)
1✔
315
        rem_actual = {
1✔
316
            "job_type": "opt",
317
            "method": "wb97m-v",
318
            "basis": "def2-qzvppd",
319
            "max_scf_cycles": "300",
320
            "gen_scfman": "true",
321
        }
322
        assert rem_actual == rem_test
1✔
323

324
    def test_read_opt(self):
1✔
325
        str_opt = """$opt
1✔
326
CONSTRAINT
327
  tors 2 3 4 5 25.0
328
   bend 2 1 4 110.0
329
ENDCONSTRAINT
330

331
FIXED
332
x y 2 4 5
333
ENDFIXED
334

335
DUMMY
336
   M 2 3 4 5
337
ENDDUMMY
338

339
CONNECT
340
4 3 2 3 5 6
341
ENDCONNECT
342
$end"""
343
        opt_test = QCInput.read_opt(str_opt)
1✔
344
        opt_actual = {
1✔
345
            "CONSTRAINT": ["tors 2 3 4 5 25.0", "bend 2 1 4 110.0"],
346
            "FIXED": ["x y 2 4 5"],
347
            "DUMMY": ["M 2 3 4 5"],
348
            "CONNECT": ["4 3 2 3 5 6"],
349
        }
350
        assert opt_actual == opt_test
1✔
351

352
    def test__str__(self):
1✔
353
        species = ["C", "O"]
1✔
354
        coords = [
1✔
355
            [-9.5782000000, 0.6241500000, 0.0000000000],
356
            [-7.5827400000, 0.5127000000, -0.0000000000],
357
        ]
358
        molecule = Molecule(species=species, coords=coords)
1✔
359
        rem = {
1✔
360
            "jobtype": "opt",
361
            "method": "wb97m-v",
362
            "basis": "def2-qzvppd",
363
            "max_scf_cycles": "300",
364
            "gen_scfman": "true",
365
        }
366
        str_test = str(QCInput(molecule=molecule, rem=rem)).split("\n")
1✔
367
        str_actual_list = [
1✔
368
            "$molecule",
369
            " 0 1",
370
            " C     -9.5782000000      0.6241500000      0.0000000000",
371
            " O     -7.5827400000      0.5127000000     -0.0000000000",
372
            "$end",
373
            "$rem",
374
            "   job_type = opt",
375
            "   method = wb97m-v",
376
            "   basis = def2-qzvppd",
377
            "   max_scf_cycles = 300",
378
            "   gen_scfman = true",
379
            "$end",
380
        ]
381

382
        for i_str in str_actual_list:
1✔
383
            assert i_str in str_test
1✔
384

385
    def test_from_string(self):
1✔
386
        string = """$molecule
1✔
387
 0  1
388
 S          -0.00250959       -0.05817469       -0.02921636
389
 C           1.70755408       -0.03033788       -0.01382912
390
 H           2.24317221       -0.05215019        0.92026728
391
 C           2.21976393        0.01718014       -1.27293235
392
 H           3.27786220        0.04082146       -1.48539646
393
 C           1.20867399        0.04478540       -2.27007793
394
 H           1.40292257        0.10591684       -3.33110912
395
 C          -0.05341046        0.01577217       -1.74839343
396
 C          -1.32843436        0.03545064       -2.45531187
397
 C          -1.55195156        0.08743920       -3.80184635
398
 H          -0.75245172        0.10267657       -4.52817967
399
 C          -2.93293778        0.08408786       -4.13352169
400
 H          -3.31125108        0.11340328       -5.14405819
401
 C          -3.73173288        0.02741365       -3.03412864
402
 H          -4.80776535        0.00535688       -2.99564645
403
 S          -2.81590978       -0.00516172       -1.58990580
404
$end
405

406

407
$rem
408
              jobtype = opt
409
               method = wb97m-v
410
                basis = def2-tzvppd
411
           gen_scfman = true
412
  geom_opt_max_cycles = 75
413
       max_scf_cycles = 300
414
        scf_algorithm = diis
415
            scf_guess = sad
416
           sym_ignore = true
417
             symmetry = false
418
               thresh = 14
419
$end
420

421

422
$opt
423
CONSTRAINT
424
tors 6 8 9 10 0.0
425
ENDCONSTRAINT
426
$end
427
"""
428
        qcinput_test = QCInput.from_string(string)
1✔
429
        species = [
1✔
430
            "S",
431
            "C",
432
            "H",
433
            "C",
434
            "H",
435
            "C",
436
            "H",
437
            "C",
438
            "C",
439
            "C",
440
            "H",
441
            "C",
442
            "H",
443
            "C",
444
            "H",
445
            "S",
446
        ]
447
        coords = [
1✔
448
            [-0.00250959, -0.05817469, -0.02921636],
449
            [1.70755408, -0.03033788, -0.01382912],
450
            [2.24317221, -0.05215019, 0.92026728],
451
            [2.21976393, 0.01718014, -1.27293235],
452
            [3.27786220, 0.04082146, -1.48539646],
453
            [1.20867399, 0.04478540, -2.27007793],
454
            [1.40292257, 0.10591684, -3.33110912],
455
            [-0.05341046, 0.01577217, -1.74839343],
456
            [-1.32843436, 0.03545064, -2.45531187],
457
            [-1.55195156, 0.08743920, -3.80184635],
458
            [-0.75245172, 0.10267657, -4.52817967],
459
            [-2.93293778, 0.08408786, -4.13352169],
460
            [-3.31125108, 0.11340328, -5.14405819],
461
            [-3.73173288, 0.02741365, -3.03412864],
462
            [-4.80776535, 0.00535688, -2.99564645],
463
            [-2.81590978, -0.00516172, -1.58990580],
464
        ]
465
        molecule_actual = Molecule(species, coords)
1✔
466
        assert molecule_actual == qcinput_test.molecule
1✔
467
        rem_actual = {
1✔
468
            "job_type": "opt",
469
            "method": "wb97m-v",
470
            "basis": "def2-tzvppd",
471
            "gen_scfman": "true",
472
            "geom_opt_max_cycles": "75",
473
            "max_scf_cycles": "300",
474
            "scf_algorithm": "diis",
475
            "scf_guess": "sad",
476
            "sym_ignore": "true",
477
            "symmetry": "false",
478
            "thresh": "14",
479
        }
480
        assert rem_actual == qcinput_test.rem
1✔
481
        opt_actual = {"CONSTRAINT": ["tors 6 8 9 10 0.0"]}
1✔
482
        assert opt_actual == qcinput_test.opt
1✔
483

484
    # TODO this test needs an update, the assertion doesn't differentiate between the different rem sections
485
    def test_multi_job_string(self):
1✔
486
        species = [
1✔
487
            "S",
488
            "C",
489
            "H",
490
            "C",
491
            "H",
492
            "C",
493
            "H",
494
            "C",
495
            "C",
496
            "C",
497
            "H",
498
            "C",
499
            "H",
500
            "C",
501
            "H",
502
            "S",
503
        ]
504
        coords = [
1✔
505
            [-0.00250959, -0.05817469, -0.02921636],
506
            [1.70755408, -0.03033788, -0.01382912],
507
            [2.24317221, -0.05215019, 0.92026728],
508
            [2.21976393, 0.01718014, -1.27293235],
509
            [3.27786220, 0.04082146, -1.48539646],
510
            [1.20867399, 0.04478540, -2.27007793],
511
            [1.40292257, 0.10591684, -3.33110912],
512
            [-0.05341046, 0.01577217, -1.74839343],
513
            [-1.32843436, 0.03545064, -2.45531187],
514
            [-1.55195156, 0.08743920, -3.80184635],
515
            [-0.75245172, 0.10267657, -4.52817967],
516
            [-2.93293778, 0.08408786, -4.13352169],
517
            [-3.31125108, 0.11340328, -5.14405819],
518
            [-3.73173288, 0.02741365, -3.03412864],
519
            [-4.80776535, 0.00535688, -2.99564645],
520
            [-2.81590978, -0.00516172, -1.58990580],
521
        ]
522
        molecule_1 = Molecule(species, coords)
1✔
523
        rem_1 = {
1✔
524
            "jobtype": "opt",
525
            "method": "wb97m-v",
526
            "basis": "def2-tzvppd",
527
            "gen_scfman": "true",
528
            "geom_opt_max_cycles": "75",
529
            "max_scf_cycles": "300",
530
            "scf_algorithm": "diis",
531
            "scf_guess": "sad",
532
            "sym_ignore": "true",
533
            "symmetry": "false",
534
            "thresh": "14",
535
        }
536
        opt_1 = {"CONSTRAINT": ["tors 6 8 9 10 0.0"]}
1✔
537
        job_1 = QCInput(molecule=molecule_1, rem=rem_1, opt=opt_1)
1✔
538
        molecule_2 = "read"
1✔
539
        rem_2 = {
1✔
540
            "jobtype": "sp",
541
            "method": "wb97m-v",
542
            "basis": "def2-tzvppd",
543
            "gen_scfman": "true",
544
            "geom_opt_max_cycles": "75",
545
            "max_scf_cycles": "300",
546
            "scf_algorithm": "diis",
547
            "scf_guess": "read",
548
            "sym_ignore": "true",
549
            "symmetry": "false",
550
            "thresh": "14",
551
        }
552
        job_2 = QCInput(molecule=molecule_2, rem=rem_2)
1✔
553
        job_list = [job_1, job_2]
1✔
554
        multi_job_str_test = QCInput.multi_job_string(job_list=job_list).split("\n")
1✔
555
        multi_job_str_actual_list = [
1✔
556
            "$molecule",
557
            " 0 1",
558
            " S     -0.0025095900     -0.0581746900     -0.0292163600",
559
            " C      1.7075540800     -0.0303378800     -0.0138291200",
560
            " H      2.2431722100     -0.0521501900      0.9202672800",
561
            " C      2.2197639300      0.0171801400     -1.2729323500",
562
            " H      3.2778622000      0.0408214600     -1.4853964600",
563
            " C      1.2086739900      0.0447854000     -2.2700779300",
564
            " H      1.4029225700      0.1059168400     -3.3311091200",
565
            " C     -0.0534104600      0.0157721700     -1.7483934300",
566
            " C     -1.3284343600      0.0354506400     -2.4553118700",
567
            " C     -1.5519515600      0.0874392000     -3.8018463500",
568
            " H     -0.7524517200      0.1026765700     -4.5281796700",
569
            " C     -2.9329377800      0.0840878600     -4.1335216900",
570
            " H     -3.3112510800      0.1134032800     -5.1440581900",
571
            " C     -3.7317328800      0.0274136500     -3.0341286400",
572
            " H     -4.8077653500      0.0053568800     -2.9956464500",
573
            " S     -2.8159097800     -0.0051617200     -1.5899058000",
574
            "$end",
575
            "$rem",
576
            "   job_type = opt",
577
            "   method = wb97m-v",
578
            "   basis = def2-tzvppd",
579
            "   gen_scfman = true",
580
            "   geom_opt_max_cycles = 75",
581
            "   max_scf_cycles = 300",
582
            "   scf_algorithm = diis",
583
            "   scf_guess = sad",
584
            "   sym_ignore = true",
585
            "   symmetry = false",
586
            "   thresh = 14",
587
            "$end",
588
            "$opt",
589
            "CONSTRAINT",
590
            "   tors 6 8 9 10 0.0",
591
            "ENDCONSTRAINT",
592
            "$end",
593
            "@@@",
594
            "$molecule",
595
            " read",
596
            "$end",
597
            "$rem",
598
            "   job_type = opt",
599
            "   method = wb97m-v",
600
            "   basis = def2-tzvppd",
601
            "   gen_scfman = true",
602
            "   geom_opt_max_cycles = 75",
603
            "   max_scf_cycles = 300",
604
            "   scf_algorithm = diis",
605
            "   scf_guess = sad",
606
            "   sym_ignore = true",
607
            "   symmetry = false",
608
            "   thresh = 14",
609
            "$end",
610
        ]
611

612
        for i_str in multi_job_str_actual_list:
1✔
613
            assert i_str in multi_job_str_test
1✔
614

615
    def test_from_multi_jobs_file(self):
1✔
616
        job_list_test = QCInput.from_multi_jobs_file(
1✔
617
            os.path.join(PymatgenTest.TEST_FILES_DIR, "qchem", "pt_n2_wb97mv_0.0.in")
618
        )
619
        species = [
1✔
620
            "S",
621
            "C",
622
            "H",
623
            "C",
624
            "H",
625
            "C",
626
            "H",
627
            "C",
628
            "C",
629
            "C",
630
            "H",
631
            "C",
632
            "H",
633
            "C",
634
            "H",
635
            "S",
636
        ]
637
        coords = [
1✔
638
            [-0.00250959, -0.05817469, -0.02921636],
639
            [1.70755408, -0.03033788, -0.01382912],
640
            [2.24317221, -0.05215019, 0.92026728],
641
            [2.21976393, 0.01718014, -1.27293235],
642
            [3.27786220, 0.04082146, -1.48539646],
643
            [1.20867399, 0.04478540, -2.27007793],
644
            [1.40292257, 0.10591684, -3.33110912],
645
            [-0.05341046, 0.01577217, -1.74839343],
646
            [-1.32843436, 0.03545064, -2.45531187],
647
            [-1.55195156, 0.08743920, -3.80184635],
648
            [-0.75245172, 0.10267657, -4.52817967],
649
            [-2.93293778, 0.08408786, -4.13352169],
650
            [-3.31125108, 0.11340328, -5.14405819],
651
            [-3.73173288, 0.02741365, -3.03412864],
652
            [-4.80776535, 0.00535688, -2.99564645],
653
            [-2.81590978, -0.00516172, -1.58990580],
654
        ]
655
        molecule_1_actual = Molecule(species, coords)
1✔
656
        rem_1_actual = {
1✔
657
            "job_type": "opt",
658
            "method": "wb97m-v",
659
            "basis": "def2-tzvppd",
660
            "gen_scfman": "true",
661
            "geom_opt_max_cycles": "75",
662
            "max_scf_cycles": "300",
663
            "scf_algorithm": "diis",
664
            "scf_guess": "sad",
665
            "sym_ignore": "true",
666
            "symmetry": "false",
667
            "thresh": "14",
668
        }
669
        opt_1_actual = {"CONSTRAINT": ["tors 6 8 9 10 0.0"]}
1✔
670
        assert molecule_1_actual == job_list_test[0].molecule
1✔
671
        assert rem_1_actual == job_list_test[0].rem
1✔
672
        assert opt_1_actual == job_list_test[0].opt
1✔
673

674
        molecule_2_actual = "read"
1✔
675
        rem_2_actual = {
1✔
676
            "job_type": "sp",
677
            "method": "wb97m-v",
678
            "basis": "def2-tzvppd",
679
            "gen_scfman": "true",
680
            "geom_opt_max_cycles": "75",
681
            "max_scf_cycles": "300",
682
            "scf_algorithm": "diis",
683
            "scf_guess": "read",
684
            "sym_ignore": "true",
685
            "symmetry": "false",
686
            "thresh": "14",
687
        }
688
        assert molecule_2_actual == job_list_test[1].molecule
1✔
689
        assert rem_2_actual == job_list_test[1].rem
1✔
690

691
    def test_read_pcm(self):
1✔
692
        str_pcm = """I'm once again trying to break you!
1✔
693

694
$pcm
695
   theory cpcm
696
   radii uff
697
   vdwscale 1.1
698
$end"""
699
        pcm_test = QCInput.read_pcm(str_pcm)
1✔
700
        pcm_actual = {"theory": "cpcm", "radii": "uff", "vdwscale": "1.1"}
1✔
701
        assert pcm_actual == pcm_test
1✔
702

703
    def test_read_pcm_nonels(self):
1✔
704
        str_pcm_nonels = """$pcm_nonels
1✔
705
   A         -0.006736
706
   B          0.032698
707
   C      -1249.6
708
   D        -21.405
709
   Delta    7.0
710
   Gamma    3.7
711
   SolvRho  0.05
712
   GauLag_N 40
713
$end"""
714
        pcm_nonels_test = QCInput.read_pcm_nonels(str_pcm_nonels)
1✔
715
        pcm_nonels_actual = {
1✔
716
            "A": "-0.006736",
717
            "B": "0.032698",
718
            "C": "-1249.6",
719
            "D": "-21.405",
720
            "Delta": "7.0",
721
            "Gamma": "3.7",
722
            "SolvRho": "0.05",
723
            "GauLag_N": "40",
724
        }
725
        assert pcm_nonels_actual == pcm_nonels_test
1✔
726

727
    def test_read_bad_pcm(self):
1✔
728
        str_pcm = """I'm once again trying to break you!
1✔
729

730
$pcm
731
   theory = cpcm
732
   radii = uff
733
   vdwscale = 1.1
734
$end"""
735
        pcm_test = QCInput.read_pcm(str_pcm)
1✔
736
        pcm_actual = {}
1✔
737
        assert pcm_actual == pcm_test
1✔
738

739
    def test_read_solvent(self):
1✔
740
        str_solvent = """Once again, I'm trying to break you!
1✔
741

742
$solvent
743
   dielectric 5.0
744
$end"""
745
        solvent_test = QCInput.read_solvent(str_solvent)
1✔
746
        solvent_actual = {
1✔
747
            "dielectric": "5.0",
748
        }
749
        assert solvent_actual == solvent_test
1✔
750

751
    def test_read_bad_solvent(self):
1✔
752
        str_solvent = """Once again, I'm trying to break you!
1✔
753

754
$solvent
755
   dielectric = 5.0
756
$end"""
757
        solvent_test = QCInput.read_solvent(str_solvent)
1✔
758
        solvent_actual = {}
1✔
759
        assert solvent_actual == solvent_test
1✔
760

761
    def test_read_smx(self):
1✔
762
        str_smx = """Once again, I'm trying to break you!
1✔
763

764
$smx
765
   solvent water
766
$end"""
767
        smx_test = QCInput.read_smx(str_smx)
1✔
768
        smx_actual = {
1✔
769
            "solvent": "water",
770
        }
771
        assert smx_actual == smx_test
1✔
772

773
    def test_read_svp(self):
1✔
774
        str_svp = """$svp
1✔
775
RHOISO=0.001, DIELST=78.36, NPTLEB=1202, ITRNGR=2, IROTGR=2, IPNRF=1, IDEFESR=1
776
$end"""
777
        svp_test = QCInput.read_svp(str_svp)
1✔
778
        svp_actual = {
1✔
779
            "RHOISO": "0.001",
780
            "DIELST": "78.36",
781
            "NPTLEB": "1202",
782
            "ITRNGR": "2",
783
            "IROTGR": "2",
784
            "IPNRF": "1",
785
            "IDEFESR": "1",
786
        }
787
        assert svp_actual == svp_test
1✔
788

789
    def test_read_bad_smx(self):
1✔
790
        str_smx = """Once again, I'm trying to break you!
1✔
791

792
$solvent
793
   solvent = water
794
$end"""
795
        smx_test = QCInput.read_smx(str_smx)
1✔
796
        smx_actual = {}
1✔
797
        assert smx_actual == smx_test
1✔
798

799
    def test_read_scan(self):
1✔
800
        str_scan = """Once more, I'm trying to break you!
1✔
801

802
$scan
803
   stre 1 2 1.1 1.4 0.03
804
   bend 3 4 5 60 90 5
805
$end"""
806
        scan_test = QCInput.read_scan(str_scan)
1✔
807
        scan_actual = {"stre": ["1 2 1.1 1.4 0.03"], "bend": ["3 4 5 60 90 5"], "tors": []}
1✔
808

809
        assert scan_test == scan_actual
1✔
810

811
    def test_read_bad_scan(self):
1✔
812
        str_scan_1 = """Once more, I"m trying to break you!
1✔
813
$scan
814
   boo 1 4 1.2 1.5 0.02
815
   tors = 3 6 1.5 1.9 0.01
816
$end
817
"""
818
        scan_test_1 = QCInput.read_scan(str_scan_1)
1✔
819
        scan_actual_1 = {}
1✔
820
        assert scan_test_1 == scan_actual_1
1✔
821

822
        str_scan_2 = """Once more, I'm trying to break you!
1✔
823

824
$scan
825
   stre 1 2 1.1 1.4 0.03
826
   bend 3 4 5 60 90 5
827
   tors 6 7 8 9 -180 180 30
828
$end"""
829

830
        with pytest.raises(ValueError):
1✔
831
            QCInput.read_scan(str_scan_2)
1✔
832

833
    def test_read_negative(self):
1✔
834
        str_molecule = """$molecule
1✔
835
 -1 1
836
 S     -1.1516880000      0.8568110000     -0.0787470000
837
 S      1.1527500000     -0.8580450000     -0.0786430000
838
 O     -1.6523520000      1.8607750000     -1.0252100000
839
 O     -0.9052880000      1.2448490000      1.3156410000
840
 O      0.9072410000     -1.2461780000      1.3158760000
841
 O      1.6543670000     -1.8616640000     -1.0249090000
842
 C     -2.5841130000     -0.3746500000      0.0297340000
843
 C      2.5833220000      0.3755850000      0.0296900000
844
 F     -3.6480730000      0.2204040000      0.6112110000
845
 F     -2.2609850000     -1.4531020000      0.7616580000
846
 F     -2.9656640000     -0.7966010000     -1.1900330000
847
 F      3.6467050000     -0.2152590000      0.6163310000
848
 F      2.2560700000      1.4560310000      0.7568190000
849
 F      2.9672080000      0.7933560000     -1.1908790000
850
 N     -0.0001900000     -0.0016540000     -0.8250640000
851
$end
852

853
$rem
854
   job_type = opt
855
   basis = 6-311++g*
856
   max_scf_cycles = 200
857
   gen_scfman = true
858
   scf_algorithm = diis
859
   method = wb97xd
860
   geom_opt_max_cycles = 200
861
$end
862
"""
863
        qcinp = QCInput.from_string(str_molecule)
1✔
864
        assert str_molecule == str(qcinp)
1✔
865

866
    def test_read_plots(self):
1✔
867
        str_molecule = """$molecule
1✔
868
 0 2
869
 O      1.6159947668      0.3522275191      0.3343192028
870
 O     -0.5921658045      1.4368355787      1.2632324885
871
 C      0.4160355545     -0.4617433561      0.2180766834
872
 C     -0.7655230468      0.4776728409      0.1826587618
873
 C      2.8437090411     -0.3853724291      0.0935770045
874
 C     -1.7918488579      2.2003569978      1.5593659974
875
 H      0.4649228147     -1.0347597878     -0.7097270414
876
 H      3.6714833661      0.3051154983      0.2509025369
877
 H      2.8395611019     -0.7401009356     -0.9372741555
878
 H     -2.1017802975      2.7482577804      0.6678359687
879
 H     -1.5445030956      2.8894960726      2.3658396091
880
 Mg      1.2856817013      1.9249743897      1.4285694502
881
$end
882

883
$rem
884
   job_type = sp
885
   basis = def2-tzvppd
886
   max_scf_cycles = 200
887
   gen_scfman = true
888
   xc_grid = 3
889
   scf_algorithm = gdm
890
   resp_charges = true
891
   symmetry = false
892
   sym_ignore = true
893
   method = wb97xv
894
   solvent_method = smd
895
   ideriv = 1
896
   thresh = 14
897
   scf_guess_always = true
898
   plots = true
899
   make_cube_files = true
900
$end
901

902
$smx
903
   solvent thf
904
$end
905

906
$plots
907
   grid_spacing 0.05
908
   total_density 0
909
$end
910
"""
911
        qcinp = QCInput.from_string(str_molecule)
1✔
912
        assert str_molecule == str(qcinp)
1✔
913

914
    def test_read_nbo(self):
1✔
915
        str_molecule = """$molecule
1✔
916
 0 2
917
 C     -2.0338520000      0.0865500000     -1.4158570000
918
 C     -1.2819580000      0.3850830000     -0.1564990000
919
 C     -2.0067300000      1.1271820000      0.9225950000
920
 C      0.1219120000     -0.0366190000      0.0148810000
921
 C      0.6767790000     -1.0507090000     -0.7802400000
922
 C      2.0072450000     -1.4517610000     -0.6185380000
923
 C      2.8079970000     -0.8434840000      0.3427930000
924
 C      2.2778880000      0.1645690000      1.1416530000
925
 C      0.9468200000      0.5630060000      0.9784410000
926
 H     -1.3919850000      0.1591240000     -2.2995570000
927
 H     -2.4671570000     -0.9174600000     -1.3722490000
928
 H     -2.8505080000      0.8017250000     -1.5613060000
929
 H     -3.0889210000      0.9823990000      0.8362370000
930
 H     -1.7216740000      0.7761670000      1.9194500000
931
 H     -1.8021560000      2.1999010000      0.8510710000
932
 H      0.0793240000     -1.5592640000     -1.5324310000
933
 H      2.4136820000     -2.2421190000     -1.2440900000
934
 H      3.8415290000     -1.1539430000      0.4689660000
935
 H      2.8984450000      0.6464300000      1.8925800000
936
 H      0.5733200000      1.3632210000      1.6120990000
937
$end
938

939
$rem
940
   job_type = sp
941
   max_scf_cycles = 200
942
   gen_scfman = true
943
   xc_grid = 3
944
   scf_algorithm = diis
945
   method = wb97xv
946
   basis = def2-tzvp
947
   symmetry = false
948
   sym_ignore = true
949
   nbo = true
950
$end
951

952
$nbo
953
$end
954
"""
955
        qcinp = QCInput.from_string(str_molecule)
1✔
956
        assert str_molecule == str(qcinp)
1✔
957

958
        str_molecule = """$molecule
1✔
959
 0 2
960
 C     -2.0338520000      0.0865500000     -1.4158570000
961
 C     -1.2819580000      0.3850830000     -0.1564990000
962
 C     -2.0067300000      1.1271820000      0.9225950000
963
 C      0.1219120000     -0.0366190000      0.0148810000
964
 C      0.6767790000     -1.0507090000     -0.7802400000
965
 C      2.0072450000     -1.4517610000     -0.6185380000
966
 C      2.8079970000     -0.8434840000      0.3427930000
967
 C      2.2778880000      0.1645690000      1.1416530000
968
 C      0.9468200000      0.5630060000      0.9784410000
969
 H     -1.3919850000      0.1591240000     -2.2995570000
970
 H     -2.4671570000     -0.9174600000     -1.3722490000
971
 H     -2.8505080000      0.8017250000     -1.5613060000
972
 H     -3.0889210000      0.9823990000      0.8362370000
973
 H     -1.7216740000      0.7761670000      1.9194500000
974
 H     -1.8021560000      2.1999010000      0.8510710000
975
 H      0.0793240000     -1.5592640000     -1.5324310000
976
 H      2.4136820000     -2.2421190000     -1.2440900000
977
 H      3.8415290000     -1.1539430000      0.4689660000
978
 H      2.8984450000      0.6464300000      1.8925800000
979
 H      0.5733200000      1.3632210000      1.6120990000
980
$end
981

982
$rem
983
   job_type = sp
984
   max_scf_cycles = 200
985
   gen_scfman = true
986
   xc_grid = 3
987
   scf_algorithm = diis
988
   method = wb97xv
989
   basis = def2-tzvp
990
   symmetry = false
991
   sym_ignore = true
992
   nbo = true
993
$end
994

995
$nbo
996
   print = 1
997
$end
998
"""
999
        qcinp = QCInput.from_string(str_molecule)
1✔
1000
        assert str_molecule == str(qcinp)
1✔
1001

1002
    def test_write_file_from_OptSet(self):
1✔
1003
        from pymatgen.io.qchem.sets import OptSet
1✔
1004

1005
        odd_dict = loadfn(os.path.join(os.path.dirname(__file__), "odd.json"))
1✔
1006
        odd_mol = odd_dict["spec"]["_tasks"][0]["molecule"]
1✔
1007
        qcinp = OptSet(odd_mol)
1✔
1008
        qcinp.write_file(os.path.join(os.path.dirname(__file__), "test.qin"))
1✔
1009
        test_file = open(os.path.join(os.path.dirname(__file__), "test.qin"))
1✔
1010
        ref_file = open(os.path.join(os.path.dirname(__file__), "test_ref.qin"))
1✔
1011

1012
        for l_test, l_ref in zip(test_file, ref_file):
1✔
1013
            # By default, if this statement fails the offending line will be printed
1014
            assert l_test == l_ref
1✔
1015

1016
        test_file.close()
1✔
1017
        ref_file.close()
1✔
1018
        os.remove(os.path.join(os.path.dirname(__file__), "test.qin"))
1✔
1019

1020
    def test_write_file_from_OptSet_with_vdw(self):
1✔
1021
        from pymatgen.io.qchem.sets import OptSet
1✔
1022

1023
        odd_dict = loadfn(os.path.join(os.path.dirname(__file__), "odd.json"))
1✔
1024
        odd_mol = odd_dict["spec"]["_tasks"][0]["molecule"]
1✔
1025
        qcinp = OptSet(odd_mol, overwrite_inputs={"van_der_waals": {"16": 3.14159}})
1✔
1026
        qcinp.write_file(os.path.join(os.path.dirname(__file__), "test_vdw.qin"))
1✔
1027
        test_file = open(os.path.join(os.path.dirname(__file__), "test_vdw.qin"))
1✔
1028
        ref_file = open(os.path.join(os.path.dirname(__file__), "test_ref_vdw.qin"))
1✔
1029

1030
        for l_test, l_ref in zip(test_file, ref_file):
1✔
1031
            # By default, if this statement fails the offending line will be printed
1032
            assert l_test == l_ref
1✔
1033

1034
        test_file.close()
1✔
1035
        ref_file.close()
1✔
1036
        os.remove(os.path.join(os.path.dirname(__file__), "test_vdw.qin"))
1✔
1037

1038
    def test_read_write_nbo7(self):
1✔
1039
        qcinp = QCInput.from_file(os.path.join(PymatgenTest.TEST_FILES_DIR, "molecules", "new_qchem_files", "nbo7.qin"))
1✔
1040
        qcinp.write_file(os.path.join(os.path.dirname(__file__), "test_nbo7.qin"))
1✔
1041
        test_file = open(os.path.join(PymatgenTest.TEST_FILES_DIR, "molecules", "new_qchem_files", "nbo7.qin"))
1✔
1042
        ref_file = open(os.path.join(os.path.dirname(__file__), "test_nbo7.qin"))
1✔
1043

1044
        for l_test, l_ref in zip(test_file, ref_file):
1✔
1045
            # By default, if this statement fails the offending line will be printed
1046
            assert l_test == l_ref
1✔
1047

1048
        test_file.close()
1✔
1049
        ref_file.close()
1✔
1050
        os.remove(os.path.join(os.path.dirname(__file__), "test_nbo7.qin"))
1✔
1051

1052
    def test_read_write_nbo_e2pert(self):
1✔
1053
        qcinp = QCInput.from_file(
1✔
1054
            os.path.join(PymatgenTest.TEST_FILES_DIR, "molecules", "new_qchem_files", "e2pert.qin")
1055
        )
1056
        qcinp.write_file(os.path.join(os.path.dirname(__file__), "test_e2pert.qin"))
1✔
1057
        test_file = open(os.path.join(PymatgenTest.TEST_FILES_DIR, "molecules", "new_qchem_files", "e2pert.qin"))
1✔
1058
        ref_file = open(os.path.join(os.path.dirname(__file__), "test_e2pert.qin"))
1✔
1059

1060
        for l_test, l_ref in zip(test_file, ref_file):
1✔
1061
            assert l_test == l_ref
1✔
1062

1063
        test_file.close()
1✔
1064
        ref_file.close()
1✔
1065
        os.remove(os.path.join(os.path.dirname(__file__), "test_e2pert.qin"))
1✔
1066

1067
    def test_read_write_custom_smd(self):
1✔
1068
        qcinp = QCInput.from_file(
1✔
1069
            os.path.join(PymatgenTest.TEST_FILES_DIR, "molecules", "new_qchem_files", "custom_smd.qin")
1070
        )
1071
        qcinp.write_file(os.path.join(os.path.dirname(__file__), "test_custom_smd.qin"))
1✔
1072
        test_file = open(os.path.join(PymatgenTest.TEST_FILES_DIR, "molecules", "new_qchem_files", "custom_smd.qin"))
1✔
1073
        ref_file = open(os.path.join(os.path.dirname(__file__), "test_custom_smd.qin"))
1✔
1074

1075
        for l_test, l_ref in zip(test_file, ref_file):
1✔
1076
            assert l_test == l_ref
1✔
1077

1078
        test_file.close()
1✔
1079
        ref_file.close()
1✔
1080
        os.remove(os.path.join(os.path.dirname(__file__), "test_custom_smd.qin"))
1✔
1081

1082

1083
if __name__ == "__main__":
1✔
1084
    unittest.main()
×
STATUS · Troubleshooting · Open an Issue · Sales · Support · CAREERS · ENTERPRISE · START FREE · SCHEDULE DEMO
ANNOUNCEMENTS · TWITTER · TOS & SLA · Supported CI Services · What's a CI service? · Automated Testing

© 2025 Coveralls, Inc