qmcpack/nexus/library/pseudopotential.py

2421 lines
76 KiB
Python

##################################################################
## (c) Copyright 2015- by Jaron T. Krogel ##
##################################################################
#! /usr/bin/env python
import os
from subprocess import Popen
from execute import execute
from numpy import linspace,array,zeros,append,mgrid,empty,exp,minimum,maximum,sqrt
from xmlreader import readxml
from superstring import string2val,split_delims
from periodic_table import pt
from unit_converter import convert
from generic import obj
from developer import DevBase,unavailable,error
from debug import *
try:
from matplotlib.pyplot import figure,plot,xlabel,ylabel,title,show,ylim,legend,xlim,rcParams,savefig,bar,xticks,subplot,grid,setp,errorbar,loglog,semilogx,semilogy
params = {'legend.fontsize':14,'figure.facecolor':'white','figure.subplot.hspace':0.,
'axes.labelsize':16,'xtick.labelsize':14,'ytick.labelsize':14}
rcParams.update(params)
except (ImportError,RuntimeError):
figure,plot,xlabel,ylabel,title,show,ylim,legend,xlim,rcParams,savefig,bar,xticks,subplot,grid,setp,errorbar,loglog,semilogx,semilogy = unavailable('matplotlib.pyplot','figure','plot','xlabel','ylabel','title','show','ylim','legend','xlim','rcParams','savefig','bar','xticks','subplot','grid','setp','errorbar','loglog','semilogx','semilogy')
#end try
try:
from scipy.optimize import curve_fit
except:
curve_fit = unavailable('curve_fit')
#end try
# basic interface for nexus, only gamess really needs this for now
class PseudoFile(DevBase):
def __init__(self,filepath=None):
self.element = None
self.filename = None
self.location = None
if filepath!=None:
self.filename = os.path.basename(filepath)
self.location = os.path.abspath(filepath)
self.element = self.filename[0:2].strip('._-')
self.read(filepath)
#end if
#end def __init__
def read(self,filepath):
None
#end def read
#end class PseudoFile
class gamessPPFile(PseudoFile):
def __init__(self,filepath=None):
self.pp_text = None
self.pp_name = None
self.basis_text = None
PseudoFile.__init__(self,filepath)
#end def __init__
def read(self,filepath):
lines = open(filepath,'r').read().splitlines()
new_block = True
tokens = []
block = ''
nline = 0
for line in lines:
nline+=1
ls = line.strip()
if len(ls)>0 and ls[0]!='!' and ls[0]!='#':
if new_block:
tokens = ls.split()
new_block = False
if len(tokens)!=5:
block+=line+'\n'
#end if
else:
block+=line+'\n'
#end if
#end if
if (len(ls)==0 or nline==len(lines)) and len(block)>0:
block = block.rstrip()
if len(tokens)==4:
self.pp_text = block
self.pp_name = tokens[0]
elif len(tokens)==5:
self.basis_text = block
else:
self.error('could not identify text block in {0} as pseudopotential or basis text\btext block:\n{1}'.format(self.filename,block))
#end if
new_block = True
tokens = []
block = ''
#end if
#end for
if self.pp_text is None:
self.error('could not find pseudopotential text in '+self.filename)
#end if
if self.basis_text is None:
self.error('could not find basis text in '+self.filename)
#end if
#end def read
#end class gamessPPFile
class Pseudopotentials(DevBase):
def __init__(self,*pseudopotentials):
if len(pseudopotentials)==1 and isinstance(pseudopotentials[0],list):
pseudopotentials = pseudopotentials[0]
#end if
ppfiles = []
pps = []
errors = False
print
for pp in pseudopotentials:
if isinstance(pp,PseudoFile):
pps.append(pp)
elif isinstance(pp,str):
ppfiles.append(pp)
else:
self.error('expected PseudoFile type or filepath, got '+str(type(pp)),exit=False)
errors = True
#end if
#end for
if errors:
self.error('cannot create Pseudopotentials object')
#end if
if len(pps)>0:
self.addpp(pps)
#end if
if len(ppfiles)>0:
self.readpp(ppfiles)
#end if
#end def __init__
def addpp(self,*pseudopotentials):
if len(pseudopotentials)==1 and isinstance(pseudopotentials[0],list):
pseudopotentials = pseudopotentials[0]
#end if
for pp in pseudopotentials:
self[pp.filename] = pp
#end for
#end def addpp
def readpp(self,*ppfiles):
if len(ppfiles)==1 and isinstance(ppfiles[0],list):
ppfiles = ppfiles[0]
#end if
pps = []
print ' Pseudopotentials'
for filepath in ppfiles:
print ' reading pp: ',filepath
ext = filepath.split('.')[-1].lower()
if ext=='gms':
pp = gamessPPFile(filepath)
else:
pp = PseudoFile(filepath)
#end if
pps.append(pp)
#end for
self.addpp(pps)
#end def readpp
def pseudos_by_atom(self,*ppfiles):
pps = obj()
for ppfile in ppfiles:
if ppfile in self:
pp = self[ppfile]
pps[pp.element] = pp
#end if
#end for
return pps
#end def pseudos_by_atom
#end class Pseudopotentials
# real pseudopotentials
from plotting import *
show_plots = show
set_title = title
class Pseudopotential(DevBase):
requires_format = False
formats = None
def __init__(self,filepath=None,format=None):
self.element = None
self.core = None
self.Zval = None
self.Zcore = None
if filepath!=None:
self.read(filepath,format)
#end if
#end def __init__
def transfer_core_from(self,other):
self.element = other.element
self.core = other.core
self.Zval = other.Zval
self.Zcore = other.Zcore
#end def transfer_core_from
def read(self,filepath,format=None):
if self.requires_format:
if format is None:
self.error('format keyword must be specified to read file {0}\nvalid options are: {1}'.format(filepath,self.formats))
elif not format in self.formats:
self.error('incorrect format requested: {0}\nvalid options are: {1}'.format(format,self.formats))
#end if
#end if
if not os.path.exists(filepath):
self.error('cannot read {0}, file does not exist'.format(filepath))
#end if
self.element = split_delims(os.path.split(filepath)[1])[0]
text = open(filepath,'r').read()
self.read_text(text,format)
#end def read
def write(self,filepath=None,format=None):
if self.requires_format:
if format is None:
self.error('format keyword must be specified to write file {0}\nvalid options are: {1}'.format(filepath,self.formats))
elif not format in self.formats:
self.error('incorrect format requested: {0}\nvalid options are: {1}'.format(format,self.formats))
#end if
#end if
text = self.write_text(format)
if filepath!=None:
open(filepath,'w').write(text)
#end if
return text
#end def write
def read_text(self,text,format=None):
self.not_implemented()
#end def read_text
def write_text(self,format=None):
self.not_implemented()
#end def write_text
def convert(self,format):
self.not_implemented()
#end def convert
def plot(self,r=None,show=True):
self.not_implemented()
#end def plot
#end class Pseudopotential
class SemilocalPP(Pseudopotential):
l_channels = tuple('spdfgh')
all_channels = ['loc']+list(l_channels)
channel_colors = obj(s='g',p='r',d='b',f='m',g='c',h='k')
numeric = False
interpolatable = True
formats = ['qmcpack']
def __init__(self,filepath=None,format=None,name=None,src=None):
self.name = name
self.rcut = None
self.lmax = None
self.local = None
if self.numeric:
self.r = None
#end if
self.channels = obj()
Pseudopotential.__init__(self,filepath,format)
if src!=None:
self.transfer_core_from(src)
#end if
#end def __init__
def transfer_core_from(self,other):
self.name = other.name
self.rcut = other.rcut
self.lmax = other.lmax
self.local = other.local
if self.numeric and other.numeric:
self.r = other.r
#end if
Pseudopotential.transfer_core_from(self,other)
#end def transfer_core_from
def read(self,filepath,format=None):
Pseudopotential.read(self,filepath,format)
if self.rcut is None:
self.update_rcut()
#end if
#end def read
def get_channel(self,l=None):
if l is None:
l = self.local
#end if
if not l in self.channels:
self.error('cannot get invalid channel: {0}\n valid options are: {1}'.format(l,self.channels.keys()))
#end if
return self.channels[l]
#end def get_channel
def remove_channel(self,l):
if l in self.channels:
del self.channels[l]
if self.local==l:
lmax = -1
for lt in self.channels.keys():
li = self.l_int_from_text(lt)
if li>lmax:
lmax = li
self.local = lt
#end if
#end for
self.lmax = lmax
#end if
#end if
#end def remove_channel
def l_int_from_text(self,ltext):
lint = 'spdfgh'.find(ltext)
return lint
#end def l_int_from_text
def evaluate(self,r=None,l=None,rpow=0,with_local=False):
if self.numeric and not self.interpolatable:
r = None
elif r is None and self.interpolatable:
r = linspace(0.01,4.0,400)
#end if
if not with_local:
v = self.evaluate_rV(r,l)
elif l==None or l==self.local:
v = self.evaluate_rV(r,l)
else:
v = self.evaluate_rV(r,l)+self.evaluate_rV(r,self.local)
#end if
if self.numeric and not self.interpolatable:
r = self.r
#end if
if rpow!=1:
v = r**(rpow-1)*v
#end if
return v
#end def evaluate
def evaluate_rV(self,r=None,l=None): # returns r*V
self.not_implemented()
#end def evaluate_rV
def numeric_channel(self,l=None,rmin=0.,rmax=10.,npts=10001,rpow=0,with_local=False):
if self.numeric and not self.interpolatable:
v = self.evaluate(None,l,rpow,with_local)
r = self.r
else:
r = linspace(rmin,rmax,npts)
v = self.evaluate(r,l,rpow,with_local)
#end if
return r,v
#end def numeric_channel
def update_rcut(self,tol=1e-5):
self.rcut = self.find_rcut(tol=tol)
return self.rcut
#end def update_rcut
def find_rcut(self,tol=1e-5):
r = None
vmin = None
vmax = None
for l in self.channels.keys():
rc,vc = self.numeric_channel(l,rmin=0.01,with_local=True)
if r is None:
r = rc
vmin = array(vc)
vmax = array(vc)
elif len(rc)!=len(r):
self.error('numeric representation of channels do not match in length')
else:
vmin = minimum(vmin,vc)
vmax = maximum(vmax,vc)
#end if
#end for
vspread = vmax-vmin
rcut = r[-1]
nr = len(r)
for i in xrange(nr):
n = nr-1-i
if vspread[n]>tol:
rcut = r[n]
break
#end if
#end for
#figure()
#plot(r,vspread,'k-')
#plot([rcut,rcut],[0,vspread[1:].max()],'k--')
#title('rcut = {0}'.format(rcut))
#show()
return rcut
#end def find_rcut
def plot(self,r=None,show=True,fig=True,linestyle='-',channels=None,with_local=False,rmin=0.01,rmax=5.0,title=None,metric=None):
if channels is None:
channels = self.all_channels
#end if
if fig:
figure()
#end if
if r is None and self.numeric:
r = self.r
elif r is None:
r = linspace(rmin,rmax,1000)
#end if
for c in channels:
if c in self.channels:
if c==self.local:
lab = self.local+' loc'
color = self.channel_colors[self.local]
else:
lab = c
color = self.channel_colors[c]
#end if
if self.name!=None:
lab = self.name+' '+lab
#end if
v = self.evaluate(r,c,with_local)
if metric=='r2':
v = r**2*v
if c==self.local:
v += self.Zval*r
#end if
elif metric!=None:
self.error('invalid metric for plotting: {0}\nvalid options are: r2'.format(metric))
#end if
plot(r,v,color+linestyle,label=lab)
#end for
#end for
if fig:
if title is None:
title = 'Semilocal {0} PP ({1} core)'.format(self.element,self.core)
#end if
set_title(title)
ylabel('channels')
xlabel('r')
legend()
if show:
show_plots()
#end if
#end if
#end def plot
def gaussian_fit(self,r=None,pmax=3,maxfev=100000,verbose=False,filepath=None,format=None,offset=0):
if verbose:
self.log('\nfitting {0} pseudopotential to gaussians'.format(self.element))
#end if
gf.Z = self.Zval
if r is None:
r = self.r
#end if
#r2 = r**2
channels = obj()
for l in self.channels.keys():
#channels[l] = self.evaluate(r,l)[offset:]*r2[offset:]
channels[l] = self.evaluate(r,l,rpow=2)
#end for
#r = r[offset:]
#del r2
p0nl = 10.0,0.3
p0loc = 0.2,0.3,10.,0.3
padd = [0.0,0.3,.27]
channel_params = obj()
for l in self.channels.keys():
if l==self.local:
channel_params[l] = tuple(p0loc)
else:
channel_params[l] = tuple(p0nl)
#end if
#end for
pmt = (1,pmax)
if not pmt in gf.functions or not pmt in gf.loc_functions:
self.error('cannot include {0} paired functions\nplease choose a smaller number for pmax'.format(pmax))
#end if
gfits = GFit()
gfits.proto = GaussianPP()
gfits.proto.transfer_core_from(self)
channel_fits = obj()
for l in self.channels.keys():
if verbose:
self.log(' fitting channel {0}'.format(l))
#end if
lfits = obj()
fail = False
for p in range(pmax+1):
if verbose:
self.log(' performing fit of order {0}'.format(p))
#end if
try:
if l==self.local:
gf_fit = gf.loc_functions[1,p]
Zval = self.Zval
else:
gf_fit = gf.functions[1,p]
Zval = None
#end if
v = channels[l]
p0 = channel_params[l]
vp,vc = curve_fit(gf_fit,r,v,p0,maxfev=maxfev)
gc = get_gf_channel(1,p,vp,Zval)
vf = gf_fit(r,*vp)
rms_dev = gf.rms_deviation(v,vf)
energy_dev = gf.energy_deviation(v,vf,r)
cfit = obj(
channel = gc,
rms_dev = rms_dev,
energy_dev = energy_dev
)
if verbose:
self.log(' rms deviation: {0}'.format(rms_dev))
self.log(' energy deviation: {0}'.format(energy_dev))
#end if
lfits.append(cfit)
except StandardError,e:
#print e
fail = True
#end try
if fail:
if verbose:
self.log(' order {0} fit failed, skipping higher orders'.format(p))
#end if
break
#end if
channel_params[l] = tuple(list(channel_params[l])+padd)
#end for
channel_fits[l] = lfits
#end for
gfits.channels = channel_fits
if filepath!=None:
for p,gpp in gfits.iteritems():
fpath = filepath.format(p)
if verbose:
self.log(' writing '+fpath)
#end if
gpp.write(fpath,format)
#end for
#end if
if verbose:
self.log(' fitting complete')
#end if
return gfits
#end def gaussian_fit
def write_qmcpack(self,filepath=None):
if self.rcut is None:
self.update_rcut(tol=1e-5)
#end if
symbol = self.element
atomic_number = self.Zcore+self.Zval
zval = self.Zval
creator = 'nexus'
npots_down = len(self.channels)
l_local = 'spdfg'.find(self.local)
rmin = 1e99
rmax = -1e99
npts = 0
vps = obj()
for l in self.channels.keys():
r,v = self.numeric_channel(l,rpow=1,with_local=True)
rmin = min(rmin,r.min())
rmax = max(rmax,r.max())
npts = len(r)
vps[l] = v
#end for
header = '''<?xml version="1.0" encoding="UTF-8"?>
<pseudo version="0.5">
<header symbol="{0}" atomic-number="{1}" zval="{2}" relativistic="unknown"
polarized="unknown" creator="{3}" flavor="unknown"
core-corrections="unknown" xc-functional-type="unknown"
xc-functional-parametrization="unknown"/>
'''.format(symbol,atomic_number,zval,creator)
grid = ' <grid type="linear" units="bohr" ri="{0}" rf="{1}" npts="{2}"/>\n'.format(rmin,rmax,npts)
semilocal = ' <semilocal units="hartree" format="r*V" npots-down="{0}" npots-up="0" l-local="{1}">\n'.format(npots_down,l_local)
dpad = '\n '
for l in self.l_channels:
if l in vps:
semilocal+=' <vps principal-n="0" l="{0}" spin="-1" cutoff="{1}" occupation="unknown">\n'.format(l,self.rcut)
semilocal+=' <radfunc>\n'
semilocal+=' '+grid
semilocal+=' <data>'
v = vps[l]
n=0
for d in v:
if n%3==0:
semilocal+=dpad
#end if
semilocal+='{0:22.14e}'.format(d)
n+=1
#end for
semilocal+=' </data>\n'
semilocal+=' </radfunc>\n'
semilocal+=' </vps>\n'
#end if
#end for
semilocal+=' </semilocal>\n'
footer = '</pseudo>\n'
text = header+grid+semilocal+footer
if filepath!=None:
open(filepath,'w').write(text)
#end if
return text
#end def write_qmcpack
#end class SemilocalPP
class GFit(DevBase):
def __init__(self):
self.proto = None # SemilocalPP
self.channels = None
#end def __init__
def best_channels(self):
cfits = obj()
for l,pfits in self.channels.iteritems():
emin = 1e99
cmin = None
for p,cfit in pfits.iteritems():
if abs(cfit.energy_dev)<emin:
emin = abs(cfit.energy_dev)
cmin = cfit
#end if
#end for
cfits[l] = cfit
#end for
return cfits
#end def best_channels
def best(self):
pp = self.proto.copy()
for l,cfit in self.best_channels().iteritems():
pp.channels[l] = cfit.channel
#end for
return pp
#end def best
def report(self,fits='best'):
print
print 'Gaussian fits for '+self.proto.element
if fits=='best':
cfits = self.best_channels()
for l in self.proto.l_channels:
if l in cfits:
cfit = cfits[l]
print ' {0} {1} {2}'.format(l,cfit.energy_dev,cfit.rms_dev)
#end if
#end for
else:
self.error('fits option {0} is not supported'.format(fits))
#end if
#end def report
#end class GFit
def process_gaussian_text(text,format,pp=True,basis=True):
if format=='gamess' or format=='gaussian':
rawlines = text.splitlines()
sections = []
last_empty = True
for rline in rawlines:
line = rline.strip()
if (not line.startswith('!')) and (not line.startswith('#')) and len(line)>0:
if last_empty:
lines = []
sections.append(lines)
#end if
lines.append(line)
last_empty = False
else:
last_empty = True
#end if
#end for
del lines
if len(sections)==2:
basis_lines = sections[0]
pp_lines = sections[1]
elif pp:
basis_lines = None
pp_lines = sections[0]
elif basis:
basis_lines = sections[0]
pp_lines = None
#end if
elif format=='crystal':
rawlines = text.splitlines()
pp_lines = []
basis_lines = []
foundpp = False
for line in rawlines:
if not foundpp:
foundpp = len(line.split())==5
#end if
if not foundpp:
pp_lines.append(line)
else:
basis_lines.append(line)
#end if
#end for
if len(pp_lines)==0:
pp_lines = None
#end if
if len(basis_lines)==0:
basis_lines = None
#end if
else:
error('{0} format is unknown'.format(format),'process_gaussian_text')
#end if
if pp and basis:
return pp_lines,basis_lines
elif pp:
return pp_lines
elif basis:
return basis_lines
else:
error('must request pp or basis')
#end if
#end def process_gaussian_text
class GaussianBasisSet(DevBase):
lset_full = tuple('spdfghijk')
lstyles = obj(s='g-',p='r-',d='b-',f='m-',g='c-',h='k-',i='g-.',j='r-.',k='b-.')
formats = 'gaussian gamess'.split()
crystal_lmap = {0:'s',1:'sp',2:'p',3:'d',4:'f'}
crystal_lmap_reverse = dict(s=0,sp=1,p=2,d=3,f=4)
@staticmethod
def process_float(s):
return float(s.replace('D','e').replace('d','e'))
#end def process_float
def __init__(self,filepath=None,format=None):
self.name = None
self.basis = obj()
if filepath!=None:
self.read(filepath,format)
#end if
#end def __init__
def read(self,filepath,format=None):
if format is None:
self.error('format keyword must be specified to read file {0}\nvalid options are: {1}'.format(filepath,self.formats))
elif not format in self.formats:
self.error('incorrect format requested: {0}\nvalid options are: {1}'.format(format,self.formats))
#end if
if not os.path.exists(filepath):
self.error('cannot read {0}, file does not exist'.format(filepath))
#end if
#self.name = split_delims(os.path.split(filepath)[1])[0]
self.name = os.path.split(filepath)[1].split('.')[0]
text = open(filepath,'r').read()
self.read_text(text,format)
#end def read
def write(self,filepath=None,format=None):
if format is None:
self.error('format keyword must be specified to write file {0}\nvalid options are: {1}'.format(filepath,self.formats))
elif not format in self.formats:
self.error('incorrect format requested: {0}\nvalid options are: {1}'.format(format,self.formats))
#end if
text = self.write_text(format)
if filepath!=None:
open(filepath,'w').write(text)
#end if
return text
#end def write
def read_text(self,text,format=None):
basis_lines = process_gaussian_text(text,format,pp=False)
self.read_lines(basis_lines,format)
#end def read_text
def read_lines(self,basis_lines,format=None):
basis = self.basis
basis.clear()
if format=='gamess':
i=1
while i<len(basis_lines):
tokens = basis_lines[i].split(); i+=1
ltext = tokens[0].lower()
ngauss = int(tokens[1])
scale = array(tokens[2:],dtype=float)
bterms = obj()
for j in xrange(ngauss):
index,expon,coeff = basis_lines[i].split(); i+=1
expon = GaussianBasisSet.process_float(expon)
coeff = GaussianBasisSet.process_float(coeff)
bterms.append(obj(expon=expon,coeff=coeff))
#end for
basis.append(obj(l=ltext,scale=scale,terms=bterms))
#end while
#end if
elif format=='gaussian':
i=1
while i<len(basis_lines):
tokens = basis_lines[i].split(); i+=1
ltext = tokens[0].lower()
ngauss = int(tokens[1])
scale = array(tokens[2:],dtype=float)
bterms = obj()
for j in xrange(ngauss):
expon,coeff = basis_lines[i].split(); i+=1
expon = GaussianBasisSet.process_float(expon)
coeff = GaussianBasisSet.process_float(coeff)
bterms.append(obj(expon=expon,coeff=coeff))
#end for
basis.append(obj(l=ltext,scale=scale,terms=bterms))
#end while
elif format=='crystal':
i=0
while i<len(basis_lines):
tokens = basis_lines[i].split(); i+=1
if len(tokens)!=5:
self.error('could not parse crystal basisset, input may be misformatted')
#end if
basis_type = int(tokens[0])
l_type = int(tokens[1])
ngauss = int(tokens[2])
formal_charge = float(tokens[3])
scale = array([tokens[4]],dtype=float)
ltext = GaussianBasisSet.crystal_lmap[l_type]
if ltext!='sp':
bterms = obj()
for j in xrange(ngauss):
expon,coeff = basis_lines[i].split(); i+=1
expon = GaussianBasisSet.process_float(expon)
coeff = GaussianBasisSet.process_float(coeff)
bterms.append(obj(expon=expon,coeff=coeff))
#end for
basis.append(obj(l=ltext,scale=scale,terms=bterms))
else: # sp has shared exponent for s and p, split them now
sterms = obj()
pterms = obj()
for j in xrange(ngauss):
expon,scoeff,pcoeff = basis_lines[i].split(); i+=1
expon = GaussianBasisSet.process_float(expon)
scoeff = GaussianBasisSet.process_float(scoeff)
pcoeff = GaussianBasisSet.process_float(pcoeff)
sterms.append(obj(expon=expon,coeff=scoeff))
pterms.append(obj(expon=expon,coeff=pcoeff))
#end for
basis.append(obj(l='s',scale=scale,terms=sterms))
basis.append(obj(l='p',scale=scale,terms=pterms))
#end if
#end while
else:
self.error('ability to read file format {0} has not been implemented'.format(format))
#end if
# sort the basis in s,p,d,f,... order
self.lsort()
#end def read_lines
def write_text(self,format=None,occ=None):
text = ''
format = format.lower()
if format=='gamess':
#text += '{0} {1} 0. 0. 0.\n'.format(self.element,self.Zcore+self.Zval)
for ib in xrange(len(self.basis)):
b = self.basis[ib]
line = '{0} {1}'.format(b.l,len(b.terms))
for s in b.scale:
line += ' {0}'.format(s)
#end for
text += line + '\n'
for it in xrange(len(b.terms)):
t = b.terms[it]
text += '{0} {1:12.8f} {2: 12.8f}\n'.format(it+1,t.expon,t.coeff)
#end for
#end for
elif format=='gaussian':
#text += '{0} 0\n'.format(self.element)
for ib in xrange(len(self.basis)):
b = self.basis[ib]
line = '{0} {1}'.format(b.l,len(b.terms))
for s in b.scale:
line += ' {0}'.format(s)
#end for
text += line + '\n'
for it in xrange(len(b.terms)):
t = b.terms[it]
text += '{0:12.8f}{1: 12.8f}\n'.format(t.expon,t.coeff)
#end for
#end for
elif format=='crystal':
if occ is not None:
lcounts = dict(s=0,p=0,d=0,f=0)
#end if
for ib in xrange(len(self.basis)):
b = self.basis[ib]
if b.l not in self.crystal_lmap_reverse:
self.error('{0} channels cannot be handled by crystal'.format(b.l))
#end if
Zf = 0
if occ is not None and b.l in occ and lcounts[b.l]<len(occ[b.l]):
Zf = occ[b.l][lcounts[b.l]]
lcounts[b.l]+=1
#end if
lnum = self.crystal_lmap_reverse[b.l]
line = '0 {0} {1} {2} {3}'.format(lnum,len(b.terms),Zf,b.scale[0])
text += line + '\n'
for it in xrange(len(b.terms)):
t = b.terms[it]
text += '{0:12.8f}{1: 12.8f}\n'.format(t.expon,t.coeff)
#end for
#end for
else:
self.error('ability to write file format {0} has not been implemented'.format(format))
#end if
return text
#end def write_text
def size(self):
return len(self.basis)
#end def size
def lset(self):
lset = set()
for bf in self.basis:
lset.add(bf.l)
#end for
return lset
#end def lset
def lcount(self):
return len(self.lset())
#end def lcount
def lbasis(self):
lbasis = obj()
for n in range(len(self.basis)):
bf = self.basis[n]
l = bf.l
if l not in lbasis:
lbasis[l] = obj()
#end if
lbasis[l].append(bf)
#end for
return lbasis
#end def lbasis
def lsort(self):
lbasis = self.lbasis()
self.basis.clear()
for l in self.lset_full:
if l in lbasis:
lbas = lbasis[l]
for n in range(len(lbas)):
bf = lbas[n]
self.basis.append(bf)
#end for
#end if
#end for
#end def lsort
def uncontracted(self):
all_uncon = True
for bf in self.basis:
all_uncon &= len(bf.terms)==1
#end for
return all_uncon
#end def uncontracted
def contracted(self):
return not self.uncontracted()
#end def contracted
def uncontract(self,tol=1e-3):
if self.uncontracted():
return
#end if
lbasis = self.lbasis()
self.basis.clear()
for l in self.lset_full:
if l in lbasis:
exponents = []
lbas = lbasis[l]
for n in xrange(len(lbas)):
uterms = lbas[n].terms
for i in xrange(len(uterms)):
expon = uterms[i].expon
if len(exponents)==0:
exponents = array([expon],dtype=float)
elif abs(exponents-expon).min()>tol:
exponents = array(list(exponents)+[expon],dtype=float)
#end if
#end for
#end for
for expon in exponents:
cterms = obj()
cterms.append(obj(expon=expon,coeff=1.0))
bf = obj(l=l,scale=array([1.0]),terms=cterms)
self.basis.append(bf)
#end for
#end if
#end for
#end def uncontract
def contracted_basis_size(self):
bcount = obj()
for bf in self.basis:
l = bf.l
if l not in bcount:
bcount[l]=0
#end if
bcount[l] += 1
#end for
bs = ''
for l in self.lset_full:
if l in bcount:
bs += str(bcount[l])+l
#end if
#end for
return bs
#end def contracted_basis_size
def basis_size(self):
uc = self.copy()
uc.uncontract()
bs = self.contracted_basis_size()
ps = uc.contracted_basis_size()
return '({0})/[{1}]'.format(ps,bs)
#end def basis_size
def incorporate(self,other):
lbasis = self.lbasis()
lbasis_other = other.lbasis()
self.basis.clear()
for l in self.lset_full:
if l in lbasis:
lbas = lbasis[l]
for n in range(len(lbas)):
bf = lbas[n]
self.basis.append(bf)
#end for
#end if
if l in lbasis_other:
lbas = lbasis_other[l]
for n in range(len(lbas)):
bf = lbas[n]
self.basis.append(bf)
#end for
#end if
#end for
#end def incorporate
def plot(self,r=None,rmin=0.01,rmax=8.0,show=True,fig=True,sep=False,prim=False,style=None,fmt=None,nsub=None):
if r is None:
r = linspace(rmin,rmax,1000)
#end if
if not prim:
ptitle = '{0} {1} basis'.format(self.name,self.basis_size())
else:
ptitle = '{0} {1} primitives'.format(self.name,self.basis_size())
#end if
if fig:
figure()
#end if
r2 = r**2
lcount = self.lcount()
if nsub!=None:
lcount = max(lcount,nsub)
#end if
lbasis = self.lbasis()
lc = 0
for l in self.lset_full:
if l in lbasis:
lc+=1
if sep:
subplot(lcount,1,lc)
ylabel(l)
if lc==1:
title(ptitle)
#end if
#end if
lstyle=self.lstyles[l]
if style!=None:
lstyle = lstyle[0]+style
#end if
if fmt!=None:
lstyle=fmt
#end if
lbas = lbasis[l]
for n in range(len(lbas)):
bf = lbas[n]
br = zeros(r.shape)
s = bf.scale[0]
for pf in bf.terms:
c = pf.coeff
a = -pf.expon*s**2
pr = exp(a*r2)
if not prim:
br += c*pr
else:
plot(r,pr,lstyle,label=l)
#end if
#end for
if not prim:
plot(r,br,lstyle,label=l)
#end if
#end for
#end if
#end for
if fig:
if not sep:
if self.name!=None:
title(ptitle)
#end if
ylabel('basis functions')
legend()
else:
xlabel('r')
#end if
if show:
show_plots()
#end if
#end if
#end def plot
def plot_primitives(self):
None
#end def plot_primitives
#end class GaussianBasisSet
class GaussianPP(SemilocalPP):
requires_format = True
formats = SemilocalPP.formats + 'gaussian gamess crystal'.split()
@staticmethod
def process_float(s):
return float(s.replace('D','e').replace('d','e'))
#end def process_float
def __init__(self,filepath=None,format=None,name=None,src=None):
self.basis = None
SemilocalPP.__init__(self,filepath,format,name,src)
#end def __init__
def read_text(self,text,format=None):
lines,basis_lines = process_gaussian_text(text,format)
format=format.lower()
channels = []
basis = None
# need lmax, element, and Zcore
if format=='gamess':
i=0
name,type,Zcore,lmax = lines[i].split(); i+=1
Zcore = int(Zcore)
lmax = int(lmax)
element = split_delims(name)[0]
while i<len(lines):
n = int(lines[i]); i+=1
terms = []
for j in range(n):
coeff,rpow,expon = lines[i].split(); i+=1
terms.append((float(coeff),int(rpow),float(expon)))
#end for
channels.append(terms)
#end while
elif format=='gaussian':
i=0
element,token = lines[i].split(); i+=1
label,lmax,Zcore = lines[i].split(); i+=1
lmax = int(lmax)
Zcore = int(Zcore)
while i<len(lines):
i+=1 # skip comment line
n = int(lines[i]); i+=1
terms = []
for j in range(n):
rpow,expon,coeff = lines[i].split(); i+=1
terms.append((float(coeff),int(rpow),float(expon)))
#end for
channels.append(terms)
#end while
elif format=='crystal':
i = 0
conv_atomic_number,nshells = lines[i].split(); i+=1
if len(conv_atomic_number)==1:
atomic_number = int(conv_atomic_number)
else:
atomic_number = int(conv_atomic_number[-2:])
#end if
element = pt.simple_elements[atomic_number].symbol
if 'input' not in lines[i].lower():
self.error('INPUT must be present for crystal pseudpotential read')
#end if
i+=1
tokens = lines[i].split()
Zval = int(float(tokens[0])); i+=1
Zcore = atomic_number-Zval
nterms = array(tokens[1:],dtype=int)
lmax = 0
if nterms[0]==0:
lmax+=1
channels.append([(0.0,2,1.0)])
nterms = nterms[1:]
#end if
for nt in nterms:
lmax += 1
terms = []
for n in range(nt):
expon,coeff,rpow = lines[i].split(); i+=1
terms.append((float(coeff),int(rpow)+2,float(expon)))
#end for
channels.append(terms)
#end for
lmax-=1
else:
self.error('ability to read file format {0} has not been implemented'.format(format))
#end if
if basis_lines!=None:
bs = GaussianBasisSet()
bs.read_lines(basis_lines,format)
basis = bs.basis
#end if
if not element in pt:
if not self.element in pt:
self.error('cannot identify element for pseudopotential file '+filepath)
#end if
else:
self.element = element
#end if
Zatom = pt[element].atomic_number
Zval = Zatom-Zcore
if Zcore==0:
core = None
else:
core = pt.simple_elements[Zcore].symbol
#end if
self.set(
core = core,
Zval = Zval,
Zcore = Zcore,
lmax = lmax
)
for c in range(len(channels)):
if c==0:
#cname = 'loc'
cname = self.l_channels[lmax]
self.local = cname
else:
cname = self.l_channels[c-1]
#end if
channel = obj()
terms = channels[c]
for t in range(len(terms)):
coeff,rpow,expon = terms[t]
channel[t] = obj(coeff=coeff,rpow=rpow,expon=expon)
#end for
self.channels[cname] = channel
#end for
self.basis = basis
if len(self.channels)!=self.lmax+1:
self.error('number of channels is not lmax+1!')
#end if
#end def read_text
def write_text(self,format=None,occ=None):
text = ''
format = format.lower()
if format=='qmcpack':
return self.write_qmcpack()
#end if
channel_order = [self.local]
for c in self.all_channels:
if c in self.channels and c!=self.local:
channel_order.append(c)
#end if
#end for
basis = self.basis
if basis!=None:
bs = GaussianBasisSet()
bs.basis = basis
basis = bs
#end if
if format=='gamess':
if basis!=None:
text += '{0} {1} 0. 0. 0.\n'.format(self.element,self.Zcore+self.Zval)
text += basis.write_text(format)
text += '\n'
#end if
text += '{0}-PP GEN {1} {2}\n'.format(self.element,self.Zcore,self.lmax)
for c in channel_order:
channel = self.channels[c]
text += '{0}\n'.format(len(channel))
for i in sorted(channel.keys()):
g = channel[i]
text += '{0:12.8f} {1} {2:12.8f}\n'.format(g.coeff,g.rpow,g.expon)
#end for
#end for
text += '\n'
elif format=='gaussian':
if basis!=None:
text += '{0} 0\n'.format(self.element)
text += basis.write_text(format)
text += '\n'
#end if
text += '{0} 0\n'.format(self.element)
text += '{0}_PP {1} {2}\n'.format(self.element,self.lmax,self.Zcore)
for c in channel_order:
channel = self.channels[c]
text += '{0} channel\n'.format(c)
text += '{0}\n'.format(len(channel))
for i in sorted(channel.keys()):
g = channel[i]
text += '{0} {1:12.8f} {2:12.8f}\n'.format(g.rpow,g.expon,g.coeff)
#end for
#end for
text += '\n'
elif format=='crystal':
if basis!=None:
conv_atomic_number = 200 + pt[self.element].atomic_number
text+='{0} {1}\n'.format(conv_atomic_number,basis.size())
btext = basis.write_text(format,occ=occ)
else:
btext = ''
#end if
text += 'INPUT\n'
tline = '{0}'.format(int(self.Zval))
channels = []
cloc = self.channels[channel_order[0]]
if len(cloc)==1 and abs(cloc[0].coeff)<1e-8:
tline += ' 0'
else:
tline += ' {0}'.format(len(cloc))
channels.append(cloc)
#end if
for c in channel_order[1:]:
channel = self.channels[c]
tline += ' {0}'.format(len(channel))
channels.append(channel)
#end for
text += tline+'\n'
for channel in channels:
for i in sorted(channel.keys()):
g = channel[i]
text += '{0} {1} {2}\n'.format(g.expon,g.coeff,g.rpow-2)
#end for
#end for
text += btext
else:
self.error('ability to write file format {0} has not been implemented'.format(format))
#end if
return text
#end def write_text
def get_basis(self):
bs = None
if self.basis!=None:
bs = GaussianBasisSet()
bs.basis = self.basis.copy()
#end if
return bs
#end def get_basis
def write_basis(self,filepath=None,format=None):
basis = self.get_basis()
text = ''
if basis!=None:
if format=='gamess':
text += '{0} {1} 0. 0. 0.\n'.format(self.element,self.Zcore+self.Zval)
text += basis.write_text(format)
text += '\n'
elif format=='gaussian':
text += '{0} 0\n'.format(self.element)
text += basis.write_text(format)
text += '\n'
else:
self.error('ability to write basis for file format {0} has not been implemented'.format(format))
#end if
#end if
if filepath!=None:
fobj = open(filepath,'w')
fobj.write(text)
fobj.close()
#end if
return text
#end def write_basis
def evaluate_rV(self,r,l=None):
r = array(r)
v = zeros(r.shape)
if l==self.local or l==None:
v += -self.Zval
#end if
for g in self.get_channel(l):
v += g.coeff * r**(g.rpow-1) * exp(-g.expon*r**2)
#end for
return v
#end def evaluate_rV
def ppconvert(self,outfile,ref):
of = outfile.lower()
if of.endswith('.xml'):
opts = '--xml'
elif of.endswith('.upf'):
opts = '--log_grid --upf'
else:
self.error('output file format unrecognized for {0}\nvalid extensions are .xml and .upf'.format(outfile))
#end if
tmpfile = 'tmp.gamess'
self.write(tmpfile,'gamess')
command = 'ppconvert --gamess_pot {0} --s_ref "{1}" --p_ref "{1}" --d_ref "{1}" {2} {3}'.format(tmpfile,ref,opts,outfile)
execute(command,verbose=True)
os.system('rm '+tmpfile)
#end def ppconvert
#end class GaussianPP
class QmcpackPP(SemilocalPP):
requires_format = False
numeric = True
interpolatable = False
def read(self,filepath,format=None):
if not os.path.exists(filepath):
self.error('cannot read {0}, file does not exist'.format(filepath))
#end if
x = readxml(filepath,contract_names=True)
x.convert_numeric()
x.condense()
x.remove_hidden()
pp = x.pseudo
h = pp.header
self.element = h.symbol
self.Zval = h.zval
self.Zcore = h.atomic_number-h.zval
if self.Zcore==0:
self.core = '0'
else:
self.core = pt.simple_elements[self.Zcore].symbol
#end if
g = pp.grid
if g.type=='linear':
self.rmin = g.ri
self.rmax = g.rf
self.r = linspace(g.ri,g.rf,g.npts)
else:
self.error('functionality for '+g.type+' grids has not yet been implemented')
#end if
sl = pp.semilocal
if sl.format!='r*V':
self.error('unrecognized potential format: {0}\nthe only supported format is r*V'.format(sl.format))
#end if
lloc = self.l_channels[sl.l_local]
self.local = lloc
vps = sl.vps
if not isinstance(vps,list):
vps = [vps]
#end if
for vp in vps:
self.channels[vp.l] = vp.radfunc.data.copy()
#end for
for l in self.channels.keys():
if l!=self.local:
self.channels[l] -= self.channels[self.local]
#end if
#end for
#end def read
def evaluate_rV(self,r=None,l=None):
if r!=None:
if len(r)==len(self.r) and abs( (r[1:]-self.r[1:])/self.r[1:] ).max()<1e-6:
r = self.r
else:
self.error('ability to interpolate at arbitrary r has not been implemented\ncalling evaluate() without specifying r will return the potential on a default grid')
#end if
else:
r = self.r
#end if
v = self.get_channel(l)
return v
#end def evaluate_rV
def v_at_zero(self,l):
r = self.r
v = self.get_channel(l)/r
vz = (v[1]*r[2]**2-v[2]*r[1]**2)/(r[2]**2-r[1]**2)
return vz
#end def v_at_zero
#end class QmcpackPP
# functions for gaussing fitting
def get_gf_channel(ns,np,params,Zval=None):
loc = Zval!=None
g = obj(
coeff = [],
rpow = [],
expon = []
)
nparam = 2*ns+3*np
if loc:
nparam += 2
#end if
if nparam!=len(params):
raise RuntimeError('wrong number of parameters given to get_gf_coeff_rpow_expon\nparameters expected: {0}\nparameters given: {1}'.format(nparams,len(params)))
#end if
pcur = 0
if loc:
a,b = params[pcur:pcur+2]
g.coeff += [ -Zval*0, Zval , .5*Zval/a**2 ]
g.rpow += [ -1 , -1 , 1 ]
g.expon += [ 0 , .5/a**2 , .5/b**2 ]
pcur+=2
#end if
for s in range(ns):
b,bs = params[pcur:pcur+2]
g.coeff.append(b/bs)
g.rpow.append( 0)
g.expon.append(.5/bs**2)
pcur+=2
#end for
for p in range(np):
b,bs,bt = params[pcur:pcur+3]
pf = 2*b/(bs+bt)
g.coeff += [ pf/bs , -pf/bt ]
g.rpow += [ 1 , 1 ]
g.expon += [ .5/bs**2 , .5/bt**2 ]
pcur+=3
#end for
g.coeff = array(g.coeff)
g.rpow = array(g.rpow, dtype=int)
g.expon = array(g.expon)
g.rpow += 2
channel = obj()
for t in range(len(g.coeff)):
channel[t] = obj(
coeff = g.coeff[t],
rpow = g.rpow[t],
expon = g.expon[t]
)
return channel
#end def get_gf_channel
def gf_s1_p0(r,b1,bs1):
r2 = r**2/2
return 2*r2*(b1/bs1*exp(-r2/bs1**2))
#end def gf_s1_p0
def gf_s1_p1(r,b1,bs1,b2,bs2,bt2):
r2 = r**2/2
return 2*r2*( b1/bs1*exp(-r2/bs1**2) \
+ b2*(2*r/(bs2+bt2))*(exp(-r2/bs2**2)/bs2-exp(-r2/bt2**2)/bt2) )
#end def gf_s1_p1
def gf_s1_p2(r,b1,bs1,b2,bs2,bt2,b3,bs3,bt3):
r2 = r**2/2
return 2*r2*( b1/bs1*exp(-r2/bs1**2) \
+ b2*(2*r/(bs2+bt2))*(exp(-r2/bs2**2)/bs2-exp(-r2/bt2**2)/bt2) \
+ b3*(2*r/(bs3+bt3))*(exp(-r2/bs3**2)/bs3-exp(-r2/bt3**2)/bt3) )
#end def gf_s1_p2
def gf_s1_p3(r,b1,bs1,b2,bs2,bt2,b3,bs3,bt3,b4,bs4,bt4):
r2 = r**2/2
return 2*r2*( b1/bs1*exp(-r2/bs1**2) \
+ b2*(2*r/(bs2+bt2))*(exp(-r2/bs2**2)/bs2-exp(-r2/bt2**2)/bt2) \
+ b3*(2*r/(bs3+bt3))*(exp(-r2/bs3**2)/bs3-exp(-r2/bt3**2)/bt3) \
+ b4*(2*r/(bs4+bt4))*(exp(-r2/bs4**2)/bs4-exp(-r2/bt4**2)/bt4) )
#end def gf_s1_p3
def gf_loc_s0_p0(r,a,b):
r2 = r**2/2
return -gf.Z*r*( 1.0 -exp(-r2/a**2) -r2/a**2*exp(-r2/b**2) )
#end def gf_loc_s0_p0
def gf_loc_s1_p0(r,a,b,b1,bs1):
r2 = r**2/2
return -gf.Z*r*( 1.0 -exp(-r2/a**2) -r2/a**2*exp(-r2/b**2) ) +2*r2*(b1/bs1*exp(-r2/bs1**2))
#end def gf_loc_s1_p0
def gf_loc_s1_p1(r,a,b,b1,bs1,b2,bs2,bt2):
r2 = r**2/2
return -gf.Z*r*( 1.0 -exp(-r2/a**2) -r2/a**2*exp(-r2/b**2) ) \
+2*r2*( b1/bs1*exp(-r2/bs1**2) \
+ b2*(2*r/(bs2+bt2))*(exp(-r2/bs2**2)/bs2-exp(-r2/bt2**2)/bt2) )
#end def gf_loc_s1_p1
def gf_loc_s1_p2(r,a,b,b1,bs1,b2,bs2,bt2,b3,bs3,bt3):
r2 = r**2/2
return -gf.Z*r*( 1.0 -exp(-r2/a**2) -r2/a**2*exp(-r2/b**2) ) \
+2*r2*( b1/bs1*exp(-r2/bs1**2) \
+ b2*(2*r/(bs2+bt2))*(exp(-r2/bs2**2)/bs2-exp(-r2/bt2**2)/bt2) \
+ b3*(2*r/(bs3+bt3))*(exp(-r2/bs3**2)/bs3-exp(-r2/bt3**2)/bt3) )
#end def gf_loc_s1_p2
def gf_loc_s1_p3(r,a,b,b1,bs1,b2,bs2,bt2,b3,bs3,bt3,b4,bs4,bt4):
r2 = r**2/2
return -gf.Z*r*( 1.0 -exp(-r2/a**2) -r2/a**2*exp(-r2/b**2) ) \
+2*r2*( b1/bs1*exp(-r2/bs1**2) \
+ b2*(2*r/(bs2+bt2))*(exp(-r2/bs2**2)/bs2-exp(-r2/bt2**2)/bt2) \
+ b3*(2*r/(bs3+bt3))*(exp(-r2/bs3**2)/bs3-exp(-r2/bt3**2)/bt3) \
+ b4*(2*r/(bs4+bt4))*(exp(-r2/bs4**2)/bs4-exp(-r2/bt4**2)/bt4) )
#end def gf_loc_s1_p3
def gf_rms_deviation(v1,v2):
return sqrt(((v1-v2)**2).mean())
#end def gf_rms_deviation
def gf_energy_deviation(v1,v2,r):
return (v1-v2).sum()*(r[1]-r[0])
#end def gf_energy_deviation
gf = obj(
Z = None,
functions = {
(1,0):gf_s1_p0,
(1,1):gf_s1_p1,
(1,2):gf_s1_p2,
(1,3):gf_s1_p3
},
loc_functions = {
(0,0):gf_loc_s0_p0,
(1,0):gf_loc_s1_p0,
(1,1):gf_loc_s1_p1,
(1,2):gf_loc_s1_p2,
(1,3):gf_loc_s1_p3
},
rms_deviation = gf_rms_deviation,
energy_deviation = gf_energy_deviation
)
# older classes, kept in case contents are useful later
#class PseudoFile(DevBase):
# colors = dict(s='k',p='r',d='b',f='m')
# lcolors= ['k','r','b','m']
# ldict = {0:'s',1:'p',2:'d',3:'f'}
#
# format = 'generic'
#
# conv_table = {('upf','fsatom'):('--upf_pot','--xml')}
# extensions = dict(upf='upf',fsatom='xml',gamess='gamess',casino='data')
#
#
# standard_energy_units = 'eV'
# standard_distance_units = 'B'
#
# def readfile(self,filepath):
# self.not_implemented()
# #end def read
#
#
# def write(self,filepath):
# self.not_implemented()
# #end def write
#
#
# def __init__(self,filepath=None,energy_units=None):
# self.initialize = False
# if energy_units is None:
# self.energy_units = self.standard_energy_units
# else:
# self.energy_units = energy_units
# #end if
# self.set(
# filename = None,
# location = None,
# element = None,
# type = None,
# Z = None,
# r = None,
# potentials = None,
# rcut = None,
# potential_spread = None,
# pp = None
# )
# if filepath!=None:
# self.read(filepath)
# #end if
# #end def __init__
#
#
# def read(self,filepath):
# self.filename = os.path.basename(filepath)
# self.location = os.path.abspath(filepath)
# self.readfile(filepath)
# if self.initialize:
# self.rcut = self.get_rcut(1e-16)
# pot = array(self.potentials.values())
# self.potential_spread = pot.max(0)-pot.min(0)
# #end if
# #end def read
#
#
# def convert(self,pptype):
# oform = pptype.format
# forms = self.format,oform
# have_conv = forms in self.conv_table
# if not have_conv:
# self.error('pseudopotential conversion from '+self.format+' to '+pptype.format+' format has not yet been implemented')
# #end if
# sflags,oflags = self.conv_table[forms]
# sfilepath = self.location
# path,sfilename = os.path.split(sfilepath)
# if not oform in self.extensions:
# self.error('attempted to convert to an unknown format: '+oform)
# #end if
# ofilename = sfilename.rsplit('.',1)[0]+'.'+self.extensions[oform]
# ofilepath = os.path.join(path,ofilename)
# command = 'ppconvert {0} {1} {2} {3}\n'.format(sflags,sfilename,oflags,ofilename)
# cwd = os.getcwd()
# os.chdir(path)
# ppcin = open(os.path.join(path,'ppconvert.in'),'w')
# ppcin.write(command)
# ppcin.close()
# out = open('./ppconvert.out','w')
# err = open('./ppconvert.err','w')
# p = Popen(command,stdout=out,stderr=err,shell=True)
# p.communicate()
# out.close()
# err.close()
# os.chdir(cwd)
# pp = pptype(ofilepath)
# return pp
# #end def convert
#
#
# def get_rcut(self,Etol=1e-16,rlower=.5):
# v = self.potentials.values()
# rcut = 0
# ir = self.r>rlower
# r = self.r[ir]
# for i in range(1,len(v)):
# vd = abs(v[i][ir]-v[0][ir])
# rc = r[abs(vd-Etol).argmin()]
# rcut = max(rcut,rc)
# #end for
# return rcut
# #end def get_rcut
#
#
# def plot(self,style='',rmax=4,vcoul=False,ptitle=None,mult=1,units='eV',lw=2):
# colors = self.lcolors
# r = self.r
# rc= self.rcut
# Z = self.Z
# if mult=='r':
# mult = r
# #end if
# vmin = 1e55
# vmax = -1e55
# for l,vpot in self.potentials.iteritems():
# pot = convert(mult*vpot,self.energy_units,units)
# vmin = min(vmin,pot.min())
# vmax = max(vmax,pot.max())
# plot(r,pot,colors[l]+style,lw=lw,label=self.ldict[l])
# #end for
# if vcoul:
# vcoul = convert(-Z/r,'Ha',units)
# vin = vcoul>vmin
# plot(r[vin],mult*vcoul[vin],'k-.')
# #dnd if
# plot([rc,rc],[vmin,vmax],'k-.',lw=lw)
# if rmax!=None:
# xlim([0,rmax])
# #end if
# if ptitle is None:
# title('Channel potentials for '+self.element+' '+self.type+' pseudopotential')
# else:
# title(ptitle)
# #end if
# ylabel('Potential Energy ({0})'.format(units))
# xlabel('Radius (bohr)')
# legend()
# #end def plot
#
#
# def plot_spread(self,style='k',label='',rmax=5):
# r = self.r
# rc= self.rcut
# vs = self.potential_spread
# semilogy(r,vs,style,lw=2,label=label)
# semilogy([rc,rc],[vs.min(),vs.max()],'k-.',lw=2)
# if rmax!=None:
# xlim([0,rmax])
# #end if
# grid()
# title("Potential spread $(\max_{\ell m}\, |v_\ell(r)-v_m(r)|)$ for "+self.element+' '+self.type+' pseudopotential')
# ylabel('Potential spread ({0})',self.energy_units)
# xlabel('Radius (bohr)')
# if label!='':
# legend()
# #end if
# #end def plot_spread
##end class PseudoFile
#
#
#
#class fsatomPP(PseudoFile):
# format = 'fsatom'
# def readfile(self,filepath):
# None
# #x = readxml(filepath,contract_names=True)
# #x.convert_numeric()
# #x.condense()
# #x.remove_hidden()
# #pp = x.pseudo
# #self.pp = pp
# #
# #h = pp.header
# #self.element = h.symbol
# #self.type = h.flavor
# #self.Z = h.zval
# #vps = self.pp.semilocal.vps
# #if not isinstance(vps,list):
# # vps = [vps]
# ##end if
# #g = vps[0].radfunc.grid
# #if g.type=='linear':
# # r = linspace(g.ri,g.rf,g.npts)
# # self.r = r[1:]
# #else:
# # self.error('functionality for '+g.type+' grids has not yet been implemented')
# ##end if
# #p = obj()
# #r = self.r
# #ldict = dict(s=0,p=1,d=2,f=3)
# #for vp in vps:
# # l = vp.l
# # v = 1./r*vp.radfunc.data[1:]
# # p[ldict[l]]= convert(v,'Ha',self.energy_units)
# ##end for
# #self.potentials = p
# #end def readfile
##end class fsatomPP
#
#
#class ncppPP(PseudoFile):
# format = 'ncpp'
# def readfile(self,filepath):
# text = open(filepath,'r').read()
#
# lines = text.splitlines()
#
# functional = lines[0].split()[0].strip("'")
# es,zs = lines[1].split(',')[0:2]
# element = es.strip("'")
# Zval = int(float(zs)+.5)
#
# self.set(
# element = element,
# type = functional,
# Z = Zval,
# r = [],
# potentials = obj(),
# pp = obj(),
# initialize = False
# )
# #end def readfile
##end class ncppPP
#
#
#class upfPP(PseudoFile):
# format='upf'
# def readfile(self,filepath):
# text = open(filepath,'r').read()
# if '<UPF' not in text:
# upf_format = 'old'
# lines = text.split('\n')
# xml = '<upf>\n'
# for l in lines:
# if l.find('/>')!=-1:
# ln = l.replace('/>','>').replace('<','</')
# else:
# ln = l
# #end if
# xml+=ln+'\n'
# #end for
# xml += '</upf>\n'
# tmppath = filepath+'_tmp'
# open(tmppath,'w').write(xml)
# x = readxml(tmppath,contract_names=True,strip_prefix='pp_')
# os.system('rm '+tmppath)
# x.convert_numeric()
# x.condense()
# x.remove_hidden()
# pp = x.upf
# else:
# upf_format = 'new'
# #x = readxml(filepath,contract_names=True,strip_prefix='pp_')
# #x.convert_numeric()
# #x.condense()
# #x.remove_hidden()
# #pp = x.upf
# pp = obj()
# pp_contents = open(filepath,'r').read()
# #end if
# if upf_format=='old':
# lines = pp.header.split('\n')
# h = obj()
# i=0
# h.version = string2val(lines[i].split()[0]); i+=1
# h.element = string2val(lines[i].split()[0]); i+=1
# h.type = string2val(lines[i].split()[0]); i+=1
# ncc = string2val(lines[i].split()[0]); i+=1
# h.nonlinear_cc = dict(T=True,F=False)[ncc]
# h.functional = lines[i].split()[0:4]; i+=1
# h.Z = string2val(lines[i].split()[0]); i+=1
# h.total_energy = string2val(lines[i].split()[0]); i+=1
# h.wfc_cutoff,h.rho_cutoff = array(lines[i].split()[0:2],dtype=float); i+=1
# h.lmax = string2val(lines[i].split()[0]); i+=1
# h.npts = string2val(lines[i].split()[0]); i+=1
# h.nwfc = string2val(lines[i].split()[0]); i+=1
# pp.header = h
# if 'nonlocal' in pp:
# if 'beta' in pp.nonlocal:
# beta = pp.nonlocal.beta
# if isinstance(beta,str):
# beta = [beta]
# #end if
# b = obj()
# for i in range(len(beta)):
# sections = beta[i].split('\n',2)
# p = string2val(sections[0].split()[0])
# v = string2val(sections[2])
# b[p]=v
# #end for
# pp.nonlocal.beta = b
# #end if
# dij = pp.nonlocal.dij
# d = obj()
# lines = dij.split('\n')[1:]
# for l in lines:
# t = l.split()
# d[int(t[0]),int(t[1])] = string2val(t[2])
# #end for
# pp.nonlocal.dij = d
# #end if
# pswfc = pp.pswfc
# tokens = pswfc.split()
# nwfc= pp.header.nwfc
# npts= pp.header.npts
# wf = []
# for n in range(nwfc):
# i = n*(4+npts)
# label = tokens[i]
# l = int(tokens[i+1])
# ws = []
# for v in tokens[i+4:i+4+npts]:
# ws.append(float(v))
# #end for
# orb = obj()
# orb.label = label
# orb.l = l
# orb.wfc = array(ws)
# wf.append(orb)
# #end for
# pp.pswfc = wf
#
# #fill in standard fields
# self.pp = pp
# self.r = pp.mesh.r[1:]
# if 'local' in pp:
# self.local = convert(pp.local,'Ry',self.energy_units)[1:]
# if 'nonlocal' in pp:
# nl = obj()
# vnl = zeros(self.local.shape)
# if 'beta' in pp.nonlocal:
# beta = pp.nonlocal.beta
# for t,d in pp.nonlocal.dij.iteritems():
# bi = beta[t[0]]
# bj = beta[t[1]]
# if not isinstance(bi,str) and not isinstance(bj,str):
# bb = d*bi*bj
# else: # the file is being misread, fix later
# bb = 0*pp.mesh.r
# #end if
# naftcut = len(pp.mesh.r)-len(bb)
# if naftcut>0:
# bb=append(bb,zeros((naftcut,)))
# #end if
# vnl += bb[1:]/self.r**2
# #end for
# #end if
# vnl = convert(vnl,'Ry',self.energy_units)
# nl[0] = vnl
# self.nonlocal = nl
# h = pp.header
# p = obj()
# p[0] = self.local
# p[1] = self.local+self.nonlocal[0]
# self.potentials = p
# #end if
# #end if
# self.element = h.element
# self.type = h.type
# self.Z = h.Z
# else:
# header_start = pp_contents.find('<PP_HEADER')
# if header_start==-1:
# self.error('could not find <PP_HEADER>')
# #end if
# header_end = pp_contents.find('/>')
# if header_end==-1:
# self.error('could not find </PP_HEADER>')
# #end if
# header = pp_contents[header_start:header_end]
# tokens = header.split()[1:]
# for token in tokens:
# if '=' in token:
# name,value = token.split('=',1)
# value = value.strip('"')
# if name=='element':
# self.element = value
# elif name=='functional':
# self.type = value
# elif name=='z_valence':
# self.Z = int(round(float(value)))
# #end if
# #end if
# #end for
#
# #self.error('ability to read new UPF format has not yet been implemented\n attempted to read '+filepath)
# #self.warn('ability to read new UPF format has not yet been implemented\n attempted to read '+filepath)
# self.initialize = False
# #end if
# #end def readfile
##end class upfPP
#
#
#class gamessPP(PseudoFile):
# format = 'gamess'
# def readfile(self,filepath):
# text = open(filepath,'r').read()
# lines = text.splitlines()
# pp = obj()
# i=0
# pp.name,pp.type,Zcore,lmax = lines[i].split(); i+=1
# Zcore = int(Zcore)
# lmax = int(lmax)
# pp.Zcore = Zcore
# pp.lmax = lmax
#
# element = split_delims(pp.name)[0]
# if not element in pt:
# element = split_delims(self.filename)[0]
# if not element in pt:
# self.error('cannot identify element for pseudopotential file '+filepath)
# #end if
# #end if
# Zatom = pt[element].atomic_number
# Z = Zatom-Zcore
#
# r = mgrid[1.e-10:150.00001:.005]
# p = obj()
# vlocal = None
# for index in range(lmax+1):
# l = (index+lmax)%(lmax+1)
# ngpot = int(lines[i].strip()); i+=1
# coeffs = empty((ngpot,),dtype=float)
# powers = empty((ngpot,),dtype=int)
# exponents = empty((ngpot,),dtype=float)
# for ig in range(ngpot):
# coef,power,exponent = lines[i].split(); i+=1
# coeffs[ig] = float(coef)
# powers[ig] = int(power)
# exponents[ig] = float(exponent)
# #end for
# pp[index] = obj(coeffs=coeffs,powers=powers,exponents=exponents)
# v = 0*r
# for ig in range(ngpot):
# v += coeffs[ig]*r**(powers[ig]-2)*exp(-exponents[ig]*r**2)
# #end for
# if index==0:
# vlocal = v - Z/r
# p[l] = vlocal.copy()
# else:
# p[l] = v + vlocal
# #end if
# #end for
# for l in p.keys():
# p[l] = convert(p[l],'Ha',self.energy_units)
# #end for
#
# self.set(
# element = element,
# type = pp.type,
# Z = Z,
# r = r,
# potentials = p
# )
# #end def readfile
##end class gamessPP
#
#
#class TextFile(DevBase):
# def __init__(self,filepath):
# if not os.path.exists(filepath):
# self.error('text file '+filepath+' does not exist')
# #end if
# text = open(filepath,'r').read()
# lines= text.splitlines()
# self.text = text
# self.lines = lines
# self.filepath = filepath
# #end def __init__
#
# def find_line(self,text,exit=False):
# for i in range(len(self.lines)):
# if text in self.lines[i]:
# return i
# #end if
# #end for
# if exit:
# self.error('text "'+text+'" not found in file '+self.filepath)
# else:
# return None
# #end if
# #end def find_line
#
# def read_tokens(self,iline,*formats):
# if isinstance(iline,str):
# iline = self.find_line(iline,exit=True)+1
# #end if
# tokens = []
# stokens = self.lines[iline].split()
# if len(formats)==1 and len(stokens)>1:
# formats = len(stokens)*formats
# elif len(formats)>len(stokens):
# self.error('line {0} only has {1} tokens, you requested {2}'.format(iline,len(stokens),len(formats)))
# #end if
# for i in range(len(formats)):
# tokens.append(formats[i](stokens[i]))
# #end for
# if len(tokens)==1:
# return tokens[0]
# else:
# return tokens
# #end if
# #end def read_tokens
##end def TextFile
#
#
#class casinoPP(PseudoFile):
# format = 'casino'
# unitmap = dict(rydberg='Ry',hartree='Ha',ev='eV')
# def readfile(self,filepath):
# text = TextFile(filepath)
# Zatom,Z = text.read_tokens('Atomic number and pseudo-charge',int,float)
# if Zatom>len(pt.simple_elements):
# self.error('element {0} is not in the periodic table')
# #end if
# element = pt.simple_elements[Zatom].symbol
# units = text.read_tokens('Energy units',str)
# if not units in self.unitmap:
# self.error('units {0} unrecognized from casino PP file {1}'.format(units,filepath))
# #end if
# lloc = text.read_tokens('Angular momentum of local component',int)
# ngrid = text.read_tokens('Number of grid points',int)
# i = text.find_line('R(i)',exit=True)+1
# r = empty((ngrid,),dtype=float)
# for ir in xrange(ngrid):
# r[ir] = float(text.lines[i])
# i+=1
# #end for
# r=r[1:]
# p = obj()
# while i<len(text.lines):
# line = text.lines[i]
# if 'potential' in line:
# eqloc = line.find('=')
# if eqloc==-1:
# self.error('"=" not found in potential line')
# #end if
# l = int(line[eqloc+1])
# i+=1
# if i+ngrid>len(text.lines):
# self.error('potentials in file {0} are not the right length'.format(filepath))
# #end if
# v = empty((ngrid,),dtype=float)
# for ir in xrange(ngrid):
# v[ir] = float(text.lines[i])
# i+=1
# #end for
# p[l] = v[1:]/r
# #end if
# #end while
#
# for l in p.keys():
# p[l] = convert(p[l],self.unitmap[units],self.energy_units)
# #end for
#
# self.set(
# element = element,
# type = 'Trail-Needs',
# Z = Z,
# r = r,
# potentials = p,
# pp = obj(
# Zatom = Zatom,
# Z = Z,
# units = units,
# lloc = lloc,
# ngrid = ngrid
# )
# )
# #end def read_file
##end class casinoPP
#
#
#class Pseudopotentials(DevBase):
# def __init__(self,*pseudopotentials):
# if len(pseudopotentials)==1 and isinstance(pseudopotentials[0],list):
# pseudopotentials = pseudopotentials[0]
# #end if
# ppfiles = []
# pps = []
# errors = False
# print
# for pp in pseudopotentials:
# if isinstance(pp,PseudoFile):
# pps.append(pp)
# elif isinstance(pp,str):
# ppfiles.append(pp)
# else:
# self.error('expected PseudoFile type or filepath, got '+str(type(pp)),exit=False)
# errors = True
# #end if
# #end for
# if errors:
# self.error('cannot create Pseudopotentials object')
# #end if
#
# if len(pps)>0:
# self.addpp(pps)
# #end if
# if len(ppfiles)>0:
# self.readpp(ppfiles)
# #end if
# #end def __init__
#
#
# def addpp(self,*pseudopotentials):
# if len(pseudopotentials)==1 and isinstance(pseudopotentials[0],list):
# pseudopotentials = pseudopotentials[0]
# #end if
# for pp in pseudopotentials:
# self[pp.filename] = pp
# #end for
# #end def addpp
#
#
# def readpp(self,*ppfiles):
# if len(ppfiles)==1 and isinstance(ppfiles[0],list):
# ppfiles = ppfiles[0]
# #end if
# pps = []
# errors = False
# print ' Pseudopotentials'
# for filepath in ppfiles:
# print ' reading pp: ',filepath
# ext = filepath.split('.')[-1].lower()
# if ext=='upf':
# pp = upfPP(filepath)
# elif ext=='xml':
# pp = fsatomPP(filepath)
# elif ext=='ncpp':
# pp = ncppPP(filepath)
# elif ext=='gms':
# pp = gamessPP(filepath)
# elif ext=='data':
# pp = casinoPP(filepath)
# else:
# self.error('cannot determine pseudopotential type from file extension '+ext+' ('+os.path.basename(filepath)+')')
# errors = True
# pp = None
# #end if
# pps.append(pp)
# #end for
# if errors:
# self.error('cannot read all pseudopotentials')
# #end if
# self.addpp(pps)
# #end def readpp
#
#
# def read_type(self,pptype,*ppfiles):
# if len(ppfiles)==1 and isinstance(ppfiles[0],list):
# ppfiles = ppfiles[0]
# #end if
# pps = []
# for filepath in ppfiles:
# pp = pptype(filepath)
# pps.append(pp)
# #end for
# self.addpp(pps)
# #end def read_type
#
#
# def read_upf(self,*ppfiles):
# self.read_type(upfPP,*ppfiles)
# #end def read_upf
#
#
# def read_fsatom(self,*ppfiles):
# self.read_type(fsatomPP,*ppfiles)
# #end def read_fsatom
#
##end class Pseudopotentials