@@ -18,7 +18,7 @@ def __init__(self):
18
18
#Electron model
19
19
self .spin_polarized = True
20
20
self .xml_name = "BFD_Library.xml"
21
- self .functional = {'exchange' :'PBE' ,'correlation' :'PBE' ,'hybrid' :0 }
21
+ self .functional = {'exchange' :'PBE' ,'correlation' :'PBE' ,'hybrid' :0 , 'predefined' : None }
22
22
self .total_spin = 0
23
23
24
24
#Numerical convergence parameters
@@ -27,7 +27,7 @@ def __init__(self):
27
27
self .kmesh = [8 ,8 ,8 ]
28
28
self .gmesh = 16
29
29
self .tolinteg = [8 ,8 ,8 ,8 ,18 ]
30
- self .dftgrid = 'XLGRID '
30
+ self .dftgrid = ''
31
31
32
32
#Memory
33
33
self .biposize = 100000000
@@ -41,7 +41,9 @@ def __init__(self):
41
41
self .levshift = []
42
42
self .broyden = [0.01 ,60 ,15 ]
43
43
self .diis = False
44
- self .smear = 0.0001
44
+ self .smear = 0.0
45
+ self .supercell = [[1. ,0. ,0. ],[0. ,1. ,0. ],[0. ,0. ,1. ]]
46
+
45
47
46
48
# Use the new crystal2qmc script. This should change soon!
47
49
self .cryapi = True
@@ -55,7 +57,6 @@ def set_struct_fromcif(self,cifstr,primitive=True):
55
57
self .primitive = primitive
56
58
self .cif = cifstr
57
59
self .struct = CifParser .from_string (self .cif ).get_structures (primitive = self .primitive )[0 ].as_dict ()
58
- self .supercell = [[1. ,0. ,0. ],[0. ,1. ,0. ],[0. ,0. ,1. ]]
59
60
self .boundary = "3d"
60
61
#-----------------------------------------------
61
62
@@ -75,7 +76,7 @@ def set_options(self, d):
75
76
selfdict [k ]= d [k ]
76
77
77
78
#-----------------------------------------------
78
- def crystal_input (self ):
79
+ def crystal_input (self , section4 = [] ):
79
80
80
81
assert self .struct is not None ,'Need to set "struct" first.'
81
82
geomlines = self .geom ()
@@ -99,15 +100,19 @@ def crystal_input(self):
99
100
outlines += ["DFT" ]
100
101
if self .spin_polarized :
101
102
outlines += ["SPIN" ]
102
- outlines += [
103
- "EXCHANGE" ,
104
- self .functional ['exchange' ],
105
- "CORRELAT" ,
106
- self .functional ['correlation' ],
107
- "HYBRID" ,
108
- str (self .functional ['hybrid' ]),
109
- self .dftgrid ,
110
- "END" ,
103
+ if self .functional ['predefined' ]!= None :
104
+ outlines += [self .functional ['predefined' ]]
105
+ else :
106
+ outlines += [
107
+ "EXCHANGE" ,
108
+ self .functional ['exchange' ],
109
+ "CORRELAT" ,
110
+ self .functional ['correlation' ],
111
+ "HYBRID" ,
112
+ str (self .functional ['hybrid' ])]
113
+ if self .dftgrid != "" :
114
+ outlines += [self .dftgrid ]
115
+ outlines += ["END" ,
111
116
"SCFDIR" ,
112
117
"BIPOSIZE" ,
113
118
str (self .biposize ),
@@ -121,10 +126,10 @@ def crystal_input(self):
121
126
' ' .join (map (str ,self .tolinteg )),
122
127
"MAXCYCLE" ,
123
128
str (self .maxcycle ),
124
- "SMEAR" ,
125
- str (self .smear ),
126
129
"SAVEWF"
127
130
]
131
+ if self .smear > 0 :
132
+ outlines += ["SMEAR" ,str (self .smear )]
128
133
if self .spin_polarized :
129
134
outlines += ['SPINLOCK' ,str (self .total_spin )+ " 200" ]
130
135
@@ -134,7 +139,7 @@ def crystal_input(self):
134
139
outlines += ["LEVSHIFT" ," " .join (map (str ,self .levshift ))]
135
140
else :
136
141
outlines += ["BROYDEN" ," " .join (map (str ,self .broyden ))]
137
-
142
+ outlines += section4
138
143
if self .restart :
139
144
outlines += ["GUESSP" ]
140
145
outlines += ["END" ]
@@ -262,19 +267,13 @@ def basis_section(self):
262
267
elements .add (nm )
263
268
basislines = []
264
269
elements = sorted (list (elements )) # Standardize ordering.
265
- if self .boundary == '3d' :
266
- for e in elements :
267
- basislines += self .generate_basis_3d (e )
268
- elif self .boundary == '0d' :
269
- for e in elements :
270
- basislines += self .generate_basis_0d (e )
271
- else :
272
- raise AssertionError ("Invalid boundary value" )
270
+ for e in elements :
271
+ basislines += self .generate_basis (e )
273
272
return basislines
274
273
275
274
276
275
########################################################
277
- def generate_basis_3d (self ,symbol ):
276
+ def generate_basis (self ,symbol ):
278
277
"""
279
278
Author: "Kittithat (Mick) Krongchon" <[email protected] > and Lucas K. Wagner
280
279
Returns a string containing the basis section. It is modified according to a simple recipe:
@@ -360,75 +359,6 @@ def generate_basis_3d(self,symbol):
360
359
ret += ["0 %i %i %g 1" % (basis_index [angular ],1 ,0.0 ),line ]
361
360
ncontract += 1
362
361
363
- return ["%i %i" % (Element (symbol ).number + 200 ,ncontract )] + \
364
- self .pseudopotential_section (symbol ) + \
365
- ret
366
-
367
- ########################################################
368
- def generate_basis_0d (self ,symbol ):
369
- """
370
- Author: "Kittithat (Mick) Krongchon" <[email protected] > and Lucas K. Wagner
371
- Returns a string containing the basis section. It is modified according to a simple recipe:
372
- Args:
373
- symbol (str): The symbol of the element to be specified in the
374
- D12 file.
375
- xml_name (str): The name of the XML pseudopotential and basis
376
- set database.
377
- Returns:
378
- str: The pseudopotential and basis section.
379
- """
380
-
381
- maxorb = 3
382
- basis_name = "vtz"
383
- maxcharge = {"s" :2 ,"p" :6 ,"d" :10 ,"f" :15 } #max charge on a basis function
384
- max_tot_charge = {"s" :2 ,"p" :6 ,"d" :10 ,"f" :15 } #max total charge in an angular momentum
385
-
386
- basis_index = {"s" :0 ,"p" :2 ,"d" :3 ,"f" :4 }
387
- transition_metals = ["Sc" ,"Ti" ,"V" ,"Cr" ,"Mn" ,"Fe" ,"Co" ,"Ni" ,"Cu" ,"Zn" ]
388
- if symbol in transition_metals :
389
- maxorb = 4
390
- max_tot_charge ['s' ]= 4
391
- charge_sum = {"s" :0 ,"p" :0 ,"d" :0 ,"f" :0 }
392
- tree = ElementTree ()
393
- tree .parse (self .xml_name )
394
- element = tree .find ('./Pseudopotential[@symbol="{}"]' .format (symbol ))
395
- atom_charge = int (element .find ('./Effective_core_charge' ).text )
396
- if symbol in self .initial_charges .keys ():
397
- atom_charge -= self .initial_charges [symbol ]
398
- basis_path = './Basis-set[@name="{}"]/Contraction' .format (basis_name )
399
- found_orbitals = []
400
- totcharge = 0
401
- ret = []
402
- ncontract = 0
403
- for contraction in element .findall (basis_path ):
404
- angular = contraction .get ('Angular_momentum' )
405
-
406
- #Figure out which coefficients to print out based on the minimal exponent
407
- nterms = 0
408
- basis_part = []
409
- for basis_term in contraction .findall ('./Basis-term' ):
410
- exp = basis_term .get ('Exp' )
411
- coeff = basis_term .get ('Coeff' )
412
- basis_part += [' {} {}' .format (exp , coeff )]
413
- nterms += 1
414
- #now write the header
415
- if nterms > 0 and angular in basis_index .keys ():
416
- found_orbitals .append (angular )
417
- charge = min (atom_charge - totcharge ,maxcharge [angular ])
418
- if charge_sum [angular ] >= max_tot_charge [angular ]:
419
- charge = 0
420
- #put in a special case for transition metals:
421
- #depopulate the 4s if the atom is charged
422
- if symbol in transition_metals and symbol in self .initial_charges .keys () \
423
- and self .initial_charges [symbol ] > 0 and found_orbitals .count (angular ) > 1 \
424
- and angular == "s" :
425
- charge = 0
426
- totcharge += charge
427
- charge_sum [angular ]+= charge
428
- ret += ["0 %i %i %g 1" % (basis_index [angular ],nterms ,charge )] + basis_part
429
- ncontract += 1
430
-
431
-
432
362
return ["%i %i" % (Element (symbol ).number + 200 ,ncontract )] + \
433
363
self .pseudopotential_section (symbol ) + \
434
364
ret
@@ -495,7 +425,6 @@ def collect(self,outfilename):
495
425
lines = f .readlines ()
496
426
for li ,line in enumerate (lines ):
497
427
if 'SCF ENDED' in line :
498
- print (line )
499
428
self .out ['total_energy' ]= float (line .split ()[8 ])
500
429
501
430
elif 'TOTAL ATOMIC SPINS' in line :
@@ -505,7 +434,8 @@ def collect(self,outfilename):
505
434
moms += map (float ,lines [li + shift ].split ())
506
435
shift += 1
507
436
self .out ['mag_moments' ]= moms
508
- print (self .out )
437
+ self .out ['etots' ] = [float (line .split ()[3 ]) for line in lines if "DETOT" in line ]
438
+
509
439
self .completed = True
510
440
else :
511
441
# Just to be sure/clear...
@@ -523,36 +453,36 @@ def write_summary(self):
523
453
def check_outputfile (self ,outfilename ,acceptable_scf = 10.0 ):
524
454
""" Check output file.
525
455
526
- Current return values:
456
+ Return values:
527
457
no_record, not_started, ok, too_many_cycles, finished (fall-back),
528
458
scf_fail, not_enough_decrease, divergence, not_finished
529
459
"""
530
460
if os .path .isfile (outfilename ):
531
- outf = open (outfilename ,'r' )
461
+ outf = open (outfilename ,'r' , errors = 'ignore' )
532
462
else :
533
463
return "not_started"
534
464
535
- outlines = outf .read (). split ( ' \n ' )
465
+ outlines = outf .readlines ( )
536
466
reslines = [line for line in outlines if "ENDED" in line ]
537
467
538
468
if len (reslines ) > 0 :
539
469
if "CONVERGENCE" in reslines [0 ]:
540
470
return "ok"
541
471
elif "TOO MANY CYCLES" in reslines [0 ]:
542
- print ("CrystalRunner: Too many cycles." )
472
+ # print("CrystalRunner: Too many cycles.")
543
473
return "too_many_cycles"
544
474
else : # What else can happen?
545
- print ("CrystalReader: Finished, but unknown state." )
475
+ # print("CrystalReader: Finished, but unknown state.")
546
476
return "finished"
547
477
548
478
detots = [float (line .split ()[5 ]) for line in outlines if "DETOT" in line ]
549
479
if len (detots ) == 0 :
550
- print ("CrystalRunner: Last run completed no cycles." )
480
+ # print("CrystalRunner: Last run completed no cycles.")
551
481
return "scf_fail"
552
482
553
483
detots_net = sum (detots [1 :])
554
484
if detots_net > acceptable_scf :
555
- print ("CrystalRunner: Last run performed poorly." )
485
+ # print("CrystalRunner: Last run performed poorly.")
556
486
return "not_enough_decrease"
557
487
558
488
etots = [float (line .split ()[3 ]) for line in outlines if "DETOT" in line ]
0 commit comments