Hot-keys on this page
r m x p toggle line displays
j k next/prev highlighted chunk
0 (zero) top of page
1 (one) first highlighted chunk
1"""This module defines an ASE interface to NWchem
3https://nwchemgit.github.io
4"""
5import os
6import numpy as np
8from ase import io
9from ase.units import Hartree
10from ase.calculators.calculator import FileIOCalculator
11from ase.spectrum.band_structure import BandStructure
14class NWChem(FileIOCalculator):
15 implemented_properties = ['energy', 'forces', 'stress', 'dipole']
16 command = 'nwchem PREFIX.nwi > PREFIX.nwo'
17 accepts_bandpath_keyword = True
18 discard_results_on_any_change = True
20 def __init__(self, restart=None,
21 ignore_bad_restart_file=FileIOCalculator._deprecated,
22 label='nwchem', atoms=None, command=None, **kwargs):
23 """
24 NWChem keywords are specified using (potentially nested)
25 dictionaries. Consider the following input file block:
27 >>> dft
28 >>> odft
29 >>> mult 2
30 >>> convergence energy 1e-9 density 1e-7 gradient 5e-6
31 >>> end
33 This can be generated by the NWChem calculator by using the
34 following settings:
36 >>> calc = NWChem(dft={'odft': None,
37 >>> 'mult': 2,
38 >>> 'convergence': {'energy': 1e-9,
39 >>> 'density': 1e-7,
40 >>> 'gradient': 5e-6,
41 >>> },
42 >>> },
43 >>> )
45 In addition, the calculator supports several special keywords:
47 theory: str
48 Which NWChem module should be used to calculate the
49 energies and forces. Supported values are ``'dft'``,
50 ``'scf'``, ``'mp2'``, ``'ccsd'``, ``'tce'``, ``'tddft'``,
51 ``'pspw'``, ``'band'``, and ``'paw'``. If not provided, the
52 calculator will attempt to guess which theory to use based
53 on the keywords provided by the user.
54 xc: str
55 The exchange-correlation functional to use. Only relevant
56 for DFT calculations.
57 task: str
58 What type of calculation is to be performed, e.g.
59 ``'energy'``, ``'gradient'``, ``'optimize'``, etc. When
60 using ``'SocketIOCalculator'``, ``task`` should be set
61 to ``'optimize'``. In most other circumstances, ``task``
62 should not be set manually.
63 basis: str or dict
64 Which basis set to use for gaussian-type orbital
65 calculations. Set to a string to use the same basis for all
66 elements. To use a different basis for different elements,
67 provide a dict of the form:
69 >>> calc = NWChem(...,
70 >>> basis={'O': '3-21G',
71 >>> 'Si': '6-31g'})
73 basispar: str
74 Additional keywords to put in the NWChem ``basis`` block,
75 e.g. ``'rel'`` for relativistic bases.
76 symmetry: int or str
77 The point group (for gaussian-type orbital calculations) or
78 space group (for plane-wave calculations) of the system.
79 Supports both group names (e.g. ``'c2v'``, ``'Fm3m'``) and
80 numbers (e.g. ``225``).
81 autosym: bool
82 Whether NWChem should automatically determine the symmetry
83 of the structure (defaults to ``False``).
84 center: bool
85 Whether NWChem should automatically center the structure
86 (defaults to ``False``). Enable at your own risk.
87 autoz: bool
88 Whether NWChem should automatically construct a Z-matrix
89 for your molecular system (defaults to ``False``).
90 geompar: str
91 Additional keywords to put in the NWChem `geometry` block,
92 e.g. ``'nucleus finite'`` for gaussian-shaped nuclear
93 charges. Do not set ``'autosym'``, ``'center'``, or
94 ``'autoz'`` in this way; instead, use the appropriate
95 keyword described above for these settings.
96 set: dict
97 Used to manually create or modify entries in the NWChem
98 rtdb. For example, the following settings enable
99 pseudopotential filtering for plane-wave calculations:
101 >>> set nwpw:kbpp_ray .true.
102 >>> set nwpw:kbpp_filter .true.
104 These settings are generated by the NWChem calculator by
105 passing the arguments:
107 >>> calc = NWChem(...,
108 >>> set={'nwpw:kbpp_ray': True,
109 >>> 'nwpw:kbpp_filter': True})
111 kpts: (int, int, int), or dict
112 Indicates which k-point mesh to use. Supported syntax is
113 similar to that of GPAW. Implies ``theory='band'``.
114 bandpath: BandPath object
115 The band path to use for a band structure calculation.
116 Implies ``theory='band'``.
117 """
118 FileIOCalculator.__init__(self, restart, ignore_bad_restart_file,
119 label, atoms, command, **kwargs)
120 self.calc = None
122 def write_input(self, atoms, properties=None, system_changes=None):
123 FileIOCalculator.write_input(self, atoms, properties, system_changes)
125 # Prepare perm and scratch directories
126 perm = os.path.abspath(self.parameters.get('perm', self.label))
127 scratch = os.path.abspath(self.parameters.get('scratch', self.label))
128 os.makedirs(perm, exist_ok=True)
129 os.makedirs(scratch, exist_ok=True)
131 io.write(self.label + '.nwi', atoms, properties=properties,
132 label=self.label, **self.parameters)
134 def read_results(self):
135 output = io.read(self.label + '.nwo')
136 self.calc = output.calc
137 self.results = output.calc.results
139 def band_structure(self):
140 self.calculate()
141 perm = self.parameters.get('perm', self.label)
142 if self.calc.get_spin_polarized():
143 alpha = np.loadtxt(os.path.join(perm, self.label + '.alpha_band'))
144 beta = np.loadtxt(os.path.join(perm, self.label + '.beta_band'))
145 energies = np.array([alpha[:, 1:], beta[:, 1:]]) * Hartree
146 else:
147 data = np.loadtxt(os.path.join(perm,
148 self.label + '.restricted_band'))
149 energies = data[np.newaxis, :, 1:] * Hartree
150 eref = self.calc.get_fermi_level()
151 if eref is None:
152 eref = 0.
153 return BandStructure(self.parameters.bandpath, energies, eref)