Source code for exatomic.nwchem.inputs
# -*- coding: utf-8 -*-
# Copyright (c) 2015-2022, Exa Analytics Development Team
# Distributed under the terms of the Apache License 2.0
"""
Input Generator and Parser
#############################
Every attempt is made to follow the Documentation on the
NWChem `website`_ with a general theme of the input Generator
accepting keyword arguments mirroring the keywords accepted by
NWChem and values corresponding to the parameters in a calculation.
.. _website: http://www.nwchem-sw.org/index.php/Release66:NWChem_Documentation
"""
# """
# Due to the complexity of the NWChem program and the innumerable
# permutations of input file formats, this is in no way meant to be
# an exhaustive wrapper of NWChem input files. Alternatively,
# valid key words are handled according to the types of the
# arguments being passed to it. If the argument is a string, it should
# be formatted how you want with new line breaks (see default argument
# for geomopts). Multiple options for the same keyword are handled as
# lists of tuples (example: basis=[('C', '3-21G'), ('H', '6-31G**')]).
# Similarly, convergence criteria may be specified with convergence =
# ['nolevelshifting', 'ncydp 30', 'damp 70']. The closer your string
# formatting is to what NWChem expects, the less likely it is that you
# will obtain syntax errors in the written input file.
# """
from __future__ import absolute_import
from __future__ import print_function
from __future__ import division
#import pandas as pd
#import numpy as np
from .editor import Editor
#from exatomic.exa.util.units import Length as L
#from exatomic import Universe
_template = """echo
start {{name}}
title {{title}}
charge {{charge}}
{{memory}}
geometry {{geomopts}}
{{atom}}
end
basis {{basisopts}}
{{basis}}
end
{{set}}
{extras}
{calc}{{prop}}
{{task}}"""
_calcscf = """scf
nopen {mult}
maxiter {iterations}
end"""
_calcdft = """dft
direct
mult {mult}
xc {xc}
iterations {iterations}
tolerances {tolerances}
{grid}
{convergence}
{dft_other}
{restart}
end"""
[docs]class Input(Editor):
[docs] @classmethod
def from_universe(cls, uni, task='scf', fp=None, name=None, title=None,
charge=0, geomopts='units bohr\nsymmetry c1',
basisopts='spherical', basis='* library 6-31G',
mult=1, xc='b3lyp', iterations=100,
convergence='nolevelshifting', prop=' nbofile 2',
relativistic='', tddft='', ecp='', sets=None, tasks='property',
dft_other='', grid='xfine', tolerances='tight', memory=''):
calc = _calcdft if task == 'dft' else _calcscf
extras = ''
extradict = {}
for arg, extra in [('ecp', ecp), ('property', prop),
('relativistic', relativistic), ('tddft', tddft)]:
if extra:
extras += '{' + arg + '}'
extradict[arg] = _handle_arg(arg, extra)
fl = cls(_template.format(calc=calc, extras=extras))
keys = [key.split('}')[0].split(':')[0] for key in _template.split('{')[1:]]
keys += [key.split('}')[0].split(':')[0] for key in _calcscf.split('{')[1:]]
keys += [key.split('}')[0].split(':')[0] for key in _calcdft.split('{')[1:]]
kwargs = {key: '' for key in keys}
kwargs['atom'] = uni.atom.to_xyz()[:-1]
if name is not None:
kwargs['name'] = name
else:
kwargs['name'] = ''.join(atom['symbol'])
kwargs['title'] = title if title is not None else kwargs['name']
kwargs['charge'] = charge
kwargs['geomopts'] = _handle_arg('geomopts', geomopts)
kwargs['basisopts'] = _handle_arg('basisopts', basisopts)
kwargs['basis'] = _handle_arg('basis', basis)
if task == 'dft':
kwargs['mult'] = mult
elif mult - 1 > 0:
kwargs['mult'] = str(mult - 1) + '\n uhf'
else:
kwargs['mult'] = mult - 1
kwargs['xc'] = xc
kwargs['iterations'] = iterations
kwargs['tolerances'] = tolerances
kwargs['convergence'] = _handle_arg('convergence', convergence)
kwargs['grid'] = _handle_arg('grid', grid)
kwargs['dft_other'] = _handle_arg('dft_other', dft_other)
kwargs['memory'] = memory
if sets != None:
kwargs['set'] = _handle_arg('set', sets)
kwargs['task'] = ''
if isinstance(tasks, list):
for i in tasks:
kwargs['task'] += '\ntask '+task+' '+i
else:
kwargs['task'] += 'task '+task+' '+tasks
#extras = {'ecp': _handle_arg('ecp', ecp),
# 'tddft': _handle_arg('tddft', tddft),
# 'property': _handle_arg('property', prop),
# 'relativistic': _handle_arg('relativistic', relativistic)}
kwargs.update(extradict)
#### TASK AND EXTRAS
#kwargs['prop'] = '\n\nproperty\n nbofile 2\nend'
#kwargs['task'] = 'property'
#kwargs['calc'] = calc
#if options is not None:
# for opt, info in options.items():
# if opt in extras:
# _handle_info(opt, info, extras)
# elif kind == 'scf' and opt == 'mult':
# kwargs['mult'] = str(int(info) - 1) + '\n uhf' if int(info) > 1 else info
# else:
# _handle_info(opt, info, kwargs)
#extras = ['\n' + key + '\n' + val for key, val in extras.items() if val]
#kwargs['extras'] = '\n'.join([extra + '\nend' for extra in extras])
fl.format(inplace=True, **kwargs)
if fp is not None:
if name is not None:
fl.write(fp+name)
else:
fl.write(fp)
else:
return fl
def __init__(self, *args, **kwargs):
super(Input, self).__init__(*args, **kwargs)
def _handle_arg(opt, info):
type1 = {'basis': 'library', 'ecp': 'library'}
type2 = ['convergence', 'set', 'grid']
type3 = ['ecp', 'property', 'tddft', 'relativistic']
if isinstance(info, str):
if opt in type3:
return '\n{0}\n{1}\n{2}\n'.format(opt, info, 'end')
return info
if opt in type1:
ret = ''
for i, tup in enumerate(info):
if i == len(info) - 1:
ret = ' '.join([ret, tup[0], type1[opt], tup[1]])
else:
ret = ' '.join([ret, tup[0], type1[opt], tup[1], '\n'])
if opt in type3:
return '\n{0}\n{1}\n{2}\n'.format(opt, ret, 'end')
return ret
elif opt in type2:
ret = ''
if not isinstance(info, list):
info = [info]
for i, arg in enumerate(info):
if i == len(info) - 1:
ret = ' '.join([ret, opt, arg])
else:
ret = ' '.join([ret, opt, arg, '\n'])
if opt in type3:
return '\n{0}\n{1}\n{2}\n'.format(opt, ret, 'end')
return ret
else:
if isinstance(info, list):
return ' '.join([item for item in info])
else:
print('{} keyword not handled correctly with value {}'.format(opt, info))
[docs]def tuning_inputs(uni, name, mult, charge, basis, gammas, alphas,
route=None, link0=None,
field=None, writedir=None, deep=False):
"""
Provided a universe, generate input files for functional tuning.
Includes input keywords for orbital visualization within exatomic.
Assumes you will copy restart checkpoint files to have the same
names as the input files.
Args
uni (exatomic.container.Universe): molecular specification
name (str): prefix for job names
mult (int): spin multiplicity
charge (int): charge of the system
basis (list): tuples of atomic symbol, string of basis name
gammas (iter): values of range separation parameter (omega)
alphas (iter): fractions of Hartree-Fock in the short range
route (list): strings or tuples of keyword, value pairs (default [("Pop", "full")])
link0 (list): strings or tuples of keyword, value pairs
writedir (str): directory path to write input files
Returns
editors (list): input files as exatomic.exa.Editors
"""
if route is None:
route = [("Pop", "full")]
fnstr = 'xcampbe96 1.0 cpbe96 1.0 HFexch 1.0\n'\
' cam {gam:.4f} cam_alpha {alp:.4f} cam_beta {bet:.4f}'.format
jbnm = '{name}-{{gam:.2f}}-{{alp:.2f}}-{{chg}}'.format(name=name).format
chgnms = ['cat', 'neut', 'an']
chgs = [charge + 1, charge, charge - 1]
mults = [2, 1, 2] if mult == 1 else [mult - 1, mult, mult + 1]
fls = []
for gam in gammas:
for alp in alphas:
#bet = 1 - alp
for chgnm, chg, mult in zip(chgnms, chgs, mults):
fnc = fnstr(gam=gam, alp=alp, bet=1-alp)
jnm = jbnm(gam=gam, alp=alp, bet=1-alp, chg=chgnm)
opts = {'charge': chg, 'mult': mult, 'task': 'dft',
'title': jnm, 'name': jnm, 'xc': fnc,
'basis': basis, 'prop': ''} #, 'writedir': writedir}
fls.append(Input.from_universe(uni, **opts))
fls[-1].name = jnm + '.nw'
return fls
# def tuning_inputs(uni, name, mult, charge, basis, gammas, alphas,
# route=[('Pop', 'full')], link0=None, nproc=4, mem=4,
# field=None, writedir=None, deep=False):
# def from_universe(cls, uni, task='scf', fp=None, name=None, title=None,
# charge=0, geomopts='units bohr\nsymmetry c1',
# basisopts='spherical', basis='* library 6-31G',
# mult=1, xc='b3lyp', iterations=100,
# convergence='nolevelshifting', prop=' nbofile 2',
# relativistic='', tddft='', ecp=''):